diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index dffbfe2..a1a0cc3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1715,6 +1715,7 @@ dependencies = [ "tauri-plugin-persisted-scope", "tauri-plugin-store", "thiserror 2.0.17", + "trash", "ts-rs", "uhlc", "url", @@ -4431,7 +4432,7 @@ dependencies = [ "tao-macros", "unicode-segmentation", "url", - "windows", + "windows 0.61.1", "windows-core 0.61.0", "windows-version", "x11-dl", @@ -4503,7 +4504,7 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows", + "windows 0.61.1", ] [[package]] @@ -4687,7 +4688,7 @@ dependencies = [ "tauri-plugin", "thiserror 2.0.17", "url", - "windows", + "windows 0.61.1", "zbus", ] @@ -4763,7 +4764,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.1", ] [[package]] @@ -4789,7 +4790,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.1", "wry", ] @@ -4849,7 +4850,7 @@ checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9" dependencies = [ "quick-xml 0.37.5", "thiserror 2.0.17", - "windows", + "windows 0.61.1", "windows-version", ] @@ -5189,6 +5190,24 @@ dependencies = [ "once_cell", ] +[[package]] +name = "trash" +version = "5.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22746c6b0c6d85d60a8f0d858f7057dfdf11297c132679f452ec908fba42b871" +dependencies = [ + "chrono", + "libc", + "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "once_cell", + "percent-encoding", + "scopeguard", + "urlencoding", + "windows 0.56.0", +] + [[package]] name = "tray-icon" version = "0.21.0" @@ -5353,6 +5372,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "urlpattern" version = "0.3.0" @@ -5638,10 +5663,10 @@ checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows", + "windows 0.61.1", "windows-core 0.61.0", - "windows-implement", - "windows-interface", + "windows-implement 0.60.0", + "windows-interface 0.59.1", ] [[package]] @@ -5662,7 +5687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" dependencies = [ "thiserror 2.0.17", - "windows", + "windows 0.61.1", "windows-core 0.61.0", ] @@ -5712,6 +5737,16 @@ dependencies = [ "windows-version", ] +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.61.1" @@ -5743,16 +5778,28 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.60.0", + "windows-interface 0.59.1", "windows-link", - "windows-result", + "windows-result 0.3.2", "windows-strings 0.4.0", ] @@ -5766,6 +5813,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "windows-implement" version = "0.60.0" @@ -5777,6 +5835,17 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "windows-interface" version = "0.59.1" @@ -5810,11 +5879,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ - "windows-result", + "windows-result 0.3.2", "windows-strings 0.3.1", "windows-targets 0.53.2", ] +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.3.2" @@ -6226,7 +6304,7 @@ dependencies = [ "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows", + "windows 0.61.1", "windows-core 0.61.0", "windows-version", "x11-dl", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9160a5f..fccec58 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -49,6 +49,7 @@ tauri-plugin-os = "2.3.2" tauri-plugin-persisted-scope = "2.3.4" tauri-plugin-store = "2.4.1" thiserror = "2.0.17" +trash = "5.2.0" ts-rs = { version = "11.1.0", features = ["serde-compat"] } uhlc = "0.8.2" url = "2.5.7" diff --git a/src-tauri/gen/android/app/src/main/assets/database/vault.db b/src-tauri/gen/android/app/src/main/assets/database/vault.db index 927a3e0..7d7b777 100644 Binary files a/src-tauri/gen/android/app/src/main/assets/database/vault.db and b/src-tauri/gen/android/app/src/main/assets/database/vault.db differ diff --git a/src-tauri/src/database/mod.rs b/src-tauri/src/database/mod.rs index fcb3bfd..653be15 100644 --- a/src-tauri/src/database/mod.rs +++ b/src-tauri/src/database/mod.rs @@ -20,6 +20,7 @@ use std::time::UNIX_EPOCH; use std::{fs, sync::Arc}; use tauri::{path::BaseDirectory, AppHandle, Manager, State}; use tauri_plugin_fs::FsExt; +use trash; use ts_rs::TS; pub struct DbConnection(pub Arc>>); @@ -212,7 +213,46 @@ pub fn vault_exists(app_handle: AppHandle, vault_name: String) -> Result Result { + let vault_path = get_vault_path(&app_handle, &vault_name)?; + let vault_shm_path = format!("{}-shm", vault_path); + let vault_wal_path = format!("{}-wal", vault_path); + + if !Path::new(&vault_path).exists() { + return Err(DatabaseError::IoError { + path: vault_path, + reason: "Vault does not exist".to_string(), + }); + } + + // Try to move to trash first (works on desktop systems) + let moved_to_trash = trash::delete(&vault_path).is_ok(); + + if moved_to_trash { + // Also try to move auxiliary files to trash (ignore errors as they might not exist) + let _ = trash::delete(&vault_shm_path); + let _ = trash::delete(&vault_wal_path); + + Ok(format!( + "Vault '{}' successfully moved to trash", + vault_name + )) + } else { + // Fallback: Permanent deletion (e.g., on mobile devices without trash) + println!( + "Trash not available, falling back to permanent deletion for vault '{}'", + vault_name + ); + delete_vault(app_handle, vault_name) + } +} + +/// Deletes a vault database file permanently (bypasses trash) #[tauri::command] pub fn delete_vault(app_handle: AppHandle, vault_name: String) -> Result { let vault_path = get_vault_path(&app_handle, &vault_name)?; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a03a817..4bf202a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -68,6 +68,7 @@ pub fn run() { .invoke_handler(tauri::generate_handler![ database::create_encrypted_database, database::delete_vault, + database::move_vault_to_trash, database::list_vaults, database::open_encrypted_database, database::sql_execute_with_crdt, diff --git a/src/components/ui/button/context.vue b/src/components/ui/button/context.vue new file mode 100644 index 0000000..2a661a1 --- /dev/null +++ b/src/components/ui/button/context.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/pages/index.vue b/src/pages/index.vue index 400fbde..ade4a8a 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -54,10 +54,18 @@ :key="vault.name" class="flex items-center justify-between group overflow-x-scroll" > - {{ vault.name }} - + { vaultToBeRemoved.value = vaultName @@ -138,7 +149,7 @@ const prepareRemoveVault = (vaultName: string) => { const toast = useToast() const onConfirmRemoveAsync = async () => { try { - await removeVaultAsync(vaultToBeRemoved.value) + await moveVaultToTrashAsync(vaultToBeRemoved.value) showRemoveDialog.value = false await syncLastVaultsAsync() } catch (error) { @@ -149,9 +160,6 @@ const onConfirmRemoveAsync = async () => { } } -const { syncLastVaultsAsync, removeVaultAsync } = useLastVaultStore() -const { syncDeviceIdAsync } = useDeviceStore() - onMounted(async () => { try { await syncLastVaultsAsync() @@ -168,6 +176,7 @@ de: lastUsed: 'Zuletzt verwendete Vaults' sponsors: Supported by remove: + button: Löschen title: Vault löschen description: Möchtest du die Vault {vaultName} wirklich löschen? @@ -176,6 +185,7 @@ en: lastUsed: 'Last used Vaults' sponsors: 'Supported by' remove: + button: Delete title: Delete Vault description: Are you sure you really want to delete {vaultName}? diff --git a/src/stores/vault/lastVaults.ts b/src/stores/vault/lastVaults.ts index 2ed2aad..f4ab796 100644 --- a/src/stores/vault/lastVaults.ts +++ b/src/stores/vault/lastVaults.ts @@ -22,9 +22,14 @@ export const useLastVaultStore = defineStore('lastVaultStore', () => { return await invoke('delete_vault', { vaultName }) } + const moveVaultToTrashAsync = async (vaultName: string) => { + return await invoke('move_vault_to_trash', { vaultName }) + } + return { syncLastVaultsAsync, lastVaults, removeVaultAsync, + moveVaultToTrashAsync, } })