From b80913cc285e4005be8c175f01ee6cbd323ff6e1 Mon Sep 17 00:00:00 2001 From: yangbinqiao Date: Fri, 30 Dec 2022 16:53:50 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=9C=AA=E8=AF=BB=E5=8F=96image=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mop/api/mop/AppletHandlerModule.java | 29 +++++++++++++++--- example/pubspec.lock | 30 +++++++++---------- pubspec.lock | 28 ++++++++--------- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java b/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java index d2b2c55..88dab1d 100644 --- a/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java +++ b/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java @@ -153,6 +153,7 @@ public class AppletHandlerModule extends BaseApi { @Nullable @Override + @SuppressWarnings("unchecked") public List getRegisteredMoreMenuItems(@NotNull String s) { CountDownLatch latch = new CountDownLatch(1); List moreMenuItems = new ArrayList<>(); @@ -162,9 +163,8 @@ public class AppletHandlerModule extends BaseApi { channel.invokeMethod("extensionApi:getCustomMenus", params, new MethodChannel.Result() { @Override public void success(Object result) { - List> ret = (List>) result; - FinAppTrace.d(TAG, "getCustomMenus success : " + ret + " size : " + ret.size()); - if (ret != null) { + if (result instanceof List) { + List> ret = (List>) result; for (Map map : ret) { String type = (String) map.get("type"); MoreMenuType moreMenuType; @@ -173,7 +173,28 @@ public class AppletHandlerModule extends BaseApi { } else { moreMenuType = MoreMenuType.ON_MINI_PROGRAM; } - moreMenuItems.add(new MoreMenuItem((String) map.get("menuId"), (String) map.get("title"), moreMenuType)); + String menuId = (String) map.get("menuId"); + if (menuId == null) { + menuId = ""; + } + String title = (String) map.get("title"); + if (title == null) { + title = ""; + } + String image = (String) map.get("image"); + if (image == null) { + image = ""; + } + moreMenuItems.add( + new MoreMenuItem( + menuId, + title, + image, + -1, + moreMenuType, + true + ) + ); } } latch.countDown(); diff --git a/example/pubspec.lock b/example/pubspec.lock index e86417e..86b7e85 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -42,7 +42,7 @@ packages: name: collection url: "https://pub.flutter-io.cn" source: hosted - version: "1.16.0" + version: "1.15.0" cupertino_icons: dependency: "direct main" description: @@ -56,7 +56,7 @@ packages: name: fake_async url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -95,13 +95,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.1.4" meta: dependency: transitive description: @@ -115,14 +108,14 @@ packages: path: ".." relative: true source: path - version: "2.37.3" + version: "2.39.1" path: dependency: transitive description: name: path url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.1" + version: "1.8.0" sky_engine: dependency: transitive description: flutter @@ -134,7 +127,7 @@ packages: name: source_span url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.2" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -169,14 +162,21 @@ packages: name: test_api url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.9" + version: "0.4.3" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.2" + version: "2.1.1" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.2.3" diff --git a/pubspec.lock b/pubspec.lock index 7d68fe5..f39f99b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,14 +42,14 @@ packages: name: collection url: "https://pub.flutter-io.cn" source: hosted - version: "1.16.0" + version: "1.15.0" fake_async: dependency: transitive description: name: fake_async url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -88,13 +88,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.1.4" meta: dependency: transitive description: @@ -108,7 +101,7 @@ packages: name: path url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.1" + version: "1.8.0" sky_engine: dependency: transitive description: flutter @@ -120,7 +113,7 @@ packages: name: source_span url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.2" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -155,14 +148,21 @@ packages: name: test_api url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.9" + version: "0.4.3" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.2" + version: "2.1.1" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.2.3" From 406964e027e321ac2403dc6d68efb3034beb23c7 Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Tue, 3 Jan 2023 22:13:59 +0800 Subject: [PATCH 02/10] 1.update --- ios/Classes/Api/MOPAppletDelegate.m | 23 +- ios/Classes/MopPlugin.m | 47 ++- ios/Classes/Utils/MOPTools.h | 21 + ios/Classes/Utils/MOPTools.m | 116 +++++ ios/Classes/Utils/MopShareView.h | 31 ++ ios/Classes/Utils/MopShareView.m | 291 +++++++++++++ ios/Classes/Utils/UIView+MOPFATToast.h | 421 +++++++++++++++++++ ios/Classes/Utils/UIView+MOPFATToast.m | 561 +++++++++++++++++++++++++ ios/mop.podspec | 4 +- 9 files changed, 1511 insertions(+), 4 deletions(-) create mode 100644 ios/Classes/Utils/MopShareView.h create mode 100644 ios/Classes/Utils/MopShareView.m create mode 100644 ios/Classes/Utils/UIView+MOPFATToast.h create mode 100644 ios/Classes/Utils/UIView+MOPFATToast.m diff --git a/ios/Classes/Api/MOPAppletDelegate.m b/ios/Classes/Api/MOPAppletDelegate.m index 6381e36..d36e9c0 100644 --- a/ios/Classes/Api/MOPAppletDelegate.m +++ b/ios/Classes/Api/MOPAppletDelegate.m @@ -9,6 +9,7 @@ #import "MopPlugin.h" #import "MopCustomMenuModel.h" #import +#import @interface NSString (FATEncode) - (NSString *)fat_encodeString; @@ -86,11 +87,16 @@ } - (void)clickCustomItemMenuWithInfo:(NSDictionary *)contentInfo inApplet:(FATAppletInfo *)appletInfo completion:(void (^)(FATExtensionCode code, NSDictionary *result))completion { + NSError *parseError = nil; + NSMutableDictionary *shareDic = [[NSMutableDictionary alloc] initWithDictionary:[self dictionaryRepresentation:appletInfo]]; + [shareDic setValue:@{@"desc" : shareDic[@"originalInfo"][@"customData"][@"detailDescription"]} forKey:@"params"]; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:shareDic options:NSJSONWritingPrettyPrinted error:&parseError]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSDictionary *arguments = @{ @"appId": contentInfo[@"appId"], @"path": contentInfo[@"path"], @"menuId": contentInfo[@"menuId"], - @"appInfo": appletInfo.description + @"appInfo": jsonString }; FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel]; [channel invokeMethod:@"extensionApi:onCustomMenuClick" arguments:arguments result:^(id _Nullable result) { @@ -102,6 +108,21 @@ } } +- (NSDictionary *)dictionaryRepresentation:(FATAppletInfo *)object { + unsigned int count; + objc_property_t *properties = class_copyPropertyList([object class], &count); + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:count]; + for (int i = 0; i < count; i++) { + NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])]; + id value = [object valueForKey:key]; + if (key && value) { + [dict setObject:value forKey:key]; + } + } + free(properties); + return dict; +} + - (void)applet:(NSString *)appletId didOpenCompletion:(NSError *)error { if (!appletId) { return; diff --git a/ios/Classes/MopPlugin.m b/ios/Classes/MopPlugin.m index dc760ea..397c85a 100644 --- a/ios/Classes/MopPlugin.m +++ b/ios/Classes/MopPlugin.m @@ -3,6 +3,9 @@ #import "MOPApiRequest.h" #import "MOPApiConverter.h" #import "MOPAppletDelegate.h" +#import +#import "MopShareView.h" +#import @implementation MopEventStream { FlutterEventSink _eventSink; @@ -55,6 +58,12 @@ static MopPlugin *_instance; binaryMessenger:[registrar messenger]]; [registrar addMethodCallDelegate:_instance channel:appletChannel]; _instance.appletMethodChannel = appletChannel; + + FlutterMethodChannel* appletShareChannel = [FlutterMethodChannel + methodChannelWithName:@"plugins.finosprite.finogeeks.com/share_applet" + binaryMessenger:[registrar messenger]]; + [registrar addMethodCallDelegate:_instance channel:appletShareChannel]; + _instance.shareMethodChannel = appletShareChannel; } @@ -77,13 +86,48 @@ static MopPlugin *_instance; result(dict); } else if ([@"copyFileAsFinFile" isEqualToString:call.method]) { - NSString *appId = call.arguments[@"appId"]; +// NSString *appId = call.arguments[@"appId"]; NSString *path = call.arguments[@"path"]; NSString *fileName = [path componentsSeparatedByString:@"/"].lastObject; NSMutableDictionary *dict = [NSMutableDictionary dictionary]; dict[@"path"] = [[FATClient sharedClient] saveFile:[NSData dataWithContentsOfFile:path] fileName:fileName]; result(dict); } + else if ([@"showShareAppletDialog" isEqualToString:call.method]) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + UIImage *image = [MOPTools imageWithScreenshot]; + MopShareView *view = [MopShareView viewWithData:call.arguments]; + view.image = image; + [view show]; + [view setDidSelcetTypeBlock:^(NSString *type) { + result(type); + }]; + }); + } + else if ([@"showLoading" isEqualToString:call.method]) { + UIViewController *currentVC = [MOPTools topViewController]; + [currentVC.view fatMakeToastActivity:CSToastPositionCenter]; + result([self appInfoDictWithAppId:call.arguments[@"appId"]]); + } + else if ([@"hideLoading" isEqualToString:call.method]) { + UIViewController *currentVC = [MOPTools topViewController]; + [currentVC.view fatHideToastActivity]; + [currentVC.view fatHideAllToasts]; + result([self appInfoDictWithAppId:call.arguments[@"appId"]]); + } + else if ([@"showToast" isEqualToString:call.method]) { + UIViewController *currentVC = [MOPTools topViewController]; + [currentVC.view fatMakeToast:call.arguments[@"msg"] + duration:2.0 + position:CSToastPositionCenter]; + result([self appInfoDictWithAppId:call.arguments[@"appId"]]); + } + else if ([@"getScreenshot" isEqualToString:call.method]) { + UIImage *image = [MOPTools imageWithScreenshot]; + NSString *filePtah = [[FATClient sharedClient] saveFile:UIImagePNGRepresentation(image) fileName:[NSString stringWithFormat:@"%@",call.arguments[@"appId"]]]; + filePtah = [[FATClient sharedClient] fat_absolutePathWithPath:filePtah]; + result(filePtah); + } else if ([@"getPhoneNumberResult" isEqualToString:call.method]) { if ([MOPAppletDelegate instance].bindGetPhoneNumbers) { NSDictionary *dic = [[NSDictionary alloc] initWithDictionary:call.arguments]; @@ -199,4 +243,5 @@ static MopPlugin *_instance; } return nil;; } + @end diff --git a/ios/Classes/Utils/MOPTools.h b/ios/Classes/Utils/MOPTools.h index 37195b2..f516da9 100644 --- a/ios/Classes/Utils/MOPTools.h +++ b/ios/Classes/Utils/MOPTools.h @@ -18,6 +18,27 @@ NS_ASSUME_NONNULL_BEGIN + (UIColor *)fat_colorWithHexString:(NSString *)hexColor; + (BOOL)fat_currentLanguageIsEn; + +/// 设置颜色( + 暗黑模式):UIDynamicProviderColor(会随着暗黑模式/明亮模式切换自动变化颜色) +/// @param lightHexString (明亮模式 的颜色值) +/// @param darkHexString (暗黑模式 的颜色值) ++ (UIColor *)fat_dynamicColorWithLightHexString:(NSString *)lightHexString darkHexString:(NSString *)darkHexString; + + +/// 获取当前页面的截图 ++ (UIImage *)currentPageAppletImage; + + +/// 生成image对象 +/// @param view 指定的view ++ (UIImage *)snapshotWithView:(UIView *)view; + + +/// 根据链接生成二维码图片 +/// @param string 二维码的内容 ++ (UIImage *)makeQRCodeForString:(NSString *)string; + ++ (UIImage *)imageWithScreenshot; @end NS_ASSUME_NONNULL_END diff --git a/ios/Classes/Utils/MOPTools.m b/ios/Classes/Utils/MOPTools.m index d9a2baa..d0efbe0 100644 --- a/ios/Classes/Utils/MOPTools.m +++ b/ios/Classes/Utils/MOPTools.m @@ -6,6 +6,7 @@ // #import "MOPTools.h" +#import @implementation MOPTools + (UIViewController *)topViewController{ @@ -120,4 +121,119 @@ return YES; } +/// 设置颜色( + 暗黑模式) +/// @param lightHexString (明亮模式 的颜色值) +/// @param darkHexString (暗黑模式 的颜色值) ++ (UIColor *)fat_dynamicColorWithLightHexString:(NSString *)lightHexString darkHexString:(NSString *)darkHexString { + return [self fat_dynamicColorWithLight:[UIColor fat_colorWithRGBAHexString:lightHexString] darkColor:[UIColor fat_colorWithRGBAHexString:darkHexString]]; +} + ++ (UIColor *)fat_dynamicColorWithLight:(UIColor *)lightColor darkColor:(UIColor *)darkColor { + if (!darkColor) { + return lightColor; + } + BOOL autoAdaptDarkMode = [FATClient sharedClient].uiConfig.autoAdaptDarkMode; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunsupported-availability-guard" +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + if (@available(iOS 13.0, *) && autoAdaptDarkMode) { + return [UIColor colorWithDynamicProvider:^UIColor *_Nonnull(UITraitCollection *_Nonnull traitCollection) { + if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { +#pragma clang diagnostic pop + return darkColor; + } else { + return lightColor; + } + }]; + } else { + return lightColor; + } +} + ++ (UIImage *)snapshotWithView:(UIView *)view { + UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [UIScreen mainScreen].scale); + [view.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + + + ++ (UIImage *)makeQRCodeForString:(NSString *)string { + NSString *text = string; + NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding]; + //生成 + CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; + [qrFilter setValue:stringData forKey:@"inputMessage"]; + [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"]; + //二维码颜色 + UIColor *onColor = [UIColor whiteColor]; + UIColor *offColor = [UIColor blackColor]; + //上色,如果只要白底黑块的QRCode可以跳过这一步 + CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor" + keysAndValues: + @"inputImage",qrFilter.outputImage, + @"inputColor0",[CIColor colorWithCGColor:onColor.CGColor], + @"inputColor1",[CIColor colorWithCGColor:offColor.CGColor], + nil]; + //绘制 + CIImage *qrImage = colorFilter.outputImage; + CGSize size = CGSizeMake(300, 300); + CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent]; + UIGraphicsBeginImageContext(size); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetInterpolationQuality(context, kCGInterpolationNone); + CGContextScaleCTM(context, 1.0, -1.0);//生成的QRCode就是上下颠倒的,需要翻转一下 + CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage); + UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + CGImageRelease(cgImage); + + return [UIImage imageWithCIImage:qrImage]; +} + + +// 截取当前屏幕 ,返回截取到的图片 ++ (UIImage *)imageWithScreenshot { + + + CGSize imageSize = CGSizeZero; + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + if (UIInterfaceOrientationIsPortrait(orientation)) { + imageSize = [UIScreen mainScreen].bounds.size; + } else { + imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width); + } + // 绘制上下文 + UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); + CGContextRef context = UIGraphicsGetCurrentContext(); + for (UIWindow *window in [[UIApplication sharedApplication] windows]) { + CGContextSaveGState(context); + CGContextTranslateCTM(context, window.center.x, window.center.y); + CGContextConcatCTM(context, window.transform); + CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y); + if (orientation == UIInterfaceOrientationLandscapeLeft) { + CGContextRotateCTM(context, M_PI_2); + CGContextTranslateCTM(context, 0, -imageSize.width); + } else if (orientation == UIInterfaceOrientationLandscapeRight) { + CGContextRotateCTM(context, -M_PI_2); + CGContextTranslateCTM(context, -imageSize.height, 0); + } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { + CGContextRotateCTM(context, M_PI); + CGContextTranslateCTM(context, -imageSize.width, -imageSize.height); + } + if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { + [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; + } else { + [window.layer renderInContext:context]; + } + CGContextRestoreGState(context); + } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + NSData *imageData = UIImagePNGRepresentation(image); + return [UIImage imageWithData:imageData]; +} + @end diff --git a/ios/Classes/Utils/MopShareView.h b/ios/Classes/Utils/MopShareView.h new file mode 100644 index 0000000..5fc7df7 --- /dev/null +++ b/ios/Classes/Utils/MopShareView.h @@ -0,0 +1,31 @@ +// +// MopShareView.h +// mop +// +// Created by 王兆耀 on 2023/1/2. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^MOPshareBottomViewTypeBlock)(NSString *type); + +@interface MopShareView : UIView +@property(nonatomic, copy) MOPshareBottomViewTypeBlock didSelcetTypeBlock; +@property (nonatomic, strong) UIImage *image; +@property(nonatomic, strong) NSDictionary *dataDic; ++ (instancetype)viewWithData:(NSDictionary *)data; +- (void)show; +- (void)dismiss; +@end + +@interface MOPshareBottomViewCell : UICollectionViewCell +@property(nonatomic, assign) NSInteger type; +@property(nonatomic, strong) UIImageView *imageView; +@property(nonatomic, strong) UILabel *label; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Classes/Utils/MopShareView.m b/ios/Classes/Utils/MopShareView.m new file mode 100644 index 0000000..b89e5f2 --- /dev/null +++ b/ios/Classes/Utils/MopShareView.m @@ -0,0 +1,291 @@ +// +// MopShareView.m +// mop +// +// Created by 王兆耀 on 2023/1/2. +// + +#import "MopShareView.h" +#import "MopPlugin.h" +#import "MOPTools.h" +#import +#import + +//获取安全区域距离 +#define kFinoSafeAreaTop kFinoWindowSafeAreaInset.top +#define kFinoSafeAreaBottom kFinoWindowSafeAreaInset.bottom + +#define kFinoWindowSafeAreaInset \ +({\ +UIEdgeInsets returnInsets = UIEdgeInsetsMake([UIApplication sharedApplication].statusBarFrame.size.height, 0, 0, 0);\ +UIWindow * keyWindow = [UIApplication sharedApplication].keyWindow;\ +if ([keyWindow respondsToSelector:NSSelectorFromString(@"safeAreaInsets")]) {\ +UIEdgeInsets inset = [[keyWindow valueForKeyPath:@"safeAreaInsets"] UIEdgeInsetsValue];\ +if (inset.top < [UIApplication sharedApplication].statusBarFrame.size.height) {\ +inset.top = [UIApplication sharedApplication].statusBarFrame.size.height;\ +}\ +returnInsets = inset;\ +}\ +(returnInsets);\ +})\ + +@interface MopShareView () + + +@property (nonatomic, strong) UIView *shareView; +@property (nonatomic, strong) UIImageView *appletImageView; + +@property (nonatomic, strong) UIView *contentView; +@property (nonatomic, strong) UIButton *cancelButton; +@property(nonatomic, strong) UICollectionView *collectionView; +@property(nonatomic, strong) NSArray *dataArray; +@property (nonatomic, strong) UIImageView *qrCodeImageView; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UILabel *descLabel; + +@end + +@implementation MopShareView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.dataArray = @[@{@"lightImage":@"share_wechat", @"title":@"微信好友", @"type":@"wechat"}, + @{@"lightImage":@"share_moments",@"title":@"朋友圈", @"type":@"moments"}, + @{@"lightImage":@"share_link",@"title":@"复制链接", @"type":@"links"}]; + self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4f]; + + float proportionWithNumber = self.frame.size.width / 375; + float proportionheightNumber = self.frame.size.height / 667; + + self.shareView = [[UIView alloc] initWithFrame:CGRectMake(52.5 * proportionWithNumber, 46 * proportionheightNumber + kFinoSafeAreaTop, 270 * proportionWithNumber, 380 * proportionheightNumber)]; + self.shareView.layer.cornerRadius = 6; + self.shareView.backgroundColor = UIColor.whiteColor; + + UIImageView *appletImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 6, self.shareView.frame.size.width, 300 * proportionheightNumber)]; + self.appletImageView = appletImageView; + appletImageView.contentMode = UIViewContentModeScaleAspectFit; + [self.shareView addSubview:appletImageView]; + + UIButton *saveButton = [[UIButton alloc] initWithFrame:CGRectMake(226 * proportionWithNumber, 12 * proportionheightNumber, 36, 36)]; + [saveButton addTarget:self action:@selector(saveOnClick) forControlEvents:UIControlEventTouchUpInside]; + [saveButton setImage:[UIImage imageNamed:@"share_download"] forState:UIControlStateNormal]; + [self.shareView addSubview:saveButton]; + + float bottomY = appletImageView.frame.size.height + appletImageView.frame.origin.y; + + UILabel *descLabel = [[UILabel alloc] init]; + descLabel.frame = CGRectMake(15, bottomY + 12, 168, 21); + descLabel.font = [UIFont fontWithName:@"PingFangSC-Semibold" size:15]; + descLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#222222" darkHexString:@"#222222"]; + self.titleLabel = descLabel; + [self.shareView addSubview:descLabel]; + + UILabel *detailLabel = [[UILabel alloc] init]; + detailLabel.frame = CGRectMake(15, bottomY + 26, 168, 44); + detailLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:11]; + detailLabel.numberOfLines = 0; + detailLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#666666" darkHexString:@"#666666"]; + self.descLabel = detailLabel; + [self.shareView addSubview:detailLabel]; + + self.qrCodeImageView = [[UIImageView alloc] initWithFrame:CGRectMake(196, bottomY + 8, 64, 64)]; + [self.shareView addSubview:self.qrCodeImageView]; + + [self addSubview:self.shareView]; + + + self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, self.shareView.frame.origin.y + self.shareView.frame.size.height + 28 , self.frame.size.width, (221 + kFinoSafeAreaBottom))]; + self.contentView.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#F0F0F0" darkHexString:@"#1A1A1A"]; + [self addSubview:self.contentView]; + + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, 58 )]; + titleLabel.text = @"分享至"; + titleLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#222222" darkHexString:@"#D0D0D0"]; + titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:16]; + titleLabel.textAlignment = NSTextAlignmentCenter; + [self.contentView addSubview:titleLabel]; + + UIView *line1 = [[UIView alloc] initWithFrame:CGRectMake(0, 58 , self.contentView.frame.size.width, 0.5)]; + line1.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#E0E0E0" darkHexString:@"#2E2E2E"]; + [self.contentView addSubview:line1]; + + self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; + NSString *cancel = [MOPTools fat_currentLanguageIsEn] ? @"Cancel" : @"取消"; + self.cancelButton.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:17]; + [self.cancelButton setTitle:cancel forState:UIControlStateNormal]; + [self.cancelButton setTitleColor:[MOPTools fat_dynamicColorWithLightHexString:@"#222222" darkHexString:@"#D0D0D0"] forState:UIControlStateNormal]; + [self.contentView addSubview:self.cancelButton]; + self.cancelButton.frame = CGRectMake(0, self.contentView.frame.size.height - kFinoSafeAreaBottom - 56, self.contentView.frame.size.width, 56 ); + [self.cancelButton addTarget:self action:@selector(dismiss) forControlEvents:UIControlEventTouchUpInside]; + + [self.contentView addSubview:self.collectionView]; + self.collectionView.frame = CGRectMake(0, 58.5, frame.size.width, 107); + + UIView *line2 = [[UIView alloc] initWithFrame:CGRectMake(0, 165.5, self.collectionView.frame.size.width, 0.5)]; + line2.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#E0E0E0" darkHexString:@"#2E2E2E"]; + [self.contentView addSubview:line2]; + UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.contentView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(6.0, 6.0)]; + CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; + maskLayer.frame = self.contentView.bounds; + maskLayer.path = maskPath.CGPath; + self.contentView.layer.mask = maskLayer; + + [self p_addNotifications]; + } + return self; +} + ++ (instancetype)viewWithData:(NSDictionary *)data { + MopShareView *view = [[self alloc] initWithFrame:[UIScreen mainScreen].bounds]; + view.dataDic = data; + return view; +} + +- (void)setDataDic:(NSDictionary *)dataDic { + dispatch_async(dispatch_get_main_queue(), ^{ + self.qrCodeImageView.image = [MOPTools makeQRCodeForString:dataDic[@"shareUrl"]]; + }); + self.titleLabel.text = dataDic[@"miniAppName"]; + self.descLabel.text = dataDic[@"miniAppDesc"]; +} + +- (void)saveOnClick { + // 把view生成图片并保存 + UIImage *image = [MOPTools snapshotWithView:self.shareView]; + UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), (__bridge void *)self); +} + +- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { + if (!error) { + // 出错 + [self fatMakeToast:@"保存成功" duration:1.5 position:CSToastPositionCenter]; + } else { + [self fatMakeToast:[NSString stringWithFormat:@"保存失败,%@", error.description] duration:1.5 position:CSToastPositionCenter]; + + } +} + + +- (void)p_addNotifications { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil]; +} + +- (void)deviceOrientationDidChange { + CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; + CGFloat currentWidth = self.frame.size.width; + if (screenWidth != currentWidth) { + [self removeFromSuperview]; + } +} + +- (void)show { + self.appletImageView.image = self.image; + if (self.superview) { + return; + } + [UIView animateWithDuration:0.3 animations:^{ + UIWindow * window = [UIApplication sharedApplication].keyWindow; + [window addSubview:self]; + } completion:^(BOOL finished) { + }]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.25 animations:^{ + self.contentView.transform = CGAffineTransformMakeTranslation(0, self.contentView.frame.size.height); + self.alpha = 0.5f; + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { +// [self dismiss]; +} + +#pragma mark colletionview ------------------------------ +static NSString *cellID = @"cellid"; +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + MOPshareBottomViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath]; +// cell.type = [self.dataArray[indexPath.row] intValue]; + cell.imageView.image = [UIImage imageNamed:self.dataArray[indexPath.row][@"lightImage"]]; + cell.label.text = self.dataArray[indexPath.row][@"title"]; + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + if (self.didSelcetTypeBlock) { + NSString *typeString = self.dataArray[indexPath.row][@"type"]; + self.didSelcetTypeBlock(typeString); + } + [self dismiss]; +} + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 1; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.dataArray.count; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return CGSizeMake(66, self.collectionView.frame.size.height); +} + +- (UICollectionViewFlowLayout *)layout { + UICollectionViewFlowLayout *collectionViewLayout = [[UICollectionViewFlowLayout alloc] init]; + collectionViewLayout.minimumLineSpacing = 0; + collectionViewLayout.minimumInteritemSpacing = 0; + collectionViewLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + return collectionViewLayout; +} + +- (UICollectionView *)collectionView { + if (!_collectionView) { + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:[self layout]]; + _collectionView.delegate = self; + _collectionView.dataSource = self; + [_collectionView registerClass:[MOPshareBottomViewCell class] forCellWithReuseIdentifier:cellID]; + _collectionView.pagingEnabled = YES; + _collectionView.showsVerticalScrollIndicator = NO; + _collectionView.showsHorizontalScrollIndicator = NO; + _collectionView.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#F0F0F0" darkHexString:@"#1A1A1A"]; + if (@available(iOS 11.0, *)) { + _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + } + return _collectionView;; +} +@end + +@implementation MOPshareBottomViewCell +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#F0F0F0" darkHexString:@"#1A1A1A"]; + + UIView *imageBgView = [[UIView alloc] initWithFrame:CGRectMake(18, 20, 48, 48)]; + imageBgView.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#FFFFFF " darkHexString:@"#2C2C2C"]; + [self.contentView addSubview:imageBgView]; + + self.imageView = [UIImageView new]; + self.imageView.frame = CGRectMake(9, 9, 30, 30); + [imageBgView addSubview:self.imageView]; + + // self.label = [[UILabel alloc] initWithFrame:CGRectMake((frame.size.width-50)/2, 65, frame.size.width, 30)]; + self.label = [[UILabel alloc] initWithFrame:CGRectMake(18, 75, 48, 12)]; + self.label.font = [UIFont systemFontOfSize:10]; + self.label.textColor = [UIColor grayColor]; + self.label.textAlignment = NSTextAlignmentCenter; + [self.contentView addSubview:self.label]; + + } + return self; +} + +@end + diff --git a/ios/Classes/Utils/UIView+MOPFATToast.h b/ios/Classes/Utils/UIView+MOPFATToast.h new file mode 100644 index 0000000..3a2fea7 --- /dev/null +++ b/ios/Classes/Utils/UIView+MOPFATToast.h @@ -0,0 +1,421 @@ +#import + +extern const NSString * CSToastPositionTop; +extern const NSString * CSToastPositionCenter; +extern const NSString * CSToastPositionBottom; + +@class CSToastStyle; + +/** + Toast is an Objective-C category that adds toast notifications to the UIView + object class. It is intended to be simple, lightweight, and easy to use. Most + toast notifications can be triggered with a single line of code. + + The `makeToast:` methods create a new view and then display it as toast. + + The `showToast:` methods display any view as toast. + + */ +@interface UIView (MOPFATToast) + +/** + Creates and presents a new toast view with a message and displays it with the + default duration and position. Styled using the shared style. + + @param message The message to be displayed + */ +- (void)fatMakeToast:(NSString *)message; + +/** + Creates and presents a new toast view with a message. Duration and position + can be set explicitly. Styled using the shared style. + + @param message The message to be displayed + @param duration The toast duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + */ +- (void)fatMakeToast:(NSString *)message + duration:(NSTimeInterval)duration + position:(id)position; + +/** + Creates and presents a new toast view with a message. Duration, position, and + style can be set explicitly. + + @param message The message to be displayed + @param duration The toast duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + @param style The style. The shared style will be used when nil + */ +- (void)fatMakeToast:(NSString *)message + duration:(NSTimeInterval)duration + position:(id)position + style:(CSToastStyle *)style; + +/** + Creates and presents a new toast view with a message, title, and image. Duration, + position, and style can be set explicitly. The completion block executes when the + toast view completes. `didTap` will be `YES` if the toast view was dismissed from + a tap. + + @param message The message to be displayed + @param duration The toast duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + @param title The title + @param image The image + @param style The style. The shared style will be used when nil + @param completion The completion block, executed after the toast view disappears. + didTap will be `YES` if the toast view was dismissed from a tap. + */ +- (void)fatMakeToast:(NSString *)message + duration:(NSTimeInterval)duration + position:(id)position + title:(NSString *)title + image:(UIImage *)image + style:(CSToastStyle *)style + completion:(void(^)(BOOL didTap))completion; + +/** + Creates a new toast view with any combination of message, title, and image. + The look and feel is configured via the style. Unlike the `makeToast:` methods, + this method does not present the toast view automatically. One of the showToast: + methods must be used to present the resulting view. + + @warning if message, title, and image are all nil, this method will return nil. + + @param message The message to be displayed + @param title The title + @param image The image + @param style The style. The shared style will be used when nil + @return The newly created toast view + */ +- (UIView *)fatToastViewForMessage:(NSString *)message + title:(NSString *)title + image:(UIImage *)image + style:(CSToastStyle *)style; + +/** + Hides the active toast. If there are multiple toasts active in a view, this method + hides the oldest toast (the first of the toasts to have been presented). + + @see `hideAllToasts` to remove all active toasts from a view. + + @warning This method has no effect on activity toasts. Use `hideToastActivity` to + hide activity toasts. + */ +- (void)fatHideToast; + +/** + Hides an active toast. + + @param toast The active toast view to dismiss. Any toast that is currently being displayed + on the screen is considered active. + + @warning this does not clear a toast view that is currently waiting in the queue. + */ +- (void)fatHideToast:(UIView *)toast; + +/** + Hides all active toast views and clears the queue. + */ +- (void)fatHideAllToasts; + +/** + Hides all active toast views, with options to hide activity and clear the queue. + + @param includeActivity If `true`, toast activity will also be hidden. Default is `false`. + @param clearQueue If `true`, removes all toast views from the queue. Default is `true`. + */ +- (void)fatHideAllToasts:(BOOL)includeActivity clearQueue:(BOOL)clearQueue; + +/** + Removes all toast views from the queue. This has no effect on toast views that are + active. Use `hideAllToasts` to hide the active toasts views and clear the queue. + */ +- (void)fatClearToastQueue; + +/** + Creates and displays a new toast activity indicator view at a specified position. + + @warning Only one toast activity indicator view can be presented per superview. Subsequent + calls to `makeToastActivity:` will be ignored until hideToastActivity is called. + + @warning `makeToastActivity:` works independently of the showToast: methods. Toast activity + views can be presented and dismissed while toast views are being displayed. `makeToastActivity:` + has no effect on the queueing behavior of the showToast: methods. + + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + */ +- (void)fatMakeToastActivity:(id)position; + +/** + Dismisses the active toast activity indicator view. + */ +- (void)fatHideToastActivity; + +/** + Displays any view as toast using the default duration and position. + + @param toast The view to be displayed as toast + */ +- (void)fatShowToast:(UIView *)toast; + +/** + Displays any view as toast at a provided position and duration. The completion block + executes when the toast view completes. `didTap` will be `YES` if the toast view was + dismissed from a tap. + + @param toast The view to be displayed as toast + @param duration The notification duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + @param completion The completion block, executed after the toast view disappears. + didTap will be `YES` if the toast view was dismissed from a tap. + */ +- (void)fatShowToast:(UIView *)toast + duration:(NSTimeInterval)duration + position:(id)position + completion:(void(^)(BOOL didTap))completion; + +@end + +/** + `CSToastStyle` instances define the look and feel for toast views created via the + `makeToast:` methods as well for toast views created directly with + `toastViewForMessage:title:image:style:`. + + @warning `CSToastStyle` offers relatively simple styling options for the default + toast view. If you require a toast view with more complex UI, it probably makes more + sense to create your own custom UIView subclass and present it with the `showToast:` + methods. + */ +@interface CSToastStyle : NSObject + +/** + The background color. Default is `[UIColor blackColor]` at 80% opacity. + */ +@property (strong, nonatomic) UIColor *backgroundColor; + +/** + The title color. Default is `[UIColor whiteColor]`. + */ +@property (strong, nonatomic) UIColor *titleColor; + +/** + The message color. Default is `[UIColor whiteColor]`. + */ +@property (strong, nonatomic) UIColor *messageColor; + +/** + A percentage value from 0.0 to 1.0, representing the maximum width of the toast + view relative to it's superview. Default is 0.8 (80% of the superview's width). + */ +@property (assign, nonatomic) CGFloat maxWidthPercentage; + +/** + A percentage value from 0.0 to 1.0, representing the maximum height of the toast + view relative to it's superview. Default is 0.8 (80% of the superview's height). + */ +@property (assign, nonatomic) CGFloat maxHeightPercentage; + +/** + The spacing from the horizontal edge of the toast view to the content. When an image + is present, this is also used as the padding between the image and the text. + Default is 10.0. + */ +@property (assign, nonatomic) CGFloat horizontalPadding; + +/** + The spacing from the vertical edge of the toast view to the content. When a title + is present, this is also used as the padding between the title and the message. + Default is 10.0. + */ +@property (assign, nonatomic) CGFloat verticalPadding; + +/** + The corner radius. Default is 10.0. + */ +@property (assign, nonatomic) CGFloat cornerRadius; + +/** + The title font. Default is `[UIFont boldSystemFontOfSize:16.0]`. + */ +@property (strong, nonatomic) UIFont *titleFont; + +/** + The message font. Default is `[UIFont systemFontOfSize:16.0]`. + */ +@property (strong, nonatomic) UIFont *messageFont; + +/** + The title text alignment. Default is `NSTextAlignmentLeft`. + */ +@property (assign, nonatomic) NSTextAlignment titleAlignment; + +/** + The message text alignment. Default is `NSTextAlignmentLeft`. + */ +@property (assign, nonatomic) NSTextAlignment messageAlignment; + +/** + The maximum number of lines for the title. The default is 0 (no limit). + */ +@property (assign, nonatomic) NSInteger titleNumberOfLines; + +/** + The maximum number of lines for the message. The default is 0 (no limit). + */ +@property (assign, nonatomic) NSInteger messageNumberOfLines; + +/** + Enable or disable a shadow on the toast view. Default is `NO`. + */ +@property (assign, nonatomic) BOOL displayShadow; + +/** + The shadow color. Default is `[UIColor blackColor]`. + */ +@property (strong, nonatomic) UIColor *shadowColor; + +/** + A value from 0.0 to 1.0, representing the opacity of the shadow. + Default is 0.8 (80% opacity). + */ +@property (assign, nonatomic) CGFloat shadowOpacity; + +/** + The shadow radius. Default is 6.0. + */ +@property (assign, nonatomic) CGFloat shadowRadius; + +/** + The shadow offset. The default is `CGSizeMake(4.0, 4.0)`. + */ +@property (assign, nonatomic) CGSize shadowOffset; + +/** + The image size. The default is `CGSizeMake(80.0, 80.0)`. + */ +@property (assign, nonatomic) CGSize imageSize; + +/** + The size of the toast activity view when `makeToastActivity:` is called. + Default is `CGSizeMake(100.0, 100.0)`. + */ +@property (assign, nonatomic) CGSize activitySize; + +/** + The fade in/out animation duration. Default is 0.2. + */ +@property (assign, nonatomic) NSTimeInterval fadeDuration; + +/** + Creates a new instance of `CSToastStyle` with all the default values set. + */ +- (instancetype)initWithDefaultStyle NS_DESIGNATED_INITIALIZER; + +/** + @warning Only the designated initializer should be used to create + an instance of `CSToastStyle`. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +/** + `CSToastManager` provides general configuration options for all toast + notifications. Backed by a singleton instance. + */ +@interface CSToastManager : NSObject + +/** + Sets the shared style on the singleton. The shared style is used whenever + a `makeToast:` method (or `toastViewForMessage:title:image:style:`) is called + with with a nil style. By default, this is set to `CSToastStyle`'s default + style. + + @param sharedStyle the shared style + */ ++ (void)setSharedStyle:(CSToastStyle *)sharedStyle; + +/** + Gets the shared style from the singlton. By default, this is + `CSToastStyle`'s default style. + + @return the shared style + */ ++ (CSToastStyle *)sharedStyle; + +/** + Enables or disables tap to dismiss on toast views. Default is `YES`. + + @param tapToDismissEnabled YES or NO + */ ++ (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled; + +/** + Returns `YES` if tap to dismiss is enabled, otherwise `NO`. + Default is `YES`. + + @return BOOL YES or NO + */ ++ (BOOL)isTapToDismissEnabled; + +/** + Enables or disables queueing behavior for toast views. When `YES`, + toast views will appear one after the other. When `NO`, multiple Toast + views will appear at the same time (potentially overlapping depending + on their positions). This has no effect on the toast activity view, + which operates independently of normal toast views. Default is `NO`. + + @param queueEnabled YES or NO + */ ++ (void)setQueueEnabled:(BOOL)queueEnabled; + +/** + Returns `YES` if the queue is enabled, otherwise `NO`. + Default is `NO`. + + @return BOOL + */ ++ (BOOL)isQueueEnabled; + +/** + Sets the default duration. Used for the `makeToast:` and + `showToast:` methods that don't require an explicit duration. + Default is 3.0. + + @param duration The toast duration + */ ++ (void)setDefaultDuration:(NSTimeInterval)duration; + +/** + Returns the default duration. Default is 3.0. + + @return duration The toast duration +*/ ++ (NSTimeInterval)defaultDuration; + +/** + Sets the default position. Used for the `makeToast:` and + `showToast:` methods that don't require an explicit position. + Default is `CSToastPositionBottom`. + + @param position The default center point. Can be one of the predefined + CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object. + */ ++ (void)setDefaultPosition:(id)position; + +/** + Returns the default toast position. Default is `CSToastPositionBottom`. + + @return position The default center point. Will be one of the predefined + CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object. + */ ++ (id)defaultPosition; + +@end diff --git a/ios/Classes/Utils/UIView+MOPFATToast.m b/ios/Classes/Utils/UIView+MOPFATToast.m new file mode 100644 index 0000000..110cd62 --- /dev/null +++ b/ios/Classes/Utils/UIView+MOPFATToast.m @@ -0,0 +1,561 @@ +#import "UIView+MOPFATToast.h" +#import +#import + +// Positions +NSString * CSToastPositionTop = @"CSToastPositionTop"; +NSString * CSToastPositionCenter = @"CSToastPositionCenter"; +NSString * CSToastPositionBottom = @"CSToastPositionBottom"; + +// Keys for values associated with toast views +static const NSString * CSToastTimerKey = @"CSToastTimerKey"; +static const NSString * CSToastDurationKey = @"CSToastDurationKey"; +static const NSString * CSToastPositionKey = @"CSToastPositionKey"; +static const NSString * CSToastCompletionKey = @"CSToastCompletionKey"; + +// Keys for values associated with self +static const NSString * CSToastActiveKey = @"CSToastActiveKey"; +static const NSString * CSToastActivityViewKey = @"CSToastActivityViewKey"; +static const NSString * CSToastQueueKey = @"CSToastQueueKey"; + +@interface UIView (ToastPrivate) + +/** + These private methods are being prefixed with "cs_" to reduce the likelihood of non-obvious + naming conflicts with other UIView methods. + + @discussion Should the public API also use the cs_ prefix? Technically it should, but it + results in code that is less legible. The current public method names seem unlikely to cause + conflicts so I think we should favor the cleaner API for now. + */ +- (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position; +- (void)cs_hideToast:(UIView *)toast; +- (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap; +- (void)cs_toastTimerDidFinish:(NSTimer *)timer; +- (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer; +- (CGPoint)cs_centerPointForPosition:(id)position withToast:(UIView *)toast; +- (NSMutableArray *)cs_toastQueue; + +@end + +@implementation UIView (MOPFATToast) + +#pragma mark - Make Toast Methods + +- (void)fatMakeToast:(NSString *)message { + [self fatMakeToast:message duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] style:nil]; +} + +- (void)fatMakeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position { + [self fatMakeToast:message duration:duration position:position style:nil]; +} + +- (void)fatMakeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position style:(CSToastStyle *)style { + UIView *toast = [self fatToastViewForMessage:message title:nil image:nil style:style]; + [self fatShowToast:toast duration:duration position:position completion:nil]; +} + +- (void)fatMakeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style completion:(void(^)(BOOL didTap))completion { + UIView *toast = [self fatToastViewForMessage:message title:title image:image style:style]; + [self fatShowToast:toast duration:duration position:position completion:completion]; +} + +#pragma mark - Show Toast Methods + +- (void)fatShowToast:(UIView *)toast { + [self fatShowToast:toast duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] completion:nil]; +} + +- (void)fatShowToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position completion:(void(^)(BOOL didTap))completion { + // sanity + if (toast == nil) return; + + // store the completion block on the toast view + objc_setAssociatedObject(toast, &CSToastCompletionKey, completion, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + if ([CSToastManager isQueueEnabled] && [self.cs_activeToasts count] > 0) { + // we're about to queue this toast view so we need to store the duration and position as well + objc_setAssociatedObject(toast, &CSToastDurationKey, @(duration), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(toast, &CSToastPositionKey, position, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // enqueue + [self.cs_toastQueue addObject:toast]; + } else { + // present + [self cs_showToast:toast duration:duration position:position]; + } +} + +#pragma mark - Hide Toast Methods + +- (void)fatHideToast { + [self fatHideToast:[[self cs_activeToasts] firstObject]]; +} + +- (void)fatHideToast:(UIView *)toast { + // sanity + if (!toast || ![[self cs_activeToasts] containsObject:toast]) return; + + [self cs_hideToast:toast]; +} + +- (void)fatHideAllToasts { + [self fatHideAllToasts:NO clearQueue:YES]; +} + +- (void)fatHideAllToasts:(BOOL)includeActivity clearQueue:(BOOL)clearQueue { + if (clearQueue) { + [self fatClearToastQueue]; + } + + for (UIView *toast in [self cs_activeToasts]) { + [self fatHideToast:toast]; + } + + if (includeActivity) { + [self fatHideToastActivity]; + } +} + +- (void)fatClearToastQueue { + [[self cs_toastQueue] removeAllObjects]; +} + +#pragma mark - Private Show/Hide Methods + +- (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position { + toast.center = [self cs_centerPointForPosition:position withToast:toast]; + toast.alpha = 0.0; + + if ([CSToastManager isTapToDismissEnabled]) { + UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cs_handleToastTapped:)]; + [toast addGestureRecognizer:recognizer]; + toast.userInteractionEnabled = YES; + toast.exclusiveTouch = YES; + } + + [[self cs_activeToasts] addObject:toast]; + + [self addSubview:toast]; + + [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] + delay:0.0 + options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction) + animations:^{ + toast.alpha = 1.0; + } completion:^(BOOL finished) { + NSTimer *timer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(cs_toastTimerDidFinish:) userInfo:toast repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + objc_setAssociatedObject(toast, &CSToastTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }]; +} + +- (void)cs_hideToast:(UIView *)toast { + [self cs_hideToast:toast fromTap:NO]; +} + +- (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap { + NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey); + [timer invalidate]; + + [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] + delay:0.0 + options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + toast.alpha = 0.0; + } completion:^(BOOL finished) { + [toast removeFromSuperview]; + + // remove + [[self cs_activeToasts] removeObject:toast]; + + // execute the completion block, if necessary + void (^completion)(BOOL didTap) = objc_getAssociatedObject(toast, &CSToastCompletionKey); + if (completion) { + completion(fromTap); + } + + if ([self.cs_toastQueue count] > 0) { + // dequeue + UIView *nextToast = [[self cs_toastQueue] firstObject]; + [[self cs_toastQueue] removeObjectAtIndex:0]; + + // present the next toast + NSTimeInterval duration = [objc_getAssociatedObject(nextToast, &CSToastDurationKey) doubleValue]; + id position = objc_getAssociatedObject(nextToast, &CSToastPositionKey); + [self cs_showToast:nextToast duration:duration position:position]; + } + }]; +} + +#pragma mark - View Construction + +- (UIView *)fatToastViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style { + // sanity + if (message == nil && title == nil && image == nil) return nil; + + // default to the shared style + if (style == nil) { + style = [CSToastManager sharedStyle]; + } + + // dynamically build a toast view with any combination of message, title, & image + UILabel *messageLabel = nil; + UILabel *titleLabel = nil; + UIImageView *imageView = nil; + + UIView *wrapperView = [[UIView alloc] init]; + wrapperView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + wrapperView.layer.cornerRadius = style.cornerRadius; + + if (style.displayShadow) { + wrapperView.layer.shadowColor = style.shadowColor.CGColor; + wrapperView.layer.shadowOpacity = style.shadowOpacity; + wrapperView.layer.shadowRadius = style.shadowRadius; + wrapperView.layer.shadowOffset = style.shadowOffset; + } + + wrapperView.backgroundColor = style.backgroundColor; + + if(image != nil) { + imageView = [[UIImageView alloc] initWithImage:image]; + imageView.contentMode = UIViewContentModeScaleAspectFit; + imageView.frame = CGRectMake(style.horizontalPadding, style.verticalPadding, style.imageSize.width, style.imageSize.height); + } + + CGRect imageRect = CGRectZero; + + if(imageView != nil) { + imageRect.origin.x = style.horizontalPadding; + imageRect.origin.y = style.verticalPadding; + imageRect.size.width = imageView.bounds.size.width; + imageRect.size.height = imageView.bounds.size.height; + } + + if (title != nil) { + titleLabel = [[UILabel alloc] init]; + titleLabel.numberOfLines = style.titleNumberOfLines; + titleLabel.font = style.titleFont; + titleLabel.textAlignment = style.titleAlignment; + titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; + titleLabel.textColor = style.titleColor; + titleLabel.backgroundColor = [UIColor clearColor]; + titleLabel.alpha = 1.0; + titleLabel.text = title; + + // size the title label according to the length of the text + CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage); + CGSize expectedSizeTitle = [titleLabel sizeThatFits:maxSizeTitle]; + // UILabel can return a size larger than the max size when the number of lines is 1 + expectedSizeTitle = CGSizeMake(MIN(maxSizeTitle.width, expectedSizeTitle.width), MIN(maxSizeTitle.height, expectedSizeTitle.height)); + titleLabel.frame = CGRectMake(0.0, 0.0, expectedSizeTitle.width, expectedSizeTitle.height); + } + + if (message != nil) { + messageLabel = [[UILabel alloc] init]; + messageLabel.numberOfLines = style.messageNumberOfLines; + messageLabel.font = style.messageFont; + messageLabel.textAlignment = style.messageAlignment; + messageLabel.lineBreakMode = NSLineBreakByTruncatingTail; + messageLabel.textColor = style.messageColor; + messageLabel.backgroundColor = [UIColor clearColor]; + messageLabel.alpha = 1.0; + messageLabel.text = message; + + CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage); + CGSize expectedSizeMessage = [messageLabel sizeThatFits:maxSizeMessage]; + // UILabel can return a size larger than the max size when the number of lines is 1 + expectedSizeMessage = CGSizeMake(MIN(maxSizeMessage.width, expectedSizeMessage.width), MIN(maxSizeMessage.height, expectedSizeMessage.height)); + messageLabel.frame = CGRectMake(0.0, 0.0, expectedSizeMessage.width, expectedSizeMessage.height); + } + + CGRect titleRect = CGRectZero; + + if(titleLabel != nil) { + titleRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding; + titleRect.origin.y = style.verticalPadding; + titleRect.size.width = titleLabel.bounds.size.width; + titleRect.size.height = titleLabel.bounds.size.height; + } + + CGRect messageRect = CGRectZero; + + if(messageLabel != nil) { + messageRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding; + messageRect.origin.y = titleRect.origin.y + titleRect.size.height + style.verticalPadding; + messageRect.size.width = messageLabel.bounds.size.width; + messageRect.size.height = messageLabel.bounds.size.height; + } + + CGFloat longerWidth = MAX(titleRect.size.width, messageRect.size.width); + CGFloat longerX = MAX(titleRect.origin.x, messageRect.origin.x); + + // Wrapper width uses the longerWidth or the image width, whatever is larger. Same logic applies to the wrapper height. + CGFloat wrapperWidth = MAX((imageRect.size.width + (style.horizontalPadding * 2.0)), (longerX + longerWidth + style.horizontalPadding)); + CGFloat wrapperHeight = MAX((messageRect.origin.y + messageRect.size.height + style.verticalPadding), (imageRect.size.height + (style.verticalPadding * 2.0))); + + wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight); + + if(titleLabel != nil) { + titleLabel.frame = titleRect; + [wrapperView addSubview:titleLabel]; + } + + if(messageLabel != nil) { + messageLabel.frame = messageRect; + [wrapperView addSubview:messageLabel]; + } + + if(imageView != nil) { + [wrapperView addSubview:imageView]; + } + + return wrapperView; +} + +#pragma mark - Storage + +- (NSMutableArray *)cs_activeToasts { + NSMutableArray *cs_activeToasts = objc_getAssociatedObject(self, &CSToastActiveKey); + if (cs_activeToasts == nil) { + cs_activeToasts = [[NSMutableArray alloc] init]; + objc_setAssociatedObject(self, &CSToastActiveKey, cs_activeToasts, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return cs_activeToasts; +} + +- (NSMutableArray *)cs_toastQueue { + NSMutableArray *cs_toastQueue = objc_getAssociatedObject(self, &CSToastQueueKey); + if (cs_toastQueue == nil) { + cs_toastQueue = [[NSMutableArray alloc] init]; + objc_setAssociatedObject(self, &CSToastQueueKey, cs_toastQueue, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return cs_toastQueue; +} + +#pragma mark - Events + +- (void)cs_toastTimerDidFinish:(NSTimer *)timer { + [self cs_hideToast:(UIView *)timer.userInfo]; +} + +- (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer { + UIView *toast = recognizer.view; + NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey); + [timer invalidate]; + + [self cs_hideToast:toast fromTap:YES]; +} + +#pragma mark - Activity Methods + +- (void)fatMakeToastActivity:(id)position { + // sanity + UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey); + if (existingActivityView != nil) return; + + CSToastStyle *style = [CSToastManager sharedStyle]; + + UIView *activityView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, style.activitySize.width, style.activitySize.height)]; + activityView.center = [self cs_centerPointForPosition:position withToast:activityView]; + activityView.backgroundColor = style.backgroundColor; + activityView.alpha = 0.0; + activityView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + activityView.layer.cornerRadius = style.cornerRadius; + + if (style.displayShadow) { + activityView.layer.shadowColor = style.shadowColor.CGColor; + activityView.layer.shadowOpacity = style.shadowOpacity; + activityView.layer.shadowRadius = style.shadowRadius; + activityView.layer.shadowOffset = style.shadowOffset; + } + + UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + activityIndicatorView.center = CGPointMake(activityView.bounds.size.width / 2, activityView.bounds.size.height / 2); + [activityView addSubview:activityIndicatorView]; + [activityIndicatorView startAnimating]; + + // associate the activity view with self + objc_setAssociatedObject (self, &CSToastActivityViewKey, activityView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + [self addSubview:activityView]; + + [UIView animateWithDuration:style.fadeDuration + delay:0.0 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + activityView.alpha = 1.0; + } completion:nil]; +} + +- (void)fatHideToastActivity { + UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey); + if (existingActivityView != nil) { + [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] + delay:0.0 + options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + existingActivityView.alpha = 0.0; + } completion:^(BOOL finished) { + [existingActivityView removeFromSuperview]; + objc_setAssociatedObject (self, &CSToastActivityViewKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }]; + } +} + +#pragma mark - Helpers + +- (CGPoint)cs_centerPointForPosition:(id)point withToast:(UIView *)toast { + CSToastStyle *style = [CSToastManager sharedStyle]; + + UIEdgeInsets safeInsets = UIEdgeInsetsZero; + if (@available(iOS 11.0, *)) { + safeInsets = self.safeAreaInsets; + } + + CGFloat topPadding = style.verticalPadding + safeInsets.top; + CGFloat bottomPadding = style.verticalPadding + safeInsets.bottom; + + if([point isKindOfClass:[NSString class]]) { + if([point caseInsensitiveCompare:CSToastPositionTop] == NSOrderedSame) { + return CGPointMake(self.bounds.size.width / 2.0, (toast.frame.size.height / 2.0) + topPadding); + } else if([point caseInsensitiveCompare:CSToastPositionCenter] == NSOrderedSame) { + return CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0); + } + } else if ([point isKindOfClass:[NSValue class]]) { + return [point CGPointValue]; + } + + // default to bottom + return CGPointMake(self.bounds.size.width / 2.0, (self.bounds.size.height - (toast.frame.size.height / 2.0)) - bottomPadding); +} + +@end + +@implementation CSToastStyle + +#pragma mark - Constructors + +- (instancetype)initWithDefaultStyle { + self = [super init]; + if (self) { + self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8]; + self.titleColor = [UIColor whiteColor]; + self.messageColor = [UIColor whiteColor]; + self.maxWidthPercentage = 0.8; + self.maxHeightPercentage = 0.8; + self.horizontalPadding = 10.0; + self.verticalPadding = 10.0; + self.cornerRadius = 10.0; + self.titleFont = [UIFont boldSystemFontOfSize:16.0]; + self.messageFont = [UIFont systemFontOfSize:16.0]; + self.titleAlignment = NSTextAlignmentLeft; + self.messageAlignment = NSTextAlignmentLeft; + self.titleNumberOfLines = 0; + self.messageNumberOfLines = 0; + self.displayShadow = NO; + self.shadowOpacity = 0.8; + self.shadowRadius = 6.0; + self.shadowOffset = CGSizeMake(4.0, 4.0); + self.imageSize = CGSizeMake(80.0, 80.0); + self.activitySize = CGSizeMake(100.0, 100.0); + self.fadeDuration = 0.2; + } + return self; +} + +- (void)setMaxWidthPercentage:(CGFloat)maxWidthPercentage { + _maxWidthPercentage = MAX(MIN(maxWidthPercentage, 1.0), 0.0); +} + +- (void)setMaxHeightPercentage:(CGFloat)maxHeightPercentage { + _maxHeightPercentage = MAX(MIN(maxHeightPercentage, 1.0), 0.0); +} + +- (instancetype)init NS_UNAVAILABLE { + return nil; +} + +@end + +@interface CSToastManager () + +@property (strong, nonatomic) CSToastStyle *sharedStyle; +@property (assign, nonatomic, getter=isTapToDismissEnabled) BOOL tapToDismissEnabled; +@property (assign, nonatomic, getter=isQueueEnabled) BOOL queueEnabled; +@property (assign, nonatomic) NSTimeInterval defaultDuration; +@property (strong, nonatomic) id defaultPosition; + +@end + +@implementation CSToastManager + +#pragma mark - Constructors + ++ (instancetype)sharedManager { + static CSToastManager *_sharedManager = nil; + static dispatch_once_t oncePredicate; + dispatch_once(&oncePredicate, ^{ + _sharedManager = [[self alloc] init]; + }); + + return _sharedManager; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.sharedStyle = [[CSToastStyle alloc] initWithDefaultStyle]; + self.tapToDismissEnabled = YES; + self.queueEnabled = NO; + self.defaultDuration = 3.0; + self.defaultPosition = CSToastPositionBottom; + } + return self; +} + +#pragma mark - Singleton Methods + ++ (void)setSharedStyle:(CSToastStyle *)sharedStyle { + [[self sharedManager] setSharedStyle:sharedStyle]; +} + ++ (CSToastStyle *)sharedStyle { + return [[self sharedManager] sharedStyle]; +} + ++ (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled { + [[self sharedManager] setTapToDismissEnabled:tapToDismissEnabled]; +} + ++ (BOOL)isTapToDismissEnabled { + return [[self sharedManager] isTapToDismissEnabled]; +} + ++ (void)setQueueEnabled:(BOOL)queueEnabled { + [[self sharedManager] setQueueEnabled:queueEnabled]; +} + ++ (BOOL)isQueueEnabled { + return [[self sharedManager] isQueueEnabled]; +} + ++ (void)setDefaultDuration:(NSTimeInterval)duration { + [[self sharedManager] setDefaultDuration:duration]; +} + ++ (NSTimeInterval)defaultDuration { + return [[self sharedManager] defaultDuration]; +} + ++ (void)setDefaultPosition:(id)position { + if ([position isKindOfClass:[NSString class]] || [position isKindOfClass:[NSValue class]]) { + [[self sharedManager] setDefaultPosition:position]; + } +} + ++ (id)defaultPosition { + return [[self sharedManager] defaultPosition]; +} + +@end diff --git a/ios/mop.podspec b/ios/mop.podspec index fc53cb3..baa3b93 100644 --- a/ios/mop.podspec +++ b/ios/mop.podspec @@ -17,7 +17,7 @@ A finclip miniprogram flutter sdk. s.dependency 'Flutter' s.ios.deployment_target = '9.0' - s.dependency 'FinApplet' , '2.39.0-alpha20221223v06' - s.dependency 'FinAppletExt' , '2.39.0-alpha20221223v06' + s.dependency 'FinApplet' , '2.39.0-alpha20221222v09' + s.dependency 'FinAppletExt' , '2.39.0-alpha20221222v09' end From 179eeacc95f8f530a22ad892884e84b95d2d09b0 Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Tue, 3 Jan 2023 23:19:33 +0800 Subject: [PATCH 03/10] =?UTF-8?q?1.=E5=8A=A0=E8=BD=BD=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Classes/Api/MOPAppletDelegate.m | 9 ++++++++- ios/mop.podspec | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ios/Classes/Api/MOPAppletDelegate.m b/ios/Classes/Api/MOPAppletDelegate.m index d36e9c0..8947600 100644 --- a/ios/Classes/Api/MOPAppletDelegate.m +++ b/ios/Classes/Api/MOPAppletDelegate.m @@ -74,7 +74,14 @@ MopCustomMenuModel *model = [[MopCustomMenuModel alloc] init]; model.menuId = data[@"menuId"]; model.menuTitle = data[@"title"]; - model.menuIconImage = [UIImage imageNamed:data[@"image"]]; + NSString *imageUrl = data[@"image"]; + if ([imageUrl hasPrefix:@"http"]) { + // 需要异步加载,待优化! + NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]; + model.menuIconImage = [UIImage imageWithData:data]; + } else { + model.menuIconImage = [UIImage imageNamed:imageUrl]; + } NSString *typeString = data[@"type"]; if (typeString) { FATAppletMenuStyle style = [typeString isEqualToString:@"onMiniProgram"] ? FATAppletMenuStyleOnMiniProgram : FATAppletMenuStyleCommon; diff --git a/ios/mop.podspec b/ios/mop.podspec index baa3b93..b6bbd2a 100644 --- a/ios/mop.podspec +++ b/ios/mop.podspec @@ -17,7 +17,7 @@ A finclip miniprogram flutter sdk. s.dependency 'Flutter' s.ios.deployment_target = '9.0' - s.dependency 'FinApplet' , '2.39.0-alpha20221222v09' - s.dependency 'FinAppletExt' , '2.39.0-alpha20221222v09' + s.dependency 'FinApplet' , '2.39.2-alpha20230103v04' + s.dependency 'FinAppletExt' , '2.39.2-alpha20230103v04' end From e25f744df42c3c2e46ee739a3547bb08d17aa181 Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Wed, 4 Jan 2023 22:03:44 +0800 Subject: [PATCH 04/10] 1.update --- ios/Classes/MopPlugin.m | 14 ++++++++++---- ios/Classes/Utils/MOPTools.m | 27 ++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/ios/Classes/MopPlugin.m b/ios/Classes/MopPlugin.m index 397c85a..ef9e9a9 100644 --- a/ios/Classes/MopPlugin.m +++ b/ios/Classes/MopPlugin.m @@ -123,10 +123,16 @@ static MopPlugin *_instance; result([self appInfoDictWithAppId:call.arguments[@"appId"]]); } else if ([@"getScreenshot" isEqualToString:call.method]) { - UIImage *image = [MOPTools imageWithScreenshot]; - NSString *filePtah = [[FATClient sharedClient] saveFile:UIImagePNGRepresentation(image) fileName:[NSString stringWithFormat:@"%@",call.arguments[@"appId"]]]; - filePtah = [[FATClient sharedClient] fat_absolutePathWithPath:filePtah]; - result(filePtah); + UIViewController *currentVC = [MOPTools topViewController]; + [currentVC.view fatHideToastActivity]; + [currentVC.view fatHideAllToasts]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + UIImage *image = [MOPTools imageWithScreenshot]; +// UIImage *image = [[FATClient sharedClient] getCurrentAppletImage]; + NSString *filePtah = [[FATClient sharedClient] saveFile:UIImagePNGRepresentation(image) fileName:[NSString stringWithFormat:@"%@",call.arguments[@"appId"]]]; + filePtah = [[FATClient sharedClient] fat_absolutePathWithPath:filePtah]; + result(filePtah); + }); } else if ([@"getPhoneNumberResult" isEqualToString:call.method]) { if ([MOPAppletDelegate instance].bindGetPhoneNumbers) { diff --git a/ios/Classes/Utils/MOPTools.m b/ios/Classes/Utils/MOPTools.m index d0efbe0..9f507ed 100644 --- a/ios/Classes/Utils/MOPTools.m +++ b/ios/Classes/Utils/MOPTools.m @@ -186,7 +186,7 @@ CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextScaleCTM(context, 1.0, -1.0);//生成的QRCode就是上下颠倒的,需要翻转一下 CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage); - UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGImageRelease(cgImage); @@ -199,9 +199,14 @@ CGSize imageSize = CGSizeZero; + + + + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (UIInterfaceOrientationIsPortrait(orientation)) { - imageSize = [UIScreen mainScreen].bounds.size; +// imageSize = [UIScreen mainScreen].bounds.size; + imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - [self getStatusHeight]); } else { imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width); } @@ -210,9 +215,9 @@ CGContextRef context = UIGraphicsGetCurrentContext(); for (UIWindow *window in [[UIApplication sharedApplication] windows]) { CGContextSaveGState(context); - CGContextTranslateCTM(context, window.center.x, window.center.y); + CGContextTranslateCTM(context, window.center.x, window.center.y - [self getStatusHeight]); CGContextConcatCTM(context, window.transform); - CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y); + CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -(window.bounds.size.height + [self getStatusHeight] ) * window.layer.anchorPoint.y); if (orientation == UIInterfaceOrientationLandscapeLeft) { CGContextRotateCTM(context, M_PI_2); CGContextTranslateCTM(context, 0, -imageSize.width); @@ -224,7 +229,7 @@ CGContextTranslateCTM(context, -imageSize.width, -imageSize.height); } if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { - [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; + [window drawViewHierarchyInRect:CGRectMake(0, [self getStatusHeight], window.bounds.size.width, window.bounds.size.height - [self getStatusHeight]) afterScreenUpdates:YES]; } else { [window.layer renderInContext:context]; } @@ -236,4 +241,16 @@ return [UIImage imageWithData:imageData]; } + +/// 顶部状态栏高度(包括安全区) ++ (CGFloat)getStatusHeight { + if (@available(iOS 13.0, *)) { + NSSet *set = [UIApplication sharedApplication].connectedScenes; + UIWindowScene *windowScene = [set anyObject]; + UIStatusBarManager *statusBarManager = windowScene.statusBarManager; + return statusBarManager.statusBarFrame.size.height; + } else { + return [UIApplication sharedApplication].statusBarFrame.size.height; + } +} @end From 64bd5f8496ae897e47fe8bf4cc7c5fe24a42da5e Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Thu, 5 Jan 2023 18:47:26 +0800 Subject: [PATCH 05/10] 1.update --- ios/Classes/MopPlugin.m | 5 +-- ios/Classes/Utils/MOPTools.h | 9 +--- ios/Classes/Utils/MOPTools.m | 50 +-------------------- ios/Classes/Utils/MopShareView.h | 18 +++++--- ios/Classes/Utils/MopShareView.m | 74 ++++++++++++++++++++------------ ios/mop.podspec | 4 +- 6 files changed, 67 insertions(+), 93 deletions(-) diff --git a/ios/Classes/MopPlugin.m b/ios/Classes/MopPlugin.m index ef9e9a9..a683d65 100644 --- a/ios/Classes/MopPlugin.m +++ b/ios/Classes/MopPlugin.m @@ -95,7 +95,7 @@ static MopPlugin *_instance; } else if ([@"showShareAppletDialog" isEqualToString:call.method]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - UIImage *image = [MOPTools imageWithScreenshot]; + UIImage *image = [[FATClient sharedClient] getDefaultCurrentAppletImage:400.0f]; MopShareView *view = [MopShareView viewWithData:call.arguments]; view.image = image; [view show]; @@ -127,8 +127,7 @@ static MopPlugin *_instance; [currentVC.view fatHideToastActivity]; [currentVC.view fatHideAllToasts]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - UIImage *image = [MOPTools imageWithScreenshot]; -// UIImage *image = [[FATClient sharedClient] getCurrentAppletImage]; + UIImage *image = [[FATClient sharedClient] getDefaultCurrentAppletImage:0.0f]; NSString *filePtah = [[FATClient sharedClient] saveFile:UIImagePNGRepresentation(image) fileName:[NSString stringWithFormat:@"%@",call.arguments[@"appId"]]]; filePtah = [[FATClient sharedClient] fat_absolutePathWithPath:filePtah]; result(filePtah); diff --git a/ios/Classes/Utils/MOPTools.h b/ios/Classes/Utils/MOPTools.h index f516da9..64c315a 100644 --- a/ios/Classes/Utils/MOPTools.h +++ b/ios/Classes/Utils/MOPTools.h @@ -24,21 +24,16 @@ NS_ASSUME_NONNULL_BEGIN /// @param darkHexString (暗黑模式 的颜色值) + (UIColor *)fat_dynamicColorWithLightHexString:(NSString *)lightHexString darkHexString:(NSString *)darkHexString; - -/// 获取当前页面的截图 -+ (UIImage *)currentPageAppletImage; - - /// 生成image对象 /// @param view 指定的view + (UIImage *)snapshotWithView:(UIView *)view; - /// 根据链接生成二维码图片 /// @param string 二维码的内容 + (UIImage *)makeQRCodeForString:(NSString *)string; -+ (UIImage *)imageWithScreenshot; + + @end NS_ASSUME_NONNULL_END diff --git a/ios/Classes/Utils/MOPTools.m b/ios/Classes/Utils/MOPTools.m index 9f507ed..5283bc8 100644 --- a/ios/Classes/Utils/MOPTools.m +++ b/ios/Classes/Utils/MOPTools.m @@ -194,54 +194,6 @@ } -// 截取当前屏幕 ,返回截取到的图片 -+ (UIImage *)imageWithScreenshot { - - - CGSize imageSize = CGSizeZero; - - - - - UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; - if (UIInterfaceOrientationIsPortrait(orientation)) { -// imageSize = [UIScreen mainScreen].bounds.size; - imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - [self getStatusHeight]); - } else { - imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width); - } - // 绘制上下文 - UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); - CGContextRef context = UIGraphicsGetCurrentContext(); - for (UIWindow *window in [[UIApplication sharedApplication] windows]) { - CGContextSaveGState(context); - CGContextTranslateCTM(context, window.center.x, window.center.y - [self getStatusHeight]); - CGContextConcatCTM(context, window.transform); - CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -(window.bounds.size.height + [self getStatusHeight] ) * window.layer.anchorPoint.y); - if (orientation == UIInterfaceOrientationLandscapeLeft) { - CGContextRotateCTM(context, M_PI_2); - CGContextTranslateCTM(context, 0, -imageSize.width); - } else if (orientation == UIInterfaceOrientationLandscapeRight) { - CGContextRotateCTM(context, -M_PI_2); - CGContextTranslateCTM(context, -imageSize.height, 0); - } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { - CGContextRotateCTM(context, M_PI); - CGContextTranslateCTM(context, -imageSize.width, -imageSize.height); - } - if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { - [window drawViewHierarchyInRect:CGRectMake(0, [self getStatusHeight], window.bounds.size.width, window.bounds.size.height - [self getStatusHeight]) afterScreenUpdates:YES]; - } else { - [window.layer renderInContext:context]; - } - CGContextRestoreGState(context); - } - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - NSData *imageData = UIImagePNGRepresentation(image); - return [UIImage imageWithData:imageData]; -} - - /// 顶部状态栏高度(包括安全区) + (CGFloat)getStatusHeight { if (@available(iOS 13.0, *)) { @@ -253,4 +205,6 @@ return [UIApplication sharedApplication].statusBarFrame.size.height; } } + + @end diff --git a/ios/Classes/Utils/MopShareView.h b/ios/Classes/Utils/MopShareView.h index 5fc7df7..0df5bdc 100644 --- a/ios/Classes/Utils/MopShareView.h +++ b/ios/Classes/Utils/MopShareView.h @@ -12,18 +12,26 @@ NS_ASSUME_NONNULL_BEGIN typedef void (^MOPshareBottomViewTypeBlock)(NSString *type); @interface MopShareView : UIView -@property(nonatomic, copy) MOPshareBottomViewTypeBlock didSelcetTypeBlock; +@property (nonatomic, copy) MOPshareBottomViewTypeBlock didSelcetTypeBlock; @property (nonatomic, strong) UIImage *image; -@property(nonatomic, strong) NSDictionary *dataDic; +@property (nonatomic, strong) NSDictionary *dataDic; + (instancetype)viewWithData:(NSDictionary *)data; - (void)show; - (void)dismiss; @end + +@class MOPshareBottomViewCell; + +@protocol MOPCellClickDelegate +- (void)iconBtnDidClick:(MOPshareBottomViewCell *)cell; +@end + @interface MOPshareBottomViewCell : UICollectionViewCell -@property(nonatomic, assign) NSInteger type; -@property(nonatomic, strong) UIImageView *imageView; -@property(nonatomic, strong) UILabel *label; +@property (nonatomic, strong) NSString *type; +@property (nonatomic, strong) UIButton *imageButton; +@property (nonatomic, strong) UILabel *label; +@property (nonatomic, weak) id delegate; @end diff --git a/ios/Classes/Utils/MopShareView.m b/ios/Classes/Utils/MopShareView.m index b89e5f2..857be23 100644 --- a/ios/Classes/Utils/MopShareView.m +++ b/ios/Classes/Utils/MopShareView.m @@ -29,7 +29,7 @@ returnInsets = inset;\ (returnInsets);\ })\ -@interface MopShareView () +@interface MopShareView () @property (nonatomic, strong) UIView *shareView; @@ -56,34 +56,30 @@ returnInsets = inset;\ @{@"lightImage":@"share_link",@"title":@"复制链接", @"type":@"links"}]; self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4f]; - float proportionWithNumber = self.frame.size.width / 375; - float proportionheightNumber = self.frame.size.height / 667; - - self.shareView = [[UIView alloc] initWithFrame:CGRectMake(52.5 * proportionWithNumber, 46 * proportionheightNumber + kFinoSafeAreaTop, 270 * proportionWithNumber, 380 * proportionheightNumber)]; + self.shareView = [[UIView alloc] initWithFrame:CGRectMake(52.5 , 46 + kFinoSafeAreaTop, 270, 380)]; self.shareView.layer.cornerRadius = 6; self.shareView.backgroundColor = UIColor.whiteColor; - UIImageView *appletImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 6, self.shareView.frame.size.width, 300 * proportionheightNumber)]; - self.appletImageView = appletImageView; + UIImageView *appletImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.shareView.frame.size.width, 300)]; appletImageView.contentMode = UIViewContentModeScaleAspectFit; + self.appletImageView = appletImageView; [self.shareView addSubview:appletImageView]; - - UIButton *saveButton = [[UIButton alloc] initWithFrame:CGRectMake(226 * proportionWithNumber, 12 * proportionheightNumber, 36, 36)]; - [saveButton addTarget:self action:@selector(saveOnClick) forControlEvents:UIControlEventTouchUpInside]; - [saveButton setImage:[UIImage imageNamed:@"share_download"] forState:UIControlStateNormal]; - [self.shareView addSubview:saveButton]; - + float bottomY = appletImageView.frame.size.height + appletImageView.frame.origin.y; + UIView *line0 = [[UIView alloc] initWithFrame:CGRectMake(0, bottomY, self.shareView.frame.size.width, 0.5)]; + line0.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#E0E0E0" darkHexString:@"#2E2E2E"]; + [self.shareView addSubview:line0]; + UILabel *descLabel = [[UILabel alloc] init]; - descLabel.frame = CGRectMake(15, bottomY + 12, 168, 21); + descLabel.frame = CGRectMake(14, bottomY + 12, 168, 21); descLabel.font = [UIFont fontWithName:@"PingFangSC-Semibold" size:15]; descLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#222222" darkHexString:@"#222222"]; self.titleLabel = descLabel; [self.shareView addSubview:descLabel]; UILabel *detailLabel = [[UILabel alloc] init]; - detailLabel.frame = CGRectMake(15, bottomY + 26, 168, 44); + detailLabel.frame = CGRectMake(14, self.titleLabel.frame.size.height + self.titleLabel.frame.origin.y + 5, 168, 44); detailLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:11]; detailLabel.numberOfLines = 0; detailLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#666666" darkHexString:@"#666666"]; @@ -96,7 +92,7 @@ returnInsets = inset;\ [self addSubview:self.shareView]; - self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0, self.shareView.frame.origin.y + self.shareView.frame.size.height + 28 , self.frame.size.width, (221 + kFinoSafeAreaBottom))]; + self.contentView = [[UIView alloc] initWithFrame:CGRectMake(0,self.frame.size.height - (221 + kFinoSafeAreaBottom) , self.frame.size.width, (221 + kFinoSafeAreaBottom))]; self.contentView.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#F0F0F0" darkHexString:@"#1A1A1A"]; [self addSubview:self.contentView]; @@ -119,7 +115,7 @@ returnInsets = inset;\ [self.contentView addSubview:self.cancelButton]; self.cancelButton.frame = CGRectMake(0, self.contentView.frame.size.height - kFinoSafeAreaBottom - 56, self.contentView.frame.size.width, 56 ); [self.cancelButton addTarget:self action:@selector(dismiss) forControlEvents:UIControlEventTouchUpInside]; - + [self.contentView addSubview:self.collectionView]; self.collectionView.frame = CGRectMake(0, 58.5, frame.size.width, 107); @@ -131,7 +127,13 @@ returnInsets = inset;\ maskLayer.frame = self.contentView.bounds; maskLayer.path = maskPath.CGPath; self.contentView.layer.mask = maskLayer; - + + self.shareView.frame = CGRectMake(52.5, self.contentView.frame.origin.y - 400 , 270 , 380); + + UIButton *saveButton = [[UIButton alloc] initWithFrame:CGRectMake(278.5, self.shareView.frame.origin.y + 12, 36, 36)]; + [saveButton addTarget:self action:@selector(saveOnClick) forControlEvents:UIControlEventTouchUpInside]; + [saveButton setImage:[UIImage imageNamed:@"share_download"] forState:UIControlStateNormal]; + [self addSubview:saveButton]; [self p_addNotifications]; } return self; @@ -209,12 +211,21 @@ returnInsets = inset;\ static NSString *cellID = @"cellid"; - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { MOPshareBottomViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath]; -// cell.type = [self.dataArray[indexPath.row] intValue]; - cell.imageView.image = [UIImage imageNamed:self.dataArray[indexPath.row][@"lightImage"]]; + [cell.imageButton setImage:[UIImage imageNamed:self.dataArray[indexPath.row][@"lightImage"]] forState:UIControlStateNormal]; cell.label.text = self.dataArray[indexPath.row][@"title"]; + cell.type = self.dataArray[indexPath.row][@"type"]; + cell.delegate = self; return cell; } +- (void)iconBtnDidClick:(MOPshareBottomViewCell *)cell { + if (self.didSelcetTypeBlock) { + NSString *typeString = cell.type; + self.didSelcetTypeBlock(typeString); + } + [self dismiss]; +} + - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (self.didSelcetTypeBlock) { NSString *typeString = self.dataArray[indexPath.row][@"type"]; @@ -268,14 +279,15 @@ static NSString *cellID = @"cellid"; if (self) { self.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#F0F0F0" darkHexString:@"#1A1A1A"]; - UIView *imageBgView = [[UIView alloc] initWithFrame:CGRectMake(18, 20, 48, 48)]; - imageBgView.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#FFFFFF " darkHexString:@"#2C2C2C"]; - [self.contentView addSubview:imageBgView]; - - self.imageView = [UIImageView new]; - self.imageView.frame = CGRectMake(9, 9, 30, 30); - [imageBgView addSubview:self.imageView]; - + UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(18, 20, 48, 48)]; + button.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#FFFFFF " darkHexString:@"#2C2C2C"]; + [self.contentView addSubview:button]; + button.layer.masksToBounds = YES; + button.layer.cornerRadius = 6; + UIImage *highBgImage = [UIImage fat_imageWithColor:[MOPTools fat_dynamicColorWithLightHexString:@"#D7D7D7 " darkHexString:@"#4A4A4A"]]; + [button setBackgroundImage:highBgImage forState:UIControlStateHighlighted]; + [button addTarget:self action:@selector(iconBtnClick:) forControlEvents:UIControlEventTouchUpInside]; + self.imageButton = button; // self.label = [[UILabel alloc] initWithFrame:CGRectMake((frame.size.width-50)/2, 65, frame.size.width, 30)]; self.label = [[UILabel alloc] initWithFrame:CGRectMake(18, 75, 48, 12)]; self.label.font = [UIFont systemFontOfSize:10]; @@ -287,5 +299,11 @@ static NSString *cellID = @"cellid"; return self; } +- (void)iconBtnClick:(UIButton *)btn { + if (self.delegate && [self.delegate respondsToSelector:@selector(iconBtnDidClick:)]) { + [self.delegate iconBtnDidClick:self]; + } +} + @end diff --git a/ios/mop.podspec b/ios/mop.podspec index b6bbd2a..20f2956 100644 --- a/ios/mop.podspec +++ b/ios/mop.podspec @@ -17,7 +17,7 @@ A finclip miniprogram flutter sdk. s.dependency 'Flutter' s.ios.deployment_target = '9.0' - s.dependency 'FinApplet' , '2.39.2-alpha20230103v04' - s.dependency 'FinAppletExt' , '2.39.2-alpha20230103v04' + s.dependency 'FinApplet' , '2.39.2-alpha20230105v08' + s.dependency 'FinAppletExt' , '2.39.2-alpha20230105v08' end From 39e5a2b52ba7799cba80fd23f5bd62c2d6714bbb Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Thu, 5 Jan 2023 19:08:33 +0800 Subject: [PATCH 06/10] 1.update --- ios/Classes/Utils/MopShareView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Classes/Utils/MopShareView.m b/ios/Classes/Utils/MopShareView.m index 857be23..4f2f042 100644 --- a/ios/Classes/Utils/MopShareView.m +++ b/ios/Classes/Utils/MopShareView.m @@ -67,7 +67,7 @@ returnInsets = inset;\ float bottomY = appletImageView.frame.size.height + appletImageView.frame.origin.y; UIView *line0 = [[UIView alloc] initWithFrame:CGRectMake(0, bottomY, self.shareView.frame.size.width, 0.5)]; - line0.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#E0E0E0" darkHexString:@"#2E2E2E"]; + line0.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#eeeeee" darkHexString:@"#2E2E2E"]; [self.shareView addSubview:line0]; From ad5d698c66020f4de096705e96fb8bc577028ec7 Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Thu, 5 Jan 2023 20:37:02 +0800 Subject: [PATCH 07/10] 1.update --- ios/Classes/MopPlugin.m | 17 +++++----- ios/Classes/Utils/MOPTools.h | 2 +- ios/Classes/Utils/MOPTools.m | 57 ++++++++++++++++++++++++++++++++ ios/Classes/Utils/MopShareView.m | 8 ++--- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/ios/Classes/MopPlugin.m b/ios/Classes/MopPlugin.m index a683d65..0417baf 100644 --- a/ios/Classes/MopPlugin.m +++ b/ios/Classes/MopPlugin.m @@ -94,15 +94,15 @@ static MopPlugin *_instance; result(dict); } else if ([@"showShareAppletDialog" isEqualToString:call.method]) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - UIImage *image = [[FATClient sharedClient] getDefaultCurrentAppletImage:400.0f]; +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + UIImage *image = [MOPTools getCurrentPageImage]; MopShareView *view = [MopShareView viewWithData:call.arguments]; view.image = image; [view show]; [view setDidSelcetTypeBlock:^(NSString *type) { result(type); }]; - }); +// }); } else if ([@"showLoading" isEqualToString:call.method]) { UIViewController *currentVC = [MOPTools topViewController]; @@ -124,14 +124,15 @@ static MopPlugin *_instance; } else if ([@"getScreenshot" isEqualToString:call.method]) { UIViewController *currentVC = [MOPTools topViewController]; - [currentVC.view fatHideToastActivity]; - [currentVC.view fatHideAllToasts]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - UIImage *image = [[FATClient sharedClient] getDefaultCurrentAppletImage:0.0f]; +// [currentVC.view fatHideToastActivity]; +// [currentVC.view fatHideAllToasts]; +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ +// UIImage *image = [[FATClient sharedClient] getDefaultCurrentAppletImage:0.0f]; + UIImage *image = [MOPTools getCurrentPageImage]; NSString *filePtah = [[FATClient sharedClient] saveFile:UIImagePNGRepresentation(image) fileName:[NSString stringWithFormat:@"%@",call.arguments[@"appId"]]]; filePtah = [[FATClient sharedClient] fat_absolutePathWithPath:filePtah]; result(filePtah); - }); +// }); } else if ([@"getPhoneNumberResult" isEqualToString:call.method]) { if ([MOPAppletDelegate instance].bindGetPhoneNumbers) { diff --git a/ios/Classes/Utils/MOPTools.h b/ios/Classes/Utils/MOPTools.h index 64c315a..f9f048a 100644 --- a/ios/Classes/Utils/MOPTools.h +++ b/ios/Classes/Utils/MOPTools.h @@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN /// @param string 二维码的内容 + (UIImage *)makeQRCodeForString:(NSString *)string; - ++ (UIImage *)getCurrentPageImage; @end diff --git a/ios/Classes/Utils/MOPTools.m b/ios/Classes/Utils/MOPTools.m index 5283bc8..a2a9e9a 100644 --- a/ios/Classes/Utils/MOPTools.m +++ b/ios/Classes/Utils/MOPTools.m @@ -206,5 +206,62 @@ } } ++ (UIImage *)getCurrentPageImage { + UIViewController *currentVC = [MOPTools topViewController]; + + UIGraphicsBeginImageContextWithOptions(CGSizeMake(currentVC.view.frame.size.width, 440), NO, [UIScreen mainScreen].scale); + [currentVC.view.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return snapshotImage; +} + +// 截取当前屏幕 ,返回截取到的图片 +//+ (UIImage *)getCurrentPageImage { +// +// +// CGSize imageSize = CGSizeZero; +// +// +// +// +// UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; +// if (UIInterfaceOrientationIsPortrait(orientation)) { +// imageSize = [UIScreen mainScreen].bounds.size; +// } else { +// imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width); +// } +// // 绘制上下文 +// UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); +// CGContextRef context = UIGraphicsGetCurrentContext(); +// for (UIWindow *window in [[UIApplication sharedApplication] windows]) { +// CGContextSaveGState(context); +// CGContextTranslateCTM(context, window.center.x, window.center.y); +// CGContextConcatCTM(context, window.transform); +// CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y); +// if (orientation == UIInterfaceOrientationLandscapeLeft) { +// CGContextRotateCTM(context, M_PI_2); +// CGContextTranslateCTM(context, 0, -imageSize.width); +// } else if (orientation == UIInterfaceOrientationLandscapeRight) { +// CGContextRotateCTM(context, -M_PI_2); +// CGContextTranslateCTM(context, -imageSize.height, 0); +// } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { +// CGContextRotateCTM(context, M_PI); +// CGContextTranslateCTM(context, -imageSize.width, -imageSize.height); +// } +// if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { +// [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; +// } else { +// [window.layer renderInContext:context]; +// } +// CGContextRestoreGState(context); +// } +// UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); +// UIGraphicsEndImageContext(); +// NSData *imageData = UIImagePNGRepresentation(image); +// return [UIImage imageWithData:imageData]; +//} + + @end diff --git a/ios/Classes/Utils/MopShareView.m b/ios/Classes/Utils/MopShareView.m index 4f2f042..bb4b36e 100644 --- a/ios/Classes/Utils/MopShareView.m +++ b/ios/Classes/Utils/MopShareView.m @@ -60,14 +60,14 @@ returnInsets = inset;\ self.shareView.layer.cornerRadius = 6; self.shareView.backgroundColor = UIColor.whiteColor; - UIImageView *appletImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.shareView.frame.size.width, 300)]; - appletImageView.contentMode = UIViewContentModeScaleAspectFit; + UIImageView *appletImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 270, 300)]; + appletImageView.contentMode = UIViewContentModeScaleToFill; self.appletImageView = appletImageView; [self.shareView addSubview:appletImageView]; float bottomY = appletImageView.frame.size.height + appletImageView.frame.origin.y; UIView *line0 = [[UIView alloc] initWithFrame:CGRectMake(0, bottomY, self.shareView.frame.size.width, 0.5)]; - line0.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#eeeeee" darkHexString:@"#2E2E2E"]; + line0.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#eeeeee" darkHexString:@"#eeeeee"]; [self.shareView addSubview:line0]; @@ -79,7 +79,7 @@ returnInsets = inset;\ [self.shareView addSubview:descLabel]; UILabel *detailLabel = [[UILabel alloc] init]; - detailLabel.frame = CGRectMake(14, self.titleLabel.frame.size.height + self.titleLabel.frame.origin.y + 5, 168, 44); + detailLabel.frame = CGRectMake(14, self.titleLabel.frame.size.height + self.titleLabel.frame.origin.y, 168, 44); detailLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:11]; detailLabel.numberOfLines = 0; detailLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#666666" darkHexString:@"#666666"]; From 49ca6becdf73aaed7f8d80c49a9693ab004959dc Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Thu, 5 Jan 2023 20:38:02 +0800 Subject: [PATCH 08/10] 1.update --- ios/Classes/Utils/MopShareView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Classes/Utils/MopShareView.m b/ios/Classes/Utils/MopShareView.m index bb4b36e..e323360 100644 --- a/ios/Classes/Utils/MopShareView.m +++ b/ios/Classes/Utils/MopShareView.m @@ -104,7 +104,7 @@ returnInsets = inset;\ [self.contentView addSubview:titleLabel]; UIView *line1 = [[UIView alloc] initWithFrame:CGRectMake(0, 58 , self.contentView.frame.size.width, 0.5)]; - line1.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#E0E0E0" darkHexString:@"#2E2E2E"]; + line1.backgroundColor = [MOPTools fat_dynamicColorWithLightHexString:@"#E0E0E0" darkHexString:@"#E0E0E0"]; [self.contentView addSubview:line1]; self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; From 3715cea1e6bab831d592a358a1ba86708b39ee8a Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Thu, 5 Jan 2023 21:06:07 +0800 Subject: [PATCH 09/10] 1.update --- ios/Classes/Utils/MopShareView.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ios/Classes/Utils/MopShareView.m b/ios/Classes/Utils/MopShareView.m index e323360..fe55b73 100644 --- a/ios/Classes/Utils/MopShareView.m +++ b/ios/Classes/Utils/MopShareView.m @@ -74,13 +74,15 @@ returnInsets = inset;\ UILabel *descLabel = [[UILabel alloc] init]; descLabel.frame = CGRectMake(14, bottomY + 12, 168, 21); descLabel.font = [UIFont fontWithName:@"PingFangSC-Semibold" size:15]; + descLabel.textAlignment = NSTextAlignmentLeft; descLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#222222" darkHexString:@"#222222"]; self.titleLabel = descLabel; [self.shareView addSubview:descLabel]; UILabel *detailLabel = [[UILabel alloc] init]; - detailLabel.frame = CGRectMake(14, self.titleLabel.frame.size.height + self.titleLabel.frame.origin.y, 168, 44); + detailLabel.frame = CGRectMake(14, self.titleLabel.frame.size.height + self.titleLabel.frame.origin.y - 3, 168, 44); detailLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:11]; + detailLabel.textAlignment = NSTextAlignmentLeft; detailLabel.numberOfLines = 0; detailLabel.textColor = [MOPTools fat_dynamicColorWithLightHexString:@"#666666" darkHexString:@"#666666"]; self.descLabel = detailLabel; @@ -128,6 +130,12 @@ returnInsets = inset;\ maskLayer.path = maskPath.CGPath; self.contentView.layer.mask = maskLayer; + UIBezierPath *appletImageViewMask = [UIBezierPath bezierPathWithRoundedRect:self.appletImageView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(6.0, 6.0)]; + CAShapeLayer *appletImageMaskLayer = [[CAShapeLayer alloc] init]; + appletImageMaskLayer.frame = self.appletImageView.bounds; + appletImageMaskLayer.path = appletImageViewMask.CGPath; + self.appletImageView.layer.mask = appletImageMaskLayer; + self.shareView.frame = CGRectMake(52.5, self.contentView.frame.origin.y - 400 , 270 , 380); UIButton *saveButton = [[UIButton alloc] initWithFrame:CGRectMake(278.5, self.shareView.frame.origin.y + 12, 36, 36)]; From 0b471e511b73dd189b14a76ac21b0666d43dd607 Mon Sep 17 00:00:00 2001 From: wangzhaoyao Date: Fri, 6 Jan 2023 14:39:25 +0800 Subject: [PATCH 10/10] 1.update version --- ios/mop.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/mop.podspec b/ios/mop.podspec index 20f2956..40eacad 100644 --- a/ios/mop.podspec +++ b/ios/mop.podspec @@ -17,7 +17,7 @@ A finclip miniprogram flutter sdk. s.dependency 'Flutter' s.ios.deployment_target = '9.0' - s.dependency 'FinApplet' , '2.39.2-alpha20230105v08' - s.dependency 'FinAppletExt' , '2.39.2-alpha20230105v08' + s.dependency 'FinApplet' , '2.39.2-alpha20230106v02' + s.dependency 'FinAppletExt' , '2.39.2-alpha20230106v02' end