Live video on the AT Protocol
1import { app, dialog, ipcMain } from "electron";
2import { parseArgs } from "node:util";
3import "source-map-support/register";
4import getEnv from "./env";
5import makeNode from "./node";
6import initUpdater from "./updater";
7import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
8import { makeWindow } from "./window";
9import runTests from "./tests/test-runner";
10import { allTestNames } from "./tests/test-runner";
11
12// Handle creating/removing shortcuts on Windows when installing/uninstalling.
13if (require("electron-squirrel-startup")) {
14 app.quit();
15} else {
16 const { values: args, positionals } = parseArgs({
17 options: {
18 path: {
19 type: "string",
20 default: "",
21 },
22 "self-test": {
23 type: "boolean",
24 },
25 "self-test-duration": {
26 type: "string",
27 default: "300000",
28 },
29 "tests-to-run": {
30 type: "string",
31 default: allTestNames.join(","),
32 },
33 },
34 });
35 const env = getEnv();
36 console.log(
37 "starting with: ",
38 JSON.stringify({ args, positionals, env }, null, 2),
39 );
40
41 app.on("ready", async () => {
42 let privateKey: `0x${string}`;
43 if (process.env.AQD_ADMIN_ACCOUNT_KEY) {
44 privateKey = process.env.AQD_ADMIN_ACCOUNT_KEY as `0x${string}`;
45 } else {
46 privateKey = generatePrivateKey();
47 }
48 ipcMain.handle("getPrivateKey", () => privateKey);
49 const account = privateKeyToAccount(privateKey);
50 const env = {
51 SP_ADMIN_ACCOUNT: account.address.toLowerCase(),
52 SP_ALLOWED_STREAMS: account.address.toLowerCase(),
53 };
54 if (args["self-test"]) {
55 const success = await runTests(
56 args["tests-to-run"].split(","),
57 args["self-test-duration"],
58 privateKey,
59 );
60 if (!success) {
61 app.exit(1);
62 } else {
63 app.exit(0);
64 }
65 } else {
66 try {
67 await start(env);
68 } catch (e) {
69 console.error(e);
70 const dialogOpts: Electron.MessageBoxOptions = {
71 type: "info",
72 buttons: ["Quit Streamplace"],
73 title: "Error on Bootup",
74 message:
75 "Please report to the Streamplace developers at git.stream.place!",
76 detail: e.message + "\n" + e.stack,
77 };
78
79 await dialog.showMessageBox(dialogOpts);
80 app.quit();
81 }
82 }
83 });
84
85 const start = async (env: { [k: string]: string }): Promise<void> => {
86 const { skipNode, nodeFrontend, noUpdate } = getEnv();
87 if (!noUpdate) {
88 initUpdater();
89 }
90 let loadAddr;
91 if (!skipNode) {
92 const { addr } = await makeNode({ env, autoQuit: true });
93 loadAddr = addr;
94 }
95 const mainWindow = await makeWindow();
96
97 let startPath;
98 if (nodeFrontend) {
99 startPath = `${loadAddr}${args.path}`;
100 } else {
101 startPath = `http://127.0.0.1:38081${args.path}`;
102 }
103 console.log(`opening ${startPath}`);
104 mainWindow.loadURL(startPath);
105 };
106
107 // This method will be called when Electron has finished
108 // initialization and is ready to create browser windows.
109 // Some APIs can only be used after this event occurs.
110
111 // Quit when all windows are closed, except on macOS. There, it's common
112 // for applications and their menu bar to stay active until the user quits
113 // explicitly with Cmd + Q.
114 // app.on("window-all-closed", () => {
115 // if (process.platform !== "darwin") {
116 // app.quit();
117 // }
118 // });
119
120 app.on("activate", () => {
121 // On OS X it's common to re-create a window in the app when the
122 // dock icon is clicked and there are no other windows open.
123 // if (BrowserWindow.getAllWindows().length === 0) {
124 // }
125 });
126
127 // In this file you can include the rest of your app's specific main process
128 // code. You can also put them in separate files and import them here.
129}