[package] name = "qbz-slint" version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true description = "Slint functional MVP shell for QBZ (private branch only)" [[bin]] name = "qbz-slint" path = "src/main.rs" [dependencies] # femtovg renderer, pinned >=1.16 for the femtovg text-rendering fixes # (slint-ui/slint #5177 pixel-grid alignment + #11335 0.5px tearing / # inconsistent glyph spacing). Skia never received that treatment. slint = { version = "1.16", default-features = false, features = [ "std", "backend-winit", "renderer-femtovg", "renderer-software", "accessibility", "compat-1-2", ] } # Direct access to the winit backend for the system tray: WinitWindowAccessor # (hide/show the OS window without quitting the event loop) and, later, the # CustomApplicationHandler (tray event pump + close-to-tray intercept). MUST be # pinned to the exact version Slint resolves (1.16.1) — i-slint-backend-winit # does not follow semver, and a mismatch makes with_winit_window() return None. i-slint-backend-winit = "=1.16.1" log = { workspace = true } env_logger = "0.11" tokio = { workspace = true } async-trait = { workspace = true } reqwest = { workspace = true } image = { version = "0.25", default-features = false, features = ["jpeg", "png"] } urlencoding = "2" open = "5" arboard = "3" rfd = { version = "0.15", default-features = false, features = ["xdg-portal", "tokio"] } serde = { workspace = true } serde_json = { workspace = true } dirs = "5" chrono = { workspace = true, features = ["unstable-locales"] } qbz-app = { path = "../qbz-app" } qbz-media-controls = { path = "../qbz-media-controls" } qbz-audio = { path = "../qbz-audio" } qbz-core = { path = "../qbz-core" } qbz-player = { path = "../qbz-player" } qconnect-app = { path = "../qconnect-app" } qconnect-transport-ws = { path = "../qconnect-transport-ws" } futures-util = { workspace = true } uuid = { version = "1", features = ["v4"] } qbz-library = { path = "../qbz-library" } qbz-plex = { path = "../qbz-plex" } qbz-offline-cache = { path = "../qbz-offline-cache" } qbz-models = { path = "../qbz-models" } qbz-mixtape = { path = "../qbz-mixtape" } qbz-qobuz = { path = "../qbz-qobuz" } qbz-lyrics = { path = "../qbz-lyrics" } qbz-integrations = { path = "../qbz-integrations" } rusqlite = { version = "0.31", features = ["bundled"] } # DJ-mix sampler thread RNG (rand::rng()), confined to a sync scope — the # same crate qbz-mixtape::shuffle is generic over (spec 40 §6). rand = { workspace = true } qbz-cache = { path = "../qbz-cache" } qbz-credentials = { path = "../qbz-credentials" } # Linux system tray via StatusNotifierItem. Same crate + rationale as the # Tauri build (src-tauri/Cargo.toml): libayatana-appindicator never dispatches # primary-activate (left-click), so we use ksni's pure-Rust SNI which exposes # Activate / SecondaryActivate / Scroll. macOS/Windows use `tray-icon` instead # (added with the CustomApplicationHandler slice). [target.'cfg(target_os = "linux")'.dependencies] ksni = { version = "0.3", features = ["blocking"] } # macOS menu-bar tray (NSStatusItem), hand-rolled directly on objc2 0.5 / # app-kit 0.2 — the SAME objc2 generation winit 0.30 uses — so the NSMenu lives # in winit's NSApplication runtime and `[NSApp sendAction:]` dispatches the menu # item target-action. A second `muda` (from tray-icon) registers a duplicate # `MudaMenuItem` objc class and either silently fails to dispatch (objc2 0.6) or # panics at startup (objc2 0.5), so tray-icon/muda is dropped on macOS. Windows # has no tray for now (untested/unshipped). [target.'cfg(target_os = "macos")'.dependencies] objc2 = "0.5" objc2-foundation = { version = "0.2", default-features = false, features = [ "std", "NSData", "NSString", ] } objc2-app-kit = { version = "0.2", default-features = false, features = [ "std", "NSApplication", "NSResponder", "NSRunningApplication", "NSStatusBar", "NSStatusItem", "NSStatusBarButton", "NSMenu", "NSMenuItem", "NSImage", "NSButton", "NSControl", "NSView", "NSEvent", ] } [build-dependencies] slint-build = "1.16"