Skip to content

Commit 24cacb3

Browse files
authored
Merge branch 'main' into feat/appearance-settings-tab
2 parents fbab76c + b7c89cf commit 24cacb3

129 files changed

Lines changed: 48065 additions & 8021 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.devcontainer/devcontainer.json‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22
"name": "T3 Code Dev",
33
"image": "debian:bookworm",
44
"features": {
5-
"ghcr.io/devcontainers-extra/features/bun:1": {},
5+
"ghcr.io/devcontainers/features/git:1": {},
6+
"ghcr.io/devcontainers-extra/features/bun:1": {
7+
"version": "1.3.11"
8+
},
69
"ghcr.io/devcontainers/features/node:1": {
7-
"version": "24",
8-
"nodeGypDependencies": true
10+
"version": "24.13.1"
911
},
1012
"ghcr.io/devcontainers/features/python:1": {
11-
"version": "3.12"
13+
"version": "3.10",
14+
"installTools": false
1215
}
1316
},
17+
"overrideFeatureInstallOrder": [
18+
"ghcr.io/devcontainers/features/git",
19+
"ghcr.io/devcontainers-extra/features/bun"
20+
],
1421
"postCreateCommand": {
1522
"bun-install": "bun install --backend=copyfile --frozen-lockfile"
1623
},

‎.github/workflows/release.yml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
tags:
66
- "v*.*.*"
7+
- "!v*-nightly.*"
78
schedule:
89
- cron: "0 */3 * * *"
910
workflow_dispatch:
@@ -41,7 +42,7 @@ jobs:
4142
- id: check
4243
name: Compare HEAD to last nightly tag
4344
run: |
44-
last_nightly_tag=$(git tag --list 'nightly-v*' --sort=-creatordate | head -n 1)
45+
last_nightly_tag=$(git tag --list 'v*-nightly.*' 'nightly-v*' --sort=-creatordate | head -n 1)
4546
if [[ -z "$last_nightly_tag" ]]; then
4647
echo "No previous nightly tag found. Proceeding with release."
4748
echo "has_changes=true" >> "$GITHUB_OUTPUT"

‎.oxfmtrc.json‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,13 @@
1313
"apps/web/src/lib/vendor/qrcodegen.ts",
1414
"*.icon/**"
1515
],
16-
"sortPackageJson": {}
16+
"sortPackageJson": {},
17+
"overrides": [
18+
{
19+
"files": [".devcontainer/devcontainer.json"],
20+
"options": {
21+
"trailingComma": "none"
22+
}
23+
}
24+
]
1725
}

‎.vscode/settings.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"source.fixAll.oxc": "always"
66
},
77
"oxc.unusedDisableDirectives": "warn",
8-
"typescript.tsdk": "node_modules/typescript/lib"
8+
"js/ts.tsdk.path": "node_modules/typescript/lib"
99
}

‎apps/desktop/src/clientPersistence.test.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
5353
confirmThreadArchive: true,
5454
confirmThreadDelete: false,
5555
diffWordWrap: true,
56+
favorites: [],
5657
sidebarProjectGroupingMode: "repository_path",
5758
sidebarProjectGroupingOverrides: {
5859
"environment-1:/tmp/project-a": "separate",

‎apps/desktop/src/main.ts‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import {
7575
} from "./updateMachine.ts";
7676
import { isArm64HostRunningIntelBuild, resolveDesktopRuntimeInfo } from "./runtimeArch.ts";
7777
import { resolveDesktopAppBranding } from "./appBranding.ts";
78+
import { bindFirstRevealTrigger, type RevealSubscription } from "./windowReveal.ts";
7879

7980
syncShellEnvironment();
8081

@@ -1998,16 +1999,17 @@ function createWindow(): BrowserWindow {
19981999
emitUpdateState();
19992000
});
20002001

2001-
let initialRevealScheduled = false;
2002-
const revealInitialWindow = () => {
2003-
if (initialRevealScheduled) {
2004-
return;
2005-
}
2006-
initialRevealScheduled = true;
2007-
revealWindow(window);
2008-
};
2009-
2010-
window.once("ready-to-show", revealInitialWindow);
2002+
// On Linux/Wayland with `show: false`, Electron's `ready-to-show` only
2003+
// fires after `show()` is called, deadlocking the standard "wait for
2004+
// ready, then show" pattern. Add `did-finish-load` as a Linux-only
2005+
// fallback so the window still surfaces once the renderer has loaded
2006+
// the page. Other platforms keep the no-flash `ready-to-show` path,
2007+
// since `did-finish-load` typically fires before the first paint there.
2008+
const revealSubscribers: RevealSubscription[] = [(fire) => window.once("ready-to-show", fire)];
2009+
if (process.platform === "linux") {
2010+
revealSubscribers.push((fire) => window.webContents.once("did-finish-load", fire));
2011+
}
2012+
bindFirstRevealTrigger(revealSubscribers, () => revealWindow(window));
20112013

