Skip to content

Commit 20ab986

Browse files
committed
feat: dialog add stop_accessing_path command
^ Conflicts: ^ plugins/dialog/ios/Sources/DialogPlugin.swift ^ plugins/dialog/src/commands.rs ^ plugins/dialog/src/mobile.rs
1 parent 449247d commit 20ab986

File tree

10 files changed

+151
-15
lines changed

10 files changed

+151
-15
lines changed

plugins/dialog/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// SPDX-License-Identifier: MIT
44

5-
const COMMANDS: &[&str] = &["open", "save", "message", "ask", "confirm"];
5+
const COMMANDS: &[&str] = &["open", "save", "stop_accessing_path", "message", "ask", "confirm"];
66

77
fn main() {
88
let result = tauri_plugin::Builder::new(COMMANDS)

plugins/dialog/guest-js/index.ts

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,31 @@
44

55
import { invoke } from '@tauri-apps/api/core'
66

7+
class Path {
8+
public path: string
9+
constructor(path: string) {
10+
this.path = path
11+
}
12+
13+
destroy() {
14+
return invoke('plugin:dialog|stop-accessing-path', { path: this.path })
15+
}
16+
17+
toPath() {
18+
return this.path
19+
}
20+
21+
toString() {
22+
return this.toPath()
23+
}
24+
25+
toJSON() {
26+
return {
27+
path: this.path
28+
}
29+
}
30+
}
31+
732
/**
833
* Extension filters for the file dialog.
934
*
@@ -224,13 +249,7 @@ interface ConfirmDialogOptions {
224249
cancelLabel?: string
225250
}
226251

227-
type OpenDialogReturn<T extends OpenDialogOptions> = T['directory'] extends true
228-
? T['multiple'] extends true
229-
? string[] | null
230-
: string | null
231-
: T['multiple'] extends true
232-
? string[] | null
233-
: string | null
252+
type OpenDialogReturn<T extends OpenDialogOptions> = T['multiple'] extends true ? Path[] | null : Path | null
234253

235254
/**
236255
* Open a file/directory selection dialog.
@@ -295,7 +314,17 @@ async function open<T extends OpenDialogOptions>(
295314
Object.freeze(options)
296315
}
297316

298-
return await invoke('plugin:dialog|open', { options })
317+
const path = await invoke<string[] | string | null>('plugin:dialog|open', { options })
318+
319+
if (Array.isArray(path)) {
320+
return path.map((p) => new Path(p))
321+
}
322+
323+
if (!path) {
324+
return null
325+
}
326+
327+
return new Path(path)
299328
}
300329

301330
/**
@@ -326,12 +355,18 @@ async function open<T extends OpenDialogOptions>(
326355
*
327356
* @since 2.0.0
328357
*/
329-
async function save(options: SaveDialogOptions = {}): Promise<string | null> {
358+
async function save(options: SaveDialogOptions = {}): Promise<Path | null> {
330359
if (typeof options === 'object') {
331360
Object.freeze(options)
332361
}
333362

334-
return await invoke('plugin:dialog|save', { options })
363+
const path = await invoke<string | null>('plugin:dialog|save', { options })
364+
365+
if (!path) {
366+
return null
367+
}
368+
369+
return new Path(path)
335370
}
336371

337372
/**

plugins/dialog/ios/Sources/DialogPlugin.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ struct SaveFileDialogOptions: Decodable {
3939
var defaultPath: String?
4040
}
4141

42+
struct StopAccessingPathOptions: Decodable {
43+
var path: URL
44+
}
45+
4246
class DialogPlugin: Plugin {
4347

4448
var filePickerController: FilePickerController!
@@ -75,6 +79,7 @@ class DialogPlugin: Plugin {
7579
onFilePickerResult = { (event: FilePickerEvent) -> Void in
7680
switch event {
7781
case .selected(let urls):
82+
urls.forEach { $0.startAccessingSecurityScopedResource() }
7883
invoke.resolve(["files": urls])
7984
case .cancelled:
8085
invoke.resolve(["files": nil])
@@ -171,6 +176,12 @@ class DialogPlugin: Plugin {
171176
}
172177
}
173178

179+
@objc public func stopAccessingPath(_ invoke: Invoke) throws {
180+
let args = try invoke.parseArgs(StopAccessingPathOptions.self)
181+
args.path.stopAccessingSecurityScopedResource()
182+
invoke.resolve()
183+
}
184+
174185
private func presentViewController(_ viewControllerToPresent: UIViewController) {
175186
self.manager.viewController?.present(viewControllerToPresent, animated: true, completion: nil)
176187
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Automatically generated - DO NOT EDIT!
2+
3+
"$schema" = "../../schemas/schema.json"
4+
5+
[[permission]]
6+
identifier = "allow-stop-accessing-path"
7+
description = "Enables the stop_accessing_path command without any pre-configured scope."
8+
commands.allow = ["stop_accessing_path"]
9+
10+
[[permission]]
11+
identifier = "deny-stop-accessing-path"
12+
description = "Denies the stop_accessing_path command without any pre-configured scope."
13+
commands.deny = ["stop_accessing_path"]

plugins/dialog/permissions/autogenerated/reference.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ All dialog types are enabled.
1414
- `allow-message`
1515
- `allow-save`
1616
- `allow-open`
17+
- `allow-stop-accessing-path`
1718

1819
## Permission Table
1920

@@ -151,6 +152,32 @@ Enables the save command without any pre-configured scope.
151152

152153
Denies the save command without any pre-configured scope.
153154

155+
</td>
156+
</tr>
157+
158+
<tr>
159+
<td>
160+
161+
`dialog:allow-stop-accessing-path`
162+
163+
</td>
164+
<td>
165+
166+
Enables the stop_accessing_path command without any pre-configured scope.
167+
168+
</td>
169+
</tr>
170+
171+
<tr>
172+
<td>
173+
174+
`dialog:deny-stop-accessing-path`
175+
176+
</td>
177+
<td>
178+
179+
Denies the stop_accessing_path command without any pre-configured scope.
180+
154181
</td>
155182
</tr>
156183
</table>

plugins/dialog/permissions/default.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ permissions = [
1717
"allow-message",
1818
"allow-save",
1919
"allow-open",
20+
"allow-stop-accessing-path"
2021
]

plugins/dialog/permissions/schemas/schema.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,22 @@
355355
"markdownDescription": "Denies the save command without any pre-configured scope."
356356
},
357357
{
358-
"description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`",
358+
"description": "Enables the stop_accessing_path command without any pre-configured scope.",
359+
"type": "string",
360+
"const": "allow-stop-accessing-path",
361+
"markdownDescription": "Enables the stop_accessing_path command without any pre-configured scope."
362+
},
363+
{
364+
"description": "Denies the stop_accessing_path command without any pre-configured scope.",
365+
"type": "string",
366+
"const": "deny-stop-accessing-path",
367+
"markdownDescription": "Denies the stop_accessing_path command without any pre-configured scope."
368+
},
369+
{
370+
"description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`\n- `allow-stop-accessing-path`",
359371
"type": "string",
360372
"const": "default",
361-
"markdownDescription": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`"
373+
"markdownDescription": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`\n- `allow-stop-accessing-path`"
362374
}
363375
]
364376
}

plugins/dialog/src/commands.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use tauri_plugin_fs::FsExt;
1111
use crate::{
1212
Dialog, FileDialogBuilder, FilePath, MessageDialogBuilder, MessageDialogButtons,
1313
MessageDialogKind, MessageDialogResult, Result, CANCEL, NO, OK, YES,
14+
StopAccessingPath
1415
};
1516

1617
#[derive(Serialize)]
@@ -241,6 +242,11 @@ pub(crate) async fn save<R: Runtime>(
241242
Ok(path.map(|p| p.simplified()))
242243
}
243244

245+
#[command]
246+
pub fn stop_accessing_path(_p: StopAccessingPath) -> bool {
247+
true
248+
}
249+
244250
fn message_dialog<R: Runtime>(
245251
#[allow(unused_variables)] window: Window<R>,
246252
dialog: State<'_, Dialog<R>>,

plugins/dialog/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
1010
)]
1111

12-
use serde::Serialize;
12+
use serde::{Deserialize, Serialize};
1313
use tauri::{
1414
plugin::{Builder, TauriPlugin},
1515
Manager, Runtime,
@@ -180,6 +180,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
180180
.invoke_handler(tauri::generate_handler![
181181
commands::open,
182182
commands::save,
183+
commands::stop_accessing_path,
183184
commands::message,
184185
commands::ask,
185186
commands::confirm
@@ -382,6 +383,11 @@ pub(crate) struct FileDialogPayload<'a> {
382383
multiple: bool,
383384
}
384385

386+
#[derive(Debug, Serialize, Deserialize)]
387+
pub struct StopAccessingPath {
388+
path: FilePath,
389+
}
390+
385391
// raw window handle :(
386392
unsafe impl<R: Runtime> Send for FileDialogBuilder<R> {}
387393

@@ -611,6 +617,10 @@ impl<R: Runtime> FileDialogBuilder<R> {
611617
pub fn save_file<F: FnOnce(Option<FilePath>) + Send + 'static>(self, f: F) {
612618
save_file(self, f)
613619
}
620+
621+
pub fn stop_accessing_path(self, p: StopAccessingPath) -> bool {
622+
stop_accessing_path(self, p)
623+
}
614624
}
615625

616626
/// Blocking APIs.
@@ -723,4 +733,8 @@ impl<R: Runtime> FileDialogBuilder<R> {
723733
pub fn blocking_save_file(self) -> Option<FilePath> {
724734
blocking_fn!(self, save_file)
725735
}
736+
737+
pub fn blocking_stop_accessing_path(self, p: StopAccessingPath) -> bool {
738+
self.stop_accessing_path(p)
739+
}
726740
}

plugins/dialog/src/mobile.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use tauri::{
88
AppHandle, Runtime,
99
};
1010

11-
use crate::{FileDialogBuilder, FilePath, MessageDialogBuilder, MessageDialogResult};
11+
use crate::{FileDialogBuilder, FilePath, MessageDialogBuilder, MessageDialogResult, StopAccessingPath};
1212

1313
#[cfg(target_os = "android")]
1414
const PLUGIN_IDENTIFIER: &str = "app.tauri.dialog";
@@ -105,6 +105,23 @@ pub fn save_file<R: Runtime, F: FnOnce(Option<FilePath>) + Send + 'static>(
105105
});
106106
}
107107

108+
#[allow(unused_variables)]
109+
pub fn stop_accessing_path<R: Runtime>(dialog: FileDialogBuilder<R>, p: StopAccessingPath) -> bool {
110+
#[cfg(target_os = "ios")]
111+
{
112+
let res = dialog
113+
.dialog
114+
.0
115+
.run_mobile_plugin::<()>("stopAccessingPath", p);
116+
117+
if let Err(_) = res {
118+
return false
119+
}
120+
}
121+
122+
true
123+
}
124+
108125
#[derive(Debug, Deserialize)]
109126
struct ShowMessageDialogResponse {
110127
value: String,

0 commit comments

Comments
 (0)