// ==UserScript==
// @name [Chrome] Enable Picture-in-picture (PiP) for Weverse.io
// @namespace Weverse Enhancements
// @match *://weverse.io/*/live/*
// @include *://weverse.io/*/live*
// @include *://weverse.io*
// @grant GM_getValue
// @grant GM_setValue
// @version 4.3
// @author jho / @jhooo_o
// @run-at document-end
// @description Enable Picture-in-picture (PiP) on weverse.io for Chrome browser.
// @license MIT
// @icon https://cdn-v2pstatic.weverse.io/wev_web_fe/assets/1.0.0/icons/logo192.png
// @downloadURL none
// ==/UserScript==
let auto_translate_status = GM_getValue('storage_translator', false);
const pip_btn_icon = `
Toggle Picture-in-picture
`;
const mutation_config = { childList: true, subtree: true };
const is_firefox = /firefox/i.test(navigator.userAgent);
if (is_firefox) {
console.log('██████████ User is using Firefox. PIP button will not be appended.');
} else {
console.log('██████████ User is not using Firefox. PIP button will be added.');
}
function toggle_pip() {
const video_player_wrapper = document.querySelector(".webplayer-internal-source-wrapper");
const video_player = document.querySelector(".webplayer-internal-video");
if (document.pictureInPictureElement) {
document.exitPictureInPicture()
.then(() => console.log("██████████ Exited Picture-in-picture mode"))
.catch(error => console.error("██████████ Error exiting PiP mode:", error));
} else {
video_player.requestPictureInPicture()
.then(() => console.log("██████████ Entered Picture-in-picture mode"))
.catch(error => console.error("██████████ Error entering PiP mode:", error));
}
}
function append_elem(changes, observer) {
// Append Picture-in-picture
const video_player = document.querySelector(".webplayer-internal-video");
if (video_player) {
if (video_player.hasAttribute("disablepictureinpicture")) {
video_player.removeAttribute("disablepictureinpicture");
console.log("██████████ Picture-in-picture is re-enabled.");
}
const locations = document.querySelectorAll(".pzp-pc__bottom-buttons-right, .pzp-mobile-bottom.pzp-mobile__bottom");
if (locations.length > 0 && !is_firefox) {
const pip_btn_exist = Array.from(locations).some(location => location.querySelector(".pzp-button-pip"));
if (!pip_btn_exist) {
const btn = document.createElement("button");
btn.setAttribute("aria-label", "Toggle Picture-in-picture");
const btn_class_names = locations[0].classList.contains("pzp-mobile-bottom")
? ["pzp-button", "pzp-setting-button", "pzp-mobile__setting-button", "pzp-button-pip"]
: ["pzp-button", "pzp-button-pip", "pzp-pc-viewmode-button", "pzp-pc__viewmode-button", "pzp-pc-ui-button"];
btn_class_names.forEach(item => btn.classList.add(item));
btn.innerHTML = pip_btn_icon;
btn.addEventListener("click", () => toggle_pip());
locations[0].insertBefore(btn, locations[0].lastChild);
}
}
}
}
// Observers
const elem_appender_observer = new MutationObserver(append_elem);
elem_appender_observer.observe(document, mutation_config);