11export default {
2- icon : "" ,
2+ icon : '<i class="fa-solid fa-headphones fa-lg"></i>' ,
33 name : {
4- en : "" ,
5- vi : "" ,
4+ en : "Audio output switcher " ,
5+ vi : "Thay đổi đầu ra âm thanh " ,
66 } ,
77 description : {
8- en : "" ,
9- vi : "" ,
8+ en : "Pick a default audio output device, customizable for each browser tab. " ,
9+ vi : "Thay đổi đầu ra âm thanh của trang web đang mở.\nMỗi tab có thể chọn đầu ra khác nhau (tai nghe/loa). " ,
1010 } ,
1111
1212 // Fb Post: https://www.facebook.com/groups/j2team.community/posts/1362716140727169
1313 // Source: https://gist.github.com/monokaijs/44ef4bd0770f83272b83c038a2769c90
1414 onClick : async ( ) => {
15- await navigator . mediaDevices . getUserMedia ( { audio : true , video : true } ) ;
15+ let key = "ufs-audio-output-switcher" ;
16+ let exist = document . querySelector ( "#" + key ) ;
17+ if ( exist ) {
18+ exist . style . display = "" ;
19+ return ;
20+ }
21+
22+ if (
23+ ! confirm (
24+ "Vui lòng cho phép truy cập audio/video để chức năng có thể chạy."
25+ )
26+ )
27+ return ;
28+
29+ function disableBtn ( btn , disable = true ) {
30+ if ( disable ) {
31+ btn . classList . add ( "disabled" ) ;
32+ btn . disabled = true ;
33+ } else {
34+ btn . classList . remove ( "disabled" ) ;
35+ btn . disabled = false ;
36+ }
37+ }
38+
1639 let popupParent = document . createElement ( "div" ) ;
17- /* positioning for the dialog */
18- popupParent . style . width = "320px" ;
19- popupParent . style . height = "120px" ;
20- popupParent . style . position = "fixed" ;
21- popupParent . style . left = "50%" ;
22- popupParent . style . top = "50%" ;
23- popupParent . style . marginLeft = "-160px" ;
24- popupParent . style . marginTop = "-60px" ;
25- /* stylizing the dialog */
26- popupParent . style . backgroundColor = "#fff" ;
27- popupParent . style . border = "1px solid rgba(0, 0, 0, .08)" ;
28- popupParent . style . zIndex = "999999" ;
40+ popupParent . id = key ;
41+ popupParent . className = "ufs-change-audio-output" ;
2942
3043 /* navigation bar */
3144 let navbar = document . createElement ( "div" ) ;
32- navbar . style . width = "100%" ;
33- navbar . style . height = "28px" ;
34- navbar . style . backgroundColor = "rgba(0, 0, 0, .05)" ;
45+ navbar . className = "navbar" ;
3546
3647 let closeButton = document . createElement ( "button" ) ;
48+ closeButton . className = "close-btn" ;
3749 closeButton . innerText = "Close" ;
38- closeButton . style . padding = "6px 8px" ;
39- closeButton . style . backgroundColor = "transparent" ;
40- closeButton . style . color = "black" ;
41- closeButton . style . position = "absolute" ;
42- closeButton . style . right = "0" ;
43- closeButton . style . top = "0" ;
44- closeButton . style . border = "none" ;
45-
46- navbar . appendChild ( closeButton ) ;
47-
4850 closeButton . onclick = function ( e ) {
49- popupParent . parentNode . removeChild ( popupParent ) ;
50- } ;
51- closeButton . onmouseover = function ( e ) {
52- e . target . style . backgroundColor = "#e74c3c" ;
53- e . target . style . color = "white" ;
54- } ;
55- closeButton . onmouseleave = function ( e ) {
56- e . target . style . backgroundColor = "transparent" ;
57- e . target . style . color = "black" ;
51+ popupParent . style . display = "none" ;
5852 } ;
53+ navbar . appendChild ( closeButton ) ;
5954
6055 /* PLEASE DO NOT REMOVE CREDIT LINE */
6156 let popupTitle = document . createElement ( "div" ) ;
57+ popupTitle . className = "title" ;
6258 popupTitle . innerHTML =
6359 "SoundSwitcher - by <a href='https://north.studio' target='_blank'>NorthStudio</a>" ;
64- popupTitle . style . fontSize = "12px" ;
65- popupTitle . style . position = "absolute" ;
66- popupTitle . style . left = "6px" ;
67- popupTitle . style . top = "8px" ;
6860 navbar . appendChild ( popupTitle ) ;
6961
7062 let titleLink = popupTitle . querySelector ( "a" ) ;
71- titleLink . style . fontWeight = "500" ;
72- titleLink . style . textDecoration = "none" ;
63+ titleLink . className = "title-link" ;
7364
7465 let popupContent = document . createElement ( "div" ) ;
75- popupContent . style . height = "92px" ;
76- popupContent . style . display = "relative" ;
77- popupContent . style . width = "100%" ;
66+ popupContent . className = "popup-content" ;
7867
7968 let bottomArea = document . createElement ( "div" ) ;
80- bottomArea . style . position = "absolute" ;
81- bottomArea . style . left = "10px" ;
82- bottomArea . style . right = "10px" ;
83- bottomArea . style . bottom = "10px" ;
69+ bottomArea . className = "bottom-area" ;
8470
8571 let submitButton = document . createElement ( "button" ) ;
86- submitButton . style . backgroundColor = "#3498db" ;
87- submitButton . style . color = "#FFF" ;
88- submitButton . style . width = "100%" ;
89- submitButton . style . padding = "6px" ;
90- submitButton . style . border = "none" ;
91- submitButton . style . borderRadius = "3px" ;
92- submitButton . innerText = "Set Device" ;
93-
94- submitButton . onclick = function ( e ) {
95- document . querySelectorAll ( "audio,video" ) . forEach ( ( el ) => {
96- el . setSinkId ( deviceSelector . value ) ;
97- } ) ;
72+ submitButton . className = "submit-btn" ;
73+ submitButton . innerText = "Waiting for permission..." ;
74+ disableBtn ( submitButton ) ;
75+
76+ submitButton . onclick = async function ( e ) {
77+ if ( submitButton . disabled ) return ;
78+
79+ submitButton . innerText = "Setting..." ;
80+ disableBtn ( submitButton ) ;
81+ for ( let el of Array . from ( document . querySelectorAll ( "audio,video" ) ) ) {
82+ await el . setSinkId ( deviceSelector . value ) ;
83+ }
84+ submitButton . innerText = "Set Device" ;
85+ disableBtn ( submitButton , false ) ;
9886 } ;
9987
10088 bottomArea . appendChild ( submitButton ) ;
10189
10290 let deviceSelector = document . createElement ( "select" ) ;
91+ deviceSelector . className = "device-selector" ;
92+
93+ popupContent . appendChild ( bottomArea ) ;
94+ popupParent . appendChild ( navbar ) ;
95+ popupParent . appendChild ( popupContent ) ;
96+ document . body . appendChild ( popupParent ) ;
97+ UsefulScriptGlobalPageContext . DOM . injectCssFile (
98+ await UsefulScriptGlobalPageContext . Extension . getURL (
99+ "scripts/changeAudioOutput.css"
100+ )
101+ ) ;
102+
103+ // ====================== Main ======================
104+ await navigator . mediaDevices . getUserMedia ( { audio : true , video : true } ) ;
105+ submitButton . innerText = "Set Device" ;
106+ disableBtn ( submitButton , false ) ;
107+
103108 navigator . mediaDevices . enumerateDevices ( ) . then ( ( devices ) => {
104109 devices = devices . filter ( ( x ) => x . kind === "audiooutput" ) ;
105110 devices . forEach ( ( device ) => {
@@ -110,15 +115,5 @@ export default {
110115 } ) ;
111116 popupContent . appendChild ( deviceSelector ) ;
112117 } ) ;
113-
114- deviceSelector . style . margin = "10px" ;
115- deviceSelector . style . padding = "5px" ;
116- deviceSelector . style . width = "calc(100% - 20px)" ;
117-
118- popupContent . appendChild ( bottomArea ) ;
119-
120- popupParent . appendChild ( navbar ) ;
121- popupParent . appendChild ( popupContent ) ;
122- document . body . appendChild ( popupParent ) ;
123118 } ,
124119} ;
0 commit comments