From 0605d614b9a0d47f0b4d37a733da2f56232d5a96 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Thu, 3 Nov 2022 23:59:25 +1100 Subject: [PATCH 01/17] =?UTF-8?q?=F0=9F=9A=91=20ItemID=20to=20not=20Overwr?= =?UTF-8?q?ite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/main.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/js/main.js b/js/main.js index 3d33cea..b7e558b 100644 --- a/js/main.js +++ b/js/main.js @@ -34,13 +34,12 @@ async function addPage() { iconUrl: pageIcon, webviewUrl: tab.url, }); - - //save to storage - saveToStorage({ - title: tab.title, - iconUrl: pageIcon, - webviewUrl: tab.url, - }); + }); + //save to storage + saveToStorage({ + title: tab.title, + iconUrl: pageIcon, + webviewUrl: tab.url, }); } }); @@ -56,6 +55,13 @@ async function addPage() { iconUrl: pageIcon, webviewUrl: pageURL, }); + + //save to storage + saveToStorage({ + title: tab.title, + iconUrl: pageIcon, + webviewUrl: pageURL, + }); } } @@ -66,7 +72,12 @@ async function saveToStorage({title: title, iconUrl: iconUrl, webviewUrl: webvie if (sidebaritems.sidebaritems == undefined) { sidebaritems.sidebaritems = []; } + + //get size of sidebaritems + let size = sidebaritems.sidebaritems.length; + sidebaritems.sidebaritems.push({ + id: size-1, title: title, iconUrl: iconUrl, webviewUrl: webviewUrl, From d3ae31d38ee002cc458a75006c795efcd090239b Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:20:26 +1100 Subject: [PATCH 02/17] =?UTF-8?q?=F0=9F=92=84=20Firefox=20Style=20and=20Da?= =?UTF-8?q?rk=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- styles/main.css | 69 +++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/styles/main.css b/styles/main.css index 0354852..3792bd4 100644 --- a/styles/main.css +++ b/styles/main.css @@ -1,45 +1,42 @@ /* This was stolen from firefox and is under MPL 2.0" */ +button { + height: 32px; + border-radius: 2px; + padding-inline: 8px; + font-size: 13px; + font-weight: 132px; + width: auto; + background-color: #0060df; + color: #fff; + border: none; -#instructions { - text-align: center; - font-size: 12px; - padding: 0 11px; - max-width: 15em; - margin: 0 auto; -} - -#url { - display: block; - padding: 4px; - font-size: 14px; - width: calc(100% - 22px); - max-width: 195px; - border: 1px solid #ccc; - resize: none; - margin: 0 auto; } -/* id addPageButton with color of #0060df and font-size of 1.5em */ -#addPageButton { - display: block; - background-color: #0060df; - color: white; - border: 0; +input { + height: 32px; border-radius: 2px; - margin: 15px auto; - padding: 8px; - text-shadow: none; - width: calc(100% - 22px); - max-width: 200px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; + padding-inline: 8px; + font-size: 13px; + font-weight: 132px; + width: auto; + background-color: #fff; + color: #000; + border: none; } -/* addPageButton hover */ -#addPageButton:hover { - background-color: #003eaa; + +/* if prefers-color-scheme theme body have dark background white text */ +@media (prefers-color-scheme: dark) { + body { + background-color: #2a2a2e; + color: #fff; + padding: 16px; + } } -#addPageButton:hover:active { - background-color: #002275; +/* if prefers-color-scheme light */ +@media (prefers-color-scheme: light) { + body { + background-color: #fff; + color: #2a2a2e; + } } \ No newline at end of file From 2c893e7aaa0043d4dae3dd6ad443fc0189ebcfd1 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:58:53 +1100 Subject: [PATCH 03/17] =?UTF-8?q?=F0=9F=8D=B1=20Sidebar=20Icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/in-content-icon.png | Bin 0 -> 14600 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/in-content-icon.png diff --git a/images/in-content-icon.png b/images/in-content-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..efddee99ccf3e13fc1d70fef460d7c270218d6b9 GIT binary patch literal 14600 zcmch8^;4Wpu=N5P+}(n^OK^8KxF2tb!rsfIPR9C`6Cr1YW09YVpd2IjyQ5XO~Fh)g&|I>Zf#S8!l zkAmc7biGWD+7QqH08B)lRp^x^YE1z)e8m6VXN@n`_SDz1_U{PNvyX{o{gZ1%S}5W7 zbZhHCVgWtILQT};Z-kEDtn()larACkOAO;Z(vlPXKm~6Hi{3{6v?hD2BIz*@R;pJM zj!9IPPhKJ?pRd2DEx`H}krNF>t_ntd@y%)xjHiArAt{-38)UlZ4Z**AmF4dLbF^_+ z{PwAFSGW^n)b&A~bP=-#`O}XMz!=T~N>DCpk``vlQ$1q*J$h=sfpomTMr;9I*M!hz z(~~unhNr+(3)rr8WAw~^Z4~}#m^;Cf&+`u-zbR7&x0FJh>OI-yy$s)VQO@c%_v5R; zAgT3*2S1qoNxkkh>_eGUka564R0pdJHrmr$dx=Vp<@!J$NwX6?`2Ye+>)SR3tF#Wm zG1?G?yAzIC-ux|5%Ev@BdGU9DV_>bk`A7A-*8Z6f&s()${Hra;9w4R=Z>TqUViw{X zc4)DbmcLES)6?`w&=JwqDslbG(g3U|`7=;rh&_m)x!F$4^!ZWcj9%dsVFu8WABct6 z&kO)TchYcF68c?O-CifqNJ{aQn(HXf4CPoYr0^+qnOD;zJ1l>DAUuaz99sYTBmCHy-d@~{qL zM^Yc?hYw?$oDX_uZaECRERt8LNo{uD{#C(6PzQg_TDn2l#n#t7^qo|6tuXrjCdow+ zm*G-1U(kEA*)0Te4dH>lI6)k7`5~Icr(vlOhX=;ZSu3(i`lgvqFvI|2HNd@@b@k?# z)I`;@a_0j*e9Ea(snm0wNsV^y*R#~^d)d#b4}Z*I<8ap~rm~jkK1Ey?85V)h6fzs4 zPjI^k_0B|nT16GF{S>4QP||gP>Uw7!d#%J6F@K8HuWI+Y_ylA5aL|Hi?uayQvTU5Z zyXVjqkbfMg%ha)nN+X20W7zq9lvuqpu!*5TOkbNldM>4t$`(g?`Gi6BNEmsGk;Z*a z%Y+&v?G0&HX|5~DeJIQ|^;{f>QB^~i`e6KcTR^-uppw^3ol2jEj8y6(Iolb3Ad11c zZKrS$4Qh~iYdu0wYu;YZ(xW#}WHxtKqqS|;bYlS@t^)#xB4BcG7?V{V9Lx;q;k4B*grPNzTvD6emzyv@U zT&J}_C6ciP#3+EXnADzI!577Qa~y*#_=?P)B!tipJV@aduunFCf49s_OVw{{cP0UDSeERLjrU!HEDtiXOr$M% zKv6jFTV3gxQDV(5^+yoLEZgZ+fP3((O^)s&?~9|`UGI>H@9ILAsf4O~5Gpt*?}%D> zbU#lT$}N3APhEX|BWvc)e@0l9i6aE}93`OgTOZ!V8RE+Y;+~>^Jelo7Tv{si7+Dv2 zdO&1zJy!lIbv{av>6qmopP!Oi5^Tz#=mlglbgs4!*xciq> zqv>|(Zq0@o49kZ{jHZEVE(s_Cv7H8EWZE1AE7y-l{i6mvhvtxXNGXg3^`cK|OCf*B z_&0d(6-0bo-==tt*S{w{m*>q84#|Xw3{bdTM18fSk8VP4+m5!VC)Si^RHr*G4gLga zzjp*C#r+V(E~Df1K}jUrN@D`kKMq-@!S?GlbD9!r3!a=yt`p(LQD;n@`6V_#mbE#@ z6O>9L6bnv%g}Wj>V>XA1UGBH#os0+vM5b}LZ0rT7roVxj-AA5^3uo3I8>W~@`po&0 z%F{cw5C1qdowTSvifGvT6xTzu$0o}B4Zy5Ps;uNfC}XFU(T93cs0ufv=`3bH?k)?s z_9;Q$OaC`hP8JX$J4>MvU`t^A&y3q*KR#C`0HAhTEi08l0G|r=YTg!sP~m;g&Ulm= z0MhHlO`c3=7i*{{rf=Xf2dU*>jDU605V#MivQMbu}Hw| zQiiCKEW_3878>_K$=m;Q(OBG*Sn~@CNv+o&^3Rpe1b&W>yMJDu*iT&@X7LnnTSeBX zDOwVNg#oXM>@CqyS)ZGJni@Z2zJg}kB|RbXs60^(MdgNb8$oXV?4ih@KW8#x>`@%; z{>>p;0+I%ji6-ZZV~N{B%CZumnG%EwMsu#8CK<_qb( z_t((NkZ+xcoQKFl_2{qGr1CPgC#vWF z>btL*4mOJKedCh=tb)GY(PKxbd3E;|f@^mmbnxhxvVFXxdT?5EoMm$sxA?tPe+kMT z@VmVeyjdoee|1sx030!w|3{E*9CMx@R<`7^bYs-7OI;>4E0g8HRs@1lKU_GM4y z$Cq)=NAKNpQ;oaHI6)91!BG>og4Ub<<0h9!3aL7Cd%s@et4&zA5_sxj^GR`@dxU%P zVft}duX3qU=iwS1)=Js(0nb2N-(N%WS;b`Wg5XM)=+^zAoOKZ+c0TQ(FpT=R&@}H zD?W9pb73Tsx(drUUz~Mn(_B6Ex4BeNlOlskh~M$jIXr$`ddqJz7A18o-a@^yaIYfi zWzBH1>g;-*M1%sTAf%zWDeC9}OV>(Y%x;0qFgQSe(>r#==ui1a<<4I#cH2DpwK24m8oswWKFfybUTt2cly7|&$lfBk z%$py%zFJxBfh}_Gz@~J8!ZIA(I~&!vmjpJ&kNLXqR%$QX`~~@^<1QU-xt+@2~=mDMQ?XC3 zdARY{7*_I$L!zzY@1CAInO_|N~V11TqDcwkyP zb^mq;wJSJ}*KTF$CLlxWGd@4xO+&8+WA_^Hr{2_4%(6x=mOwl5O~uYsUPGHI?yU`_ zUO|bURvaLF5cio|l>;HUk5V?DA;U>ouf*R&y&sTCdSPO}s18#9Ww3?{xjkZ)(4PqT zuOp36Ho`u=dbczpHVcEvWqmU89X?bP=8Np^_BcWec)0DmdoA={DjN2TewUhbyK8@P z8yP5eZd>Q&IOCEJ89G%;AIQkP9}il6ex4f}fKxg&3)%TCyjS|3!nH??bPGfHeQ`=j zE2KUiRB+tvzUp6lE7x;MQn=wM5$CNF{a7w)@EWRq$b8;pkH1^ArEw_+-Gc2@o!(t@ zDYxSUtv^-J|5##C(XMPZt-0ow!rz7|_H%PKthWldzIZ16f^q$qwc905J;TFm&5`R~ za+(@3+_wq5B_~G2dSSWh=J|+F6yF-z?sbN3`EjRar6T5^**JEeLDY(n&>^=L zQbHLzr^6Mgw`twlBlys%TjrJYtf^S_edbM)wZCHeJa>H$@Yxh0vsU!~>NSFu=P}D3 zf%8IbT&&a?Yd+)saZmY-SE}d2Vvfd6wCRK4$Ctu7eeeH!#Rt$cV3 zrac+!*Xws}&`19s`o3AFA}%WxqAfMi#!UuIg!RcU|2+@Z$Q zSCj1WkRfkhoiqE}DpLCz(%-s?srgDqk1uhDJQ=D6-`YYTV?!DONwCm+pPyF~LUW_N zq54skjn(!g@U?zPz4O1+IH0yzi+uX?B<1rN%-)L?jF61!Hr&q%1e37R7UYwC-XPXi z2>AV72i=Sdrz0vv0*g~L^3+ItbS3)rQ!Wc{rgR$~_{QL9_YUUKhLFv<_C#jt09CD} z0#Z6@xgM?;2lDFzj*4!`Y1Y15A_*bP)!V(`+=)PZ^|5p|$pLdG-yM8#@`B_P{rE8+ z005Ir!=b&P081Z-5@CdZSpy=PwXrv~qFlX@Q9!oIl3g?vQRj6)8d( zEcGt%2NGaWIF@QIm#+TTkp_UKUaX7#Av?%2!GUH8aOQAzj8wb^rWlkOGsA3a?JM&F z5>fJ92=Y{KZ~)veM98o-+p8r6$UXv!k9`P$l)u8#?_CkVuYb>f$`eP#HkyU>hyZk_ z9EkfuxhSvJ#yr0qtU_PHsd1oB5B7I2SWhROO~yHeFmZM^;SM#dB`Zv6#gErlg2iig z9|seZx)J6coNI(uXx2!lap|Wi04MH%Up@)w2)#J$Qj$6VQrF*Et`nV_vUN1MZF1X-6FH^uuKdNvH z3wEM1Lh&L)sf`^U6UvDhfM%9I?-e5UpP=D)kraRyonrXlLk-91MRD{t)iymjmk=t- z31A`uU^cMVHKnn}@ z0}l1~xWa5qL|yR4OyngdB6fXfT?8KB3;6G8hfG_w%#R+yA*8SA*DcnK;Q@JX3>_Uy zV?rqbd>3Na5{e1cJ9Q;qNNW;HI7F0guxLsG6wUVcY^gMBnunG8V`K3 zxm@iwd$zB#gK9^#^$uNefRqGI2Gk?=04v=`5w@!}JFZr7{t*Nkm$0s1oJ%xoJo=3Y zW~WX4dw~IYD7MZ0q|#VLxhu~7B`7F*lz>gQnOY(?;UKl1_kg47!VNSaWnJM0JQi%i zE;Vz6;402nZI1>n@I4R}z-2Yc6ID2021WpwPJ1>2^;%x4;Jw&HJt)!C~rN6hDUpFjrqBdI;yE zjn;Gl3iBo|!1;7_@4XE?3Wp+w#IL|IN}J~JAXGt=MZnUO0nNITt8O{0Yi3qR0kT7aHXbPY)f?UR?0II2$KTDF9hxt~v%hU|#Z40HW!-G5I!g zioq;be899n3AT+^oEBa!J2Ie?+<8%#3@0Z@t{j>Y`TYM=%o7zs_kC;&KSIqfw#&Ph zrTUvg$Z|%@qz|#|n?MAF_ep)k9eq0|-(o`cF!^|}WyaYC$y!DyxSA*V4oQRZMJ-WBP z-1=e5F_6hMm!m~5m)jXOn%y|klKU8rk7df|3t$s_YFd617_Lw&bM-8@7_N0B@!@GA zvCvrKK}8MHME=NEg8{@SC}w$KKmI5qoyz++8(~}oVN-a_Tpd-N;VYO9y_F?!Ll?Vo z{Eb(5UaC25=v*$aqo0)2(k5D&5S&XZpK9@~k?Vrs{Z=o3;%mk}W2ZMJ+sWL(f@0K% zmyk9MZv5Ar-#As1H+tkz1C`w=!z=W^ZkX$`ZmihO(#%*yP!Q}0Tg2MjzCC*1B8yw& z{8qdT7XU<~lyyBuiOZ#Pot*d8mF-3ov$Jy{W~S5&ZLoDcHQ(L)s-?vLu1`inPO};X zVR9bANQMl<1o z^}7G>%{FdgF8cGE3>qA44_>BVSHKDZtutL|L&_IBsTZ@OeRd+oC17Uvoj4>VZ#Cib@27b$r&}Y5}=mkdvzjq>QjJs7>5%2RI0Q<>|S>JEh zn4{V0)xg(WbB2WkWt@UOi015A10|L3B6g6r?$ls%i$@yoI*+3RtH&$=x$+4MU3O`x zJxYRmm=J7ssiM3r1mqr{LDogtX^B~`NAVGKA#t<}82^%q(1)eI`GcLhXRoE{_a{9d z)<@739?<+5gVtc{i8fGe+M3}DoI^E_W5|D7yqma=e8MB2~| z@0IDzntfTu_lM}A^6{s{Z9cg6EzUzK{ry8BX zcI2e?F*%YneJK6?!330Wvo>nklvH#pGYr0TCN-lP*)Q?OVA}}d$!tPVF5^Z14fek^ zcvPj?zpA}stA7lC2YdVoU9()Hs#mvhK^GHTiJg!)@f&4~Mio-jyu_Vy5YXgifFmq? zkw77vY)Y@j>(zg(oa4XgnW!Cd0U?(vO{Qa*eq(n3=X}#}y_@rIvD1)`DrJ3N+Bco3 z9vk*A?)aluF~M`L`@vv-#)3(A-;^uSX>wqDG<&Etjq;jio|KJ=3aWQJ%}}MuMWsgG zOVCG_m~EQxl1!WFJrGXm{CYe!ik}@StUA)xmMfNnp`LH91S5a66N;wB#j~4kf3kO2 z#5IAPbxMaHV&N*VLXKr{3#-!??`Ea^K?8#(> z%IaavX(sR|YEG09OZ#w==6=I{e8ViCI$hL{RS6UT{{jvV&#;qmC|SqZ*y!iYYe%Zt zCrOJ$1+0;BI#kxX0&W+oe_@=YFqf4lVT`iz>~80H7+nnA&{Uk4v-!Nna-p;avgCXY z6HsGOgzs_oDGE2Ry&pU+)%wa4S zLHtSsR}O!O>^HvcWc^ZO^8TEcr;moy1Sqw{zHZ8-pA0Jxx-S+rbXTQJ<<0pb+00K& zx+Q$xpI_HjU6oq?n3UPs6shux2g2$l!U7jfd3N>x2+fWyu?3k8u!_nB{PVnGULsuC z(KwOShc%k`>n_vnBWp{onm5TGu2%dCJtYQid!^ZoQ~ggkpGEi{i!`mj`Rs5R{9Z~G z8}02-`Eos#F)^MZ*Q;uA{QOkOdy!zU#z=@Un3J!EBLfCA{-D5xM<7Th5Vyr(Ba&jh zJA=bwE%&(Zrr^qNvLJ?)@Xxm%e&RgaK{DyNODf}U6ypq41Gu*wCmHT!xHj*awk;S& z?U2MQkQk9BJqNeBOdh8!Ntgdpm~>#_X?@Vs!Tl6UwNM2FsjTl2zGT=8!Qb$cDix&lCt#MvcbOc@z?;W=&H_))AR z8~)91YnMo<&mFV%lq}!h1NS>Ky1yF^LWMYKz}W<;zBq)d`Dn?IF4S6A2tt zd|}|Eq*Joj6m?GMH=c5~jlw?OtGHcW*xonTkW2(g%lnLKsJc6lol1gad|J&g+ynXk z9Md7HQ6T(}cX*|9J3MRW4E@|Va3;ssHtC0rVrh&bfFpR$>8?b88U4{ zXyDXS-kUlGCTfa1MNp8CK6kmq{qm7HuO~|5L9=vIUCB*?!XZhkZcy&HA6B0^inAS?s?jlCPsFe!kO) zhBr9pwp+(9r~JqnKe1kW^)8cG?xJ)FBX=iQHcFO((|ygQOj<7x($D%(+H%$3Z+!!u z?&lCL8RO}p%1HUI7WN0gNzd0Xt#V>8B=Gh(b4bHEpIhf(^4+*3_>qtiVe+WPt&K^? zWZ9z^WY?PeS}+}*RAfzF_RhU(FGBB~d+)s$Ob4oI`#Ic^WN5)Fp2EWS$p6-2SI?;W z`D75FG*X`W=%a>H*hLyX5JodZU>0LW!=j+TEEG|ce`Ah^f|a`sMdC(rfxOyWT|wI0 zXJK_JqvuayjIMc_*&P3JjXp=aP+=1Gqdv3z=e)}K#^kgf(K@}6N%x`uErz?Zo>I-l zu0Gz^eHn~wDKdE49~(};9yg1S$>*h1TZ&q_5LJZUpx8gujvToayw()a(|q52|Bj>8 zoAZhGud^gsMw*5wVlTq%@Y&nZ?}4W+-rC#PJ5z~iYJHu zcsYmP`YU12D%p{Kw&qL`8tV}ZaEEq!HzFSY*0Q}dsHgq=CUE3%C4?`>4i)R8S|6rH z4k9foY*j~79|11lb(r0{2aVgiZ)7m-!a7XLtxLbmWn4+z$FB^XM-D<=J17&|!Z7d0 zKdhKhUMI}DTbD{?+!e!Km)s{25 zyYWJ9H;PXBVGNm8G8CUYp@tNJcAhvJ5$~Hhhj&a3UAo*~yegL$?EUITF-lZ5QjlT@orM}}i0M9sf) zdZgf2Zk)9dc^-ayevw==l-X6&JLq^R8CY$4tT3uplpDqK(?AfIu?Cz4|M*8aQI!Kc z=i9IEMs1JIm+Ea}&~C$%OzXTR?FOg4HZi|Cj^A7ldQFm8Wgg9~s`Wf($-2%3Htu?o zS(ygnODuox<4HCk0D99S1;fkoz3KjTv7T3dNYdPcP5C%wTe&3e$*B@=cf0`ATL+MY zR&}qtiulv!wwyfQ%cGD=({Yi)j_8qN!ubsWm0TTo(T_AwsFBR&Ls~vhia?K|E)&rF z%NSzdzlzVPr`^=hh~M0$@xjb@iLX28SLc@FkJENSvDWi3_CGOvneziv!(L?O(P08q zJMN+1d0O7wIB+_5@%x0At==d3MtdeLX z!yVZQ#*`i02r$3c90~XBD#z6PBE{uHI9Gu%ssnaN& z+ki~GT}JqDLzeF2c>*j1Iwn7bZ#DR+ouK}aLlXYaP{X-0&x+Cew zRZ*&{BHe-6x(wc~$fz(f7m4sdE|V^#8LyMgG!bL*S`{=#D#`P+NRqS8`v9l&8zRzk zx9LLWfvEZ-qRw#CFH-*G&50AnDr>g8sdVz{UrJXD8$z<23Fa&I8)2~TEX z3$5;m*v7ZZA^7 zOYg{YoJm+FSFa#r$p$>*Y^XzdLdO9 z!L#B>4OP;VcUsh*e&?*LRmaxHZliv~6VkWW%$CRX+=!%!Q@S^8y3@Lvcvf6CGWxan ziMezQHj?EyOR{JwIiNS6ez&2CX>S=%VhCe)W9$I<6m@HOU^DvKH-k$bUuQo_WgGKmI z3N;6awbXF8+R;`*{%yi!&qYN$;|eiA zapBV{N2}ytgYhVN{zfytI*OMT;NUUf;pB>lr?#XD^}-e7@&`Cq*tsvTEPopM!Z*n{ z<1=ahhtV084+E$TQh>L2i36-3uPk0iq$kq48A^>u$GnJli}rpCejLdU^4t=K%u*da zdVTmtsTE57@nb;J5Cy^Aa`$a^@&MVRZDB_8NeyrQ=hNZZjh(tnjtwR~y^Tfz zy(}E88_1N8OhkHn;<}1`V<|<(i$^K0NU9evR<%RNKm*m|KGhLy&NJH%Po$sJ0e*af zS*?KP)sHi}_L*cQ_$kdE^=a4lwdaGEh;w(6dM|H%D~hM9j{LPW?hW=k1ZlYQ$pzz( zmX62`hF(Gu>SNj65AJlm-t0QnLdBv<)Yw{g3%cf zRnOY8M6u1=lg<+y2{ghtag#rRl%Wnm3Y2d+G}tymNklv$V0NZVsvzv!^6lDDK2wiD zk$2vM^8&2Ss2xYm-Ms&G(fmxt{C9G6Mfb3bz2|u{GrWR_p(}xTTSHcYPUe%--U^X8 zdQ)`fEt&;#B>~#5=uX0xiv?!t?i?jgcAq?T8zBi*{A*07>!Xt4fy(rfa0-%rLp&j1 z&aht^2|SH=aJbv>(8Te>V`t!*Z9DiLepn{g=4Bm=#y`QAfOEAuhVu;I9{(v^8ltR1 znPW$4;<**6yMy$*^dKWSICos>%~5gT(7-z5 zS=nS?c!=njE5p+V7suU4Q_Qqb@V!NmR31INhkt?u57J z)4Ihc)#cr`)~c7Mv`IdFIS=%=jze#<*Miti$Zo^}Kr_PX{9Px5CZ^|agfL1HW z$}`+e_x7q`zh$1uSzCbVAM&z2xTtWmrFo+G%3EMsx3_=$?gu@uR{RBJtG_4m7vA>l z?RNa0wR-4T4++U|C{E|=;jy|=XZcn4M*0d*$|6ku^TtWq3RY7CYfc>vDzdZJ-G9Yc zKvxMnJUt3mM8ON>Y#6hGGKvr>R@FIFi*c+Gvi_S~>;8vs56y7OYZRQt#U2w68x!is zQvkmTxEv zO~_@w?9!SyI~&%ca@u<4`dqT23Ml;k6KNAcCt#3;`$jGO)u%824yL2rK2S*q(q(L^ z(zX6Zi?hOX3DK@&>B8bZFRjIaw-mJF^SM_i;U3J@J4U>6N(K6yZIH=fGN`)cs;#w(RbkdG;$nsH`yTPLlUBgN8^UYVA%>w30RAol+ zM<=K>e+ss%zhZ!II;*4~*KoV{oA2B#%)b)g@m5BJQ1URn9SUJ#Da7b-*V$Ii;o}MX z?_58b2k)`{1Ic|j$HgYug%18!N8Haqz+o{w7FJw8p*lfqc3ozDz7_9;S^{faMgpR( zah)S%QJcQudg5L*_H`#mYX1#@H)Y`am)g%loSxQtlwtmd`g#@6sR4LOb;9Gn zWxk=-eHt^v`D@=VZ=`g<@>>`@g}h*8Atw|etZBa|7$ZLxFy>-bQcgQDj;WU4E@O#k zq0G?URnhvnzuhN$q@}ks|71jDzjW2T(c=&!z5AuCDRYtFyq>zV0F%%tMi8&-u@f)f8cWHm5Ah6)i7kq?p`mvyyD7_;47I*hW=mf0||>=A0wES;~8FQ z32yaa$JDIO6f=~#eozlIgd0fhRe1%%VdyU?xoB79(qh&Ba5F;!a8RmQp6h~xO5A80^aT8!_V z#vd{X~fClvT##(BGFCXfLG zNapA20WDGtBGbqy=3iRS+xY1q3#+#C_K5I5YjA5Sy2F_ds#_m7BEqu?UL#Y2w0&Nf zSmZsy#+e7P4EL$;UuIV6tWbKtCjhlxCa^%-@zFZlgYgKxVUGM9TA+B8@_~Rnn_Z^; z6b5fSx&Fx5ZOoXUY>jv;7#7RttcIgC7SIC|C?mQ!j0UZ zh@bO)Dg6O?>B3y%`$o&D!UG~U=T8EG`4nJY;QjAf-z845#jsQiTnl*wf3i4BKr+68M0`Z|F@=~X<3NF*HKcqegf z&}TTA{z!;}(Bt@pTScU`(M0J%Y}B?^C`t%AMqLRN%JD(j;$&cXSxe+1pZKk0X-*cn zLU57?sEXi1FkJH8=a5CFOezj|E`>J=Tg1c^f9g;5>pFi`EMo0&j0DTXrh@t;s zvEizLg$&#b63+?4pkU}{TWYSzAteJZWs|mefEhptR{it_)@@qx(IU^1%JCk;1FLe3 z8hrW_NFeRQ*Sh_xa84nP->Lm&22st$B{C)zzqw=;=0z2h0!((wXUX8+rl$bwWy?uvC6TBf(#hqVw~8rpBGI zc7K2L=HSva;nMUKlhoolj`I`2oQSvXoj69;GpgykLIoQL!0Yv#8U<*=dQDpXDVmu3 zd@2|X>fDnC+*noNSo!?jWy#DEPP^01zGw!M_buW?z#p_O)CI3MQEqt6LO}8PL~GTe zOTR%Ic8DPL5t&wPnkBf%M1;HF#Yp{NpqA+E4|e>TzKR$YFgV2kN(z+QB%eR9R;Mg; zaMBDvuZN6NrdxROt=Yvi>c|-9b$?%<1RQ=%M`|Nu0NDm0MS~|T`u6rkC&n6hm@AGg z)(Nfq$S7ecyIGX&=U;@T-@ydWuVc^Q?_}^{dBsHrXkW14;6?xU-=)Tsf~?a#;6c$2@mknyTH=62x0c8;7*FqufoH zHhhfFHxPNwAyO;~EZC{h)kZ@$6&tFi*7|w0W+x?nQiA|?^#nb)oJsK=X_4R$wmbcMmFMRSxhyK?(YNvRRu!)$c|1K z+(5(~+*`Hkk~%?!95eC0cfN@+zAV(;>ze_-EK)NXcgxqm6z-57dcXXyuf9P0WKI|&r--+fWG4q*KMOFDk4wcd`A z0i>*grLFmhIat}7Y?_CWm8I=_!Ld~f^fi^rR67?aPO^r{Db7ei&p#@|=C~_Oqhp@l z_JW_v{1FYd@2dS1vu0x%H>tNNs*vV(HuTOIeT+&Knt~@yXrVz$qk$NfNKAl2V~YL= z1#S9-ASO`eB>`9Z503kq8l1bDIs)>=FTR_1FH`!GWcI4%2&>cySR=O41G4e5LqcIV zMf=i#t1e2YJ6WqCvJrQrnUxRwiS#>%0#Vnu_Y$z+eE&C2 z4psdM#^l_Pu1fg2U#AnRP-UGtT%+6wqE{g#F1`|OIc@cC=DNgBwxs`%Q+Vf!_)Xu1 zZy{imIQU%6=kPiqJmt&}W&tV7x*0uCV%ryiNZf4OUemAM;-LA*W?kakzkm4-O@F9X z3Y9VnY~gH6>!!9{X`B4;dxA-r6Wi3cd#1!Cc^Pp)4UmLoEsmm(c(G62)9Msb|L^5Rkb=5= Jg{)c7{{Utz34s6r literal 0 HcmV?d00001 From 66e2c3b241114da2f34cd42cc4f2b618745e74fb Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:59:12 +1100 Subject: [PATCH 04/17] Add Image --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 2f3d5a6..0a3cbec 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ +

