// ==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);