@convep_mobilogy/react-native-qms-plugin 0.10.5 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -1
- package/ios/QmsPlugin/QmsDashboardViewManager.mm +64 -1
- package/ios/QmsPlugin/QmsModule.mm +19 -2
- package/ios/QmsPlugin/QmsThemeRuntime.h +22 -0
- package/ios/QmsPlugin/QmsThemeRuntime.m +39 -0
- package/ios/QmsPlugin/UIViewController+QmsAnalytics.m +148 -7
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Bold.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Medium.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Regular.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/_CodeSignature/CodeResources +68 -2
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/bm.json +780 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/cn.json +781 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/en.json +781 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Assets.car +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Bold.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Medium.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Regular.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/QmsPluginFramework +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/_CodeSignature/CodeResources +68 -2
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/bm.json +780 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/cn.json +781 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/en.json +781 -0
- package/lib/module/QmsDashboardView.android.js +16 -16
- package/lib/module/QmsDashboardView.android.js.map +1 -1
- package/lib/module/QmsDashboardView.ios.js +12 -2
- package/lib/module/QmsDashboardView.ios.js.map +1 -1
- package/lib/typescript/src/QmsDashboardView.ios.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/QmsDashboardView.android.tsx +16 -16
- package/src/QmsDashboardView.ios.tsx +28 -2
package/android/build.gradle
CHANGED
|
@@ -75,7 +75,7 @@ dependencies {
|
|
|
75
75
|
implementation "com.facebook.react:react-android"
|
|
76
76
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
77
77
|
implementation 'com.facebook.react:react-native:+'
|
|
78
|
-
implementation "com.convep.qms:qms-plugin:1.
|
|
78
|
+
implementation "com.convep.qms:qms-plugin:1.14.0"
|
|
79
79
|
|
|
80
80
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
81
81
|
|
|
@@ -241,6 +241,9 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
241
241
|
|
|
242
242
|
- (NSString *)stringFromPayload:(NSDictionary *)payload key:(NSString *)key {
|
|
243
243
|
id value = payload[key];
|
|
244
|
+
if ((!value || value == [NSNull null]) && [payload[@"data"] isKindOfClass:[NSDictionary class]]) {
|
|
245
|
+
value = payload[@"data"][key];
|
|
246
|
+
}
|
|
244
247
|
if (!value || value == [NSNull null]) return nil;
|
|
245
248
|
return [value description];
|
|
246
249
|
}
|
|
@@ -306,6 +309,23 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
306
309
|
}
|
|
307
310
|
}
|
|
308
311
|
|
|
312
|
+
- (void)pushIssuesViewControllerWithPayload:(NSDictionary *)payload {
|
|
313
|
+
Class cls = NSClassFromString(@"IssuesViewController");
|
|
314
|
+
if (!cls) return;
|
|
315
|
+
UIViewController *vc = [[cls alloc] init];
|
|
316
|
+
if (!vc) return;
|
|
317
|
+
NSString *issueId = [self stringFromPayload:payload key:@"issue_id"];
|
|
318
|
+
if (issueId.length > 0 && [vc respondsToSelector:NSSelectorFromString(@"setDeepLinkIssueId:")]) {
|
|
319
|
+
@try {
|
|
320
|
+
[vc setValue:issueId forKey:@"deepLinkIssueId"];
|
|
321
|
+
} @catch (__unused NSException *exception) {}
|
|
322
|
+
}
|
|
323
|
+
UINavigationController *nav = [self mainNavigationController];
|
|
324
|
+
if (nav) {
|
|
325
|
+
[nav pushViewController:vc animated:YES];
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
309
329
|
- (void)routePayloadIfNeeded:(NSDictionary *)payload force:(BOOL)force {
|
|
310
330
|
if (![payload isKindOfClass:[NSDictionary class]] || payload.count == 0) return;
|
|
311
331
|
if (!_didSetupVC || !self.dashboardVC) return;
|
|
@@ -315,12 +335,27 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
315
335
|
[self applyPayloadContext:payload];
|
|
316
336
|
|
|
317
337
|
NSString *type = [self stringFromPayload:payload key:@"type"];
|
|
338
|
+
NSLog(@"🧭 routePayloadIfNeeded type=%@ issue_id=%@ plan_id=%@ project_id=%@",
|
|
339
|
+
type ?: @"", [self stringFromPayload:payload key:@"issue_id"] ?: @"",
|
|
340
|
+
[self stringFromPayload:payload key:@"plan_id"] ?: @"",
|
|
341
|
+
[self stringFromPayload:payload key:@"project_id"] ?: @"");
|
|
318
342
|
if ([self isIssueType:type]) {
|
|
319
|
-
[self
|
|
343
|
+
NSString *issueId = [self stringFromPayload:payload key:@"issue_id"];
|
|
344
|
+
if (issueId.length > 0) {
|
|
345
|
+
NSLog(@"🧭 routing issue deep link to IssuesViewController issue_id=%@", issueId);
|
|
346
|
+
[self pushIssuesViewControllerWithPayload:payload];
|
|
347
|
+
} else {
|
|
348
|
+
NSLog(@"🧭 routing issue type without issue_id to IssuesViewController");
|
|
349
|
+
[self pushViewControllerNamed:@"IssuesViewController"];
|
|
350
|
+
}
|
|
320
351
|
} else if ([self isAppointmentType:type]) {
|
|
352
|
+
NSLog(@"🧭 routing appointment type to AppointmentViewController");
|
|
321
353
|
[self pushViewControllerNamed:@"AppointmentViewController"];
|
|
322
354
|
} else if ([type isEqualToString:@"clearance_letter"]) {
|
|
355
|
+
NSLog(@"🧭 routing clearance_letter to GeneralInfoViewController");
|
|
323
356
|
[self pushViewControllerNamed:@"GeneralInfoViewController"];
|
|
357
|
+
} else {
|
|
358
|
+
NSLog(@"🧭 no route matched for type=%@", type ?: @"");
|
|
324
359
|
}
|
|
325
360
|
}
|
|
326
361
|
|
|
@@ -426,11 +461,39 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
426
461
|
}
|
|
427
462
|
}
|
|
428
463
|
|
|
464
|
+
- (void)applyDashboardHeaderOverlayTintRecursivelyOnView:(UIView *)view color:(UIColor *)themeColor {
|
|
465
|
+
if (!view || !themeColor || !_dashboardVC || !_dashboardVC.view) return;
|
|
466
|
+
|
|
467
|
+
if ([view isKindOfClass:[UIImageView class]]) {
|
|
468
|
+
UIImageView *imageView = (UIImageView *)view;
|
|
469
|
+
CGPoint originInRoot = [imageView.superview convertPoint:imageView.frame.origin toView:_dashboardVC.view];
|
|
470
|
+
CGFloat rootWidth = CGRectGetWidth(_dashboardVC.view.bounds);
|
|
471
|
+
BOOL isHeaderBand = originInRoot.y <= 220.0 &&
|
|
472
|
+
CGRectGetHeight(imageView.bounds) >= 56.0 &&
|
|
473
|
+
CGRectGetHeight(imageView.bounds) <= 120.0 &&
|
|
474
|
+
CGRectGetWidth(imageView.bounds) >= (rootWidth * 0.75) &&
|
|
475
|
+
imageView.contentMode == UIViewContentModeScaleToFill &&
|
|
476
|
+
!imageView.userInteractionEnabled;
|
|
477
|
+
if (isHeaderBand && imageView.image) {
|
|
478
|
+
UIImage *templated = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
|
479
|
+
if (templated != imageView.image) {
|
|
480
|
+
imageView.image = templated;
|
|
481
|
+
}
|
|
482
|
+
imageView.tintColor = themeColor;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
for (UIView *subview in view.subviews) {
|
|
487
|
+
[self applyDashboardHeaderOverlayTintRecursivelyOnView:subview color:themeColor];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
429
491
|
- (void)applyThemeColorIfNeeded {
|
|
430
492
|
if (!_dashboardVC || !_dashboardVC.view) return;
|
|
431
493
|
UIColor *theme = [self qms_colorFromHexString:_themeColor];
|
|
432
494
|
if (!theme) return;
|
|
433
495
|
[self applyThemeRecursivelyOnView:_dashboardVC.view color:theme];
|
|
496
|
+
[self applyDashboardHeaderOverlayTintRecursivelyOnView:_dashboardVC.view color:theme];
|
|
434
497
|
}
|
|
435
498
|
|
|
436
499
|
- (void)applyAccentRecursivelyOnView:(UIView *)view color:(UIColor *)color {
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
#import <UIKit/UIKit.h>
|
|
4
4
|
#import <objc/runtime.h>
|
|
5
5
|
#import <QmsPluginFramework/QmsPlugin.h>
|
|
6
|
+
#import "QmsThemeRuntime.h"
|
|
6
7
|
|
|
7
8
|
static NSString * const kQmsThemePrimaryColorKey = @"QmsThemePrimaryColor";
|
|
8
9
|
static NSString * const kQmsThemeHeaderTextColorKey = @"QmsThemeHeaderTextColor";
|
|
10
|
+
static NSString * const kQmsThemeHeaderIconColorKey = @"QmsThemeHeaderIconColor";
|
|
9
11
|
static NSString * const kQmsThemeAccentColorKey = @"QmsThemeAccentColor";
|
|
10
12
|
static NSString * const kQmsThemeFontFamilyKey = @"QmsThemeFontFamily";
|
|
11
13
|
static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotification";
|
|
@@ -105,30 +107,45 @@ RCT_EXPORT_METHOD(setPrimaryColor:(NSString *)hexColor) {
|
|
|
105
107
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
106
108
|
if (hexColor.length > 0) [defaults setObject:hexColor forKey:kQmsThemePrimaryColorKey];
|
|
107
109
|
else [defaults removeObjectForKey:kQmsThemePrimaryColorKey];
|
|
110
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
111
|
+
runtime.primaryColorHex = (hexColor.length > 0 ? hexColor : nil);
|
|
112
|
+
[runtime notifyThemeChanged];
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
RCT_EXPORT_METHOD(setHeaderTextColor:(NSString *)hexColor) {
|
|
111
116
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
112
117
|
if (hexColor.length > 0) [defaults setObject:hexColor forKey:kQmsThemeHeaderTextColorKey];
|
|
113
118
|
else [defaults removeObjectForKey:kQmsThemeHeaderTextColorKey];
|
|
119
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
120
|
+
runtime.headerTextColorHex = (hexColor.length > 0 ? hexColor : nil);
|
|
121
|
+
[runtime notifyThemeChanged];
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
RCT_EXPORT_METHOD(setHeaderIconColor:(NSString *)hexColor) {
|
|
117
125
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
118
|
-
if (hexColor.length > 0) [defaults setObject:hexColor forKey:
|
|
119
|
-
else [defaults removeObjectForKey:
|
|
126
|
+
if (hexColor.length > 0) [defaults setObject:hexColor forKey:kQmsThemeHeaderIconColorKey];
|
|
127
|
+
else [defaults removeObjectForKey:kQmsThemeHeaderIconColorKey];
|
|
128
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
129
|
+
runtime.headerIconColorHex = (hexColor.length > 0 ? hexColor : nil);
|
|
130
|
+
[runtime notifyThemeChanged];
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
RCT_EXPORT_METHOD(setAccentColor:(NSString *)hexColor) {
|
|
123
134
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
124
135
|
if (hexColor.length > 0) [defaults setObject:hexColor forKey:kQmsThemeAccentColorKey];
|
|
125
136
|
else [defaults removeObjectForKey:kQmsThemeAccentColorKey];
|
|
137
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
138
|
+
runtime.accentColorHex = (hexColor.length > 0 ? hexColor : nil);
|
|
139
|
+
[runtime notifyThemeChanged];
|
|
126
140
|
}
|
|
127
141
|
|
|
128
142
|
RCT_EXPORT_METHOD(setFontFamily:(NSString *)fontFamily) {
|
|
129
143
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
130
144
|
if (fontFamily.length > 0) [defaults setObject:fontFamily forKey:kQmsThemeFontFamilyKey];
|
|
131
145
|
else [defaults removeObjectForKey:kQmsThemeFontFamilyKey];
|
|
146
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
147
|
+
runtime.fontFamily = (fontFamily.length > 0 ? fontFamily : nil);
|
|
148
|
+
[runtime notifyThemeChanged];
|
|
132
149
|
}
|
|
133
150
|
|
|
134
151
|
RCT_EXPORT_METHOD(emitInAppNotification:(NSString *)title body:(NSString *)body) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
extern NSString * const QmsThemeDidChangeNotification;
|
|
6
|
+
|
|
7
|
+
@interface QmsThemeRuntime : NSObject
|
|
8
|
+
|
|
9
|
+
+ (instancetype)shared;
|
|
10
|
+
|
|
11
|
+
@property (nonatomic, copy, nullable) NSString *primaryColorHex;
|
|
12
|
+
@property (nonatomic, copy, nullable) NSString *headerTextColorHex;
|
|
13
|
+
@property (nonatomic, copy, nullable) NSString *headerIconColorHex;
|
|
14
|
+
@property (nonatomic, copy, nullable) NSString *accentColorHex;
|
|
15
|
+
@property (nonatomic, copy, nullable) NSString *fontFamily;
|
|
16
|
+
|
|
17
|
+
- (void)reloadFromDefaults;
|
|
18
|
+
- (void)notifyThemeChanged;
|
|
19
|
+
|
|
20
|
+
@end
|
|
21
|
+
|
|
22
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#import "QmsThemeRuntime.h"
|
|
2
|
+
|
|
3
|
+
static NSString * const kQmsThemePrimaryColorKey = @"QmsThemePrimaryColor";
|
|
4
|
+
static NSString * const kQmsThemeHeaderTextColorKey = @"QmsThemeHeaderTextColor";
|
|
5
|
+
static NSString * const kQmsThemeHeaderIconColorKey = @"QmsThemeHeaderIconColor";
|
|
6
|
+
static NSString * const kQmsThemeAccentColorKey = @"QmsThemeAccentColor";
|
|
7
|
+
static NSString * const kQmsThemeFontFamilyKey = @"QmsThemeFontFamily";
|
|
8
|
+
|
|
9
|
+
NSString * const QmsThemeDidChangeNotification = @"QmsThemeDidChangeNotification";
|
|
10
|
+
|
|
11
|
+
@implementation QmsThemeRuntime
|
|
12
|
+
|
|
13
|
+
+ (instancetype)shared {
|
|
14
|
+
static QmsThemeRuntime *instance = nil;
|
|
15
|
+
static dispatch_once_t onceToken;
|
|
16
|
+
dispatch_once(&onceToken, ^{
|
|
17
|
+
instance = [[QmsThemeRuntime alloc] init];
|
|
18
|
+
[instance reloadFromDefaults];
|
|
19
|
+
});
|
|
20
|
+
return instance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (void)reloadFromDefaults {
|
|
24
|
+
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
25
|
+
self.primaryColorHex = [defaults stringForKey:kQmsThemePrimaryColorKey];
|
|
26
|
+
self.headerTextColorHex = [defaults stringForKey:kQmsThemeHeaderTextColorKey];
|
|
27
|
+
self.headerIconColorHex = [defaults stringForKey:kQmsThemeHeaderIconColorKey];
|
|
28
|
+
self.accentColorHex = [defaults stringForKey:kQmsThemeAccentColorKey];
|
|
29
|
+
self.fontFamily = [defaults stringForKey:kQmsThemeFontFamilyKey];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
- (void)notifyThemeChanged {
|
|
33
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
34
|
+
[[NSNotificationCenter defaultCenter] postNotificationName:QmsThemeDidChangeNotification
|
|
35
|
+
object:nil];
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import <Foundation/Foundation.h>
|
|
2
2
|
#import <UIKit/UIKit.h>
|
|
3
3
|
#import <objc/runtime.h>
|
|
4
|
+
#import "QmsThemeRuntime.h"
|
|
4
5
|
|
|
5
6
|
static NSString * const QmsAnalyticsScreenNotification = @"QmsAnalyticsScreenNotification";
|
|
6
7
|
static NSString * const QmsAnalyticsEventNotification = @"QmsAnalyticsEventNotification";
|
|
@@ -9,6 +10,8 @@ static NSString * const QmsThemeHeaderTextColorKey = @"QmsThemeHeaderTextColor";
|
|
|
9
10
|
static NSString * const QmsThemeAccentColorKey = @"QmsThemeAccentColor";
|
|
10
11
|
static NSString * const QmsThemeFontFamilyKey = @"QmsThemeFontFamily";
|
|
11
12
|
static char QmsStatusBarFillViewKey;
|
|
13
|
+
static char QmsThemeObserverAttachedKey;
|
|
14
|
+
static char QmsThemeGuardTokenKey;
|
|
12
15
|
|
|
13
16
|
static void qms_swizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizzledSelector) {
|
|
14
17
|
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
|
@@ -36,16 +39,28 @@ static void qms_swizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizz
|
|
|
36
39
|
static dispatch_once_t onceToken;
|
|
37
40
|
dispatch_once(&onceToken, ^{
|
|
38
41
|
Class class = [self class];
|
|
42
|
+
qms_swizzleInstanceMethod(class, @selector(viewDidLoad), @selector(qms_viewDidLoad));
|
|
39
43
|
qms_swizzleInstanceMethod(class, @selector(viewWillAppear:), @selector(qms_viewWillAppear:));
|
|
40
44
|
qms_swizzleInstanceMethod(class, @selector(viewDidAppear:), @selector(qms_viewDidAppear:));
|
|
41
45
|
qms_swizzleInstanceMethod(class, @selector(viewDidLayoutSubviews), @selector(qms_viewDidLayoutSubviews));
|
|
42
46
|
});
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
- (void)qms_viewDidLoad {
|
|
50
|
+
[self qms_viewDidLoad];
|
|
51
|
+
if (![self qms_shouldApplyTheme]) return;
|
|
52
|
+
[self qms_registerThemeObserverIfNeeded];
|
|
53
|
+
[self qms_applyThemeIfNeeded];
|
|
54
|
+
[self qms_startThemeGuardWindow];
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
- (void)qms_viewWillAppear:(BOOL)animated {
|
|
46
58
|
[self qms_viewWillAppear:animated];
|
|
47
|
-
if (![self
|
|
59
|
+
if (![self qms_shouldApplyTheme]) return;
|
|
60
|
+
[self qms_registerThemeObserverIfNeeded];
|
|
48
61
|
[self qms_applyThemeIfNeeded];
|
|
62
|
+
[self qms_scheduleThemeReapplyPasses];
|
|
63
|
+
[self qms_startThemeGuardWindow];
|
|
49
64
|
}
|
|
50
65
|
|
|
51
66
|
- (void)qms_viewDidAppear:(BOOL)animated {
|
|
@@ -56,6 +71,8 @@ static void qms_swizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizz
|
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
[self qms_applyThemeIfNeeded];
|
|
74
|
+
[self qms_scheduleThemeReapplyPasses];
|
|
75
|
+
[self qms_startThemeGuardWindow];
|
|
59
76
|
|
|
60
77
|
NSString *screenName = NSStringFromClass([self class]);
|
|
61
78
|
NSString *screenClass = screenName;
|
|
@@ -81,9 +98,82 @@ static void qms_swizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizz
|
|
|
81
98
|
userInfo:eventInfo];
|
|
82
99
|
}
|
|
83
100
|
|
|
101
|
+
- (void)qms_registerThemeObserverIfNeeded {
|
|
102
|
+
NSNumber *attached = objc_getAssociatedObject(self, &QmsThemeObserverAttachedKey);
|
|
103
|
+
if (attached.boolValue) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
107
|
+
selector:@selector(qms_handleThemeDidChange:)
|
|
108
|
+
name:QmsThemeDidChangeNotification
|
|
109
|
+
object:nil];
|
|
110
|
+
objc_setAssociatedObject(self, &QmsThemeObserverAttachedKey, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
- (void)qms_handleThemeDidChange:(NSNotification *)note {
|
|
114
|
+
if (![self qms_shouldApplyTheme]) return;
|
|
115
|
+
if (!self.isViewLoaded) return;
|
|
116
|
+
[self qms_applyThemeIfNeeded];
|
|
117
|
+
[self qms_scheduleThemeReapplyPasses];
|
|
118
|
+
[self qms_startThemeGuardWindow];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
- (void)qms_scheduleThemeReapplyPasses {
|
|
122
|
+
__weak typeof(self) weakSelf = self;
|
|
123
|
+
NSArray<NSNumber *> *delays = @[@0.02, @0.12, @0.30, @0.55, @1.0, @1.35];
|
|
124
|
+
for (NSNumber *delay in delays) {
|
|
125
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay.doubleValue * NSEC_PER_SEC)),
|
|
126
|
+
dispatch_get_main_queue(), ^{
|
|
127
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
128
|
+
if (!strongSelf || !strongSelf.isViewLoaded) return;
|
|
129
|
+
if (![strongSelf qms_shouldApplyTheme]) return;
|
|
130
|
+
[strongSelf qms_applyThemeIfNeeded];
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
- (void)qms_startThemeGuardWindow {
|
|
136
|
+
NSNumber *currentToken = objc_getAssociatedObject(self, &QmsThemeGuardTokenKey);
|
|
137
|
+
NSInteger nextToken = currentToken.integerValue + 1;
|
|
138
|
+
objc_setAssociatedObject(self, &QmsThemeGuardTokenKey, @(nextToken), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
139
|
+
[self qms_runThemeGuardTickWithToken:nextToken elapsed:0.0];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
- (void)qms_runThemeGuardTickWithToken:(NSInteger)token elapsed:(NSTimeInterval)elapsed {
|
|
143
|
+
NSNumber *activeToken = objc_getAssociatedObject(self, &QmsThemeGuardTokenKey);
|
|
144
|
+
if (activeToken.integerValue != token) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (![self qms_shouldApplyTheme]) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (!self.isViewLoaded) {
|
|
151
|
+
NSTimeInterval retryElapsed = elapsed + 0.05;
|
|
152
|
+
if (retryElapsed > 2.2) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)),
|
|
156
|
+
dispatch_get_main_queue(), ^{
|
|
157
|
+
[self qms_runThemeGuardTickWithToken:token elapsed:retryElapsed];
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
[self qms_applyThemeIfNeeded];
|
|
163
|
+
|
|
164
|
+
NSTimeInterval nextElapsed = elapsed + 0.05;
|
|
165
|
+
if (nextElapsed > 2.2) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)),
|
|
169
|
+
dispatch_get_main_queue(), ^{
|
|
170
|
+
[self qms_runThemeGuardTickWithToken:token elapsed:nextElapsed];
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
84
174
|
- (void)qms_viewDidLayoutSubviews {
|
|
85
175
|
[self qms_viewDidLayoutSubviews];
|
|
86
|
-
if (![self
|
|
176
|
+
if (![self qms_shouldApplyTheme]) return;
|
|
87
177
|
[self qms_applyThemeIfNeeded];
|
|
88
178
|
}
|
|
89
179
|
|
|
@@ -199,11 +289,18 @@ static void qms_swizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizz
|
|
|
199
289
|
}
|
|
200
290
|
|
|
201
291
|
- (void)qms_applyThemeIfNeeded {
|
|
202
|
-
|
|
203
|
-
UIColor *themeColor = [self qms_colorFromHexString:
|
|
204
|
-
UIColor *headerTextColor = [self qms_colorFromHexString:
|
|
205
|
-
UIColor *accentColor = [self qms_colorFromHexString:
|
|
206
|
-
NSString *fontFamily =
|
|
292
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
293
|
+
UIColor *themeColor = [self qms_colorFromHexString:runtime.primaryColorHex];
|
|
294
|
+
UIColor *headerTextColor = [self qms_colorFromHexString:runtime.headerTextColorHex];
|
|
295
|
+
UIColor *accentColor = [self qms_colorFromHexString:runtime.accentColorHex];
|
|
296
|
+
NSString *fontFamily = runtime.fontFamily;
|
|
297
|
+
if (!themeColor && !headerTextColor && !accentColor && fontFamily.length == 0) {
|
|
298
|
+
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
299
|
+
themeColor = [self qms_colorFromHexString:[defaults stringForKey:QmsThemePrimaryColorKey]];
|
|
300
|
+
headerTextColor = [self qms_colorFromHexString:[defaults stringForKey:QmsThemeHeaderTextColorKey]];
|
|
301
|
+
accentColor = [self qms_colorFromHexString:[defaults stringForKey:QmsThemeAccentColorKey]];
|
|
302
|
+
fontFamily = [defaults stringForKey:QmsThemeFontFamilyKey];
|
|
303
|
+
}
|
|
207
304
|
if (themeColor) {
|
|
208
305
|
[self qms_applyPrimaryRecursively:self.view themeColor:themeColor];
|
|
209
306
|
[self qms_applyForegroundRecursively:self.view
|
|
@@ -335,4 +432,48 @@ static void qms_swizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizz
|
|
|
335
432
|
return NO;
|
|
336
433
|
}
|
|
337
434
|
|
|
435
|
+
- (BOOL)qms_themeIsConfigured {
|
|
436
|
+
QmsThemeRuntime *runtime = [QmsThemeRuntime shared];
|
|
437
|
+
return runtime.primaryColorHex.length > 0 ||
|
|
438
|
+
runtime.headerTextColorHex.length > 0 ||
|
|
439
|
+
runtime.accentColorHex.length > 0 ||
|
|
440
|
+
runtime.fontFamily.length > 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
- (BOOL)qms_isKnownSdkControllerClassName:(NSString *)className {
|
|
444
|
+
static NSSet<NSString *> *knownClasses;
|
|
445
|
+
static dispatch_once_t onceToken;
|
|
446
|
+
dispatch_once(&onceToken, ^{
|
|
447
|
+
knownClasses = [NSSet setWithArray:@[
|
|
448
|
+
@"DashboardViewController",
|
|
449
|
+
@"UnitViewController",
|
|
450
|
+
@"GeneralInfoViewController",
|
|
451
|
+
@"ProfileViewController",
|
|
452
|
+
@"AppointmentViewController",
|
|
453
|
+
@"AppointmentDetailsViewController",
|
|
454
|
+
@"AppointmentConfirmationViewController",
|
|
455
|
+
@"AppointmentTutorialViewController",
|
|
456
|
+
@"IssuesViewController",
|
|
457
|
+
@"IssueDetailViewController",
|
|
458
|
+
@"AccessItemViewController",
|
|
459
|
+
@"AccessTransactionViewController",
|
|
460
|
+
@"SyncScreenViewController",
|
|
461
|
+
@"FormsListViewController",
|
|
462
|
+
@"AnnouncementViewController",
|
|
463
|
+
@"NotificationViewController"
|
|
464
|
+
]];
|
|
465
|
+
});
|
|
466
|
+
return [knownClasses containsObject:className];
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
- (BOOL)qms_shouldApplyTheme {
|
|
470
|
+
if (![self qms_themeIsConfigured]) {
|
|
471
|
+
return NO;
|
|
472
|
+
}
|
|
473
|
+
if ([self qms_shouldTrackAnalytics]) {
|
|
474
|
+
return YES;
|
|
475
|
+
}
|
|
476
|
+
return [self qms_isKnownSdkControllerClassName:NSStringFromClass([self class])];
|
|
477
|
+
}
|
|
478
|
+
|
|
338
479
|
@end
|
package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework
CHANGED
|
Binary file
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<dict>
|
|
7
7
|
<key>Assets.car</key>
|
|
8
8
|
<data>
|
|
9
|
-
|
|
9
|
+
kEpAubglJYNFlRT4LSRI2MmXQlg=
|
|
10
10
|
</data>
|
|
11
11
|
<key>Headers/QmsPlugin.h</key>
|
|
12
12
|
<data>
|
|
@@ -24,6 +24,30 @@
|
|
|
24
24
|
<data>
|
|
25
25
|
BD9YnWBkeFmDcuOl4cAjALd/7yw=
|
|
26
26
|
</data>
|
|
27
|
+
<key>Montserrat-Bold.ttf</key>
|
|
28
|
+
<data>
|
|
29
|
+
vnwUOAcKtjfhFxaRXk5QkDcm3Mg=
|
|
30
|
+
</data>
|
|
31
|
+
<key>Montserrat-Medium.ttf</key>
|
|
32
|
+
<data>
|
|
33
|
+
d/NVNBXYWMZTuupFqsqyAZZ3YzQ=
|
|
34
|
+
</data>
|
|
35
|
+
<key>Montserrat-Regular.ttf</key>
|
|
36
|
+
<data>
|
|
37
|
+
7BPvHyyZ+HgNby6z+fJ++J8wFhs=
|
|
38
|
+
</data>
|
|
39
|
+
<key>bm.json</key>
|
|
40
|
+
<data>
|
|
41
|
+
PWeiaoATJ5Tmok3tqZ2zbqPpvY0=
|
|
42
|
+
</data>
|
|
43
|
+
<key>cn.json</key>
|
|
44
|
+
<data>
|
|
45
|
+
IeWp7CtgjE4S1AXI2avoC5pUwMA=
|
|
46
|
+
</data>
|
|
47
|
+
<key>en.json</key>
|
|
48
|
+
<data>
|
|
49
|
+
X7Dm5XAAyo7V/dbykrhTjHVVkn4=
|
|
50
|
+
</data>
|
|
27
51
|
</dict>
|
|
28
52
|
<key>files2</key>
|
|
29
53
|
<dict>
|
|
@@ -31,7 +55,7 @@
|
|
|
31
55
|
<dict>
|
|
32
56
|
<key>hash2</key>
|
|
33
57
|
<data>
|
|
34
|
-
|
|
58
|
+
0sUdnIkwFavEcnM4vnqYtEL76ynKxgMhnZSeTzEv99c=
|
|
35
59
|
</data>
|
|
36
60
|
</dict>
|
|
37
61
|
<key>Headers/QmsPlugin.h</key>
|
|
@@ -55,6 +79,48 @@
|
|
|
55
79
|
e+P6RtiuicqWfZ3H2B43r960DPkFwUWqXKWU+w7OVD0=
|
|
56
80
|
</data>
|
|
57
81
|
</dict>
|
|
82
|
+
<key>Montserrat-Bold.ttf</key>
|
|
83
|
+
<dict>
|
|
84
|
+
<key>hash2</key>
|
|
85
|
+
<data>
|
|
86
|
+
f6k9fapcL4gaZycinCEXgt5rdgCPvWNGs9dmTo/IP0M=
|
|
87
|
+
</data>
|
|
88
|
+
</dict>
|
|
89
|
+
<key>Montserrat-Medium.ttf</key>
|
|
90
|
+
<dict>
|
|
91
|
+
<key>hash2</key>
|
|
92
|
+
<data>
|
|
93
|
+
zRYcujo83PaK1yGSD80WTIfnt8yea61RAnjD+jeNkdI=
|
|
94
|
+
</data>
|
|
95
|
+
</dict>
|
|
96
|
+
<key>Montserrat-Regular.ttf</key>
|
|
97
|
+
<dict>
|
|
98
|
+
<key>hash2</key>
|
|
99
|
+
<data>
|
|
100
|
+
75z5nwF1vvUwuIk0vZBPz1b3c87G/U37jMr3ziu9OV4=
|
|
101
|
+
</data>
|
|
102
|
+
</dict>
|
|
103
|
+
<key>bm.json</key>
|
|
104
|
+
<dict>
|
|
105
|
+
<key>hash2</key>
|
|
106
|
+
<data>
|
|
107
|
+
66O9IXhz9EzcdoULJI0EQ2d+TxbKeqB/ojI1dKuPF5M=
|
|
108
|
+
</data>
|
|
109
|
+
</dict>
|
|
110
|
+
<key>cn.json</key>
|
|
111
|
+
<dict>
|
|
112
|
+
<key>hash2</key>
|
|
113
|
+
<data>
|
|
114
|
+
iBpiD/sGrHsIjhadlFeetj9OBEd+QOCIlXDBBibjEw4=
|
|
115
|
+
</data>
|
|
116
|
+
</dict>
|
|
117
|
+
<key>en.json</key>
|
|
118
|
+
<dict>
|
|
119
|
+
<key>hash2</key>
|
|
120
|
+
<data>
|
|
121
|
+
S+vrXUroDoLwz8Wj8IbMLzSfNPdBglOGEIJmJos1nrg=
|
|
122
|
+
</data>
|
|
123
|
+
</dict>
|
|
58
124
|
</dict>
|
|
59
125
|
<key>rules</key>
|
|
60
126
|
<dict>
|