20122014
if (isDevelopment) {
20132015
void window.loadURL(resolveDesktopDevServerUrl());
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { EventEmitter } from "node:events";
2+
3+
import { describe, expect, it, vi } from "vitest";
4+
5+
import { bindFirstRevealTrigger } from "./windowReveal.ts";
6+
7+
describe("bindFirstRevealTrigger", () => {
8+
it("reveals when the first trigger fires", () => {
9+
const window = new EventEmitter();
10+
const webContents = new EventEmitter();
11+
const reveal = vi.fn();
12+
13+
bindFirstRevealTrigger(
14+
[
15+
(fire) => window.once("ready-to-show", fire),
16+
(fire) => webContents.once("did-finish-load", fire),
17+
],
18+
reveal,
19+
);
20+
21+
window.emit("ready-to-show");
22+
23+
expect(reveal).toHaveBeenCalledTimes(1);
24+
});
25+
26+
it("reveals when only the fallback trigger fires (Wayland deadlock case)", () => {
27+
const window = new EventEmitter();
28+
const webContents = new EventEmitter();
29+
const reveal = vi.fn();
30+
31+
bindFirstRevealTrigger(
32+
[
33+
(fire) => window.once("ready-to-show", fire),
34+
(fire) => webContents.once("did-finish-load", fire),
35+
],
36+
reveal,
37+
);
38+
39+
webContents.emit("did-finish-load");
40+
41+
expect(reveal).toHaveBeenCalledTimes(1);
42+
});
43+
44+
it("only reveals once when multiple triggers fire", () => {
45+
const window = new EventEmitter();
46+
const webContents = new EventEmitter();
47+
const reveal = vi.fn();
48+
49+
bindFirstRevealTrigger(
50+
[
51+
(fire) => window.once("ready-to-show", fire),
52+
(fire) => webContents.once("did-finish-load", fire),
53+
],
54+
reveal,
55+
);
56+
57+
webContents.emit("did-finish-load");
58+
window.emit("ready-to-show");
59+
60+
expect(reveal).toHaveBeenCalledTimes(1);
61+
});
62+
63+
it("subscribers using `once` ignore re-emitted events after reveal", () => {
64+
const window = new EventEmitter();
65+
const reveal = vi.fn();
66+
67+
bindFirstRevealTrigger([(fire) => window.once("ready-to-show", fire)], reveal);
68+
69+
window.emit("ready-to-show");
70+
window.emit("ready-to-show");
71+
72+
expect(reveal).toHaveBeenCalledTimes(1);
73+
});
74+
});

‎apps/desktop/src/windowReveal.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export type RevealSubscription = (listener: () => void) => void;
2+
3+
/**
4+
* Wire a reveal callback to fire exactly once, on whichever of the provided
5+
* event subscribers fires first. Each subscriber is responsible for binding
6+
* its own event source.
7+
*
8+
* Used by the desktop main window's first-paint reveal logic. The standard
9+
* Electron pattern is to wait for `ready-to-show` before calling `show()`,
10+
* but on Linux/Wayland with `show: false`, `ready-to-show` only fires after
11+
* `show()` is called, deadlocking that pattern. Subscribing to both
12+
* `ready-to-show` and `did-finish-load` (or any other "renderer is alive"
13+
* signal) lets the window surface reliably across platforms.
14+
*/
15+
export function bindFirstRevealTrigger(
16+
subscribers: readonly RevealSubscription[],
17+
reveal: () => void,
18+
): void {
19+
let revealed = false;
20+
const fire = () => {
21+
if (revealed) return;
22+
revealed = true;
23+
reveal();
24+
};
25+
for (const subscribe of subscribers) {
26+
subscribe(fire);
27+
}
28+
}

‎apps/server/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@types/bun": "catalog:",
4545
"@types/node": "catalog:",
4646
"effect-acp": "workspace:*",
47+
"effect-codex-app-server": "workspace:*",
4748
"tsdown": "catalog:",
4849
"typescript": "catalog:",
4950
"vitest": "catalog:"

0 commit comments

Comments
 (0)