From 85eac4be142a0fa2cec43d56a5e257ee2e7dfa78 Mon Sep 17 00:00:00 2001 From: redphx <96280+redphx@users.noreply.github.com> Date: Sat, 11 May 2024 12:18:36 +0700 Subject: [PATCH] Move screenshot functions to a separate file --- src/index.ts | 8 +-- src/modules/game-bar/action-screenshot.ts | 54 +---------------- src/modules/ui/ui.ts | 6 +- src/utils/screenshot.ts | 72 +++++++++++++++++++++++ 4 files changed, 82 insertions(+), 58 deletions(-) create mode 100644 src/utils/screenshot.ts diff --git a/src/index.ts b/src/index.ts index 241030d..bbcd20c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,6 +28,7 @@ import { STATES } from "@utils/global"; import { injectStreamMenuButtons } from "@modules/stream/stream-ui"; import { BxLogger } from "@utils/bx-logger"; import { GameBar } from "./modules/game-bar/game-bar"; +import { Screenshot } from "./utils/screenshot"; // Handle login page @@ -143,7 +144,7 @@ window.addEventListener(BxEvent.STREAM_STARTING, e => { }); window.addEventListener(BxEvent.STREAM_PLAYING, e => { - const $video = (e as any).$video; + const $video = (e as any).$video as HTMLVideoElement; STATES.currentStream.$video = $video; STATES.isPlaying = true; @@ -156,10 +157,7 @@ window.addEventListener(BxEvent.STREAM_PLAYING, e => { gameBar.showBar(); } - if (STATES.currentStream.$screenshotCanvas) { - STATES.currentStream.$screenshotCanvas.width = $video.videoWidth; - STATES.currentStream.$screenshotCanvas.height = $video.videoHeight; - } + Screenshot.updateCanvasSize($video.videoWidth, $video.videoHeight); updateVideoPlayerCss(); }); diff --git a/src/modules/game-bar/action-screenshot.ts b/src/modules/game-bar/action-screenshot.ts index 3d6121a..da06056 100644 --- a/src/modules/game-bar/action-screenshot.ts +++ b/src/modules/game-bar/action-screenshot.ts @@ -1,9 +1,9 @@ import { BxEvent } from "@utils/bx-event"; -import { AppInterface, STATES } from "@utils/global"; import { BxIcon } from "@utils/bx-icon"; -import { createButton, ButtonStyle, CE } from "@utils/html"; +import { createButton, ButtonStyle } from "@utils/html"; import { BaseGameBarAction } from "./action-base"; import { t } from "@utils/translation"; +import { Screenshot } from "@/utils/screenshot"; export class ScreenshotAction extends BaseGameBarAction { $content: HTMLElement; @@ -11,13 +11,9 @@ export class ScreenshotAction extends BaseGameBarAction { constructor() { super(); - const currentStream = STATES.currentStream; - currentStream.$screenshotCanvas = CE('canvas', {'class': 'bx-gone'}); - document.documentElement.appendChild(currentStream.$screenshotCanvas!); - const onClick = (e: Event) => { BxEvent.dispatch(window, BxEvent.GAME_BAR_ACTION_ACTIVATED); - this.takeScreenshot(); + Screenshot.takeScreenshot(); }; this.$content = createButton({ @@ -31,48 +27,4 @@ export class ScreenshotAction extends BaseGameBarAction { render(): HTMLElement { return this.$content; } - - takeScreenshot(callback?: any) { - const currentStream = STATES.currentStream; - const $video = currentStream.$video; - const $canvas = currentStream.$screenshotCanvas; - if (!$video || !$canvas) { - return; - } - - const $canvasContext = $canvas.getContext('2d', { - alpha: false, - willReadFrequently: false, - })!; - - $canvasContext.drawImage($video, 0, 0, $canvas.width, $canvas.height); - - // Get data URL and pass to parent app - if (AppInterface) { - const data = $canvas.toDataURL('image/png').split(';base64,')[1]; - AppInterface.saveScreenshot(currentStream.titleId, data); - - // Free screenshot from memory - $canvasContext.clearRect(0, 0, $canvas.width, $canvas.height); - - callback && callback(); - return; - } - - $canvas && $canvas.toBlob(blob => { - // Download screenshot - const now = +new Date; - const $anchor = CE('a', { - 'download': `${currentStream.titleId}-${now}.png`, - 'href': URL.createObjectURL(blob!), - }); - $anchor.click(); - - // Free screenshot from memory - URL.revokeObjectURL($anchor.href); - $canvasContext.clearRect(0, 0, $canvas.width, $canvas.height); - - callback && callback(); - }, 'image/png'); - } } diff --git a/src/modules/ui/ui.ts b/src/modules/ui/ui.ts index b0fd131..3a2529f 100644 --- a/src/modules/ui/ui.ts +++ b/src/modules/ui/ui.ts @@ -10,6 +10,7 @@ import { TouchController } from "@modules/touch-controller"; import { t } from "@utils/translation"; import { VibrationManager } from "@modules/vibration-manager"; import { GameBar } from "../game-bar/game-bar"; +import { Screenshot } from "@/utils/screenshot"; export function localRedirect(path: string) { @@ -427,8 +428,8 @@ export function updateVideoPlayerCss() { } // Apply video filters to screenshots - if (getPref(PrefKey.SCREENSHOT_APPLY_FILTERS) && STATES.currentStream.$screenshotCanvas) { - STATES.currentStream.$screenshotCanvas.getContext('2d')!.filter = filters; + if (getPref(PrefKey.SCREENSHOT_APPLY_FILTERS)) { + Screenshot.updateCanvasFilters(filters); } const PREF_RATIO = getPref(PrefKey.VIDEO_RATIO); @@ -475,6 +476,7 @@ export function setupStreamUi() { setupQuickSettingsBar(); StreamStats.render(); + Screenshot.setup(); getPref(PrefKey.GAME_BAR_ENABLED) && GameBar.getInstance(); } diff --git a/src/utils/screenshot.ts b/src/utils/screenshot.ts new file mode 100644 index 0000000..a748d3d --- /dev/null +++ b/src/utils/screenshot.ts @@ -0,0 +1,72 @@ +import { AppInterface, STATES } from "./global"; +import { CE } from "./html"; + + +export class Screenshot { + static #filters: string = ''; + + static setup() { + const currentStream = STATES.currentStream; + if (!currentStream.$screenshotCanvas) { + currentStream.$screenshotCanvas = CE('canvas', {'class': 'bx-gone'}); + } + // document.documentElement.appendChild(currentStream.$screenshotCanvas!); + } + + static updateCanvasSize(width: number, height: number) { + const $canvas = STATES.currentStream.$screenshotCanvas; + if ($canvas) { + $canvas.width = width; + $canvas.height = height; + } + } + + static updateCanvasFilters(filters: string) { + Screenshot.#filters = filters; + } + + static takeScreenshot(callback?: any) { + const currentStream = STATES.currentStream; + const $video = currentStream.$video; + const $canvas = currentStream.$screenshotCanvas; + if (!$video || !$canvas) { + return; + } + + const canvasContext = $canvas.getContext('2d', { + alpha: false, + willReadFrequently: false, + })!; + + canvasContext.filter = Screenshot.#filters; + canvasContext.drawImage($video, 0, 0, $canvas.width, $canvas.height); + + // Get data URL and pass to parent app + if (AppInterface) { + const data = $canvas.toDataURL('image/png').split(';base64,')[1]; + AppInterface.saveScreenshot(currentStream.titleId, data); + + // Free screenshot from memory + canvasContext.clearRect(0, 0, $canvas.width, $canvas.height); + + callback && callback(); + return; + } + + $canvas && $canvas.toBlob(blob => { + // Download screenshot + const now = +new Date; + const $anchor = CE('a', { + 'download': `${currentStream.titleId}-${now}.png`, + 'href': URL.createObjectURL(blob!), + }); + $anchor.click(); + + // Free screenshot from memory + URL.revokeObjectURL($anchor.href); + canvasContext.clearRect(0, 0, $canvas.width, $canvas.height); + + callback && callback(); + }, 'image/png'); + } +}