feat(scripts): automated screenshots with realistic demo data - #1500
Conversation
… data Starts a throwaway aw-server-rust (free port, temp db and HOME), seeds a deterministic year of multi-device demo data (macOS laptop, Linux desktop, Android phone synced via aw-sync), configures settings for clean shots, and captures the main web UI views in light and dark with Playwright. Run with `make screenshots` or `uv run scripts/screenshots.py`.
…report behind --only Demo categories get muted colors derived per theme so bar labels stay readable (#333 on light, white on dark, ~5:1 contrast). Trends and Work report have known webui bugs, so they are only captured on request.
|
@greptileai review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…e and schema.org image Generated with scripts/screenshots.py (ActivityWatch/activitywatch#1500): light and dark for 13 views. Latest section shows light with a dark-mode link; Activity and Timeline sliders gain a v0.14.0 stop. Homepage swaps the v0.9.3/v0.8.0 images.
|
| parser.add_argument("--full-page", action="store_true", help="capture every view as a full-page (tall) screenshot") | ||
| parser.add_argument("--keep-running", action="store_true", help="leave the seeded server up after capturing") | ||
| parser.add_argument("--no-capture", action="store_true", help="only start and seed the server (implies --keep-running)") | ||
| args = parser.parse_args() |
There was a problem hiding this comment.
Relative --server-bin and --webpath values pass the file checks in the caller’s directory, but run_server reuses them after changing to a temporary directory. For example, --server-bin aw-server-rust/target/release/aw-server passes the check, then fails to launch with FileNotFoundError. Resolve both paths before building, checking, or starting the server.
| args = parser.parse_args() | |
| args = parser.parse_args() | |
| args.server_bin = args.server_bin.resolve() | |
| args.webpath = args.webpath.resolve() |
There was a problem hiding this comment.
Fixed in 597fe56: resolve --server-bin/--webpath (and --out) right after parse_args, before build/check/start.
| page.on("pageerror", lambda exc: console_errors.append(str(exc))) | ||
| theme_dir = out_dir / theme | ||
| theme_dir.mkdir(parents=True, exist_ok=True) | ||
| for i, shot in enumerate(shots, start=1): |
There was a problem hiding this comment.
Partial refresh leaves old screenshots
--only changes each selected screenshot’s numeric prefix. After a full run writes 07-timeline.png, running --only timeline writes 01-timeline.png and leaves the old image untouched. Anyone using the original filename still gets the stale screenshot. Keep each view’s filename stable before filtering.
There was a problem hiding this comment.
Fixed in 597fe56: each view's NN prefix is fixed by its position in the full list (trends/work-report are 14/15), independent of --only.
| for a_s, a_e in active: | ||
| pieces = [(a_s, a_e, None)] | ||
| for m in meetings + lunch_browse: |
There was a problem hiding this comment.
Lunch browsing is marked as active without creating its window or web events. active excludes lunch, but the code only creates lunch events while splitting those remaining intervals. A browse session wholly inside lunch never reaches fill_session, so the demo misses the intended activity. Generate the lunch-browse sessions separately so the activity data matches the not-away periods.
There was a problem hiding this comment.
Fixed in 597fe56: lunch-browse sessions are now filled separately inside the lunch break; verified 0 window events outside not-afk.
…nch-browse sessions - Resolve --server-bin/--webpath/--out before starting the server in a temp cwd - File prefixes come from a view's place in the full list, so --only overwrites the same files (trends/work-report are 14/15) - Lunch-time browsing lies inside the lunch break and was never filled; generate it separately so window/web events match not-afk periods
|
@greptileai review |
| for lb_s, lb_e in lunch_browse: | ||
| fill_session(dev, rng, lb_s, lb_e, laptop_lunch()) |
There was a problem hiding this comment.
The separate lunch fill can create events that overlap work events. lunch lasts 35–55 minutes, but lunch_browse can end 39 minutes after lunch starts. When browsing runs past lunch, both loops fill the same time, recording two foreground activities at once. This makes the demo data less realistic and can inflate recorded activity time by a few minutes.
Clamp the browse end to lunch[1] before using it for events and not-away periods.
There was a problem hiding this comment.
Fixed in cdd86d3: the browse end is clamped to lunch[1].
#88) * feat(screenshots): data-driven page with latest shots, per-view version slider, and web-sized images The page is now generated from _data/screenshots.yml: a Latest section (filled by ActivityWatch/activitywatch scripts/screenshots.py), a 'How it has evolved' slider per view across versions, and the community competition gallery with credits. Displays downscaled WebP copies (36 MB -> 1.5 MB) and links the full PNGs. * feat(screenshots): add v0.14.0 shots (demo data) to the page, homepage and schema.org image Generated with scripts/screenshots.py (ActivityWatch/activitywatch#1500): light and dark for 13 views. Latest section shows light with a dark-mode link; Activity and Timeline sliders gain a v0.14.0 stop. Homepage swaps the v0.9.3/v0.8.0 images. * fix(screenshots): announce the selected version on the slider (aria-valuetext)
| def wait_until_loaded(page, timeout_s: float = 60) -> None: | ||
| try: | ||
| page.wait_for_load_state("networkidle", timeout=timeout_s * 1000) | ||
| except Exception: |
| page.wait_for_function(WAIT_FOR_LOADED_JS, timeout=timeout_s * 1000, polling=250) | ||
| try: | ||
| page.wait_for_load_state("networkidle", timeout=timeout_s * 1000) | ||
| except Exception: |
Adds
scripts/screenshots.py(uv script, Playwright) andmake screenshots: one command to take fresh screenshots of the current web UI for the website, README, docs and store listings.--build) or reuses the web UI and aw-server-rust from the submodule pins, then starts an isolated server: free port (refuses 5600/5666), temp db/HOME/XDG dirs, removed on exit, and refuses to seed a server that already has buckets.--size,--full-page,--only,--keep-runningto browse and pick extra shots). About 70 s per run once built.Output:
dist/screenshots/{light,dark}/NN-<view>.png. Trends and Work report are behind--onlyuntil ActivityWatch/aw-webui#1058 is fixed.Used for the v0.14.0 screenshots on activitywatch.net (ActivityWatch/activitywatch.github.io#88).