{
+ return await TAURI_INVOKE("plugin:misc|image_delete", { sessionId, imageFilename });
}
}
diff --git a/plugins/misc/permissions/autogenerated/commands/image_delete.toml b/plugins/misc/permissions/autogenerated/commands/image_delete.toml
new file mode 100644
index 000000000..72eb41937
--- /dev/null
+++ b/plugins/misc/permissions/autogenerated/commands/image_delete.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-image-delete"
+description = "Enables the image_delete command without any pre-configured scope."
+commands.allow = ["image_delete"]
+
+[[permission]]
+identifier = "deny-image-delete"
+description = "Denies the image_delete command without any pre-configured scope."
+commands.deny = ["image_delete"]
diff --git a/plugins/misc/permissions/autogenerated/commands/image_upload.toml b/plugins/misc/permissions/autogenerated/commands/image_upload.toml
new file mode 100644
index 000000000..ad7724289
--- /dev/null
+++ b/plugins/misc/permissions/autogenerated/commands/image_upload.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-image-upload"
+description = "Enables the image_upload command without any pre-configured scope."
+commands.allow = ["image_upload"]
+
+[[permission]]
+identifier = "deny-image-upload"
+description = "Denies the image_upload command without any pre-configured scope."
+commands.deny = ["image_upload"]
diff --git a/plugins/misc/permissions/autogenerated/reference.md b/plugins/misc/permissions/autogenerated/reference.md
index 3a82d84bd..d6e514a1b 100644
--- a/plugins/misc/permissions/autogenerated/reference.md
+++ b/plugins/misc/permissions/autogenerated/reference.md
@@ -12,6 +12,8 @@ Default permissions for the plugin
- `allow-audio-open`
- `allow-audio-exist`
- `allow-audio-delete`
+- `allow-image-upload`
+- `allow-image-delete`
## Permission Table
@@ -181,6 +183,58 @@ Denies the get_git_hash command without any pre-configured scope.
|
+`misc:allow-image-delete`
+
+ |
+
+
+Enables the image_delete command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`misc:deny-image-delete`
+
+ |
+
+
+Denies the image_delete command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`misc:allow-image-upload`
+
+ |
+
+
+Enables the image_upload command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`misc:deny-image-upload`
+
+ |
+
+
+Denies the image_upload command without any pre-configured scope.
+
+ |
+
+
+
+|
+
`misc:allow-opinionated-md-to-html`
|
diff --git a/plugins/misc/permissions/default.toml b/plugins/misc/permissions/default.toml
index e3072d21a..66da0a90b 100644
--- a/plugins/misc/permissions/default.toml
+++ b/plugins/misc/permissions/default.toml
@@ -9,4 +9,6 @@ permissions = [
"allow-audio-open",
"allow-audio-exist",
"allow-audio-delete",
+ "allow-image-upload",
+ "allow-image-delete",
]
diff --git a/plugins/misc/permissions/schemas/schema.json b/plugins/misc/permissions/schemas/schema.json
index 624ba5654..88ebfec97 100644
--- a/plugins/misc/permissions/schemas/schema.json
+++ b/plugins/misc/permissions/schemas/schema.json
@@ -366,6 +366,30 @@
"const": "deny-get-git-hash",
"markdownDescription": "Denies the get_git_hash command without any pre-configured scope."
},
+ {
+ "description": "Enables the image_delete command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-image-delete",
+ "markdownDescription": "Enables the image_delete command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the image_delete command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-image-delete",
+ "markdownDescription": "Denies the image_delete command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the image_upload command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-image-upload",
+ "markdownDescription": "Enables the image_upload command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the image_upload command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-image-upload",
+ "markdownDescription": "Denies the image_upload command without any pre-configured scope."
+ },
{
"description": "Enables the opinionated_md_to_html command without any pre-configured scope.",
"type": "string",
@@ -391,10 +415,10 @@
"markdownDescription": "Denies the parse_meeting_link command without any pre-configured scope."
},
{
- "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-git-hash`\n- `allow-get-fingerprint`\n- `allow-opinionated-md-to-html`\n- `allow-delete-session-folder`\n- `allow-parse-meeting-link`\n- `allow-audio-open`\n- `allow-audio-exist`\n- `allow-audio-delete`",
+ "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-git-hash`\n- `allow-get-fingerprint`\n- `allow-opinionated-md-to-html`\n- `allow-delete-session-folder`\n- `allow-parse-meeting-link`\n- `allow-audio-open`\n- `allow-audio-exist`\n- `allow-audio-delete`\n- `allow-image-upload`\n- `allow-image-delete`",
"type": "string",
"const": "default",
- "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-git-hash`\n- `allow-get-fingerprint`\n- `allow-opinionated-md-to-html`\n- `allow-delete-session-folder`\n- `allow-parse-meeting-link`\n- `allow-audio-open`\n- `allow-audio-exist`\n- `allow-audio-delete`"
+ "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-git-hash`\n- `allow-get-fingerprint`\n- `allow-opinionated-md-to-html`\n- `allow-delete-session-folder`\n- `allow-parse-meeting-link`\n- `allow-audio-open`\n- `allow-audio-exist`\n- `allow-audio-delete`\n- `allow-image-upload`\n- `allow-image-delete`"
}
]
}
diff --git a/plugins/misc/src/commands.rs b/plugins/misc/src/commands.rs
index 1155e596c..c98755f2d 100644
--- a/plugins/misc/src/commands.rs
+++ b/plugins/misc/src/commands.rs
@@ -98,3 +98,48 @@ pub async fn parse_meeting_link(
) -> Option {
app.parse_meeting_link(&text)
}
+
+#[tauri::command]
+#[specta::specta]
+pub async fn image_upload(
+ app: tauri::AppHandle,
+ session_id: String,
+ image_data: Vec,
+ extension: String,
+) -> Result {
+ let data_dir = app.path().app_data_dir().map_err(|e| e.to_string())?;
+ let session_dir = data_dir.join(&session_id);
+ let images_dir = session_dir.join("images");
+
+ // Create directories if they don't exist
+ std::fs::create_dir_all(&images_dir).map_err(|e| e.to_string())?;
+
+ // Generate unique filename
+ let uuid = uuid::Uuid::new_v4();
+ let filename = format!("{}.{}", uuid, extension);
+ let file_path = images_dir.join(&filename);
+
+ // Write image data to file
+ std::fs::write(&file_path, image_data).map_err(|e| e.to_string())?;
+
+ // Return tauri local URL
+ let url = format!("tauri://localhost/{}/images/{}", session_id, filename);
+ Ok(url)
+}
+
+#[tauri::command]
+#[specta::specta]
+pub async fn image_delete(
+ app: tauri::AppHandle,
+ session_id: String,
+ image_filename: String,
+) -> Result<(), String> {
+ let data_dir = app.path().app_data_dir().map_err(|e| e.to_string())?;
+ let image_path = data_dir.join(session_id).join("images").join(image_filename);
+
+ if image_path.exists() {
+ std::fs::remove_file(image_path).map_err(|e| e.to_string())?;
+ }
+
+ Ok(())
+}
diff --git a/plugins/misc/src/lib.rs b/plugins/misc/src/lib.rs
index 0bc337896..bbcd7b00c 100644
--- a/plugins/misc/src/lib.rs
+++ b/plugins/misc/src/lib.rs
@@ -16,6 +16,8 @@ fn make_specta_builder() -> tauri_specta::Builder {
commands::audio_exist::,
commands::audio_open::,
commands::audio_delete::,
+ commands::image_upload::,
+ commands::image_delete::,
])
.error_handling(tauri_specta::ErrorHandlingMode::Throw)
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b267490e4..e1c59a5ad 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -595,6 +595,9 @@ importers:
'@hypr/plugin-db':
specifier: workspace:^
version: link:../../plugins/db
+ '@hypr/plugin-misc':
+ specifier: workspace:^
+ version: link:../../plugins/misc
'@hypr/ui':
specifier: workspace:^
version: link:../ui
@@ -603,13 +606,13 @@ importers:
version: link:../utils
'@remixicon/react':
specifier: ^4.6.0
- version: 4.6.0(react@18.3.1)
+ version: 4.6.0(react@19.1.1)
'@tanstack/react-query':
specifier: ^5.87.1
- version: 5.87.1(react@18.3.1)
+ version: 5.87.1(react@19.1.1)
'@tanstack/react-router':
specifier: ^1.131.35
- version: 1.131.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 1.131.35(react-dom@18.3.1(react@19.1.1))(react@19.1.1)
'@tiptap/core':
specifier: ^3.4.1
version: 3.4.1(@tiptap/pm@3.4.1)
@@ -619,6 +622,9 @@ importers:
'@tiptap/extension-document':
specifier: ^3.4.1
version: 3.4.1(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))
+ '@tiptap/extension-file-handler':
+ specifier: ^3.4.2
+ version: 3.4.2(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/extension-text-style@3.4.2(@tiptap/core@3.4.1(@tiptap/pm@3.4.1)))(@tiptap/pm@3.4.1)
'@tiptap/extension-highlight':
specifier: ^3.4.1
version: 3.4.1(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))
@@ -663,7 +669,7 @@ importers:
version: 3.4.1
'@tiptap/react':
specifier: ^3.4.1
- version: 3.4.1(@floating-ui/dom@1.7.4)(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)(@types/react-dom@18.3.7(@types/react@18.3.24))(@types/react@18.3.24)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ version: 3.4.1(@floating-ui/dom@1.7.4)(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)(@types/react-dom@18.3.7(@types/react@18.3.24))(@types/react@18.3.24)(react-dom@18.3.1(react@19.1.1))(react@19.1.1)
'@tiptap/starter-kit':
specifier: ^3.4.1
version: 3.4.1
@@ -675,7 +681,7 @@ importers:
version: 2.1.1
lucide-react:
specifier: ^0.525.0
- version: 0.525.0(react@18.3.1)
+ version: 0.525.0(react@19.1.1)
prosemirror-commands:
specifier: ^1.7.1
version: 1.7.1
@@ -687,10 +693,10 @@ importers:
version: 1.4.3
react:
specifier: ^18.3.1
- version: 18.3.1
+ version: 19.1.1
react-dom:
specifier: ^18.3.1
- version: 18.3.1(react@18.3.1)
+ version: 18.3.1(react@19.1.1)
turndown:
specifier: ^7.2.1
version: 7.2.1
@@ -4207,6 +4213,13 @@ packages:
peerDependencies:
'@tiptap/extensions': ^3.4.1
+ '@tiptap/extension-file-handler@3.4.2':
+ resolution: {integrity: sha512-MjX1Y58/pGg7pbsZrg3iIBQy0HDDa/meNdna+tUyQIx0wJoQax1bmuCUug2QFer9bEZ/BYLa+SoqxILvNz1Ojg==}
+ peerDependencies:
+ '@tiptap/core': ^3.4.2
+ '@tiptap/extension-text-style': ^3.4.2
+ '@tiptap/pm': ^3.4.2
+
'@tiptap/extension-floating-menu@3.4.1':
resolution: {integrity: sha512-9qGINja20Kz4XI0uESoYiwgGo+ejvDrHiSoRmd3jkDMv6fGMXj1U+HYzqhXZTV30kuQZQN8twNmbmzBu+jltYQ==}
peerDependencies:
@@ -4314,6 +4327,11 @@ packages:
peerDependencies:
'@tiptap/extension-list': ^3.4.1
+ '@tiptap/extension-text-style@3.4.2':
+ resolution: {integrity: sha512-ioCf7VxWj2t+seC2vfzGtGlcToGKpwz6R5HMpo6/CSBDTZc5LsPTiJqJ6R6ahjqWwAKHI6SzlW5vtS36OywDzw==}
+ peerDependencies:
+ '@tiptap/core': ^3.4.2
+
'@tiptap/extension-text@3.4.1':
resolution: {integrity: sha512-6qcBjRAE4HpjbFShf9e44uBuq8jMvrumzvK4FwhAwZ7S8nyywN1WLZY3S1UQLMYJr3wZn+9IhKMb2CjBeGIPiA==}
peerDependencies:
@@ -14011,6 +14029,10 @@ snapshots:
dependencies:
react: 18.3.1
+ '@remixicon/react@4.6.0(react@19.1.1)':
+ dependencies:
+ react: 19.1.1
+
'@rolldown/pluginutils@1.0.0-beta.27': {}
'@rollup/plugin-alias@5.1.1(rollup@4.50.0)':
@@ -14471,6 +14493,17 @@ snapshots:
tiny-invariant: 1.3.3
tiny-warning: 1.0.3
+ '@tanstack/react-router@1.131.35(react-dom@18.3.1(react@19.1.1))(react@19.1.1)':
+ dependencies:
+ '@tanstack/history': 1.131.2
+ '@tanstack/react-store': 0.7.4(react-dom@18.3.1(react@19.1.1))(react@19.1.1)
+ '@tanstack/router-core': 1.131.35
+ isbot: 5.1.30
+ react: 19.1.1
+ react-dom: 18.3.1(react@19.1.1)
+ tiny-invariant: 1.3.3
+ tiny-warning: 1.0.3
+
'@tanstack/react-start-client@1.131.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/react-router': 1.131.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -14585,6 +14618,13 @@ snapshots:
react-dom: 18.3.1(react@18.3.1)
use-sync-external-store: 1.5.0(react@18.3.1)
+ '@tanstack/react-store@0.7.4(react-dom@18.3.1(react@19.1.1))(react@19.1.1)':
+ dependencies:
+ '@tanstack/store': 0.7.4
+ react: 19.1.1
+ react-dom: 18.3.1(react@19.1.1)
+ use-sync-external-store: 1.5.0(react@19.1.1)
+
'@tanstack/router-core@1.131.35':
dependencies:
'@tanstack/history': 1.131.2
@@ -14935,6 +14975,12 @@ snapshots:
dependencies:
'@tiptap/extensions': 3.4.1(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)
+ '@tiptap/extension-file-handler@3.4.2(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/extension-text-style@3.4.2(@tiptap/core@3.4.1(@tiptap/pm@3.4.1)))(@tiptap/pm@3.4.1)':
+ dependencies:
+ '@tiptap/core': 3.4.1(@tiptap/pm@3.4.1)
+ '@tiptap/extension-text-style': 3.4.2(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))
+ '@tiptap/pm': 3.4.1
+
'@tiptap/extension-floating-menu@3.4.1(@floating-ui/dom@1.7.4)(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)':
dependencies:
'@floating-ui/dom': 1.7.4
@@ -15024,6 +15070,10 @@ snapshots:
dependencies:
'@tiptap/extension-list': 3.4.1(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)
+ '@tiptap/extension-text-style@3.4.2(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))':
+ dependencies:
+ '@tiptap/core': 3.4.1(@tiptap/pm@3.4.1)
+
'@tiptap/extension-text@3.4.1(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))':
dependencies:
'@tiptap/core': 3.4.1(@tiptap/pm@3.4.1)
@@ -15062,7 +15112,7 @@ snapshots:
prosemirror-transform: 1.10.4
prosemirror-view: 1.41.0
- '@tiptap/react@3.4.1(@floating-ui/dom@1.7.4)(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)(@types/react-dom@18.3.7(@types/react@18.3.24))(@types/react@18.3.24)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ '@tiptap/react@3.4.1(@floating-ui/dom@1.7.4)(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)(@types/react-dom@18.3.7(@types/react@18.3.24))(@types/react@18.3.24)(react-dom@18.3.1(react@19.1.1))(react@19.1.1)':
dependencies:
'@tiptap/core': 3.4.1(@tiptap/pm@3.4.1)
'@tiptap/pm': 3.4.1
@@ -15070,9 +15120,9 @@ snapshots:
'@types/react-dom': 18.3.7(@types/react@18.3.24)
'@types/use-sync-external-store': 0.0.6
fast-deep-equal: 3.1.3
- react: 18.3.1
- react-dom: 18.3.1(react@18.3.1)
- use-sync-external-store: 1.5.0(react@18.3.1)
+ react: 19.1.1
+ react-dom: 18.3.1(react@19.1.1)
+ use-sync-external-store: 1.5.0(react@19.1.1)
optionalDependencies:
'@tiptap/extension-bubble-menu': 3.4.1(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)
'@tiptap/extension-floating-menu': 3.4.1(@floating-ui/dom@1.7.4)(@tiptap/core@3.4.1(@tiptap/pm@3.4.1))(@tiptap/pm@3.4.1)
@@ -19400,6 +19450,10 @@ snapshots:
dependencies:
react: 18.3.1
+ lucide-react@0.525.0(react@19.1.1):
+ dependencies:
+ react: 19.1.1
+
luxon@3.7.1:
optional: true
@@ -21442,7 +21496,6 @@ snapshots:
loose-envify: 1.4.0
react: 19.1.1
scheduler: 0.23.2
- optional: true
react-draggable@4.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
@@ -23212,6 +23265,10 @@ snapshots:
dependencies:
react: 18.3.1
+ use-sync-external-store@1.5.0(react@19.1.1):
+ dependencies:
+ react: 19.1.1
+
userhome@1.0.1: {}
util-deprecate@1.0.2: {}