Skip to content

feat(ui): window with a sidebar and status cards, after the chosen mockup - #20

Merged
mbeczynski merged 1 commit into
mainfrom
ui/redesign-makieta
Oct 9, 2026
Merged

mbeczynski merged 1 commit into
mainfrom
ui/redesign-makieta

Conversation

@mbeczynski

Copy link
Copy Markdown
Contributor

Redesign of the window and the menu bar popover after the mockup the owner picked (violet-to-cyan frame, sidebar, large title, glass cards with gradient borders, green status cards with pills). Only views, the theme and the Polish table change; the controller, services and status model are untouched.

Do not merge without a look at the running app - merging to main releases to Homebrew.

What follows the mockup

  • Window without a title bar (.windowStyle(.hiddenTitleBar)), gradient frame with a soft glow, ambient violet and cyan glow behind the content.
  • Sidebar: Overview / Backups / Storage / Settings, active item highlighted with the vertical violet accent; Cmd+1...4.
  • Large "CloudMachine" title; refresh time and a refresh icon button in the top-right corner, like the mockup's icon buttons.
  • Overview cards:
    • SSD buffer - real buffer size (large number), free disk space, upload queue.
    • Google Drive Time Machine - status dot + UploadState.headline (dot pulses while uploading); gradient progress bar with "84% | Backing up: 3.4 GB of 4 GB" only while Time Machine runs, from tmutil status; otherwise the age of the last completed backup.
    • System status - pill and headline; Disks - Drive mount, backup image, Time Machine destination.

Real data and error states

  • Green only when the state really is good (AppStatus.healthy, or every disk fact OK). A hard failure is red ("Action needed", "Not attached", "Drive disconnected"): image detached/dead (ENXIO counts as not attached), Drive not mounted, Time Machine not pointing here, upload needing action, no backup for hours. Unknown or self-passing states (tmutil did not answer, queue unknown, Google 750 GB limit) are amber.
  • Sections with a problem get a coloured dot in the sidebar (Backups: stale backup / dead watchdog; Storage: upload, free space, limit).
  • The error banner now shows in every section.

What is left out, and why

  • Sparkline in the SSD card and the Backup history chart: the app keeps no history of the buffer or the backups, and the task was not to add data collection. The sparkline's spot shows the upload queue; the chart's spot shows the upload card with its explanation.
  • Mockup sample values ("4,000 GB", "Optimized", "2 Drives") - replaced with real readings.
  • The Google Drive logo: an SF Symbol tile instead (no brand assets in the repo).

Nothing removed

Setup steps (with folder choice and image size), upload card, buffer details, space limit (limit field, Save, Measure now, quota command), OAuth credentials, Back up now / Stop, Check image consistency, Refresh, Open CloudMachine, Quit - all still there, sorted into sections:

  • Overview: setup steps (first, when any), the four cards, upload card, Back up now / Stop.
  • Backups: running backup (or "No backup is running"), backup cycle (last completed backup, watchdog run, and the watchdog's problem sentences, which the window never showed before), Back up now / Stop, Check image consistency.
  • Storage: upload card, buffer details, space limit.
  • Settings: OAuth credentials (no longer folded, since they have their own section).

Small fixes on the way

  • The views observe AppStatus directly. It is a separate ObservableObject whose changes do not go through the controller, so the window redrew only when credentials was assigned at the start of each refresh, and showed the previous cycle's readings.
  • The limit field placeholder showed "1.500": the interpolated literal became a LocalizedStringKey.
  • The selected section is remembered (@AppStorage("dashboardSection")).

Accessibility

  • Pills use fills dark enough for white text (about 4.5:1 or better); muted text on dark background about 7:1.
  • Pulsing dots and button press animations are off with Reduce Motion; cards go opaque and the frame glow goes away with Reduce Transparency.
  • Icons are hidden from VoiceOver or labelled (refresh, quit); sidebar items carry the selected trait and an "Attention" value when they have a problem; cards are combined into one element each.
  • Interface texts stay in English with Polish translations (L10n); 16 new keys added and 8 that are no longer used removed.

How it was checked

  • swift-format lint --strict --recursive Sources Tests - clean. Locally this was the Xcode toolchain's swift-format, not the Homebrew one CI uses, so CI has the final word.
  • swift build - OK.
  • swift test --filter "L10nTests|AppStatusHealthTests|UploadStateTests" - 35 tests, 0 failures (every key translated, no unused entries, no Polish in code). The full suite was not run locally; CI runs it.
  • Screenshots: a DEV harness outside the repo compiled these views against a stub controller with no side effects and rendered three scenarios (healthy, backup running, failure: ENXIO + Google daily limit + no backup for 26 h + stale watchdog), in Polish and English. The app itself was not launched, because on start it reloads the launchd agents (AgentRepair.afterLaunch), and that is the owner's production backup. cacheDisplay does not render blurs, so the glows in those screenshots look like hard circles; in the app they are blurred. Worth checking in the real window: the frame's corner radius against the system window corners, and the traffic lights over the sidebar.

🤖 Generated with Claude Code

…ckup

The window follows the mockup the owner picked: a violet-to-cyan frame, a
sidebar (Overview, Backups, Storage, Settings) under the traffic lights, a
large title and glass cards with gradient borders.

Every card shows what the app already reads; nothing is made up:
- SSD buffer: buffer size, free disk space and the upload queue (where the
  mockup has a sparkline - the app keeps no buffer history).
- Google Drive Time Machine: the upload state from `UploadState`, a progress
  bar only while Time Machine runs (no empty "0%" bar), otherwise the age of
  the last completed backup.
- System status and Disks: green only when the state really is good; a hard
  failure (image detached, Drive not mounted, no backup for hours, upload
  needing action) is red, an unknown or self-passing one amber.
- The mockup's backup history chart is left out: no history exists.

Nothing was removed: the setup steps, the error banner (now in every
section), the upload card, buffer details, space limit, OAuth credentials
and every button are still there, sorted into the sections. Sections with a
problem get a coloured dot in the sidebar. The backup watchdog's problem
sentences, which the window never showed, are listed under Backups.

The views now observe `AppStatus` themselves. It is a separate
ObservableObject, so the window redrew only when the controller assigned
`credentials` at the start of a refresh, and showed the previous cycle.

The menu bar popover gets the same frame, pill and tiles, plus the age of
the last completed backup. Pulsing status dots and button animations respect
Reduce Motion, cards turn opaque with Reduce Transparency, and pills use fills
dark enough for white text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mbeczynski
mbeczynski merged commit 849744d into main Oct 9, 2026
2 checks passed
@mbeczynski
mbeczynski deleted the ui/redesign-makieta branch October 9, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant