Skip to content

Commit 68ca427

Browse files
committed
feat: logging and devtool entry
1 parent a074de9 commit 68ca427

File tree

9 files changed

+369
-113
lines changed

9 files changed

+369
-113
lines changed

electron/main/index.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { join } from "node:path";
33
// import NodeURL from "node:url";
44
import { app, BrowserWindow, desktopCapturer, ipcMain, Menu, shell, Tray } from "electron";
55
import { VocechatServer } from "@/types/common";
6-
import { readUserData, USER_DATA_PATH, writeUserData } from "./user-data";
6+
import { readUserData, USER_DATA_PATH, USER_LOG_PATH, writeUserData } from "./user-data";
7+
import logger from "./logger";
78

89
// import { update } from "./update";
910

@@ -195,6 +196,12 @@ app.on("activate", () => {
195196
createWindow();
196197
}
197198
});
199+
ipcMain.on("vocechat-logging", (evt, arg) => {
200+
console.log("handle:vocechat-logging", arg);
201+
202+
logger.error(JSON.stringify(arg));
203+
// return true;
204+
});
198205
// Event handler for asynchronous incoming messages
199206
// init redux store
200207
ipcMain.handle("init-servers", () => {
@@ -205,9 +212,18 @@ ipcMain.handle("data-file-path", () => {
205212
console.log("handle:data-file-path", USER_DATA_PATH);
206213
return USER_DATA_PATH;
207214
});
208-
ipcMain.on("show-data-file", () => {
209-
console.log("show-data-file", USER_DATA_PATH);
210-
shell.showItemInFolder(USER_DATA_PATH);
215+
ipcMain.on("show-file", (evt, arg) => {
216+
console.log("show-file", arg);
217+
switch (arg) {
218+
case "data":
219+
shell.showItemInFolder(USER_DATA_PATH);
220+
break;
221+
case "log":
222+
shell.showItemInFolder(USER_LOG_PATH);
223+
break;
224+
default:
225+
break;
226+
}
211227
});
212228
// controls from non-macOS
213229
ipcMain.on("control-mini", () => {

electron/main/logger.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import winston from "winston";
2+
import { USER_ERROR_LOG_FILE, USER_LOG_FILE } from "./user-data";
3+
const logger = winston.createLogger({
4+
level: "info",
5+
format: winston.format.json(),
6+
defaultMeta: { service: "vocechat" },
7+
transports: [
8+
//
9+
// - Write all logs with importance level of `error` or less to `error.log`
10+
// - Write all logs with importance level of `info` or less to `combined.log`
11+
//
12+
new winston.transports.File({
13+
filename: USER_ERROR_LOG_FILE,
14+
level: "error",
15+
maxsize: 5242880,
16+
maxFiles: 5,
17+
tailable: true
18+
}),
19+
new winston.transports.File({ filename: USER_LOG_FILE })
20+
]
21+
});
22+
23+
//
24+
// If we're not in production then log to the `console` with the format:
25+
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
26+
//
27+
if (process.env.NODE_ENV !== "production") {
28+
logger.add(
29+
new winston.transports.Console({
30+
format: winston.format.simple()
31+
})
32+
);
33+
}
34+
export default logger;

electron/main/user-data.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
import fs from "fs";
33
import path from "path";
44
import { app } from "electron";
5-
5+
const date = new Date();
6+
const d = date.getDate();
7+
const m = date.getMonth() + 1;
68
export const USER_DATA_PATH = path.join(app.getPath("userData"), "server_list.json");
9+
export const USER_LOG_PATH = path.join(app.getPath("userData"), "log/");
10+
export const USER_ERROR_LOG_FILE = path.join(USER_LOG_PATH, `error-${m}-${d}.log`);
11+
export const USER_LOG_FILE = path.join(USER_LOG_PATH, `combined-${m}-${d}.log`);
712

813
export function readUserData() {
914
try {

package.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vocechat-desktop",
3-
"version": "0.7.11",
3+
"version": "0.7.12",
44
"main": "dist-electron/main/index.js",
55
"description": "vocechat desktop version",
66
"author": "Tristan <yanggc888@163.com>",
@@ -25,39 +25,40 @@
2525
"@tippyjs/react": "^4.2.6",
2626
"clsx": "^2.0.0",
2727
"electron-updater": "^6.1.1",
28-
"framer-motion": "^10.15.0",
28+
"framer-motion": "^10.15.1",
2929
"react-redux": "^8.1.2",
3030
"react-router-dom": "^6.14.2",
3131
"redux-state-sync": "^3.1.4",
3232
"rooks": "^7.14.1",
33-
"tippy.js": "^6.3.7"
33+
"tippy.js": "^6.3.7",
34+
"winston": "^3.10.0"
3435
},
3536
"devDependencies": {
3637
"@ianvs/prettier-plugin-sort-imports": "^4.1.0",
3738
"@types/react": "^18.2.18",
3839
"@types/react-dom": "^18.2.7",
3940
"@types/redux-state-sync": "^3.1.5",
40-
"@typescript-eslint/eslint-plugin": "^6.2.1",
41-
"@typescript-eslint/parser": "^6.2.1",
41+
"@typescript-eslint/eslint-plugin": "^6.3.0",
42+
"@typescript-eslint/parser": "^6.3.0",
4243
"@vitejs/plugin-react": "^4.0.4",
4344
"autoprefixer": "^10.4.14",
44-
"electron": "^25.3.2",
45+
"electron": "^25.4.0",
4546
"electron-builder": "^24.6.3",
4647
"electron-builder-notarize": "^1.5.1",
4748
"eslint": "^8.46.0",
48-
"eslint-config-prettier": "^8.9.0",
49+
"eslint-config-prettier": "^9.0.0",
4950
"eslint-plugin-prettier": "^5.0.0",
5051
"eslint-plugin-react": "^7.33.1",
5152
"eslint-plugin-react-hooks": "^4.6.0",
5253
"patch-package": "^8.0.0",
5354
"postcss": "^8.4.27",
54-
"prettier": "^3.0.0",
55+
"prettier": "^3.0.1",
5556
"prettier-plugin-tailwindcss": "^0.4.1",
5657
"react": "^18.2.0",
5758
"react-dom": "^18.2.0",
5859
"tailwindcss": "^3.3.3",
5960
"typescript": "^5.1.6",
60-
"vite": "^4.4.8",
61+
"vite": "^4.4.9",
6162
"vite-plugin-electron": "^0.12.0",
6263
"vite-plugin-electron-renderer": "^0.14.5",
6364
"vite-plugin-svgr": "^3.2.0",

src/app/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const LOCAL_DATA_KEY = "VC_DESKTOP_DATA";
22
export const PRIVOCE_SERVER_URL = "https://dev.voce.chat";
3+
// export const PRIVOCE_WEB_URL = "https://privoce.voce.chat";
34
export const PRIVOCE_WEB_URL =
45
process.env.NODE_ENV == "development" ? "http://localhost:3009" : "https://privoce.voce.chat";

src/assets/icons/debug.svg

Lines changed: 3 additions & 0 deletions
Loading

src/components/about.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import IconLogo from "../assets/icon.png";
33
import pkg from "../../package.json";
44
import { useEffect, useState } from "react";
5-
import { ipcRenderer, shell } from "electron";
5+
import { ipcRenderer } from "electron";
66
import Button from "./base/button";
77
// type Props = {}
88

@@ -14,16 +14,21 @@ const About = () => {
1414
setFilePath(path);
1515
});
1616
}, []);
17-
const handleOpen = () => {
18-
ipcRenderer.send("show-data-file");
17+
const handleOpen = (type: "data" | "log") => {
18+
ipcRenderer.send("show-file", type);
1919
};
2020
return (
2121
<section className="flex h-screen w-screen flex-col items-center justify-center gap-2 dark:bg-neutral-800">
2222
<img className="h-20 w-20" src={IconLogo} alt="vocechat logo" />
2323
<h1 className="dark:text-neutral-200">About VoceChat Desktop</h1>
24-
<Button onClick={handleOpen} title={filePath} size="sm">
25-
Data file
26-
</Button>
24+
<div className="flex items-center gap-2">
25+
<Button onClick={handleOpen.bind(null, "data")} title={filePath} size="sm">
26+
Data
27+
</Button>
28+
<Button onClick={handleOpen.bind(null, "log")} size="sm">
29+
Log
30+
</Button>
31+
</div>
2732
<div className="mt-8 flex flex-col items-center gap-1">
2833
<span className="text-xs text-gray-500">Version: {pkg.version}</span>
2934
<span className="text-xs text-gray-500">

src/components/layout.tsx

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,22 @@ import { motion } from "framer-motion";
55
import { switchServer, updateAddModalVisible } from "@/app/slices/data";
66
import { useAppSelector } from "@/app/store";
77
import { ReactComponent as IconAdd } from "@/assets/icons/add.svg";
8-
// import { ReactComponent as IconDrag } from "@/assets/icons/drag.svg";
98
import { ReactComponent as IconRefresh } from "@/assets/icons/refresh.svg";
10-
// import { isDarkMode } from "@/utils";
9+
import { ReactComponent as IconDebug } from "@/assets/icons/debug.svg";
1110
import ServerTip from "./server-tip";
1211
import AddServerModal from "./modal-add-server";
1312
import RemoveServerModal from "./modal-remove-server";
14-
import { WebviewTag } from "electron";
13+
import { WebviewTag, ipcRenderer } from "electron";
1514
import Tippy from "@tippyjs/react";
1615
import { hideAll } from "tippy.js";
1716
import ContextMenu, { MenuItem } from "./context-menu";
1817
import TitleBar from "./titlebar";
19-
18+
// const LevelMap = {
19+
// 0: "verbose",
20+
// 1: "info",
21+
// 2: "warning",
22+
// 3: "error"
23+
// };
2024
const Layout = () => {
2125
const [removeServer, setRemoveServer] = useState<undefined | string>();
2226
const [reloadVisible, setReloadVisible] = useState(false);
@@ -26,6 +30,22 @@ const Layout = () => {
2630
useEffect(() => {
2731
if (servers.length == 0) {
2832
handleAddServer();
33+
} else {
34+
const webviews = [...document.querySelectorAll("webview")] as WebviewTag[];
35+
webviews.forEach((webview) => {
36+
webview.addEventListener("dom-ready", () => {
37+
const url = webview.dataset.src;
38+
console.log(`${url} dom-ready`);
39+
});
40+
webview.addEventListener("console-message", (e) => {
41+
const { level, message, sourceId } = e;
42+
if (level == 3) {
43+
// error
44+
// console.log("Guest page logged a message:", message, sourceId);
45+
ipcRenderer.send("vocechat-logging", { level, message, sourceId });
46+
}
47+
});
48+
});
2949
}
3050
}, [servers]);
3151
const handleSwitch = (evt: MouseEvent<HTMLLIElement>) => {
@@ -45,6 +65,12 @@ const Layout = () => {
4565
wv.loadURL(wv.dataset.src);
4666
}
4767
};
68+
const handleOpenWebviewDevTools = () => {
69+
const wv = document.querySelector("webview[data-visible='true']") as WebviewTag;
70+
if (wv && wv.dataset.src) {
71+
wv.openDevTools();
72+
}
73+
};
4874
const showContextMenu = (_key: string) => {
4975
setMenuVisibleMap((prev) => {
5076
return {
@@ -92,6 +118,7 @@ const Layout = () => {
92118
>
93119
<aside
94120
className={clsx(
121+
"relative",
95122
"flex h-full w-[66px] flex-col items-center gap-3 bg-neutral-200 dark:bg-gray-900",
96123
contextMenuVisible ? "" : "app-drag",
97124
isMac ? "pt-8" : "pt-1"
@@ -185,6 +212,13 @@ const Layout = () => {
185212
<IconRefresh className="outline-none group-hover:stroke-white" />
186213
</div>
187214
</ServerTip>
215+
<button
216+
title="Open DevTools"
217+
onClick={handleOpenWebviewDevTools}
218+
className="app-no-drag group absolute bottom-2 left-4 flex h-9 w-9 cursor-pointer items-center justify-center rounded hover:bg-gray-500/50"
219+
>
220+
<IconDebug className="invisible outline-none group-hover:visible group-hover:stroke-white" />
221+
</button>
188222
</aside>
189223
<motion.main className="relative flex h-full flex-1 items-center justify-center">
190224
{servers.map((server) => {

0 commit comments

Comments
 (0)