feat: implement iOS

pull/829/head
Lucas Nogueira 2 years ago
parent 9ca0b64db1
commit 7f910323fc
No known key found for this signature in database
GPG Key ID: 3AFF5CAD641DD470

@ -40,5 +40,7 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSFaceIDUsageDescription</key>
<string>Biometric Test</string>
</dict>
</plist>

@ -2,15 +2,142 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import LocalAuthentication
import SwiftRs
import Tauri
import UIKit
import WebKit
class BiometricStatus {
let available: Bool
let biometryType: LABiometryType
let errorReason: String?
let errorCode: String?
init(available: Bool, biometryType: LABiometryType, errorReason: String?, errorCode: String?) {
self.available = available
self.biometryType = biometryType
self.errorReason = errorReason
self.errorCode = errorCode
}
}
class BiometricPlugin: Plugin {
@objc public func ping(_ invoke: Invoke) throws {
let value = invoke.getString("value")
invoke.resolve(["value": value as Any])
let authenticationErrorCodeMap: [Int: String] = [
0: "",
LAError.appCancel.rawValue: "appCancel",
LAError.authenticationFailed.rawValue: "authenticationFailed",
LAError.invalidContext.rawValue: "invalidContext",
LAError.notInteractive.rawValue: "notInteractive",
LAError.passcodeNotSet.rawValue: "passcodeNotSet",
LAError.systemCancel.rawValue: "systemCancel",
LAError.userCancel.rawValue: "userCancel",
LAError.userFallback.rawValue: "userFallback",
LAError.biometryLockout.rawValue: "biometryLockout",
LAError.biometryNotAvailable.rawValue: "biometryNotAvailable",
LAError.biometryNotEnrolled.rawValue: "biometryNotEnrolled",
]
var status: BiometricStatus!
public override func load(webview: WKWebView) {
let context = LAContext()
var error: NSError?
var available = context.canEvaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics, error: &error)
var reason: String? = nil
var errorCode: String? = nil
if available && context.biometryType == .faceID {
let entry = Bundle.main.infoDictionary?["NSFaceIDUsageDescription"] as? String
if entry == nil {
available = false
reason = "NSFaceIDUsageDescription is not in the app Info.plist"
errorCode = authenticationErrorCodeMap[LAError.biometryNotAvailable.rawValue] ?? ""
}
} else if !available, let error = error {
reason = error.localizedDescription
if let failureReason = error.localizedFailureReason {
reason = "\(reason ?? ""): \(failureReason)"
}
errorCode =
authenticationErrorCodeMap[error.code] ?? authenticationErrorCodeMap[
LAError.biometryNotAvailable.rawValue] ?? ""
}
self.status = BiometricStatus(
available: available,
biometryType: context.biometryType,
errorReason: reason,
errorCode: errorCode
)
}
@objc func status(_ invoke: Invoke) {
if self.status.available {
invoke.resolve([
"isAvailable": self.status.available,
"biometryType": self.status.biometryType.rawValue,
])
} else {
invoke.resolve([
"isAvailable": self.status.available,
"biometryType": self.status.biometryType.rawValue,
"reason": self.status.errorReason ?? "",
"code": self.status.errorCode ?? "",
])
}
}
@objc func authenticate(_ invoke: Invoke) {
guard self.status.available else {
invoke.reject(
self.status.errorReason ?? "",
self.status.errorCode ?? ""
)
return
}
guard let reason = invoke.getString("reason"), !reason.isEmpty else {
invoke.reject("`reason` is required")
return
}
let context = LAContext()
context.localizedFallbackTitle = invoke.getString("fallbackTitle")
context.localizedCancelTitle = invoke.getString("cancelTitle")
context.touchIDAuthenticationAllowableReuseDuration = 0
let allowDeviceCredential = invoke.getBool("allowDeviceCredential") ?? false
// force system default fallback title if an empty string is provided (the OS hides the fallback button in this case)
if allowDeviceCredential,
let fallbackTitle = context.localizedFallbackTitle,
fallbackTitle.isEmpty
{
context.localizedFallbackTitle = nil
}
context.evaluatePolicy(
allowDeviceCredential ? .deviceOwnerAuthentication : .deviceOwnerAuthenticationWithBiometrics,
localizedReason: reason
) { success, error in
if success {
invoke.resolve()
} else {
if let policyError = error as? LAError {
let code = self.authenticationErrorCodeMap[policyError.code.rawValue]
invoke.reject(policyError.localizedDescription, code)
} else {
invoke.reject(
"Unknown error",
self.authenticationErrorCodeMap[LAError.authenticationFailed.rawValue]
)
}
}
}
}
}

