8 Commits

Author SHA1 Message Date
claude-timemachine b31fdd023a rename: cloud sync -> instance sync; cloud -> Timemachine Network; drop Tk
CI / test (3.10) (push) Successful in 7s
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 7s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
Product / UI / CLI / docs rebrand. Internal package, repo, and
on-disk dir names stay 'cloud_sync' / 'cloud-sync' / '.cloud-sync/'
to avoid breaking existing installs; a future commit can do the
file-system rename when the cost is worth paying.

User-facing changes:
  CLI prog name:        cloud-sync     -> instance-sync
  CLI description:      cloud-svc URL  -> Timemachine Network endpoint
  Dialog title:         CLOUD SYNC     -> INSTANCE SYNC
  Dialog title:         CLOUD CONFLICT -> INSTANCE CONFLICT
  Dialog title:         CONNECT CLOUD SAVE -> CONNECT TO THE NETWORK
  Card label:           Cloud Save     -> Remote Save
  Skip button:          Skip cloud sync -> Skip instance sync
  Body copy:            'the cloud'    -> 'the Timemachine Network'
  Window titles:        Cloud sync — ... -> Instance sync — ...
  Log prefix:           cloud-sync:    -> instance-sync:
  Error prose:          'cloud-sync token' -> 'instance-sync token'

Backend changes:
  restic --host tag:    cloud-sync     -> instance-sync
  State.host_tag dflt:  cloud-sync     -> instance-sync
  (Existing snapshots with the old tag still pull fine; we use 'latest'.)

Drop tkinter fallback: ui.py now offers Qt OR Headless. tkinter is
unnecessary given we already maintain Qt + headless; one less code
path to keep styled, smaller pyz. make_progress() picks Qt first,
falls through to HeadlessProgress on ImportError with a stderr hint
to 'pip install PySide6'.

README: rebrand title + prose; note repo/dir rename deferred; call
out the PySide6 install step. Conflict/login dialogs are now Qt-only;
without Qt, conflict aborts (defensive) and login tells the user to
paste the token manually.

52 tests green; no test-file label changes needed since they only
exercise internal APIs.
2026-06-05 01:14:02 +02:00
claude-timemachine f1cb9f4b86 feat(ui): inline SVG icons across all three dialogs
CI / test (3.10) (push) Successful in 6s
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 6s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
New module cloud_sync/icons.py:
  - CLOUD_SVG, STORAGE_SVG: card glyphs (Material Icons, Apache-2.0)
  - WARNING_BADGE_SVG, PLUS_BADGE_SVG, SYNC_BADGE_SVG: header badges
    (hand-rolled — circle + vector primitives, no glyph font dependency)
  - svg_pixmap(svg, size): QSvgRenderer-backed rasteriser; dual-binding
    helper falls back from PySide6 to PyQt6.QtSvg.

Wired into ui_qt.py:
  - Conflict dialog: warning badge SVG (light disc + dark !), cloud
    card SVG, storage card SVG. Drops the QSS circle hack — entire
    badge is one pixmap now.
  - Login dialog: plus badge SVG (Prism-green disc + dark +).
  - Progress window: sync arrow badge SVG (Prism-green disc + circular
    arrow + head).

QSS shed: no more bg/border-radius/font-size acrobatics for badges
since the SVG includes the disc. Card icons are crisp at any DPI.

52 tests still green; pyz grows ~5 KB for the SVG strings + the new
icons module.
2026-06-05 01:05:54 +02:00
claude-timemachine fa04fade74 style(ui): progress window matches conflict + login
CI / test (3.10) (push) Successful in 7s
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 7s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
Same skeleton: Prism-green badge ('↻') + uppercase title in the
header row, status text under it, indeterminate progress bar (dark
inset with Prism-green chunk), Cancel button bottom-right styled
as the shared 'secondary' button.

Bumped from 440x160 to 520x240 so the header reads at the same
weight as the other two dialogs. title.upper() applied in run_with
so callers can keep passing 'Cloud sync — pulling' without manual
uppercasing.

