Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use PermissionState type from tauri, closes #979 #1701

Merged
merged 4 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changes/consolidate-permission-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"barcode-scanner": patch
"barcode-scanner-js": patch
"geolocation": patch
"geolocation-js": patch
"notification": patch
"notification-js": patch
---

Use `PermissionState` from the `tauri` crate, which now also includes a "prompt with rationale" variant for Android (returned when your app must explain to the user why it needs the permission).
5 changes: 5 additions & 0 deletions .changes/notification-permission-type-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"notification-js": patch
---

**Breaking change**: The permission type when using the API is now `'granted' | 'denied' | 'prompt' | 'prompt-with-rationale'` instead of `'granted' | 'denied' | 'default'` for consistency with Rust types. When using the `window.Notification` API the type is unchanged to match the Web API type.
2 changes: 1 addition & 1 deletion .changes/tauri-rc-7.md → .changes/tauri-rc-8.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@
"geolocation-js": patch
---

Update to tauri 2.0.0-rc.7
Update to tauri 2.0.0-rc.8
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ resolver = "2"
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
log = "0.4"
tauri = { version = "2.0.0-rc.7", default-features = false }
tauri = { version = "2.0.0-rc.8", default-features = false }
tauri-build = "2.0.0-rc.7"
tauri-plugin = "2.0.0-rc.7"
tauri-utils = "2.0.0-rc.7"
Expand Down
3 changes: 3 additions & 0 deletions plugins/barcode-scanner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ serde_json = { workspace = true }
tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }

[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
2 changes: 1 addition & 1 deletion plugins/barcode-scanner/api-iife.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions plugins/barcode-scanner/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

import { invoke } from "@tauri-apps/api/core";
import {
invoke,
requestPermissions as checkPermissions_,
checkPermissions as requestPermissions_,
} from "@tauri-apps/api/core";

export type PermissionState = "granted" | "denied" | "prompt";
export type { PermissionState } from "@tauri-apps/api/core";

export enum Format {
QRCode = "QR_CODE",
Expand Down Expand Up @@ -53,17 +57,17 @@ export async function cancel(): Promise<void> {
* Get permission state.
*/
export async function checkPermissions(): Promise<PermissionState> {
return await invoke<{ camera: PermissionState }>(
"plugin:barcode-scanner|check_permissions",
return await checkPermissions_<{ camera: PermissionState }>(
"barcode-scanner",
).then((r) => r.camera);
}

/**
* Request permissions to use the camera.
*/
export async function requestPermissions(): Promise<PermissionState> {
return await invoke<{ camera: PermissionState }>(
"plugin:barcode-scanner|request_permissions",
return await requestPermissions_<{ camera: PermissionState }>(
"barcode-scanner",
).then((r) => r.camera);
}

Expand Down
14 changes: 1 addition & 13 deletions plugins/geolocation/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use serde::{Deserialize, Serialize};
use specta::Type;
use tauri::plugin::PermissionState;

#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
Expand All @@ -24,19 +25,6 @@ pub struct PermissionStatus {
pub coarse_location: PermissionState,
}

/// Permission state.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
pub enum PermissionState {
/// Permission access has been granted.
Granted,
/// Permission access has been denied.
Denied,
/// The end user should be prompted for permission.
#[default]
Prompt,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
pub struct PositionOptions {
Expand Down
8 changes: 3 additions & 5 deletions plugins/notification/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
addPluginListener,
} from "@tauri-apps/api/core";

export type { PermissionState } from "@tauri-apps/api/core";

/**
* Options to send a notification.
*
Expand Down Expand Up @@ -304,9 +306,6 @@ interface Channel {
visibility?: Visibility;
}

/** Possible permission values. */
type Permission = "granted" | "denied" | "default";

/**
* Checks if the permission to send notifications is granted.
* @example
Expand Down Expand Up @@ -340,7 +339,7 @@ async function isPermissionGranted(): Promise<boolean> {
*
* @since 2.0.0
*/
async function requestPermission(): Promise<Permission> {
async function requestPermission(): Promise<NotificationPermission> {
return await window.Notification.requestPermission();
}

Expand Down Expand Up @@ -570,7 +569,6 @@ async function onAction(
export type {
Attachment,
Options,
Permission,
Action,
ActionType,
PendingNotification,
Expand Down
15 changes: 7 additions & 8 deletions plugins/notification/guest-js/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: MIT

import { invoke } from "@tauri-apps/api/core";
import type { PermissionState } from "@tauri-apps/api/core";
import type { Options } from "./index";

(function () {
Expand All @@ -19,23 +20,21 @@ import type { Options } from "./index";
return await invoke("plugin:notification|is_permission_granted");
}

function setNotificationPermission(
value: "granted" | "denied" | "default",
): void {
function setNotificationPermission(value: NotificationPermission): void {
permissionSettable = true;
// @ts-expect-error we can actually set this value on the webview
window.Notification.permission = value;
permissionSettable = false;
}

async function requestPermission(): Promise<
"default" | "denied" | "granted" | "prompt"
> {
return await invoke<"prompt" | "default" | "granted" | "denied">(
async function requestPermission(): Promise<PermissionState> {
return await invoke<PermissionState>(
"plugin:notification|request_permission",
).then((permission) => {
setNotificationPermission(
permission === "prompt" ? "default" : permission,
permission === "prompt" || permission === "prompt-with-rationale"
? "default"
: permission,
);
return permission;
});
Expand Down
6 changes: 3 additions & 3 deletions plugins/notification/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use tauri::{command, AppHandle, Runtime, State};
use tauri::{command, plugin::PermissionState, AppHandle, Runtime, State};

use crate::{Notification, NotificationData, PermissionState, Result};
use crate::{Notification, NotificationData, Result};

#[command]
pub(crate) async fn is_permission_granted<R: Runtime>(
Expand All @@ -15,7 +15,7 @@ pub(crate) async fn is_permission_granted<R: Runtime>(
match state {
PermissionState::Granted => Ok(Some(true)),
PermissionState::Denied => Ok(Some(false)),
PermissionState::Unknown => Ok(None),
PermissionState::Unknown | PermissionState::PromptWithRationale => Ok(None),
}
}

Expand Down
7 changes: 5 additions & 2 deletions plugins/notification/src/desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
// SPDX-License-Identifier: MIT

use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Runtime};
use tauri::{
plugin::{PermissionState, PluginApi},
AppHandle, Runtime,
};

use crate::{models::*, NotificationBuilder};
use crate::NotificationBuilder;

pub fn init<R: Runtime, C: DeserializeOwned>(
app: &AppHandle<R>,
Expand Down
2 changes: 1 addition & 1 deletion plugins/notification/src/init-iife.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plugins/notification/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use tauri::{
};

pub use models::*;
pub use tauri::plugin::PermissionState;

#[cfg(desktop)]
mod desktop;
Expand Down
2 changes: 1 addition & 1 deletion plugins/notification/src/mobile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use serde::{de::DeserializeOwned, Deserialize};
use tauri::{
plugin::{PluginApi, PluginHandle},
plugin::{PermissionState, PluginApi, PluginHandle},
AppHandle, Runtime,
};

Expand Down
45 changes: 0 additions & 45 deletions plugins/notification/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,51 +209,6 @@ impl Default for NotificationData {
}
}

/// Permission state.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionState {
/// Permission access has been granted.
Granted,
/// Permission access has been denied.
Denied,
/// Unknown state. Must request permission.
Unknown,
}

impl Display for PermissionState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Granted => write!(f, "granted"),
Self::Denied => write!(f, "denied"),
Self::Unknown => write!(f, "Unknown"),
}
}
}

impl Serialize for PermissionState {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_ref())
}
}

impl<'de> Deserialize<'de> for PermissionState {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
match s.to_lowercase().as_str() {
"granted" => Ok(Self::Granted),
"denied" => Ok(Self::Denied),
"prompt" => Ok(Self::Unknown),
_ => Err(DeError::custom(format!("unknown permission state '{s}'"))),
}
}
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PendingNotification {
Expand Down
Loading