@convep_mobilogy/react-native-qms-plugin 1.8.3 → 1.9.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/QmsPlugin.podspec +2 -4
- package/QmsPluginFramework.podspec +12 -0
- package/README.md +183 -4
- package/android/build.gradle +12 -2
- package/android/consumer-rules.pro +13 -0
- package/ios/QmsPlugin/QmsDashboardViewManager.mm +82 -29
- package/ios/QmsPlugin/QmsModule.mm +1296 -1
- package/ios/QmsPlugin/UIViewController+QmsAnalytics.m +3 -1
- package/lib/module/QmsDashboardView.android.js +121 -9
- package/lib/module/QmsDashboardView.android.js.map +1 -1
- package/lib/module/QmsPlugin.js +57 -0
- package/lib/module/QmsPlugin.js.map +1 -1
- package/lib/typescript/src/QmsDashboardView.android.d.ts.map +1 -1
- package/lib/typescript/src/QmsPlugin.d.ts +137 -0
- package/lib/typescript/src/QmsPlugin.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +7 -4
- package/src/QmsDashboardView.android.tsx +156 -11
- package/src/QmsPlugin.ts +312 -0
- package/src/index.tsx +13 -1
- package/ios/QmsPluginFramework.xcframework/Info.plist +0 -44
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Headers/QmsPlugin.h +0 -43
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Headers/QmsPluginFramework.h +0 -17
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Info.plist +0 -0
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Modules/module.modulemap +0 -6
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Bold.ttf +0 -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-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/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 +0 -289
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/bm.json +0 -781
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/cn.json +0 -782
- package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/en.json +0 -782
- 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 +0 -43
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Headers/QmsPluginFramework.h +0 -17
- 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/Modules/module.modulemap +0 -6
- 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-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-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/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 +0 -289
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/bm.json +0 -781
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/cn.json +0 -782
- package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/en.json +0 -782
package/QmsPlugin.podspec
CHANGED
|
@@ -14,16 +14,14 @@ Pod::Spec.new do |s|
|
|
|
14
14
|
s.homepage = homepage
|
|
15
15
|
s.license = package["license"]
|
|
16
16
|
s.authors = package["author"]
|
|
17
|
-
s.platforms = { :ios => "
|
|
17
|
+
s.platforms = { :ios => "15.1" }
|
|
18
18
|
|
|
19
19
|
s.source = { :git => "http://convep.ddns.me:20000/WeiHan/weihan-plugin.git", :tag => "#{s.version}" }
|
|
20
20
|
s.source_files = "ios/QmsPlugin/**/*.{h,m,mm,cpp}", "ios/QmsPluginSpec/**/*.{h,mm}"
|
|
21
21
|
s.private_header_files = "ios/QmsPlugin/**/*.h"
|
|
22
22
|
s.public_header_files = "ios/QmsPluginSpec/**/*.h"
|
|
23
23
|
|
|
24
|
-
s.
|
|
25
|
-
s.vendored_frameworks = "ios/QmsPluginFramework.xcframework"
|
|
26
|
-
|
|
24
|
+
s.dependency "QmsPluginFramework", "1.31.0"
|
|
27
25
|
s.dependency "React-Core"
|
|
28
26
|
s.dependency "ReactCommon"
|
|
29
27
|
s.dependency "React-Codegen"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = "QmsPluginFramework"
|
|
3
|
+
s.version = "1.31.0"
|
|
4
|
+
s.summary = "QMS Native iOS Framework"
|
|
5
|
+
s.description = "Native QMS iOS SDK distributed as XCFramework."
|
|
6
|
+
s.homepage = "https://sdk.convep.com"
|
|
7
|
+
s.license = { :type => "Proprietary", :text => "Copyright © Convep Mobilogy. All rights reserved." }
|
|
8
|
+
s.author = { "Convep Mobilogy" => "developer@convep.com" }
|
|
9
|
+
s.platform = :ios, "15.1"
|
|
10
|
+
s.source = { :http => "https://sdk.convep.com/ios/QMS/qms-plugin/1.31.0", :type => "zip", :sha256 => "6bae9da81e3b0df77a98edf939279290990539e954407dae90904b96192705cf" }
|
|
11
|
+
s.vendored_frameworks = "QmsPluginFramework.xcframework"
|
|
12
|
+
end
|
package/README.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
A React Native plugin that provides QMS (Quality Management System) components and APIs for defect management, dashboard visualization, and QMS workflow operations.
|
|
4
4
|
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
The development toolchain is managed with [mise](https://mise.jdx.dev/). From
|
|
8
|
+
the repository root, install the pinned Node.js, Java, and Ruby versions and
|
|
9
|
+
the JavaScript dependencies:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
mise install
|
|
13
|
+
mise run setup
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The project pins Yarn through the `packageManager` field in `package.json`; the
|
|
17
|
+
setup task enables Corepack before running the immutable Yarn install. Android
|
|
18
|
+
SDK tooling and Xcode are platform dependencies and are not installed by mise.
|
|
19
|
+
|
|
20
|
+
See [Contributing](CONTRIBUTING.md) for the complete development workflow and
|
|
21
|
+
available mise tasks.
|
|
22
|
+
|
|
23
|
+
To create a separate framework workspace with npm and local-development example
|
|
24
|
+
apps, run:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
./setup_framework.sh
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The script confirms before moving this repository into a new
|
|
31
|
+
`QmsPlugin_Framework` directory one level above its current location. See the
|
|
32
|
+
contributing guide for the generated layout and non-interactive usage. It adds
|
|
33
|
+
mise configuration to both generated apps and runs `mise install` plus
|
|
34
|
+
`mise run setup` in the plugin and each app.
|
|
35
|
+
|
|
36
|
+
For direct Kotlin/Java and Swift/Objective-C integration with the native AAR
|
|
37
|
+
and XCFramework, see
|
|
38
|
+
[Native QMS SDK Integration for Android and iOS](docs/ANDROID_IOS_INTEGRATION.md).
|
|
39
|
+
|
|
40
|
+
For native Android development, AAR/Maven generation, example-app testing, and
|
|
41
|
+
npm publishing, see
|
|
42
|
+
[Android SDK Development and npm Release](docs/ANDROID_DEVELOPMENT_AND_RELEASE.md).
|
|
43
|
+
|
|
5
44
|
---
|
|
6
45
|
|
|
7
46
|
# Installation
|
|
@@ -22,20 +61,132 @@ yarn add @convep_mobilogy/react-native-qms-plugin
|
|
|
22
61
|
|
|
23
62
|
# iOS Setup
|
|
24
63
|
|
|
25
|
-
|
|
64
|
+
Add the hosted native framework pod to the application `Podfile`. The podspec
|
|
65
|
+
is shipped with the npm package and CocoaPods downloads the matching ZIP from
|
|
66
|
+
`sdk.convep.com`:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
qms_plugin_package = Pod::Executable.execute_command('node', ['-p',
|
|
70
|
+
'require.resolve(
|
|
71
|
+
"@convep_mobilogy/react-native-qms-plugin/package.json",
|
|
72
|
+
{paths: [process.argv[1]]},
|
|
73
|
+
)', __dir__]).strip
|
|
74
|
+
|
|
75
|
+
target 'YourApp' do
|
|
76
|
+
pod 'QmsPluginFramework',
|
|
77
|
+
:path => File.dirname(qms_plugin_package)
|
|
78
|
+
end
|
|
79
|
+
```
|
|
26
80
|
|
|
27
|
-
|
|
81
|
+
Autolinking sets up the React Native wrapper. From the application's root
|
|
82
|
+
directory, install all CocoaPods dependencies:
|
|
28
83
|
|
|
29
84
|
```sh
|
|
30
85
|
cd ios
|
|
31
86
|
pod install
|
|
32
87
|
```
|
|
33
88
|
|
|
89
|
+
## iOS framework development
|
|
90
|
+
|
|
91
|
+
Use the following workflow when changing the native iOS framework and testing
|
|
92
|
+
it in the included example app.
|
|
93
|
+
|
|
94
|
+
### 1. Open the framework project
|
|
95
|
+
|
|
96
|
+
Open the following project in Xcode and make the required native changes:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
framework/ios_framework/QmsPluginFramework.xcodeproj
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2. Build and publish the XCFramework
|
|
103
|
+
|
|
104
|
+
From the plugin root, run the build helper. It archives the framework for both
|
|
105
|
+
iOS devices and the iOS Simulator, creates the XCFramework, packages it, and
|
|
106
|
+
uploads the versioned ZIP used by the native CocoaPod:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
./compile_framework.sh ios
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
You can optionally provide the SDK version:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
./compile_framework.sh ios <sdk-version>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The versioned XCFramework ZIP and its SHA-256 checksum are written to
|
|
119
|
+
`framework/ios_framework/build/releases/<sdk-version>/`. The root
|
|
120
|
+
`QmsPluginFramework.podspec` is updated for the release. The native pod has no
|
|
121
|
+
React dependency. The command uploads the ZIP to
|
|
122
|
+
`https://sdk.convep.com/api/uploadIOS` using the same credentials and upload
|
|
123
|
+
fields as Android. See [the iOS release guide](docs/IOS_COCOAPODS_RELEASE.md)
|
|
124
|
+
for upload settings and the client Podfile.
|
|
125
|
+
|
|
126
|
+
To build the XCFramework manually instead, run the following commands:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
cd framework/ios_framework
|
|
130
|
+
rm -rf QmsPluginFramework.xcframework
|
|
131
|
+
|
|
132
|
+
xcodebuild archive \
|
|
133
|
+
-project QmsPluginFramework.xcodeproj \
|
|
134
|
+
-scheme QmsPluginFramework \
|
|
135
|
+
-destination "generic/platform=iOS" \
|
|
136
|
+
-archivePath ./build/ios_devices.xcarchive \
|
|
137
|
+
SKIP_INSTALL=NO \
|
|
138
|
+
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
|
|
139
|
+
|
|
140
|
+
xcodebuild archive \
|
|
141
|
+
-project QmsPluginFramework.xcodeproj \
|
|
142
|
+
-scheme QmsPluginFramework \
|
|
143
|
+
-destination "generic/platform=iOS Simulator" \
|
|
144
|
+
-archivePath ./build/ios_simulators.xcarchive \
|
|
145
|
+
SKIP_INSTALL=NO \
|
|
146
|
+
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
|
|
147
|
+
|
|
148
|
+
xcodebuild -create-xcframework \
|
|
149
|
+
-framework ./build/ios_devices.xcarchive/Products/Library/Frameworks/QmsPluginFramework.framework \
|
|
150
|
+
-framework ./build/ios_simulators.xcarchive/Products/Library/Frameworks/QmsPluginFramework.framework \
|
|
151
|
+
-output ./QmsPluginFramework.xcframework
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 3. Install the example app's iOS dependencies
|
|
155
|
+
|
|
156
|
+
From the plugin root, run this after the uploaded version is available so
|
|
157
|
+
CocoaPods downloads the latest native build:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
cd example/ios
|
|
161
|
+
pod install
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 4. Start Metro
|
|
165
|
+
|
|
166
|
+
In a separate terminal, start Metro from the plugin root:
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
cd example
|
|
170
|
+
npx react-native start
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 5. Build and run the example app
|
|
174
|
+
|
|
175
|
+
Open the CocoaPods workspace (not the `.xcodeproj`) and run the desired iOS
|
|
176
|
+
Simulator or connected device:
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
example/ios/QmsPluginExample.xcworkspace
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Repeat steps 2 through 5 after each native framework change.
|
|
183
|
+
|
|
34
184
|
---
|
|
35
185
|
|
|
36
186
|
# Android Setup
|
|
37
187
|
|
|
38
|
-
Autolinking should set up everything automatically, but you need to add the
|
|
188
|
+
Autolinking should set up everything automatically, but you need to add the QMS
|
|
189
|
+
Maven repository and enable core library desugaring.
|
|
39
190
|
|
|
40
191
|
1. In `android/build.gradle`, add the Maven repo:
|
|
41
192
|
|
|
@@ -47,7 +198,10 @@ allprojects {
|
|
|
47
198
|
maven { url = uri("https://www.jitpack.io") }
|
|
48
199
|
|
|
49
200
|
maven {
|
|
50
|
-
url = uri("https://
|
|
201
|
+
url = uri("https://sdk.convep.com/maven")
|
|
202
|
+
content {
|
|
203
|
+
includeGroup("com.convep.qms")
|
|
204
|
+
}
|
|
51
205
|
}
|
|
52
206
|
}
|
|
53
207
|
}
|
|
@@ -125,6 +279,31 @@ const styles = StyleSheet.create({
|
|
|
125
279
|
|
|
126
280
|
---
|
|
127
281
|
|
|
282
|
+
## Open Add Issue Directly
|
|
283
|
+
|
|
284
|
+
Use `QmsPlugin.openAddIssue` when the host app already knows the target unit and wants to skip the QMS project/unit/dashboard flow.
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
import { QmsPlugin } from '@convep_mobilogy/react-native-qms-plugin';
|
|
288
|
+
|
|
289
|
+
async function handleAddIssuePress() {
|
|
290
|
+
await QmsPlugin.openAddIssue({
|
|
291
|
+
userToken: '<UserToken>',
|
|
292
|
+
clientID: '<ClientID>',
|
|
293
|
+
clientCode: '<CompanyCode>',
|
|
294
|
+
isOrigin: false,
|
|
295
|
+
drawingPlanId: 1183,
|
|
296
|
+
projectId: 4,
|
|
297
|
+
unitName: 'C-L(7)',
|
|
298
|
+
projectName: 'Ara E Residence Dev',
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
`drawingPlanId` is required because Add Issue needs a selected unit plan. `projectId`, `unitName`, and `projectName` are optional but recommended so the SDK can display and cache the correct context.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
128
307
|
# Props
|
|
129
308
|
|
|
130
309
|
## QmsDashboardView Props
|
package/android/build.gradle
CHANGED
|
@@ -21,6 +21,16 @@ apply plugin: "kotlin-android"
|
|
|
21
21
|
|
|
22
22
|
apply plugin: "com.facebook.react"
|
|
23
23
|
|
|
24
|
+
def qmsLocalMavenRepo = uri("$projectDir/maven-repo")
|
|
25
|
+
|
|
26
|
+
// Make the bundled native framework available to the consuming app. This lets
|
|
27
|
+
// local TGZ installs use the matching AAR without waiting for remote publishing.
|
|
28
|
+
rootProject.allprojects {
|
|
29
|
+
repositories {
|
|
30
|
+
maven { url = qmsLocalMavenRepo }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
def getExtOrIntegerDefault(name) {
|
|
25
35
|
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["QmsPlugin_" + name]).toInteger()
|
|
26
36
|
}
|
|
@@ -33,6 +43,7 @@ android {
|
|
|
33
43
|
defaultConfig {
|
|
34
44
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
35
45
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
46
|
+
consumerProguardFiles "consumer-rules.pro"
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
buildFeatures {
|
|
@@ -75,8 +86,7 @@ dependencies {
|
|
|
75
86
|
implementation "com.facebook.react:react-android"
|
|
76
87
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
77
88
|
implementation 'com.facebook.react:react-native:+'
|
|
78
|
-
implementation "com.convep.qms:qms-plugin:1.
|
|
79
|
-
|
|
89
|
+
implementation "com.convep.qms:qms-plugin:1.31.0"
|
|
80
90
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
81
91
|
|
|
82
92
|
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# React Native creates this package from the generated PackageList. Keep the
|
|
2
|
+
# package and its native module entry points stable in minified host apps.
|
|
3
|
+
-keep class com.qmsplugin.QmsPluginPackage { *; }
|
|
4
|
+
-keep class com.qmsplugin.QmsPluginModule { *; }
|
|
5
|
+
|
|
6
|
+
# The wrapper returns the native framework module to React Native. ReactMethod
|
|
7
|
+
# methods are invoked through bridge metadata rather than ordinary Java calls.
|
|
8
|
+
-keep class com.convep.qms.QmsModule { *; }
|
|
9
|
+
-keepclassmembers class com.convep.qms.** {
|
|
10
|
+
@com.facebook.react.bridge.ReactMethod <methods>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
-keepattributes RuntimeVisibleAnnotations,RuntimeVisibleParameterAnnotations,AnnotationDefault
|
|
@@ -72,9 +72,12 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
72
72
|
|
|
73
73
|
- (instancetype)initWithFrame:(CGRect)frame {
|
|
74
74
|
if (self = [super initWithFrame:frame]) {
|
|
75
|
-
|
|
75
|
+
// The controller must only be created after this native view is mounted.
|
|
76
|
+
// Creating it here lets credential props start the API flow before React
|
|
77
|
+
// has forwarded isOrigin, leaving a detached controller making requests.
|
|
78
|
+
_dashboardVC = nil;
|
|
76
79
|
_didSetupVC = NO;
|
|
77
|
-
|
|
80
|
+
_isOrigin = NO;
|
|
78
81
|
|
|
79
82
|
// Listen for native dashboard close notification
|
|
80
83
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
@@ -114,6 +117,7 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
114
117
|
|
|
115
118
|
// 1️⃣ create VC with props
|
|
116
119
|
_dashboardVC = [QmsPluginUI makeViewController];
|
|
120
|
+
_dashboardVC.view.backgroundColor = [UIColor whiteColor];
|
|
117
121
|
|
|
118
122
|
[parentVC addChildViewController:_dashboardVC];
|
|
119
123
|
_dashboardVC.view.frame = parentVC.view.bounds;
|
|
@@ -177,8 +181,13 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
- (void)cleanupDashboard {
|
|
184
|
+
// APIConfig is process-global inside the framework. Reset it before
|
|
185
|
+
// teardown so a later embedded dashboard cannot inherit origin mode.
|
|
186
|
+
_isOrigin = NO;
|
|
180
187
|
if (!_dashboardVC) return;
|
|
181
188
|
|
|
189
|
+
[self forwardProp:@"isOrigin" value:@NO];
|
|
190
|
+
|
|
182
191
|
[_dashboardVC willMoveToParentViewController:nil];
|
|
183
192
|
[_dashboardVC.view removeFromSuperview];
|
|
184
193
|
[_dashboardVC removeFromParentViewController];
|
|
@@ -268,6 +277,9 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
268
277
|
}
|
|
269
278
|
|
|
270
279
|
- (void)forwardPropsToVC {
|
|
280
|
+
// Apply mode before credentials. The token setter can make the project
|
|
281
|
+
// controller ready and start its API chain immediately.
|
|
282
|
+
[self forwardProp:@"isOrigin" value:@(_isOrigin)];
|
|
271
283
|
[self forwardProp:@"ClientID" value:_ClientID];
|
|
272
284
|
[self forwardProp:@"ClientCode" value:_ClientCode];
|
|
273
285
|
[self forwardProp:@"user_token" value:_user_token];
|
|
@@ -277,7 +289,6 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
277
289
|
[self forwardProp:@"headerIconColor" value:_headerIconColor];
|
|
278
290
|
[self forwardProp:@"accentColor" value:_accentColor];
|
|
279
291
|
[self forwardProp:@"fontFamily" value:_fontFamily];
|
|
280
|
-
[self forwardProp:@"isOrigin" value:@(_isOrigin)];
|
|
281
292
|
[self forwardProp:@"versionNumber" value:_versionNumber];
|
|
282
293
|
[self applyAllThemeImmediatelyIfNeeded];
|
|
283
294
|
}
|
|
@@ -299,7 +310,7 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
299
310
|
@"new_issue", @"new_info", @"accept_issue", @"reject_issue", @"decline_issue",
|
|
300
311
|
@"start_fix", @"redo", @"completed", @"close_internal", @"close_external",
|
|
301
312
|
@"pending_owner_acceptance", @"assign_issue", @"reassign_issue", @"poa_reminder",
|
|
302
|
-
@"auto_close_reminder", @"
|
|
313
|
+
@"auto_close_reminder", @"overdue_reminder",
|
|
303
314
|
@"issue_summary_reminder", @"lodge_summary_reminder", @"overdue_summary_reminder"
|
|
304
315
|
]];
|
|
305
316
|
});
|
|
@@ -311,8 +322,15 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
311
322
|
[type isEqualToString:@"unattend_appt_reminder"];
|
|
312
323
|
}
|
|
313
324
|
|
|
314
|
-
- (BOOL)
|
|
315
|
-
|
|
325
|
+
- (BOOL)isDashboardType:(NSString *)type {
|
|
326
|
+
static NSSet<NSString *> *types;
|
|
327
|
+
static dispatch_once_t onceToken;
|
|
328
|
+
dispatch_once(&onceToken, ^{
|
|
329
|
+
types = [NSSet setWithArray:@[
|
|
330
|
+
@"pending_access_reminder", @"completion_letter", @"key_collection", @"defect_summary", @"clearance_letter"
|
|
331
|
+
]];
|
|
332
|
+
});
|
|
333
|
+
return type.length > 0 && [types containsObject:type];
|
|
316
334
|
}
|
|
317
335
|
|
|
318
336
|
- (void)applyPayloadContext:(NSDictionary *)payload {
|
|
@@ -429,23 +447,9 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
429
447
|
UIViewController *presenter = self.dashboardVC;
|
|
430
448
|
if (!presenter) return;
|
|
431
449
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
UIViewController *vc = [[cls alloc] init];
|
|
439
|
-
if (!vc) return;
|
|
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
|
-
|
|
448
|
-
[self presentDeepLinkVC:vc];
|
|
450
|
+
// Delegate to QmsPluginUI which handles account switching + presentation.
|
|
451
|
+
// AccountManager and DraftListingViewController are both inside the framework.
|
|
452
|
+
[QmsPluginUI presentDraftListingFromPayload:payload fromViewController:presenter];
|
|
449
453
|
}
|
|
450
454
|
|
|
451
455
|
- (void)routePayloadIfNeeded:(NSDictionary *)payload force:(BOOL)force {
|
|
@@ -485,13 +489,12 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
485
489
|
} else if ([self isAppointmentType:type]) {
|
|
486
490
|
NSLog(@"🧭 [QmsDashboardView] routing → presentAppointmentFromPayload (appointment type: %@)", type);
|
|
487
491
|
[self presentAppointmentDetailsViewControllerWithPayload:payload title:title ?: @""];
|
|
488
|
-
} else if ([type
|
|
489
|
-
NSLog(@"🧭 [QmsDashboardView] routing → presentDashboardFromPayload (
|
|
492
|
+
} else if ([self isDashboardType:type]) {
|
|
493
|
+
NSLog(@"🧭 [QmsDashboardView] routing → presentDashboardFromPayload (dashboard type: %@)", type);
|
|
490
494
|
[self presentDashboardViewControllerWithPayload:payload title:title ?: @""];
|
|
491
|
-
} else if ([
|
|
495
|
+
} else if ([type isEqualToString:@"draft_reminder"]) {
|
|
492
496
|
NSLog(@"🧭 [QmsDashboardView] routing → presentDraftListingViewController (draft_reminder)");
|
|
493
|
-
|
|
494
|
-
[self presentDashboardViewControllerWithPayload:payload title:title ?: @""];
|
|
497
|
+
[self presentDraftListingViewControllerWithPayload:payload];
|
|
495
498
|
} else {
|
|
496
499
|
NSLog(@"🧭 [QmsDashboardView] routePayloadIfNeeded — no route matched for type=%@", type ?: @"(none)");
|
|
497
500
|
}
|
|
@@ -544,6 +547,12 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
544
547
|
- (void)applyHeaderThemeRecursivelyOnView:(UIView *)view textColor:(UIColor *)textColor iconColor:(UIColor *)iconColor {
|
|
545
548
|
if (!view) return;
|
|
546
549
|
|
|
550
|
+
// Skip views tagged 9001 and their entire subtree — they manage their own colour.
|
|
551
|
+
if (view.tag == 9001) return;
|
|
552
|
+
|
|
553
|
+
// Never reach into UISegmentedControl internals.
|
|
554
|
+
if ([view isKindOfClass:[UISegmentedControl class]]) return;
|
|
555
|
+
|
|
547
556
|
if (textColor && [view isKindOfClass:[UILabel class]]) {
|
|
548
557
|
UILabel *label = (UILabel *)view;
|
|
549
558
|
CGPoint originInRoot = [label.superview convertPoint:label.frame.origin toView:_dashboardVC.view];
|
|
@@ -588,6 +597,13 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
588
597
|
- (void)applyThemeRecursivelyOnView:(UIView *)view color:(UIColor *)themeColor {
|
|
589
598
|
if (!view || !themeColor) return;
|
|
590
599
|
|
|
600
|
+
// Skip views tagged 9001 and their entire subtree — they manage their own colour.
|
|
601
|
+
if (view.tag == 9001) return;
|
|
602
|
+
|
|
603
|
+
// Never reach into UISegmentedControl internals — its tint/selected colour
|
|
604
|
+
// is set directly via selectedSegmentTintColor and must not be overwritten here.
|
|
605
|
+
if ([view isKindOfClass:[UISegmentedControl class]]) return;
|
|
606
|
+
|
|
591
607
|
CGPoint originInRoot = [view.superview convertPoint:view.frame.origin toView:_dashboardVC.view];
|
|
592
608
|
BOOL nearHeader = originInRoot.y <= 140.0 && view.bounds.size.height <= 120.0;
|
|
593
609
|
if (nearHeader && [self isDefaultQmsBlueColor:view.backgroundColor]) {
|
|
@@ -644,6 +660,16 @@ static NSString * const kQmsRoutePayloadNotification = @"QmsRoutePayloadNotifica
|
|
|
644
660
|
- (void)applyAccentRecursivelyOnView:(UIView *)view color:(UIColor *)color {
|
|
645
661
|
if (!view || !color) return;
|
|
646
662
|
|
|
663
|
+
// Skip views (and their entire subtree) that have been tagged 9001 —
|
|
664
|
+
// this lets individual controls opt-out of theme colour replacement.
|
|
665
|
+
if (view.tag == 9001) return;
|
|
666
|
+
|
|
667
|
+
if ([view isKindOfClass:[UISegmentedControl class]]) {
|
|
668
|
+
// Never touch the internals of a UISegmentedControl — its
|
|
669
|
+
// selectedSegmentTintColor is managed by the VC that owns it.
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
|
|
647
673
|
if ([view isKindOfClass:[UIButton class]]) {
|
|
648
674
|
UIButton *button = (UIButton *)view;
|
|
649
675
|
button.tintColor = color;
|
|
@@ -798,7 +824,10 @@ RCT_EXPORT_MODULE();
|
|
|
798
824
|
@"onAnalyticsScreen",
|
|
799
825
|
@"onAnalyticsEvent",
|
|
800
826
|
@"QmsSdkOnAnalyticsScreen",
|
|
801
|
-
@"QmsSdkOnAnalyticsEvent"
|
|
827
|
+
@"QmsSdkOnAnalyticsEvent",
|
|
828
|
+
@"onDraftIssueCreated",
|
|
829
|
+
@"onDraftIssueDeleted",
|
|
830
|
+
@"onPoaSignOffCompleted"
|
|
802
831
|
];
|
|
803
832
|
}
|
|
804
833
|
|
|
@@ -826,6 +855,18 @@ RCT_EXPORT_MODULE();
|
|
|
826
855
|
selector:@selector(handleActiveAccountChangeEmitter:)
|
|
827
856
|
name:@"QmsActiveAccountDidChangeNotification"
|
|
828
857
|
object:nil];
|
|
858
|
+
[center addObserver:self
|
|
859
|
+
selector:@selector(handleDraftIssueCreated:)
|
|
860
|
+
name:@"QmsDraftIssueCreatedNotification"
|
|
861
|
+
object:nil];
|
|
862
|
+
[center addObserver:self
|
|
863
|
+
selector:@selector(handleDraftIssueDeleted:)
|
|
864
|
+
name:@"QmsDraftIssueDeletedNotification"
|
|
865
|
+
object:nil];
|
|
866
|
+
[center addObserver:self
|
|
867
|
+
selector:@selector(handlePoaSignOffCompleted:)
|
|
868
|
+
name:@"QmsPoaSignOffCompleted"
|
|
869
|
+
object:nil];
|
|
829
870
|
}
|
|
830
871
|
|
|
831
872
|
- (void)stopObserving {
|
|
@@ -855,6 +896,18 @@ RCT_EXPORT_MODULE();
|
|
|
855
896
|
[self sendEventWithName:@"onActiveAccountChange" body:note.userInfo];
|
|
856
897
|
}
|
|
857
898
|
|
|
899
|
+
- (void)handleDraftIssueCreated:(NSNotification *)note {
|
|
900
|
+
[self sendEventWithName:@"onDraftIssueCreated" body:note.userInfo];
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
- (void)handleDraftIssueDeleted:(NSNotification *)note {
|
|
904
|
+
[self sendEventWithName:@"onDraftIssueDeleted" body:note.userInfo];
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
- (void)handlePoaSignOffCompleted:(NSNotification *)note {
|
|
908
|
+
[self sendEventWithName:@"onPoaSignOffCompleted" body:note.userInfo ?: @{}];
|
|
909
|
+
}
|
|
910
|
+
|
|
858
911
|
- (void)dealloc {
|
|
859
912
|
[self stopObserving];
|
|
860
913
|
}
|