@convep_mobilogy/react-native-qms-plugin 0.10.3 → 0.10.5
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 +373 -2
- package/ios/QmsPlugin/QmsModule.mm +220 -0
- package/ios/QmsPlugin/UIViewController+QmsAnalytics.m +276 -19
- package/ios/QmsPluginFramework.xcframework/Info.plist +5 -5
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Info.plist +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/_CodeSignature/CodeResources +3 -3
- 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/Info.plist +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 +3 -3
- package/lib/module/QmsDashboardView.ios.js +27 -11
- package/lib/module/QmsDashboardView.ios.js.map +1 -1
- package/lib/module/QmsPlugin.js +4 -0
- package/lib/module/QmsPlugin.js.map +1 -1
- package/lib/typescript/src/QmsDashboardView.ios.d.ts.map +1 -1
- package/lib/typescript/src/QmsPlugin.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/QmsDashboardView.ios.tsx +36 -23
- package/src/QmsPlugin.ts +13 -0
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.12.
|
|
78
|
+
implementation "com.convep.qms:qms-plugin:1.12.17"
|
|
79
79
|
|
|
80
80
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
81
81
|
|
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
#import <QmsPluginFramework/QmsPluginFramework.h>
|
|
4
4
|
#import <QmsPluginFramework/QmsPlugin.h>
|
|
5
5
|
|
|
6
|
+
static NSString * const kQmsThemePrimaryColorKey = @"QmsThemePrimaryColor";
|
|
7
|
+
static NSString * const kQmsThemeHeaderTextColorKey = @"QmsThemeHeaderTextColor";
|
|
8
|
+
static NSString * const kQmsThemeAccentColorKey = @"QmsThemeAccentColor";
|
|
9
|
+
static NSString * const kQmsThemeFontFamilyKey = @"QmsThemeFontFamily";
|
|
10
|
+
static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotification";
|
|
11
|
+
|
|
6
12
|
@interface QmsDashboardView : UIView
|
|
7
13
|
@property (nonatomic, strong) UIViewController *dashboardVC;
|
|
8
14
|
@property (nonatomic, assign) BOOL didSetupVC;
|
|
@@ -10,18 +16,51 @@
|
|
|
10
16
|
@property (nonatomic, copy) NSString *ClientID;
|
|
11
17
|
@property (nonatomic, copy) NSString *ClientCode;
|
|
12
18
|
@property (nonatomic, copy) NSString *user_token;
|
|
19
|
+
@property (nonatomic, copy) NSString *themeColor;
|
|
13
20
|
@property (nonatomic, copy) NSString *headerTextColor;
|
|
14
21
|
@property (nonatomic, copy) NSString *headerIconColor;
|
|
15
22
|
@property (nonatomic, copy) NSString *accentColor;
|
|
16
23
|
@property (nonatomic, copy) NSString *fontFamily;
|
|
24
|
+
@property (nonatomic, assign) BOOL isOrigin;
|
|
25
|
+
@property (nonatomic, copy) NSDictionary *payload;
|
|
26
|
+
@property (nonatomic, assign) BOOL didRouteInitialPayload;
|
|
17
27
|
|
|
18
28
|
@property (nonatomic, copy) RCTDirectEventBlock onClose;
|
|
29
|
+
@property (nonatomic, copy) RCTDirectEventBlock onLogout;
|
|
19
30
|
@property (nonatomic, copy) RCTDirectEventBlock onAnalyticsScreen;
|
|
20
31
|
@property (nonatomic, copy) RCTDirectEventBlock onAnalyticsEvent;
|
|
21
32
|
@end
|
|
22
33
|
|
|
23
34
|
@implementation QmsDashboardView
|
|
24
35
|
|
|
36
|
+
- (void)persistThemeDefaults {
|
|
37
|
+
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
38
|
+
if (_themeColor.length > 0) [defaults setObject:_themeColor forKey:kQmsThemePrimaryColorKey];
|
|
39
|
+
else [defaults removeObjectForKey:kQmsThemePrimaryColorKey];
|
|
40
|
+
|
|
41
|
+
if (_headerTextColor.length > 0) [defaults setObject:_headerTextColor forKey:kQmsThemeHeaderTextColorKey];
|
|
42
|
+
else [defaults removeObjectForKey:kQmsThemeHeaderTextColorKey];
|
|
43
|
+
|
|
44
|
+
if (_accentColor.length > 0) [defaults setObject:_accentColor forKey:kQmsThemeAccentColorKey];
|
|
45
|
+
else [defaults removeObjectForKey:kQmsThemeAccentColorKey];
|
|
46
|
+
|
|
47
|
+
if (_fontFamily.length > 0) [defaults setObject:_fontFamily forKey:kQmsThemeFontFamilyKey];
|
|
48
|
+
else [defaults removeObjectForKey:kQmsThemeFontFamilyKey];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
- (void)applyAllThemeImmediatelyIfNeeded {
|
|
52
|
+
if (!_dashboardVC || !_dashboardVC.view) return;
|
|
53
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
54
|
+
[self persistThemeDefaults];
|
|
55
|
+
[self applyThemeColorIfNeeded];
|
|
56
|
+
[self applyHeaderThemeIfNeeded];
|
|
57
|
+
[self applyAccentColorIfNeeded];
|
|
58
|
+
[self applyFontFamilyIfNeeded];
|
|
59
|
+
[_dashboardVC.view setNeedsLayout];
|
|
60
|
+
[_dashboardVC.view layoutIfNeeded];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
25
64
|
- (instancetype)initWithFrame:(CGRect)frame {
|
|
26
65
|
if (self = [super initWithFrame:frame]) {
|
|
27
66
|
_dashboardVC = [QmsPluginUI makeViewController];
|
|
@@ -41,6 +80,14 @@
|
|
|
41
80
|
selector:@selector(handleAnalyticsEvent:)
|
|
42
81
|
name:@"QmsAnalyticsEventNotification"
|
|
43
82
|
object:nil];
|
|
83
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
84
|
+
selector:@selector(handleDashboardLogout:)
|
|
85
|
+
name:@"QmsDashboardDidLogoutNotification"
|
|
86
|
+
object:nil];
|
|
87
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
88
|
+
selector:@selector(handleRoutePayloadNotification:)
|
|
89
|
+
name:kQmsRoutePayloadNotification
|
|
90
|
+
object:nil];
|
|
44
91
|
}
|
|
45
92
|
return self;
|
|
46
93
|
}
|
|
@@ -50,6 +97,7 @@
|
|
|
50
97
|
if (self.window && !_didSetupVC) {
|
|
51
98
|
UIViewController *parentVC = [UIApplication sharedApplication].keyWindow.rootViewController;
|
|
52
99
|
if (parentVC) {
|
|
100
|
+
[self persistThemeDefaults];
|
|
53
101
|
|
|
54
102
|
// 1️⃣ create VC with props
|
|
55
103
|
_dashboardVC = [QmsPluginUI makeViewController];
|
|
@@ -63,6 +111,8 @@
|
|
|
63
111
|
|
|
64
112
|
// 2️⃣ forward props again if needed
|
|
65
113
|
[self forwardPropsToVC];
|
|
114
|
+
[self routePayloadIfNeeded:self.payload force:NO];
|
|
115
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
66
116
|
}
|
|
67
117
|
}
|
|
68
118
|
}
|
|
@@ -89,6 +139,12 @@
|
|
|
89
139
|
}
|
|
90
140
|
}
|
|
91
141
|
|
|
142
|
+
- (void)handleDashboardLogout:(NSNotification *)note {
|
|
143
|
+
if (self.onLogout) {
|
|
144
|
+
self.onLogout(note.userInfo ?: @{});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
92
148
|
- (void)cleanupDashboard {
|
|
93
149
|
if (!_dashboardVC) return;
|
|
94
150
|
|
|
@@ -116,27 +172,51 @@
|
|
|
116
172
|
[self forwardProp:@"user_token" value:_user_token];
|
|
117
173
|
}
|
|
118
174
|
|
|
175
|
+
- (void)setThemeColor:(NSString *)themeColor {
|
|
176
|
+
_themeColor = [themeColor copy];
|
|
177
|
+
[self persistThemeDefaults];
|
|
178
|
+
[self forwardProp:@"themeColor" value:_themeColor];
|
|
179
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
180
|
+
}
|
|
181
|
+
|
|
119
182
|
- (void)setHeaderTextColor:(NSString *)headerTextColor {
|
|
120
183
|
_headerTextColor = [headerTextColor copy];
|
|
184
|
+
[self persistThemeDefaults];
|
|
121
185
|
[self forwardProp:@"headerTextColor" value:_headerTextColor];
|
|
186
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
122
187
|
}
|
|
123
188
|
|
|
124
189
|
- (void)setHeaderIconColor:(NSString *)headerIconColor {
|
|
125
190
|
_headerIconColor = [headerIconColor copy];
|
|
126
191
|
[self forwardProp:@"headerIconColor" value:_headerIconColor];
|
|
192
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
127
193
|
}
|
|
128
194
|
|
|
129
195
|
- (void)setAccentColor:(NSString *)accentColor {
|
|
130
196
|
_accentColor = [accentColor copy];
|
|
197
|
+
[self persistThemeDefaults];
|
|
131
198
|
[self forwardProp:@"accentColor" value:_accentColor];
|
|
199
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
132
200
|
}
|
|
133
201
|
|
|
134
202
|
- (void)setFontFamily:(NSString *)fontFamily {
|
|
135
203
|
_fontFamily = [fontFamily copy];
|
|
204
|
+
[self persistThemeDefaults];
|
|
136
205
|
[self forwardProp:@"fontFamily" value:_fontFamily];
|
|
206
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
- (void)setIsOrigin:(BOOL)isOrigin {
|
|
210
|
+
_isOrigin = isOrigin;
|
|
211
|
+
[self forwardProp:@"isOrigin" value:@(isOrigin)];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
- (void)setPayload:(NSDictionary *)payload {
|
|
215
|
+
_payload = [payload copy];
|
|
216
|
+
[self routePayloadIfNeeded:_payload force:NO];
|
|
137
217
|
}
|
|
138
218
|
#pragma mark - Forward Props via KVC
|
|
139
|
-
- (void)forwardProp:(NSString *)key value:(
|
|
219
|
+
- (void)forwardProp:(NSString *)key value:(id)value {
|
|
140
220
|
if (_dashboardVC && [_dashboardVC respondsToSelector:NSSelectorFromString(key)]) {
|
|
141
221
|
@try {
|
|
142
222
|
[_dashboardVC setValue:value forKey:key];
|
|
@@ -150,10 +230,280 @@
|
|
|
150
230
|
[self forwardProp:@"ClientID" value:_ClientID];
|
|
151
231
|
[self forwardProp:@"ClientCode" value:_ClientCode];
|
|
152
232
|
[self forwardProp:@"user_token" value:_user_token];
|
|
233
|
+
[self forwardProp:@"themeColor" value:_themeColor];
|
|
153
234
|
[self forwardProp:@"headerTextColor" value:_headerTextColor];
|
|
154
235
|
[self forwardProp:@"headerIconColor" value:_headerIconColor];
|
|
155
236
|
[self forwardProp:@"accentColor" value:_accentColor];
|
|
156
237
|
[self forwardProp:@"fontFamily" value:_fontFamily];
|
|
238
|
+
[self forwardProp:@"isOrigin" value:@(_isOrigin)];
|
|
239
|
+
[self applyAllThemeImmediatelyIfNeeded];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
- (NSString *)stringFromPayload:(NSDictionary *)payload key:(NSString *)key {
|
|
243
|
+
id value = payload[key];
|
|
244
|
+
if (!value || value == [NSNull null]) return nil;
|
|
245
|
+
return [value description];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
- (BOOL)isIssueType:(NSString *)type {
|
|
249
|
+
static NSSet<NSString *> *types;
|
|
250
|
+
static dispatch_once_t onceToken;
|
|
251
|
+
dispatch_once(&onceToken, ^{
|
|
252
|
+
types = [NSSet setWithArray:@[
|
|
253
|
+
@"new_issue", @"new_info", @"accept_issue", @"reject_issue", @"decline_issue",
|
|
254
|
+
@"start_fix", @"redo", @"completed", @"close_internal", @"close_external",
|
|
255
|
+
@"pending_owner_acceptance", @"assign_issue", @"reassign_issue", @"poa_reminder",
|
|
256
|
+
@"auto_close_reminder", @"pending_access_reminder", @"overdue_reminder",
|
|
257
|
+
@"issue_summary_reminder", @"lodge_summary_reminder", @"overdue_summary_reminder"
|
|
258
|
+
]];
|
|
259
|
+
});
|
|
260
|
+
return type.length > 0 && [types containsObject:type];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
- (BOOL)isAppointmentType:(NSString *)type {
|
|
264
|
+
return [type isEqualToString:@"appointment_reminder"] ||
|
|
265
|
+
[type isEqualToString:@"unattend_appt_reminder"];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
- (void)applyPayloadContext:(NSDictionary *)payload {
|
|
269
|
+
Class apiConfig = NSClassFromString(@"APIConfig");
|
|
270
|
+
if (!apiConfig) return;
|
|
271
|
+
|
|
272
|
+
NSString *projectId = [self stringFromPayload:payload key:@"project_id"];
|
|
273
|
+
NSString *planId = [self stringFromPayload:payload key:@"plan_id"];
|
|
274
|
+
|
|
275
|
+
if (projectId.length > 0 && [apiConfig respondsToSelector:NSSelectorFromString(@"setProjectId:")]) {
|
|
276
|
+
[apiConfig performSelector:NSSelectorFromString(@"setProjectId:") withObject:projectId];
|
|
277
|
+
}
|
|
278
|
+
if (planId.length > 0 && [apiConfig respondsToSelector:NSSelectorFromString(@"setDrawingPlanId:")]) {
|
|
279
|
+
[apiConfig performSelector:NSSelectorFromString(@"setDrawingPlanId:") withObject:planId];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
- (UINavigationController *)mainNavigationController {
|
|
284
|
+
id mainVC = nil;
|
|
285
|
+
@try {
|
|
286
|
+
mainVC = [self.dashboardVC valueForKey:@"mainViewController"];
|
|
287
|
+
} @catch (__unused NSException *exception) {}
|
|
288
|
+
|
|
289
|
+
if ([mainVC isKindOfClass:[UINavigationController class]]) {
|
|
290
|
+
return (UINavigationController *)mainVC;
|
|
291
|
+
}
|
|
292
|
+
if ([self.dashboardVC isKindOfClass:[UINavigationController class]]) {
|
|
293
|
+
return (UINavigationController *)self.dashboardVC;
|
|
294
|
+
}
|
|
295
|
+
return self.dashboardVC.navigationController;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
- (void)pushViewControllerNamed:(NSString *)className {
|
|
299
|
+
Class cls = NSClassFromString(className);
|
|
300
|
+
if (!cls) return;
|
|
301
|
+
UIViewController *vc = [[cls alloc] init];
|
|
302
|
+
if (!vc) return;
|
|
303
|
+
UINavigationController *nav = [self mainNavigationController];
|
|
304
|
+
if (nav) {
|
|
305
|
+
[nav pushViewController:vc animated:YES];
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
- (void)routePayloadIfNeeded:(NSDictionary *)payload force:(BOOL)force {
|
|
310
|
+
if (![payload isKindOfClass:[NSDictionary class]] || payload.count == 0) return;
|
|
311
|
+
if (!_didSetupVC || !self.dashboardVC) return;
|
|
312
|
+
if (_didRouteInitialPayload && !force) return;
|
|
313
|
+
|
|
314
|
+
_didRouteInitialPayload = YES;
|
|
315
|
+
[self applyPayloadContext:payload];
|
|
316
|
+
|
|
317
|
+
NSString *type = [self stringFromPayload:payload key:@"type"];
|
|
318
|
+
if ([self isIssueType:type]) {
|
|
319
|
+
[self pushViewControllerNamed:@"IssuesViewController"];
|
|
320
|
+
} else if ([self isAppointmentType:type]) {
|
|
321
|
+
[self pushViewControllerNamed:@"AppointmentViewController"];
|
|
322
|
+
} else if ([type isEqualToString:@"clearance_letter"]) {
|
|
323
|
+
[self pushViewControllerNamed:@"GeneralInfoViewController"];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
- (void)handleRoutePayloadNotification:(NSNotification *)note {
|
|
328
|
+
NSDictionary *payload = [note.userInfo isKindOfClass:[NSDictionary class]] ? note.userInfo : nil;
|
|
329
|
+
[self routePayloadIfNeeded:payload force:YES];
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
- (UIColor *)qms_colorFromHexString:(NSString *)hexString {
|
|
333
|
+
if (hexString.length == 0) return nil;
|
|
334
|
+
NSString *value = [[hexString stringByTrimmingCharactersInSet:
|
|
335
|
+
[NSCharacterSet whitespaceAndNewlineCharacterSet]]
|
|
336
|
+
uppercaseString];
|
|
337
|
+
if ([value hasPrefix:@"#"]) value = [value substringFromIndex:1];
|
|
338
|
+
if (value.length == 3) {
|
|
339
|
+
unichar c0 = [value characterAtIndex:0];
|
|
340
|
+
unichar c1 = [value characterAtIndex:1];
|
|
341
|
+
unichar c2 = [value characterAtIndex:2];
|
|
342
|
+
value = [NSString stringWithFormat:@"%C%C%C%C%C%C", c0, c0, c1, c1, c2, c2];
|
|
343
|
+
}
|
|
344
|
+
if (value.length != 6 && value.length != 8) return nil;
|
|
345
|
+
|
|
346
|
+
unsigned int hex = 0;
|
|
347
|
+
[[NSScanner scannerWithString:value] scanHexInt:&hex];
|
|
348
|
+
|
|
349
|
+
CGFloat a = 1.0;
|
|
350
|
+
CGFloat r = 0, g = 0, b = 0;
|
|
351
|
+
if (value.length == 8) {
|
|
352
|
+
a = ((hex >> 24) & 0xFF) / 255.0;
|
|
353
|
+
r = ((hex >> 16) & 0xFF) / 255.0;
|
|
354
|
+
g = ((hex >> 8) & 0xFF) / 255.0;
|
|
355
|
+
b = (hex & 0xFF) / 255.0;
|
|
356
|
+
} else {
|
|
357
|
+
r = ((hex >> 16) & 0xFF) / 255.0;
|
|
358
|
+
g = ((hex >> 8) & 0xFF) / 255.0;
|
|
359
|
+
b = (hex & 0xFF) / 255.0;
|
|
360
|
+
}
|
|
361
|
+
return [UIColor colorWithRed:r green:g blue:b alpha:a];
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
- (void)applyHeaderThemeRecursivelyOnView:(UIView *)view textColor:(UIColor *)textColor iconColor:(UIColor *)iconColor {
|
|
365
|
+
if (!view) return;
|
|
366
|
+
|
|
367
|
+
if (textColor && [view isKindOfClass:[UILabel class]]) {
|
|
368
|
+
UILabel *label = (UILabel *)view;
|
|
369
|
+
CGPoint originInRoot = [label.superview convertPoint:label.frame.origin toView:_dashboardVC.view];
|
|
370
|
+
if (originInRoot.y <= 120) {
|
|
371
|
+
label.textColor = textColor;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (iconColor && [view isKindOfClass:[UIButton class]]) {
|
|
376
|
+
UIButton *button = (UIButton *)view;
|
|
377
|
+
CGPoint originInRoot = [button.superview convertPoint:button.frame.origin toView:_dashboardVC.view];
|
|
378
|
+
if (originInRoot.y <= 120) {
|
|
379
|
+
button.tintColor = iconColor;
|
|
380
|
+
[button setTitleColor:iconColor forState:UIControlStateNormal];
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
for (UIView *subview in view.subviews) {
|
|
385
|
+
[self applyHeaderThemeRecursivelyOnView:subview textColor:textColor iconColor:iconColor];
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
- (void)applyHeaderThemeIfNeeded {
|
|
390
|
+
if (!_dashboardVC || !_dashboardVC.view) return;
|
|
391
|
+
UIColor *text = [self qms_colorFromHexString:_headerTextColor];
|
|
392
|
+
UIColor *icon = [self qms_colorFromHexString:_headerIconColor];
|
|
393
|
+
if (!text && !icon) return;
|
|
394
|
+
[self applyHeaderThemeRecursivelyOnView:_dashboardVC.view textColor:text iconColor:icon];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
- (BOOL)isDefaultQmsBlueColor:(UIColor *)color {
|
|
398
|
+
if (!color) return NO;
|
|
399
|
+
CGFloat r = 0, g = 0, b = 0, a = 0;
|
|
400
|
+
if (![color getRed:&r green:&g blue:&b alpha:&a]) return NO;
|
|
401
|
+
if (a < 0.01) return NO;
|
|
402
|
+
|
|
403
|
+
BOOL closeToBlueA = (fabs(r - 0.0) < 0.12 && fabs(g - 0.50) < 0.16 && fabs(b - 0.60) < 0.16);
|
|
404
|
+
BOOL closeToBlueB = (fabs(r - 0.0) < 0.12 && fabs(g - 0.43) < 0.16 && fabs(b - 0.55) < 0.16);
|
|
405
|
+
return closeToBlueA || closeToBlueB;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
- (void)applyThemeRecursivelyOnView:(UIView *)view color:(UIColor *)themeColor {
|
|
409
|
+
if (!view || !themeColor) return;
|
|
410
|
+
|
|
411
|
+
CGPoint originInRoot = [view.superview convertPoint:view.frame.origin toView:_dashboardVC.view];
|
|
412
|
+
BOOL nearHeader = originInRoot.y <= 140.0 && view.bounds.size.height <= 120.0;
|
|
413
|
+
if (nearHeader && [self isDefaultQmsBlueColor:view.backgroundColor]) {
|
|
414
|
+
view.backgroundColor = themeColor;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if ([view isKindOfClass:[UIButton class]]) {
|
|
418
|
+
UIButton *button = (UIButton *)view;
|
|
419
|
+
if ([self isDefaultQmsBlueColor:button.backgroundColor]) {
|
|
420
|
+
button.backgroundColor = themeColor;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
for (UIView *subview in view.subviews) {
|
|
425
|
+
[self applyThemeRecursivelyOnView:subview color:themeColor];
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
- (void)applyThemeColorIfNeeded {
|
|
430
|
+
if (!_dashboardVC || !_dashboardVC.view) return;
|
|
431
|
+
UIColor *theme = [self qms_colorFromHexString:_themeColor];
|
|
432
|
+
if (!theme) return;
|
|
433
|
+
[self applyThemeRecursivelyOnView:_dashboardVC.view color:theme];
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
- (void)applyAccentRecursivelyOnView:(UIView *)view color:(UIColor *)color {
|
|
437
|
+
if (!view || !color) return;
|
|
438
|
+
|
|
439
|
+
if ([view isKindOfClass:[UIButton class]]) {
|
|
440
|
+
UIButton *button = (UIButton *)view;
|
|
441
|
+
button.tintColor = color;
|
|
442
|
+
} else if ([view isKindOfClass:[UITextField class]]) {
|
|
443
|
+
((UITextField *)view).tintColor = color;
|
|
444
|
+
} else if ([view isKindOfClass:[UITextView class]]) {
|
|
445
|
+
((UITextView *)view).tintColor = color;
|
|
446
|
+
} else if ([view isKindOfClass:[UISwitch class]]) {
|
|
447
|
+
((UISwitch *)view).onTintColor = color;
|
|
448
|
+
} else if ([view isKindOfClass:[UISlider class]]) {
|
|
449
|
+
((UISlider *)view).minimumTrackTintColor = color;
|
|
450
|
+
} else if ([view isKindOfClass:[UIPageControl class]]) {
|
|
451
|
+
((UIPageControl *)view).currentPageIndicatorTintColor = color;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
for (UIView *subview in view.subviews) {
|
|
455
|
+
[self applyAccentRecursivelyOnView:subview color:color];
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
- (void)applyAccentColorIfNeeded {
|
|
460
|
+
if (!_dashboardVC || !_dashboardVC.view) return;
|
|
461
|
+
UIColor *accent = [self qms_colorFromHexString:_accentColor];
|
|
462
|
+
if (!accent) return;
|
|
463
|
+
[self applyAccentRecursivelyOnView:_dashboardVC.view color:accent];
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
- (UIFont *)fontByPreservingStyleFromFont:(UIFont *)sourceFont {
|
|
467
|
+
if (sourceFont == nil || _fontFamily.length == 0) return sourceFont;
|
|
468
|
+
|
|
469
|
+
UIFont *base = [UIFont fontWithName:_fontFamily size:sourceFont.pointSize];
|
|
470
|
+
if (!base) return sourceFont;
|
|
471
|
+
|
|
472
|
+
UIFontDescriptorSymbolicTraits traits = sourceFont.fontDescriptor.symbolicTraits;
|
|
473
|
+
UIFontDescriptor *descriptor = [base.fontDescriptor fontDescriptorWithSymbolicTraits:traits];
|
|
474
|
+
if (descriptor) {
|
|
475
|
+
return [UIFont fontWithDescriptor:descriptor size:sourceFont.pointSize];
|
|
476
|
+
}
|
|
477
|
+
return base;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
- (void)applyFontFamilyRecursivelyOnView:(UIView *)view {
|
|
481
|
+
if (!view) return;
|
|
482
|
+
|
|
483
|
+
if ([view isKindOfClass:[UILabel class]]) {
|
|
484
|
+
UILabel *label = (UILabel *)view;
|
|
485
|
+
label.font = [self fontByPreservingStyleFromFont:label.font];
|
|
486
|
+
} else if ([view isKindOfClass:[UIButton class]]) {
|
|
487
|
+
UIButton *button = (UIButton *)view;
|
|
488
|
+
if (button.titleLabel) {
|
|
489
|
+
button.titleLabel.font = [self fontByPreservingStyleFromFont:button.titleLabel.font];
|
|
490
|
+
}
|
|
491
|
+
} else if ([view isKindOfClass:[UITextField class]]) {
|
|
492
|
+
UITextField *textField = (UITextField *)view;
|
|
493
|
+
textField.font = [self fontByPreservingStyleFromFont:textField.font];
|
|
494
|
+
} else if ([view isKindOfClass:[UITextView class]]) {
|
|
495
|
+
UITextView *textView = (UITextView *)view;
|
|
496
|
+
textView.font = [self fontByPreservingStyleFromFont:textView.font];
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
for (UIView *subview in view.subviews) {
|
|
500
|
+
[self applyFontFamilyRecursivelyOnView:subview];
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
- (void)applyFontFamilyIfNeeded {
|
|
505
|
+
if (_fontFamily.length == 0 || !_dashboardVC || !_dashboardVC.view) return;
|
|
506
|
+
[self applyFontFamilyRecursivelyOnView:_dashboardVC.view];
|
|
157
507
|
}
|
|
158
508
|
|
|
159
509
|
- (void)removeFromSuperview {
|
|
@@ -178,10 +528,14 @@ RCT_EXPORT_MODULE(QmsDashboardView)
|
|
|
178
528
|
RCT_EXPORT_VIEW_PROPERTY(ClientID, NSString)
|
|
179
529
|
RCT_EXPORT_VIEW_PROPERTY(ClientCode, NSString)
|
|
180
530
|
RCT_EXPORT_VIEW_PROPERTY(user_token, NSString)
|
|
531
|
+
RCT_EXPORT_VIEW_PROPERTY(themeColor, NSString)
|
|
181
532
|
RCT_EXPORT_VIEW_PROPERTY(headerTextColor, NSString)
|
|
182
533
|
RCT_EXPORT_VIEW_PROPERTY(headerIconColor, NSString)
|
|
183
534
|
RCT_EXPORT_VIEW_PROPERTY(accentColor, NSString)
|
|
184
535
|
RCT_EXPORT_VIEW_PROPERTY(fontFamily, NSString)
|
|
536
|
+
RCT_EXPORT_VIEW_PROPERTY(isOrigin, BOOL)
|
|
537
|
+
RCT_EXPORT_VIEW_PROPERTY(payload, NSDictionary)
|
|
538
|
+
RCT_EXPORT_VIEW_PROPERTY(onLogout, RCTDirectEventBlock)
|
|
185
539
|
RCT_EXPORT_VIEW_PROPERTY(onAnalyticsScreen, RCTDirectEventBlock)
|
|
186
540
|
RCT_EXPORT_VIEW_PROPERTY(onAnalyticsEvent, RCTDirectEventBlock)
|
|
187
541
|
|
|
@@ -221,12 +575,23 @@ RCT_EXPORT_MODULE();
|
|
|
221
575
|
selector:@selector(handleAnalyticsEvent:)
|
|
222
576
|
name:@"QmsAnalyticsEventNotification"
|
|
223
577
|
object:nil];
|
|
578
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
579
|
+
selector:@selector(handleDashboardLogout:)
|
|
580
|
+
name:@"QmsDashboardDidLogoutNotification"
|
|
581
|
+
object:nil];
|
|
224
582
|
}
|
|
225
583
|
return self;
|
|
226
584
|
}
|
|
227
585
|
|
|
228
586
|
- (NSArray<NSString *> *)supportedEvents {
|
|
229
|
-
return @[
|
|
587
|
+
return @[
|
|
588
|
+
@"onClose",
|
|
589
|
+
@"onLogout",
|
|
590
|
+
@"onAnalyticsScreen",
|
|
591
|
+
@"onAnalyticsEvent",
|
|
592
|
+
@"QmsSdkOnAnalyticsScreen",
|
|
593
|
+
@"QmsSdkOnAnalyticsEvent"
|
|
594
|
+
];
|
|
230
595
|
}
|
|
231
596
|
|
|
232
597
|
- (void)handleDashboardClose:(NSNotification *)note {
|
|
@@ -236,10 +601,16 @@ RCT_EXPORT_MODULE();
|
|
|
236
601
|
|
|
237
602
|
- (void)handleAnalyticsScreen:(NSNotification *)note {
|
|
238
603
|
[self sendEventWithName:@"onAnalyticsScreen" body:note.userInfo];
|
|
604
|
+
[self sendEventWithName:@"QmsSdkOnAnalyticsScreen" body:note.userInfo];
|
|
239
605
|
}
|
|
240
606
|
|
|
241
607
|
- (void)handleAnalyticsEvent:(NSNotification *)note {
|
|
242
608
|
[self sendEventWithName:@"onAnalyticsEvent" body:note.userInfo];
|
|
609
|
+
[self sendEventWithName:@"QmsSdkOnAnalyticsEvent" body:note.userInfo];
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
- (void)handleDashboardLogout:(NSNotification *)note {
|
|
613
|
+
[self sendEventWithName:@"onLogout" body:note.userInfo];
|
|
243
614
|
}
|
|
244
615
|
|
|
245
616
|
- (void)dealloc {
|