diff --git a/ui/package.json b/ui/package.json index 87bd376..82cedab 100644 --- a/ui/package.json +++ b/ui/package.json @@ -29,6 +29,7 @@ "@radix-ui/react-toast": "^1.2.4", "@radix-ui/react-tooltip": "^1.1.6", "@tauri-apps/api": "^2", + "@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-shell": "^2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/ui/src-tauri/Cargo.toml b/ui/src-tauri/Cargo.toml index dab3a15..b26970e 100644 --- a/ui/src-tauri/Cargo.toml +++ b/ui/src-tauri/Cargo.toml @@ -28,3 +28,4 @@ data = { path = "../../data" } thiserror = "1.0" itertools = "0.14.0" deranged = "=0.4.0" +tauri-plugin-dialog = "2" diff --git a/ui/src-tauri/capabilities/default.json b/ui/src-tauri/capabilities/default.json index 3bb4cc4..821dac5 100644 --- a/ui/src-tauri/capabilities/default.json +++ b/ui/src-tauri/capabilities/default.json @@ -3,8 +3,5 @@ "identifier": "default", "description": "Capability for the main window", "windows": ["main"], - "permissions": [ - "core:default", - "shell:allow-open" - ] + "permissions": ["core:default", "shell:allow-open", "dialog:default"] } diff --git a/ui/src-tauri/src/lib.rs b/ui/src-tauri/src/lib.rs index 1f90dd6..5db64bb 100644 --- a/ui/src-tauri/src/lib.rs +++ b/ui/src-tauri/src/lib.rs @@ -8,6 +8,7 @@ use logic::{ SearchCommandError, UpdateCommandError, }, config::{Config, ConfigReadError, ConfigWriteError, UiDefaultTerminal}, + import_export::{ExportError, ImportError}, parameters::{parser::SerializableParameter, ParameterError}, Logic, LogicInitError, }; @@ -43,6 +44,10 @@ pub enum UiError { Race, #[error("Failed to execute command in terminal")] ExecuteCommand, + #[error("Failed to import data")] + ImportData(#[from] ImportError), + #[error("Failed to export data")] + ExportData(#[from] ExportError), } // we must manually implement serde::Serialize (https://github.com/tauri-apps/tauri/discussions/8805) @@ -256,6 +261,26 @@ fn update_command_last_used(command_id: i64, state: State) -> Result<(), UiE Err(UiError::Race) } +#[tauri::command] +fn import_data(path: String, state: State) -> Result { + let path = std::path::Path::new(&path); + + if let Ok(logic) = state.logic.write() { + return Ok(logic.import_data(path)?); + } + Err(UiError::Race) +} + +#[tauri::command] +fn export_data(path: String, state: State) -> Result<(), UiError> { + let path = std::path::Path::new(&path); + + if let Ok(logic) = state.logic.write() { + return Ok(logic.create_export_json(path)?); + } + Err(UiError::Race) +} + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let logic = Logic::try_default() @@ -263,6 +288,7 @@ pub fn run() { .unwrap(); tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) .manage(Ui { logic: logic.into(), }) @@ -280,7 +306,9 @@ pub fn run() { read_config, write_config, update_command_last_used, - execute_in_terminal + execute_in_terminal, + import_data, + export_data ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/ui/src-tauri/tauri.conf.json b/ui/src-tauri/tauri.conf.json index 9abc1ae..27d07e5 100644 --- a/ui/src-tauri/tauri.conf.json +++ b/ui/src-tauri/tauri.conf.json @@ -13,8 +13,7 @@ "windows": [ { "title": "CmdStack", - "width": 1440, - "height": 810, + "maximized": true, "minWidth": 850, "minHeight": 600 } @@ -34,4 +33,4 @@ "icons/icon.ico" ] } -} \ No newline at end of file +} diff --git a/ui/src/components/add-form.tsx b/ui/src/components/add-form.tsx index be1e205..f4a46d2 100644 --- a/ui/src/components/add-form.tsx +++ b/ui/src/components/add-form.tsx @@ -53,7 +53,7 @@ export function AddForm({ onSuccess }: AddFormProps) { .then((res) => { console.log(res); toast({ - title: 'Command added ✅ ', + title: 'Command added ✅', }); refreshCommands(); diff --git a/ui/src/components/command-display/command-display.tsx b/ui/src/components/command-display/command-display.tsx index f373fd8..1df78cf 100644 --- a/ui/src/components/command-display/command-display.tsx +++ b/ui/src/components/command-display/command-display.tsx @@ -71,7 +71,7 @@ export function CommandDisplay({ command }: CommandDisplayProps) { .then((res) => { console.log(res); toast({ - title: 'Command updated ✅ ', + title: 'Command updated ✅', }); refreshCommands(); diff --git a/ui/src/components/settings/import-export.tsx b/ui/src/components/settings/import-export.tsx new file mode 100644 index 0000000..fd163da --- /dev/null +++ b/ui/src/components/settings/import-export.tsx @@ -0,0 +1,87 @@ +import { invoke } from '@tauri-apps/api/core'; +import { Button } from '../ui/button'; +import { open, save } from '@tauri-apps/plugin-dialog'; +import { toast } from '@/hooks/use-toast'; +import { useCommands } from '@/use-command'; + +export function ImportButton() { + const [, refreshCommands] = useCommands(); + + return ( + + ); +} + +export function ExportButton() { + return ( + + ); +} diff --git a/ui/src/components/settings/settings-dialog.tsx b/ui/src/components/settings/settings-dialog.tsx index 7e0a306..2f2cbc8 100644 --- a/ui/src/components/settings/settings-dialog.tsx +++ b/ui/src/components/settings/settings-dialog.tsx @@ -15,13 +15,14 @@ import { } from '../ui/dialog'; import { Label } from '../ui/label'; import { TerminalToggle } from './terminal-toggle'; +import { ExportButton, ImportButton } from './import-export'; interface SettingsDialogProps { isCollapsed: boolean; } export function SettingsDialog({ isCollapsed }: SettingsDialogProps) { - const [_, refreshSettings] = useSettings(); + const [, refreshSettings] = useSettings(); function onDialogClick() { startTransition(() => { @@ -61,6 +62,18 @@ export function SettingsDialog({ isCollapsed }: SettingsDialogProps) { +
+ +
+ +
+
+
+ +
+ +
+
diff --git a/ui/src/components/settings/terminal-toggle.tsx b/ui/src/components/settings/terminal-toggle.tsx index 4ae737d..b131a7d 100644 --- a/ui/src/components/settings/terminal-toggle.tsx +++ b/ui/src/components/settings/terminal-toggle.tsx @@ -22,7 +22,7 @@ export function TerminalToggle() { .then((res) => { console.log(res); toast({ - title: 'Settings updated ✅ ', + title: 'Settings updated ✅', }); refreshSettings(); }) diff --git a/ui/src/components/settings/theme-toggle.tsx b/ui/src/components/settings/theme-toggle.tsx index 6b33181..38fcb3c 100644 --- a/ui/src/components/settings/theme-toggle.tsx +++ b/ui/src/components/settings/theme-toggle.tsx @@ -22,7 +22,7 @@ export function ThemeToggle() { .then((res) => { console.log(res); toast({ - title: 'Settings updated ✅ ', + title: 'Settings updated ✅', }); refreshSettings(); }) diff --git a/ui/yarn.lock b/ui/yarn.lock index 54fb856..cd33ffb 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -1116,6 +1116,13 @@ "@tauri-apps/cli-win32-ia32-msvc" "2.0.3" "@tauri-apps/cli-win32-x64-msvc" "2.0.3" +"@tauri-apps/plugin-dialog@~2": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-dialog/-/plugin-dialog-2.2.0.tgz#2f7b841a982820adbc9c182e0e95acd8d90aa6fc" + integrity sha512-6bLkYK68zyK31418AK5fNccCdVuRnNpbxquCl8IqgFByOgWFivbiIlvb79wpSXi0O+8k8RCSsIpOquebusRVSg== + dependencies: + "@tauri-apps/api" "^2.0.0" + "@tauri-apps/plugin-shell@^2": version "2.0.1" resolved "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.0.1.tgz"