Cross-compile groundwork: make the tree build for Windows (3.1)
`cargo check --target x86_64-pc-windows-gnu` is now green (only the upstream egui f32:From<f64> warnings). The Linux-only desktop deps are target-gated so the rest of the stack — which already cross-compiles — can build off Linux: - Cargo.toml: ksni and rfd's xdg-portal backend move to [target.'cfg(target_os = "linux")'.dependencies]; non-Linux gets rfd with its native Win32/AppKit backend (default features). - tray.rs: cfg-split. The ksni/SNI implementation stays Linux-only; other OSes get a no-op `start() -> None`, i.e. windowed-only (identical to the Linux no-SNI-host path). TrayEvent/TrayHandle stay cross-platform. - plex.rs: add a Windows `symlink_file` arm to make_symlink (also fixes an unused-variable warning on non-unix). The rest was already portable (disk_space/statvfs, mpv IPC UnixStream, chmod/PermissionsExt guards all cfg(unix)). macOS is Unix so those apply there unchanged. Still not a *shipped* binary: needs a real per-OS tray backend and a linking CI matrix. ROADMAP 3.1 + CLAUDE.md updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ec8cf6f934
commit
d797f2a698
6 changed files with 80 additions and 18 deletions
13
src/plex.rs
13
src/plex.rs
|
|
@ -118,8 +118,17 @@ fn make_symlink(target: &Path, link: &Path) -> Result<(), String> {
|
|||
#[cfg(unix)]
|
||||
std::os::unix::fs::symlink(target, link)
|
||||
.map_err(|e| format!("{}: {e}", link.display()))?;
|
||||
#[cfg(not(unix))]
|
||||
return Err("symlinks are not supported on this platform".to_string());
|
||||
// Windows distinguishes file vs dir symlinks; the Plex tree only links to
|
||||
// video files. Requires Developer Mode or admin at runtime — a failure
|
||||
// here surfaces as the usual per-link error rather than aborting.
|
||||
#[cfg(windows)]
|
||||
std::os::windows::fs::symlink_file(target, link)
|
||||
.map_err(|e| format!("{}: {e}", link.display()))?;
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
{
|
||||
let _ = target;
|
||||
return Err("symlinks are not supported on this platform".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
19
src/tray.rs
19
src/tray.rs
|
|
@ -21,7 +21,7 @@
|
|||
//! the tray entirely optional — if `TrayController::start` fails the app
|
||||
//! continues normally.
|
||||
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
||||
/// Menu events emitted by the tray. The main app drains these in
|
||||
/// [`eframe::App::update`] and translates them into viewport commands or
|
||||
|
|
@ -49,8 +49,9 @@ pub struct TrayHandle {
|
|||
/// by ksni when the SNI host needs a property; menu activations call the
|
||||
/// boxed closures we store in `MenuItem::activate`, which forward into
|
||||
/// the channel back to the main thread.
|
||||
#[cfg(target_os = "linux")]
|
||||
struct TrayModel {
|
||||
tx: Sender<TrayEvent>,
|
||||
tx: std::sync::mpsc::Sender<TrayEvent>,
|
||||
/// PNG bytes for the icon, decoded once at construction. ksni asks
|
||||
/// for raw ARGB so we keep both forms.
|
||||
icon_argb: Vec<u8>,
|
||||
|
|
@ -58,6 +59,7 @@ struct TrayModel {
|
|||
icon_h: i32,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
impl ksni::Tray for TrayModel {
|
||||
fn id(&self) -> String {
|
||||
"yt-offline".into()
|
||||
|
|
@ -127,6 +129,7 @@ impl ksni::Tray for TrayModel {
|
|||
/// Returns `None` if the runtime / channel can't be set up. A `Some(_)`
|
||||
/// return does *not* guarantee the icon is actually visible — that depends
|
||||
/// on whether a StatusNotifier host is registered on the user's desktop.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn start(icon_png_bytes: &[u8]) -> Option<TrayHandle> {
|
||||
// Decode the PNG eagerly so we fail fast if the embedded asset is bad.
|
||||
let img = image::load_from_memory(icon_png_bytes).ok()?;
|
||||
|
|
@ -141,7 +144,7 @@ pub fn start(icon_png_bytes: &[u8]) -> Option<TrayHandle> {
|
|||
argb.push(px[2]);
|
||||
}
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let model = TrayModel {
|
||||
tx,
|
||||
icon_argb: argb,
|
||||
|
|
@ -175,3 +178,13 @@ pub fn start(icon_png_bytes: &[u8]) -> Option<TrayHandle> {
|
|||
|
||||
Some(TrayHandle { events: rx })
|
||||
}
|
||||
|
||||
/// Non-Linux stub: there's no StatusNotifierItem tray backend on Windows or
|
||||
/// macOS yet (ksni is Linux/SNI-only), so the tray is simply absent and the
|
||||
/// app runs windowed-only. A real implementation would need a per-OS backend
|
||||
/// (e.g. `tray-icon`) behind this same signature. Returning `None` makes
|
||||
/// `App` behave exactly as it does on Linux when no SNI host is registered.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn start(_icon_png_bytes: &[u8]) -> Option<TrayHandle> {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue