diff --git a/bun.lock b/bun.lock index d7d63de..494e562 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,10 @@ "name": "shark", "dependencies": { "@tauri-apps/api": "^2", + "@tauri-apps/plugin-dialog": "~2", + "@tauri-apps/plugin-fs": "~2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-store": "~2", }, "devDependencies": { "@sveltejs/adapter-static": "^3.0.6", @@ -166,8 +169,14 @@ "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.8.4", "", { "os": "win32", "cpu": "x64" }, "sha512-XuvGB4ehBdd7QhMZ9qbj/8icGEatDuBNxyYHbLKsTYh90ggUlPa/AtaqcC1Fo69lGkTmq9BOKrs1aWSi7xDonA=="], + "@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.4.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OvXkrEBfWwtd8tzVCEXIvRfNEX87qs2jv6SqmVPiHcJjBhSF/GUvjqUNIDmKByb5N8nvDqVUM7+g1sXwdC/S9w=="], + + "@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-YGhmYuTgXGsi6AjoV+5mh2NvicgWBfVJHHheuck6oHD+HC9bVWPaHvCP0/Aw4pHDejwrvT8hE3+zZAaWf+hrig=="], + "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-B0LShOYae4CZjN8leiNDbnfjSrTwoZakqKaWpfoH6nXiJwt6Rgj6RnVIffG3DoJiKsffRhMkjmBV9VeilSb4TA=="], + "@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-PjBnlnH6jyI71MGhrPaxUUCsOzc7WO1mbc4gRhME0m2oxLgCqbksw6JyeKQimuzv4ysdpNO3YbmaY2haf82a3A=="], + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], diff --git a/package.json b/package.json index d57ebf1..089ae12 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,10 @@ "license": "MIT", "dependencies": { "@tauri-apps/api": "^2", - "@tauri-apps/plugin-opener": "^2" + "@tauri-apps/plugin-dialog": "~2", + "@tauri-apps/plugin-fs": "~2", + "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-store": "~2" }, "devDependencies": { "@sveltejs/adapter-static": "^3.0.6", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 29621b5..795708c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -10,7 +10,10 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-dialog", + "tauri-plugin-fs", "tauri-plugin-opener", + "tauri-plugin-store", ] [[package]] @@ -67,6 +70,27 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "ashpd" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.2", + "raw-window-handle", + "serde", + "serde_repr", + "tokio", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -748,6 +772,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.9.4", + "block2 0.6.1", + "libc", "objc2 0.6.2", ] @@ -762,6 +788,15 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + [[package]] name = "dlopen2" version = "0.8.0" @@ -785,6 +820,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dpi" version = "0.1.2" @@ -2657,7 +2698,7 @@ checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", "indexmap 2.11.4", - "quick-xml", + "quick-xml 0.38.3", "serde", "time", ] @@ -2787,6 +2828,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + [[package]] name = "quick-xml" version = "0.38.3" @@ -2836,6 +2886,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -2856,6 +2916,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -2874,6 +2944,15 @@ dependencies = [ "getrandom 0.2.16", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -3002,6 +3081,31 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rfd" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" +dependencies = [ + "ashpd", + "block2 0.6.1", + "dispatch2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2 0.6.2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.1", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.59.0", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -3102,6 +3206,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -3719,6 +3829,46 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-dialog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beee42a4002bc695550599b011728d9dfabf82f767f134754ed6655e434824e" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror 2.0.17", + "url", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "315784ec4be45e90a987687bae7235e6be3d6e9e350d2b75c16b8a4bf22c1db7" +dependencies = [ + "anyhow", + "dunce", + "glob", + "percent-encoding", + "schemars 0.8.22", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "tauri-utils", + "thiserror 2.0.17", + "toml 0.9.7", + "url", +] + [[package]] name = "tauri-plugin-opener" version = "2.5.0" @@ -3741,6 +3891,22 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-store" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85dd80d60a76ee2c2fdce09e9ef30877b239c2a6bb76e6d7d03708aa5f13a19" +dependencies = [ + "dunce", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "tauri-runtime" version = "2.8.0" @@ -3958,11 +4124,25 @@ dependencies = [ "libc", "mio", "pin-project-lite", + "signal-hook-registry", "slab", "socket2", + "tokio-macros", + "tracing", "windows-sys 0.59.0", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "tokio-util" version = "0.7.16" @@ -4466,6 +4646,66 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.9.4", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.9.4", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml 0.37.5", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.81" @@ -5135,6 +5375,7 @@ dependencies = [ "ordered-stream", "serde", "serde_repr", + "tokio", "tracing", "uds_windows", "windows-sys 0.60.2", @@ -5254,6 +5495,7 @@ dependencies = [ "endi", "enumflags2", "serde", + "url", "winnow 0.7.13", "zvariant_derive", "zvariant_utils", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e3a3bda..0484aa4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,6 +20,9 @@ tauri-build = { version = "2", features = [] } [dependencies] tauri = { version = "2", features = [] } tauri-plugin-opener = "2" +tauri-plugin-store = "2" +tauri-plugin-dialog = "2" +tauri-plugin-fs = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 5058a24..71ad1f9 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -10,6 +10,16 @@ "core:window:allow-start-dragging", "core:window:allow-minimize", "core:window:allow-toggle-maximize", - "core:window:allow-close" + "core:window:allow-close", + "store:default", + "dialog:default", + "fs:default", + { + "identifier": "fs:scope", + "allow": [ + { "path": "$HOME/**/*" }, + { "path": "$APPDATA/**/*" } + ] + } ] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4a277ef..c9586db 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -8,6 +8,9 @@ fn greet(name: &str) -> String { pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_store::Builder::new().build()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_fs::init()) .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/lib/stores/settings.ts b/src/lib/stores/settings.ts new file mode 100644 index 0000000..a3550c8 --- /dev/null +++ b/src/lib/stores/settings.ts @@ -0,0 +1,74 @@ +import { LazyStore } from '@tauri-apps/plugin-store'; +import { writable, type Writable } from 'svelte/store'; + +// Settings interface +export interface AppSettings { + musicFolder: string | null; + playlistsFolder: string | null; +} + +// Initialize the store with settings.json +const store = new LazyStore('settings.json'); + +// Default settings +const defaultSettings: AppSettings = { + musicFolder: null, + playlistsFolder: null +}; + +// Create a writable store for reactive UI updates +export const settings: Writable = writable(defaultSettings); + +// Load settings from store +export async function loadSettings(): Promise { + const musicFolder = await store.get('musicFolder'); + const playlistsFolder = await store.get('playlistsFolder'); + + settings.set({ + musicFolder: musicFolder ?? null, + playlistsFolder: playlistsFolder ?? null + }); +} + +// Save music folder setting +export async function setMusicFolder(path: string | null): Promise { + if (path) { + await store.set('musicFolder', path); + } else { + await store.delete('musicFolder'); + } + await store.save(); + + settings.update(s => ({ + ...s, + musicFolder: path + })); +} + +// Save playlists folder setting +export async function setPlaylistsFolder(path: string | null): Promise { + if (path) { + await store.set('playlistsFolder', path); + } else { + await store.delete('playlistsFolder'); + } + await store.save(); + + settings.update(s => ({ + ...s, + playlistsFolder: path + })); +} + +// Get music folder setting +export async function getMusicFolder(): Promise { + return await store.get('musicFolder'); +} + +// Get playlists folder setting +export async function getPlaylistsFolder(): Promise { + return await store.get('playlistsFolder'); +} + +// Initialize settings on app start +loadSettings(); diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index bc377a1..6e72bc2 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -95,6 +95,7 @@ flex-shrink: 0; padding: 0; overflow-y: auto; + background: #121212; } .sidebar-nav { @@ -153,7 +154,7 @@ overflow-y: auto; padding: 8px; font-family: "Pixelated MS Sans Serif", Arial; - + background: #121212; } .status-text { diff --git a/src/routes/settings/+page.svelte b/src/routes/settings/+page.svelte index fa3ca59..9319d40 100644 --- a/src/routes/settings/+page.svelte +++ b/src/routes/settings/+page.svelte @@ -1,7 +1,91 @@ + +

Settings

+

Library Folders

+

+ Note: Music and Playlists folders should be in the same parent directory for playlists to work properly in other apps. +

+
+ +
+ + +
+ {#if currentMusicFolder} + Currently using: {currentMusicFolder} + {:else} + No music folder selected. Click Browse to choose one. + {/if} +
+ +
+ +
+ + +
+ {#if currentPlaylistsFolder} + Currently using: {currentPlaylistsFolder} + {:else} + No playlists folder selected. Click Browse to choose one. + {/if}
@@ -11,7 +95,50 @@ margin-top: 0; } + h3 { + margin-top: 0; + margin-bottom: 12px; + font-size: 1.1em; + } + .library-content { margin-top: 20px; } + + .info-note { + background-color: var(--button-shadow, #2a2a2a); + padding: 12px; + margin-bottom: 20px; + border-left: 3px solid var(--button-highlight, #606060); + font-size: 0.9em; + } + + .info-note strong { + font-weight: bold; + } + + .field-row-stacked { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 16px; + } + + .folder-selector { + display: flex; + gap: 8px; + align-items: center; + } + + .folder-path { + flex: 1; + background-color: var(--button-highlight); + cursor: not-allowed; + } + + .help-text { + color: var(--text-color, #FFFFFF); + opacity: 0.7; + font-size: 0.9em; + }