Fixa omladdningsloopen + churn; CI/släpp flyttat till x64-byggnoden
Some checks failed
check / check (push) Failing after 1m4s

- KRITISKT: notify-watchern reagerade på Access-events, så vår egen
  läsning av configen triggade ny omladdning i all oändlighet (var
  155:e ms). Panelen revs och byggdes om konstant → blinkande hover,
  klick som aldrig landade. Nu filtreras eventen till riktiga
  skrivningar (Modify/Create/Remove/Close-Write).
- Titeländringar (webbläsare/terminaler) bygger inte längre om UI:t;
  tooltips slås i stället upp färskt vid hover (query-tooltip), och
  klick/skroll/menyer agerar på färskt fönster-state vid eventtillfället.
- hotspots::rebuild är idempotent (skippar om config+skärmar oförändrade).
- Settings: markup-escape i rubriker (Kant & skugga-varningen).
- CI: check + release körs på byggnoden brasse-linux01 (runs-on
  linux-amd64) — waydock byggs BARA för x86_64, aldrig på Pi5:ns
  arm-runner. Ny release.yaml: vX.Y.Z-tagg bygger x64-binären och
  laddar upp till Gitea-släppsidan + rullande latest. release.sh är
  nu bara tagga-och-pusha.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-29 23:51:27 +02:00
parent 0ded844b3a
commit e4e4d39405
10 changed files with 230 additions and 70 deletions

View File

@@ -389,11 +389,23 @@ pub fn watch(path: &Path, on_change: Rc<dyn Fn()>) {
let dir = path.parent().unwrap_or(Path::new(".")).to_path_buf();
let mut watcher = match notify::recommended_watcher(move |res: notify::Result<notify::Event>| {
use notify::event::{AccessKind, AccessMode, EventKind};
if let Ok(ev) = res {
let hit = ev
.paths
.iter()
.any(|p| p.file_name().map(|s| s.to_os_string()) == file_name);
// VIKTIGT: bara riktiga skrivningar. Access-events (öppna/läsa)
// måste ignoreras — annars triggar vår egen läsning en ny
// omladdning i all oändlighet.
let relevant = matches!(
ev.kind,
EventKind::Modify(_)
| EventKind::Create(_)
| EventKind::Remove(_)
| EventKind::Access(AccessKind::Close(AccessMode::Write))
);
let hit = relevant
&& ev
.paths
.iter()
.any(|p| p.file_name().map(|s| s.to_os_string()) == file_name);
if hit {
let _ = tx.send_blocking(());
}