mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 18:41:47 +00:00
Create first version of picture in picture plugin
This commit is contained in:
58
plugins/picture-in-picture/back.js
Normal file
58
plugins/picture-in-picture/back.js
Normal file
@ -0,0 +1,58 @@
|
||||
const path = require("path");
|
||||
|
||||
const { app, ipcMain } = require("electron");
|
||||
|
||||
const { injectCSS } = require("../utils");
|
||||
|
||||
let isInPiPMode = false;
|
||||
let originalPosition;
|
||||
let originalSize;
|
||||
|
||||
const pipPosition = [10, 10];
|
||||
const pipSize = [400, 220];
|
||||
|
||||
const togglePiP = async (win) => {
|
||||
isInPiPMode = !isInPiPMode;
|
||||
|
||||
if (isInPiPMode) {
|
||||
injectCSS(win.webContents, path.join(__dirname, "style.css"));
|
||||
|
||||
originalPosition = win.getPosition();
|
||||
originalSize = win.getSize();
|
||||
|
||||
win.setFullScreenable(false);
|
||||
await win.webContents.executeJavaScript(
|
||||
// Go fullscreen
|
||||
`document.querySelector(".fullscreen-button").click()`
|
||||
);
|
||||
|
||||
app.dock.hide();
|
||||
win.setVisibleOnAllWorkspaces(true, {
|
||||
visibleOnFullScreen: true,
|
||||
});
|
||||
app.dock.show();
|
||||
win.setAlwaysOnTop(true, "screen-saver", 1);
|
||||
} else {
|
||||
win.setFullScreenable(true);
|
||||
await win.webContents.executeJavaScript(
|
||||
// Exit fullscreen
|
||||
`document.querySelector(".exit-fullscreen-button").click()`
|
||||
);
|
||||
|
||||
win.setVisibleOnAllWorkspaces(false);
|
||||
win.setAlwaysOnTop(false);
|
||||
}
|
||||
|
||||
const [x, y] = isInPiPMode ? pipPosition : originalPosition;
|
||||
const [w, h] = isInPiPMode ? pipSize : originalSize;
|
||||
win.setPosition(x, y);
|
||||
win.setSize(w, h);
|
||||
|
||||
win.setWindowButtonVisibility(!isInPiPMode);
|
||||
};
|
||||
|
||||
module.exports = (win) => {
|
||||
ipcMain.on("picture-in-picture", async () => {
|
||||
await togglePiP(win);
|
||||
});
|
||||
};
|
||||
42
plugins/picture-in-picture/front.js
Normal file
42
plugins/picture-in-picture/front.js
Normal file
@ -0,0 +1,42 @@
|
||||
const { ipcRenderer } = require("electron");
|
||||
|
||||
const { getSongMenu } = require("../../providers/dom-elements");
|
||||
const { ElementFromFile, templatePath } = require("../utils");
|
||||
|
||||
let menu = null;
|
||||
const pipButton = ElementFromFile(
|
||||
templatePath(__dirname, "picture-in-picture.html")
|
||||
);
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!menu) {
|
||||
menu = getSongMenu();
|
||||
if (!menu) return;
|
||||
}
|
||||
if (menu.contains(pipButton)) return;
|
||||
const menuUrl = document.querySelector(
|
||||
'tp-yt-paper-listbox [tabindex="0"] #navigation-endpoint'
|
||||
)?.href;
|
||||
if (menuUrl && !menuUrl.includes("watch?")) return;
|
||||
|
||||
menu.prepend(pipButton);
|
||||
});
|
||||
|
||||
global.togglePictureInPicture = () => {
|
||||
ipcRenderer.send("picture-in-picture");
|
||||
};
|
||||
|
||||
function observeMenu(options) {
|
||||
document.addEventListener(
|
||||
"apiLoaded",
|
||||
() => {
|
||||
observer.observe(document.querySelector("ytmusic-popup-container"), {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
},
|
||||
{ once: true, passive: true }
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = observeMenu;
|
||||
7
plugins/picture-in-picture/style.css
Normal file
7
plugins/picture-in-picture/style.css
Normal file
@ -0,0 +1,7 @@
|
||||
/* Make entire window draggable */
|
||||
body {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
button {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
51
plugins/picture-in-picture/templates/picture-in-picture.html
Normal file
51
plugins/picture-in-picture/templates/picture-in-picture.html
Normal file
@ -0,0 +1,51 @@
|
||||
<div
|
||||
class="style-scope menu-item ytmusic-menu-popup-renderer"
|
||||
role="option"
|
||||
tabindex="-1"
|
||||
aria-disabled="false"
|
||||
aria-selected="false"
|
||||
onclick="togglePictureInPicture()"
|
||||
>
|
||||
<div
|
||||
id="navigation-endpoint"
|
||||
class="yt-simple-endpoint style-scope ytmusic-menu-navigation-item-renderer"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="icon menu-icon style-scope ytmusic-menu-navigation-item-renderer"
|
||||
>
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
style="enable-background: new 0 0 512 512"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<style type="text/css">
|
||||
.st0 {
|
||||
fill: #aaaaaa;
|
||||
}
|
||||
</style>
|
||||
<g id="XMLID_6_">
|
||||
<path
|
||||
id="XMLID_11_"
|
||||
class="st0"
|
||||
d="M418.5,139.4H232.4v139.8h186.1V139.4z M464.8,46.7H46.3C20.5,46.7,0,68.1,0,93.1v325.9
|
||||
c0,25.8,21.4,46.3,46.3,46.3h419.4c25.8,0,46.3-20.5,46.3-46.3V93.1C512,67.2,490.6,46.7,464.8,46.7z M464.8,418.9H46.3V92.2h419.4
|
||||
v326.8H464.8z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="text style-scope ytmusic-menu-navigation-item-renderer"
|
||||
id="ytmcustom-pip"
|
||||
>
|
||||
Picture in picture
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user