Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions docs/developer/app-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,18 @@ Theme primitives hold palette and appearance values. Structural semantic tokens
map those values to the first-level regions, and structural selectors consume
the semantic tokens rather than naming the current contents.

| Structural token | Current mapping |
| Structural token | Current base mapping |
| --- | --- |
| `--app-shell-background` | `--paper` |
| `--app-shell-background` | `--hover-line` |
| `--app-header-background` | `--app-shell-background` |
| `--left-pane-background` | `rgb(var(--surface-rgb) / 42%)` |
| `--left-pane-background` | `--neutral-soft` |
| `--center-pane-background` | `--paper` |
| `--right-pane-background` | `--accent-soft` |
| `--right-pane-background` | `--neutral-soft` |

Palette and appearance overrides may replace a base mapping with a literal or
another theme role. For example, Olive light maps the app shell to `#dde1d2`.
The floating theme-token inspector reports each token's live computed custom-
property value so these overrides remain truthful.

Use full property suffixes such as `-background` for structural tokens. Child
content and component tokens keep their existing names until their vocabulary
Expand Down
1 change: 1 addition & 0 deletions scripts/app-layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const runtimeModuleNames = [
'startup-contract',
'startup-diagnostic',
't3-thread-titles',
'window-bounds',
'workspace-state',
'workspace-store'
] as const
Expand Down
56 changes: 28 additions & 28 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,7 @@ <h3>Selected UI direction</h3>
<img
id="brand-mark"
class="brand-mark"
src="../design/brand/markover-mark.svg"
alt=""
aria-hidden="true"
>
<img
id="brand-logotype"
class="brand-logotype"
src="../design/brand/markover-logotype.svg"
src="../design/brand/markover-lockup.svg"
alt=""
aria-hidden="true"
>
Expand Down Expand Up @@ -317,20 +310,6 @@ <h3>Selected UI direction</h3>
></div>

<div id="review-tab-strip" class="review-tab-strip" hidden>
<nav class="review-navigation-tabs" aria-label="Review organization">
<button
id="review-navigation-inbox"
class="review-navigation-tab is-active"
type="button"
aria-pressed="true"
>Inbox <span id="review-inbox-count" class="review-inbox-count">0</span></button>
<button
id="review-navigation-projects"
class="review-navigation-tab"
type="button"
aria-pressed="false"
>Projects</button>
</nav>
<form id="review-id-activation" class="review-id-activation">
<label class="visually-hidden" for="review-id-input">Open an exact review ID</label>
<input
Expand Down Expand Up @@ -366,6 +345,20 @@ <h3>Selected UI direction</h3>

<main id="pane-layout" class="pane-layout" hidden>
<aside id="left-pane" class="left-pane" hidden>
<nav class="review-navigation-tabs" aria-label="Review organization">
<button
id="review-navigation-inbox"
class="review-navigation-tab is-active"
type="button"
aria-pressed="true"
>Inbox <span id="review-inbox-count" class="review-inbox-count">0</span></button>
<button
id="review-navigation-projects"
class="review-navigation-tab"
type="button"
aria-pressed="false"
>Projects</button>
</nav>
<header class="documents-list-header">
<div class="pane-header-leading">
<span class="eyebrow">Reviews</span>
Expand Down Expand Up @@ -440,12 +433,6 @@ <h3>Selected UI direction</h3>
</div>
</div>
<div id="pinned-selection" class="pinned-selection" hidden></div>
<div id="scrollbar-row-cover" class="scrollbar-row-cover" hidden></div>
<div
id="hover-scrollbar-row-cover"
class="scrollbar-row-cover is-hovered"
hidden
></div>
<div id="tree" class="tree"></div>
<div class="keyboard-help">
<kbd>↑</kbd><kbd>↓</kbd> siblings
Expand Down Expand Up @@ -949,6 +936,19 @@ <h2 id="review-resolution-title">Resolve selected reviews?</h2>
</div>
</dialog>

