From 1f8b51310e581bee77214bef1d37ec0b6d04e0fc Mon Sep 17 00:00:00 2001 From: FTCHD <144691102+FTCHD@users.noreply.github.com> Date: Sun, 12 Jul 2026 00:30:36 +0300 Subject: [PATCH] remove unnecessary command --- lib/scheduler.ts | 11 -- src-tauri/src/lib.rs | 1 - src-tauri/src/scheduler/mod.rs | 212 +-------------------------------- 3 files changed, 1 insertion(+), 223 deletions(-) diff --git a/lib/scheduler.ts b/lib/scheduler.ts index 5b266f0..58d6abe 100644 --- a/lib/scheduler.ts +++ b/lib/scheduler.ts @@ -127,17 +127,6 @@ export async function schedulerReadLog(taskId: string, which: 'runner' | 'daemon }) } -export interface SchedulerDoctorCheck { - name: string - ok: boolean - detail: string - fix?: string -} - -export async function schedulerDoctor() { - return invoke('scheduler_doctor') -} - function buildJobSpec(task: ScheduledTask): SchedulerJobSpec { return { schemaVersion: 1, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6c687c5..2cd41cd 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -885,7 +885,6 @@ pub fn run() { scheduler::scheduler_status, scheduler::scheduler_read_history, scheduler::scheduler_read_log, - scheduler::scheduler_doctor, scheduler::scheduler_unregister_all, scheduler::scheduler_sweep_orphans, notifications::notifications_catalog, diff --git a/src-tauri/src/scheduler/mod.rs b/src-tauri/src/scheduler/mod.rs index 4d40d67..f9a43bd 100644 --- a/src-tauri/src/scheduler/mod.rs +++ b/src-tauri/src/scheduler/mod.rs @@ -346,7 +346,7 @@ pub fn scheduler_validate_cron(cron: String) -> CronValidation { valid: true, error: None, next_runs: cronconv::parse(&cron) - .map(|spec| cronconv::next_fires(&spec, chrono::Local::now(), 5)) + .map(|spec| cronconv::next_fires(&spec, chrono::Local::now(), 10)) .unwrap_or_default(), }, Err(error) => CronValidation { @@ -664,216 +664,6 @@ pub async fn scheduler_read_history( .map_err(|e| e.to_string())? } -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct DoctorCheck { - pub name: String, - pub ok: bool, - pub detail: String, - pub fix: Option, -} - -/// Preflight diagnostics with actionable fixes — the "why didn't my task run" surface. -#[tauri::command] -pub async fn scheduler_doctor() -> Result, String> { - tauri::async_runtime::spawn_blocking(move || { - let mut checks: Vec = Vec::new(); - - if crate::is_flatpak() { - // Scheduling works under Flatpak through the host's cron (crontab via - // `flatpak-spawn --host`, entries re-launch the app with `flatpak run`). The startup - // gate normally guarantees these permissions; verify anyway so the doctor stays - // truthful if that gate ever changes. - let ok = crate::has_flatpak_permissions(); - checks.push(DoctorCheck { - name: "Sandbox host access".to_string(), - ok, - detail: if ok { - "host filesystem and host-spawn access are granted — scheduling uses the host's cron" - .to_string() - } else { - "missing host filesystem or host-spawn permission — the app cannot reach the host's crontab" - .to_string() - }, - fix: if ok { - None - } else { - Some(format!( - "Grant it: flatpak override --user --filesystem=host --talk-name=org.freedesktop.Flatpak {}", - flatpak_app_id() - )) - }, - }); - if !ok { - return Ok(checks); - } - } - - #[cfg(unix)] - { - match crontab::check_available() { - Ok(()) => checks.push(DoctorCheck { - name: "cron installed".to_string(), - ok: true, - detail: if crate::is_flatpak() { - "crontab found on the host".to_string() - } else { - "crontab found in PATH".to_string() - }, - fix: None, - }), - Err(_) => { - checks.push(DoctorCheck { - name: "cron installed".to_string(), - ok: false, - detail: if crate::is_flatpak() { - "no crontab binary found on the host".to_string() - } else { - "no crontab binary found in PATH".to_string() - }, - fix: Some( - "Install 'cron' (Debian/Ubuntu) or 'cronie' (Fedora/Arch), then restart the app." - .to_string(), - ), - }); - return Ok(checks); - } - } - - match crontab::host_command("crontab").arg("-l").output() { - Ok(output) if output.status.success() => { - let managed = String::from_utf8_lossy(&output.stdout) - .lines() - .filter(|line| line.trim_start().starts_with("# rclone-ui-task:")) - .count(); - checks.push(DoctorCheck { - name: "crontab access".to_string(), - ok: true, - detail: format!("{} scheduled task(s) registered", managed), - fix: None, - }); - } - Ok(output) => { - let stderr = String::from_utf8_lossy(&output.stderr); - if crontab::stderr_means_no_crontab(&stderr) { - checks.push(DoctorCheck { - name: "crontab access".to_string(), - ok: true, - detail: "no crontab yet — created on first schedule".to_string(), - fix: None, - }); - } else { - checks.push(DoctorCheck { - name: "crontab access".to_string(), - ok: false, - detail: format!("crontab -l failed: {}", stderr.trim()), - fix: Some( - "Your user may be denied cron access (cron.deny / system policy)." - .to_string(), - ), - }); - } - } - Err(e) => checks.push(DoctorCheck { - name: "crontab access".to_string(), - ok: false, - detail: format!("could not run crontab: {}", e), - fix: None, - }), - } - } - - #[cfg(target_os = "linux")] - { - // Inside the Flatpak sandbox (own PID namespace) host processes are invisible to - // sysinfo — list them on the host instead. - let cron_running = if crate::is_flatpak() { - crontab::host_command("sh") - .arg("-c") - .arg("ps -e -o comm=") - .output() - .map(|o| { - String::from_utf8_lossy(&o.stdout) - .lines() - .any(|name| matches!(name.trim(), "cron" | "crond" | "cronie")) - }) - .unwrap_or(false) - } else { - let mut system = sysinfo::System::new(); - system.refresh_processes(sysinfo::ProcessesToUpdate::All, true); - system.processes().values().any(|process| { - let name = process.name().to_string_lossy().to_lowercase(); - name == "cron" || name == "crond" || name == "cronie" - }) - }; - checks.push(DoctorCheck { - name: "cron service".to_string(), - ok: cron_running, - detail: if cron_running { - "cron daemon is running".to_string() - } else { - "no cron daemon process found — schedules will not fire".to_string() - }, - fix: if cron_running { - None - } else { - Some("Enable it: sudo systemctl enable --now cron (or cronie)".to_string()) - }, - }); - } - - #[cfg(target_os = "macos")] - { - // TCC is the common silent failure for tasks touching Desktop/Documents/Downloads or - // external/network volumes. The fix differs by run mode: user-mode tasks run as the - // app via a LaunchAgent (grant the app), system-mode tasks run under cron (grant cron). - checks.push(DoctorCheck { - name: "macOS privacy (TCC)".to_string(), - ok: true, - detail: - "Tasks reading protected folders (Desktop, Documents, Downloads) or external/network volumes may be blocked by macOS privacy protections. A scheduled run cannot show a permission prompt, so access must be granted beforehand." - .to_string(), - fix: Some( - "'User' run mode (default): grant Rclone UI access to the folder, or add Rclone UI to Full Disk Access in System Settings → Privacy & Security. 'System' run mode: grant Full Disk Access to /usr/sbin/cron instead." - .to_string(), - ), - }); - } - - #[cfg(target_os = "windows")] - { - let query = std::process::Command::new("schtasks").arg("/Query").output(); - let ok = query.map(|o| o.status.success()).unwrap_or(false); - checks.push(DoctorCheck { - name: "Task Scheduler".to_string(), - ok, - detail: if ok { - "Task Scheduler service is reachable".to_string() - } else { - "schtasks query failed — the Task Scheduler service may be disabled".to_string() - }, - fix: if ok { - None - } else { - Some("Start the 'Task Scheduler' service (services.msc).".to_string()) - }, - }); - checks.push(DoctorCheck { - name: "Runs while logged out".to_string(), - ok: true, - detail: - "Schedules in 'System' run mode run while logged out (S4U) but cannot access mapped drives or implicit-auth network shares — schedules that need them should use the 'User' run mode. S4U also requires the 'Log on as a batch job' right: on domain-managed machines that deny it, System-mode tasks register but never start." - .to_string(), - fix: None, - }); - } - - Ok(checks) - }) - .await - .map_err(|e| e.to_string())? -} - /// Remove every registration this app ever made (Settings escape hatch / pre-uninstall cleanup). /// Sweeps both job files and orphaned OS artifacts by prefix. #[tauri::command]