Skip to content

Commit f61eb05

Browse files
committed
Merge upstream/main into fork with conflict resolution
Integrates 8 upstream commits: downloads page, app version display, terminal restart type fix, custom provider auth skip, default git action fix, desktop theme sync, error handling cleanup, and Codex overrides overflow fix. Resolves 5 merge conflicts preserving fork's multi-provider support.
2 parents fad5a92 + b37279c commit f61eb05

33 files changed

Lines changed: 1461 additions & 594 deletions

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
AGENTS.md
1+
AGENTS.md

apps/desktop/src/main.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,24 @@ import * as FS from "node:fs";
44
import * as OS from "node:os";
55
import * as Path from "node:path";
66

7-
import { app, BrowserWindow, dialog, ipcMain, Menu, nativeImage, protocol, shell } from "electron";
7+
import {
8+
app,
9+
BrowserWindow,
10+
dialog,
11+
ipcMain,
12+
Menu,
13+
nativeImage,
14+
nativeTheme,
15+
protocol,
16+
shell,
17+
} from "electron";
818
import type { MenuItemConstructorOptions } from "electron";
919
import * as Effect from "effect/Effect";
10-
import type { DesktopUpdateActionResult, DesktopUpdateState } from "@t3tools/contracts";
20+
import type {
21+
DesktopTheme,
22+
DesktopUpdateActionResult,
23+
DesktopUpdateState,
24+
} from "@t3tools/contracts";
1125
import { autoUpdater } from "electron-updater";
1226

1327
import type { ContextMenuItem } from "@t3tools/contracts";
@@ -34,6 +48,7 @@ fixPath();
3448

3549
const PICK_FOLDER_CHANNEL = "desktop:pick-folder";
3650
const CONFIRM_CHANNEL = "desktop:confirm";
51+
const SET_THEME_CHANNEL = "desktop:set-theme";
3752
const CONTEXT_MENU_CHANNEL = "desktop:context-menu";
3853
const OPEN_EXTERNAL_CHANNEL = "desktop:open-external";
3954
const MENU_ACTION_CHANNEL = "desktop:menu-action";
@@ -137,6 +152,14 @@ function getSafeExternalUrl(rawUrl: unknown): string | null {
137152
return parsedUrl.toString();
138153
}
139154

155+
function getSafeTheme(rawTheme: unknown): DesktopTheme | null {
156+
if (rawTheme === "light" || rawTheme === "dark" || rawTheme === "system") {
157+
return rawTheme;
158+
}
159+
160+
return null;
161+
}
162+
140163
function writeDesktopStreamChunk(
141164
streamName: "stdout" | "stderr",
142165
chunk: unknown,
@@ -1037,6 +1060,16 @@ function registerIpcHandlers(): void {
10371060
return showDesktopConfirmDialog(message, owner);
10381061
});
10391062

