fix: use Tauri clipboard plugin for reliable share links

- Add tauri-plugin-clipboard-manager for reliable clipboard access
- Replace browser clipboard API with Tauri plugin
- Improve error messages in share functions to be more specific
- Add loading indicator for Song.link fetch
This commit is contained in:
vicrodh committed 2026-01-09 17:35:18 -06:00
1 parent 31549828e6
commit e908d334c1
5 files changed
+12 -16

No files matched your search

+1
View File
@@ -14,6 +14,7 @@
"license": "MIT",
"dependencies": {
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-clipboard-manager": "^2",
"@tauri-apps/plugin-dialog": "^2.5.0",
"@tauri-apps/plugin-opener": "^2",
"lucide-svelte": "^0.562.0",
+3
View File
@@ -73,3 +73,6 @@ dotenvy = "0.15"
# Secure credential storage (system keyring)
keyring = "3"
# Clipboard
tauri-plugin-clipboard-manager = "2"
+2 -1
View File
@@ -6,6 +6,7 @@
"permissions": [
"core:default",
"opener:default",
"dialog:default"
"dialog:default",
"clipboard-manager:default"
]
}
+1
View File
@@ -97,6 +97,7 @@ pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_clipboard_manager::init())
.manage(AppState::new())
.manage(library_state)
.invoke_handler(tauri::generate_handler![
+5 -15
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { invoke } from '@tauri-apps/api/core';
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
// Components
import Sidebar from '$lib/components/Sidebar.svelte';
@@ -364,19 +365,7 @@
async function copyToClipboard(text: string, successMessage: string) {
try {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
} else {
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}
await writeText(text);
showToast(successMessage, 'success');
} catch (err) {
console.error('Failed to copy to clipboard:', err);
@@ -475,7 +464,7 @@
await copyToClipboard(url, 'Qobuz link copied');
} catch (err) {
console.error('Failed to get Qobuz link:', err);
showToast('Failed to share link', 'error');
showToast(`Failed to share Qobuz link: ${err}`, 'error');
}
}
@@ -499,11 +488,12 @@
return;
}
try {
showToast('Fetching Song.link...', 'info');
const response = await invoke<SongLinkResponse>('share_track_songlink', { isrc: resolvedIsrc });
await copyToClipboard(response.pageUrl, 'Song.link copied');
} catch (err) {
console.error('Failed to get Song.link:', err);
showToast('Failed to share link', 'error');
showToast(`Song.link error: ${err}`, 'error');
}
}