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