Three dialogs now share one visual language: Prism dark surface
(#313131), Prism-green accent (#96db59), monospace for code/data,
circled badge in the top-left of every header.
2026-06-04 23:34:50 +02:00
claude-timemachine aba6472292 style(ui): login dialog matches Steam-layout in Prism dark
CI / test (3.10) (push) Successful in 7s
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 7s
CI / build-pyz (push) Successful in 5s
CI / release (push) Has been skipped
Same skeleton as the conflict dialog: header (Prism-green badge +
uppercase title), body copy, content, foot row.

Specifics:
  - badge: '+' on Prism-green circle (vs the conflict's '!' on
    light gray) — green reads as 'setup / new', not warning
  - command callout: monospace, green text, dark inset card
  - token input: monospace, dark inset, green focus border, green
    selection highlight
  - 'Skip cloud sync' = secondary (dark surface, green hover border)
  - 'Save and continue' = primary (Prism-green fill, black text)

Same Enter-to-submit + format validation behavior as before;
on-screen error reuses Prism's BrightText red.
2026-06-04 23:32:32 +02:00
claude-timemachine 016c88f60f style(ui): conflict dialog in Prism dark palette
CI / test (3.10) (push) Successful in 7s
CI / test (3.11) (push) Successful in 8s
CI / test (3.12) (push) Successful in 8s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
Same Steam-Cloud-Conflict layout (header glyph + uppercase title +
two card-buttons + Cancel) but recolored to Prism's palette:

  background       #313131 (Prism Window)
  cards            #2a2a2a (Prism AlternateBase)
  card hover       #383838 + #96db59 border (Prism Highlight green)
  cancel button    #303030 + #96db59 border on hover

Warning glyph keeps the light circle (#d6dde6) for high contrast
against the dark surface — gives the same 'pay attention' weight
without forcing a different theme just for one dialog.
2026-06-04 23:23:47 +02:00
claude-timemachine 98c63a261b feat(ui): Steam-style conflict dialog
CI / test (3.10) (push) Successful in 7s
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 7s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
Replaces the radio+continue layout with a Steam Cloud Conflict
lookalike: uppercase title with circled-! glyph, three-line body
copy, two large card-buttons (Cloud Save / Local Save) each showing
icon + label + 'Modified <date>', Cancel bottom-right. Card click
commits the choice and dismisses — no separate Continue button.

Background switched to Steam-blue (#1b2838) instead of Prism dark
so the dialog reads as a 'pay attention' moment rather than another
status pane.

Card glyphs are unicode placeholders (☁ / ▢) — easy SVG swap later
if we want crisp HDD/cloud icons.

API change:
  prompt_conflict_qt(local_summary, remote_summary)
    → prompt_conflict_qt(local_modified, remote_modified, save_label)
  Caller now passes pre-formatted timestamp strings + an optional
  noun phrase ('Minecraft save').
2026-06-04 23:22:26 +02:00
claude-timemachine d4c76a4e37 feat(ui): login + conflict dialogs (Qt)
CI / test (3.10) (push) Successful in 7s
CI / test (3.11) (push) Successful in 7s
CI / test (3.12) (push) Successful in 8s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
Login dialog (prompt_login_qt):
  Modal asking for a discord_id:password token. Echo masked. Validates
  format before accepting. 'Skip cloud sync' returns None so caller can
  bypass sync without blocking the launch.

Conflict dialog (prompt_conflict_qt):
  Modal with three radio options — keep_local, use_remote, cancel.
  Shown when local files were modified since the last pulled snapshot
  AND the remote has a newer snapshot from another host (divergence
  state.json detection happens in sync.pull; not wired yet).

Both reuse the Prism dark palette via _apply_prism_dark. Tk fallbacks
not implemented — Qt is the path most players will hit.

Next: state.json (last_pulled_snapshot_id), divergence detection in
sync.pull, integration with these dialogs.
2026-06-04 23:19:25 +02:00
claude-timemachine fe26ed309c feat(ui): Qt progress window with Prism-Launcher-inspired dark palette
CI / test (3.10) (push) Successful in 8s
CI / test (3.11) (push) Successful in 6s
CI / test (3.12) (push) Successful in 7s
CI / build-pyz (push) Successful in 4s
CI / release (push) Has been skipped
cloud-sync now ships a real Qt UI alongside the tkinter fallback.

Architecture:
  - HeadlessProgress: --no-gui path, plain stdout
  - TkProgressWindow: stdlib fallback when Qt isn't installed
  - QtProgressWindow: preferred path; supports both PySide6 and PyQt6
    (interchangeable APIs for our subset)

The factory in ui.py picks Qt → tkinter → headless. Tk stays so the
zipapp still works on bare Python with no extras.

Threading: QApplication runs on the main thread (started by run_with
via QDialog.exec). The restic worker runs on a daemon threading.Thread.
Cross-thread UI updates go via a Signal on a bridge QObject so Qt
auto-marshals them onto the main thread via a queued connection.

Cancellation: WM close + Cancel button both set a flag. sync.pull/push
pass ui.is_cancelled as restic.run's cancel_check; the subprocess gets
killed and returns -1 → exit 1.

Theme: Fusion style + Prism's dark palette (RGB values copied as facts
from PrismLauncher's DarkTheme.cpp). Override with PRISM_THEME=off.

Pyz size went 20 KB → 36 KB (added ui.py + ui_qt.py).
33 tests still green.
2026-06-04 23:12:58 +02:00