Files
warp-engine-client/src/renderer/views/TopBarView.ts
T
mr.zeroandClaude Opus 5 8511ccbef8
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
WarpEngine Client: the whole catalog, and a build that can point elsewhere
**The app is called WarpEngine Client.** "Store" named the thing it opens rather than the
thing you run, and the store is a catalog on a site, not a window on your machine. The
window title, the bundle, the packages and the menu entry follow; the repository already
did. The store being driven is named in the side menu, so the bar stopped repeating it as
a badge — the element stays in the page, hidden, because the window check reads it.

**Every title is listed, including the ones this machine cannot install.** They arrive
from the engine with `installable: false` and a reason, and they are drawn dimmed, with an
*unsupported platform* or *no build for this machine* badge, the engine's own sentence
underneath, and nothing to press: a disabled Install would invite a click that can never
work. They get a category of their own — *Not for this machine* — and they are kept out of
the native/hosted categories and counts, because a title with no build has no mode to be
counted under. An engine older than desktop 1.2.0 is unaffected: a missing `installable`
field reads as installable, which is what those engines mean.

**A build can be pointed at another site's registry:**

    make dist STORES_API=https://games.example.org/api/stores

BuildConfiguration reads the packaged package.json, where electron-builder's
extraMetadata writes that address, so a client for somebody else's catalog needs no source
change and nothing set on the user's machine. Precedence is runtime environment, then
build, then ours — three audiences, most specific first.

Also: the scrollbars are the window's own, because the platform's light track down the
side menu of a dark window looked like a mistake.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 19:45:54 +02:00

34 lines
1.5 KiB
TypeScript

import { requireElement, setHidden, setText } from '../dom/Dom'
import type { AppState } from '../state/AppStore'
export interface TopBarViewCallbacks {
readonly onToggleNavigation: () => void
}
/** The bar: what this is, which store is open, and how far a sync has got. */
export class TopBarView {
private readonly appName = requireElement('app-name', HTMLElement)
private readonly storeId = requireElement('store-id', HTMLElement)
private readonly progress = requireElement('progress', HTMLElement)
private readonly navToggle = requireElement('nav-toggle', HTMLButtonElement)
public constructor (callbacks: TopBarViewCallbacks) {
this.navToggle.addEventListener('click', callbacks.onToggleNavigation)
}
public render (state: AppState): void {
setText(this.appName, state.messages.appName)
// The bar names the app, not the store: which store is open is what the switcher in
// the side menu says, and saying it twice made the title read like a breadcrumb. The
// element stays in the page, hidden, because the window check reads it.
setText(this.storeId, state.currentStore === null ? '' : state.currentStore.id)
this.navToggle.title = state.messages.menu
this.navToggle.setAttribute('aria-label', state.messages.menu)
this.navToggle.setAttribute('aria-expanded', String(state.navigationOpen))
const progress = state.progress
setHidden(this.progress, progress === null)
setText(this.progress, progress === null ? '' : progress.label)
}
}