diff --git a/Cargo.lock b/Cargo.lock index 3ea929e8..499ccbc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5699,6 +5699,7 @@ dependencies = [ "log", "serde", "serde_json", + "serde_repr", "tauri", "tauri-build", "thiserror", diff --git a/examples/api/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/api/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json index 90eea7ec..dd3b8bcc 100644 --- a/examples/api/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/examples/api/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,116 +1,116 @@ { - "images" : [ + "images": [ { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "AppIcon-20x20@2x.png", - "scale" : "2x" + "size": "20x20", + "idiom": "iphone", + "filename": "AppIcon-20x20@2x.png", + "scale": "2x" }, { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "AppIcon-20x20@3x.png", - "scale" : "3x" + "size": "20x20", + "idiom": "iphone", + "filename": "AppIcon-20x20@3x.png", + "scale": "3x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "AppIcon-29x29@2x-1.png", - "scale" : "2x" + "size": "29x29", + "idiom": "iphone", + "filename": "AppIcon-29x29@2x-1.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "AppIcon-29x29@3x.png", - "scale" : "3x" + "size": "29x29", + "idiom": "iphone", + "filename": "AppIcon-29x29@3x.png", + "scale": "3x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "AppIcon-40x40@2x.png", - "scale" : "2x" + "size": "40x40", + "idiom": "iphone", + "filename": "AppIcon-40x40@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "AppIcon-40x40@3x.png", - "scale" : "3x" + "size": "40x40", + "idiom": "iphone", + "filename": "AppIcon-40x40@3x.png", + "scale": "3x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "AppIcon-60x60@2x.png", - "scale" : "2x" + "size": "60x60", + "idiom": "iphone", + "filename": "AppIcon-60x60@2x.png", + "scale": "2x" }, { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "AppIcon-60x60@3x.png", - "scale" : "3x" + "size": "60x60", + "idiom": "iphone", + "filename": "AppIcon-60x60@3x.png", + "scale": "3x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "AppIcon-20x20@1x.png", - "scale" : "1x" + "size": "20x20", + "idiom": "ipad", + "filename": "AppIcon-20x20@1x.png", + "scale": "1x" }, { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "AppIcon-20x20@2x-1.png", - "scale" : "2x" + "size": "20x20", + "idiom": "ipad", + "filename": "AppIcon-20x20@2x-1.png", + "scale": "2x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "AppIcon-29x29@1x.png", - "scale" : "1x" + "size": "29x29", + "idiom": "ipad", + "filename": "AppIcon-29x29@1x.png", + "scale": "1x" }, { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "AppIcon-29x29@2x.png", - "scale" : "2x" + "size": "29x29", + "idiom": "ipad", + "filename": "AppIcon-29x29@2x.png", + "scale": "2x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "AppIcon-40x40@1x.png", - "scale" : "1x" + "size": "40x40", + "idiom": "ipad", + "filename": "AppIcon-40x40@1x.png", + "scale": "1x" }, { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "AppIcon-40x40@2x-1.png", - "scale" : "2x" + "size": "40x40", + "idiom": "ipad", + "filename": "AppIcon-40x40@2x-1.png", + "scale": "2x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "AppIcon-76x76@1x.png", - "scale" : "1x" + "size": "76x76", + "idiom": "ipad", + "filename": "AppIcon-76x76@1x.png", + "scale": "1x" }, { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "AppIcon-76x76@2x.png", - "scale" : "2x" + "size": "76x76", + "idiom": "ipad", + "filename": "AppIcon-76x76@2x.png", + "scale": "2x" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "AppIcon-83.5x83.5@2x.png", - "scale" : "2x" + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "AppIcon-83.5x83.5@2x.png", + "scale": "2x" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "AppIcon-512@2x.png", - "scale" : "1x" + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "AppIcon-512@2x.png", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/examples/api/src-tauri/gen/apple/Assets.xcassets/Contents.json b/examples/api/src-tauri/gen/apple/Assets.xcassets/Contents.json index da4a164c..97a8662e 100644 --- a/examples/api/src-tauri/gen/apple/Assets.xcassets/Contents.json +++ b/examples/api/src-tauri/gen/apple/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/plugins/biometric/Cargo.toml b/plugins/biometric/Cargo.toml index facc80b8..89835c3d 100644 --- a/plugins/biometric/Cargo.toml +++ b/plugins/biometric/Cargo.toml @@ -20,3 +20,4 @@ serde_json = { workspace = true } tauri = { workspace = true } log = { workspace = true } thiserror = { workspace = true } +serde_repr = "0.1" diff --git a/plugins/biometric/guest-js/index.ts b/plugins/biometric/guest-js/index.ts index 6b1d80ff..c15256bf 100644 --- a/plugins/biometric/guest-js/index.ts +++ b/plugins/biometric/guest-js/index.ts @@ -2,4 +2,52 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -export async function doSomething() {} +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} + +export enum BiometryType { + None = 0, + TouchID = 1, + FaceID = 2, +} + +export interface Status { + isAvailable: boolean; + biometryType: BiometryType; + error?: string; + errorCode?: + | "appCancel" + | "authenticationFailed" + | "invalidContext" + | "notInteractive" + | "passcodeNotSet" + | "systemCancel" + | "userCancel" + | "userFallback" + | "biometryLockout" + | "biometryNotAvailable" + | "biometryNotEnrolled"; +} + +export interface AuthOptions { + fallbackTitle?: string; + cancelTitle?: string; + allowDeviceCredential?: boolean; +} + +export async function checkStatus(): Promise { + return window.__TAURI_INVOKE__("plugin:biometry|status"); +} + +export async function authenticate( + reason: string, + options?: AuthOptions, +): Promise { + return window.__TAURI_INVOKE__("plugin:biometry|authenticate", { + reason, + ...options, + }); +} diff --git a/plugins/biometric/ios/Sources/BiometricPlugin.swift b/plugins/biometric/ios/Sources/BiometricPlugin.swift index ff3113f9..602da7f2 100644 --- a/plugins/biometric/ios/Sources/BiometricPlugin.swift +++ b/plugins/biometric/ios/Sources/BiometricPlugin.swift @@ -84,8 +84,8 @@ class BiometricPlugin: Plugin { invoke.resolve([ "isAvailable": self.status.available, "biometryType": self.status.biometryType.rawValue, - "reason": self.status.errorReason ?? "", - "code": self.status.errorCode ?? "", + "error": self.status.errorReason ?? "", + "errorCode": self.status.errorCode ?? "", ]) } } diff --git a/plugins/biometric/src/api-iife.js b/plugins/biometric/src/api-iife.js index e14c806b..8db1f666 100644 --- a/plugins/biometric/src/api-iife.js +++ b/plugins/biometric/src/api-iife.js @@ -1 +1 @@ -if("__TAURI__"in window){var __TAURI_BIOMETRIC__=function(_){"use strict";return _.doSomething=async function(){},_}({});Object.defineProperty(window.__TAURI__,"biometric",{value:__TAURI_BIOMETRIC__})} +if("__TAURI__"in window){var __TAURI_BIOMETRIC__=function(e){"use strict";var _;return e.BiometryType=void 0,(_=e.BiometryType||(e.BiometryType={}))[_.None=0]="None",_[_.TouchID=1]="TouchID",_[_.FaceID=2]="FaceID",e.authenticate=async function(e,_){return window.__TAURI_INVOKE__("plugin:biometry|authenticate",{reason:e,..._})},e.checkStatus=async function(){return window.__TAURI_INVOKE__("plugin:biometry|status")},e}({});Object.defineProperty(window.__TAURI__,"biometric",{value:__TAURI_BIOMETRIC__})} diff --git a/plugins/biometric/src/commands.rs b/plugins/biometric/src/commands.rs deleted file mode 100644 index 99cc0eaf..00000000 --- a/plugins/biometric/src/commands.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use tauri::{AppHandle, command, Runtime, Window}; - -use crate::Result; - -#[command] -pub(crate) async fn execute( - _app: AppHandle, - _window: Window, -) -> Result { - Ok("success".to_string()) -} diff --git a/plugins/biometric/src/lib.rs b/plugins/biometric/src/lib.rs index 6f6f8410..8b0d472d 100644 --- a/plugins/biometric/src/lib.rs +++ b/plugins/biometric/src/lib.rs @@ -4,6 +4,7 @@ #![cfg(mobile)] +use serde::Serialize; use tauri::{ plugin::{Builder, PluginHandle, TauriPlugin}, Manager, Runtime, @@ -11,7 +12,6 @@ use tauri::{ pub use models::*; -mod commands; mod error; mod models; @@ -26,10 +26,21 @@ tauri::ios_plugin_binding!(init_plugin_biometric); /// Access to the biometric APIs. pub struct Biometric(PluginHandle); +#[derive(Serialize)] +struct AuthenticatePayload { + reason: String, + #[serde(flatten)] + options: AuthOptions, +} + impl Biometric { - pub fn ping(&self, payload: PingRequest) -> crate::Result { + pub fn status(&self) -> crate::Result { + self.0.run_mobile_plugin("status", ()).map_err(Into::into) + } + + pub fn authenticate(&self, reason: String, options: AuthOptions) -> crate::Result<()> { self.0 - .run_mobile_plugin("ping", payload) + .run_mobile_plugin("authenticate", AuthenticatePayload { reason, options }) .map_err(Into::into) } } @@ -49,7 +60,6 @@ impl> crate::BiometricExt for T { pub fn init() -> TauriPlugin { Builder::new("biometric") .js_init_script(include_str!("api-iife.js").to_string()) - .invoke_handler(tauri::generate_handler![commands::execute]) .setup(|app, api| { #[cfg(target_os = "android")] let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "BiometricPlugin")?; diff --git a/plugins/biometric/src/models.rs b/plugins/biometric/src/models.rs index d50dcf91..42e84475 100644 --- a/plugins/biometric/src/models.rs +++ b/plugins/biometric/src/models.rs @@ -4,14 +4,27 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Serialize)] +#[derive(Debug, Default, Serialize)] #[serde(rename_all = "camelCase")] -pub struct PingRequest { - pub value: Option, +pub struct AuthOptions { + pub fallback_title: Option, + pub cancel_title: Option, + pub allow_device_credential: bool, } -#[derive(Debug, Clone, Default, Deserialize)] +#[derive(Debug, Clone, serde_repr::Deserialize_repr)] +#[repr(u8)] +pub enum BiometryType { + None = 0, + TouchID = 1, + FaceID = 2, +} + +#[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PingResponse { - pub value: Option, +pub struct Status { + pub is_available: bool, + pub biometry_type: BiometryType, + pub error: Option, + pub error_code: Option, }