From c25a6f9d2ab4d5d04384c3fd6f93b98ad7adfb2e Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 10 Apr 2022 01:12:06 +0300 Subject: [PATCH 01/10] launch pip from video overlay v1 --- plugins/picture-in-picture/style.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/picture-in-picture/style.css b/plugins/picture-in-picture/style.css index adb962d8..ee890c65 100644 --- a/plugins/picture-in-picture/style.css +++ b/plugins/picture-in-picture/style.css @@ -1,7 +1,10 @@ ytmusic-player-bar.pip svg, -ytmusic-player-bar.pip yt-formatted-string { - filter: drop-shadow(2px 4px 6px black); - color: white; +ytmusic-player-bar.pip .time-info, +ytmusic-player-bar.pip yt-formatted-string, +ytmusic-player-bar.pip .yt-formatted-string { + filter: drop-shadow(2px 4px 6px black); + color: white !important; + fill: white !important; } ytmusic-player-bar.pip ytmusic-player-expanding-menu { From 768ec7bda73505c307b50d7bb3519d8433eb00fe Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 10 Apr 2022 19:19:20 +0300 Subject: [PATCH 02/10] v2 --- index.js | 16 ++++-- plugins/picture-in-picture/back.js | 78 +++++++++++++++++++++-------- plugins/picture-in-picture/front.js | 17 ++++++- plugins/picture-in-picture/menu.js | 20 ++++++++ plugins/quality-changer/front.js | 3 +- 5 files changed, 106 insertions(+), 28 deletions(-) create mode 100644 plugins/picture-in-picture/menu.js diff --git a/index.js b/index.js index 96de5491..0b4566fb 100644 --- a/index.js +++ b/index.js @@ -175,6 +175,8 @@ function createMainWindow() { win.webContents.loadURL(urlToLoad); win.on("closed", onClosed); + const setPiPOptions = (key, value) => config.plugins.setOptions("picture-in-picture", { [key]: value }); + win.on("move", () => { if (win.isMaximized()) return; let position = win.getPosition(); @@ -183,6 +185,8 @@ function createMainWindow() { config.plugins.getOptions("picture-in-picture")["isInPiP"]; if (!isPiPEnabled) { lateSave("window-position", { x: position[0], y: position[1] }); + } else if(config.plugins.getOptions("picture-in-picture")["savePosition"]) { + lateSave("pip-position", position, setPiPOptions); } }); @@ -196,25 +200,29 @@ function createMainWindow() { winWasMaximized = isMaximized; config.set("window-maximized", isMaximized); } + if (isMaximized) return; + const isPiPEnabled = config.plugins.isEnabled("picture-in-picture") && config.plugins.getOptions("picture-in-picture")["isInPiP"]; - if (!isMaximized && !isPiPEnabled) { + if (!isPiPEnabled) { lateSave("window-size", { width: windowSize[0], height: windowSize[1], }); + } else if(config.plugins.getOptions("picture-in-picture")["saveSize"]) { + lateSave("pip-size", windowSize, setPiPOptions); } }); let savedTimeouts = {}; - function lateSave(key, value) { + function lateSave(key, value, fn = config.set) { if (savedTimeouts[key]) clearTimeout(savedTimeouts[key]); savedTimeouts[key] = setTimeout(() => { - config.set(key, value); + fn(key, value); savedTimeouts[key] = undefined; - }, 1000) + }, 600); } win.webContents.on("render-process-gone", (event, webContents, details) => { diff --git a/plugins/picture-in-picture/back.js b/plugins/picture-in-picture/back.js index 7cda241f..c4a0bb40 100644 --- a/plugins/picture-in-picture/back.js +++ b/plugins/picture-in-picture/back.js @@ -5,18 +5,33 @@ const { app, ipcMain } = require("electron"); const { setOptions } = require("../../config/plugins"); const { injectCSS } = require("../utils"); -let isInPiPMode = false; +let isInPiP = false; let originalPosition; let originalSize; +let originalFullScreen; +let originalMaximized; -const pipPosition = [10, 10]; -const pipSize = [450, 275]; +let win; +let options; -const togglePiP = async (win) => { - isInPiPMode = !isInPiPMode; - setOptions("picture-in-picture", { isInPiP: isInPiPMode }); +const pipPosition = () => (options.savePosition && options["pip-position"]) || [10, 10]; +const pipSize = () => (options.saveSize && options["pip-size"]) || [450, 275]; - if (isInPiPMode) { +const setLocalOptions = (_options) => { + options = { ...options, ..._options }; + setOptions("picture-in-picture", _options); +} + +const togglePiP = async () => { + isInPiP = !isInPiP; + setLocalOptions({ isInPiP }); + + if (isInPiP) { + originalFullScreen = win.isFullScreen(); + if (originalFullScreen) win.setFullScreen(false); + originalMaximized = win.isMaximized(); + if (originalMaximized) win.unmaximize(); + originalPosition = win.getPosition(); originalSize = win.getSize(); @@ -26,6 +41,13 @@ const togglePiP = async (win) => { await win.webContents.executeJavaScript( // Go fullscreen ` + var exitButton = document.querySelector(".exit-fullscreen-button"); + exitButton.replaceWith(exitButton.cloneNode(true)); + document.querySelector(".exit-fullscreen-button").onclick = () => togglePictureInPicture(); + + var onPlayerDblClick = document.querySelector('#player').onDoubleClick_ + document.querySelector('#player').onDoubleClick_ = () => {}; + document.querySelector('#expanding-menu').onmouseleave = () => document.querySelector('.middle-controls').click(); if (!document.querySelector("ytmusic-player-page").playerPageOpen_) { document.querySelector(".toggle-player-page-button").click(); } @@ -47,6 +69,9 @@ const togglePiP = async (win) => { await win.webContents.executeJavaScript( // Exit fullscreen ` + document.querySelector('#player').onDoubleClick_ = onPlayerDblClick; + document.querySelector('#expanding-menu').onmouseleave = undefined; + document.querySelector(".exit-fullscreen-button").replaceWith(exitButton); document.querySelector(".exit-fullscreen-button").click(); document.querySelector("ytmusic-player-bar").classList.remove("pip"); ` @@ -54,26 +79,39 @@ const togglePiP = async (win) => { win.setVisibleOnAllWorkspaces(false); win.setAlwaysOnTop(false); + + if (originalFullScreen) win.setFullScreen(true); + if (originalMaximized) win.maximize(); } - const [x, y] = isInPiPMode ? pipPosition : originalPosition; - const [w, h] = isInPiPMode ? pipSize : originalSize; + const [x, y] = isInPiP ? pipPosition() : originalPosition; + const [w, h] = isInPiP ? pipSize() : originalSize; win.setPosition(x, y); win.setSize(w, h); - win.setWindowButtonVisibility?.(!isInPiPMode); -}; - -module.exports = (win) => { - injectCSS(win.webContents, path.join(__dirname, "style.css")); - ipcMain.on("picture-in-picture", async () => { - await togglePiP(win); - }); + win.setWindowButtonVisibility?.(!isInPiP); }; const blockShortcutsInPiP = (event, input) => { - const blockedShortcuts = ["f", "escape"]; - if (blockedShortcuts.includes(input.key.toLowerCase())) { + const key = input.key.toLowerCase(); + + if (key === "f") { event.preventDefault(); - } + } else if (key === 'escape') { + togglePiP(); + event.preventDefault(); + }; }; + +module.exports = (_win, _options) => { + options ??= _options; + win ??= _win; + setLocalOptions({ isInPiP }); + injectCSS(win.webContents, path.join(__dirname, "style.css")); + ipcMain.on("picture-in-picture", async () => { + await togglePiP(); + }); +}; + +module.exports.setOptions = setLocalOptions; + diff --git a/plugins/picture-in-picture/front.js b/plugins/picture-in-picture/front.js index 637c7fb6..ea03cedd 100644 --- a/plugins/picture-in-picture/front.js +++ b/plugins/picture-in-picture/front.js @@ -3,6 +3,8 @@ const { ipcRenderer } = require("electron"); const { getSongMenu } = require("../../providers/dom-elements"); const { ElementFromFile, templatePath } = require("../utils"); +function $(selector) { return document.querySelector(selector); } + let menu = null; const pipButton = ElementFromFile( templatePath(__dirname, "picture-in-picture.html") @@ -14,7 +16,7 @@ const observer = new MutationObserver(() => { if (!menu) return; } if (menu.contains(pipButton)) return; - const menuUrl = document.querySelector( + const menuUrl = $( 'tp-yt-paper-listbox [tabindex="0"] #navigation-endpoint' )?.href; if (menuUrl && !menuUrl.includes("watch?")) return; @@ -30,7 +32,18 @@ function observeMenu(options) { document.addEventListener( "apiLoaded", () => { - observer.observe(document.querySelector("ytmusic-popup-container"), { + const minButton = $(".player-minimize-button"); + // remove native listeners + minButton.replaceWith(minButton.cloneNode(true)); + $(".player-minimize-button").onclick = () => { + global.togglePictureInPicture(); + setTimeout(() => $('#player').click()); + }; + + // allows easily closing the menu by programmatically clicking outside of it + $("#expanding-menu").removeAttribute("no-cancel-on-outside-click"); + // TODO: think about wether an additional button in songMenu is needed + observer.observe($("ytmusic-popup-container"), { childList: true, subtree: true, }); diff --git a/plugins/picture-in-picture/menu.js b/plugins/picture-in-picture/menu.js new file mode 100644 index 00000000..f996a57f --- /dev/null +++ b/plugins/picture-in-picture/menu.js @@ -0,0 +1,20 @@ +const { setOptions } = require("./back.js"); + +module.exports = (_win, options) => [ + { + label: "Save window position", + type: "checkbox", + checked: options.savePosition, + click: (item) => { + setOptions({ savePosition: item.checked }); + }, + }, + { + label: "Save window size", + type: "checkbox", + checked: options.saveSize, + click: (item) => { + setOptions({ saveSize: item.checked }); + }, + } +]; diff --git a/plugins/quality-changer/front.js b/plugins/quality-changer/front.js index 669d39ba..4c553a9f 100644 --- a/plugins/quality-changer/front.js +++ b/plugins/quality-changer/front.js @@ -18,8 +18,7 @@ function setup(event) { $('.top-row-buttons.ytmusic-player').prepend(qualitySettingsButton); qualitySettingsButton.onclick = function chooseQuality() { - if (api.getPlayerState() === 2) api.playVideo(); - else if (api.getPlayerState() === 1) api.pauseVideo(); + setTimeout(() => $('#player').click()); const currentIndex = api.getAvailableQualityLevels().indexOf(api.getPlaybackQuality()) From d23bfe936840b947ca101fd304464f65d36e88cc Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 10 Apr 2022 21:16:43 +0300 Subject: [PATCH 03/10] v3 --- plugins/in-app-menu/front.js | 7 +++ .../adaptors/in-app-menu.js | 37 ++++++++++++++ plugins/picture-in-picture/back.js | 48 +++++++------------ plugins/picture-in-picture/front.js | 36 ++++++++++++++ plugins/picture-in-picture/menu.js | 11 ++++- 5 files changed, 108 insertions(+), 31 deletions(-) create mode 100644 plugins/picture-in-picture/adaptors/in-app-menu.js diff --git a/plugins/in-app-menu/front.js b/plugins/in-app-menu/front.js index aa025f3d..26d5992d 100644 --- a/plugins/in-app-menu/front.js +++ b/plugins/in-app-menu/front.js @@ -1,6 +1,7 @@ const { ipcRenderer } = require("electron"); const config = require("../../config"); const { Titlebar, Color } = require("custom-electron-titlebar"); +const { isEnabled } = require("../../config/plugins"); function $(selector) { return document.querySelector(selector); } module.exports = () => { @@ -25,6 +26,12 @@ module.exports = () => { } }); + if (isEnabled("picture-in-picture")) { + ipcRenderer.on("pip-toggle", (_, pipEnabled) => { + bar.refreshMenu(); + }); + } + // Increases the right margin of Navbar background when the scrollbar is visible to avoid blocking it (z-index doesn't affect it) document.addEventListener('apiLoaded', () => { setNavbarMargin(); diff --git a/plugins/picture-in-picture/adaptors/in-app-menu.js b/plugins/picture-in-picture/adaptors/in-app-menu.js new file mode 100644 index 00000000..a96ae967 --- /dev/null +++ b/plugins/picture-in-picture/adaptors/in-app-menu.js @@ -0,0 +1,37 @@ +const { Menu, app } = require("electron"); +const { setApplicationMenu } = require("../../../menu"); + +module.exports = (win, options, setOptions, togglePip, isInPip) => { + if (isInPip) { + Menu.setApplicationMenu(Menu.buildFromTemplate([ + { + label: "App", + submenu: [ + { + label: "Exit Picture in Picture", + click: togglePip, + }, + { + label: "Always on top", + type: "checkbox", + checked: options.alwaysOnTop, + click: (item) => { + setOptions({ alwaysOnTop: item.checked }); + win.setAlwaysOnTop(item.checked); + }, + }, + { + label: "Restart", + click: () => { + app.relaunch(); + app.quit(); + }, + }, + { role: "quit" }, + ], + }, + ])); + } else { + setApplicationMenu(win); + } +}; diff --git a/plugins/picture-in-picture/back.js b/plugins/picture-in-picture/back.js index c4a0bb40..f462a2b7 100644 --- a/plugins/picture-in-picture/back.js +++ b/plugins/picture-in-picture/back.js @@ -2,7 +2,7 @@ const path = require("path"); const { app, ipcMain } = require("electron"); -const { setOptions } = require("../../config/plugins"); +const { setOptions, isEnabled } = require("../../config/plugins"); const { injectCSS } = require("../utils"); let isInPiP = false; @@ -22,6 +22,15 @@ const setLocalOptions = (_options) => { setOptions("picture-in-picture", _options); } + +const adaptors = []; +const runAdaptors = () => adaptors.forEach(a => a()); + +if (isEnabled("in-app-menu")) { + let adaptor = require("./adaptors/in-app-menu"); + adaptors.push(() => adaptor(win, options, setLocalOptions, togglePiP, isInPiP)); +} + const togglePiP = async () => { isInPiP = !isInPiP; setLocalOptions({ isInPiP }); @@ -38,44 +47,24 @@ const togglePiP = async () => { win.webContents.on("before-input-event", blockShortcutsInPiP); win.setFullScreenable(false); - await win.webContents.executeJavaScript( - // Go fullscreen - ` - var exitButton = document.querySelector(".exit-fullscreen-button"); - exitButton.replaceWith(exitButton.cloneNode(true)); - document.querySelector(".exit-fullscreen-button").onclick = () => togglePictureInPicture(); - var onPlayerDblClick = document.querySelector('#player').onDoubleClick_ - document.querySelector('#player').onDoubleClick_ = () => {}; - document.querySelector('#expanding-menu').onmouseleave = () => document.querySelector('.middle-controls').click(); - if (!document.querySelector("ytmusic-player-page").playerPageOpen_) { - document.querySelector(".toggle-player-page-button").click(); - } - document.querySelector(".fullscreen-button").click(); - document.querySelector("ytmusic-player-bar").classList.add("pip"); - ` - ); - win.setFullScreenable(true); + runAdaptors(); + win.webContents.send("pip-toggle", true); app.dock?.hide(); win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true, }); app.dock?.show(); - win.setAlwaysOnTop(true, "screen-saver", 1); + if (options.alwaysOnTop) { + win.setAlwaysOnTop(true, "screen-saver", 1); + } } else { win.webContents.removeListener("before-input-event", blockShortcutsInPiP); + win.setFullScreenable(true); - await win.webContents.executeJavaScript( - // Exit fullscreen - ` - document.querySelector('#player').onDoubleClick_ = onPlayerDblClick; - document.querySelector('#expanding-menu').onmouseleave = undefined; - document.querySelector(".exit-fullscreen-button").replaceWith(exitButton); - document.querySelector(".exit-fullscreen-button").click(); - document.querySelector("ytmusic-player-bar").classList.remove("pip"); - ` - ); + runAdaptors(); + win.webContents.send("pip-toggle", false); win.setVisibleOnAllWorkspaces(false); win.setAlwaysOnTop(false); @@ -114,4 +103,3 @@ module.exports = (_win, _options) => { }; module.exports.setOptions = setLocalOptions; - diff --git a/plugins/picture-in-picture/front.js b/plugins/picture-in-picture/front.js index ea03cedd..f57f20ae 100644 --- a/plugins/picture-in-picture/front.js +++ b/plugins/picture-in-picture/front.js @@ -28,10 +28,46 @@ global.togglePictureInPicture = () => { ipcRenderer.send("picture-in-picture"); }; +const listenForToggle = () => { + const originalExitButton = $(".exit-fullscreen-button"); + const clonedExitButton = originalExitButton.cloneNode(true); + clonedExitButton.onclick = () => togglePictureInPicture(); + + const player = $('#player'); + const onPlayerDblClick = player.onDoubleClick_; + + const playerBar = $("ytmusic-player-bar"); + const expandMenu = $('#expanding-menu'); + const middleControls = $('.middle-controls'); + const playerPage = $("ytmusic-player-page"); + const togglePlayerPageButton = $(".toggle-player-page-button"); + const fullScreenButton = $(".fullscreen-button"); + + ipcRenderer.on('pip-toggle', (_, isPip) => { + if (isPip) { + $(".exit-fullscreen-button").replaceWith(clonedExitButton); + player.onDoubleClick_ = () => {}; + expandMenu.onmouseleave = () => middleControls.click(); + if (!playerPage.playerPageOpen_) { + togglePlayerPageButton.click(); + } + fullScreenButton.click(); + playerBar.classList.add("pip"); + } else { + $(".exit-fullscreen-button").replaceWith(originalExitButton); + player.onDoubleClick_ = onPlayerDblClick; + expandMenu.onmouseleave = undefined; + originalExitButton.click(); + playerBar.classList.remove("pip"); + } + }); +} + function observeMenu(options) { document.addEventListener( "apiLoaded", () => { + listenForToggle(); const minButton = $(".player-minimize-button"); // remove native listeners minButton.replaceWith(minButton.cloneNode(true)); diff --git a/plugins/picture-in-picture/menu.js b/plugins/picture-in-picture/menu.js index f996a57f..c2eb35cd 100644 --- a/plugins/picture-in-picture/menu.js +++ b/plugins/picture-in-picture/menu.js @@ -1,6 +1,15 @@ const { setOptions } = require("./back.js"); -module.exports = (_win, options) => [ +module.exports = (win, options) => [ + { + label: "Always on top", + type: "checkbox", + checked: options.alwaysOnTop, + click: (item) => { + setOptions({ alwaysOnTop: item.checked }); + win.setAlwaysOnTop(item.checked); + }, + }, { label: "Save window position", type: "checkbox", From 30840804fab5c0f27a883bcb7e39eba933262f9d Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 11 Apr 2022 00:15:19 +0300 Subject: [PATCH 04/10] fix: sync pip and index.js options --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 0b4566fb..bfc06ccc 100644 --- a/index.js +++ b/index.js @@ -175,7 +175,9 @@ function createMainWindow() { win.webContents.loadURL(urlToLoad); win.on("closed", onClosed); - const setPiPOptions = (key, value) => config.plugins.setOptions("picture-in-picture", { [key]: value }); + const setPiPOptions = config.plugins.isEnabled("picture-in-picture") + ? (key, value) => require("./plugins/picture-in-picture/back").setOptions({ [key]: value }) + : () => {}; win.on("move", () => { if (win.isMaximized()) return; From 0f192aab2b542334cd6b6dca38ac63c1d44b1073 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 11 Apr 2022 01:07:07 +0300 Subject: [PATCH 05/10] fix precise-volume position in PiP --- plugins/picture-in-picture/front.js | 11 +++++------ plugins/picture-in-picture/style.css | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/plugins/picture-in-picture/front.js b/plugins/picture-in-picture/front.js index f57f20ae..685b15c1 100644 --- a/plugins/picture-in-picture/front.js +++ b/plugins/picture-in-picture/front.js @@ -33,15 +33,14 @@ const listenForToggle = () => { const clonedExitButton = originalExitButton.cloneNode(true); clonedExitButton.onclick = () => togglePictureInPicture(); - const player = $('#player'); - const onPlayerDblClick = player.onDoubleClick_; - - const playerBar = $("ytmusic-player-bar"); + const appLayout = $("ytmusic-app-layout"); const expandMenu = $('#expanding-menu'); const middleControls = $('.middle-controls'); const playerPage = $("ytmusic-player-page"); const togglePlayerPageButton = $(".toggle-player-page-button"); const fullScreenButton = $(".fullscreen-button"); + const player = $('#player'); + const onPlayerDblClick = player.onDoubleClick_; ipcRenderer.on('pip-toggle', (_, isPip) => { if (isPip) { @@ -52,13 +51,13 @@ const listenForToggle = () => { togglePlayerPageButton.click(); } fullScreenButton.click(); - playerBar.classList.add("pip"); + appLayout.classList.add("pip"); } else { $(".exit-fullscreen-button").replaceWith(originalExitButton); player.onDoubleClick_ = onPlayerDblClick; expandMenu.onmouseleave = undefined; originalExitButton.click(); - playerBar.classList.remove("pip"); + appLayout.classList.remove("pip"); } }); } diff --git a/plugins/picture-in-picture/style.css b/plugins/picture-in-picture/style.css index ee890c65..beb45251 100644 --- a/plugins/picture-in-picture/style.css +++ b/plugins/picture-in-picture/style.css @@ -1,14 +1,21 @@ -ytmusic-player-bar.pip svg, -ytmusic-player-bar.pip .time-info, -ytmusic-player-bar.pip yt-formatted-string, -ytmusic-player-bar.pip .yt-formatted-string { +/* improve visibility of the player bar elements */ +ytmusic-app-layout.pip ytmusic-player-bar svg, +ytmusic-app-layout.pip ytmusic-player-bar .time-info, +ytmusic-app-layout.pip ytmusic-player-bar yt-formatted-string, +ytmusic-app-layout.pip ytmusic-player-bar .yt-formatted-string { filter: drop-shadow(2px 4px 6px black); color: white !important; fill: white !important; } -ytmusic-player-bar.pip ytmusic-player-expanding-menu { +/* improve the style of the player bar expanding menu */ +ytmusic-app-layout.pip ytmusic-player-expanding-menu { border-radius: 30px; background-color: rgba(0, 0, 0, 0.3); backdrop-filter: blur(5px) brightness(20%); } + +/* fix volumeHud position when both in-app-menu and PiP are active */ +.cet-container ytmusic-app-layout.pip #volumeHud{ + top: 22px !important; +} From feb06b015e2ce0b5eaebcb595b5918ca7116cbbd Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Fri, 15 Apr 2022 15:27:16 +0300 Subject: [PATCH 06/10] dont save maximized state in PiP mode --- index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index bfc06ccc..d3badf25 100644 --- a/index.js +++ b/index.js @@ -196,17 +196,18 @@ function createMainWindow() { win.on("resize", () => { const windowSize = win.getSize(); - const isMaximized = win.isMaximized(); - if (winWasMaximized !== isMaximized) { + + const isPiPEnabled = + config.plugins.isEnabled("picture-in-picture") && + config.plugins.getOptions("picture-in-picture")["isInPiP"]; + + if (!isPiPEnabled && winWasMaximized !== isMaximized) { winWasMaximized = isMaximized; config.set("window-maximized", isMaximized); } if (isMaximized) return; - const isPiPEnabled = - config.plugins.isEnabled("picture-in-picture") && - config.plugins.getOptions("picture-in-picture")["isInPiP"]; if (!isPiPEnabled) { lateSave("window-size", { width: windowSize[0], From b4209984587ce21a84f9db5cd34aaa5875a50fa0 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Fri, 15 Apr 2022 15:27:31 +0300 Subject: [PATCH 07/10] disable the video-toggle button when in PiP mode --- plugins/picture-in-picture/style.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/picture-in-picture/style.css b/plugins/picture-in-picture/style.css index beb45251..1856e01b 100644 --- a/plugins/picture-in-picture/style.css +++ b/plugins/picture-in-picture/style.css @@ -16,6 +16,11 @@ ytmusic-app-layout.pip ytmusic-player-expanding-menu { } /* fix volumeHud position when both in-app-menu and PiP are active */ -.cet-container ytmusic-app-layout.pip #volumeHud{ +.cet-container ytmusic-app-layout.pip #volumeHud { top: 22px !important; } + +/* disable the video-toggle button when in PiP mode */ +ytmusic-app-layout.pip .video-switch-button { + display: none !important; +} From 77d4e9cb84a3def032cafbbe82bfd8e7fc1318e2 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Fri, 15 Apr 2022 15:57:48 +0300 Subject: [PATCH 08/10] add optional PiP hotkey --- plugins/picture-in-picture/back.js | 4 ++++ plugins/picture-in-picture/menu.js | 32 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/plugins/picture-in-picture/back.js b/plugins/picture-in-picture/back.js index f462a2b7..fa679d79 100644 --- a/plugins/picture-in-picture/back.js +++ b/plugins/picture-in-picture/back.js @@ -1,6 +1,7 @@ const path = require("path"); const { app, ipcMain } = require("electron"); +const electronLocalshortcut = require("electron-localshortcut"); const { setOptions, isEnabled } = require("../../config/plugins"); const { injectCSS } = require("../utils"); @@ -100,6 +101,9 @@ module.exports = (_win, _options) => { ipcMain.on("picture-in-picture", async () => { await togglePiP(); }); + if (options.hotkey) { + electronLocalshortcut.register(win, options.hotkey, togglePiP); + } }; module.exports.setOptions = setLocalOptions; diff --git a/plugins/picture-in-picture/menu.js b/plugins/picture-in-picture/menu.js index c2eb35cd..98de5033 100644 --- a/plugins/picture-in-picture/menu.js +++ b/plugins/picture-in-picture/menu.js @@ -1,3 +1,6 @@ +const prompt = require("custom-electron-prompt"); + +const promptOptions = require("../../providers/prompt-options"); const { setOptions } = require("./back.js"); module.exports = (win, options) => [ @@ -25,5 +28,34 @@ module.exports = (win, options) => [ click: (item) => { setOptions({ saveSize: item.checked }); }, + }, + { + label: "Hotkey", + type: "checkbox", + checked: options.hotkey, + click: async (item) => { + const output = await prompt({ + title: "Picture in Picture Hotkey", + label: "Choose a hotkey for toggling Picture in Picture", + type: "keybind", + keybindOptions: [{ + value: "hotkey", + label: "Hotkey", + default: options.hotkey + }], + ...promptOptions() + }, win) + + if (output) { + const { value, accelerator } = output[0]; + console.log({ [value]: accelerator }); // DELETE + setOptions({ [value]: accelerator }); + + item.checked = !!accelerator; + } else { + // Reset checkbox if prompt was canceled + item.checked = !item.checked; + } + }, } ]; From f6de5c7c22250bcdab9685685f2a0393bb17cd77 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Wed, 20 Apr 2022 15:20:34 +0300 Subject: [PATCH 09/10] PiP options defaults + migrations --- config/defaults.js | 7 +++++++ config/store.js | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/config/defaults.js b/config/defaults.js index 0a920895..442f1357 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -82,6 +82,13 @@ const defaultConfig = { enabled: false, forceHide: false, }, + "picture-in-picture": { + "enabled": false, + "alwaysOnTop": true, + "savePosition": true, + "saveSize": false, + "hotkey": "P" + }, }, }; diff --git a/config/store.js b/config/store.js index 0b20693e..de04a582 100644 --- a/config/store.js +++ b/config/store.js @@ -2,7 +2,16 @@ const Store = require("electron-store"); const defaults = require("./defaults"); +const setDefaultPluginOptions = (store, plugin) => { + if (!store.get(`plugins.${plugin}`)) { + store.set(`plugins.${plugin}`, defaults.plugins[plugin]); + } +} + const migrations = { + ">=1.17.0": (store) => { + setDefaultPluginOptions(store, "picture-in-picture"); + }, ">=1.14.0": (store) => { if ( typeof store.get("plugins.precise-volume.globalShortcuts") !== "object" From 7fe937b21ebfeee84bded6c9d7327e17d8592f1a Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Fri, 20 May 2022 19:26:55 +0300 Subject: [PATCH 10/10] lint --- plugins/picture-in-picture/menu.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/picture-in-picture/menu.js b/plugins/picture-in-picture/menu.js index 98de5033..bdbc1cee 100644 --- a/plugins/picture-in-picture/menu.js +++ b/plugins/picture-in-picture/menu.js @@ -48,7 +48,6 @@ module.exports = (win, options) => [ if (output) { const { value, accelerator } = output[0]; - console.log({ [value]: accelerator }); // DELETE setOptions({ [value]: accelerator }); item.checked = !!accelerator;