authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-02-19 01:21:16-08:00
committergravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-02-19 01:21:16-08:00
loga32701ef8d6565875d126115389839abaea72c21
tree7236a534cefb54513202e05339fab64c281fb6fc
parentefbab1b104aebb2f72e152310f41a753aec347d6
signature Commit is signed but in an unrecognized format.

use icon


1 files changed, 42 insertions(+), 1 deletions(-)

apps/desktop/src/main.ts+42-1
...@@ -21,6 +21,8 @@ const BACKEND_ENTRY = path.join(ROOT_DIR, "apps/server/dist/index.mjs");...@@ -21,6 +21,8 @@ const BACKEND_ENTRY = path.join(ROOT_DIR, "apps/server/dist/index.mjs");
21const WEB_ENTRY = path.join(ROOT_DIR, "apps/web/dist/index.html");21const WEB_ENTRY = path.join(ROOT_DIR, "apps/web/dist/index.html");
22const STATE_DIR = path.join(os.homedir(), ".t3", "userdata");22const STATE_DIR = path.join(os.homedir(), ".t3", "userdata");
23const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);23const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
24const APP_DISPLAY_NAME = "T3 Code";
25const APP_USER_MODEL_ID = "com.t3tools.t3code";
2426
25let mainWindow: BrowserWindow | null = null;27let mainWindow: BrowserWindow | null = null;
26let backendProcess: ChildProcess | null = null;28let backendProcess: ChildProcess | null = null;
...@@ -31,6 +33,41 @@ let restartAttempt = 0;...@@ -31,6 +33,41 @@ let restartAttempt = 0;
31let restartTimer: ReturnType<typeof setTimeout> | null = null;33let restartTimer: ReturnType<typeof setTimeout> | null = null;
32let isQuitting = false;34let isQuitting = false;
3335
36function resolveResourcePath(fileName: string): string | null {
37 const candidates = [
38 path.join(__dirname, "../resources", fileName),
39 path.join(process.resourcesPath, "resources", fileName),
40 path.join(process.resourcesPath, fileName),
41 ];
42
43 for (const candidate of candidates) {
44 if (fs.existsSync(candidate)) {
45 return candidate;
46 }
47 }
48
49 return null;
50}
51
52function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
53 return resolveResourcePath(`icon.${ext}`);
54}
55
56function configureAppIdentity(): void {
57 app.setName(APP_DISPLAY_NAME);
58
59 if (process.platform === "win32") {
60 app.setAppUserModelId(APP_USER_MODEL_ID);
61 }
62
63 if (process.platform === "darwin" && app.dock) {
64 const iconPath = resolveIconPath("png");
65 if (iconPath) {
66 app.dock.setIcon(iconPath);
67 }
68 }
69}
70
34async function reserveLoopbackPort(): Promise<number> {71async function reserveLoopbackPort(): Promise<number> {
35 return new Promise((resolve, reject) => {72 return new Promise((resolve, reject) => {
36 const probe = net.createServer();73 const probe = net.createServer();
...@@ -207,7 +244,8 @@ function registerIpcHandlers(): void {...@@ -207,7 +244,8 @@ function registerIpcHandlers(): void {
207function getIconOption(): { icon: string } | Record<string, never> {244function getIconOption(): { icon: string } | Record<string, never> {
208 if (process.platform === "darwin") return {}; // macOS uses .icns from app bundle245 if (process.platform === "darwin") return {}; // macOS uses .icns from app bundle
209 const ext = process.platform === "win32" ? "ico" : "png";246 const ext = process.platform === "win32" ? "ico" : "png";
210 return { icon: path.join(__dirname, `../resources/icon.${ext}`) };247 const iconPath = resolveIconPath(ext);
248 return iconPath ? { icon: iconPath } : {};
211}249}
212250
213function createWindow(): BrowserWindow {251function createWindow(): BrowserWindow {
...@@ -219,6 +257,7 @@ function createWindow(): BrowserWindow {...@@ -219,6 +257,7 @@ function createWindow(): BrowserWindow {
219 show: false,257 show: false,
220 autoHideMenuBar: true,258 autoHideMenuBar: true,
221 ...getIconOption(),259 ...getIconOption(),
260 title: APP_DISPLAY_NAME,
222 titleBarStyle: "hiddenInset",261 titleBarStyle: "hiddenInset",
223 trafficLightPosition: { x: 16, y: 18 },262 trafficLightPosition: { x: 16, y: 18 },
224 webPreferences: {263 webPreferences: {
...@@ -253,6 +292,8 @@ function createWindow(): BrowserWindow {...@@ -253,6 +292,8 @@ function createWindow(): BrowserWindow {
253 return window;292 return window;
254}293}
255294
295configureAppIdentity();
296
256async function bootstrap(): Promise<void> {297async function bootstrap(): Promise<void> {
257 backendPort = await reserveLoopbackPort();298 backendPort = await reserveLoopbackPort();
258 backendAuthToken = randomBytes(24).toString("hex");299 backendAuthToken = randomBytes(24).toString("hex");