diff --git a/.env b/.env index bb2cd1c..b9ce7eb 100644 --- a/.env +++ b/.env @@ -1,2 +1,4 @@ VITE_BASEURL=https://api.example.com -VITE_BEARERTOKEN=YOUR_BEARER_TOKEN \ No newline at end of file +VITE_BEARERTOKEN=YOUR_BEARER_TOKEN +VITE_LOG_FILE_NAME = vigad.log +VITE_LOGLEVEL = error \ No newline at end of file diff --git a/electron/main/index.ts b/electron/main/index.ts index 748708e..ea8cb4d 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -97,6 +97,10 @@ async function createWindow() { // Get all screens/windows from the main process to the renderer process ipcMain.handle('get-screens', getScreen); + + // Electron wants this to be called initially before calling + // app.getPath('logs') + app.setAppLogsPath(); } // This method will be called when Electron has finished diff --git a/electron/preload/index.ts b/electron/preload/index.ts index bfe56c3..54aa702 100644 --- a/electron/preload/index.ts +++ b/electron/preload/index.ts @@ -1,3 +1,8 @@ +import { app } from 'electron'; +import log from 'electron-log'; +import path from 'node:path'; +import fs from 'fs'; + function domReady( condition: DocumentReadyState[] = ['complete', 'interactive'] ) { @@ -110,4 +115,66 @@ contextBridge.exposeInMainWorld('electronAPI', { }); }); }, + saveLog: ( + message: string, + level: ElectronLogLevel = ElectronLogLevel.INFO, + logFileName: string + ) => { + //github.com/finos/SymphonyElectron/blob/0431a9f5add13cd16c19006775f1e907f3c3b2ce/src/common/logger.ts#L66 + const logDirectoryPath = path.join(app.getPath('exe'), 'logs'); + + // Create the log directory if it doesn't exist + if (!fs.existsSync(logDirectoryPath)) { + fs.mkdirSync(logDirectoryPath); + } + + const logFilePath = path.join(logDirectoryPath, logFileName); + + try { + // Save log message using electron-log + log.transports.file.resolvePath = () => logFilePath; + log[level](message); + + return { success: true, message: message }; + } catch (error) { + console.error(error); + return { success: false, message: 'Error saving log file.' }; + } + + // const logDirecotryName = 'logs'; + + // console.log(process.env.NODE_ENV); + + // log.transports.file.format = '[{h}:{i}:{s}:{ms}] [{level}] {text}'; + // log.transports.file.maxSize = 5 * 1024 * 1024; // 5 MB + + // if (process.env.NODE_ENV === 'development') { + // // Set the desired log file name + // log.transports.file.resolvePath = () => + // path.join(logDirecotryName, logFileName); + + // // Save log message using electron-log + // log[level](message); + // } else { + // // TODO: cant save log file in the root directory of the installed application yet + // // Set the desired log file name in the root directory of the installed application + // const logFilePath = path.join(app.getPath('exe'), logFileName); + // log.transports.file.resolvePath = () => logFilePath; + + // // Save log message using electron-log + // log[level](message); + // } + }, }); + +/** + * Electron log levels enum declaration + */ +export enum ElectronLogLevel { + INFO = 'info', + WARN = 'warn', + ERROR = 'error', + VERBOSE = 'verbose', + DEBUG = 'debug', + SILLY = 'silly', +} diff --git a/package-lock.json b/package-lock.json index ba89816..33e602d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,12 @@ "@vueuse/components": "^10.1.2", "@vueuse/core": "^10.1.2", "clipboardy": "^3.0.0", + "electron-log": "^4.4.8", "randexp": "^0.5.3", "roboto-fontface": "^0.10.0", "tesseract.js": "^3.0.3", "tplant": "^3.1.0", + "tslog": "^4.8.2", "vue-router": "^4.2.2", "vue3-drag-resize": "^2.0.5", "vuetify": "^3.3.2" @@ -4135,6 +4137,11 @@ "node": ">= 10.0.0" } }, + "node_modules/electron-log": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.8.tgz", + "integrity": "sha512-QQ4GvrXO+HkgqqEOYbi+DHL7hj5JM+nHi/j+qrN9zeeXVKy8ZABgbu4CnG+BBqDZ2+tbeq9tUC4DZfIWFU5AZA==" + }, "node_modules/electron-publish": { "version": "24.4.0", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.4.0.tgz", @@ -8088,6 +8095,17 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/tslog": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.8.2.tgz", + "integrity": "sha512-eAKIRjxfSKYLs06r1wT7oou6Uv9VN6NW9g0JPidBlqQwPBBl5+84dm7r8zSOPVq1kyfEw1P6B3/FLSpZCorAgA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/fullstack-build/tslog?sponsor=1" + } + }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", @@ -11961,6 +11979,11 @@ } } }, + "electron-log": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.8.tgz", + "integrity": "sha512-QQ4GvrXO+HkgqqEOYbi+DHL7hj5JM+nHi/j+qrN9zeeXVKy8ZABgbu4CnG+BBqDZ2+tbeq9tUC4DZfIWFU5AZA==" + }, "electron-publish": { "version": "24.4.0", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.4.0.tgz", @@ -14848,6 +14871,11 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "tslog": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.8.2.tgz", + "integrity": "sha512-eAKIRjxfSKYLs06r1wT7oou6Uv9VN6NW9g0JPidBlqQwPBBl5+84dm7r8zSOPVq1kyfEw1P6B3/FLSpZCorAgA==" + }, "tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", diff --git a/package.json b/package.json index b173ec7..2f0d9c2 100644 --- a/package.json +++ b/package.json @@ -72,10 +72,12 @@ "@vueuse/components": "^10.1.2", "@vueuse/core": "^10.1.2", "clipboardy": "^3.0.0", + "electron-log": "^4.4.8", "randexp": "^0.5.3", "roboto-fontface": "^0.10.0", "tesseract.js": "^3.0.3", "tplant": "^3.1.0", + "tslog": "^4.8.2", "vue-router": "^4.2.2", "vue3-drag-resize": "^2.0.5", "vuetify": "^3.3.2" diff --git a/src/App.vue b/src/App.vue index b00b0e2..bec84ee 100644 --- a/src/App.vue +++ b/src/App.vue @@ -44,6 +44,7 @@ import BottomNavigation from '@/components/Navigation/BottomNavigation.vue'; import NotificantionProvider from '@/components/Notifications/NotificationProvider/NotificationProvider.vue'; import { NotificationAnchorPosition } from '@/components/Notifications/NotificationAnchorPosition'; import useStreamHandler from '@/composables/useStreamHandler/useStreamHandler'; +import useLogger from '@/composables/useLogger/useLogger'; // Force the application to navigate to the default route const router = useRouter(); @@ -51,11 +52,16 @@ const router = useRouter(); // Get the default preview video stream function const { setDefaultPreviewVideoStream } = useStreamHandler(); +// Get the addLog function from the useLogger composable +const { addLog } = useLogger(); + onMounted(async () => { // set the default preview video stream await setDefaultPreviewVideoStream(); // navigate to the default route router.push('/'); + // add a log entry + addLog('Application started'); }); diff --git a/src/composables/useLogger/electron-log-level.ts b/src/composables/useLogger/electron-log-level.ts new file mode 100644 index 0000000..f43e7a0 --- /dev/null +++ b/src/composables/useLogger/electron-log-level.ts @@ -0,0 +1,11 @@ +/** + * Electron log levels enum + */ +export enum ElectronLogLevel { + INFO = 'info', + WARN = 'warn', + ERROR = 'error', + VERBOSE = 'verbose', + DEBUG = 'debug', + SILLY = 'silly', +} diff --git a/src/composables/useLogger/useLogger.ts b/src/composables/useLogger/useLogger.ts new file mode 100644 index 0000000..8a9f208 --- /dev/null +++ b/src/composables/useLogger/useLogger.ts @@ -0,0 +1,87 @@ +import { ref } from 'vue'; +import { Logger } from 'tslog'; +import { ElectronLogLevel } from './electron-log-level'; + +/** + * Create a logger instance + * @type {Logger} + */ +const logger = new Logger(); + +/** + * Reference to the electron logger in the main process + * @type {any} + */ +const electronLogger = (window as any).electronAPI; + +/** + * Logger composable + */ +export default function useLogger() { + const logMessages = ref([]); + + /** + * Function to add log messages + * @param {string} message - The log message + * @param {ElectronLogLevel} [logLevel=ElectronLogLevel.INFO] - The log level + */ + const addLog = ( + message: string, + logLevel = ElectronLogLevel.INFO, + fileName = import.meta.env.VITE_LOG_FILE_NAME + ) => { + logger.debug(message); + logMessages.value.push(message); + electronLogger.saveLog(message, logLevel, fileName); + }; + + /** + * Function to add warning log messages + * @param {string} message - The log message + */ + const addWarnLog = (message: string) => { + addLog(message, ElectronLogLevel.WARN); + }; + + /** + * Function to add error log messages + * @param {string} message - The log message + */ + const addErrorLog = (message: string) => { + addLog(message, ElectronLogLevel.ERROR); + }; + + /** + * Function to add verbose log messages + * @param {string} message - The log message + */ + const addVerboseLog = (message: string) => { + addLog(message, ElectronLogLevel.VERBOSE); + }; + + /** + * Function to add debug log messages + * @param {string} message - The log message + */ + const addDebugLog = (message: string) => { + addLog(message, ElectronLogLevel.DEBUG); + }; + + /** + * Function to add silly log messages + * @param {string} message - The log message + */ + const addSillyLog = (message: string) => { + addLog(message, ElectronLogLevel.SILLY); + }; + + return { + log: logMessages, + addLog, + addErrorLog, + addWarnLog, + addVerboseLog, + addDebugLog, + addSillyLog, + }; +} diff --git a/src/composables/useNotificationSystem/useNotificationSystem.ts b/src/composables/useNotificationSystem/useNotificationSystem.ts index d0ad7d4..cc5ff02 100644 --- a/src/composables/useNotificationSystem/useNotificationSystem.ts +++ b/src/composables/useNotificationSystem/useNotificationSystem.ts @@ -1,5 +1,6 @@ import { ref } from 'vue'; import useTokenGenerator from '@/composables/useTokenGenerator/useTokenGenerator'; +import useLogger from '@/composables/useLogger/useLogger'; /** * notifications list @@ -11,6 +12,7 @@ const notifications = ref([]); */ export default function useNotificationSystem() { const { generateValidToken } = useTokenGenerator(); + const { addLog, addWarnLog, addErrorLog } = useLogger(); /** * Create a notification @@ -22,6 +24,17 @@ export default function useNotificationSystem() { options ); + const type = _options.type; + + // Add log message to the log file + if (type === 'error') { + addErrorLog(_options.title); + } else if (type === 'warning') { + addWarnLog(_options.title); + } else { + addLog(_options.title); + } + notifications.value.push( ...[ {