Skip to content

Commit 39fd66b

Browse files
authored
Migrate to TypeScript + Update packages (#41)
* Add TypeScript * Move IPC actions to an enum * Add types to src/actions/* * Add types for redux-logger * Add types to reducers/toastPopup * Add types to reducers/selectedTab * Add types to reducers/isTabAreaOpen * Add types to reducers/isDarkTheme * Add types to reducers/tabs * Fix reducers * Add types to hooks/usePrevious * Refactor - use Action and ActionCreator from redux typings * (Tentative?) fix types in App container * Add types to TabAreaContainer * Add types to TextAreaContainer * Add types to TitleBar * Rename local TitleBarProps to just Props * Add ToastPopupContainer + Add types for ToastPopup * Fix import (not using export default anymore) * Change Themes.js to Themes.ts * Add type to ThemeWrapper * Add types to TextArea * Fix reducer switch case * Update import * Add types to PopupMenuItem * Add types to Tab * Remove unused import * Add types to PopupMenu * Fix import in Tab * Add types to NewTabButton * Remove electron-is-dev dependency (using app.isPackaged now) * Add types to TabArea * Add types to App * Fix linter errors * Fix some more linter errors * Add types to placeholderVariations * Add types to ipcHooks * Add db schema and types to dbHandler * Make IpcActions enum members strings * Add types to usePrevious hook * Replace module.exports in defaultSettings * Add types to src/index * Delete old dbHandler * Fix TextArea linter errors * Fix ThemeWrapper (needs to be refactored) * Move main-process-related code to electron/ * Replace electron-packager with electron-builder, node-sass with sass * Add /dist to gitignore * Add tsconfig for rendere-process-related code * Address linter errors * Remove ipcHooks * Fix char counter in TextArea * Update .eslintrc.json
1 parent 7debbaa commit 39fd66b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+2157
-1760
lines changed

.eslintrc.json

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,50 @@
44
"es2021": true,
55
"node": true
66
},
7-
"extends": ["plugin:react/recommended", "airbnb", "prettier"],
7+
"extends": [
8+
"eslint:recommended",
9+
"plugin:@typescript-eslint/recommended",
10+
"airbnb",
11+
"prettier"
12+
],
13+
"parser": "@typescript-eslint/parser",
14+
"plugins": ["react", "@typescript-eslint"],
15+
"root": true,
816
"overrides": [],
917
"parserOptions": {
1018
"ecmaVersion": "latest",
11-
"sourceType": "module"
19+
"sourceType": "module",
20+
"project": ["tsconfig.json", "electron/tsconfig.json"]
21+
},
22+
"globals": {
23+
"NodeJS": true
24+
},
25+
"ignorePatterns": ["serviceWorker.js", "dist/**"],
26+
"settings": {
27+
"import/resolver": {
28+
"node": {
29+
"extensions": [".js", ".jsx", ".ts", ".tsx"],
30+
"moduleDirectory": ["src", "node_modules"]
31+
}
32+
}
1233
},
13-
"ignorePatterns": ["serviceWorker.js"],
14-
"plugins": ["react"],
1534
"rules": {
35+
"no-shadow": "off",
36+
"@typescript-eslint/no-shadow": ["error"],
37+
"no-unused-vars": "off",
38+
"@typescript-eslint/no-unused-vars": "error",
1639
"default-param-last": "off",
17-
"import/prefer-default-export": "off"
40+
"import/prefer-default-export": "off",
41+
"react/jsx-filename-extension": [1, { "extensions": [".tsx", ".ts"] }],
42+
"import/extensions": [
43+
"error",
44+
"ignorePackages",
45+
{
46+
"js": "never",
47+
"jsx": "never",
48+
"ts": "never",
49+
"tsx": "never"
50+
}
51+
]
1852
}
1953
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
# production
1212
/build
13+
/dist
1314
/release-builds
1415

1516
# misc

electron/main.ts

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { app, BrowserWindow, ipcMain } from "electron";
2+
import * as path from "path";
3+
import {
4+
createTab,
5+
deleteTab,
6+
initDatabaseWithDefaults,
7+
loadPersistedState,
8+
loadWindowSettings,
9+
saveCurrentlySelectedTab,
10+
saveIsAlwaysOnTop,
11+
saveIsDarkTheme,
12+
saveIsTabAreaOpen,
13+
saveWindowDimensions,
14+
setupDatabaseSource,
15+
swapTabs,
16+
updateTabContent,
17+
updateTabName,
18+
} from "../src/data/dbHandler";
19+
import {
20+
DEFAULT_MIN_WINDOW_HEIGHT,
21+
DEFAULT_MIN_WINDOW_WIDTH,
22+
} from "../src/data/defaultSettings";
23+
import { IpcActions } from "../src/data/ipcActions";
24+
25+
let window: BrowserWindow | null = null;
26+
27+
function createWindow() {
28+
const windowSettings = loadWindowSettings();
29+
if (!windowSettings) {
30+
// TODO
31+
throw new Error();
32+
}
33+
34+
window = new BrowserWindow({
35+
width: windowSettings.width,
36+
minWidth: DEFAULT_MIN_WINDOW_WIDTH,
37+
height: windowSettings.height,
38+
minHeight: DEFAULT_MIN_WINDOW_HEIGHT,
39+
webPreferences: { nodeIntegration: true },
40+
alwaysOnTop: windowSettings.isAlwaysOnTop,
41+
titleBarStyle: "hiddenInset",
42+
frame: false,
43+
backgroundColor: "#2E3440",
44+
});
45+
46+
window.loadURL(
47+
app.isPackaged
48+
? `file://${path.join(__dirname, "../build/index.html")}`
49+
: "http://localhost:3000/index.html"
50+
);
51+
52+
window.on("closed", () => {
53+
window = null;
54+
});
55+
56+
window.on("resize", () => {
57+
if (window) {
58+
const newDimensions = window.getSize();
59+
const [newWidth, newHeight] = newDimensions;
60+
saveWindowDimensions(newWidth, newHeight);
61+
}
62+
});
63+
}
64+
65+
app.on("ready", () => {
66+
setupDatabaseSource();
67+
initDatabaseWithDefaults();
68+
createWindow();
69+
});
70+
71+
app.on("window-all-closed", () => {
72+
app.quit();
73+
});
74+
75+
app.on("activate", () => {
76+
if (window === null) {
77+
createWindow();
78+
}
79+
});
80+
81+
// Register IPC listeners on the Main Process first...
82+
83+
ipcMain.once(IpcActions.LoadPersistedData, (event) => {
84+
const persistedState = loadPersistedState();
85+
// eslint-disable-next-line no-param-reassign
86+
event.returnValue = persistedState;
87+
});
88+
89+
ipcMain.once(IpcActions.CheckIfMacOs, (event) => {
90+
const isMacOS = process.platform === "darwin";
91+
// eslint-disable-next-line no-param-reassign
92+
event.returnValue = isMacOS;
93+
});
94+
95+
// Tabs
96+
97+
ipcMain.on(IpcActions.CreateTab, (_, payload) => {
98+
const { id, index, name } = payload;
99+
createTab(id, index, name);
100+
});
101+
102+
ipcMain.on(IpcActions.UpdateTabName, (_, payload) => {
103+
const { id, newName } = payload;
104+
updateTabName(id, newName);
105+
});
106+
107+
ipcMain.on(IpcActions.UpdateTabContent, (_, payload) => {
108+
const { id, newContent } = payload;
109+
updateTabContent(id, newContent);
110+
});
111+
112+
ipcMain.on(IpcActions.SwapTabs, (_, payload) => {
113+
const { id, isMovingUp } = payload;
114+
swapTabs(id, isMovingUp);
115+
});
116+
117+
ipcMain.on(IpcActions.DeleteTab, (_, payload) => {
118+
const { id } = payload;
119+
deleteTab(id);
120+
});
121+
122+
// Tab Area Open
123+
124+
ipcMain.on(IpcActions.ToggleOpenTabArea, () => {
125+
saveIsTabAreaOpen();
126+
});
127+
128+
// Select Tab
129+
130+
ipcMain.on(IpcActions.SelectTab, (_, payload) => {
131+
const { tabId } = payload;
132+
saveCurrentlySelectedTab(tabId);
133+
});
134+
135+
// Color Theme
136+
137+
ipcMain.on(IpcActions.ToggleColorTheme, () => {
138+
saveIsDarkTheme();
139+
});
140+
141+
ipcMain.on(IpcActions.ToggleAlwaysOnTopRequest, (event) => {
142+
if (window) {
143+
const isNowAlwaysOnTop = !window.isAlwaysOnTop();
144+
window.setAlwaysOnTop(isNowAlwaysOnTop);
145+
saveIsAlwaysOnTop();
146+
147+
event.sender.send(IpcActions.ToggleAlwaysOnTopResponse, {
148+
message: isNowAlwaysOnTop ? "Always on top on." : "Always on top off.",
149+
});
150+
}
151+
});
152+
153+
// Window Controls (Non-MacOS only)
154+
155+
ipcMain.on(IpcActions.MinimizeWindow, () => {
156+
window?.minimize();
157+
});
158+
159+
ipcMain.on(IpcActions.ToggleMaximizeWindow, () => {
160+
if (window) {
161+
if (window.isMaximized()) {
162+
window.unmaximize();
163+
} else {
164+
window.maximize();
165+
}
166+
}
167+
});
168+
169+
ipcMain.on(IpcActions.CloseWindow, () => {
170+
window?.close();
171+
});

electron/tsconfig.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "commonjs",
5+
"esModuleInterop": true,
6+
"sourceMap": true,
7+
"strict": true,
8+
"outDir": "../build",
9+
"rootDir": "../",
10+
"noEmitOnError": true,
11+
"typeRoots": ["node_modules/@types"]
12+
}
13+
}

package.json

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
{
2-
"name": "Moonpad",
2+
"name": "moonpad",
33
"version": "0.1.0",
44
"private": true,
5-
"main": "./src/electron.js",
5+
"main": "build/electron/main.js",
66
"homepage": "./",
77
"dependencies": {
8+
"@types/jest": "^29.2.6",
9+
"@types/node": "^18.11.18",
10+
"@types/react": "^18.0.27",
11+
"@types/react-dom": "^18.0.10",
12+
"@types/redux-logger": "^3.0.9",
813
"electron": "^7.2.4",
9-
"electron-is-dev": "^1.1.0",
1014
"lowdb": "^1.0.0",
1115
"prop-types": "^15.7.2",
1216
"react": "^18.2.0",
@@ -15,30 +19,44 @@
1519
"react-scripts": "^5.0.1",
1620
"redux": "^4.0.5",
1721
"redux-logger": "^3.0.6",
18-
"redux-thunk": "^2.3.0"
22+
"redux-thunk": "^2.3.0",
23+
"typescript": "^4.9.4"
1924
},
2025
"devDependencies": {
26+
"@types/lowdb": "^1.0.11",
27+
"@typescript-eslint/eslint-plugin": "^5.48.2",
28+
"@typescript-eslint/parser": "^5.48.2",
2129
"concurrently": "^5.0.0",
22-
"electron-packager": "^14.0.6",
23-
"eslint": "^7.32.0 || ^8.2.0",
30+
"cross-env": "^7.0.3",
31+
"electron-builder": "^23.6.0",
32+
"eslint": "^8.32.0",
2433
"eslint-config-airbnb": "^19.0.4",
2534
"eslint-config-prettier": "^8.6.0",
2635
"eslint-plugin-import": "^2.25.3",
2736
"eslint-plugin-jsx-a11y": "^6.5.1",
2837
"eslint-plugin-react": "^7.28.0",
2938
"eslint-plugin-react-hooks": "^4.3.0",
30-
"node-sass": "^4.13.1",
3139
"prettier": "2.8.3",
40+
"sass": "^1.57.1",
3241
"wait-on": "^3.3.0"
3342
},
3443
"scripts": {
3544
"start": "react-scripts start",
3645
"build": "react-scripts build",
3746
"test": "react-scripts test",
38-
"electron-dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"",
39-
"pack-osx": "yarn build && electron-packager . --plataform=darwin --out=./release-builds/macOS --icon=./assets/moonpad.icns --overwrite=true --prune=true --package-manager=yarn",
40-
"pack-win": "yarn build && electron-packager . --platform=win32 --out=./release-builds/win --icon=./assets/moonpad.ico --overwrite=true --prune=true --package-manager=yarn",
41-
"pack-lin": "yarn build && electron-packager . --platform=linux --out=./release-builds/lin --icon=./assets/moonpad.png --overwrite=true --prune=true --package-manager=yarn"
47+
"postinstall": "electron-builder install-app-deps",
48+
"electron:dev": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://127.0.0.1:3000 && tsc -p electron -w\" \"wait-on http://127.0.0.1:3000 && tsc -p electron && electron .\"",
49+
"electron:build": "yarn build && tsc -p electron && electron-builder",
50+
"eject": "react-scripts eject"
51+
},
52+
"build": {
53+
"extends": null,
54+
"files": [
55+
"build/**/*"
56+
],
57+
"directories": {
58+
"buildResources": "assets"
59+
}
4260
},
4361
"eslintConfig": {
4462
"extends": "react-app"

src/actions/colorTheme.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/actions/colorTheme.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Action, ActionCreator, Dispatch } from "redux";
2+
import { Actions } from ".";
3+
import { IpcActions } from "../data/ipcActions";
4+
5+
const { ipcRenderer } = window.require("electron");
6+
7+
export type ToggleColorThemeAction = Action<Actions.ToggleTheme> & {
8+
isNowDarkTheme: boolean;
9+
};
10+
11+
const toggleColorTheme: ActionCreator<ToggleColorThemeAction> = (
12+
isNowDarkTheme: boolean
13+
): ToggleColorThemeAction => ({
14+
type: Actions.ToggleTheme,
15+
isNowDarkTheme,
16+
});
17+
18+
export const toggleColorThemeAndPersist =
19+
(isNowDarkTheme: boolean) => (dispatch: Dispatch<ToggleColorThemeAction>) => {
20+
dispatch(toggleColorTheme(isNowDarkTheme));
21+
ipcRenderer.send(IpcActions.ToggleColorTheme);
22+
};

src/actions/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const enum Actions {
2+
ToggleTheme = "Toggle Color Theme",
3+
SelectTab = "Select Tab",
4+
ShowToastPopup = "Show Toast Popup",
5+
HideToastPopup = "Hide Toast Popup",
6+
ToggleOpenTabArea = "Toggle Open Tab Area",
7+
CreateTab = "Create Tab",
8+
DeleteTab = "Delete Tab",
9+
UpdateTabName = "Update Tab Name",
10+
UpdateTabContent = "Update Tab Content",
11+
SwapTabs = "Swap Tabs",
12+
}

src/actions/isTabAreaOpen.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)