Files
commitea/apps/desktop/src/main/index.ts
Croissant Le Doux 94199639f2 feat: read the real gitea backlog into the app (P1 thin slice)
The app now displays its own live backlog instead of fixtures. First
end of the sync loop — the tap-root (#1) grows list reads and a read
path through the Electron main process.

- @commitea/core: client gains `listIssues` (paginated, PRs excluded)
  and `listMilestones`; a `lifecycle-v0` mapper (closed→done,
  labelled/milestoned→triage, bare→diagnosis — steeping/review await
  event inference in P1-5). +10 unit tests.
- main: gitea bridge over IPC (token stays in main, never the renderer);
  config from env / .env.local; gated off under COMMITEA_E2E so the
  committed e2e stays on fixtures. Preload exposes the typed bridge.
- renderer: useBacklog() reconciles once on mount; issuesToBoardColumns
  shapes real issues into The pot. Board takes optional real columns +
  a loading state, falling back to demo fixtures when unconfigured.

Verified: 14 e2e green (fixture mode) + a gated live spec that launches
against the real repo — the board renders the actual 25 open + 9 closed
issues (screenshot). SQLite mirror + reconcile-on-a-timer + lifecycle
event inference are the next slices (#2/#3/#5).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:57:57 -04:00

48 lines
1.1 KiB
TypeScript

import { join } from 'node:path'
import { BrowserWindow, app, shell } from 'electron'
import { registerGiteaIpc } from './gitea.js'
function createWindow(): void {
const win = new BrowserWindow({
width: 1440,
height: 900,
minWidth: 1080,
minHeight: 700,
show: false,
autoHideMenuBar: true,
backgroundColor: '#F0F4F0',
webPreferences: {
preload: join(import.meta.dirname, '../preload/index.mjs'),
sandbox: false,
},
})
win.on('ready-to-show', () => win.show())
win.webContents.setWindowOpenHandler(({ url }) => {
void shell.openExternal(url)
return { action: 'deny' }
})
if (process.env.ELECTRON_RENDERER_URL) {
void win.loadURL(process.env.ELECTRON_RENDERER_URL)
} else {
void win.loadFile(join(import.meta.dirname, '../renderer/index.html'))
}
}
void app.whenReady().then(() => {
registerGiteaIpc()
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})