From e309f9d88c0d9b07fabf69b34d71e7bf1ab55173 Mon Sep 17 00:00:00 2001 From: devknight216 Date: Wed, 20 Mar 2024 13:58:54 +0000 Subject: [PATCH 1/5] Temporary changes --- package.json | 1 + public/overlay.html | 45 ++++++++++++++++ src/components/ControlPanel.vue | 49 +++++++++++++++++ src/components/dialogs/AddEvidenceDialog.vue | 5 +- src/modules/IpcHandlers.js | 6 +++ src/modules/WindowUtility.js | 55 +++++++++++++++++++- src/modules/constants.js | 2 + src/modules/overlay.html | 45 ++++++++++++++++ src/services/electronService.js | 14 +++++ yarn.lock | 15 +++++- 10 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 public/overlay.html create mode 100644 src/modules/overlay.html diff --git a/package.json b/package.json index 57d660b1..48aa9463 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "ffprobe-static": "^3.1.0", "fluent-ffmpeg": "^2.1.2", "form-data": "^4.0.0", + "iohook2": "^1.0.6", "lodash": "^4.17.21", "node-polyfill-webpack-plugin": "^2.0.1", "os": "^0.1.2", diff --git a/public/overlay.html b/public/overlay.html new file mode 100644 index 00000000..27be7040 --- /dev/null +++ b/public/overlay.html @@ -0,0 +1,45 @@ + + + + Overlay + + + +
+ + + + + diff --git a/src/components/ControlPanel.vue b/src/components/ControlPanel.vue index 44ffa23f..5a1f8fed 100644 --- a/src/components/ControlPanel.vue +++ b/src/components/ControlPanel.vue @@ -1111,9 +1111,13 @@ export default { this.sources = data; if (this.viewMode === "normal") { + console.log("1"); this.sourcePickerDialog = true; } else { + console.log("3"); if (this.$isElectron) { + console.log("88"); + await this.$electronService.openSourcePickerWindow(this.sources); } } @@ -1473,6 +1477,45 @@ export default { } }, async videoRecordProcess() { + const handleKeyPress = (event) => { + let eventText = ""; + if (event.ctrlKey) { + eventText += "Ctrl + "; + } + if (event.altKey) { + eventText += "Alt + "; + } + if (event.shiftKey) { + eventText += "Shift + "; + } + eventText += event.key.toUpperCase(); + // Show the text overlay + showTextOverlay(eventText); + }; + + const handleMouseClick = () => { + // Show the text overlay for mouse click + showTextOverlay("Mouse Click"); + }; + + const showTextOverlay = (text) => { + const textOverlay = document.createElement("div"); + textOverlay.textContent = text; + textOverlay.style.position = "fixed"; + textOverlay.style.top = "50%"; + textOverlay.style.left = "50%"; + textOverlay.style.transform = "translate(-50%, -50%)"; + textOverlay.style.background = "rgba(0, 0, 0, 0.5)"; + textOverlay.style.color = "white"; + textOverlay.style.padding = "10px"; + textOverlay.style.borderRadius = "5px"; + textOverlay.style.zIndex = "9999"; + document.body.appendChild(textOverlay); + setTimeout(() => { + textOverlay.remove(); + }, 1000); // Remove after 1 second + }; + this.handleStream = (stream) => { if (this.config.audioCapture && this.audioDevices.length > 0) { stream.addTrack(dest.stream.getAudioTracks()[0]); @@ -1487,6 +1530,9 @@ export default { let poster; let frames = []; mediaRecorder.onstart = () => { + document.addEventListener("click", handleMouseClick); + document.addEventListener("keydown", handleKeyPress); + // this.$electronService.startKeyboardCapture(); this.recordVideoStarted = true; const video = document.createElement("video"); video.srcObject = stream; @@ -1521,6 +1567,9 @@ export default { } }; mediaRecorder.onstop = async () => { + // this.$electronService.stopKeyboardCapture(); + document.removeEventListener("click", handleMouseClick); + document.removeEventListener("keydown", handleKeyPress); this.recordVideoStarted = false; const blob = new Blob(frames, { type: mimeType }); const buffer = await blob.arrayBuffer(); diff --git a/src/components/dialogs/AddEvidenceDialog.vue b/src/components/dialogs/AddEvidenceDialog.vue index c259f77a..af166663 100644 --- a/src/components/dialogs/AddEvidenceDialog.vue +++ b/src/components/dialogs/AddEvidenceDialog.vue @@ -455,6 +455,7 @@ export default { }, mounted() { this.getAllTags(); + console.log("78787evidencedialog"); if (this.$isElectron) { // this.$electronService.onActiveSession(this.activeSession); // this.activeSession(); @@ -506,18 +507,20 @@ export default { this.allTags = [...new Set([...defaultTagTexts, ...sessionTagTexts])]; }, async activeSession() { + console.log("89898activeSession"); // set theme mode const isDarkMode = this.config.apperance === "dark"; this.$vuetify.theme.dark = isDarkMode; localStorage.setItem("isDarkMode", isDarkMode); this.item = { ...this.itemData }; - + console.log("465373", this.item); const splitName = this.item?.fileName.split(".") || [""]; this.name = splitName.slice(0, -1).join("."); // optimize video if (this.item.fileType === "video") { + console.log("1111111 optimize started"); await this.optimizeVideo(); } else { this.processing = false; diff --git a/src/modules/IpcHandlers.js b/src/modules/IpcHandlers.js index 875111a8..886db450 100644 --- a/src/modules/IpcHandlers.js +++ b/src/modules/IpcHandlers.js @@ -50,6 +50,12 @@ ipcMain.handle(IPC_HANDLERS.CAPTURE, async (event, args) => { ipcMain.handle(IPC_HANDLERS.WINDOW, async (event, args) => { switch (args.func) { + case IPC_FUNCTIONS.START_KEYBOARD_CAPTURE: + console.log("666"); + return windowUtility.startKeyboardCapture(); + case IPC_FUNCTIONS.STOP_KEYBOARD_CAPTURE: + console.log("222"); + return windowUtility.stopKeyboardCapture(); case IPC_FUNCTIONS.SET_DEV_MODE: return windowUtility.setDevMode(args.data); case IPC_FUNCTIONS.OPEN_ADD_WINDOW: diff --git a/src/modules/WindowUtility.js b/src/modules/WindowUtility.js index 92e88bf0..169846cc 100644 --- a/src/modules/WindowUtility.js +++ b/src/modules/WindowUtility.js @@ -1,4 +1,5 @@ -const { app, BrowserWindow, screen } = require("electron"); +const { app, BrowserWindow, screen, ipcMain } = require("electron"); +const iohook = require("iohook2"); let isDevelopment = process.env.NODE_ENV !== "production"; @@ -8,11 +9,61 @@ const browserUtility = require("./BrowserWindowUtility"); const path = require("path"); const { VIEW_MODE, IPC_BIND_KEYS } = require("./constants"); +let overlayWindow; +function createOverlayWindow() { + overlayWindow = new BrowserWindow({ + width: 400, + height: 200, + transparent: true, + frame: false, + alwaysOnTop: true, + webPreferences: { + nodeIntegration: true + } + }); + + overlayWindow.setIgnoreMouseEvents(true); + + overlayWindow.loadURL("app://./overlay.html"); + // "app://./index.html" + + overlayWindow.on('closed', () => { + overlayWindow = null; + }); +} module.exports.setDevMode = async ({ enabled }) => { isDevelopment = enabled; }; +module.exports.startKeyboardCapture = () => { + ipcMain.on('overlayShown', () => { + // After 1 second, send a message to hide the overlay + setTimeout(() => { + overlayWindow.webContents.send('hideOverlay'); + }, 1000); + }); + createOverlayWindow(); + iohook.on("keydown", event => { + console.log("Key pressed:", event); + overlayWindow.webContents.send("showOverlay", event.key); + // Handle the event as needed + }); + + // Start listening for mouse events + iohook.on("mousedown", event => { + console.log("Mouse clicked:", event); + overlayWindow.webContents.send("showOverlay", "Mouse Click"); + // Handle the event as needed + }); + iohook.start(); +}; + +module.exports.stopKeyboardCapture = () => { + console.log("123 Stop!"); + iohook.stop(); +}; + module.exports.getMainWindow = () => { const win = new BrowserWindow({ width: 800, @@ -275,12 +326,12 @@ module.exports.setWindowSize = ({ width, height }) => { }; module.exports.openModalWindow = (data) => { + console.log("999"); const parentWindow = browserUtility.getParentWindow(); const url = process.env.NODE_ENV === "development" ? `http://localhost:8080/#/${data.path}` : `file://${__dirname}/index.html#${data.path}`; - if (!modalWin) { modalWin = new BrowserWindow({ width: data.size.width, diff --git a/src/modules/constants.js b/src/modules/constants.js index 1f913bab..617cefd3 100644 --- a/src/modules/constants.js +++ b/src/modules/constants.js @@ -11,6 +11,8 @@ export const IPC_HANDLERS = { }; export const IPC_FUNCTIONS = { + START_KEYBOARD_CAPTURE: "startKeyboardCapture", + STOP_KEYBOARD_CAPTURE: "stopKeyboardCapture", GET_SYSTEM_INFO: "getSystemInfo", GET_MEDIA_SOURCE: "getMediaSource", SAVE_NOTE: "saveNote", diff --git a/src/modules/overlay.html b/src/modules/overlay.html new file mode 100644 index 00000000..27be7040 --- /dev/null +++ b/src/modules/overlay.html @@ -0,0 +1,45 @@ + + + + Overlay + + + +
+ + + + + diff --git a/src/services/electronService.js b/src/services/electronService.js index 5becf2d6..508dda90 100644 --- a/src/services/electronService.js +++ b/src/services/electronService.js @@ -86,6 +86,19 @@ export default class ElectronService { }); } + async startKeyboardCapture() { + return await window.ipc.invoke(IPC_HANDLERS.WINDOW, { + func: IPC_FUNCTIONS.START_KEYBOARD_CAPTURE, + }); + } + + stopKeyboardCapture() { + console.log("333"); + return window.ipc.invoke(IPC_HANDLERS.WINDOW, { + func: IPC_FUNCTIONS.STOP_KEYBOARD_CAPTURE, + }); + } + async openAddWindow(data) { await window.ipc.invoke(IPC_HANDLERS.WINDOW, { func: IPC_FUNCTIONS.OPEN_ADD_WINDOW, @@ -135,6 +148,7 @@ export default class ElectronService { } async openSourcePickerWindow(sources) { + console.log("0123"); return await window.ipc.invoke(IPC_HANDLERS.WINDOW, { func: IPC_FUNCTIONS.OPEN_MODAL_WINDOW, data: { diff --git a/yarn.lock b/yarn.lock index 20dceb9a..eac8d50f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3516,7 +3516,7 @@ bind-event-listener@^2.1.1: resolved "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-2.1.1.tgz" integrity sha512-O+a5c0D2se/u2VlBJmPRn45IB6R4mYMh1ok3dWxrIZ2pmLqzggBhb875mbq73508ylzofc0+hT9W41x4Y2s8lg== -bindings@^1.5.0: +bindings@^1.2.1, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== @@ -7308,6 +7308,14 @@ interpret@^1.0.0: resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +iohook2@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/iohook2/-/iohook2-1.0.6.tgz#1460b7f6f6b8552ddd4f1a1cf5936833b170440b" + integrity sha512-fZuMADzz9uDof/SgmVt0XeH8uYYRPowAto+8m7NiBcp12IJub78HcyqcMoEVyTGFLzoS8p1AcBFJTS9l5Yb8eQ== + dependencies: + bindings "^1.2.1" + nan "^2.4.0" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz" @@ -9077,6 +9085,11 @@ nan@^2.12.1, nan@^2.17.0: resolved "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== +nan@^2.4.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" + integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== + nanoid@^3.3.6: version "3.3.6" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" From c6a16eeec675685bb8f815634d7401464fcbd11b Mon Sep 17 00:00:00 2001 From: devknight216 Date: Wed, 20 Mar 2024 14:38:02 +0000 Subject: [PATCH 2/5] Revert "Temporary changes" This reverts commit e309f9d88c0d9b07fabf69b34d71e7bf1ab55173. --- package.json | 1 - public/overlay.html | 45 ---------------- src/components/ControlPanel.vue | 49 ----------------- src/components/dialogs/AddEvidenceDialog.vue | 5 +- src/modules/IpcHandlers.js | 6 --- src/modules/WindowUtility.js | 55 +------------------- src/modules/constants.js | 2 - src/modules/overlay.html | 45 ---------------- src/services/electronService.js | 14 ----- yarn.lock | 15 +----- 10 files changed, 4 insertions(+), 233 deletions(-) delete mode 100644 public/overlay.html delete mode 100644 src/modules/overlay.html diff --git a/package.json b/package.json index 48aa9463..57d660b1 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "ffprobe-static": "^3.1.0", "fluent-ffmpeg": "^2.1.2", "form-data": "^4.0.0", - "iohook2": "^1.0.6", "lodash": "^4.17.21", "node-polyfill-webpack-plugin": "^2.0.1", "os": "^0.1.2", diff --git a/public/overlay.html b/public/overlay.html deleted file mode 100644 index 27be7040..00000000 --- a/public/overlay.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - Overlay - - - -
- - - - - diff --git a/src/components/ControlPanel.vue b/src/components/ControlPanel.vue index 5a1f8fed..44ffa23f 100644 --- a/src/components/ControlPanel.vue +++ b/src/components/ControlPanel.vue @@ -1111,13 +1111,9 @@ export default { this.sources = data; if (this.viewMode === "normal") { - console.log("1"); this.sourcePickerDialog = true; } else { - console.log("3"); if (this.$isElectron) { - console.log("88"); - await this.$electronService.openSourcePickerWindow(this.sources); } } @@ -1477,45 +1473,6 @@ export default { } }, async videoRecordProcess() { - const handleKeyPress = (event) => { - let eventText = ""; - if (event.ctrlKey) { - eventText += "Ctrl + "; - } - if (event.altKey) { - eventText += "Alt + "; - } - if (event.shiftKey) { - eventText += "Shift + "; - } - eventText += event.key.toUpperCase(); - // Show the text overlay - showTextOverlay(eventText); - }; - - const handleMouseClick = () => { - // Show the text overlay for mouse click - showTextOverlay("Mouse Click"); - }; - - const showTextOverlay = (text) => { - const textOverlay = document.createElement("div"); - textOverlay.textContent = text; - textOverlay.style.position = "fixed"; - textOverlay.style.top = "50%"; - textOverlay.style.left = "50%"; - textOverlay.style.transform = "translate(-50%, -50%)"; - textOverlay.style.background = "rgba(0, 0, 0, 0.5)"; - textOverlay.style.color = "white"; - textOverlay.style.padding = "10px"; - textOverlay.style.borderRadius = "5px"; - textOverlay.style.zIndex = "9999"; - document.body.appendChild(textOverlay); - setTimeout(() => { - textOverlay.remove(); - }, 1000); // Remove after 1 second - }; - this.handleStream = (stream) => { if (this.config.audioCapture && this.audioDevices.length > 0) { stream.addTrack(dest.stream.getAudioTracks()[0]); @@ -1530,9 +1487,6 @@ export default { let poster; let frames = []; mediaRecorder.onstart = () => { - document.addEventListener("click", handleMouseClick); - document.addEventListener("keydown", handleKeyPress); - // this.$electronService.startKeyboardCapture(); this.recordVideoStarted = true; const video = document.createElement("video"); video.srcObject = stream; @@ -1567,9 +1521,6 @@ export default { } }; mediaRecorder.onstop = async () => { - // this.$electronService.stopKeyboardCapture(); - document.removeEventListener("click", handleMouseClick); - document.removeEventListener("keydown", handleKeyPress); this.recordVideoStarted = false; const blob = new Blob(frames, { type: mimeType }); const buffer = await blob.arrayBuffer(); diff --git a/src/components/dialogs/AddEvidenceDialog.vue b/src/components/dialogs/AddEvidenceDialog.vue index af166663..c259f77a 100644 --- a/src/components/dialogs/AddEvidenceDialog.vue +++ b/src/components/dialogs/AddEvidenceDialog.vue @@ -455,7 +455,6 @@ export default { }, mounted() { this.getAllTags(); - console.log("78787evidencedialog"); if (this.$isElectron) { // this.$electronService.onActiveSession(this.activeSession); // this.activeSession(); @@ -507,20 +506,18 @@ export default { this.allTags = [...new Set([...defaultTagTexts, ...sessionTagTexts])]; }, async activeSession() { - console.log("89898activeSession"); // set theme mode const isDarkMode = this.config.apperance === "dark"; this.$vuetify.theme.dark = isDarkMode; localStorage.setItem("isDarkMode", isDarkMode); this.item = { ...this.itemData }; - console.log("465373", this.item); + const splitName = this.item?.fileName.split(".") || [""]; this.name = splitName.slice(0, -1).join("."); // optimize video if (this.item.fileType === "video") { - console.log("1111111 optimize started"); await this.optimizeVideo(); } else { this.processing = false; diff --git a/src/modules/IpcHandlers.js b/src/modules/IpcHandlers.js index 886db450..875111a8 100644 --- a/src/modules/IpcHandlers.js +++ b/src/modules/IpcHandlers.js @@ -50,12 +50,6 @@ ipcMain.handle(IPC_HANDLERS.CAPTURE, async (event, args) => { ipcMain.handle(IPC_HANDLERS.WINDOW, async (event, args) => { switch (args.func) { - case IPC_FUNCTIONS.START_KEYBOARD_CAPTURE: - console.log("666"); - return windowUtility.startKeyboardCapture(); - case IPC_FUNCTIONS.STOP_KEYBOARD_CAPTURE: - console.log("222"); - return windowUtility.stopKeyboardCapture(); case IPC_FUNCTIONS.SET_DEV_MODE: return windowUtility.setDevMode(args.data); case IPC_FUNCTIONS.OPEN_ADD_WINDOW: diff --git a/src/modules/WindowUtility.js b/src/modules/WindowUtility.js index 169846cc..92e88bf0 100644 --- a/src/modules/WindowUtility.js +++ b/src/modules/WindowUtility.js @@ -1,5 +1,4 @@ -const { app, BrowserWindow, screen, ipcMain } = require("electron"); -const iohook = require("iohook2"); +const { app, BrowserWindow, screen } = require("electron"); let isDevelopment = process.env.NODE_ENV !== "production"; @@ -9,61 +8,11 @@ const browserUtility = require("./BrowserWindowUtility"); const path = require("path"); const { VIEW_MODE, IPC_BIND_KEYS } = require("./constants"); -let overlayWindow; -function createOverlayWindow() { - overlayWindow = new BrowserWindow({ - width: 400, - height: 200, - transparent: true, - frame: false, - alwaysOnTop: true, - webPreferences: { - nodeIntegration: true - } - }); - - overlayWindow.setIgnoreMouseEvents(true); - - overlayWindow.loadURL("app://./overlay.html"); - // "app://./index.html" - - overlayWindow.on('closed', () => { - overlayWindow = null; - }); -} module.exports.setDevMode = async ({ enabled }) => { isDevelopment = enabled; }; -module.exports.startKeyboardCapture = () => { - ipcMain.on('overlayShown', () => { - // After 1 second, send a message to hide the overlay - setTimeout(() => { - overlayWindow.webContents.send('hideOverlay'); - }, 1000); - }); - createOverlayWindow(); - iohook.on("keydown", event => { - console.log("Key pressed:", event); - overlayWindow.webContents.send("showOverlay", event.key); - // Handle the event as needed - }); - - // Start listening for mouse events - iohook.on("mousedown", event => { - console.log("Mouse clicked:", event); - overlayWindow.webContents.send("showOverlay", "Mouse Click"); - // Handle the event as needed - }); - iohook.start(); -}; - -module.exports.stopKeyboardCapture = () => { - console.log("123 Stop!"); - iohook.stop(); -}; - module.exports.getMainWindow = () => { const win = new BrowserWindow({ width: 800, @@ -326,12 +275,12 @@ module.exports.setWindowSize = ({ width, height }) => { }; module.exports.openModalWindow = (data) => { - console.log("999"); const parentWindow = browserUtility.getParentWindow(); const url = process.env.NODE_ENV === "development" ? `http://localhost:8080/#/${data.path}` : `file://${__dirname}/index.html#${data.path}`; + if (!modalWin) { modalWin = new BrowserWindow({ width: data.size.width, diff --git a/src/modules/constants.js b/src/modules/constants.js index 617cefd3..1f913bab 100644 --- a/src/modules/constants.js +++ b/src/modules/constants.js @@ -11,8 +11,6 @@ export const IPC_HANDLERS = { }; export const IPC_FUNCTIONS = { - START_KEYBOARD_CAPTURE: "startKeyboardCapture", - STOP_KEYBOARD_CAPTURE: "stopKeyboardCapture", GET_SYSTEM_INFO: "getSystemInfo", GET_MEDIA_SOURCE: "getMediaSource", SAVE_NOTE: "saveNote", diff --git a/src/modules/overlay.html b/src/modules/overlay.html deleted file mode 100644 index 27be7040..00000000 --- a/src/modules/overlay.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - Overlay - - - -
- - - - - diff --git a/src/services/electronService.js b/src/services/electronService.js index 508dda90..5becf2d6 100644 --- a/src/services/electronService.js +++ b/src/services/electronService.js @@ -86,19 +86,6 @@ export default class ElectronService { }); } - async startKeyboardCapture() { - return await window.ipc.invoke(IPC_HANDLERS.WINDOW, { - func: IPC_FUNCTIONS.START_KEYBOARD_CAPTURE, - }); - } - - stopKeyboardCapture() { - console.log("333"); - return window.ipc.invoke(IPC_HANDLERS.WINDOW, { - func: IPC_FUNCTIONS.STOP_KEYBOARD_CAPTURE, - }); - } - async openAddWindow(data) { await window.ipc.invoke(IPC_HANDLERS.WINDOW, { func: IPC_FUNCTIONS.OPEN_ADD_WINDOW, @@ -148,7 +135,6 @@ export default class ElectronService { } async openSourcePickerWindow(sources) { - console.log("0123"); return await window.ipc.invoke(IPC_HANDLERS.WINDOW, { func: IPC_FUNCTIONS.OPEN_MODAL_WINDOW, data: { diff --git a/yarn.lock b/yarn.lock index eac8d50f..20dceb9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3516,7 +3516,7 @@ bind-event-listener@^2.1.1: resolved "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-2.1.1.tgz" integrity sha512-O+a5c0D2se/u2VlBJmPRn45IB6R4mYMh1ok3dWxrIZ2pmLqzggBhb875mbq73508ylzofc0+hT9W41x4Y2s8lg== -bindings@^1.2.1, bindings@^1.5.0: +bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== @@ -7308,14 +7308,6 @@ interpret@^1.0.0: resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -iohook2@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/iohook2/-/iohook2-1.0.6.tgz#1460b7f6f6b8552ddd4f1a1cf5936833b170440b" - integrity sha512-fZuMADzz9uDof/SgmVt0XeH8uYYRPowAto+8m7NiBcp12IJub78HcyqcMoEVyTGFLzoS8p1AcBFJTS9l5Yb8eQ== - dependencies: - bindings "^1.2.1" - nan "^2.4.0" - ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz" @@ -9085,11 +9077,6 @@ nan@^2.12.1, nan@^2.17.0: resolved "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== -nan@^2.4.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" - integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== - nanoid@^3.3.6: version "3.3.6" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" From f8bdc8c53d5d8d9b260e2ca1194a6eef1c518367 Mon Sep 17 00:00:00 2001 From: devknight216 Date: Thu, 21 Mar 2024 16:30:00 +0000 Subject: [PATCH 3/5] feat: capture modifier binding presses and speed up the optimization process --- package.json | 1 + src/components/ControlPanel.vue | 5 +++ src/components/dialogs/AddEvidenceDialog.vue | 10 +++-- src/modules/CaptureUtility.js | 12 +++++- src/modules/IpcHandlers.js | 4 ++ src/modules/WindowUtility.js | 40 ++++++++++++++++++++ src/modules/constants.js | 2 + src/services/electronService.js | 15 +++++++- yarn.lock | 15 +++++++- 9 files changed, 97 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 57d660b1..48aa9463 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "ffprobe-static": "^3.1.0", "fluent-ffmpeg": "^2.1.2", "form-data": "^4.0.0", + "iohook2": "^1.0.6", "lodash": "^4.17.21", "node-polyfill-webpack-plugin": "^2.0.1", "os": "^0.1.2", diff --git a/src/components/ControlPanel.vue b/src/components/ControlPanel.vue index 44ffa23f..ea8e4f74 100644 --- a/src/components/ControlPanel.vue +++ b/src/components/ControlPanel.vue @@ -735,6 +735,7 @@ v-if="evidenceData" v-model="addEvidenceDialog" :item-data="evidenceData" + :captured-events="capturedEvents" @close=" addEvidenceDialog = false; evidenceData = null; @@ -1005,6 +1006,7 @@ export default { evidenceData: null, addEvidenceDialog: false, mediaStream: null, + capturedEvents: [], }; }, mounted() { @@ -1487,6 +1489,7 @@ export default { let poster; let frames = []; mediaRecorder.onstart = () => { + this.$electronService.startKeyboardCapture(); this.recordVideoStarted = true; const video = document.createElement("video"); video.srcObject = stream; @@ -1521,6 +1524,8 @@ export default { } }; mediaRecorder.onstop = async () => { + this.capturedEvents = + await this.$electronService.stopKeyboardCapture(); this.recordVideoStarted = false; const blob = new Blob(frames, { type: mimeType }); const buffer = await blob.arrayBuffer(); diff --git a/src/components/dialogs/AddEvidenceDialog.vue b/src/components/dialogs/AddEvidenceDialog.vue index c259f77a..6326318f 100644 --- a/src/components/dialogs/AddEvidenceDialog.vue +++ b/src/components/dialogs/AddEvidenceDialog.vue @@ -357,6 +357,10 @@ export default { type: Object, default: () => {}, }, + capturedEvents: { + type: Array, + default: () => {}, + }, }, data() { return { @@ -512,12 +516,11 @@ export default { localStorage.setItem("isDarkMode", isDarkMode); this.item = { ...this.itemData }; - const splitName = this.item?.fileName.split(".") || [""]; this.name = splitName.slice(0, -1).join("."); // optimize video - if (this.item.fileType === "video") { + if (this.item.fileType === "video/mp4") { await this.optimizeVideo(); } else { this.processing = false; @@ -566,7 +569,8 @@ export default { this.processing = true; const { status, message } = await this.$electronService.optimizeVideo( - this.item.filePath + this.item.filePath, + this.capturedEvents ); if (status === STATUSES.ERROR) { diff --git a/src/modules/CaptureUtility.js b/src/modules/CaptureUtility.js index ed52bbdb..64999db9 100644 --- a/src/modules/CaptureUtility.js +++ b/src/modules/CaptureUtility.js @@ -157,7 +157,7 @@ module.exports.createVideo = ({ buffer }) => { }; }; -module.exports.optimizeVideo = ({ filePath }) => { +module.exports.optimizeVideo = ({ filePath, capturedEvents }) => { const fileFormat = DEFAULT_FILE_TYPES["video"].suffix; const tempName = "temp-optimizing-video-" + @@ -170,12 +170,20 @@ module.exports.optimizeVideo = ({ filePath }) => { persistenceUtility.getSessionID(), tempName ); + let filterString = capturedEvents.map((overlay, index) => { + let backgroundColor = 'black'; + let textColor = 'white'; + let padding = 5; + return `drawtext=text='${overlay.text}':x=(w-text_w)/2:y=(h-text_h)/2:fontcolor=${textColor}:box=1:boxcolor=${backgroundColor}:boxborderw=${padding}:fontsize=24:fontfile=/path/to/font.ttf:enable='between(t,${overlay.start},${overlay.end})'`; + }).join(','); return new Promise(function (resolve, reject) { ffmpeg(filePath) + .complexFilter(filterString) .videoCodec("libx264") .audioCodec("aac") .format(fileFormat) + .addOption("-preset", "ultrafast") .save(tempPath) .on("start", function (commandLine) { console.log("start : " + commandLine); @@ -229,7 +237,7 @@ module.exports.updateVideo = ({ item, start, end, previousDuration }) => { const duration = parseInt(end - start); return new Promise(function (resolve, reject) { - if (previousDuration !== duration) { + if (previousDuration && previousDuration !== duration) { ffmpeg(item.filePath) .setStartTime(parseInt(start)) .setDuration(duration) diff --git a/src/modules/IpcHandlers.js b/src/modules/IpcHandlers.js index 875111a8..b4227df3 100644 --- a/src/modules/IpcHandlers.js +++ b/src/modules/IpcHandlers.js @@ -50,6 +50,10 @@ ipcMain.handle(IPC_HANDLERS.CAPTURE, async (event, args) => { ipcMain.handle(IPC_HANDLERS.WINDOW, async (event, args) => { switch (args.func) { + case IPC_FUNCTIONS.START_KEYBOARD_CAPTURE: + return windowUtility.startKeyboardCapture(); + case IPC_FUNCTIONS.STOP_KEYBOARD_CAPTURE: + return windowUtility.stopKeyboardCapture(); case IPC_FUNCTIONS.SET_DEV_MODE: return windowUtility.setDevMode(args.data); case IPC_FUNCTIONS.OPEN_ADD_WINDOW: diff --git a/src/modules/WindowUtility.js b/src/modules/WindowUtility.js index 92e88bf0..611cf83e 100644 --- a/src/modules/WindowUtility.js +++ b/src/modules/WindowUtility.js @@ -1,4 +1,5 @@ const { app, BrowserWindow, screen } = require("electron"); +const iohook = require("iohook2"); let isDevelopment = process.env.NODE_ENV !== "production"; @@ -8,11 +9,50 @@ const browserUtility = require("./BrowserWindowUtility"); const path = require("path"); const { VIEW_MODE, IPC_BIND_KEYS } = require("./constants"); +let capturedEvents = []; module.exports.setDevMode = async ({ enabled }) => { isDevelopment = enabled; }; +module.exports.startKeyboardCapture = () => { + iohook.start(); + const startingPoint = Date.now(); + capturedEvents = []; + + iohook.on("keydown", event => { + if ((event.ctrl || event.shift || event.alt || event.meta ) && !isControlKey(event.key)) { + // If Ctrl, Shift, Alt or Meta key is pressed along with a regular key + capturedEvents.push({ + type: "hotkey", + text: `${event.ctrl ? 'Ctrl+' : ''}${event.shift ? 'Shift+' : ''}${event.alt ? 'Alt+' : ''}${event.meta ? 'Meta+' : ''}${event.key.toUpperCase()}`, + start: parseFloat((Date.now() - startingPoint)/1000).toFixed(2), + end: parseFloat(((Date.now() - startingPoint)/1000).toFixed(2)) + 1, + }); + } + }); + + function isControlKey(key) { + // Check if the key is one of the individual control keys + return ['leftCtrl', 'rightCtrl', 'leftAlt', 'rightAlt', 'leftShift', 'rightShift', 'leftMeta', 'rightMeta'].includes(key); + } + + iohook.on("mousedown", event => { + capturedEvents.push({ + type: "mouse", + text: "Mouse Click", + start: parseFloat((Date.now() - startingPoint)/1000).toFixed(2), + end: parseFloat(((Date.now() - startingPoint)/1000).toFixed(2)) + 1, + }); + }); +}; + +module.exports.stopKeyboardCapture = () => { + iohook.stop(); + capturedEvents.pop(); + return capturedEvents; +}; + module.exports.getMainWindow = () => { const win = new BrowserWindow({ width: 800, diff --git a/src/modules/constants.js b/src/modules/constants.js index 1f913bab..617cefd3 100644 --- a/src/modules/constants.js +++ b/src/modules/constants.js @@ -11,6 +11,8 @@ export const IPC_HANDLERS = { }; export const IPC_FUNCTIONS = { + START_KEYBOARD_CAPTURE: "startKeyboardCapture", + STOP_KEYBOARD_CAPTURE: "stopKeyboardCapture", GET_SYSTEM_INFO: "getSystemInfo", GET_MEDIA_SOURCE: "getMediaSource", SAVE_NOTE: "saveNote", diff --git a/src/services/electronService.js b/src/services/electronService.js index 5becf2d6..ea149625 100644 --- a/src/services/electronService.js +++ b/src/services/electronService.js @@ -86,6 +86,18 @@ export default class ElectronService { }); } + async startKeyboardCapture() { + return await window.ipc.invoke(IPC_HANDLERS.WINDOW, { + func: IPC_FUNCTIONS.START_KEYBOARD_CAPTURE, + }); + } + + stopKeyboardCapture() { + return window.ipc.invoke(IPC_HANDLERS.WINDOW, { + func: IPC_FUNCTIONS.STOP_KEYBOARD_CAPTURE, + }); + } + async openAddWindow(data) { await window.ipc.invoke(IPC_HANDLERS.WINDOW, { func: IPC_FUNCTIONS.OPEN_ADD_WINDOW, @@ -289,11 +301,12 @@ export default class ElectronService { }); } - async optimizeVideo(filePath) { + async optimizeVideo(filePath, capturedEvents) { return window.ipc.invoke(IPC_HANDLERS.CAPTURE, { func: IPC_FUNCTIONS.OPTIMIZE_VIDEO, data: { filePath, + capturedEvents, }, }); } diff --git a/yarn.lock b/yarn.lock index 20dceb9a..eac8d50f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3516,7 +3516,7 @@ bind-event-listener@^2.1.1: resolved "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-2.1.1.tgz" integrity sha512-O+a5c0D2se/u2VlBJmPRn45IB6R4mYMh1ok3dWxrIZ2pmLqzggBhb875mbq73508ylzofc0+hT9W41x4Y2s8lg== -bindings@^1.5.0: +bindings@^1.2.1, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== @@ -7308,6 +7308,14 @@ interpret@^1.0.0: resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +iohook2@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/iohook2/-/iohook2-1.0.6.tgz#1460b7f6f6b8552ddd4f1a1cf5936833b170440b" + integrity sha512-fZuMADzz9uDof/SgmVt0XeH8uYYRPowAto+8m7NiBcp12IJub78HcyqcMoEVyTGFLzoS8p1AcBFJTS9l5Yb8eQ== + dependencies: + bindings "^1.2.1" + nan "^2.4.0" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz" @@ -9077,6 +9085,11 @@ nan@^2.12.1, nan@^2.17.0: resolved "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== +nan@^2.4.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" + integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== + nanoid@^3.3.6: version "3.3.6" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" From 66c68313b9834c473d779dad8647551018326fa2 Mon Sep 17 00:00:00 2001 From: devknight216 Date: Thu, 21 Mar 2024 16:37:25 +0000 Subject: [PATCH 4/5] fix: lint --- src/modules/CaptureUtility.js | 14 ++++++++------ src/modules/IpcHandlers.js | 2 +- src/modules/SystemInfoUtility.js | 13 ++++++------- src/modules/WindowUtility.js | 32 +++++++++++++++++++++++--------- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/modules/CaptureUtility.js b/src/modules/CaptureUtility.js index 64999db9..24883977 100644 --- a/src/modules/CaptureUtility.js +++ b/src/modules/CaptureUtility.js @@ -170,12 +170,14 @@ module.exports.optimizeVideo = ({ filePath, capturedEvents }) => { persistenceUtility.getSessionID(), tempName ); - let filterString = capturedEvents.map((overlay, index) => { - let backgroundColor = 'black'; - let textColor = 'white'; - let padding = 5; - return `drawtext=text='${overlay.text}':x=(w-text_w)/2:y=(h-text_h)/2:fontcolor=${textColor}:box=1:boxcolor=${backgroundColor}:boxborderw=${padding}:fontsize=24:fontfile=/path/to/font.ttf:enable='between(t,${overlay.start},${overlay.end})'`; - }).join(','); + let filterString = capturedEvents + .map((overlay) => { + let backgroundColor = "black"; + let textColor = "white"; + let padding = 5; + return `drawtext=text='${overlay.text}':x=(w-text_w)/2:y=(h-text_h)/2:fontcolor=${textColor}:box=1:boxcolor=${backgroundColor}:boxborderw=${padding}:fontsize=24:fontfile=/path/to/font.ttf:enable='between(t,${overlay.start},${overlay.end})'`; + }) + .join(","); return new Promise(function (resolve, reject) { ffmpeg(filePath) diff --git a/src/modules/IpcHandlers.js b/src/modules/IpcHandlers.js index b4227df3..298b516e 100644 --- a/src/modules/IpcHandlers.js +++ b/src/modules/IpcHandlers.js @@ -187,4 +187,4 @@ ipcMain.handle(IPC_HANDLERS.SYSTEMINFO, async (event, args) => { case IPC_FUNCTIONS.GET_SYSTEM_INFO: return await systemInfoUtility.getSystemInfo(); } -}) +}); diff --git a/src/modules/SystemInfoUtility.js b/src/modules/SystemInfoUtility.js index 46b3541c..8f382f53 100644 --- a/src/modules/SystemInfoUtility.js +++ b/src/modules/SystemInfoUtility.js @@ -1,8 +1,8 @@ -const os = require('os'); -const si = require('systeminformation'); +const os = require("os"); +const si = require("systeminformation"); async function getCurrentDateTime() { - return new Date().toLocaleString('en-US', { timeZone: 'UTC' }); + return new Date().toLocaleString("en-US", { timeZone: "UTC" }); } async function getComputerName() { @@ -18,7 +18,7 @@ async function getSystemInfo() { const systemInfo = await si.system(); return { manufacturer: systemInfo.manufacturer, - model: systemInfo.model + model: systemInfo.model, }; } @@ -58,10 +58,9 @@ module.exports.getSystemInfo = async () => { biosVersion, processor, memory, - }; } catch (error) { - console.error('Error fetching system information:', error); + console.error("Error fetching system information:", error); return null; // or handle the error in a different way as per your requirement } -} +}; diff --git a/src/modules/WindowUtility.js b/src/modules/WindowUtility.js index 611cf83e..b4ae96b3 100644 --- a/src/modules/WindowUtility.js +++ b/src/modules/WindowUtility.js @@ -20,29 +20,43 @@ module.exports.startKeyboardCapture = () => { const startingPoint = Date.now(); capturedEvents = []; - iohook.on("keydown", event => { - if ((event.ctrl || event.shift || event.alt || event.meta ) && !isControlKey(event.key)) { + iohook.on("keydown", (event) => { + if ( + (event.ctrl || event.shift || event.alt || event.meta) && + !isControlKey(event.key) + ) { // If Ctrl, Shift, Alt or Meta key is pressed along with a regular key capturedEvents.push({ type: "hotkey", - text: `${event.ctrl ? 'Ctrl+' : ''}${event.shift ? 'Shift+' : ''}${event.alt ? 'Alt+' : ''}${event.meta ? 'Meta+' : ''}${event.key.toUpperCase()}`, - start: parseFloat((Date.now() - startingPoint)/1000).toFixed(2), - end: parseFloat(((Date.now() - startingPoint)/1000).toFixed(2)) + 1, + text: `${event.ctrl ? "Ctrl+" : ""}${event.shift ? "Shift+" : ""}${ + event.alt ? "Alt+" : "" + }${event.meta ? "Meta+" : ""}${event.key.toUpperCase()}`, + start: parseFloat((Date.now() - startingPoint) / 1000).toFixed(2), + end: parseFloat(((Date.now() - startingPoint) / 1000).toFixed(2)) + 1, }); } }); function isControlKey(key) { // Check if the key is one of the individual control keys - return ['leftCtrl', 'rightCtrl', 'leftAlt', 'rightAlt', 'leftShift', 'rightShift', 'leftMeta', 'rightMeta'].includes(key); + return [ + "leftCtrl", + "rightCtrl", + "leftAlt", + "rightAlt", + "leftShift", + "rightShift", + "leftMeta", + "rightMeta", + ].includes(key); } - iohook.on("mousedown", event => { + iohook.on("mousedown", () => { capturedEvents.push({ type: "mouse", text: "Mouse Click", - start: parseFloat((Date.now() - startingPoint)/1000).toFixed(2), - end: parseFloat(((Date.now() - startingPoint)/1000).toFixed(2)) + 1, + start: parseFloat((Date.now() - startingPoint) / 1000).toFixed(2), + end: parseFloat(((Date.now() - startingPoint) / 1000).toFixed(2)) + 1, }); }); }; From caf23f54302f15ce83a551209c7f9ceb79eb3b73 Mon Sep 17 00:00:00 2001 From: devknight216 Date: Fri, 22 Mar 2024 13:52:49 +0000 Subject: [PATCH 5/5] fix: keep last captured press --- src/modules/WindowUtility.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/WindowUtility.js b/src/modules/WindowUtility.js index b4ae96b3..057d77de 100644 --- a/src/modules/WindowUtility.js +++ b/src/modules/WindowUtility.js @@ -63,7 +63,6 @@ module.exports.startKeyboardCapture = () => { module.exports.stopKeyboardCapture = () => { iohook.stop(); - capturedEvents.pop(); return capturedEvents; };