#import "TGFlutterPagPlatformView.h" #import "TGFlutterPagDownloadManager.h" #import #import #import #import #import @interface TGFlutterPagPlatformView : NSObject @property(nonatomic, strong) PAGView* pagView; @property(nonatomic, weak) NSObject* registrar; @end @implementation TGFlutterPagPlatformView - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)arguments registrar:(NSObject*)registrar { self = [super init]; if (self) { _registrar = registrar; _pagView = [[PAGView alloc] initWithFrame:frame]; _pagView.backgroundColor = UIColor.clearColor; _pagView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [_pagView setScaleMode:PAGScaleModeLetterBox]; [_pagView addListener:self]; [self configureWithArguments:arguments]; } return self; } - (UIView*)view { return _pagView; } - (void)configureWithArguments:(id)arguments { if (![arguments isKindOfClass:NSDictionary.class]) { return; } NSDictionary* params = arguments; int repeatCount = 1; id repeatValue = params[@"repeatCount"]; if ([repeatValue respondsToSelector:@selector(intValue)]) { repeatCount = [repeatValue intValue]; } double initProgress = 0.0; id progressValue = params[@"initProgress"]; if ([progressValue respondsToSelector:@selector(doubleValue)]) { initProgress = [progressValue doubleValue]; } BOOL autoPlay = NO; id autoPlayValue = params[@"autoPlay"]; if ([autoPlayValue respondsToSelector:@selector(boolValue)]) { autoPlay = [autoPlayValue boolValue]; } NSDictionary* imageReplacementsByName = [self imageReplacementsByNameFromParams:params]; [_pagView setRepeatCount:repeatCount]; [_pagView setProgress:initProgress]; NSString* assetName = [self nonEmptyString:params[@"assetName"]]; if (assetName.length > 0) { NSString* package = [self nonEmptyString:params[@"package"]]; NSString* assetPath = [self assetPathForName:assetName package:package]; [self loadPath:assetPath initProgress:initProgress autoPlay:autoPlay imageReplacementsByName:imageReplacementsByName]; return; } NSString* url = [self nonEmptyString:params[@"url"]]; if (url.length > 0) { __weak typeof(self) weakSelf = self; [TGFlutterPagDownloadManager download:url completionHandler:^(NSData* data, NSError* error) { if (data == nil || data.length == 0) { return; } dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf loadData:data initProgress:initProgress autoPlay:autoPlay imageReplacementsByName:imageReplacementsByName]; }); }]; return; } id bytesData = params[@"bytesData"]; if ([bytesData isKindOfClass:FlutterStandardTypedData.class]) { FlutterStandardTypedData* typedData = bytesData; if (typedData.type == FlutterStandardDataTypeUInt8) { [self loadData:typedData.data initProgress:initProgress autoPlay:autoPlay imageReplacementsByName:imageReplacementsByName]; } } } - (NSString*)nonEmptyString:(id)value { if (![value isKindOfClass:NSString.class]) { return nil; } NSString* text = [(NSString*)value stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]; return text.length > 0 ? text : nil; } - (NSString*)assetPathForName:(NSString*)assetName package:(NSString*)package { NSString* resourcePath = nil; if (package.length > 0) { resourcePath = [_registrar lookupKeyForAsset:assetName fromPackage:package]; } else { resourcePath = [_registrar lookupKeyForAsset:assetName]; } return [[NSBundle mainBundle] pathForResource:resourcePath ofType:nil]; } - (void)loadPath:(NSString*)path initProgress:(double)initProgress autoPlay:(BOOL)autoPlay imageReplacementsByName:(NSDictionary*)imageReplacementsByName { if (path.length == 0) { return; } if (imageReplacementsByName.count > 0) { PAGFile* file = [PAGFile Load:path]; [self applyImageReplacementsByName:imageReplacementsByName toFile:file]; [self setFile:file initProgress:initProgress autoPlay:autoPlay]; return; } if (![_pagView setPath:path]) { return; } [_pagView setProgress:initProgress]; [_pagView flush]; if (autoPlay) { [_pagView play]; } } - (void)loadData:(NSData*)data initProgress:(double)initProgress autoPlay:(BOOL)autoPlay imageReplacementsByName:(NSDictionary*)imageReplacementsByName { if (data == nil || data.length == 0) { return; } PAGFile* file = [PAGFile Load:data.bytes size:data.length]; [self applyImageReplacementsByName:imageReplacementsByName toFile:file]; [self setFile:file initProgress:initProgress autoPlay:autoPlay]; } - (void)setFile:(PAGFile*)file initProgress:(double)initProgress autoPlay:(BOOL)autoPlay { if (file == nil || file.width <= 0 || file.height <= 0) { return; } [_pagView setComposition:file]; [_pagView setProgress:initProgress]; [_pagView flush]; if (autoPlay) { [_pagView play]; } } - (NSDictionary*)imageReplacementsByNameFromParams:(NSDictionary*)params { id raw = params[@"imageReplacementsByName"]; if (![raw isKindOfClass:NSDictionary.class]) { return @{}; } NSMutableDictionary* result = [[NSMutableDictionary alloc] init]; [(NSDictionary*)raw enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) { if (![key isKindOfClass:NSString.class]) { return; } NSString* layerName = [(NSString*)key stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]; if (layerName.length == 0) { return; } NSData* data = nil; if ([value isKindOfClass:FlutterStandardTypedData.class]) { FlutterStandardTypedData* typedData = value; if (typedData.type == FlutterStandardDataTypeUInt8) { data = typedData.data; } } else if ([value isKindOfClass:NSData.class]) { data = value; } if (data.length > 0) { result[layerName] = data; } }]; return result; } - (void)applyImageReplacementsByName:(NSDictionary*)imageReplacementsByName toFile:(PAGFile*)file { if (file == nil || imageReplacementsByName == nil || imageReplacementsByName.count == 0) { return; } [imageReplacementsByName enumerateKeysAndObjectsUsingBlock:^(NSString* layerName, NSData* data, BOOL* stop) { if (![layerName isKindOfClass:NSString.class] || layerName.length == 0 || ![data isKindOfClass:NSData.class] || data.length == 0) { return; } PAGImage* image = [PAGImage FromBytes:data.bytes size:data.length]; if (image == nil) { return; } [image setScaleMode:PAGScaleModeZoom]; [file replaceImageByName:layerName data:image]; }]; } - (void)dealloc { [_pagView removeListener:self]; [_pagView stop]; [_pagView setComposition:nil]; } @end @implementation TGFlutterPagPlatformViewFactory { __weak NSObject* _registrar; } - (instancetype)initWithRegistrar:(NSObject*)registrar { self = [super init]; if (self) { _registrar = registrar; } return self; } - (NSObject*)createArgsCodec { return FlutterStandardMessageCodec.sharedInstance; } - (NSObject*)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args { return [[TGFlutterPagPlatformView alloc] initWithFrame:frame viewIdentifier:viewId arguments:args registrar:_registrar]; } @end