@ -138,7 +138,7 @@ importers:
version: 3.59.1
unocss:
specifier: ^0.53.1
version: 0.53.1(postcss@8.4.26)(rollup@3.26.3)(vite@4.4.4)
version: 0.53.1(postcss@8.4.31)(rollup@3.26.3)(vite@4.4.4)
vite:
specifier: ^4.3.9
version: 4.4.4
@ -1370,8 +1370,8 @@ packages:
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
dev: false
/@tauri-apps/cli-darwin-arm64@2.0.0-alpha.14:
resolution: {integrity: sha512-3K416rvSUt8el/fdPnSnHJOI2j5Os9Kyy17XZp+z3PKRRuo/iJPp9L3w0zFGYsh7C+ylzV4OBUSVTi+e+gO5qA==}
/@tauri-apps/cli-darwin-arm64@2.0.0-alpha.15:
resolution: {integrity: sha512-PxmXanPZtSLtDJyEoj538//cauKoyc/sExAO0fTwJ+o8y2NZB/qQfpbdMIloQQnusRwh+6RjOr0Zs5Y6nBhO5Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@ -1379,8 +1379,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-darwin-x64@2.0.0-alpha.14:
resolution: {integrity: sha512-aLEUGG8Z0UpTENe4/UG6DU8bnB2e1uxyxYvcmFKrHv+EAtR9nLH14alBxPl2K54YXy3JLR4bKROW15a/sFrX9g==}
/@tauri-apps/cli-darwin-x64@2.0.0-alpha.15:
resolution: {integrity: sha512-IcJGd6mIwQQ9xQhmkNHWjERJoGYpZEknhWeU8a2MnuosX8c9O/zmKWey4ol2KPrumMdmbh8QZzPyh9986GmnUA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@ -1388,8 +1388,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-alpha.14:
resolution: {integrity: sha512-Lu7unNvurBccxfHIaUQ0gPgUioTkQBMtWGrqO/auZ/JbjPR1W2eBlRwVNXf+nBWX9HwomPR3YD5yZuZmzxRV2g==}
/@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-alpha.15:
resolution: {integrity: sha512-zD88WJaEZ49BzgmIgj0RVFF/zKrB+NYHEDwmvt60eehQCPfnMuE5/asj0Gp4YJRZ07jZzDfzMCdTGbwWsLnZEA==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
@ -1397,8 +1397,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm64-gnu@2.0.0-alpha.14:
resolution: {integrity: sha512-g8HkwKvAsWLLMJzPup7B1BCilYmXKwXdee7sf8QFbaIUSccR8i5pXLK5N/quKw5lmldYgFveEyuW9Qs8RgTYnQ==}
/@tauri-apps/cli-linux-arm64-gnu@2.0.0-alpha.15:
resolution: {integrity: sha512-rmHIZsEb1RT5Ny4hjeK7LC3MRqWLZBfiKC29DX5UzhJySb9g0UeR2esx1PMX6kuU8DOC0RBr8xpEmoTNMtFJ3Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -1406,8 +1406,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-arm64-musl@2.0.0-alpha.14:
resolution: {integrity: sha512-ag4UuX6zg7vmBFWmg9ChyiJI7GTMkc8tjr/qobd3Lg9ddmjnVWwLUHt6v1kYhXiU7iLPD5DYDIjU8x/POc3hSA==}
/@tauri-apps/cli-linux-arm64-musl@2.0.0-alpha.15:
resolution: {integrity: sha512-l3oix62YRE/vjpdxWq38NwZ61yg1vCcGAdfHaSt+Um/ojZHudekchQx56sEh7IMxsHxEtipxZdNEb1WsyAa5JA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@ -1415,8 +1415,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-x64-gnu@2.0.0-alpha.14:
resolution: {integrity: sha512-+CviROc4fzrGqqyHQXh3uc2dGr/oYr19I8r2k+LJ2CDfmtj7CbNd/oC5oehHbHdw1oGFKuDPudrTGvzdRNygYA==}
/@tauri-apps/cli-linux-x64-gnu@2.0.0-alpha.15:
resolution: {integrity: sha512-m7jWcyA4URtfvM4ySN1G3mO6gQP0qULawP9henks/bcrx2DU5xFP7WFxUxQhlWEtjwtJOI/NscQfzUEE6igs+Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -1424,8 +1424,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-linux-x64-musl@2.0.0-alpha.14:
resolution: {integrity: sha512-aCP51HOAQXgVhyPHXKy627bYVRkNnpCvSU3L03pYV8YDoGo+veeuek5UiW7PlNdwx52B/yC3Jz7Dr3gEbFimfQ==}
/@tauri-apps/cli-linux-x64-musl@2.0.0-alpha.15:
resolution: {integrity: sha512-Xa4JTnYbebnLAMY7JdNuUDgnv/wWA4a8fbg1288kckq3aRXb+ETTV3Tlr/rnsx1s3TpECmSkXjTIvNecvsqjTA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@ -1433,8 +1433,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-arm64-msvc@2.0.0-alpha.14:
resolution: {integrity: sha512-b6Ei5ERUF0KS1bttM7i6U62GmjIvlgK03XZqvL/KLNvUfqRMu8F7JA1ejSExgTxhEhKSWA768HiTXpXk2GjFFw==}
/@tauri-apps/cli-win32-arm64-msvc@2.0.0-alpha.15:
resolution: {integrity: sha512-YOKmqenjwQkwBesJ3rYWnJ2renRhPAWIdIoTRhMnDacRk28mMWizsGWLT7ZDbYi7AHMR6jMk0eYgAKKd+uBjFg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@ -1442,8 +1442,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-ia32-msvc@2.0.0-alpha.14:
resolution: {integrity: sha512-TDkvu5pd37bKxZ6N+BqngCNGcefY7aHxyJ3BdBGxF+wRMjEMh70mgEXk8i0uM/aUi/Kl1GQoO6xJfUDlIMPXOA==}
/@tauri-apps/cli-win32-ia32-msvc@2.0.0-alpha.15:
resolution: {integrity: sha512-Z8yMn6jKSCN8atdWwIzHNoqd+kS684RpgFoZhftcxtqYDXfSgU63KLasKu2Wu12a/7TmXqHGHlEBst9nD2VSLw==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@ -1451,8 +1451,8 @@ packages:
dev: true
optional: true
/@tauri-apps/cli-win32-x64-msvc@2.0.0-alpha.14:
resolution: {integrity: sha512-9yfoEe2RSykKr5hCifVAL5o0gHXgRCS+Wo+RJjQ9L2+QHY7XPLZYAhj/h8jdcAdRveyIQwat3k7wl+SW87v1eg==}
/@tauri-apps/cli-win32-x64-msvc@2.0.0-alpha.15:
resolution: {integrity: sha512-fcIXUgI1PKeAj2cp7vvXDssWcXxhauCyvtJPmaCVl5pk+5aJlOSx5TPjv0BRyaIO8l4IPW1IakvTRcDvEAQHRw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@ -1461,20 +1461,20 @@ packages:
optional: true
/@tauri-apps/cli@2.0.0-alpha.15:
resolution: {integrity: sha512-4/IQwN5S94D6LTXQrDWbSea0pGb9TTC4BwxHUFmhep4NjFxms161v1zadAUIsq/N2x6WwCBGrsdq9SIkgKv49Q==, tarball: https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-alpha.15.tgz}
resolution: {integrity: sha512-eMMD5MXJDt/j37IGBP501Ov3lux+mrA1WT4EjTk+Oaw4t8fb8ncb7yvbVZ6qyzVo7WHplIGKRzyV0CyZXZropQ==}
engines: {node: '>= 10'}
hasBin: true
optionalDependencies:
'@tauri-apps/cli-darwin-arm64': 2.0.0-alpha.14
'@tauri-apps/cli-darwin-x64': 2.0.0-alpha.14
'@tauri-apps/cli-linux-arm-gnueabihf': 2.0.0-alpha.14
'@tauri-apps/cli-linux-arm64-gnu': 2.0.0-alpha.14
'@tauri-apps/cli-linux-arm64-musl': 2.0.0-alpha.14
'@tauri-apps/cli-linux-x64-gnu': 2.0.0-alpha.14
'@tauri-apps/cli-linux-x64-musl': 2.0.0-alpha.14
'@tauri-apps/cli-win32-arm64-msvc': 2.0.0-alpha.14
'@tauri-apps/cli-win32-ia32-msvc': 2.0.0-alpha.14
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-alpha.14
'@tauri-apps/cli-darwin-arm64': 2.0.0-alpha.15
'@tauri-apps/cli-darwin-x64': 2.0.0-alpha.15
'@tauri-apps/cli-linux-arm-gnueabihf': 2.0.0-alpha.15
'@tauri-apps/cli-linux-arm64-gnu': 2.0.0-alpha.15
'@tauri-apps/cli-linux-arm64-musl': 2.0.0-alpha.15
'@tauri-apps/cli-linux-x64-gnu': 2.0.0-alpha.15
'@tauri-apps/cli-linux-x64-musl': 2.0.0-alpha.15
'@tauri-apps/cli-win32-arm64-msvc': 2.0.0-alpha.15
'@tauri-apps/cli-win32-ia32-msvc': 2.0.0-alpha.15
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-alpha.15
dev: true
/@tauri-apps/toml@2.2.4:
@ -1775,7 +1775,7 @@ packages:
sirv: 2.0.3
dev: true
/@unocss/postcss@0.53.1(postcss@8.4.26):
/@unocss/postcss@0.53.1(postcss@8.4.31):
resolution: {integrity: sha512-vuUj/Tsvn6/YlEYp/AezyjoZLNBp+YomwpQctNZAC5ged5cqKfaw+oISw1LYzi/48Ynx7cV/4XqikApuozrvRQ==}
engines: {node: '>=14'}
peerDependencies:
@ -1786,7 +1786,7 @@ packages:
css-tree: 2.3.1
fast-glob: 3.3.0
magic-string: 0.30.1
postcss: 8.4.26
postcss: 8.4.31
dev: true
/@unocss/preset-attributify@0.53.1:
@ -2185,7 +2185,7 @@ packages:
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.2
fsevents: 2.3.3
dev: true
/cidr-regex@4.0.3:
@ -3043,8 +3043,8 @@ packages:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
/fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
/fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
requiresBuild: true
@ -4103,6 +4103,15 @@ packages:
source-map-js: 1.0.2
dev: true
/postcss@8.4.31:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.6
picocolors: 1.0.0
source-map-js: 1.0.2
dev: true
/prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@ -4236,7 +4245,7 @@ packages:
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
optionalDependencies:
fsevents: 2.3.2
fsevents: 2.3.3
dev: true
/run-async@2.4.1:
@ -4841,7 +4850,7 @@ packages:
'@types/unist': 2.0.7
dev: true
/unocss@0.53.1(postcss@8.4.26)(rollup@3.26.3)(vite@4.4.4):
/unocss@0.53.1(postcss@8.4.31)(rollup@3.26.3)(vite@4.4.4):
resolution: {integrity: sha512-0lRblA8hX7VUu5dywbcStzm590Iz5ahSJGsMNKNH3+u9C7AfJcKT8epxjkIkJWQBNJLD5vsao4SuuhLWB7eMQQ==}
engines: {node: '>=14'}
peerDependencies:
@ -4854,7 +4863,7 @@ packages:
'@unocss/cli': 0.53.1(rollup@3.26.3)
'@unocss/core': 0.53.1
'@unocss/extractor-arbitrary-variants': 0.53.1
'@unocss/postcss': 0.53.1(postcss@8.4.26)
'@unocss/postcss': 0.53.1(postcss@8.4.31)
'@unocss/preset-attributify': 0.53.1
'@unocss/preset-icons': 0.53.1
'@unocss/preset-mini': 0.53.1
@ -4932,7 +4941,7 @@ packages:
postcss: 8.4.26
rollup: 3.26.3
optionalDependencies:
fsevents: 2.3.2
fsevents: 2.3.3
dev: true
/vite@4.4.4:
@ -4967,7 +4976,7 @@ packages:
postcss: 8.4.26
rollup: 3.26.3
optionalDependencies:
fsevents: 2.3.2
fsevents: 2.3.3
dev: true
/vitefu@0.2.4(vite@4.4.4):

Loading…
Cancel
Save