@convep_mobilogy/react-native-qms-plugin 1.7.0 → 1.8.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 +95 -53
- package/ios/QmsPlugin/QmsModule.mm +24 -1
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Headers/QmsPlugin.h +30 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-BoldItalic.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-ExtraBold.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-ExtraLight.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Italic.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Light.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-SemiBold.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Thin.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/_CodeSignature/CodeResources +83 -6
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/en.json +4 -4
- 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/Headers/QmsPlugin.h +30 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-BoldItalic.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-ExtraBold.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-ExtraLight.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Italic.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Light.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-SemiBold.ttf +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Thin.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 +83 -6
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/en.json +4 -4
- package/package.json +1 -1
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.25.0"
|
|
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
|
+
// Forward declaration — QmsModule is defined in QmsModule.mm (same plugin target).
|
|
7
|
+
// We only need the class-method signature here; no header required.
|
|
8
|
+
@interface QmsModule : NSObject
|
|
9
|
+
+ (nullable NSDictionary *)drainPendingLocalNotificationPayload;
|
|
10
|
+
@end
|
|
11
|
+
|
|
6
12
|
static NSString * const kQmsThemePrimaryColorKey = @"QmsThemePrimaryColor";
|
|
7
13
|
static NSString * const kQmsThemeHeaderTextColorKey = @"QmsThemeHeaderTextColor";
|
|
8
14
|
static NSString * const kQmsThemeAccentColorKey = @"QmsThemeAccentColor";
|
|
@@ -120,6 +126,18 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
120
126
|
[self forwardPropsToVC];
|
|
121
127
|
[self routePayloadIfNeeded:self.payload force:NO];
|
|
122
128
|
[self applyAllThemeImmediatelyIfNeeded];
|
|
129
|
+
|
|
130
|
+
// 3️⃣ Drain any pending local-notification payload (cold-launch tap).
|
|
131
|
+
// AppDelegate stores draft_reminder payloads in NSUserDefaults before
|
|
132
|
+
// this view exists; we pick them up here and route them exactly like
|
|
133
|
+
// any other payload — after a short delay so the VC hierarchy settles.
|
|
134
|
+
NSDictionary *pendingLocalPayload = [QmsModule drainPendingLocalNotificationPayload];
|
|
135
|
+
if (pendingLocalPayload) {
|
|
136
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)),
|
|
137
|
+
dispatch_get_main_queue(), ^{
|
|
138
|
+
[self routePayloadIfNeeded:pendingLocalPayload force:YES];
|
|
139
|
+
});
|
|
140
|
+
}
|
|
123
141
|
}
|
|
124
142
|
}
|
|
125
143
|
}
|
|
@@ -293,6 +311,10 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
293
311
|
[type isEqualToString:@"unattend_appt_reminder"];
|
|
294
312
|
}
|
|
295
313
|
|
|
314
|
+
- (BOOL)isDraftReminderType:(NSString *)type {
|
|
315
|
+
return [type isEqualToString:@"draft_reminder"];
|
|
316
|
+
}
|
|
317
|
+
|
|
296
318
|
- (void)applyPayloadContext:(NSDictionary *)payload {
|
|
297
319
|
Class apiConfig = NSClassFromString(@"APIConfig");
|
|
298
320
|
if (!apiConfig) return;
|
|
@@ -380,90 +402,110 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
380
402
|
}
|
|
381
403
|
|
|
382
404
|
- (void)presentIssueDetailViewControllerWithPayload:(NSDictionary *)payload title:(NSString *)title {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (!cls) return;
|
|
388
|
-
UIViewController *vc = [[cls alloc] init];
|
|
389
|
-
if (!vc) return;
|
|
390
|
-
[self applyProjectContext:vc payload:payload title:title];
|
|
391
|
-
NSString *issueId = [self stringFromPayload:payload key:@"issue_id"];
|
|
392
|
-
if (issueId.length > 0) {
|
|
393
|
-
@try { [vc setValue:issueId forKey:@"deepLinkIssueId"]; }
|
|
394
|
-
@catch (__unused NSException *e) {}
|
|
395
|
-
}
|
|
396
|
-
[self presentDeepLinkVC:vc];
|
|
405
|
+
UIViewController *presenter = self.dashboardVC;
|
|
406
|
+
if (!presenter) return;
|
|
407
|
+
[QmsPluginUI presentIssueFromPayload:payload fromViewController:presenter];
|
|
397
408
|
}
|
|
398
409
|
|
|
399
410
|
- (void)presentAppointmentDetailsViewControllerWithPayload:(NSDictionary *)payload title:(NSString *)title {
|
|
400
|
-
//
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if (!
|
|
404
|
-
|
|
405
|
-
if (!vc) return;
|
|
406
|
-
[self applyProjectContext:vc payload:payload title:title];
|
|
407
|
-
|
|
408
|
-
// Pass the appointment ID so the VC can fetch its own data.
|
|
409
|
-
// The deep-link payload carries "appointment_id" (or "id" as a fallback).
|
|
410
|
-
NSString *appointmentIdStr = [self stringFromPayload:payload key:@"appointment_id"]
|
|
411
|
-
?: [self stringFromPayload:payload key:@"id"];
|
|
412
|
-
if (appointmentIdStr.length > 0) {
|
|
413
|
-
NSNumber *appointmentId = @([appointmentIdStr integerValue]);
|
|
414
|
-
@try { [vc setValue:appointmentId forKey:@"appointmentId"]; }
|
|
415
|
-
@catch (__unused NSException *e) {}
|
|
416
|
-
}
|
|
417
|
-
[self presentDeepLinkVC:vc];
|
|
411
|
+
// Delegates to QmsPluginUI which primes APIConfig (project_id / plan_id) before
|
|
412
|
+
// presenting AppointmentDetailsViewController — same pattern as the dashboard deep-link.
|
|
413
|
+
UIViewController *presenter = self.dashboardVC;
|
|
414
|
+
if (!presenter) return;
|
|
415
|
+
[QmsPluginUI presentAppointmentFromPayload:payload fromViewController:presenter];
|
|
418
416
|
}
|
|
419
417
|
|
|
420
418
|
- (void)presentDashboardViewControllerWithPayload:(NSDictionary *)payload title:(NSString *)title {
|
|
421
|
-
|
|
422
|
-
|
|
419
|
+
// Fetch the project list, find the matching project + unit by project_id/plan_id,
|
|
420
|
+
// and present a fully-configured DashboardViewController — same as the normal
|
|
421
|
+
// ProjectViewController → UnitViewController → DashboardViewController flow.
|
|
422
|
+
// The loading overlay and modal presentation are managed inside the framework method.
|
|
423
|
+
UIViewController *presenter = self.dashboardVC;
|
|
424
|
+
if (!presenter) return;
|
|
425
|
+
[QmsPluginUI presentDashboardFromPayload:payload fromViewController:presenter];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
- (void)presentDraftListingViewControllerWithPayload:(NSDictionary *)payload {
|
|
429
|
+
UIViewController *presenter = self.dashboardVC;
|
|
430
|
+
if (!presenter) return;
|
|
431
|
+
|
|
432
|
+
Class cls = NSClassFromString(@"DraftListingViewController");
|
|
433
|
+
if (!cls) {
|
|
434
|
+
NSLog(@"🧭 [DraftReminder] DraftListingViewController class not found");
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
423
438
|
UIViewController *vc = [[cls alloc] init];
|
|
424
439
|
if (!vc) return;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
440
|
+
|
|
441
|
+
// Pass project name if available so the listing filters to the right project
|
|
442
|
+
NSString *projectName = payload[@"project_name"];
|
|
443
|
+
if (projectName.length > 0) {
|
|
444
|
+
@try { [vc setValue:projectName forKey:@"projectName"]; }
|
|
445
|
+
@catch (__unused NSException *e) {}
|
|
446
|
+
}
|
|
447
|
+
|
|
432
448
|
[self presentDeepLinkVC:vc];
|
|
433
449
|
}
|
|
434
450
|
|
|
435
451
|
- (void)routePayloadIfNeeded:(NSDictionary *)payload force:(BOOL)force {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
452
|
+
NSLog(@"🧭 [QmsDashboardView] routePayloadIfNeeded — force=%d payload.count=%lu _didSetupVC=%d _didRouteInitialPayload=%d",
|
|
453
|
+
force, (unsigned long)payload.count, _didSetupVC, _didRouteInitialPayload);
|
|
454
|
+
|
|
455
|
+
if (![payload isKindOfClass:[NSDictionary class]] || payload.count == 0) {
|
|
456
|
+
NSLog(@"⚠️ [QmsDashboardView] routePayloadIfNeeded: payload invalid/empty — bailing");
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
if (!_didSetupVC || !self.dashboardVC) {
|
|
460
|
+
NSLog(@"⚠️ [QmsDashboardView] routePayloadIfNeeded: VC not ready yet (_didSetupVC=%d dashboardVC=%@) — bailing",
|
|
461
|
+
_didSetupVC, self.dashboardVC ? @"exists" : @"nil");
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (_didRouteInitialPayload && !force) {
|
|
465
|
+
NSLog(@"⚠️ [QmsDashboardView] routePayloadIfNeeded: already routed and force=NO — bailing");
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
439
468
|
|
|
440
469
|
_didRouteInitialPayload = YES;
|
|
441
470
|
[self applyPayloadContext:payload];
|
|
442
471
|
|
|
443
472
|
NSString *type = [self stringFromPayload:payload key:@"type"];
|
|
444
473
|
NSString *title = [self stringFromPayload:payload key:@"title"];
|
|
445
|
-
NSLog(@"🧭 routePayloadIfNeeded type=%@ project_id=%@ plan_id=%@ title=%@",
|
|
446
|
-
type ?: @"",
|
|
447
|
-
[self stringFromPayload:payload key:@"project_id"] ?: @"",
|
|
448
|
-
[self stringFromPayload:payload key:@"plan_id"] ?: @"",
|
|
449
|
-
|
|
474
|
+
NSLog(@"🧭 [QmsDashboardView] routePayloadIfNeeded — type=%@ project_id=%@ plan_id=%@ issue_id=%@ appointment_id=%@ title=%@",
|
|
475
|
+
type ?: @"(none)",
|
|
476
|
+
[self stringFromPayload:payload key:@"project_id"] ?: @"(none)",
|
|
477
|
+
[self stringFromPayload:payload key:@"plan_id"] ?: @"(none)",
|
|
478
|
+
[self stringFromPayload:payload key:@"issue_id"] ?: @"(none)",
|
|
479
|
+
[self stringFromPayload:payload key:@"appointment_id"] ?: @"(none)",
|
|
480
|
+
title ?: @"(none)");
|
|
450
481
|
|
|
451
482
|
if ([self isIssueType:type]) {
|
|
452
|
-
NSLog(@"🧭 routing issue type
|
|
483
|
+
NSLog(@"🧭 [QmsDashboardView] routing → presentIssueFromPayload (issue type: %@)", type);
|
|
453
484
|
[self presentIssueDetailViewControllerWithPayload:payload title:title ?: @""];
|
|
454
485
|
} else if ([self isAppointmentType:type]) {
|
|
455
|
-
NSLog(@"🧭 routing appointment type
|
|
486
|
+
NSLog(@"🧭 [QmsDashboardView] routing → presentAppointmentFromPayload (appointment type: %@)", type);
|
|
456
487
|
[self presentAppointmentDetailsViewControllerWithPayload:payload title:title ?: @""];
|
|
457
488
|
} else if ([type isEqualToString:@"clearance_letter"]) {
|
|
458
|
-
NSLog(@"🧭 routing
|
|
489
|
+
NSLog(@"🧭 [QmsDashboardView] routing → presentDashboardFromPayload (clearance_letter)");
|
|
490
|
+
[self presentDashboardViewControllerWithPayload:payload title:title ?: @""];
|
|
491
|
+
} else if ([self isDraftReminderType:type]) {
|
|
492
|
+
NSLog(@"🧭 [QmsDashboardView] routing → presentDraftListingViewController (draft_reminder)");
|
|
493
|
+
// [self presentDraftListingViewControllerWithPayload:payload];
|
|
459
494
|
[self presentDashboardViewControllerWithPayload:payload title:title ?: @""];
|
|
460
495
|
} else {
|
|
461
|
-
NSLog(@"🧭 no route matched for type=%@", type ?: @"");
|
|
496
|
+
NSLog(@"🧭 [QmsDashboardView] routePayloadIfNeeded — no route matched for type=%@", type ?: @"(none)");
|
|
462
497
|
}
|
|
463
498
|
}
|
|
464
499
|
|
|
465
500
|
- (void)handleRoutePayloadNotification:(NSNotification *)note {
|
|
501
|
+
NSLog(@"📬 [QmsDashboardView] handleRoutePayloadNotification received — userInfo class=%@", NSStringFromClass([note.userInfo class]));
|
|
466
502
|
NSDictionary *payload = [note.userInfo isKindOfClass:[NSDictionary class]] ? note.userInfo : nil;
|
|
503
|
+
if (!payload) {
|
|
504
|
+
NSLog(@"⚠️ [QmsDashboardView] handleRoutePayloadNotification: userInfo is not a dict, dropping");
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
NSLog(@"📬 [QmsDashboardView] handleRoutePayloadNotification — _didSetupVC=%d dashboardVC=%@",
|
|
508
|
+
_didSetupVC, _dashboardVC ? @"exists" : @"nil");
|
|
467
509
|
[self routePayloadIfNeeded:payload force:YES];
|
|
468
510
|
}
|
|
469
511
|
|
|
@@ -11,6 +11,7 @@ static NSString * const kQmsThemeHeaderIconColorKey = @"QmsThemeHeaderIconColor"
|
|
|
11
11
|
static NSString * const kQmsThemeAccentColorKey = @"QmsThemeAccentColor";
|
|
12
12
|
static NSString * const kQmsThemeFontFamilyKey = @"QmsThemeFontFamily";
|
|
13
13
|
static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotification";
|
|
14
|
+
static NSString * const kQmsPendingLocalNotifKey = @"QmsPendingLocalNotificationPayload";
|
|
14
15
|
|
|
15
16
|
@interface QmsModule : NSObject <RCTBridgeModule>
|
|
16
17
|
@property (nonatomic, strong) UIView *bannerView;
|
|
@@ -20,6 +21,17 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
20
21
|
|
|
21
22
|
RCT_EXPORT_MODULE(QmsModule)
|
|
22
23
|
|
|
24
|
+
/// Drain the pending local-notification payload written by AppDelegate on cold-launch tap.
|
|
25
|
+
/// Returns nil (and removes the stored value) if nothing is pending.
|
|
26
|
+
+ (nullable NSDictionary *)drainPendingLocalNotificationPayload {
|
|
27
|
+
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
|
28
|
+
id stored = [ud objectForKey:kQmsPendingLocalNotifKey];
|
|
29
|
+
if (![stored isKindOfClass:[NSDictionary class]]) return nil;
|
|
30
|
+
[ud removeObjectForKey:kQmsPendingLocalNotifKey];
|
|
31
|
+
NSLog(@"📬 [QmsModule] Drained pending local notification payload: %@", stored);
|
|
32
|
+
return (NSDictionary *)stored;
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
- (dispatch_queue_t)methodQueue {
|
|
24
36
|
return dispatch_get_main_queue();
|
|
25
37
|
}
|
|
@@ -60,7 +72,18 @@ RCT_EXPORT_MODULE(QmsModule)
|
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
- (void)routePayload:(NSDictionary *)payload {
|
|
63
|
-
|
|
75
|
+
NSLog(@"📨 [QmsModule] routePayload called — payload class=%@", NSStringFromClass([payload class]));
|
|
76
|
+
if (![payload isKindOfClass:[NSDictionary class]] || payload.count == 0) {
|
|
77
|
+
NSLog(@"⚠️ [QmsModule] routePayload: invalid or empty payload, aborting");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
NSLog(@"📨 [QmsModule] routePayload posting QmsRoutePayloadNotification — type=%@ project_id=%@ plan_id=%@ issue_id=%@ appointment_id=%@",
|
|
81
|
+
payload[@"type"] ?: payload[@"data"][@"type"] ?: @"(none)",
|
|
82
|
+
payload[@"project_id"] ?: payload[@"data"][@"project_id"] ?: @"(none)",
|
|
83
|
+
payload[@"plan_id"] ?: payload[@"data"][@"plan_id"] ?: @"(none)",
|
|
84
|
+
payload[@"issue_id"] ?: payload[@"data"][@"issue_id"] ?: @"(none)",
|
|
85
|
+
payload[@"appointment_id"] ?: payload[@"data"][@"appointment_id"] ?: @"(none)");
|
|
86
|
+
NSLog(@"📨 [QmsModule] full payload: %@", payload);
|
|
64
87
|
[[NSNotificationCenter defaultCenter] postNotificationName:kQmsRoutePayloadNotification
|
|
65
88
|
object:nil
|
|
66
89
|
userInfo:payload];
|
package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car
CHANGED
|
Binary file
|
|
@@ -8,6 +8,36 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
8
8
|
|
|
9
9
|
+ (UIViewController *)makeViewController;
|
|
10
10
|
|
|
11
|
+
/// Fetches project list data and presents DashboardViewController fully configured
|
|
12
|
+
/// for the given FCM deep-link payload. The payload must contain at minimum
|
|
13
|
+
/// `project_id` and `plan_id`. Auth/base-URL must already be configured in APIConfig
|
|
14
|
+
/// (i.e. the SDK has already been initialised by the user opening the app).
|
|
15
|
+
///
|
|
16
|
+
/// @param payload The FCM notification data dictionary.
|
|
17
|
+
/// @param presenter The view controller from which the dashboard will be presented modally.
|
|
18
|
+
+ (void)presentDashboardFromPayload:(NSDictionary *)payload
|
|
19
|
+
fromViewController:(UIViewController *)presenter;
|
|
20
|
+
|
|
21
|
+
/// Configures APIConfig with the project/plan context from the payload, then
|
|
22
|
+
/// presents AppointmentDetailsViewController modally. The payload must contain
|
|
23
|
+
/// `project_id`, `plan_id`, and `appointment_id` (or `id` as a fallback).
|
|
24
|
+
/// Auth/base-URL must already be configured in APIConfig.
|
|
25
|
+
///
|
|
26
|
+
/// @param payload The FCM notification data dictionary.
|
|
27
|
+
/// @param presenter The view controller from which the appointment screen will be presented.
|
|
28
|
+
+ (void)presentAppointmentFromPayload:(NSDictionary *)payload
|
|
29
|
+
fromViewController:(UIViewController *)presenter;
|
|
30
|
+
|
|
31
|
+
/// Fetches the issue list, finds the matching issue by `issue_id` from the payload,
|
|
32
|
+
/// and presents IssueDetailViewController fully configured. The payload must contain
|
|
33
|
+
/// at minimum `project_id`, `plan_id`, and `issue_id`. Auth/base-URL must already
|
|
34
|
+
/// be configured in APIConfig.
|
|
35
|
+
///
|
|
36
|
+
/// @param payload The FCM notification data dictionary.
|
|
37
|
+
/// @param presenter The view controller from which the issue screen will be presented.
|
|
38
|
+
+ (void)presentIssueFromPayload:(NSDictionary *)payload
|
|
39
|
+
fromViewController:(UIViewController *)presenter;
|
|
40
|
+
|
|
11
41
|
@end
|
|
12
42
|
|
|
13
43
|
NS_ASSUME_NONNULL_END
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework
CHANGED
|
Binary file
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
<dict>
|
|
7
7
|
<key>Assets.car</key>
|
|
8
8
|
<data>
|
|
9
|
-
|
|
9
|
+
TWfalcvk3qO6mG21qB5bdrcMBjM=
|
|
10
10
|
</data>
|
|
11
11
|
<key>Headers/QmsPlugin.h</key>
|
|
12
12
|
<data>
|
|
13
|
-
|
|
13
|
+
/jmzwY1kiBwDfgZJ8i6EPSgavTU=
|
|
14
14
|
</data>
|
|
15
15
|
<key>Headers/QmsPluginFramework.h</key>
|
|
16
16
|
<data>
|
|
@@ -28,6 +28,26 @@
|
|
|
28
28
|
<data>
|
|
29
29
|
vnwUOAcKtjfhFxaRXk5QkDcm3Mg=
|
|
30
30
|
</data>
|
|
31
|
+
<key>Montserrat-BoldItalic.ttf</key>
|
|
32
|
+
<data>
|
|
33
|
+
zTeJrlXMcCd2r90v0aga4Wxp+/Q=
|
|
34
|
+
</data>
|
|
35
|
+
<key>Montserrat-ExtraBold.ttf</key>
|
|
36
|
+
<data>
|
|
37
|
+
hPFnduIJnTtX2O0jm3bm+jKEsuc=
|
|
38
|
+
</data>
|
|
39
|
+
<key>Montserrat-ExtraLight.ttf</key>
|
|
40
|
+
<data>
|
|
41
|
+
zHokqGLxd5vbv3immEu5rpMkoSg=
|
|
42
|
+
</data>
|
|
43
|
+
<key>Montserrat-Italic.ttf</key>
|
|
44
|
+
<data>
|
|
45
|
+
rvTmoa8YSWRM4ek0tKuQWekW2Ic=
|
|
46
|
+
</data>
|
|
47
|
+
<key>Montserrat-Light.ttf</key>
|
|
48
|
+
<data>
|
|
49
|
+
M5fNmOUTZcielc0RMOAUG9pQUd4=
|
|
50
|
+
</data>
|
|
31
51
|
<key>Montserrat-Medium.ttf</key>
|
|
32
52
|
<data>
|
|
33
53
|
d/NVNBXYWMZTuupFqsqyAZZ3YzQ=
|
|
@@ -36,6 +56,14 @@
|
|
|
36
56
|
<data>
|
|
37
57
|
7BPvHyyZ+HgNby6z+fJ++J8wFhs=
|
|
38
58
|
</data>
|
|
59
|
+
<key>Montserrat-SemiBold.ttf</key>
|
|
60
|
+
<data>
|
|
61
|
+
efdGFtaLh9bPiXmP5yJZA2MmVno=
|
|
62
|
+
</data>
|
|
63
|
+
<key>Montserrat-Thin.ttf</key>
|
|
64
|
+
<data>
|
|
65
|
+
VQ5uHZkjael+nwCqca5IKmpjJtc=
|
|
66
|
+
</data>
|
|
39
67
|
<key>bm.json</key>
|
|
40
68
|
<data>
|
|
41
69
|
J8m1xUyQbIm7FjEl6dgNTLhSBVU=
|
|
@@ -46,7 +74,7 @@
|
|
|
46
74
|
</data>
|
|
47
75
|
<key>en.json</key>
|
|
48
76
|
<data>
|
|
49
|
-
|
|
77
|
+
VeWo6AyHrREEY0vQ5PaYJwdMY1g=
|
|
50
78
|
</data>
|
|
51
79
|
</dict>
|
|
52
80
|
<key>files2</key>
|
|
@@ -55,14 +83,14 @@
|
|
|
55
83
|
<dict>
|
|
56
84
|
<key>hash2</key>
|
|
57
85
|
<data>
|
|
58
|
-
|
|
86
|
+
6l4RTp5ZrLIp0kzkUpLOxcL0TNvCePYwUcTD/aPlyG4=
|
|
59
87
|
</data>
|
|
60
88
|
</dict>
|
|
61
89
|
<key>Headers/QmsPlugin.h</key>
|
|
62
90
|
<dict>
|
|
63
91
|
<key>hash2</key>
|
|
64
92
|
<data>
|
|
65
|
-
|
|
93
|
+
5YE/tWhfpg+TSsnziCLpEp2m4bzkKkH4oKHM990abTc=
|
|
66
94
|
</data>
|
|
67
95
|
</dict>
|
|
68
96
|
<key>Headers/QmsPluginFramework.h</key>
|
|
@@ -86,6 +114,41 @@
|
|
|
86
114
|
f6k9fapcL4gaZycinCEXgt5rdgCPvWNGs9dmTo/IP0M=
|
|
87
115
|
</data>
|
|
88
116
|
</dict>
|
|
117
|
+
<key>Montserrat-BoldItalic.ttf</key>
|
|
118
|
+
<dict>
|
|
119
|
+
<key>hash2</key>
|
|
120
|
+
<data>
|
|
121
|
+
ABpZsPLFQQgAM7g8pt+szgMJXZnKo1lINfUbfG2c51g=
|
|
122
|
+
</data>
|
|
123
|
+
</dict>
|
|
124
|
+
<key>Montserrat-ExtraBold.ttf</key>
|
|
125
|
+
<dict>
|
|
126
|
+
<key>hash2</key>
|
|
127
|
+
<data>
|
|
128
|
+
XPCiMTPMzjX54RW427+QQ0IBgnvCRl0S+dkbvwLPlGY=
|
|
129
|
+
</data>
|
|
130
|
+
</dict>
|
|
131
|
+
<key>Montserrat-ExtraLight.ttf</key>
|
|
132
|
+
<dict>
|
|
133
|
+
<key>hash2</key>
|
|
134
|
+
<data>
|
|
135
|
+
GsDgBpJUjjFCENEGGd5lYiVFf9RcebVtJCzfc5z3J48=
|
|
136
|
+
</data>
|
|
137
|
+
</dict>
|
|
138
|
+
<key>Montserrat-Italic.ttf</key>
|
|
139
|
+
<dict>
|
|
140
|
+
<key>hash2</key>
|
|
141
|
+
<data>
|
|
142
|
+
fofA+Ws5+7kZswrviZEyPQsldknzkeZFa88DwjFEj0k=
|
|
143
|
+
</data>
|
|
144
|
+
</dict>
|
|
145
|
+
<key>Montserrat-Light.ttf</key>
|
|
146
|
+
<dict>
|
|
147
|
+
<key>hash2</key>
|
|
148
|
+
<data>
|
|
149
|
+
lj13LJxEs8QBslfWk60mAG/HvVQhWVfVE1a0DjY1P4Q=
|
|
150
|
+
</data>
|
|
151
|
+
</dict>
|
|
89
152
|
<key>Montserrat-Medium.ttf</key>
|
|
90
153
|
<dict>
|
|
91
154
|
<key>hash2</key>
|
|
@@ -100,6 +163,20 @@
|
|
|
100
163
|
75z5nwF1vvUwuIk0vZBPz1b3c87G/U37jMr3ziu9OV4=
|
|
101
164
|
</data>
|
|
102
165
|
</dict>
|
|
166
|
+
<key>Montserrat-SemiBold.ttf</key>
|
|
167
|
+
<dict>
|
|
168
|
+
<key>hash2</key>
|
|
169
|
+
<data>
|
|
170
|
+
nE2zgUh1QQ59ZP3I5pZ2w7hJaLsVvzrOizlExZ+8VrY=
|
|
171
|
+
</data>
|
|
172
|
+
</dict>
|
|
173
|
+
<key>Montserrat-Thin.ttf</key>
|
|
174
|
+
<dict>
|
|
175
|
+
<key>hash2</key>
|
|
176
|
+
<data>
|
|
177
|
+
qMAnFkOz0iN+EeE+5ZACTUmzW3dgFJWOYP5hV8P1I/o=
|
|
178
|
+
</data>
|
|
179
|
+
</dict>
|
|
103
180
|
<key>bm.json</key>
|
|
104
181
|
<dict>
|
|
105
182
|
<key>hash2</key>
|
|
@@ -118,7 +195,7 @@
|
|
|
118
195
|
<dict>
|
|
119
196
|
<key>hash2</key>
|
|
120
197
|
<data>
|
|
121
|
-
|
|
198
|
+
1loRLBPvXhMxef8cbl/CEpfB0j0axeW+shU+jSRHK8w=
|
|
122
199
|
</data>
|
|
123
200
|
</dict>
|
|
124
201
|
</dict>
|
|
@@ -524,11 +524,11 @@
|
|
|
524
524
|
"SIGN_UP_SUBTITLE": "Please enter required details to continue.",
|
|
525
525
|
"APPOINTMENT_FOR_UNIT": "Appointment for unit",
|
|
526
526
|
"STEP_1": "Step 1/3",
|
|
527
|
-
"STEP_1_TITLE": "Select your preferred date",
|
|
527
|
+
"STEP_1_TITLE": "Select your preferred date.",
|
|
528
528
|
"STEP_2": " Step 2/3",
|
|
529
|
-
"STEP_2_TITLE": "Select your preferred time",
|
|
529
|
+
"STEP_2_TITLE": "Select your preferred time.",
|
|
530
530
|
"STEP_3": "Step 3/3",
|
|
531
|
-
"STEP_3_TITLE": "Confirm your appointment",
|
|
531
|
+
"STEP_3_TITLE": "Confirm your appointment.",
|
|
532
532
|
"OWNER_SIGN_UP": "Owner Sign Up",
|
|
533
533
|
"NO_RECORD_FOUND": "No Record Found",
|
|
534
534
|
"ASK_CS": "Would you like our Customer Support Team to contact you",
|
|
@@ -724,7 +724,7 @@
|
|
|
724
724
|
"ISSUES_SELECTED": "Issue(s) selected",
|
|
725
725
|
"ENTER_REMARKS_HERE": "Enter remarks here...",
|
|
726
726
|
"WITHDRAWING": "Withdrawing",
|
|
727
|
-
"WITHDRAW_ALERT_MESSAGE": "Confirm to withdraw issue?",
|
|
727
|
+
"WITHDRAW_ALERT_MESSAGE": "Confirm to withdraw this issue?",
|
|
728
728
|
"WITHDRAW_ISSUES_SUCCESS_LABEL": "You have succesfully withdrawn",
|
|
729
729
|
"FILTER_ISSUE_LIST": "Filter Issue",
|
|
730
730
|
"APPLY": "Apply",
|
|
Binary file
|
|
@@ -8,6 +8,36 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
8
8
|
|
|
9
9
|
+ (UIViewController *)makeViewController;
|
|
10
10
|
|
|
11
|
+
/// Fetches project list data and presents DashboardViewController fully configured
|
|
12
|
+
/// for the given FCM deep-link payload. The payload must contain at minimum
|
|
13
|
+
/// `project_id` and `plan_id`. Auth/base-URL must already be configured in APIConfig
|
|
14
|
+
/// (i.e. the SDK has already been initialised by the user opening the app).
|
|
15
|
+
///
|
|
16
|
+
/// @param payload The FCM notification data dictionary.
|
|
17
|
+
/// @param presenter The view controller from which the dashboard will be presented modally.
|
|
18
|
+
+ (void)presentDashboardFromPayload:(NSDictionary *)payload
|
|
19
|
+
fromViewController:(UIViewController *)presenter;
|
|
20
|
+
|
|
21
|
+
/// Configures APIConfig with the project/plan context from the payload, then
|
|
22
|
+
/// presents AppointmentDetailsViewController modally. The payload must contain
|
|
23
|
+
/// `project_id`, `plan_id`, and `appointment_id` (or `id` as a fallback).
|
|
24
|
+
/// Auth/base-URL must already be configured in APIConfig.
|
|
25
|
+
///
|
|
26
|
+
/// @param payload The FCM notification data dictionary.
|
|
27
|
+
/// @param presenter The view controller from which the appointment screen will be presented.
|
|
28
|
+
+ (void)presentAppointmentFromPayload:(NSDictionary *)payload
|
|
29
|
+
fromViewController:(UIViewController *)presenter;
|
|
30
|
+
|
|
31
|
+
/// Fetches the issue list, finds the matching issue by `issue_id` from the payload,
|
|
32
|
+
/// and presents IssueDetailViewController fully configured. The payload must contain
|
|
33
|
+
/// at minimum `project_id`, `plan_id`, and `issue_id`. Auth/base-URL must already
|
|
34
|
+
/// be configured in APIConfig.
|
|
35
|
+
///
|
|
36
|
+
/// @param payload The FCM notification data dictionary.
|
|
37
|
+
/// @param presenter The view controller from which the issue screen will be presented.
|
|
38
|
+
+ (void)presentIssueFromPayload:(NSDictionary *)payload
|
|
39
|
+
fromViewController:(UIViewController *)presenter;
|
|
40
|
+
|
|
11
41
|
@end
|
|
12
42
|
|
|
13
43
|
NS_ASSUME_NONNULL_END
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
<dict>
|
|
7
7
|
<key>Assets.car</key>
|
|
8
8
|
<data>
|
|
9
|
-
|
|
9
|
+
TWfalcvk3qO6mG21qB5bdrcMBjM=
|
|
10
10
|
</data>
|
|
11
11
|
<key>Headers/QmsPlugin.h</key>
|
|
12
12
|
<data>
|
|
13
|
-
|
|
13
|
+
/jmzwY1kiBwDfgZJ8i6EPSgavTU=
|
|
14
14
|
</data>
|
|
15
15
|
<key>Headers/QmsPluginFramework.h</key>
|
|
16
16
|
<data>
|
|
@@ -28,6 +28,26 @@
|
|
|
28
28
|
<data>
|
|
29
29
|
vnwUOAcKtjfhFxaRXk5QkDcm3Mg=
|
|
30
30
|
</data>
|
|
31
|
+
<key>Montserrat-BoldItalic.ttf</key>
|
|
32
|
+
<data>
|
|
33
|
+
zTeJrlXMcCd2r90v0aga4Wxp+/Q=
|
|
34
|
+
</data>
|
|
35
|
+
<key>Montserrat-ExtraBold.ttf</key>
|
|
36
|
+
<data>
|
|
37
|
+
hPFnduIJnTtX2O0jm3bm+jKEsuc=
|
|
38
|
+
</data>
|
|
39
|
+
<key>Montserrat-ExtraLight.ttf</key>
|
|
40
|
+
<data>
|
|
41
|
+
zHokqGLxd5vbv3immEu5rpMkoSg=
|
|
42
|
+
</data>
|
|
43
|
+
<key>Montserrat-Italic.ttf</key>
|
|
44
|
+
<data>
|
|
45
|
+
rvTmoa8YSWRM4ek0tKuQWekW2Ic=
|
|
46
|
+
</data>
|
|
47
|
+
<key>Montserrat-Light.ttf</key>
|
|
48
|
+
<data>
|
|
49
|
+
M5fNmOUTZcielc0RMOAUG9pQUd4=
|
|
50
|
+
</data>
|
|
31
51
|
<key>Montserrat-Medium.ttf</key>
|
|
32
52
|
<data>
|
|
33
53
|
d/NVNBXYWMZTuupFqsqyAZZ3YzQ=
|
|
@@ -36,6 +56,14 @@
|
|
|
36
56
|
<data>
|
|
37
57
|
7BPvHyyZ+HgNby6z+fJ++J8wFhs=
|
|
38
58
|
</data>
|
|
59
|
+
<key>Montserrat-SemiBold.ttf</key>
|
|
60
|
+
<data>
|
|
61
|
+
efdGFtaLh9bPiXmP5yJZA2MmVno=
|
|
62
|
+
</data>
|
|
63
|
+
<key>Montserrat-Thin.ttf</key>
|
|
64
|
+
<data>
|
|
65
|
+
VQ5uHZkjael+nwCqca5IKmpjJtc=
|
|
66
|
+
</data>
|
|
39
67
|
<key>bm.json</key>
|
|
40
68
|
<data>
|
|
41
69
|
J8m1xUyQbIm7FjEl6dgNTLhSBVU=
|
|
@@ -46,7 +74,7 @@
|
|
|
46
74
|
</data>
|
|
47
75
|
<key>en.json</key>
|
|
48
76
|
<data>
|
|
49
|
-
|
|
77
|
+
VeWo6AyHrREEY0vQ5PaYJwdMY1g=
|
|
50
78
|
</data>
|
|
51
79
|
</dict>
|
|
52
80
|
<key>files2</key>
|
|
@@ -55,14 +83,14 @@
|
|
|
55
83
|
<dict>
|
|
56
84
|
<key>hash2</key>
|
|
57
85
|
<data>
|
|
58
|
-
|
|
86
|
+
6l4RTp5ZrLIp0kzkUpLOxcL0TNvCePYwUcTD/aPlyG4=
|
|
59
87
|
</data>
|
|
60
88
|
</dict>
|
|
61
89
|
<key>Headers/QmsPlugin.h</key>
|
|
62
90
|
<dict>
|
|
63
91
|
<key>hash2</key>
|
|
64
92
|
<data>
|
|
65
|
-
|
|
93
|
+
5YE/tWhfpg+TSsnziCLpEp2m4bzkKkH4oKHM990abTc=
|
|
66
94
|
</data>
|
|
67
95
|
</dict>
|
|
68
96
|
<key>Headers/QmsPluginFramework.h</key>
|
|
@@ -86,6 +114,41 @@
|
|
|
86
114
|
f6k9fapcL4gaZycinCEXgt5rdgCPvWNGs9dmTo/IP0M=
|
|
87
115
|
</data>
|
|
88
116
|
</dict>
|
|
117
|
+
<key>Montserrat-BoldItalic.ttf</key>
|
|
118
|
+
<dict>
|
|
119
|
+
<key>hash2</key>
|
|
120
|
+
<data>
|
|
121
|
+
ABpZsPLFQQgAM7g8pt+szgMJXZnKo1lINfUbfG2c51g=
|
|
122
|
+
</data>
|
|
123
|
+
</dict>
|
|
124
|
+
<key>Montserrat-ExtraBold.ttf</key>
|
|
125
|
+
<dict>
|
|
126
|
+
<key>hash2</key>
|
|
127
|
+
<data>
|
|
128
|
+
XPCiMTPMzjX54RW427+QQ0IBgnvCRl0S+dkbvwLPlGY=
|
|
129
|
+
</data>
|
|
130
|
+
</dict>
|
|
131
|
+
<key>Montserrat-ExtraLight.ttf</key>
|
|
132
|
+
<dict>
|
|
133
|
+
<key>hash2</key>
|
|
134
|
+
<data>
|
|
135
|
+
GsDgBpJUjjFCENEGGd5lYiVFf9RcebVtJCzfc5z3J48=
|
|
136
|
+
</data>
|
|
137
|
+
</dict>
|
|
138
|
+
<key>Montserrat-Italic.ttf</key>
|
|
139
|
+
<dict>
|
|
140
|
+
<key>hash2</key>
|
|
141
|
+
<data>
|
|
142
|
+
fofA+Ws5+7kZswrviZEyPQsldknzkeZFa88DwjFEj0k=
|
|
143
|
+
</data>
|
|
144
|
+
</dict>
|
|
145
|
+
<key>Montserrat-Light.ttf</key>
|
|
146
|
+
<dict>
|
|
147
|
+
<key>hash2</key>
|
|
148
|
+
<data>
|
|
149
|
+
lj13LJxEs8QBslfWk60mAG/HvVQhWVfVE1a0DjY1P4Q=
|
|
150
|
+
</data>
|
|
151
|
+
</dict>
|
|
89
152
|
<key>Montserrat-Medium.ttf</key>
|
|
90
153
|
<dict>
|
|
91
154
|
<key>hash2</key>
|
|
@@ -100,6 +163,20 @@
|
|
|
100
163
|
75z5nwF1vvUwuIk0vZBPz1b3c87G/U37jMr3ziu9OV4=
|
|
101
164
|
</data>
|
|
102
165
|
</dict>
|
|
166
|
+
<key>Montserrat-SemiBold.ttf</key>
|
|
167
|
+
<dict>
|
|
168
|
+
<key>hash2</key>
|
|
169
|
+
<data>
|
|
170
|
+
nE2zgUh1QQ59ZP3I5pZ2w7hJaLsVvzrOizlExZ+8VrY=
|
|
171
|
+
</data>
|
|
172
|
+
</dict>
|
|
173
|
+
<key>Montserrat-Thin.ttf</key>
|
|
174
|
+
<dict>
|
|
175
|
+
<key>hash2</key>
|
|
176
|
+
<data>
|
|
177
|
+
qMAnFkOz0iN+EeE+5ZACTUmzW3dgFJWOYP5hV8P1I/o=
|
|
178
|
+
</data>
|
|
179
|
+
</dict>
|
|
103
180
|
<key>bm.json</key>
|
|
104
181
|
<dict>
|
|
105
182
|
<key>hash2</key>
|
|
@@ -118,7 +195,7 @@
|
|
|
118
195
|
<dict>
|
|
119
196
|
<key>hash2</key>
|
|
120
197
|
<data>
|
|
121
|
-
|
|
198
|
+
1loRLBPvXhMxef8cbl/CEpfB0j0axeW+shU+jSRHK8w=
|
|
122
199
|
</data>
|
|
123
200
|
</dict>
|
|
124
201
|
</dict>
|
|
@@ -524,11 +524,11 @@
|
|
|
524
524
|
"SIGN_UP_SUBTITLE": "Please enter required details to continue.",
|
|
525
525
|
"APPOINTMENT_FOR_UNIT": "Appointment for unit",
|
|
526
526
|
"STEP_1": "Step 1/3",
|
|
527
|
-
"STEP_1_TITLE": "Select your preferred date",
|
|
527
|
+
"STEP_1_TITLE": "Select your preferred date.",
|
|
528
528
|
"STEP_2": " Step 2/3",
|
|
529
|
-
"STEP_2_TITLE": "Select your preferred time",
|
|
529
|
+
"STEP_2_TITLE": "Select your preferred time.",
|
|
530
530
|
"STEP_3": "Step 3/3",
|
|
531
|
-
"STEP_3_TITLE": "Confirm your appointment",
|
|
531
|
+
"STEP_3_TITLE": "Confirm your appointment.",
|
|
532
532
|
"OWNER_SIGN_UP": "Owner Sign Up",
|
|
533
533
|
"NO_RECORD_FOUND": "No Record Found",
|
|
534
534
|
"ASK_CS": "Would you like our Customer Support Team to contact you",
|
|
@@ -724,7 +724,7 @@
|
|
|
724
724
|
"ISSUES_SELECTED": "Issue(s) selected",
|
|
725
725
|
"ENTER_REMARKS_HERE": "Enter remarks here...",
|
|
726
726
|
"WITHDRAWING": "Withdrawing",
|
|
727
|
-
"WITHDRAW_ALERT_MESSAGE": "Confirm to withdraw issue?",
|
|
727
|
+
"WITHDRAW_ALERT_MESSAGE": "Confirm to withdraw this issue?",
|
|
728
728
|
"WITHDRAW_ISSUES_SUCCESS_LABEL": "You have succesfully withdrawn",
|
|
729
729
|
"FILTER_ISSUE_LIST": "Filter Issue",
|
|
730
730
|
"APPLY": "Apply",
|