Skip to content

Commit f7759ab

Browse files
Merge pull request #194 from TheAngryRaven/BETA
Release BETA → main: landing page UX overhaul + mobile garage polish
2 parents ae123c7 + 411337f commit f7759ab

17 files changed

Lines changed: 580 additions & 266 deletions

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
> from git history and grouped by theme rather than exhaustive per-commit
1212
> detail.
1313
14+
## [2.5.1] - unreleased
15+
16+
### Added
17+
- **Log type bubble in the file browser.** Each session row (shown by date/time)
18+
now carries a small pill with the log's format — Dove, Dovex, XRK, XRZ,
19+
iRacing, VBO, MoTeC, UBX, NMEA, CSV, … — derived from the file's extension, so
20+
you can tell at a glance what kind of log each one is. Appears on local and
21+
cloud rows and in the Profile → Cloud logs list.
22+
23+
### Changed
24+
- **Landing page UX overhaul** — the home screen is simpler and friendlier. The
25+
cluster of small buttons that used to live inside the file dropzone is gone;
26+
importing a file is now a single large drag-and-drop / click-to-browse zone,
27+
and every other action (load sample data, browse saved files, download from
28+
the logger over Bluetooth, manage tracks, build your own logger) is a big,
29+
clearly-labelled tile. Pricing is no longer shown on the landing page — it
30+
lives on the registration page where you pick a plan. Colors and design tokens
31+
are unchanged; this is a layout/usability pass only.
32+
- **Mobile garage & header polish.** The Garage/Device drawer now covers the
33+
full screen on mobile (it stays at half width on larger screens) so it's
34+
easier to use on a phone. In the loaded-session header, the track/course label
35+
and edit button are consolidated into a single course control — now using a
36+
route icon (at every screen size) with the current track : course as its label
37+
from tablet up.
38+
39+
### Fixed
40+
- **Pro-mode panel resizing on touch.** Dragging a resizable divider (the
41+
left/right split and the InfoBox/MiniMap split in pro mode, plus the video
42+
panel) would stop after only a few pixels on touchscreens. The handle's
43+
invisible grab strip was only a few pixels wide while the drag-start margin
44+
extended over the neighbouring chart/map — so a finger landing just off the
45+
divider started the resize on an element without `touch-action: none`, and the
46+
browser reclaimed the gesture as a scroll. The grab strip is now wider and the
47+
start margin is aligned to it, so touch drags track all the way.
48+
1449
## [2.5.0] - 2026-06-13
1550

1651
### Added

CLAUDE.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
4. **Update credits** (in README) when adding new FOSS dependencies.
1818
5. **Never do on the server what you can do on the client.**
1919
6. **Add tests when possible**: New parsers, pure utilities, and protocol/format logic should ship with Vitest coverage. Bug fixes should add a regression test that fails before the fix. Don't leave testable logic untested.
20-
7. **Keep `CHANGELOG.md` updated**: Add user-facing changes under the `[Unreleased]` heading (Keep a Changelog format) as you make them — don't wait for release time. Cut a new version section + tag when releasing.
20+
7. **Keep `CHANGELOG.md` updated**: Add user-facing changes as you make them — don't wait for release time. **Once a beta version number has been picked (e.g. `2.5.1`), keep that version as the heading and mark it unreleased — `## [2.5.1] - unreleased` — and keep adding every change under that same section until it actually ships. Do NOT create a new `[Unreleased]` block or bump the patch number on every commit; we are not cutting a `.1` release per change.** Only on release do you set the date and tag, then start the next version. (A bare `[Unreleased]` is fine only before any beta version has been chosen.)
2121
8. **Keep it professional**: This is a public, released OSS project (v1.5.0+). Hold the bar — see the standards below.
2222

