Skip to content
Merged
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
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@t3tools/desktop",
"version": "0.0.48",
"version": "0.0.49",
"private": true,
"type": "module",
"main": "dist-electron/main.cjs",
Expand Down
56 changes: 0 additions & 56 deletions apps/desktop/src/app/DesktopApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import * as DesktopAppIdentity from "./DesktopAppIdentity.ts";
import * as DesktopClerk from "./DesktopClerk.ts";
import * as DesktopApplicationMenu from "../window/DesktopApplicationMenu.ts";
import * as DesktopWindow from "../window/DesktopWindow.ts";
import * as DesktopBackendConfiguration from "../backend/DesktopBackendConfiguration.ts";
import * as DesktopBackendManager from "../backend/DesktopBackendManager.ts";
import * as DesktopBackendPool from "../backend/DesktopBackendPool.ts";
import * as FileSystem from "effect/FileSystem";
import * as DesktopEnvironment from "./DesktopEnvironment.ts";
import * as DesktopLifecycle from "./DesktopLifecycle.ts";
import * as DesktopLinuxUrlHandler from "./DesktopLinuxUrlHandler.ts";
Expand Down Expand Up @@ -218,59 +215,6 @@ const bootstrap = Effect.gen(function* () {
// in parallel rather than blocking primary readiness on a possibly
// slow first wsl.exe spawn.
yield* Effect.forkScoped(wslBackend.reconcile);
// Personal T3 Code home: when ~/.t3 (the pre-rebrand home the standalone
// t3code app used to serve) still holds a database, host it as a second
// local backend so the personal T3 Code + Clerk environment survives
// without a second app install. Forked for the same reason as WSL: a
// port scan or spawn must never block primary readiness. Port scan
// starts at primary+2 — the WSL secondary scans from primary+1.
yield* Effect.forkScoped(
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const net = yield* NetService.NetService;
const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration;
const personalHome = environment.path.join(
environment.path.dirname(environment.baseDir),
".t3",
);
const hasData = yield* fs
.exists(environment.path.join(personalHome, "userdata", "state.sqlite"))
.pipe(Effect.orElseSucceed(() => false));
if (!hasData) {
return;
}
let personalPort: number | null = null;
for (let candidate = backendPort + 2; candidate <= 65535; candidate += 1) {
if (yield* net.canListenOnHost(candidate, "127.0.0.1")) {
personalPort = candidate;
break;
}
}
if (personalPort === null) {
yield* logBootstrapInfo("no loopback port for the personal T3 backend; skipping");
return;
}
yield* logBootstrapInfo("registering personal T3 backend", {
home: personalHome,
port: personalPort,
});
const instance = yield* pool.register({
id: DesktopBackendManager.BackendInstanceId("local:t3"),
label: Effect.succeed("T3 Code (personal)"),
configResolve: configuration.resolveLocalHome({
port: personalPort,
t3Home: personalHome,
}),
});
yield* instance.start;
}).pipe(
Effect.catchCause((cause) =>
logBootstrapInfo("personal T3 backend registration failed", {
cause: Cause.pretty(cause),
}),
),
),
);
}
}).pipe(Effect.withSpan("desktop.bootstrap"));

Expand Down
76 changes: 0 additions & 76 deletions apps/desktop/src/backend/DesktopBackendConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,6 @@ export class DesktopBackendConfiguration extends Context.Service<
DesktopBackendManager.DesktopBackendStartConfig,
PlatformError.PlatformError
>;
// Build a start config for a secondary local backend serving another T3
// home directory (e.g. ~/.t3 — the pre-rebrand home the standalone t3code
// app used to serve), so the personal T3 Code + Clerk environment stays
// available without a second app install. Loopback-only: the primary owns
// LAN exposure.
readonly resolveLocalHome: (input: {
readonly port: number;
readonly t3Home: string;
}) => Effect.Effect<
DesktopBackendManager.DesktopBackendStartConfig,
PlatformError.PlatformError
>;
// The renderer-facing label for the primary instance, derived from the
// same decision resolvePrimary makes (including the WSL-availability
// fall-back to Windows), so the env switcher can't show "WSL" for a
Expand Down Expand Up @@ -531,59 +519,6 @@ const resolvePrimaryStartConfig = Effect.fn("desktop.backendConfiguration.resolv
},
);

