- lib.rs MAIN_WINDOW: the "main" window label that the reminder worker, the capture window and the shell each wrote, 5 sites in all. - lib.rs now_ms(): the epoch-milliseconds clock that the reminder worker and autosync's cycle stamp each computed. LastCycle.at_ms becomes i64, the same number on the wire. - integration.rs applications_dir(): the XDG launcher directory that the entry path and the desktop-database refresh each built. rustfmt --check is clean in the CI image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
|
||||
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender};
|
||||
use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use serde::Serialize;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
@@ -85,7 +85,7 @@ pub enum Trigger {
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct LastCycle {
|
||||
/// When it finished, in milliseconds since the epoch — the frontend formats it.
|
||||
pub at_ms: u64,
|
||||
pub at_ms: i64,
|
||||
pub trigger: Trigger,
|
||||
pub ok: bool,
|
||||
/// Why it failed, in words a person can act on. None when `ok`.
|
||||
@@ -299,9 +299,7 @@ fn worker(app: AppHandle, rx: Receiver<Request>) {
|
||||
}
|
||||
|
||||
let cycle = LastCycle {
|
||||
at_ms: SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_or(0, |d| d.as_millis() as u64),
|
||||
at_ms: crate::now_ms(),
|
||||
trigger,
|
||||
ok: result.is_ok(),
|
||||
error: result.as_ref().err().cloned(),
|
||||
|
||||
@@ -214,7 +214,7 @@ pub fn capture_done(saved: bool, app: AppHandle) -> Result<(), String> {
|
||||
window.hide().map_err(|e| e.to_string())?;
|
||||
}
|
||||
if saved {
|
||||
if let Some(main) = app.get_webview_window("main") {
|
||||
if let Some(main) = app.get_webview_window(crate::MAIN_WINDOW) {
|
||||
// Failure here is cosmetic — the note is saved either way and the board
|
||||
// will show it on its next load — so it is logged, not raised.
|
||||
if let Err(e) = main.emit(CAPTURED_EVENT, ()) {
|
||||
|
||||
@@ -42,8 +42,13 @@ fn appimage_path() -> Option<PathBuf> {
|
||||
std::env::var_os("APPIMAGE").map(PathBuf::from)
|
||||
}
|
||||
|
||||
/// Where per-user launchers live (XDG): `~/.local/share/applications`.
|
||||
fn applications_dir(home: &Path) -> PathBuf {
|
||||
home.join(".local/share/applications")
|
||||
}
|
||||
|
||||
fn desktop_entry_path() -> Option<PathBuf> {
|
||||
home().map(|h| h.join(".local/share/applications").join(DESKTOP_ENTRY_NAME))
|
||||
home().map(|h| applications_dir(&h).join(DESKTOP_ENTRY_NAME))
|
||||
}
|
||||
|
||||
fn icon_path() -> Option<PathBuf> {
|
||||
@@ -154,7 +159,7 @@ fn set_executable(_p: &Path) -> Result<(), String> {
|
||||
// Best-effort: refresh the desktop database so the entry appears promptly. The entry
|
||||
// still works on next login without it, so failures are ignored.
|
||||
fn refresh_desktop_database(home: &Path) {
|
||||
let apps = home.join(".local/share/applications");
|
||||
let apps = applications_dir(home);
|
||||
let _ = std::process::Command::new("update-desktop-database")
|
||||
.arg(&apps)
|
||||
.output();
|
||||
|
||||
@@ -54,6 +54,18 @@ pub(crate) fn display_version() -> &'static str {
|
||||
// this crate — the extraction changed where they live, not what they are.
|
||||
use inkwell_core::{local, sync};
|
||||
|
||||
/// The app's own window, as `tauri.conf.json` names it. The capture window is the
|
||||
/// other one (`capture::CAPTURE_WINDOW`).
|
||||
pub(crate) const MAIN_WINDOW: &str = "main";
|
||||
|
||||
/// Milliseconds since the Unix epoch: the unit the page's clocks and the reminder
|
||||
/// worker count in. 0 for a clock set before 1970.
|
||||
pub(crate) fn now_ms() -> i64 {
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map_or(0, |d| d.as_millis() as i64)
|
||||
}
|
||||
|
||||
pub fn run() {
|
||||
use tauri_plugin_log::{Target, TargetKind};
|
||||
|
||||
@@ -156,7 +168,7 @@ pub fn run() {
|
||||
reminders::start(app.handle())?;
|
||||
// Coming back to the window is when someone is about to look, so it asks
|
||||
// for a cycle. Rate-limited in autosync, because focus flaps constantly.
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
if let Some(window) = app.get_webview_window(MAIN_WINDOW) {
|
||||
let handle = app.handle().clone();
|
||||
window.on_window_event(move |event| {
|
||||
if let tauri::WindowEvent::Focused(true) = event {
|
||||
@@ -243,7 +255,7 @@ pub fn run() {
|
||||
/// colour, is a cosmetic loss and must never stop the app from opening.
|
||||
fn paint_window_before_the_webview_does(app: &tauri::App) {
|
||||
use tauri::Manager;
|
||||
let Some(window) = app.get_webview_window("main") else {
|
||||
let Some(window) = app.get_webview_window(MAIN_WINDOW) else {
|
||||
return;
|
||||
};
|
||||
// Unknown theme reads as light, matching the platform default we'd get anyway.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
//! reports clicks only on mobile. The toast waiting in the window does.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use std::time::Duration;
|
||||
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri_plugin_notification::NotificationExt;
|
||||
@@ -53,7 +53,7 @@ fn worker(app: AppHandle) {
|
||||
let mut announcer = Announcer::default();
|
||||
loop {
|
||||
std::thread::sleep(TICK);
|
||||
let now = now_ms();
|
||||
let now = crate::now_ms();
|
||||
let due = match due(&app, now) {
|
||||
Ok(due) => due,
|
||||
Err(e) => {
|
||||
@@ -74,7 +74,7 @@ fn due(app: &AppHandle, now: i64) -> Result<Vec<DueReminder>, String> {
|
||||
}
|
||||
|
||||
fn announce(app: &AppHandle, reminder: &DueReminder) {
|
||||
if let Err(e) = app.emit_to("main", DUE_EVENT, reminder) {
|
||||
if let Err(e) = app.emit_to(crate::MAIN_WINDOW, DUE_EVENT, reminder) {
|
||||
log::warn!("could not tell the window about a due reminder: {e}");
|
||||
}
|
||||
if main_window_in_front(app) {
|
||||
@@ -99,16 +99,10 @@ fn announce(app: &AppHandle, reminder: &DueReminder) {
|
||||
/// Whether someone is looking at the main window right now. Unknown counts as no:
|
||||
/// a duplicate alert is a smaller failure than a missed one.
|
||||
fn main_window_in_front(app: &AppHandle) -> bool {
|
||||
app.get_webview_window("main")
|
||||
app.get_webview_window(crate::MAIN_WINDOW)
|
||||
.is_some_and(|w| w.is_focused().unwrap_or(false) && !w.is_minimized().unwrap_or(true))
|
||||
}
|
||||
|
||||
fn now_ms() -> i64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_or(0, |d| d.as_millis() as i64)
|
||||
}
|
||||
|
||||
/// Which occurrences have been announced. Keyed by note id, holding the `remind_at`
|
||||
/// announced: completing or snoozing a reminder changes that value, so the next
|
||||
/// occurrence is new to it.
|
||||
|
||||
Reference in New Issue
Block a user