diff --git a/platform/darwin/common/lynx/LynxEnv.mm b/platform/darwin/common/lynx/LynxEnv.mm index 5b559b6a3d..0558eefca3 100644 --- a/platform/darwin/common/lynx/LynxEnv.mm +++ b/platform/darwin/common/lynx/LynxEnv.mm @@ -573,6 +573,16 @@ - (BOOL)enableImageCancelRequest { return enableImageCancelRequest; } +- (BOOL)enableImagePlaceholderResetFix { + static dispatch_once_t onceToken; + static BOOL enableImagePlaceholderResetFix = YES; + dispatch_once(&onceToken, ^{ + enableImagePlaceholderResetFix = [self boolFromExternalEnv:LynxEnvEnableImagePlaceholderResetFix + defaultValue:YES]; + }); + return enableImagePlaceholderResetFix; +} + - (BOOL)enableImageCIGaussianBlur { static dispatch_once_t onceToken; static BOOL enableCIGaussianBlur = NO; @@ -784,6 +794,7 @@ + (NSString *)_keyStringFromType:(LynxEnvKey)key { @(LynxEnvEnableImageEventReport) : @"enable_image_event_report", @(LynxEnvEnableImageAsyncLayout) : @"enable_image_async_layout", @(LynxEnvEnableImageCancelRequest) : @"enable_image_cancel_request", + @(LynxEnvEnableImagePlaceholderResetFix) : @"enable_image_placeholder_reset_fix", @(LynxEnvEnableImageCIGaussianBlur) : @"enable_image_ci_gaussian_blur", @(LynxEnvEnableGenericResourceFetcher) : @"enable_generic_resource_fetcher", @(LynxEnvEnableAnimationSyncTimeOpt) : @"enable_animation_sync_time_opt", diff --git a/platform/darwin/common/lynx/public/LynxEnv.h b/platform/darwin/common/lynx/public/LynxEnv.h index 2b8f72cf87..6cb8e45c82 100644 --- a/platform/darwin/common/lynx/public/LynxEnv.h +++ b/platform/darwin/common/lynx/public/LynxEnv.h @@ -150,6 +150,8 @@ typedef NS_ENUM(NSInteger, LynxMemoryPressureLevel) { - (BOOL)enableImageCancelRequest; +- (BOOL)enableImagePlaceholderResetFix; + - (BOOL)enableImageCIGaussianBlur; - (BOOL)getUseNewImage; diff --git a/platform/darwin/common/lynx/public/LynxEnvKey.h b/platform/darwin/common/lynx/public/LynxEnvKey.h index db010ca5d3..7e87f5d19b 100644 --- a/platform/darwin/common/lynx/public/LynxEnvKey.h +++ b/platform/darwin/common/lynx/public/LynxEnvKey.h @@ -49,6 +49,7 @@ typedef NS_ENUM(uint64_t, LynxEnvKey) { // Internal-only Lynx settings key. Do not mention graphics backend details in the key. LynxEnvSetupCanvasSurfaceEarlier, + LynxEnvEnableImagePlaceholderResetFix, // Please add new enum values above LynxEnvKeyEndMark, // Keep this as the last enum value, and do not use diff --git a/platform/darwin/ios/api/lynx_ios.api b/platform/darwin/ios/api/lynx_ios.api index 7f2fb6b2b6..93a16d13a3 100644 --- a/platform/darwin/ios/api/lynx_ios.api +++ b/platform/darwin/ios/api/lynx_ios.api @@ -1508,6 +1508,7 @@ public class LynxEnv : NSObject { public BOOL LynxEnv::enableImageEventReport(); public BOOL LynxEnv::enableImageAsyncLayout(); public BOOL LynxEnv::enableImageCancelRequest(); + public BOOL LynxEnv::enableImagePlaceholderResetFix(); public BOOL LynxEnv::enableImageCIGaussianBlur(); public BOOL LynxEnv::getUseNewImage(); public BOOL LynxEnv::enableGenericResourceFetcher(); @@ -6394,6 +6395,7 @@ public enum LynxEnvKey { LynxEnvFSPEnable LynxEnvFSPConfigJsonString LynxEnvSetupCanvasSurfaceEarlier + LynxEnvEnableImagePlaceholderResetFix LynxEnvKeyEndMark } diff --git a/platform/darwin/ios/lynx/ui/image/LynxUIImage.mm b/platform/darwin/ios/lynx/ui/image/LynxUIImage.mm index 66cb38c61b..4c0fe9c34c 100644 --- a/platform/darwin/ios/lynx/ui/image/LynxUIImage.mm +++ b/platform/darwin/ios/lynx/ui/image/LynxUIImage.mm @@ -253,6 +253,7 @@ @interface LynxUIImage () @property(nonatomic, assign) BOOL enableImageEventReport; @property(nonatomic, assign) BOOL enableImageAsyncLayout; @property(nonatomic, assign) BOOL enableImageCancelRequest; +@property(nonatomic, assign) BOOL enableImagePlaceholderResetFix; @property(nonatomic, assign) BOOL enableGenericFetcher; @property(nonatomic, assign) BOOL enableFetchUIImage; @property(nonatomic, strong) NSDictionary* additional_custom_info; @@ -265,6 +266,7 @@ @interface LynxUIImage () @property(nonatomic, assign) LynxImagePlayState playState; @property(nonatomic, assign) BOOL keepAnimPlayState; @property(nonatomic, assign) CGRect regionToDecode; +@property(nonatomic, assign) BOOL imageFromSrc; @end @implementation LynxUIImage { @@ -295,12 +297,14 @@ - (void)initProperties { _enableImageEventReport = [LynxEnv.sharedInstance enableImageEventReport]; _enableImageAsyncLayout = [LynxEnv.sharedInstance enableImageAsyncLayout]; _enableImageCancelRequest = [LynxEnv.sharedInstance enableImageCancelRequest]; + _enableImagePlaceholderResetFix = [LynxEnv.sharedInstance enableImagePlaceholderResetFix]; _frameCacheAutomatically = LynxBooleanOptionUnset; _superResolutionScale = 0.0; _enableReportInfo = false; _playState = LynxImagePlayStateDefault; _keepAnimPlayState = NO; _regionToDecode = CGRectNull; + _imageFromSrc = NO; } - (void)dealloc { @@ -442,6 +446,7 @@ __block void (^ready)(UIImage*, LynxURL*) = ^(UIImage* image, LynxURL* requestUR } if (image == nil) { [strongSelf setImageToView:image]; + strongSelf.imageFromSrc = NO; return; } if (strongSelf.enableFadeIn && [strongSelf shouldUseNewImage] && !requestURL.fromMemoryCache) { @@ -482,6 +487,7 @@ __block void (^ready)(UIImage*, LynxURL*) = ^(UIImage* image, LynxURL* requestUR if (strongSelf.loopCount <= 0) { [strongSelf setImageToView:image]; + strongSelf.imageFromSrc = requestURL && requestURL.type == LynxImageRequestSrc; if (image.images != nil && [image.images count] > 1) { strongSelf.view.animationDuration = image.duration; if (strongSelf.autoPlay) { @@ -501,6 +507,7 @@ __block void (^ready)(UIImage*, LynxURL*) = ^(UIImage* image, LynxURL* requestUR [[LynxImageLoader imageService] handleAnimatedImage:image view:strongSelf.view loopCount:strongSelf.loopCount]; + strongSelf.imageFromSrc = requestURL && requestURL.type == LynxImageRequestSrc; } }; if ([NSThread isMainThread]) { @@ -1245,6 +1252,7 @@ - (void)resetImage { LynxUIImage* image = (LynxUIImage*)ui; image.view.image = nil; + image.imageFromSrc = NO; if (![[LynxImageLoader imageService] checkImageType:image.view]) { image.view.animationImages = nil; } @@ -1273,6 +1281,7 @@ - (NSURL*)illegalUrlHandler:(NSString*)value { [self markAsDirty]; if (requestReset || value == nil) { self.image = nil; + self.imageFromSrc = NO; [self resetImage]; _src = nil; return; @@ -1302,8 +1311,12 @@ - (NSURL*)illegalUrlHandler:(NSString*)value { LYNX_PROP_SETTER("placeholder", setPlaceholder, NSString*) { [self markAsDirty]; if (requestReset || value == nil) { - self.image = nil; - [self resetImage]; + if (self.enableImagePlaceholderResetFix && self.imageFromSrc) { + // Keep the current src image when only placeholder is reset. + } else { + self.image = nil; + [self resetImage]; + } _placeholder = nil; return; } @@ -1314,9 +1327,13 @@ - (NSURL*)illegalUrlHandler:(NSString*)value { _placeholder.type = LynxImageRequestPlaceholder; } if (!newURL || ![newURL.absoluteString isEqualToString:_placeholder.url.absoluteString]) { - self.image = nil; - if (!_deferSrcInvalidation) { - [self resetImage]; + if (self.enableImagePlaceholderResetFix && self.imageFromSrc) { + // Keep the current src image when only placeholder changes. + } else { + self.image = nil; + if (!_deferSrcInvalidation) { + [self resetImage]; + } } _placeholder.imageSize = CGSizeZero; _placeholder.url = newURL;