const resolveLocalHomeStartConfig = Effect.fn("desktop.backendConfiguration.resolveLocalHome")(
function* (
input: SharedBootstrapInput & {
readonly port: number;
readonly t3Home: string;
},
): Effect.fn.Return<
DesktopBackendManager.DesktopBackendStartConfig,
never,
DesktopEnvironment.DesktopEnvironment
> {
const environment = yield* DesktopEnvironment.DesktopEnvironment;

const bootstrap = {
mode: "desktop" as const,
noBrowser: true,
port: input.port,
t3Home: input.t3Home,
// Loopback-only on purpose: this secondary serves a personal local
// environment; the primary owns LAN/tailscale exposure when the user
// opts in.
host: "127.0.0.1",
desktopBootstrapToken: input.bootstrapToken,
// PortSchema rejects 0, so the disabled pair still needs a valid
// number; the backend reads tailscaleServePort only when serve is
// enabled, so the value is inert.
tailscaleServeEnabled: false,
tailscaleServePort: 443,
// No telemetry fds and no resource-monitor sidecar: those pipelines
// belong to the primary. Like the WSL secondary, this instance reports
// resource telemetry unavailable.
...buildObservabilityFragment(input.observabilitySettings),
};

return {
executablePath: process.execPath,
args: [environment.backendEntryPath, "--bootstrap-fd", "3"],
entryPath: environment.backendEntryPath,
cwd: environment.backendCwd,
env: {
...backendChildEnvPatch(),
ELECTRON_RUN_AS_NODE: "1",
},
extendEnv: true,
bootstrap,
bootstrapDelivery: "fd3",
httpBaseUrl: new URL(`http://127.0.0.1:${input.port}`),
captureOutput: true,
preflightFailure: Option.none(),
} satisfies DesktopBackendManager.DesktopBackendStartConfig;
},
);

const resolveWslStartConfig = Effect.fn("desktop.backendConfiguration.resolveWsl")(function* (
input: SharedBootstrapInput & {
readonly port: number;
Expand Down Expand Up @@ -934,17 +869,6 @@ export const make = Effect.gen(function* () {
attributes: { port: input.port, distro: input.distro ?? null },
}),
),
resolveLocalHome: (input) =>
Effect.gen(function* () {
const shared = yield* sharedInputs;
return yield* resolveLocalHomeStartConfig({ ...shared, ...input }).pipe(
Effect.provideService(DesktopEnvironment.DesktopEnvironment, environment),
);
}).pipe(
Effect.withSpan("desktop.backendConfiguration.resolveLocalHome", {
attributes: { port: input.port, t3Home: input.t3Home },
}),
),
});
});

Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/backend/DesktopBackendPool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ function makePoolLayer(
resolvePrimary: Effect.die("unexpected primary config resolve"),
resolvePrimaryLabel: Ref.get(labelRef),
resolveWsl: () => Effect.die("unexpected WSL config resolve"),
resolveLocalHome: () => Effect.die("unexpected local-home config resolve"),
} satisfies DesktopBackendConfiguration.DesktopBackendConfiguration["Service"]),
DesktopAppSettings.layerTest(),
DesktopWslEnvironment.layerTest(),
Expand Down
15 changes: 5 additions & 10 deletions apps/desktop/src/ipc/methods/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
DesktopPreviewConfigInputSchema,
DesktopPreviewNavigateInputSchema,
DesktopPreviewRecordingArtifactSchema,
DesktopPreviewRecordingSourceSchema,
DesktopPreviewRecordingSaveInputSchema,
DesktopPreviewRegisterWebviewInputSchema,
DesktopPreviewScreenshotArtifactSchema,
Expand Down Expand Up @@ -174,15 +173,11 @@ export const cancelPickElement = tabMethod(
"desktop.ipc.preview.cancelPickElement",
(manager, tabId) => manager.cancelPickElement(tabId),
);
export const startRecording = DesktopIpc.makeIpcMethod({
channel: IpcChannels.PREVIEW_RECORDING_START_CHANNEL,
payload: DesktopPreviewTabInputSchema,
result: DesktopPreviewRecordingSourceSchema,
handler: Effect.fn("desktop.ipc.preview.startRecording")(function* ({ tabId }) {
const manager = yield* PreviewManager.PreviewManager;
return yield* manager.startRecording(tabId);
}),
});
export const startRecording = tabMethod(
IpcChannels.PREVIEW_RECORDING_START_CHANNEL,
"desktop.ipc.preview.startRecording",
(manager, tabId) => manager.startRecording(tabId),
);
export const stopRecording = tabMethod(
IpcChannels.PREVIEW_RECORDING_STOP_CHANNEL,
"desktop.ipc.preview.stopRecording",
Expand Down
16 changes: 13 additions & 3 deletions apps/desktop/src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,19 @@ contextBridge.exposeInMainWorld("desktopBridge", {
};
},
onQuitShortcut: (listener) => {
const wrappedListener = (_event: Electron.IpcRendererEvent, state: unknown) => {
if (state !== "down" && state !== "up") return;
listener(state);
const wrappedListener = (_event: Electron.IpcRendererEvent, hint: unknown) => {
if (typeof hint !== "object" || hint === null || !("state" in hint)) return;
if (hint.state === "up") {
listener({ state: "up" });
return;
}
if (
hint.state === "down" &&
"mode" in hint &&
(hint.mode === "hold" || hint.mode === "double-click")
) {
listener({ state: "down", mode: hint.mode });
}
};

ipcRenderer.on(IpcChannels.QUIT_SHORTCUT_CHANNEL, wrappedListener);
Expand Down
Loading
Loading