@regulaforensics/idv 3.2.23-beta
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/README.md +36 -0
- package/RNIDV.podspec +21 -0
- package/android/CVDIDV.kt +48 -0
- package/android/build.gradle +41 -0
- package/android/cordova.gradle +20 -0
- package/android/src/main/java/com/regula/plugin/idv/JSONConstructor.kt +135 -0
- package/android/src/main/java/com/regula/plugin/idv/Main.kt +124 -0
- package/android/src/main/java/com/regula/plugin/idv/RNIDVModule.kt +71 -0
- package/android/src/main/java/com/regula/plugin/idv/Utils.kt +60 -0
- package/examples/capacitor/README.md +15 -0
- package/examples/capacitor/android/app/build.gradle +50 -0
- package/examples/capacitor/android/app/capacitor.build.gradle +22 -0
- package/examples/capacitor/android/app/proguard-rules.pro +21 -0
- package/examples/capacitor/android/app/src/main/AndroidManifest.xml +26 -0
- package/examples/capacitor/android/app/src/main/assets/Regula/.gitkeep +0 -0
- package/examples/capacitor/android/app/src/main/java/com/regula/example/idv/capacitor/MainActivity.java +5 -0
- package/examples/capacitor/android/app/src/main/res/drawable/ic_launcher.png +0 -0
- package/examples/capacitor/android/app/src/main/res/drawable/ic_launcher_foreground.png +0 -0
- package/examples/capacitor/android/app/src/main/res/drawable/ic_launcher_round.png +0 -0
- package/examples/capacitor/android/app/src/main/res/drawable/launcher.xml +4 -0
- package/examples/capacitor/android/app/src/main/res/drawable/launcher_round.xml +4 -0
- package/examples/capacitor/android/app/src/main/res/drawable/splash.png +0 -0
- package/examples/capacitor/android/app/src/main/res/layout/activity_main.xml +12 -0
- package/examples/capacitor/android/app/src/main/res/values/styles.xml +22 -0
- package/examples/capacitor/android/build.gradle +30 -0
- package/examples/capacitor/android/capacitor.settings.gradle +15 -0
- package/examples/capacitor/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/capacitor/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/examples/capacitor/android/gradle.properties +22 -0
- package/examples/capacitor/android/gradlew +252 -0
- package/examples/capacitor/android/gradlew.bat +94 -0
- package/examples/capacitor/android/settings.gradle +5 -0
- package/examples/capacitor/android/variables.gradle +16 -0
- package/examples/capacitor/index.html +5 -0
- package/examples/capacitor/index.tsx +16 -0
- package/examples/capacitor/ionic.config.json +7 -0
- package/examples/capacitor/ios/App/App/App.entitlements +10 -0
- package/examples/capacitor/ios/App/App/AppDelegate.swift +49 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png +0 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json +14 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/Contents.json +6 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json +23 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png +0 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png +0 -0
- package/examples/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png +0 -0
- package/examples/capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard +32 -0
- package/examples/capacitor/ios/App/App/Base.lproj/Main.storyboard +19 -0
- package/examples/capacitor/ios/App/App/Info.plist +65 -0
- package/examples/capacitor/ios/App/App.xcodeproj/project.pbxproj +414 -0
- package/examples/capacitor/ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/examples/capacitor/ios/App/App.xcworkspace/contents.xcworkspacedata +10 -0
- package/examples/capacitor/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/examples/capacitor/ios/App/Podfile +26 -0
- package/examples/capacitor/package.json +27 -0
- package/examples/capacitor/public/assets/.gitkeep +0 -0
- package/examples/capacitor/scripts/android.sh +9 -0
- package/examples/capacitor/scripts/ios.sh +8 -0
- package/examples/capacitor/scripts/setup.sh +14 -0
- package/examples/capacitor/src/main.css +148 -0
- package/examples/capacitor/src/main.html +38 -0
- package/examples/capacitor/src/main.tsx +10 -0
- package/examples/capacitor/tsconfig.json +5 -0
- package/examples/capacitor/vite.config.ts +17 -0
- package/examples/ionic/README.md +15 -0
- package/examples/ionic/angular.json +39 -0
- package/examples/ionic/assets/.gitkeep +0 -0
- package/examples/ionic/config.xml +59 -0
- package/examples/ionic/images/icon.png +0 -0
- package/examples/ionic/index.html +19 -0
- package/examples/ionic/index.tsx +28 -0
- package/examples/ionic/ionic.config.json +7 -0
- package/examples/ionic/package.json +46 -0
- package/examples/ionic/scripts/android.sh +8 -0
- package/examples/ionic/scripts/ios.sh +8 -0
- package/examples/ionic/scripts/setup.sh +8 -0
- package/examples/ionic/src/main.css +148 -0
- package/examples/ionic/src/main.html +38 -0
- package/examples/ionic/src/main.tsx +10 -0
- package/examples/ionic/tsconfig.json +14 -0
- package/examples/react_native/README.md +15 -0
- package/examples/react_native/app.config.ts +46 -0
- package/examples/react_native/assets/.gitkeep +0 -0
- package/examples/react_native/images/icon.png +0 -0
- package/examples/react_native/index.html +11 -0
- package/examples/react_native/index.tsx +63 -0
- package/examples/react_native/metro.config.js +7 -0
- package/examples/react_native/package.json +29 -0
- package/examples/react_native/scripts/android.sh +13 -0
- package/examples/react_native/scripts/ios.sh +12 -0
- package/examples/react_native/scripts/setup.sh +9 -0
- package/examples/react_native/src/main.css +148 -0
- package/examples/react_native/src/main.html +38 -0
- package/examples/react_native/src/main.tsx +10 -0
- package/ios/CVDIDV.swift +72 -0
- package/ios/FlutterIDVPlugin.swift +72 -0
- package/ios/JSONConstructor.swift +134 -0
- package/ios/Main.swift +89 -0
- package/ios/RNIDV.swift +72 -0
- package/ios/Utils.swift +56 -0
- package/package.json +38 -0
- package/plugin.xml +45 -0
- package/test/json.tsx +0 -0
- package/test/package-lock.json +584 -0
- package/test/package.json +9 -0
- package/test/test.tsx +3 -0
- package/test/utils.tsx +38 -0
- package/www/capacitor/index.js +6 -0
- package/www/capacitor/internal/bridge.js +19 -0
- package/www/capacitor/internal/cordova.js +17 -0
- package/www/cordova.js +150 -0
- package/www/react-native/index.js +6 -0
- package/www/react-native/internal/bridge.js +19 -0
- package/www/types/index.d.ts +12 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<div class="column" style="height: 100%">
|
|
2
|
+
<div class="column header">
|
|
3
|
+
<span id="status">Loading...</span>
|
|
4
|
+
<div class="column divider"></div>
|
|
5
|
+
</div>
|
|
6
|
+
<div id="main" class="column no-scroll">
|
|
7
|
+
<div class="row">
|
|
8
|
+
<div class="column" style="padding: 5px;">
|
|
9
|
+
<p>Portrait</p>
|
|
10
|
+
<img id="portrait-image" src="images/portrait.png" height="160px" width="120px">
|
|
11
|
+
</div>
|
|
12
|
+
<div class="column" style="padding: 5px;">
|
|
13
|
+
<p>Document image</p>
|
|
14
|
+
<img id="document-image" src="images/document.png" height="160px" width="200px">
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
<div id="scenario-container" class="column no-scroll" style="margin-top: 15px; background-color: rgba(0, 0, 0, 0.03);">
|
|
18
|
+
<div id="scenarios" class="scroll"></div>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="row" style="width: 360px; padding-top: 15px;">
|
|
21
|
+
<span id="rfid-checkbox-description" style="font-size: 18px;width: 100%;">Process rfid reading(unavailable)</span>
|
|
22
|
+
<input id="rfid-checkbox" type="checkbox" style="margin-left: auto;" disabled />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="row">
|
|
25
|
+
<button id="scan" class="button">Scan document</button>
|
|
26
|
+
<button id="recognize" class="button">Scan image</button>
|
|
27
|
+
</div>
|
|
28
|
+
<button id="connect" class="button" style="width: 360px; display: none;">Connect</button>
|
|
29
|
+
<div style="padding-top: 20px;"></div>
|
|
30
|
+
</div>
|
|
31
|
+
<div id="custom-rfid" class="column no-scroll" style="display: none;">
|
|
32
|
+
<span id="rfid-description" style="font-size: 22px">Place your phone on top of the NFC tag</span>
|
|
33
|
+
<div class="progress-bar">
|
|
34
|
+
<div id="progress"></div>
|
|
35
|
+
</div>
|
|
36
|
+
<button id="cancel-rfid" class="text-button" style="margin-top: 50px; padding-bottom: 100px;">X</button>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"include": [
|
|
3
|
+
"*.tsx"
|
|
4
|
+
],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"types": [],
|
|
7
|
+
"module": "esnext",
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"target": "es2022",
|
|
11
|
+
"jsx": "react-jsx",
|
|
12
|
+
"skipLibCheck": true, // Temp fix for https://github.com/ionic-team/ionic-framework/issues/30650
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Regula IDV React Native demo application
|
|
2
|
+
|
|
3
|
+
## How to build demo application
|
|
4
|
+
1. Download or the clone current repository using the command `git clone https://github.com/regulaforensics/npm-idv.git`.
|
|
5
|
+
2. Put `regula.license` file at `public/assets/` (you can get a trial license [here](https://client.regulaforensics.com)).
|
|
6
|
+
3. Put `db.dat` file at `public/assets/` (you can get a trial database [here](https://client.regulaforensics.com/customer/databases))
|
|
7
|
+
4. Execute `npm run setup` within this directory.
|
|
8
|
+
5. In `src/main.tsx` choose prefered login configuration(`loginType` variable) and provide your login data according to it: username and password for `credentials`, tokenUrl for `token`, apiKey for `apiKey`.
|
|
9
|
+
6. Run the app:
|
|
10
|
+
* IOS: `npm run ios`.
|
|
11
|
+
* Android: `npm run android`.
|
|
12
|
+
7. After initialization choose **General KYC - AP** from workflows list and click **Start Workflow** button.
|
|
13
|
+
8. Complete workflow and get your session id.
|
|
14
|
+
|
|
15
|
+
**Note**: `npm run ios`/`npm run android` is just one way of running the app. You can also pass `-o` or `--open` argument to the command, and this will open Xcode/Android Studio, then run the app directly from the IDE. Overall, this is a more consistent way, so if you're having troubles running the app from terminal, try running it from the IDE. Just don't forget to make sure that Metro Bundler is running(`npm start`).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ExpoConfig, ConfigContext } from 'expo/config'
|
|
2
|
+
|
|
3
|
+
export default ({ config }: ConfigContext): ExpoConfig => ({
|
|
4
|
+
...config,
|
|
5
|
+
slug: 'idv',
|
|
6
|
+
name: 'IDV',
|
|
7
|
+
orientation: 'portrait',
|
|
8
|
+
icon: 'images/icon.png',
|
|
9
|
+
ios: {
|
|
10
|
+
bundleIdentifier: 'com.regula.example.idv.react',
|
|
11
|
+
infoPlist: {
|
|
12
|
+
NSCameraUsageDescription: 'To use camera',
|
|
13
|
+
NSPhotoLibraryUsageDescription: 'To use gallery',
|
|
14
|
+
NFCReaderUsageDescription: 'To use NFC',
|
|
15
|
+
'com.apple.developer.nfc.readersession.iso7816.select-identifiers': [
|
|
16
|
+
'A0000002471001',
|
|
17
|
+
'E80704007F00070302',
|
|
18
|
+
'A000000167455349474E',
|
|
19
|
+
'A0000002480100',
|
|
20
|
+
'A0000002480200',
|
|
21
|
+
'A0000002480300',
|
|
22
|
+
'A00000045645444C2D3031'
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
entitlements: { 'com.apple.developer.nfc.readersession.formats': ['TAG'] },
|
|
26
|
+
appleTeamId: ''
|
|
27
|
+
},
|
|
28
|
+
android: {
|
|
29
|
+
package: 'com.regula.example.idv.react',
|
|
30
|
+
permissions: ['android.permission.NFC'],
|
|
31
|
+
edgeToEdgeEnabled: true
|
|
32
|
+
},
|
|
33
|
+
plugins: [
|
|
34
|
+
['expo-custom-assets', { assetsPaths: ['./assets'] }],
|
|
35
|
+
['expo-build-properties', {
|
|
36
|
+
android: {
|
|
37
|
+
extraMavenRepos: [
|
|
38
|
+
{ url: 'https://maven.regulaforensics.com/RegulaDocumentReader' },
|
|
39
|
+
{ url: 'https://maven.regulaforensics.com/RegulaDocumentReader/Beta' },
|
|
40
|
+
{ url: 'https://maven.regulaforensics.com/RegulaDocumentReader/Nightly' },
|
|
41
|
+
{ url: 'https://maven.regulaforensics.com/RegulaDocumentReader/Stage' }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}]
|
|
45
|
+
]
|
|
46
|
+
})
|
|
File without changes
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<meta name="viewport" content="initial-scale=1, user-scalable=no, viewport-fit=cover">
|
|
2
|
+
<link rel="stylesheet" href="src/main.css">
|
|
3
|
+
|
|
4
|
+
<div id="content" style="height: 100%"></div>
|
|
5
|
+
|
|
6
|
+
<script>
|
|
7
|
+
fetch("src/main.html")
|
|
8
|
+
.then(response => response.text())
|
|
9
|
+
.then(html => document.getElementById("content").innerHTML = html)
|
|
10
|
+
.then(_ => window.ReactNativeWebView.postMessage(`{"id": "ready"}`))
|
|
11
|
+
</script>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { registerRootComponent } from 'expo'
|
|
2
|
+
import WebView from 'react-native-webview'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { main } from './src/main'
|
|
5
|
+
|
|
6
|
+
var webViewRef: any
|
|
7
|
+
const onclicks: any = {}
|
|
8
|
+
const onMessage = (json: any) => {
|
|
9
|
+
const event = JSON.parse(json.nativeEvent.data)
|
|
10
|
+
if (event.id === "ready") main()
|
|
11
|
+
if (event.id === "onclick") {
|
|
12
|
+
onclicks[event.value]()
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const document = {
|
|
17
|
+
getElementById(id: string): any {
|
|
18
|
+
return new Proxy({}, {
|
|
19
|
+
set(_, prop: string, value) {
|
|
20
|
+
if (prop == "onclick") {
|
|
21
|
+
onclicks[id] = value
|
|
22
|
+
webViewRef.injectJavaScript(`
|
|
23
|
+
document.getElementById("${id}").onclick = () => {
|
|
24
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ id: "onclick", value: "${id}" }));
|
|
25
|
+
}; true
|
|
26
|
+
`)
|
|
27
|
+
} else
|
|
28
|
+
webViewRef.injectJavaScript(`document.getElementById("${id}").${prop} = ${parseValue(value)}; true`)
|
|
29
|
+
return true
|
|
30
|
+
},
|
|
31
|
+
get(_, prop: string) {
|
|
32
|
+
if (prop === "style") return new Proxy({}, {
|
|
33
|
+
set(_, styleProp: string, value) {
|
|
34
|
+
webViewRef.injectJavaScript(`document.getElementById("${id}").style.${styleProp} = ${parseValue(value)}; true`)
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
if (prop === "insertAdjacentHTML") return (position: string, html: string) => {
|
|
39
|
+
webViewRef.injectJavaScript(`document.getElementById("${id}").insertAdjacentHTML('${position}', \`${html}\`); true`)
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
return undefined
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function parseValue(value: any) {
|
|
50
|
+
if (value !== true && value !== false) return `"${value}"`
|
|
51
|
+
return value
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
(globalThis as any).document = document;
|
|
55
|
+
registerRootComponent(() =>
|
|
56
|
+
<WebView
|
|
57
|
+
ref={ref => { webViewRef = ref }}
|
|
58
|
+
onMessage={onMessage}
|
|
59
|
+
source={require("./index.html")}
|
|
60
|
+
scrollEnabled={false}
|
|
61
|
+
overScrollMode={'content'}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "idv",
|
|
3
|
+
"main": "./index.tsx",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"setup": "scripts/setup.sh",
|
|
6
|
+
"ios": "scripts/ios.sh",
|
|
7
|
+
"android": "scripts/android.sh",
|
|
8
|
+
"start": "expo start"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@regulaforensics/idv": "3.2.23-beta",
|
|
12
|
+
"@regulaforensics/document-reader": "8.4.312-beta",
|
|
13
|
+
"@regulaforensics/face-sdk": "7.2.455-beta",
|
|
14
|
+
"@regulaforensics/document-reader-core-fullauthrfid": "8.4.271-beta",
|
|
15
|
+
"@regulaforensics/face-core-basic": "7.3.280-beta",
|
|
16
|
+
"@regulaforensics/idv-module-document-reader": "3.2.29-beta",
|
|
17
|
+
"@regulaforensics/idv-module-face": "3.2.28-beta",
|
|
18
|
+
"react-native": "^0.81.4",
|
|
19
|
+
"react-native-webview": "^13.16.0",
|
|
20
|
+
"@react-native/metro-config": "^0.81.1",
|
|
21
|
+
"react": "^19.1.1",
|
|
22
|
+
"@types/react": "^19.1.13",
|
|
23
|
+
"expo": "^54.0.7",
|
|
24
|
+
"expo-dev-client": "^6.0.12",
|
|
25
|
+
"expo-custom-assets": "^1.5.0",
|
|
26
|
+
"expo-build-properties": "^1.0.8",
|
|
27
|
+
"typescript": "5.9.2"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
adb reverse tcp:8081 tcp:8081 >/dev/null || :
|
|
4
|
+
if [[ $npm_config_o || $npm_config_open ]]; then
|
|
5
|
+
studio android || open -a 'Android Studio' android
|
|
6
|
+
# check if metro is already running
|
|
7
|
+
if ! pgrep -f "expo start" >/dev/null; then
|
|
8
|
+
watchman shutdown-server # fix potential errors
|
|
9
|
+
npm start
|
|
10
|
+
fi
|
|
11
|
+
else
|
|
12
|
+
expo run:android --device
|
|
13
|
+
fi
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
if [[ $npm_config_o || $npm_config_open ]]; then
|
|
4
|
+
open ios/IDV.xcworkspace
|
|
5
|
+
# check if metro is already running
|
|
6
|
+
if ! pgrep -f "expo start" > /dev/null; then
|
|
7
|
+
watchman shutdown-server # fix potential errors
|
|
8
|
+
npm start
|
|
9
|
+
fi
|
|
10
|
+
else
|
|
11
|
+
npx expo run:ios --device
|
|
12
|
+
fi
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
npm install
|
|
5
|
+
expo prebuild
|
|
6
|
+
|
|
7
|
+
mkdir -p android/app/src/main/assets/Regula
|
|
8
|
+
mv android/app/src/main/res/raw/regula.license android/app/src/main/assets/Regula/
|
|
9
|
+
mv android/app/src/main/res/raw/db.dat android/app/src/main/assets/Regula/
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
html,
|
|
2
|
+
body {
|
|
3
|
+
margin: 0;
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 99vh;
|
|
6
|
+
display: flex;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Prevent text selection */
|
|
12
|
+
* {
|
|
13
|
+
user-select: none !important;
|
|
14
|
+
-webkit-user-select: none !important;
|
|
15
|
+
-webkit-user-drag: none !important;
|
|
16
|
+
-webkit-touch-callout: none !important;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.column {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.row {
|
|
28
|
+
display: flex;
|
|
29
|
+
flex-direction: row;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.header {
|
|
35
|
+
text-align: center;
|
|
36
|
+
padding-top: 80px;
|
|
37
|
+
margin-top: -10px;
|
|
38
|
+
background-color: rgba(0, 0, 0, 0.03);
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
font-size: 18px;
|
|
41
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.sub-header {
|
|
45
|
+
background-color: rgba(0, 0, 0, 0.03);
|
|
46
|
+
width: 100%;
|
|
47
|
+
padding-top: 13px;
|
|
48
|
+
text-align: center;
|
|
49
|
+
font-weight: 550;
|
|
50
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.divider {
|
|
54
|
+
height: 1px;
|
|
55
|
+
background-color: rgba(0, 0, 0, 0.075);
|
|
56
|
+
margin-top: 13px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.scroll {
|
|
60
|
+
flex-grow: 1;
|
|
61
|
+
overflow-y: auto;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.no-scroll {
|
|
65
|
+
flex-grow: 1;
|
|
66
|
+
overflow-y: hidden;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.button {
|
|
70
|
+
width: 175px;
|
|
71
|
+
height: 40px;
|
|
72
|
+
margin: 5px;
|
|
73
|
+
margin-top: 10px;
|
|
74
|
+
background-color: #4285F4;
|
|
75
|
+
color: white;
|
|
76
|
+
border: none;
|
|
77
|
+
padding: 10px 20px;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
font-size: 16px;
|
|
80
|
+
border-radius: 100px;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
transition: all 0.3s ease;
|
|
83
|
+
user-select: none;
|
|
84
|
+
-webkit-user-select: none;
|
|
85
|
+
-moz-user-select: none;
|
|
86
|
+
-ms-user-select: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.button:active {
|
|
90
|
+
position: relative;
|
|
91
|
+
top: 1px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.text-button {
|
|
95
|
+
background: none;
|
|
96
|
+
border: none;
|
|
97
|
+
color: #2196f3;
|
|
98
|
+
font-size: 20px;
|
|
99
|
+
font-weight: bold;
|
|
100
|
+
padding: 5px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.text-button:active {
|
|
104
|
+
position: relative;
|
|
105
|
+
top: 1px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.radio {
|
|
109
|
+
align-items: baseline;
|
|
110
|
+
padding: 15px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
input[type="checkbox"] {
|
|
114
|
+
width: 20px;
|
|
115
|
+
height: 20px;
|
|
116
|
+
border: 2px solid black;
|
|
117
|
+
background-color: white;
|
|
118
|
+
display: inline-block;
|
|
119
|
+
position: relative;
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
input[type="text"] {
|
|
124
|
+
width: 173px;
|
|
125
|
+
height: 40px;
|
|
126
|
+
font-size: 15px;
|
|
127
|
+
margin: 5px;
|
|
128
|
+
border-radius: 100px;
|
|
129
|
+
padding-left: 10px;
|
|
130
|
+
padding-right: 10px;
|
|
131
|
+
margin-top: 10px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.progress-bar {
|
|
135
|
+
width: 75%;
|
|
136
|
+
padding: 3px;
|
|
137
|
+
margin-top: 40px;
|
|
138
|
+
background-color: #eee;
|
|
139
|
+
border-radius: 8px;
|
|
140
|
+
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#progress {
|
|
144
|
+
width: 0%;
|
|
145
|
+
height: 20px;
|
|
146
|
+
background-color: #4285F4;
|
|
147
|
+
border-radius: 5px;
|
|
148
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<div class="column" style="height: 100%">
|
|
2
|
+
<div class="column header">
|
|
3
|
+
<span id="status">Loading...</span>
|
|
4
|
+
<div class="column divider"></div>
|
|
5
|
+
</div>
|
|
6
|
+
<div id="main" class="column no-scroll">
|
|
7
|
+
<div class="row">
|
|
8
|
+
<div class="column" style="padding: 5px;">
|
|
9
|
+
<p>Portrait</p>
|
|
10
|
+
<img id="portrait-image" src="images/portrait.png" height="160px" width="120px">
|
|
11
|
+
</div>
|
|
12
|
+
<div class="column" style="padding: 5px;">
|
|
13
|
+
<p>Document image</p>
|
|
14
|
+
<img id="document-image" src="images/document.png" height="160px" width="200px">
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
<div id="scenario-container" class="column no-scroll" style="margin-top: 15px; background-color: rgba(0, 0, 0, 0.03);">
|
|
18
|
+
<div id="scenarios" class="scroll"></div>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="row" style="width: 360px; padding-top: 15px;">
|
|
21
|
+
<span id="rfid-checkbox-description" style="font-size: 18px;width: 100%;">Process rfid reading(unavailable)</span>
|
|
22
|
+
<input id="rfid-checkbox" type="checkbox" style="margin-left: auto;" disabled />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="row">
|
|
25
|
+
<button id="scan" class="button">Scan document</button>
|
|
26
|
+
<button id="recognize" class="button">Scan image</button>
|
|
27
|
+
</div>
|
|
28
|
+
<button id="connect" class="button" style="width: 360px; display: none;">Connect</button>
|
|
29
|
+
<div style="padding-top: 20px;"></div>
|
|
30
|
+
</div>
|
|
31
|
+
<div id="custom-rfid" class="column no-scroll" style="display: none;">
|
|
32
|
+
<span id="rfid-description" style="font-size: 22px">Place your phone on top of the NFC tag</span>
|
|
33
|
+
<div class="progress-bar">
|
|
34
|
+
<div id="progress"></div>
|
|
35
|
+
</div>
|
|
36
|
+
<button id="cancel-rfid" class="text-button" style="margin-top: 50px; padding-bottom: 100px;">X</button>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
package/ios/CVDIDV.swift
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import Flutter
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
let channelID = "flutter_idv"
|
|
5
|
+
var eventSinks: [String: FlutterEventSink] = [:]
|
|
6
|
+
|
|
7
|
+
private var args: [Any?] = []
|
|
8
|
+
|
|
9
|
+
func sendEvent(_ event: String, _ data: Any? = nil) {
|
|
10
|
+
DispatchQueue.main.async {
|
|
11
|
+
if let sink = eventSinks[event] {
|
|
12
|
+
sink(data.toSendable())
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func args<T>(_ index: Int) -> T {
|
|
18
|
+
return args[index] as! T
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func argsNullable<T>(_ index: Int) -> T? {
|
|
22
|
+
if (args[index] is NSNull) { return nil }
|
|
23
|
+
return args[index] as! T?
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public class FlutterIDVPlugin: NSObject, FlutterPlugin {
|
|
27
|
+
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
28
|
+
func setupEventChannel(_ eventId: String) {
|
|
29
|
+
let channel = FlutterEventChannel(name: "\(channelID)/event/\(eventId)", binaryMessenger: registrar.messenger())
|
|
30
|
+
channel.setStreamHandler(GenericStreamHandler(eventId))
|
|
31
|
+
}
|
|
32
|
+
setupEventChannel(didStartSessionEvent);
|
|
33
|
+
setupEventChannel(didEndSessionEvent);
|
|
34
|
+
setupEventChannel(didStartRestoreSessionEvent);
|
|
35
|
+
setupEventChannel(didContinueRemoteSessionEvent);
|
|
36
|
+
|
|
37
|
+
let channel = FlutterMethodChannel(name: "\(channelID)/method", binaryMessenger: registrar.messenger())
|
|
38
|
+
registrar.addMethodCallDelegate(FlutterIDVPlugin(), channel: channel)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
42
|
+
args = call.arguments as! [Any?]
|
|
43
|
+
methodCall(call.method, { data in result(data.toSendable()) })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class GenericStreamHandler: NSObject, FlutterStreamHandler {
|
|
48
|
+
private let eventId: String
|
|
49
|
+
|
|
50
|
+
public init(_ eventId: String) {
|
|
51
|
+
self.eventId = eventId
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
|
|
55
|
+
eventSinks[eventId] = eventSink
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public func onCancel(withArguments arguments: Any?) -> FlutterError? {
|
|
60
|
+
eventSinks[eventId] = nil
|
|
61
|
+
return nil
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let rootViewController: () -> UIViewController? = {
|
|
66
|
+
for window in UIApplication.shared.windows {
|
|
67
|
+
if window.isKeyWindow {
|
|
68
|
+
return window.rootViewController
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return nil
|
|
72
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import Flutter
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
let channelID = "flutter_idv"
|
|
5
|
+
var eventSinks: [String: FlutterEventSink] = [:]
|
|
6
|
+
|
|
7
|
+
private var args: [Any?] = []
|
|
8
|
+
|
|
9
|
+
func sendEvent(_ event: String, _ data: Any? = nil) {
|
|
10
|
+
DispatchQueue.main.async {
|
|
11
|
+
if let sink = eventSinks[event] {
|
|
12
|
+
sink(data.toSendable())
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func args<T>(_ index: Int) -> T {
|
|
18
|
+
return args[index] as! T
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func argsNullable<T>(_ index: Int) -> T? {
|
|
22
|
+
if (args[index] is NSNull) { return nil }
|
|
23
|
+
return args[index] as! T?
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public class FlutterIDVPlugin: NSObject, FlutterPlugin {
|
|
27
|
+
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
28
|
+
func setupEventChannel(_ eventId: String) {
|
|
29
|
+
let channel = FlutterEventChannel(name: "\(channelID)/event/\(eventId)", binaryMessenger: registrar.messenger())
|
|
30
|
+
channel.setStreamHandler(GenericStreamHandler(eventId))
|
|
31
|
+
}
|
|
32
|
+
setupEventChannel(didStartSessionEvent);
|
|
33
|
+
setupEventChannel(didEndSessionEvent);
|
|
34
|
+
setupEventChannel(didStartRestoreSessionEvent);
|
|
35
|
+
setupEventChannel(didContinueRemoteSessionEvent);
|
|
36
|
+
|
|
37
|
+
let channel = FlutterMethodChannel(name: "\(channelID)/method", binaryMessenger: registrar.messenger())
|
|
38
|
+
registrar.addMethodCallDelegate(FlutterIDVPlugin(), channel: channel)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
42
|
+
args = call.arguments as! [Any?]
|
|
43
|
+
methodCall(call.method, { data in result(data.toSendable()) })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class GenericStreamHandler: NSObject, FlutterStreamHandler {
|
|
48
|
+
private let eventId: String
|
|
49
|
+
|
|
50
|
+
public init(_ eventId: String) {
|
|
51
|
+
self.eventId = eventId
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
|
|
55
|
+
eventSinks[eventId] = eventSink
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public func onCancel(withArguments arguments: Any?) -> FlutterError? {
|
|
60
|
+
eventSinks[eventId] = nil
|
|
61
|
+
return nil
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let rootViewController: () -> UIViewController? = {
|
|
66
|
+
for window in UIApplication.shared.windows {
|
|
67
|
+
if window.isKeyWindow {
|
|
68
|
+
return window.rootViewController
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return nil
|
|
72
|
+
}
|