From 5daf9bbac2fab19478c64006eeb444f9167367b9 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 21 Apr 2026 00:21:50 +0200 Subject: [PATCH 01/25] Feature: Screenshot copy to clipboard --- src/constants.js | 1 + src/main/index.js | 7 +- src/preload/interface.js | 9 ++ .../PlayerSettings/PlayerSettings.vue | 130 +++++++++++------- .../ft-shaka-video-player.js | 61 +++++--- src/renderer/store/modules/settings.js | 2 + static/locales/en-US.yaml | 4 + 7 files changed, 148 insertions(+), 66 deletions(-) diff --git a/src/constants.js b/src/constants.js index 7c61599a0ea7b..6a44e9b0d3ebd 100644 --- a/src/constants.js +++ b/src/constants.js @@ -44,6 +44,7 @@ const IpcChannels = { CHOOSE_DEFAULT_FOLDER: 'choose-default-folder', WRITE_TO_DEFAULT_FOLDER: 'write-to-default-folder', + WRITE_IMAGE_TO_CLIPBOARD: 'write-image-to-clipboard', OPEN_IN_EXTERNAL_PLAYER: 'open-in-external-player', OPEN_IN_EXTERNAL_PLAYER_RESULT: 'open-in-external-player-result' diff --git a/src/main/index.js b/src/main/index.js index 64e8d2e7525a9..bfafedfbda54b 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -2,7 +2,7 @@ import { app, BrowserWindow, dialog, Menu, ipcMain, powerSaveBlocker, screen, session, shell, nativeTheme, net, protocol, clipboard, - Tray + Tray, nativeImage, } from 'electron' import path from 'path' import cp from 'child_process' @@ -1448,6 +1448,11 @@ function runApp() { return true }) + ipcMain.handle(IpcChannels.WRITE_IMAGE_TO_CLIPBOARD, (_, arrayBuffer, width, height) => { + const image = nativeImage.createFromBuffer(Buffer.from(arrayBuffer), { width, height }) + clipboard.writeImage(image) + }) + /** @type {Map} */ const activePowerSaveBlockers = new Map() diff --git a/src/preload/interface.js b/src/preload/interface.js index d8eb910d6109c..2233ca0f457eb 100644 --- a/src/preload/interface.js +++ b/src/preload/interface.js @@ -131,6 +131,15 @@ export default { return await ipcRenderer.invoke(IpcChannels.WRITE_TO_DEFAULT_FOLDER, filename, contents) }, + /** + * @param {ArrayBuffer} arrayBuffer + * @param {number} width + * @param {number} height + */ + writeImageToClipboard: async (arrayBuffer, width, height) => { + return await ipcRenderer.invoke(IpcChannels.WRITE_IMAGE_TO_CLIPBOARD, arrayBuffer, width, height) + }, + relaunch: () => { ipcRenderer.send(IpcChannels.RELAUNCH_REQUEST) }, diff --git a/src/renderer/components/PlayerSettings/PlayerSettings.vue b/src/renderer/components/PlayerSettings/PlayerSettings.vue index ff02f2f3f4d14..65b676d652ae2 100644 --- a/src/renderer/components/PlayerSettings/PlayerSettings.vue +++ b/src/renderer/components/PlayerSettings/PlayerSettings.vue @@ -197,58 +197,72 @@ - - -

- {{ t('Settings.Player Settings.Screenshot.Folder Label') }} -

- -
- -

- {{ t('Settings.Player Settings.Screenshot.File Name Label') }} - + + -

- - -
+ + +

+ {{ t('Settings.Player Settings.Screenshot.Folder Label') }} +

+ + +
+ +

+ {{ t('Settings.Player Settings.Screenshot.File Name Label') }} + +

+ + +
+
@@ -671,6 +685,26 @@ async function getScreenshotFilenameExample(pattern) { return false } } + +/** @type {import('vue').ComputedRef} */ +const screenshotCopyToClipboard = computed(() => store.getters.getScreenshotCopyToClipboard) + +/** + * @param {boolean} value + */ +function updateScreenshotCopyToClipboard(value) { + store.dispatch('updateScreenshotCopyToClipboard', value) +} + +/** @type {import('vue').ComputedRef} */ +const screenshotSaveOnDisk = computed(() => store.getters.getScreenshotSaveOnDisk) + +/** + * @param {boolean} value + */ +function updateScreenshotSaveOnDisk(value) { + store.dispatch('updateScreenshotSaveOnDisk', value) +}