2323
---
@@ -615,7 +615,7 @@ The `course_layouts` table stores polyline drawings of track layouts (1:1 with c
615615

616616
**Draw tool**: In the VisualEditor, a "Draw" button allows clicking on the satellite map to build a polyline outline. It is shown whenever `showDrawTool` is set — **available to all users**, not just admin (the old `isAdminEditor` gate was removed). User-drawn (or lap-generated) outlines are persisted on `Course.layout` (a `{lat, lon}[]` polyline) through the normal track-storage CRUD, so they ride cloud-sync and travel with a community submission. Built-in courses still get their outline from `public/drawings.json` (see `loadCourseDrawings`); when editing, the user's own `course.layout` takes precedence over the built-in drawing.
617617

618-
**Manage Tracks (home screen)**: `FileImport` renders a **Manage Tracks** button (below "Download from Datalogger") that opens `TrackEditor` via its `triggerButton` + `startInManage` props — the track manager is reachable with no datalog loaded. The create-flow dialogs (`AddTrackDialog`/`AddCourseDialog`) pass `isNewTrack`/`showDrawTool` so location search + manual drawing are available there.
618+
**Manage Tracks (home screen)**: `LandingPage` renders a **Manage Tracks** action tile that opens `TrackEditor` via its `triggerButton` + `startInManage` props — the track manager is reachable with no datalog loaded. The create-flow dialogs (`AddTrackDialog`/`AddCourseDialog`) pass `isNewTrack`/`showDrawTool` so location search + manual drawing are available there.
619619

620620
**Generate Drawing**: A "Generate" button (visible when `showDrawTool` is true and either laps *or* GPS samples are available) auto-populates the drawing from GPS data. With detected laps it opens a picker — each lap **plus** a **Whole session** option; with no laps (a fresh track at a brand-new venue where waypoint mode never closed a lap) it generates straight from the full session trace, so the outline can be drawn before a course exists. Available in user-side TrackEditor when session data is loaded. Laps and samples are threaded from `Index.tsx``TrackEditor``VisualEditor` (and into the create-flow dialogs). The drawing state lives in `useTrackEditorForm` (`formLayout`) and is written into the course via `buildCourse()`. The editor's satellite basemap shares the race-line map's Esri **Wayback** imagery-date picker (`useWaybackImagery`), so lines can be placed against a cloud-free capture (online-only, lazy).
621621

@@ -775,6 +775,10 @@ Profile **Cloud logs** panel reuses `SessionBrowser` with its own rows.
775775
- **Display name = the session's date/time**, derived from `sessionStartTime` (the
776776
first valid sample), e.g. "2/12/2026 11:15 AM" — *not* the upload time or raw
777777
filename (filename is the row's `title`/tooltip + the stable IndexedDB key).
778+
- **Log type bubble:** each row shows a `FileTypeBadge` (`components/FileTypeBadge.tsx`)
779+
with the format derived from the file extension (`lib/logFileType.ts`, pure +
780+
unit-tested) — the format isn't persisted, so the extension is the source of
781+
truth. Used on FilesTab local + cloud rows and the Profile Cloud logs panel.
778782
- **Smart collapse:** a folder level is only rendered when there's more than one
779783
entry — a single track and/or single course auto-descends straight to the logs
780784
(the breadcrumb still records the collapsed segments so date names read in

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "doves-dataviewer",
33
"private": true,
4-
"version": "2.5.0",
4+
"version": "2.5.1",
55
"description": "Open-source, offline-first motorsport telemetry viewer (Dove's DataViewer / HackTheTrack).",
66
"license": "GPL-3.0-or-later",
77
"author": "TheAngryRaven",

src/components/ActionTile.tsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import type { LucideIcon } from "lucide-react";
2+
import { cn } from "@/lib/utils";
3+
4+
interface ActionTileProps {
5+
icon: LucideIcon;
6+
title: string;
7+
description: string;
8+
/** Click handler — rendered as a <button> unless `href` is set. */
9+
onClick?: () => void;
10+
/** When set, the tile renders as an external link instead of a button. */
11+
href?: string;
12+
disabled?: boolean;
13+
/** Native title attribute (tooltip), e.g. for an unsupported action. */
14+
hint?: string;
15+
/** Highlight the most important action with the primary accent. */
16+
featured?: boolean;
17+
/** Spin the icon (e.g. while an action is in progress). */
18+
spinning?: boolean;
19+
className?: string;
20+
}
21+
22+
const TILE_BASE =
23+
"group flex w-full items-start gap-4 rounded-xl border bg-card p-5 text-left transition-colors " +
24+
"hover:border-primary/50 hover:bg-accent disabled:pointer-events-none disabled:opacity-50";
25+
26+
/**
27+
* A big, scannable home-screen action: icon + title + one-line description.
28+
* Used across the landing page so every primary action reads the same way
29+
* (replacing the cluster of small outline buttons that used to live inside the
30+
* file dropzone). Renders as a button by default, or an external link when
31+
* `href` is provided; either way the visual content is identical.
32+
*/
33+
export function ActionTile({
34+
icon: Icon,
35+
title,
36+
description,
37+
onClick,
38+
href,
39+
disabled,
40+
hint,
41+
featured,
42+
spinning,
43+
className,
44+
}: ActionTileProps) {
45+
const classes = cn(
46+
TILE_BASE,
47+
featured && "border-primary/40 bg-primary/5 hover:bg-primary/10",
48+
className,
49+
);
50+
51+
const content = (
52+
<>
53+
<span
54+
className={cn(
55+
"flex h-11 w-11 shrink-0 items-center justify-center rounded-lg",
56+
featured ? "bg-primary text-primary-foreground" : "bg-primary/10 text-primary",
57+
)}
58+
>
59+
<Icon className={cn("h-5 w-5", spinning && "animate-spin")} />
60+
</span>
61+
<span className="space-y-1">
62+
<span className="block font-semibold text-foreground">{title}</span>
63+
<span className="block text-sm text-muted-foreground">{description}</span>
64+
</span>
65+
</>
66+
);
67+
68+
if (href) {
69+
return (
70+
<a
71+
href={href}
72+
target="_blank"
73+
rel="noopener noreferrer"
74+
className={classes}
75+
title={hint}
76+
>
77+
{content}
78+
</a>
79+
);
80+
}
81+
82+
return (
83+
<button type="button" onClick={onClick} disabled={disabled} title={hint} className={classes}>
84+
{content}
85+
</button>
86+
);
87+
}

0 commit comments

Comments
 (0)