Add websites/items to your sidebar for ease of access.

From 1879ee5883325a3a319610562cf4f1f9e95d6c0d Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:59:57 +1100 Subject: [PATCH 05/17] =?UTF-8?q?=F0=9F=92=84=20Styling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- styles/main.css | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/styles/main.css b/styles/main.css index 3792bd4..5f48e1d 100644 --- a/styles/main.css +++ b/styles/main.css @@ -5,10 +5,10 @@ button { padding-inline: 8px; font-size: 13px; font-weight: 132px; - width: auto; background-color: #0060df; color: #fff; border: none; + width: 217px; } @@ -18,18 +18,29 @@ input { padding-inline: 8px; font-size: 13px; font-weight: 132px; - width: auto; background-color: #fff; color: #000; border: none; + width: 200px; } +#instructions{ + font-size: 14px; + font-weight: 132px; + width: 200px; +} + + /* if prefers-color-scheme theme body have dark background white text */ @media (prefers-color-scheme: dark) { body { - background-color: #2a2a2e; - color: #fff; - padding: 16px; + background-color: #2a2a2e; + color: #fff; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 8px; } } @@ -38,5 +49,10 @@ input { body { background-color: #fff; color: #2a2a2e; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 8px; } } \ No newline at end of file From cbe56d1fa2d7e5f3c16ab1767e3ff2f8e32c9761 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 4 Nov 2022 01:08:48 +1100 Subject: [PATCH 06/17] =?UTF-8?q?=F0=9F=92=AC=20README=20Sidebar=20View=20?= =?UTF-8?q?Icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0e04a2a..78d5380 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # sidebar-tabs An add-on for Pulse Browser that lets you save pages directly to your sidebar. This add-on was developed solely for Pulse Browser and makes use of its specific APIs. + +#### Sidebar View Icon +Sidebar View Icon from Side-View [\[MPL-2.0\]](https://github.com/mozilla/side-view/blob/master/LICENSE) - Available at https://github.com/mozilla/side-view/blob/master/addon/images/in-content-icon.png From 2b0b2217847d0c933f42d6ea7c3644ae481a8b83 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 11 Nov 2022 18:39:16 +1100 Subject: [PATCH 07/17] =?UTF-8?q?=F0=9F=92=84=20Button=20Hover?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- styles/main.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/styles/main.css b/styles/main.css index 5f48e1d..f909e08 100644 --- a/styles/main.css +++ b/styles/main.css @@ -9,7 +9,10 @@ button { color: #fff; border: none; width: 217px; +} +button:hover { + background-color: #0047b3; } input { From 6bee1f007f075ddc464d7d244b21bddc4b539095 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 18 Nov 2022 10:11:47 +1100 Subject: [PATCH 08/17] =?UTF-8?q?=F0=9F=9A=A7=20=F0=9F=92=84=20Cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- styles/main.css | 65 +++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/styles/main.css b/styles/main.css index f909e08..68cd287 100644 --- a/styles/main.css +++ b/styles/main.css @@ -1,4 +1,29 @@ /* This was stolen from firefox and is under MPL 2.0" */ +body { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + font-size: 13px; + gap: 12px; +} + +/* +@media (prefers-color-scheme: dark) { + body { + background-color: #2a2a2e; + color: #cccccc; + } +} + +@media (prefers-color-scheme: light) { + body { + background-color: #fff; + color: #2a2a2e; + } +} */ + + button { height: 32px; border-radius: 2px; @@ -11,11 +36,7 @@ button { width: 217px; } -button:hover { - background-color: #0047b3; -} - -input { +#url { height: 32px; border-radius: 2px; padding-inline: 8px; @@ -28,34 +49,8 @@ input { } #instructions{ - font-size: 14px; - font-weight: 132px; - width: 200px; -} - - -/* if prefers-color-scheme theme body have dark background white text */ -@media (prefers-color-scheme: dark) { - body { - background-color: #2a2a2e; - color: #fff; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - gap: 8px; - } -} - -/* if prefers-color-scheme light */ -@media (prefers-color-scheme: light) { - body { - background-color: #fff; - color: #2a2a2e; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - gap: 8px; - } + text-align: center; + padding: 0 11px; + max-width: 15em; + margin: 0 auto; } \ No newline at end of file From bbacd97ac4e5dc7bec1d28ed44c4de61dc9b632f Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 18 Nov 2022 10:14:50 +1100 Subject: [PATCH 09/17] =?UTF-8?q?=F0=9F=92=84=20Firefox=20Theme=20Colors?= =?UTF-8?q?=20Fixes=20#1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/main.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/js/main.js b/js/main.js index b7e558b..42ae34c 100644 --- a/js/main.js +++ b/js/main.js @@ -85,4 +85,60 @@ async function saveToStorage({title: title, iconUrl: iconUrl, webviewUrl: webvie browser.storage.local.set(sidebaritems); } -document.getElementById("addPageButton").addEventListener("click", addPage); \ No newline at end of file +document.getElementById("addPageButton").addEventListener("click", addPage); + + + + + + + + + + + + + + +function setSidebarStyle(theme) { + const body = document.body; + + if (theme.colors && theme.colors.frame) { + body.style.backgroundColor = + theme.colors.frame; + } else { + body.style.backgroundColor = "white"; + } + + if (theme.colors && theme.colors.toolbar) { + body.style.backgroundColor = theme.colors.toolbar; + } else { + body.style.backgroundColor = "#ebebeb"; + } + + if (theme.colors && theme.colors.toolbar_text) { + body.style.color = theme.colors.toolbar_text; + } else { + body.style.color = "black"; + } +} + +// Set the element style when the extension page loads +async function setInitialStyle() { + const theme = await browser.theme.getCurrent(); + setSidebarStyle(theme); +} +setInitialStyle(); + +// Watch for theme updates +browser.theme.onUpdated.addListener(async ({ theme, windowId }) => { + const sidebarWindow = await browser.windows.getCurrent(); + /* + Only update theme if it applies to the window the sidebar is in. + If a windowId is passed during an update, it means that the theme is applied to that specific window. + Otherwise, the theme is applied globally to all windows. + */ + if (!windowId || windowId == sidebarWindow.id) { + setSidebarStyle(theme); + } +}); \ No newline at end of file From d4a55dc364c7dd0007f169af14d956bb0411e939 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 18 Nov 2022 10:30:46 +1100 Subject: [PATCH 10/17] Add Credit --- js/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/main.js b/js/main.js index 42ae34c..3508cc3 100644 --- a/js/main.js +++ b/js/main.js @@ -99,7 +99,7 @@ document.getElementById("addPageButton").addEventListener("click", addPage); - +//Stolen from https://github.com/mdn/webextensions-examples function setSidebarStyle(theme) { const body = document.body; From 7ad40b7ada48ac6e06f5f462778afe0a3ab5add0 Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Fri, 18 Nov 2022 10:35:11 +1100 Subject: [PATCH 11/17] =?UTF-8?q?=F0=9F=94=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/main.js b/js/main.js index 3508cc3..48a85bf 100644 --- a/js/main.js +++ b/js/main.js @@ -75,9 +75,8 @@ async function saveToStorage({title: title, iconUrl: iconUrl, webviewUrl: webvie //get size of sidebaritems let size = sidebaritems.sidebaritems.length; - sidebaritems.sidebaritems.push({ - id: size-1, + id: size, title: title, iconUrl: iconUrl, webviewUrl: webviewUrl, From 235665c5222f8b89cf01d31237001a1be0c7fe8e Mon Sep 17 00:00:00 2001 From: PressJump <40802367+PressJump@users.noreply.github.com> Date: Sat, 17 Dec 2022 14:54:02 +1100 Subject: [PATCH 12/17] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rewrite=20and=20Clea?= =?UTF-8?q?nup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/background.js | 24 ++++----- js/main.js | 137 ++++++++++++++++++----------------------------- 2 files changed, 63 insertions(+), 98 deletions(-) diff --git a/js/background.js b/js/background.js index 19c07ec..c20a024 100644 --- a/js/background.js +++ b/js/background.js @@ -10,36 +10,36 @@ getFromStorage().then(createSidebarItems); async function getFromStorage() { //get from storage let sidebaritems = await browser.storage.local.get("sidebaritems"); - console.log(sidebaritems); return sidebaritems; } async function createSidebarItems(sidebaritems) { - //create sidebar items + if (sidebaritems.sidebaritems == undefined) { + sidebaritems.sidebaritems = []; + } + for (let i = 0; i < sidebaritems.sidebaritems.length; i++) { - browser.sidebars.add({ + var item = await browser.sidebars.add({ title: sidebaritems.sidebaritems[i].title, iconUrl: sidebaritems.sidebaritems[i].iconUrl, webviewUrl: sidebaritems.sidebaritems[i].webviewUrl, }); + sidebaritems.sidebaritems[i].id = item; } + + await browser.storage.local.set(sidebaritems); } async function removeSidebarItems(itemId) { - const item = await browser.sidebars.get(itemId); - - //remove from storage let storagearray = await getFromStorage(); - let storageitems = storagearray.sidebaritems; - - for (let i = 0; i < storageitems.length; i++) { - if (storageitems[i].webviewUrl == item.webviewUrl) { - storageitems.splice(i, 1); + for (let i = 0; i < storagearray.sidebaritems.length; i++) { + if (storagearray.sidebaritems[i].id == itemId) { + storagearray.sidebaritems.splice(i, 1); } } - browser.storage.local.set(storagearray); + await browser.storage.local.set(storagearray); } browser.sidebars.onRemove.addListener((itemId) => { diff --git a/js/main.js b/js/main.js index 48a85bf..fdfb162 100644 --- a/js/main.js +++ b/js/main.js @@ -1,102 +1,67 @@ -async function addPage() { - var pageURL = (document.getElementById("url").value); - if (!pageURL) { - return; - } - - // remove https:// or http:// from the url - pageURL = pageURL.replace(/^https?:\/\//, ''); - - let pageIcon = "chrome://global/skin/icons/link.svg"; - - if (navigator.onLine) { - //fetch https://icons.duckduckgo.com/ip3 image for icon - var response = await fetch(`https://icons.duckduckgo.com/ip3/${pageURL}.ico`); - if (response.ok) { - //Update pageIcon with the fetched icon - pageIcon = ('https://icons.duckduckgo.com/ip3/'+pageURL+'.ico') - } - } - - if (navigator.onLine) { - //create new tab - let newtab = browser.tabs.create({ url: "https://"+pageURL, active: true}); - //newtab await complete load - newtab.then(function(tab) { - browser.tabs.onUpdated.addListener(function listener(tabId, changeInfo, tab) { - if (tabId == tab.id && changeInfo.status == "complete") { - //remove listener - browser.tabs.onUpdated.removeListener(listener); - browser.tabs.get(tab.id).then(function(tab) { - //create new sidebar item - browser.sidebars.add({ - title: tab.title, - iconUrl: pageIcon, - webviewUrl: tab.url, - }); - }); - //save to storage - saveToStorage({ - title: tab.title, - iconUrl: pageIcon, - webviewUrl: tab.url, - }); - } - }); - }); - - } - else - { - //If the user is offline, create a sidebar item with the title as the url - //and the icon as the default icon so the browser sidebar is functional offline - browser.sidebars.add({ - title: pageURL, - iconUrl: pageIcon, - webviewUrl: pageURL, - }); - - //save to storage - saveToStorage({ - title: tab.title, - iconUrl: pageIcon, - webviewUrl: pageURL, - }); - } - +async function getFromStorage() { + //get from storage + let sidebaritems = await browser.storage.local.get("sidebaritems"); + return sidebaritems; } -async function saveToStorage({title: title, iconUrl: iconUrl, webviewUrl: webviewUrl}) { - //save to sidebaritems - let sidebaritems = await browser.storage.local.get("sidebaritems"); - if (sidebaritems.sidebaritems == undefined) { - sidebaritems.sidebaritems = []; +async function createSidebarItem(title, iconUrl, webviewUrl) { + //get from local storage sidebaritems and wait for it to return + let storagearray = await getFromStorage(); + if (storagearray.sidebaritems == undefined) { + storagearray.sidebaritems = []; } - //get size of sidebaritems - let size = sidebaritems.sidebaritems.length; - sidebaritems.sidebaritems.push({ - id: size, + var item = await browser.sidebars.add({ title: title, iconUrl: iconUrl, webviewUrl: webviewUrl, }); - browser.storage.local.set(sidebaritems); -} - -document.getElementById("addPageButton").addEventListener("click", addPage); - - - - - - - + storagearray.sidebaritems.push({ + id: item, + title: title, + iconUrl: iconUrl, + webviewUrl: webviewUrl, + }); + await browser.storage.local.set(storagearray); +} +async function addPage(){ + var pageURL = (document.getElementById("url").value); + if (!pageURL) { + return; + } + pageURL = pageURL.replace(/^https?:\/\//, ''); + let pageIcon = "chrome://global/skin/icons/link.svg"; + if (navigator.onLine) { + var response = await fetch(`https://icons.duckduckgo.com/ip3/${pageURL}.ico`); + if (response.ok) { + pageIcon = ('https://icons.duckduckgo.com/ip3/'+pageURL+'.ico') + } + } + + if (navigator.onLine) { + let newtab = browser.tabs.create({ url: "https://"+pageURL, active: true}); + newtab.then(function(tab) { + browser.tabs.onUpdated.addListener(function listener(tabId, changeInfo, tab) { + if (tabId == tab.id && changeInfo.status == "complete") { + browser.tabs.onUpdated.removeListener(listener); + browser.tabs.get(tab.id).then(function(tab) { + createSidebarItem(tab.title, pageIcon, tab.url); + }); + } + }); + }); + } + else + { + createSidebarItem(pageURL, pageIcon, "https://"+page); + } +} +document.getElementById("addPageButton").addEventListener("click", addPage); //Stolen from https://github.com/mdn/webextensions-examples function setSidebarStyle(theme) { From 94b37712a9f7e1239a63314ddc4cbd89e55c1dea Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Sat, 24 Dec 2022 14:33:17 +1100 Subject: [PATCH 13/17] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20backgroun?= =?UTF-8?q?d=20to=20make=20it=20more=20readable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc | 4 ++ js/background.js | 95 ++++++++++++++++++++++++++++++------------------ 2 files changed, 63 insertions(+), 36 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..2eed64c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "semi": false, + "singleQuote": true +} \ No newline at end of file diff --git a/js/background.js b/js/background.js index c20a024..4791b27 100644 --- a/js/background.js +++ b/js/background.js @@ -1,47 +1,70 @@ -browser.sidebars.add({ - title: "Add Shortcut to Sidebar", - iconUrl: "plus.svg", - webviewUrl: "index.html", - isBottom: true, -}) +// ============================================================================= +// Types +// @ts-check + +/** + * @typedef {object} SidebarItem + * + * @property {number} id The id of this specific sidebar item. Valid for a browser session + * @property {string} title The title of the sidebar item, generally the webpage title + * @property {string} iconUrl The website's favicon + * @property {string} webviewUrl The url of the website to navigate to + */ -getFromStorage().then(createSidebarItems); +// ============================================================================= +// Functions +/** + * @returns {Promise<{ sidebaritems: SidebarItem[] }>} + */ async function getFromStorage() { - //get from storage - let sidebaritems = await browser.storage.local.get("sidebaritems"); - return sidebaritems; + return await browser.storage.local.get('sidebaritems') } -async function createSidebarItems(sidebaritems) { - if (sidebaritems.sidebaritems == undefined) { - sidebaritems.sidebaritems = []; - } - - for (let i = 0; i < sidebaritems.sidebaritems.length; i++) { - var item = await browser.sidebars.add({ - title: sidebaritems.sidebaritems[i].title, - iconUrl: sidebaritems.sidebaritems[i].iconUrl, - webviewUrl: sidebaritems.sidebaritems[i].webviewUrl, - }); - sidebaritems.sidebaritems[i].id = item; - } - - await browser.storage.local.set(sidebaritems); +/** + * @param {{sidebaritems: SidebarItem[]}} storage + */ +async function spawnExistingSidebarItems(storage) { + let { sidebaritems: sidebarItems } = storage + + if (typeof sidebarItems === 'undefined') { + sidebarItems = [] + } + + for (let i = 0; i < sidebarItems.length; i++) { + const item = sidebarItems[i] + const id = await browser.sidebars.add(item) + + sidebarItems[i].id = id + } + + storage.sidebaritems = sidebarItems + await browser.storage.local.set(storage) } -async function removeSidebarItems(itemId) -{ - let storagearray = await getFromStorage(); - for (let i = 0; i < storagearray.sidebaritems.length; i++) { - if (storagearray.sidebaritems[i].id == itemId) { - storagearray.sidebaritems.splice(i, 1); - } - } +/** + * @param {number} idToRemove The id of the sidebar item you wish to remove + */ +async function removeSidebarItems(idToRemove) { + let storage = await getFromStorage() + + storage.sidebaritems = storage.sidebaritems.filter( + (item) => item.id !== idToRemove + ) - await browser.storage.local.set(storagearray); + await browser.storage.local.set(storage) } -browser.sidebars.onRemove.addListener((itemId) => { - removeSidebarItems(itemId); +// ============================================================================= +// Init logic + +browser.sidebars.add({ + title: 'Add Shortcut to Sidebar', + iconUrl: 'plus.svg', + webviewUrl: 'index.html', + isBottom: true, }) + +getFromStorage().then(spawnExistingSidebarItems) + +browser.sidebars.onRemove.addListener((itemId) => removeSidebarItems(itemId)) From 82c57c6a284d2d9e6cc35dd9006ca435add7a68c Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Sat, 24 Dec 2022 14:44:12 +1100 Subject: [PATCH 14/17] =?UTF-8?q?=F0=9F=9A=A7=20Remove=20all=20race=20cond?= =?UTF-8?q?itions=20in=20background.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/background.js | 20 +++++++++++++++----- js/mutex.js | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 js/mutex.js diff --git a/js/background.js b/js/background.js index 4791b27..ebc4458 100644 --- a/js/background.js +++ b/js/background.js @@ -1,3 +1,5 @@ +import { Mutex } from './mutex.js' + // ============================================================================= // Types // @ts-check @@ -14,18 +16,23 @@ // ============================================================================= // Functions +const storageMutex = new Mutex() + /** * @returns {Promise<{ sidebaritems: SidebarItem[] }>} */ async function getFromStorage() { - return await browser.storage.local.get('sidebaritems') + const { unlock } = await storageMutex.lock() + + const storage = await browser.storage.local.get('sidebaritems') + + unlock() + return storage } -/** - * @param {{sidebaritems: SidebarItem[]}} storage - */ async function spawnExistingSidebarItems(storage) { - let { sidebaritems: sidebarItems } = storage + const { unlock } = await storageMutex.lock() + let { sidebaritems: sidebarItems } = await getFromStorage() if (typeof sidebarItems === 'undefined') { sidebarItems = [] @@ -40,12 +47,14 @@ async function spawnExistingSidebarItems(storage) { storage.sidebaritems = sidebarItems await browser.storage.local.set(storage) + unlock() } /** * @param {number} idToRemove The id of the sidebar item you wish to remove */ async function removeSidebarItems(idToRemove) { + const { unlock } = await storageMutex.lock() let storage = await getFromStorage() storage.sidebaritems = storage.sidebaritems.filter( @@ -53,6 +62,7 @@ async function removeSidebarItems(idToRemove) { ) await browser.storage.local.set(storage) + unlock() } // ============================================================================= diff --git a/js/mutex.js b/js/mutex.js new file mode 100644 index 0000000..d72a377 --- /dev/null +++ b/js/mutex.js @@ -0,0 +1,24 @@ +// @ts-check + +/** + * @param {number} time How long (in ms) to wait for + */ +const wait = (time) => new Promise((res) => setTimeout(res, time)) + +export class Mutex { + /** + * @private + * @type {boolean} + */ + _locked = false + + /** + * @returns {Promise<{ unlock: () => void }>} + */ + async lock() { + while (this._locked) await wait(10) + + this._locked = true + return { unlock: () => (this._locked = false) } + } +} From 9aeae63d2207307241b71633c83f17112c8bd580 Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Sat, 24 Dec 2022 15:19:38 +1100 Subject: [PATCH 15/17] Make the UI race condition safe --- js/background.js | 55 ++++++++++++++++--- js/main.js | 135 +++++++++++++++++++++++------------------------ js/message.js | 11 ++++ 3 files changed, 125 insertions(+), 76 deletions(-) create mode 100644 js/message.js diff --git a/js/background.js b/js/background.js index ebc4458..d363078 100644 --- a/js/background.js +++ b/js/background.js @@ -1,3 +1,4 @@ +import { MessageTypeValues } from './message.js' import { Mutex } from './mutex.js' // ============================================================================= @@ -13,6 +14,17 @@ import { Mutex } from './mutex.js' * @property {string} webviewUrl The url of the website to navigate to */ +/** + * This is an incomplete version of {@link SidebarItem} intended for sending + * creation data around with. Currently it only excludes `id`. + * + * @typedef {object} SidebarItemData + * + * @property {string} title The title of the sidebar item, generally the webpage title + * @property {string} iconUrl The website's favicon + * @property {string} webviewUrl The url of the website to navigate to + */ + // ============================================================================= // Functions @@ -20,17 +32,15 @@ const storageMutex = new Mutex() /** * @returns {Promise<{ sidebaritems: SidebarItem[] }>} + * + * @note We assume that the parent caller has already locked {@see storageMutex} to avoid a race condition */ async function getFromStorage() { - const { unlock } = await storageMutex.lock() - const storage = await browser.storage.local.get('sidebaritems') - - unlock() return storage } -async function spawnExistingSidebarItems(storage) { +async function spawnExistingSidebarItems() { const { unlock } = await storageMutex.lock() let { sidebaritems: sidebarItems } = await getFromStorage() @@ -65,6 +75,23 @@ async function removeSidebarItems(idToRemove) { unlock() } +/** + * Creates a sidebar item and registers it, storing it for future browser + * instances + * + * @param {SidebarItemData} itemInfo Information about the sidebar to be created + */ +async function createSidebarItem(itemInfo) { + const { unlock } = await storageMutex.lock() + const storage = await getFromStorage() + + const id = await browser.sidebars.add(itemInfo) + storage.sidebaritems.push({ ...itemInfo, id }) + + await browser.storage.local.set(storage) + unlock() +} + // ============================================================================= // Init logic @@ -75,6 +102,22 @@ browser.sidebars.add({ isBottom: true, }) -getFromStorage().then(spawnExistingSidebarItems) +spawnExistingSidebarItems() browser.sidebars.onRemove.addListener((itemId) => removeSidebarItems(itemId)) + +// ============================================================================= +// Messages from UI + +browser.runtime.onMessage.addListener(({ type, data }, sender) => { + switch (type) { + case MessageTypeValues.CREATE_SIDEBAR_ITEMS: + createSidebarItem(data) + break + + default: + throw new Error(`Unknown message type: ${type}`) + } + + return null +}) diff --git a/js/main.js b/js/main.js index fdfb162..12a4bb7 100644 --- a/js/main.js +++ b/js/main.js @@ -1,108 +1,103 @@ -async function getFromStorage() { - //get from storage - let sidebaritems = await browser.storage.local.get("sidebaritems"); - return sidebaritems; +import { MessageTypeValues } from './message' + +/** + * Send a message to the background page to be processed + * @param {import("./message").MessageType} type + * @param {*} data + */ +async function sendMessageToBackgroundScript(type, data) { + return await browser.runtime.sendMessage({ type, data }) } async function createSidebarItem(title, iconUrl, webviewUrl) { - //get from local storage sidebaritems and wait for it to return - let storagearray = await getFromStorage(); - if (storagearray.sidebaritems == undefined) { - storagearray.sidebaritems = []; - } - - var item = await browser.sidebars.add({ - title: title, - iconUrl: iconUrl, - webviewUrl: webviewUrl, - }); - - storagearray.sidebaritems.push({ - id: item, - title: title, - iconUrl: iconUrl, - webviewUrl: webviewUrl, - }); - - await browser.storage.local.set(storagearray); + await sendMessageToBackgroundScript(MessageTypeValues.CREATE_SIDEBAR_ITEMS, { + title, + iconUrl, + webviewUrl, + }) } -async function addPage(){ - var pageURL = (document.getElementById("url").value); - if (!pageURL) { - return; - } - pageURL = pageURL.replace(/^https?:\/\//, ''); - let pageIcon = "chrome://global/skin/icons/link.svg"; - if (navigator.onLine) { - var response = await fetch(`https://icons.duckduckgo.com/ip3/${pageURL}.ico`); - if (response.ok) { - pageIcon = ('https://icons.duckduckgo.com/ip3/'+pageURL+'.ico') - } - } - - if (navigator.onLine) { - let newtab = browser.tabs.create({ url: "https://"+pageURL, active: true}); - newtab.then(function(tab) { - browser.tabs.onUpdated.addListener(function listener(tabId, changeInfo, tab) { - if (tabId == tab.id && changeInfo.status == "complete") { - browser.tabs.onUpdated.removeListener(listener); - browser.tabs.get(tab.id).then(function(tab) { - createSidebarItem(tab.title, pageIcon, tab.url); - }); - } - }); - }); - } - else - { - createSidebarItem(pageURL, pageIcon, "https://"+page); +async function addPage() { + var pageURL = document.getElementById('url').value + if (!pageURL) { + return + } + pageURL = pageURL.replace(/^https?:\/\//, '') + let pageIcon = 'chrome://global/skin/icons/link.svg' + if (navigator.onLine) { + var response = await fetch( + `https://icons.duckduckgo.com/ip3/${pageURL}.ico` + ) + if (response.ok) { + pageIcon = 'https://icons.duckduckgo.com/ip3/' + pageURL + '.ico' } + } + if (navigator.onLine) { + let newtab = browser.tabs.create({ + url: 'https://' + pageURL, + active: true, + }) + newtab.then(function (tab) { + browser.tabs.onUpdated.addListener(function listener( + tabId, + changeInfo, + tab + ) { + if (tabId == tab.id && changeInfo.status == 'complete') { + browser.tabs.onUpdated.removeListener(listener) + browser.tabs.get(tab.id).then(function (tab) { + createSidebarItem(tab.title, pageIcon, tab.url) + }) + } + }) + }) + } else { + createSidebarItem(pageURL, pageIcon, 'https://' + page) + } } -document.getElementById("addPageButton").addEventListener("click", addPage); +document.getElementById('addPageButton').addEventListener('click', addPage) //Stolen from https://github.com/mdn/webextensions-examples function setSidebarStyle(theme) { - const body = document.body; + const body = document.body if (theme.colors && theme.colors.frame) { - body.style.backgroundColor = - theme.colors.frame; + body.style.backgroundColor = theme.colors.frame } else { - body.style.backgroundColor = "white"; + body.style.backgroundColor = 'white' } if (theme.colors && theme.colors.toolbar) { - body.style.backgroundColor = theme.colors.toolbar; + body.style.backgroundColor = theme.colors.toolbar } else { - body.style.backgroundColor = "#ebebeb"; + body.style.backgroundColor = '#ebebeb' } - + if (theme.colors && theme.colors.toolbar_text) { - body.style.color = theme.colors.toolbar_text; + body.style.color = theme.colors.toolbar_text } else { - body.style.color = "black"; + body.style.color = 'black' } } // Set the element style when the extension page loads async function setInitialStyle() { - const theme = await browser.theme.getCurrent(); - setSidebarStyle(theme); + const theme = await browser.theme.getCurrent() + setSidebarStyle(theme) } -setInitialStyle(); +setInitialStyle() // Watch for theme updates browser.theme.onUpdated.addListener(async ({ theme, windowId }) => { - const sidebarWindow = await browser.windows.getCurrent(); + const sidebarWindow = await browser.windows.getCurrent() /* Only update theme if it applies to the window the sidebar is in. If a windowId is passed during an update, it means that the theme is applied to that specific window. Otherwise, the theme is applied globally to all windows. */ if (!windowId || windowId == sidebarWindow.id) { - setSidebarStyle(theme); + setSidebarStyle(theme) } -}); \ No newline at end of file +}) diff --git a/js/message.js b/js/message.js new file mode 100644 index 0000000..54ae23e --- /dev/null +++ b/js/message.js @@ -0,0 +1,11 @@ +/** + * @typedef {string} MessageType + */ + +/** + * @readonly + * @enum {MessageType} + */ +export const MessageTypeValues = { + CREATE_SIDEBAR_ITEMS: 'createSidebarItems', +} From 2d830364bf8be17153118e9cd502b27d00cf6f93 Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Sat, 24 Dec 2022 15:48:52 +1100 Subject: [PATCH 16/17] =?UTF-8?q?=F0=9F=90=9B=20Fix=20module=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background.html | 9 +++++++++ index.html | 14 ++++++++------ js/background.js | 3 ++- js/main.js | 2 +- manifest.json | 6 ++---- 5 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 background.html diff --git a/background.html b/background.html new file mode 100644 index 0000000..d74ca98 --- /dev/null +++ b/background.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/index.html b/index.html index 0a3cbec..20eebe8 100644 --- a/index.html +++ b/index.html @@ -1,14 +1,16 @@ - - + + - -

Add websites/items to your sidebar for ease of access.

- + +

+ Add websites/items to your sidebar for ease of access. +

+ - + diff --git a/js/background.js b/js/background.js index d363078..642f18e 100644 --- a/js/background.js +++ b/js/background.js @@ -42,7 +42,8 @@ async function getFromStorage() { async function spawnExistingSidebarItems() { const { unlock } = await storageMutex.lock() - let { sidebaritems: sidebarItems } = await getFromStorage() + let storage = await getFromStorage() + let { sidebaritems: sidebarItems } = storage if (typeof sidebarItems === 'undefined') { sidebarItems = [] diff --git a/js/main.js b/js/main.js index 12a4bb7..20f5a20 100644 --- a/js/main.js +++ b/js/main.js @@ -1,4 +1,4 @@ -import { MessageTypeValues } from './message' +import { MessageTypeValues } from './message.js' /** * Send a message to the background page to be processed diff --git a/manifest.json b/manifest.json index a9427d8..6b6dc88 100644 --- a/manifest.json +++ b/manifest.json @@ -1,4 +1,5 @@ { + "$schema": "https://json.schemastore.org/webextension.json", "manifest_version": 2, "name": "Pulse Sidebar Expansion", "version": "1.0", @@ -10,7 +11,6 @@ "webRequest", "activeTab", "https://icons.duckduckgo.com/" - ], "web_accessible_resources": [ "icon.svg", @@ -19,9 +19,7 @@ "page.html" ], "background": { - "scripts": [ - "js/background.js" - ] + "page": "background.html" }, "applications": { "gecko": { From c8862a60bfeff5a9ca53099366009f80e48cefa1 Mon Sep 17 00:00:00 2001 From: TrickyPR <23250792+trickypr@users.noreply.github.com> Date: Sat, 24 Dec 2022 16:03:38 +1100 Subject: [PATCH 17/17] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Simplify=20`addPage(?= =?UTF-8?q?)`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/main.js | 66 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/js/main.js b/js/main.js index 20f5a20..f76143b 100644 --- a/js/main.js +++ b/js/main.js @@ -1,3 +1,4 @@ +// @ts-check import { MessageTypeValues } from './message.js' /** @@ -18,43 +19,44 @@ async function createSidebarItem(title, iconUrl, webviewUrl) { } async function addPage() { - var pageURL = document.getElementById('url').value - if (!pageURL) { - return + /** @type {HTMLInputElement?} */ + // @ts-ignore + const pageUrlElement = document.getElementById('url') + + if (!pageUrlElement) { + throw new Error('Could not find the URL element') } - pageURL = pageURL.replace(/^https?:\/\//, '') + + const pageUrl = pageUrlElement.value.replace(/^https?:\/\//, '') let pageIcon = 'chrome://global/skin/icons/link.svg' - if (navigator.onLine) { - var response = await fetch( - `https://icons.duckduckgo.com/ip3/${pageURL}.ico` - ) - if (response.ok) { - pageIcon = 'https://icons.duckduckgo.com/ip3/' + pageURL + '.ico' - } + + if (!navigator.onLine) { + createSidebarItem(pageUrl, pageIcon, 'https://' + pageUrl) + return } - if (navigator.onLine) { - let newtab = browser.tabs.create({ - url: 'https://' + pageURL, - active: true, - }) - newtab.then(function (tab) { - browser.tabs.onUpdated.addListener(function listener( - tabId, - changeInfo, - tab - ) { - if (tabId == tab.id && changeInfo.status == 'complete') { - browser.tabs.onUpdated.removeListener(listener) - browser.tabs.get(tab.id).then(function (tab) { - createSidebarItem(tab.title, pageIcon, tab.url) - }) - } - }) - }) - } else { - createSidebarItem(pageURL, pageIcon, 'https://' + page) + const response = await fetch( + `https://icons.duckduckgo.com/ip3/${pageUrl}.ico` + ) + if (response.ok) { + pageIcon = `https://icons.duckduckgo.com/ip3/${pageUrl}.ico` } + + const tab = await browser.tabs.create({ + url: 'https://' + pageUrl, + active: true, + }) + + browser.tabs.onUpdated.addListener(async function listener( + tabId, + changeInfo, + tab + ) { + if (tabId == tab.id && changeInfo.status == 'complete') { + browser.tabs.onUpdated.removeListener(listener) + createSidebarItem(tab.title, pageIcon, tab.url) + } + }) } document.getElementById('addPageButton').addEventListener('click', addPage)