Skip to content

Commit

Permalink
refactor: with redux
Browse files Browse the repository at this point in the history
  • Loading branch information
pd4d10 committed Feb 11, 2024
1 parent 62f0b7f commit 7eb363d
Show file tree
Hide file tree
Showing 15 changed files with 301 additions and 260 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@electron-forge/plugin-auto-unpack-natives": "^7.2.0",
"@electron-forge/plugin-vite": "^7.2.0",
"@electron-forge/publisher-github": "^7.2.0",
"@reduxjs/toolkit": "^2.1.0",
"@types/eslint": "^8",
"@types/ini": "^4.1.0",
"@types/lodash-es": "^4.17.12",
Expand All @@ -59,6 +60,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-redux": "^9.1.0",
"typescript": "^5.3.3",
"universal-analytics": "^0.5.3"
},
Expand Down
39 changes: 22 additions & 17 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import { WinAdapter } from "./main/win";
import { MacosAdapter } from "./main/macos";
import { LinuxAdapter } from "./main/linux";
import { setUpdater, setReporter } from "./main/utils";
import { AppInfo } from "./renderer/app-context";
import { PageInfo, SessionDispatch } from "./renderer/session-context";
import { AppInfo } from "./reducers/app";
import { PageInfo, sessionSlice } from "./reducers/session";
import getPort from "get-port";
import { v4 } from "uuid";
import { Dispatch } from "./reducers";

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require("electron-squirrel-startup")) {
Expand Down Expand Up @@ -64,12 +65,9 @@ if (!gotTheLock) {
app.quit();
} else {
// send action to renderer
// const appDispatch: AppDispatch = (action) => {
// mainWindow?.webContents.send("app-dispatch", action);
// };
const sessionDispatch: SessionDispatch = (action) => {
mainWindow?.webContents.send("session-dispatch", action);
};
const dispatch = ((action: unknown) => {
mainWindow?.webContents.send("dispatch", action);
}) as Dispatch;

app.on("second-instance", () => {
if (mainWindow) {
Expand Down Expand Up @@ -160,20 +158,21 @@ if (!gotTheLock) {
);

const sessionId = v4();
sessionDispatch({
type: "add",
sessionId,
appId: app.id,
nodePort,
windowPort,
});
dispatch(
sessionSlice.actions.add({
sessionId,
appId: app.id,
nodePort,
windowPort,
}),
);

sp.on("error", (err) => {
dialog.showErrorBox(`Error: ${app.name}`, err.message);
});
sp.on("close", () => {
// console.log(`child process exited with code ${code}`)
sessionDispatch({ type: "remove", sessionId });
dispatch(sessionSlice.actions.remove(sessionId));
// TODO: Remove temp app
});

Expand All @@ -182,7 +181,12 @@ if (!gotTheLock) {
(chunk: Buffer) => {
// TODO: stderr colors
console.log(isError);
sessionDispatch({ type: "log", sessionId, text: chunk.toString() });
dispatch(
sessionSlice.actions.updateLog({
sessionId,
text: chunk.toString(),
}),
);
};

if (sp.stdout) {
Expand All @@ -201,6 +205,7 @@ if (!gotTheLock) {
const pages = payloads.flatMap((p) =>
p.status === "fulfilled" ? p.value : [],
);
console.log(ports, pages);
return pages;
});
ipcMain.handle("read-apps", () => {
Expand Down
2 changes: 1 addition & 1 deletion src/main/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppInfo } from "../renderer/app-context";
import { AppInfo } from "../reducers/app";

export abstract class Adapter {
abstract readApps(): Promise<(AppInfo | undefined)[]>;
Expand Down
2 changes: 1 addition & 1 deletion src/main/linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import ini from "ini";
import fs from "fs";
import { Adapter } from "./adapter";
import { readdirSafe, readFileSafe } from "./utils";
import { AppInfo } from "../renderer/app-context";
import { AppInfo } from "../reducers/app";

const desktopFilesDir = "/usr/share/applications";

Expand Down
8 changes: 7 additions & 1 deletion src/main/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ import fs from "fs";
import os from "os";
// import { setUpdateNotification } from 'electron-update-notification' // TODO:
import plist from "simple-plist";
import { MacosAppInfo } from "../types";
import { machineId } from "node-machine-id";
import ua from "universal-analytics";

interface MacosAppInfo {
CFBundleIdentifier: string;
CFBundleName: string;
CFBundleExecutable: string;
CFBundleIconFile: string;
}

export async function readdirSafe(p: string) {
try {
return await fs.promises.readdir(p);
Expand Down
2 changes: 1 addition & 1 deletion src/main/win.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from "path";
import type { HKEY, RegistryValue, RegistryStringEntry } from "registry-js";
import { Adapter } from "./adapter";
import { readdirSafe } from "./utils";
import { AppInfo } from "../renderer/app-context";
import { AppInfo } from "../reducers/app";

export class WinAdapter extends Adapter {
async readApps() {
Expand Down
60 changes: 60 additions & 0 deletions src/reducers/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { asyncThunkCreator, buildCreateSlice } from "@reduxjs/toolkit";

type AppId = string;
export type AppInfo = {
id: AppId;
name: string;
icon: string;
exePath: string;
hidden?: boolean;
};
type State = {
status: "idle" | "loading" | "failed";
info: Record<AppId, AppInfo>;
};

const initialState: State = {
status: "idle",
info: {},
};

export const appSlice = buildCreateSlice({
creators: { asyncThunk: asyncThunkCreator },
})({
name: "app",
initialState,
reducers: (create) => ({
read: create.asyncThunk(
async () => {
const { ipcRenderer } = require("electron");
const apps: AppInfo[] = await ipcRenderer.invoke("read-apps");
return apps;
},
{
pending: (state) => {
state.status = "loading";
},
fulfilled: (state, action) => {
state.status = "idle";
state.info = action.payload
.sort((a, b) => (a.id < b.id ? -1 : 1))
.reduce((s, app) => {
return {
...s,
[app.id]: app,
};
}, state.info);
},
rejected: (state) => {
state.status = "failed";
},
},
),
addTemp: create.reducer<AppInfo>((state, { payload }) => {
if (payload) {
state.info[payload.id] = payload; // TODO: Remove it after session closed
state.info[payload.id]!.hidden = true;
}
}),
}),
});
14 changes: 14 additions & 0 deletions src/reducers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as rr from "react-redux";
import { combineSlices, configureStore } from "@reduxjs/toolkit";
import { appSlice } from "./app";
import { sessionSlice } from "./session";

const reducer = combineSlices(appSlice, sessionSlice);
export const store = configureStore({ reducer });

export type Dispatch = (typeof store)["dispatch"];

export const useDispatch =
rr.useDispatch.withTypes<(typeof store)["dispatch"]>();
export const useSelector =
rr.useSelector.withTypes<ReturnType<typeof reducer>>();
73 changes: 73 additions & 0 deletions src/reducers/session.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { asyncThunkCreator, buildCreateSlice } from "@reduxjs/toolkit";

type SessionId = string;
type PageId = string;
export type PageInfo = {
description: string;
devtoolsFrontendUrl: string;
id: PageId;
title: string;
type: "node" | "page" | "webview";
url: string;
};
type SessionInfo = {
appId: string;
pages: Record<string, PageInfo>;
log: string;
nodePort: number;
windowPort: number;
};
type State = Record<SessionId, SessionInfo>;

const initialState: State = {};

export const sessionSlice = buildCreateSlice({
creators: { asyncThunk: asyncThunkCreator },
})({
name: "session",
initialState,
reducers: (create) => ({
add: create.reducer<{
sessionId: SessionId;
appId: string;
nodePort: number;
windowPort: number;
}>((state, { payload }) => {
state[payload.sessionId] = {
appId: payload.appId,
nodePort: payload.nodePort,
windowPort: payload.windowPort,
pages: {},
log: "",
};
}),
remove: create.reducer<SessionId>((state, { payload }) => {
delete state[payload];
}),
updatePages: create.asyncThunk(
async ({ ports, sessionId }: { ports: number[]; sessionId: string }) => {
const { ipcRenderer } = require("electron");
const pages: PageInfo[] = await ipcRenderer.invoke(
"fetch-pages",
ports,
);
return { sessionId, pages };
},
{
fulfilled: (state, { payload: { sessionId, pages } }) => {
state[sessionId]!.pages = {};
pages
.sort((a, b) => (a.id < b.id ? -1 : 1))
.forEach((page) => {
state[sessionId]!.pages[page.id] = page;
});
},
},
),
updateLog: create.reducer<{ sessionId: string; text: string }>(
(state, { payload }) => {
state[payload.sessionId]!.log += payload.text;
},
),
}),
});
82 changes: 0 additions & 82 deletions src/renderer/app-context.tsx

This file was deleted.

0 comments on commit 7eb363d

Please sign in to comment.