1063+
ipcMain.removeHandler(SET_THEME_CHANNEL);
1064+
ipcMain.handle(SET_THEME_CHANNEL, async (_event, rawTheme: unknown) => {
1065+
const theme = getSafeTheme(rawTheme);
1066+
if (!theme) {
1067+
return;
1068+
}
1069+
1070+
nativeTheme.themeSource = theme;
1071+
});
1072+
10401073
ipcMain.removeHandler(CONTEXT_MENU_CHANNEL);
10411074
ipcMain.handle(
10421075
CONTEXT_MENU_CHANNEL,

apps/desktop/src/preload.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { DesktopBridge } from "@t3tools/contracts";
33

44
const PICK_FOLDER_CHANNEL = "desktop:pick-folder";
55
const CONFIRM_CHANNEL = "desktop:confirm";
6+
const SET_THEME_CHANNEL = "desktop:set-theme";
67
const CONTEXT_MENU_CHANNEL = "desktop:context-menu";
78
const OPEN_EXTERNAL_CHANNEL = "desktop:open-external";
89
const MENU_ACTION_CHANNEL = "desktop:menu-action";
@@ -16,6 +17,7 @@ contextBridge.exposeInMainWorld("desktopBridge", {
1617
getWsUrl: () => wsUrl,
1718
pickFolder: () => ipcRenderer.invoke(PICK_FOLDER_CHANNEL),
1819
confirm: (message) => ipcRenderer.invoke(CONFIRM_CHANNEL, message),
20+
setTheme: (theme) => ipcRenderer.invoke(SET_THEME_CHANNEL, theme),
1921
showContextMenu: (items, position) => ipcRenderer.invoke(CONTEXT_MENU_CHANNEL, items, position),
2022
openExternal: (url: string) => ipcRenderer.invoke(OPEN_EXTERNAL_CHANNEL, url),
2123
onMenuAction: (listener) => {
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
---
2+
interface Props {
3+
title?: string;
4+
description?: string;
5+
}
6+
7+
const {
8+
title = "T3 Code",
9+
description = "T3 Code — The best way to code with AI.",
10+
} = Astro.props;
11+
---
12+
13+
<html lang="en">
14+
<head>
15+
<meta charset="UTF-8" />
16+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
17+
<meta name="description" content={description} />
18+
<link rel="preconnect" href="https://fonts.googleapis.com" />
19+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
20+
<link
21+
href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600&display=swap"
22+
rel="stylesheet"
23+
/>
24+
<link rel="icon" href="/favicon.ico" sizes="48x48" />
25+
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32" />
26+
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16" />
27+
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
28+
<title>{title}</title>
29+
</head>
30+
<body>
31+
<div class="page">
32+
<nav class="nav">
33+
<a href="/" class="nav-brand">
34+
<img src="/icon.png" alt="T3" class="nav-icon" />
35+
</a>
36+
<a
37+
href="https://github.com/pingdotgg/t3code"
38+
target="_blank"
39+
rel="noopener noreferrer"
40+
class="nav-github"
41+
>
42+
GitHub
43+
<span class="nav-github-arrow" aria-hidden="true">&#8599;</span>
44+
</a>
45+
</nav>
46+
47+
<main class="main">
48+
<slot />
49+
</main>
50+
51+
<footer class="footer">
52+
<span class="footer-copy">&copy; {new Date().getFullYear()} T3 Tools Inc</span>
53+
<div class="footer-links">
54+
<a href="https://github.com/pingdotgg/t3code" target="_blank" rel="noopener noreferrer">GitHub</a>
55+
<a href="https://discord.gg/jn4EGJjrvv" target="_blank" rel="noopener noreferrer">Discord</a>
56+
</div>
57+
</footer>
58+
</div>
59+
</body>
60+
</html>
61+
62+
<style is:global>
63+
:root {
64+
--bg: #09090b;
65+
--fg: #fafafa;
66+
--fg-muted: #a1a1aa;
67+
--fg-dim: #71717a;
68+
--border: rgba(255, 255, 255, 0.08);
69+
}
70+
71+
* {
72+
box-sizing: border-box;
73+
margin: 0;
74+
padding: 0;
75+
}
76+
77+
html {
78+
color-scheme: dark;
79+
}
80+
81+
body {
82+
background: var(--bg);
83+
color: var(--fg);
84+
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
85+
-webkit-font-smoothing: antialiased;
86+
-moz-osx-font-smoothing: grayscale;
87+
min-height: 100vh;
88+
overflow-x: hidden;
89+
}
90+
91+
body::after {
92+
content: "";
93+
position: fixed;
94+
inset: 0;
95+
pointer-events: none;
96+
opacity: 0.035;
97+
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
98+
background-repeat: repeat;
99+
background-size: 256px 256px;
100+
z-index: 9999;
101+
}
102+
103+
a {
104+
color: inherit;
105+
text-decoration: none;
106+
}
107+
108+
img {
109+
display: block;
110+
max-width: 100%;
111+
}
112+
113+
@keyframes fade-in {
114+
from {
115+
opacity: 0;
116+
transform: translateY(8px);
117+
}
118+
to {
119+
opacity: 1;
120+
transform: translateY(0);
121+
}
122+
}
123+
</style>
124+
125+
<style>
126+
/* ── Page ── */
127+
128+
.page {
129+
min-height: 100vh;
130+
display: flex;
131+
flex-direction: column;
132+
overflow-x: hidden;
133+
}
134+
135+
/* ── Navbar ── */
136+
137+
.nav {
138+
display: flex;
139+
align-items: center;
140+
justify-content: space-between;
141+
padding: 1.5rem 2.5rem;
142+
opacity: 0.5;
143+
transition: opacity 0.4s ease;
144+
}
145+
146+
.nav:hover {
147+
opacity: 1;
148+
}
149+
150+
.nav-brand {
151+
display: flex;
152+
align-items: center;
153+
}
154+
155+
.nav-icon {
156+
width: 28px;
157+
height: 28px;
158+
border-radius: 6px;
159+
}
160+
161+
.nav-github {
162+
display: flex;
163+
align-items: center;
164+
gap: 0.35rem;
165+
color: var(--fg-muted);
166+
font-size: 0.875rem;
167+
transition: color 0.3s ease;
168+
}
169+
170+
.nav-github:hover {
171+
color: var(--fg);
172+
}
173+
174+
.nav-github-arrow {
175+
display: inline-block;
176+
transition: transform 0.3s ease;
177+
}
178+
179+
.nav-github:hover .nav-github-arrow {
180+
transform: translateX(2px) translateY(-1px);
181+
}
182+
183+
/* ── Main content ── */
184+
185+
.main {
186+
flex: 1;
187+
display: flex;
188+
flex-direction: column;
189+
align-items: center;
190+
}
191+
192+
/* ── Footer ── */
193+
194+
.footer {
195+
display: flex;
196+
align-items: center;
197+
justify-content: space-between;
198+
padding: 1.5rem 2.5rem;
199+
font-size: 0.8rem;
200+
color: var(--fg-dim);
201+
}
202+
203+
.footer-links {
204+
display: flex;
205+
gap: 1.25rem;
206+
}
207+
208+
.footer-links a {
209+
color: var(--fg-dim);
210+
transition: color 0.3s ease;
211+
}
212+
213+
.footer-links a:hover {
214+
color: var(--fg);
215+
}
216+
217+
/* ── Mobile ── */
218+
219+
@media (max-width: 640px) {
220+
.nav {
221+
padding: 1.25rem;
222+
}
223+
224+
.footer {
225+
padding: 1.25rem;
226+
}
227+
}
228+
</style>

apps/marketing/src/lib/releases.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const REPO = "pingdotgg/t3code";
2+
3+
export const RELEASES_URL = `https://github.com/${REPO}/releases`;
4+
5+
const API_URL = `https://api.github.com/repos/${REPO}/releases/latest`;
6+
const CACHE_KEY = "t3code-latest-release";
7+
8+
export interface ReleaseAsset {
9+
name: string;
10+
browser_download_url: string;
11+
}
12+
13+
export interface Release {
14+
tag_name: string;
15+
html_url: string;
16+
assets: ReleaseAsset[];
17+
}
18+
19+
export async function fetchLatestRelease(): Promise<Release> {
20+
const cached = sessionStorage.getItem(CACHE_KEY);
21+
if (cached) return JSON.parse(cached);
22+
23+
const data = await fetch(API_URL).then((r) => r.json());
24+
25+
if (data?.assets) {
26+
sessionStorage.setItem(CACHE_KEY, JSON.stringify(data));
27+
}
28+
29+
return data;
30+
}

0 commit comments

Comments
 (0)