<!-- TEMPORARY theme-token inspector. Remove with its styles and wiring. -->
<div id="theme-token-inspector" class="theme-token-inspector">
<header>
<span>Theme tokens</span>
<button id="theme-token-inspector-close" type="button" aria-label="Hide theme-token inspector">&times;</button>
</header>
<label class="theme-token-inspector-field">
<span>App header background</span>
<select id="theme-token-inspector-app-header-background"></select>
</label>
<div id="theme-token-inspector-tokens" class="theme-token-inspector-tokens"></div>
</div>

<script type="module" src="renderer.js"></script>
</body>
</html>
47 changes: 45 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ import {
} from './service-endpoint'
import { SettingsStore } from './settings-store'
import { t3ThreadTitleSnapshot } from './t3-thread-titles'
import {
WindowBoundsStore,
clampWindowBounds
} from './window-bounds'
import { WorkspaceStore } from './workspace-store'
import { smokeReviewTree } from './smoke-fixture'
import {
Expand Down Expand Up @@ -279,6 +283,7 @@ let remoteGatewayQueue: Promise<void> = Promise.resolve()
let serviceRepairQueue: Promise<void> = Promise.resolve()
let settingsStore: SettingsStore | null = null
let workspaceStore: WorkspaceStore | null = null
let windowBoundsStore: WindowBoundsStore | null = null
let zoomWriter: Promise<void> = Promise.resolve()
let managedAutosave: ReviewAutosave | null = null
let snapshotSequence = 0
Expand Down Expand Up @@ -1136,11 +1141,18 @@ function createWindow(
const startupSettings = settingsEnvelope(
settingsStore?.settings || DEFAULT_SETTINGS
)
const workAreaRect = screen.getPrimaryDisplay().workArea
const workArea = screen.getPrimaryDisplay().workAreaSize
const minimumSize = minimumWindowSize(startupSettings.zoomPercent, workArea)
const rememberedBounds = smokeMode || !windowBoundsStore?.bounds
? null
: clampWindowBounds(windowBoundsStore.bounds, workAreaRect, minimumSize)
const window = new BrowserWindow({
width: Math.min(1180, workArea.width),
height: Math.min(760, workArea.height),
width: rememberedBounds?.width ?? Math.min(1180, workArea.width),
height: rememberedBounds?.height ?? Math.min(760, workArea.height),
...(rememberedBounds
? { x: rememberedBounds.x, y: rememberedBounds.y }
: {}),
minWidth: minimumSize.width,
minHeight: minimumSize.height,
show: show && !showWithoutActivating,
Expand All @@ -1158,6 +1170,32 @@ function createWindow(
}
})
mainWindow = window
if (rememberedBounds?.maximized) window.maximize()
let boundsWriteTimer: NodeJS.Timeout | null = null
const recordWindowBounds = (): void => {
if (smokeMode || !windowBoundsStore || window.isDestroyed()) return
if (window.isFullScreen() || window.isMinimized()) return
const normal = window.getNormalBounds()
windowBoundsStore.save({
x: normal.x,
y: normal.y,
width: normal.width,
height: normal.height,
maximized: window.isMaximized()
})
}
const scheduleWindowBoundsWrite = (): void => {
if (boundsWriteTimer) clearTimeout(boundsWriteTimer)
boundsWriteTimer = setTimeout(recordWindowBounds, 250)
}
window.on('resize', scheduleWindowBoundsWrite)
window.on('move', scheduleWindowBoundsWrite)
window.on('maximize', scheduleWindowBoundsWrite)
window.on('unmaximize', scheduleWindowBoundsWrite)
window.on('close', () => {
if (boundsWriteTimer) clearTimeout(boundsWriteTimer)
recordWindowBounds()
})
let currentDisplayId = screen.getDisplayMatching(window.getBounds()).id
const applyCurrentWindowZoom = (): void => {
if (window.isDestroyed()) return
Expand Down Expand Up @@ -2312,6 +2350,11 @@ if (!hasSingleInstanceLock) {
)
workspaceStore = privateWorkspaceStore
await privateWorkspaceStore.load()
const boundsStore = new WindowBoundsStore(
path.join(app.getPath('userData'), 'window.json')
)
windowBoundsStore = boundsStore
await boundsStore.load()
managedAutosave = new ReviewAutosave(requireReviewStore(), {
maximumDelayMs: initialSettings.autosaveMaximumDelayMs,
onFailure(reviewId, error) {
Expand Down
Loading