From 72efd76cea372e07f979e1a0b9eca1ff555b5223 Mon Sep 17 00:00:00 2001
From: Lim Chee Aun
Date: Fri, 5 Jan 2024 19:24:53 +0000
Subject: [PATCH] Imported from 2024.01.05.32c53b8.tar.gz.
SHA256:73b875c33e9e3a93fbdc31ad135730ebc8f2bf61e06f5185b0f831caa18f1b04
---
assets/{compose-Cvq_Pe8Z.js => compose-qZBynDN_.js} | 4 ++--
.../{compose-Cvq_Pe8Z.js.map => compose-qZBynDN_.js.map} | 2 +-
assets/{main-93nxKW6L.js => main-9vVntYq7.js} | 6 +++---
assets/{main-93nxKW6L.js.map => main-9vVntYq7.js.map} | 2 +-
assets/{useTitle-qcvAjFcD.js => useTitle-60DQEO3r.js} | 2 +-
.../{useTitle-qcvAjFcD.js.map => useTitle-60DQEO3r.js.map} | 2 +-
assets/useTitle-dYQBP_L8.css | 7 -------
assets/useTitle-uX1iWnvm.css | 7 +++++++
compose/index.html | 6 +++---
index.html | 6 +++---
version.json | 2 +-
11 files changed, 23 insertions(+), 23 deletions(-)
rename assets/{compose-Cvq_Pe8Z.js => compose-qZBynDN_.js} (88%)
rename assets/{compose-Cvq_Pe8Z.js.map => compose-qZBynDN_.js.map} (97%)
rename assets/{main-93nxKW6L.js => main-9vVntYq7.js} (99%)
rename assets/{main-93nxKW6L.js.map => main-9vVntYq7.js.map} (99%)
rename assets/{useTitle-qcvAjFcD.js => useTitle-60DQEO3r.js} (99%)
rename assets/{useTitle-qcvAjFcD.js.map => useTitle-60DQEO3r.js.map} (99%)
delete mode 100644 assets/useTitle-dYQBP_L8.css
create mode 100644 assets/useTitle-uX1iWnvm.css
diff --git a/assets/compose-Cvq_Pe8Z.js b/assets/compose-qZBynDN_.js
similarity index 88%
rename from assets/compose-Cvq_Pe8Z.js
rename to assets/compose-qZBynDN_.js
index a41b760..124e43e 100644
--- a/assets/compose-Cvq_Pe8Z.js
+++ b/assets/compose-qZBynDN_.js
@@ -1,2 +1,2 @@
-import{W as u,G as p}from"./useTitle-qcvAjFcD.js";import{h as w,p as f,a as e,K as m}from"./vendor-jabuMAqb.js";window.opener&&(console=window.opener.console);function S(){var s,a;const[t,i]=w("default"),{editStatus:n,replyToStatus:o,draftStatus:d}=window.__COMPOSE__||{};return u(n?"Editing source status":o?`Replying to @${((s=o.account)==null?void 0:s.acct)||((a=o.account)==null?void 0:a.username)}`:"Compose"),f(()=>{if(t==="closed"){try{window.opener.focus()}catch{}window.close()}},[t]),t==="closed"?e("div",{class:"box",children:[e("p",{children:"You may close this page now."}),e("p",{children:e("button",{onClick:()=>{window.close()},children:"Close window"})})]}):e(p,{editStatus:n,replyToStatus:o,draftStatus:d,standalone:!0,hasOpener:window.opener,onClose:c=>{const{newStatus:r,fn:l=()=>{}}=c||{};try{r&&window.opener.__STATES__.reloadStatusPage++,l(),i("closed")}catch{}}})}m(e(S,{}),document.getElementById("app-standalone"));
-//# sourceMappingURL=compose-Cvq_Pe8Z.js.map
+import{W as u,G as p}from"./useTitle-60DQEO3r.js";import{h as w,p as f,a as e,K as m}from"./vendor-jabuMAqb.js";window.opener&&(console=window.opener.console);function S(){var s,a;const[t,i]=w("default"),{editStatus:n,replyToStatus:o,draftStatus:d}=window.__COMPOSE__||{};return u(n?"Editing source status":o?`Replying to @${((s=o.account)==null?void 0:s.acct)||((a=o.account)==null?void 0:a.username)}`:"Compose"),f(()=>{if(t==="closed"){try{window.opener.focus()}catch{}window.close()}},[t]),t==="closed"?e("div",{class:"box",children:[e("p",{children:"You may close this page now."}),e("p",{children:e("button",{onClick:()=>{window.close()},children:"Close window"})})]}):e(p,{editStatus:n,replyToStatus:o,draftStatus:d,standalone:!0,hasOpener:window.opener,onClose:c=>{const{newStatus:r,fn:l=()=>{}}=c||{};try{r&&window.opener.__STATES__.reloadStatusPage++,l(),i("closed")}catch{}}})}m(e(S,{}),document.getElementById("app-standalone"));
+//# sourceMappingURL=compose-qZBynDN_.js.map
diff --git a/assets/compose-Cvq_Pe8Z.js.map b/assets/compose-qZBynDN_.js.map
similarity index 97%
rename from assets/compose-Cvq_Pe8Z.js.map
rename to assets/compose-qZBynDN_.js.map
index 124d2c4..eefe7d8 100644
--- a/assets/compose-Cvq_Pe8Z.js.map
+++ b/assets/compose-qZBynDN_.js.map
@@ -1 +1 @@
-{"version":3,"file":"compose-Cvq_Pe8Z.js","sources":["../../src/compose.jsx"],"sourcesContent":["import './index.css';\n\nimport './app.css';\n\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nimport Compose from './components/compose';\nimport useTitle from './utils/useTitle';\n\nif (window.opener) {\n console = window.opener.console;\n}\n\nfunction App() {\n const [uiState, setUIState] = useState('default');\n\n const { editStatus, replyToStatus, draftStatus } = window.__COMPOSE__ || {};\n\n useTitle(\n editStatus\n ? 'Editing source status'\n : replyToStatus\n ? `Replying to @${\n replyToStatus.account?.acct || replyToStatus.account?.username\n }`\n : 'Compose',\n );\n\n useEffect(() => {\n if (uiState === 'closed') {\n try {\n // Focus parent window\n window.opener.focus();\n } catch (e) {}\n window.close();\n }\n }, [uiState]);\n\n if (uiState === 'closed') {\n return (\n \n
You may close this page now.
\n
\n {\n window.close();\n }}\n >\n Close window\n \n
\n
\n );\n }\n\n console.debug('OPEN COMPOSE');\n\n return (\n {\n const { newStatus, fn = () => {} } = results || {};\n try {\n if (newStatus) {\n window.opener.__STATES__.reloadStatusPage++;\n }\n fn();\n setUIState('closed');\n } catch (e) {}\n }}\n />\n );\n}\n\nrender( , document.getElementById('app-standalone'));\n"],"names":["window","opener","console","App","uiState","setUIState","useState","editStatus","replyToStatus","draftStatus","__COMPOSE__","account","acct","username","useEffect","focus","close","_jsxs","class","children","_jsx","onClick","standalone","hasOpener","newStatus","results","fn","render"],"mappings":"gHAUIA,OAAOC,SACTC,QAAUF,OAAOC,OAAOC,SAG1B,SAASC,GAAM,SACb,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAS,SAAS,EAE1C,CAAEC,WAAAA,EAAYC,cAAAA,EAAeC,YAAAA,CAAAA,EAAgBT,OAAOU,aAAe,GAsBzE,OAnBEH,EAAAA,EACI,wBACAC,EACC,kBACCA,EAAAA,EAAcG,UAAdH,YAAAA,EAAuBI,SAAQJ,EAAAA,EAAcG,UAAdH,YAAAA,EAAuBK,SACvD,GACD,SACN,EAEAC,EAAU,IAAM,CACd,GAAIV,IAAY,SAAU,CACpB,GAAA,CAEFJ,OAAOC,OAAOc,aACJ,CAAC,CACbf,OAAOgB,MAAM,CACf,CAAA,EACC,CAACZ,CAAO,CAAC,EAERA,IAAY,SAEZa,EAAA,MAAA,CAAKC,MAAM,MAAKC,UACdC,EAAA,IAAA,CAAAD,SAAG,8BAAA,CAA+B,EAClCC,EAAA,IAAA,CAAAD,SACEC,EAAA,SAAA,CACEC,QAASA,IAAM,CACbrB,OAAOgB,MAAM,CACf,EAAEG,SACH,cAAA,CAEO,CAAA,CACP,CAAC,CAAA,CACD,EAITjB,IAA4B,CAE5B,WAAAK,EAEIA,cAAAA,EACAC,YAAAA,EACAC,WAAAA,GACAa,UAAU,OAAA,OACVC,WAAkBtB,OAEV,UAAAuB,EAAEA,GAAAA,EAAAA,IAAAA,EAAsB,EAACC,GAAA,CAAA,EAAE,GAAIA,CACjCD,GACF,OAAe,OAAA,WAAA,mBAEfE,IACGrB,EAAA,QAAA,CACHA,MAAAA,EACW,CAAA,CACf,CAAA,CAGNsB,EAAAP,EAAAjB,EAAA,CAAA,CAAA,EAAA,SAAA,eAAA,gBAAA,CAAA"}
\ No newline at end of file
+{"version":3,"file":"compose-qZBynDN_.js","sources":["../../src/compose.jsx"],"sourcesContent":["import './index.css';\n\nimport './app.css';\n\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nimport Compose from './components/compose';\nimport useTitle from './utils/useTitle';\n\nif (window.opener) {\n console = window.opener.console;\n}\n\nfunction App() {\n const [uiState, setUIState] = useState('default');\n\n const { editStatus, replyToStatus, draftStatus } = window.__COMPOSE__ || {};\n\n useTitle(\n editStatus\n ? 'Editing source status'\n : replyToStatus\n ? `Replying to @${\n replyToStatus.account?.acct || replyToStatus.account?.username\n }`\n : 'Compose',\n );\n\n useEffect(() => {\n if (uiState === 'closed') {\n try {\n // Focus parent window\n window.opener.focus();\n } catch (e) {}\n window.close();\n }\n }, [uiState]);\n\n if (uiState === 'closed') {\n return (\n \n
You may close this page now.
\n
\n {\n window.close();\n }}\n >\n Close window\n \n
\n
\n );\n }\n\n console.debug('OPEN COMPOSE');\n\n return (\n {\n const { newStatus, fn = () => {} } = results || {};\n try {\n if (newStatus) {\n window.opener.__STATES__.reloadStatusPage++;\n }\n fn();\n setUIState('closed');\n } catch (e) {}\n }}\n />\n );\n}\n\nrender( , document.getElementById('app-standalone'));\n"],"names":["window","opener","console","App","uiState","setUIState","useState","editStatus","replyToStatus","draftStatus","__COMPOSE__","account","acct","username","useEffect","focus","close","_jsxs","class","children","_jsx","onClick","standalone","hasOpener","newStatus","results","fn","render"],"mappings":"gHAUIA,OAAOC,SACTC,QAAUF,OAAOC,OAAOC,SAG1B,SAASC,GAAM,SACb,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAS,SAAS,EAE1C,CAAEC,WAAAA,EAAYC,cAAAA,EAAeC,YAAAA,CAAAA,EAAgBT,OAAOU,aAAe,GAsBzE,OAnBEH,EAAAA,EACI,wBACAC,EACC,kBACCA,EAAAA,EAAcG,UAAdH,YAAAA,EAAuBI,SAAQJ,EAAAA,EAAcG,UAAdH,YAAAA,EAAuBK,SACvD,GACD,SACN,EAEAC,EAAU,IAAM,CACd,GAAIV,IAAY,SAAU,CACpB,GAAA,CAEFJ,OAAOC,OAAOc,aACJ,CAAC,CACbf,OAAOgB,MAAM,CACf,CAAA,EACC,CAACZ,CAAO,CAAC,EAERA,IAAY,SAEZa,EAAA,MAAA,CAAKC,MAAM,MAAKC,UACdC,EAAA,IAAA,CAAAD,SAAG,8BAAA,CAA+B,EAClCC,EAAA,IAAA,CAAAD,SACEC,EAAA,SAAA,CACEC,QAASA,IAAM,CACbrB,OAAOgB,MAAM,CACf,EAAEG,SACH,cAAA,CAEO,CAAA,CACP,CAAC,CAAA,CACD,EAITjB,IAA4B,CAE5B,WAAAK,EAEIA,cAAAA,EACAC,YAAAA,EACAC,WAAAA,GACAa,UAAU,OAAA,OACVC,WAAkBtB,OAEV,UAAAuB,EAAEA,GAAAA,EAAAA,IAAAA,EAAsB,EAACC,GAAA,CAAA,EAAE,GAAIA,CACjCD,GACF,OAAe,OAAA,WAAA,mBAEfE,IACGrB,EAAA,QAAA,CACHA,MAAAA,EACW,CAAA,CACf,CAAA,CAGNsB,EAAAP,EAAAjB,EAAA,CAAA,CAAA,EAAA,SAAA,eAAA,gBAAA,CAAA"}
\ No newline at end of file
diff --git a/assets/main-93nxKW6L.js b/assets/main-9vVntYq7.js
similarity index 99%
rename from assets/main-93nxKW6L.js
rename to assets/main-9vVntYq7.js
index 26d1e0c..e1c85fc 100644
--- a/assets/main-93nxKW6L.js
+++ b/assets/main-9vVntYq7.js
@@ -1,4 +1,4 @@
-import{s as k,a as z,b as Ae,u as _n,c as pe,o as ms,I as w,M as Ce,d as se,A as et,N as It,e as Fe,f as Be,L as ee,g as at,h as En,l as gs,t as Qt,R as $t,i as bs,p as tt,j as He,k as Pn,m as Pt,E as Nn,n as Ue,q as Ke,r as ys,v as Ie,w as en,T as Dn,x as ht,y as Un,z as tn,B as ws,C as vs,D as Fn,F as Ee,G as Ss,S as Me,H as ks,J as Is,K as Ge,O as On,P as Nt,Q as Ts,U as rt,V as Bn,W as _e,X as zn,Y as Cs,Z as $s,_ as xs,$ as gt,a0 as As,a1 as nn,a2 as Ls,a3 as sn,a4 as on}from"./useTitle-qcvAjFcD.js";import{_ as D,p as B,h as $,u as Re,w as ze,a as e,b as Se,g as A,s as xt,c as Ht,M as oe,d as De,e as lt,F as he,T as Ve,S as Ms,I as je,y as Je,f as qn,l as an,i as Hn,j as Vn,k as qe,A as Rs,N as _s,m as Es,q as Ps,J as Ns,C as Gn,n as Ds,o as nt,r as jn,t as Us,v as Fs,x as Os,z as pt,B as Yn,D as cn,E as Bs,R as Vt,G as Te,H as zs,K as qs}from"./vendor-jabuMAqb.js";function ct(t=()=>{},n=[]){const i=D(t);B(()=>{i.current=t},[n]),B(()=>{const o=()=>{const a=document.hidden||document.visibilityState==="hidden";i.current(!a)};return document.addEventListener("visibilitychange",o),()=>document.removeEventListener("visibilitychange",o)},[])}const Hs=1e3*3,Vs=15e3,Gs=ze(function({isLoggedIn:n}){const[i,o]=$(!0);ct(o);const a=async(l,c,d)=>{var h;if(k.notificationsLast){const r=l.v1.notifications.list({limit:1,sinceId:k.notificationsLast.id}),{value:p}=await r.next();if(p!=null&&p.length)if(d)k.notificationsShowNew=!0;else{let f;try{const b=await l.v1.markers.fetch({timeline:"notifications"});f=(h=b==null?void 0:b.notifications)==null?void 0:h.lastReadId}catch{}f?k.notificationsShowNew=p[0].id!==f:k.notificationsShowNew=!0}}};B(()=>{let l,c;if(n&&i){const{masto:d,streaming:h,instance:r}=z();(async()=>{await a(d,r);let p=!1;h&&(c=setTimeout(()=>{(async()=>{try{p=!0,l=h.user.notification.subscribe();for await(const f of l){if(!l||!i)break;f.event==="notification"&&Ae(f.payload,r,{skipThreading:!0}),k.notificationsShowNew=!0}}catch{p=!1}p||(c=setInterval(()=>{a(d,r,!0)},Vs))})()},Hs))})()}return()=>{var d;(d=l==null?void 0:l.unsubscribe)==null||d.call(l),l=null,clearTimeout(c),clearInterval(c)}},[i,n]);const s=D(),u=()=>{s.current=Date.now(),fetch("./version.json").then(l=>l.json()).then(l=>{l&&(k.appVersion=l)}).catch(l=>{})};return _n(u,i&&1e3*60*30),ct(l=>{l&&(s.current?Date.now()-s.current>1e3*60*60&&u():u())}),Re("shift+alt+k",()=>{const l=k.settings.cloakMode;k.settings.cloakMode=!l,pe({text:`Cloak mode ${l?"disabled":"enabled"}`})}),null});function js(){function t(n){n.shiftKey?ms()||(k.showCompose=!0):k.showCompose=!0}return Re("c, shift+c",t,{ignoreEventWhen:n=>!!document.querySelector("#modal-container > *")}),e("button",{type:"button",id:"compose-button",onClick:t,children:e(w,{icon:"quill",size:"xl",alt:"Compose"})})}const Ys=ze(function(){const n=Se(k);function i(){k.showKeyboardShortcutsHelp=!1}return Re("?, shift+?",o=>{k.showKeyboardShortcutsHelp=!0},{ignoreEventWhen:o=>!!document.querySelector("#modal-container > *")}),!!n.showKeyboardShortcutsHelp&&e(Ce,{class:"light",onClose:i,children:e("div",{id:"keyboard-shortcuts-help-container",class:"sheet",tabindex:"-1",children:[e("button",{type:"button",class:"sheet-close",onClick:i,children:e(w,{icon:"x"})}),e("header",{children:e("h2",{children:"Keyboard shortcuts"})}),e("main",{children:e("table",{children:[{action:"Keyboard shortcuts help",keys:e("kbd",{children:"?"})},{action:"Next post",keys:e("kbd",{children:"j"})},{action:"Previous post",keys:e("kbd",{children:"k"})},{action:"Skip carousel to next post",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"j"})]})},{action:"Skip carousel to previous post",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"k"})]})},{action:"Open post details",keys:e(A,{children:[e("kbd",{children:"Enter"})," or ",e("kbd",{children:"o"})]})},{action:e(A,{children:["Expand content warning or",e("br",{}),"toggle expanded/collapsed thread"]}),keys:e("kbd",{children:"x"})},{action:"Close post or dialogs",keys:e(A,{children:[e("kbd",{children:"Esc"})," or ",e("kbd",{children:"Backspace"})]})},{action:"Focus column in multi-column mode",keys:e(A,{children:[e("kbd",{children:"1"})," to ",e("kbd",{children:"9"})]})},{action:"Compose new post",keys:e("kbd",{children:"c"})},{action:"Compose new post (new window)",className:"insignificant",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"c"})]})},{action:"Send post",keys:e(A,{children:[e("kbd",{children:"Ctrl"})," + ",e("kbd",{children:"Enter"})," or ",e("kbd",{children:"⌘"})," +"," ",e("kbd",{children:"Enter"})]})},{action:"Search",keys:e("kbd",{children:"/"})},{action:"Reply",keys:e("kbd",{children:"r"})},{action:"Reply (new window)",className:"insignificant",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"r"})]})},{action:"Like (favourite)",keys:e(A,{children:[e("kbd",{children:"l"})," or ",e("kbd",{children:"f"})]})},{action:"Boost",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"b"})]})},{action:"Bookmark",keys:e("kbd",{children:"d"})},{action:"Toggle Cloak mode",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"Alt"})," + ",e("kbd",{children:"k"})]})}].map(({action:o,className:a,keys:s})=>e("tr",{children:[e("th",{class:a,children:o}),e("td",{children:s})]},o))})})]})})});function Ws({onClose:t}){const{masto:n}=z(),i=se.local.getJSON("accounts"),o=se.session.get("currentAccount"),a=i.length>1,[s,u]=xt(c=>c+1,0),[l]=Ht();return e("div",{id:"accounts-container",class:"sheet",tabIndex:"-1",children:[!!t&&e("button",{type:"button",class:"sheet-close",onClick:t,children:e(w,{icon:"x"})}),e("header",{class:"header-grid",children:e("h2",{children:"Accounts"})}),e("main",{children:e("section",{children:[e("ul",{class:"accounts-list",ref:l,children:i.map((c,d)=>{const h=c.info.id===o,r=d===0;return e("li",{children:[e("div",{children:[a&&e("span",{class:`current ${h?"is-current":""}`,children:e(w,{icon:"check-circle",alt:"Current"})}),e(et,{url:c.info.avatarStatic,size:"xxl",onDblClick:async()=>{if(h)try{const p=await n.v1.accounts.$select(c.info.id).fetch();c.info=p,se.local.setJSON("accounts",i),u()}catch{}}}),e(It,{account:a?{...c.info,acct:/@/.test(c.info.acct)?c.info.acct:`${c.info.acct}@${c.instanceURL}`}:c.info,showAcct:!0,onClick:()=>{h?k.showAccount=`${c.info.username}@${c.instanceURL}`:(se.session.set("currentAccount",c.info.id),location.reload())}})]}),e("div",{class:"actions",children:[r&&a&&e(A,{children:[e("span",{class:"tag",children:"Default"})," "]}),e(Fe,{align:"end",menuButton:e("button",{type:"button",title:"More",class:"plain more-button",children:e(w,{icon:"more",size:"l",alt:"More"})}),children:[e(oe,{onClick:()=>{k.showAccount=`${c.info.username}@${c.instanceURL}`},children:[e(w,{icon:"user"}),e("span",{children:"View profile…"})]}),e(De,{}),a&&e(oe,{disabled:r,onClick:()=>{i.splice(d,1),i.unshift(c),se.local.setJSON("accounts",i),u()},children:[e(w,{icon:"check-circle"}),e("span",{children:"Set as default"})]}),e(Be,{subMenu:!0,confirmLabel:e(A,{children:[e(w,{icon:"exit"}),e("span",{children:["Log out @",c.info.acct,"?"]})]}),disabled:!h,menuItemClassName:"danger",onClick:()=>{i.splice(d,1),se.local.setJSON("accounts",i),location.href=location.pathname||"/"},children:[e(w,{icon:"exit"}),e("span",{children:"Log out…"})]})]})]})]},c.info.id)})}),e("p",{children:e(ee,{to:"/login",class:"button plain2",onClick:t,children:[e(w,{icon:"plus"})," ",e("span",{children:"Add an existing account"})]})}),a&&e("p",{children:e("small",{children:["Note: ",e("i",{children:"Default"})," account will always be used for first load. Switched accounts will persist during the session."]})})]})})]})}const Gt="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20xml:space='preserve'%20fill-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%20clip-rule='evenodd'%20viewBox='0%200%2064%2064'%3e%3cpath%20fill='none'%20d='M0%200h63.994v63.994H0z'/%3e%3cpath%20fill='%23a4bff7'%20d='M37.774%2011.471c14.639%203.752%2019.034%2016.557%2015.889%2031.304-.696%203.261-2.563%206.661-6.356%208.693-3.204%201.717-8.07%202.537-15.338.55l-9.634-2.404C11.651%2046.992%208.378%2038.733%2010.027%2031.823c3.627-15.201%2015.543-23.48%2027.747-20.352Z'/%3e%3cpath%20fill='%23d8e7fe'%20d='M36.76%2015.429c12.289%203.15%2015.547%2014.114%2012.907%2026.493-.947%204.44-4.937%209.365-16.664%206.143l-9.684-2.417c-7.854-1.923-10.53-7.8-9.318-12.877%203.016-12.639%2012.611-19.943%2022.759-17.342Z'/%3e%3cpath%20fill='%236081e6'%20d='M27.471%2024.991c-1.457-.698-7.229%203.213-7.663%208.926-.182%202.39%204.55%203.237%205.071-.169.725-4.743%203.715-8.218%202.592-8.757Zm10.746%202.005c-2.083.327-.382%205.901-.595%2010.727-.123%202.8%204.388%203.464%204.703%202.011%201.098-5.073-2.066-13.058-4.108-12.738Z'/%3e%3c/svg%3e";function rn(t){const{masto:n}=z();return n.v1.push.subscription.create(t)}function Ks(){const{masto:t}=z();return t.v1.push.subscription.fetch()}function Zs(t){const{masto:n}=z();return n.v1.push.subscription.update(t)}function Js(){const{masto:t}=z();return t.v1.push.subscription.remove()}function At(){return"serviceWorker"in navigator&&"PushManager"in window}function Xs(){return navigator.serviceWorker.getRegistration()}async function jt(){const t=await Xs(),n=t?await t.pushManager.getSubscription():void 0;return{registration:t,subscription:n}}function Wn(t){const n="=".repeat((4-t.length%4)%4),i=`${t}${n}`.replace(/-/g,"+").replace(/_/g,"/"),o=window.atob(i),a=new Uint8Array(o.length);for(let s=0;s{f.preventDefault();const g=new FormData(o.current).get("theme"),v=document.documentElement;if(g==="auto"){v.classList.remove("is-light","is-dark");const m=document.querySelector('meta[data-theme-setting="manual"]');m&&(m.name=""),document.querySelectorAll('meta[data-theme-setting="auto"]').forEach(S=>{S.name="theme-color"})}else{v.classList.toggle("is-light",g==="light"),v.classList.toggle("is-dark",g==="dark");const m=document.querySelector('meta[data-theme-setting="manual"]');m&&(m.name="theme-color",m.content=g==="light"?m.dataset.themeLightColor:m.dataset.themeDarkColor),document.querySelectorAll('meta[data-theme-setting="auto"]').forEach(S=>{S.name=""})}document.querySelector('meta[name="color-scheme"]').setAttribute("content",g==="auto"?"dark light":g),g==="auto"?se.local.del("theme"):se.local.set("theme",g)},children:e("div",{class:"radio-group",children:[e("label",{children:[e("input",{type:"radio",name:"theme",value:"light",defaultChecked:i==="light"}),e("span",{children:"Light"})]}),e("label",{children:[e("input",{type:"radio",name:"theme",value:"dark",defaultChecked:i==="dark"}),e("span",{children:"Dark"})]}),e("label",{children:[e("input",{type:"radio",name:"theme",value:"auto",defaultChecked:i!=="light"&&i!=="dark"}),e("span",{children:"Auto"})]})]})})})]}),e("li",{children:[e("div",{children:e("label",{children:"Text size"})}),e("div",{class:"range-group",children:[e("span",{style:{fontSize:Qe[0]},children:"A"})," ",e("input",{type:"range",min:Qe[0],max:Qe[Qe.length-1],step:"1",value:l,list:"sizes",onChange:f=>{const b=parseInt(f.target.value,10);document.documentElement.style.setProperty("--text-size",`${b}px`),b===un?se.local.del("textSize"):se.local.set("textSize",f.target.value)}})," ",e("span",{style:{fontSize:Qe[Qe.length-1]},children:"A"}),e("datalist",{id:"sizes",children:Qe.map(f=>e("option",{value:f}))})]})]})]})}),r&&e(A,{children:[e("h3",{children:"Posting"}),e("section",{children:e("ul",{children:e("li",{children:[e("div",{children:e("label",{for:"posting-privacy-field",children:["Default visibility"," ",e(w,{icon:"cloud",alt:"Synced",class:"synced-icon"})]})}),e("div",{children:e("select",{id:"posting-privacy-field",value:c["posting:default:visibility"]||"public",onChange:f=>{const{value:b}=f.target;(async()=>{try{await h.v1.accounts.updateCredentials({source:{privacy:b}}),d({...c,"posting:default:visibility":b}),se.account.set("preferences",{...c,"posting:default:visibility":b})}catch{alert("Failed to update posting privacy")}})()},children:[e("option",{value:"public",children:"Public"}),e("option",{value:"unlisted",children:"Unlisted"}),e("option",{value:"private",children:"Followers only"})]})})]})})}),e("p",{class:"section-postnote",children:[e(w,{icon:"cloud",alt:"Synced",class:"synced-icon"})," ",e("small",{children:["Synced to your instance server's settings."," ",e("a",{href:`https://${p}/`,target:"_blank",rel:"noopener noreferrer",children:["Go to your instance (",p,") for more settings."]})]})]})]}),e("h3",{children:"Experiments"}),e("section",{children:e("ul",{children:[e("li",{children:e("label",{children:[e("input",{type:"checkbox",checked:n.settings.autoRefresh,onChange:f=>{k.settings.autoRefresh=f.target.checked}})," ","Auto refresh timeline posts"]})}),e("li",{children:e("label",{children:[e("input",{type:"checkbox",checked:n.settings.boostsCarousel,onChange:f=>{k.settings.boostsCarousel=f.target.checked}})," ","Boosts carousel"]})}),e("li",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.contentTranslation,onChange:f=>{const{checked:b}=f.target;k.settings.contentTranslation=b,b||(k.settings.contentTranslationTargetLanguage=null)}})," ","Post translation"]}),e("div",{class:`sub-section ${n.settings.contentTranslation?"":"more-insignificant"}`,children:[e("div",{children:e("label",{children:["Translate to"," ",e("select",{value:a||"",disabled:!n.settings.contentTranslation,onChange:f=>{k.settings.contentTranslationTargetLanguage=f.target.value||null},children:[e("option",{value:"",children:["System language (",u,")"]}),e("option",{disabled:!0,children:"──────────"}),Qt.map(f=>e("option",{value:f.code,children:f.name}))]})]})}),e("hr",{}),e("p",{class:"checkbox-fieldset",children:['Hide "Translate" button for',n.settings.contentTranslationHideLanguages.length>0&&e(A,{children:[" ","(",n.settings.contentTranslationHideLanguages.length,")"]}),":",e("div",{class:"checkbox-fields",children:Qt.map(f=>e("label",{children:[e("input",{type:"checkbox",checked:n.settings.contentTranslationHideLanguages.includes(f.code),onChange:b=>{const{checked:g}=b.target;g?k.settings.contentTranslationHideLanguages.push(f.code):k.settings.contentTranslationHideLanguages=n.settings.contentTranslationHideLanguages.filter(v=>v!==f.code)}})," ",f.name]}))})]}),e("p",{class:"insignificant",children:e("small",{children:["Note: This feature uses external translation services, powered by"," ",e("a",{href:"https://github.com/cheeaun/lingva-api",target:"_blank",rel:"noopener noreferrer",children:"Lingva API"})," ","&"," ",e("a",{href:"https://github.com/thedaviddelta/lingva-translate",target:"_blank",rel:"noopener noreferrer",children:"Lingva Translate"}),"."]})}),e("hr",{}),e("div",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.contentTranslationAutoInline,disabled:!n.settings.contentTranslation,onChange:f=>{k.settings.contentTranslationAutoInline=f.target.checked}})," ","Auto inline translation"]}),e("p",{class:"insignificant",children:e("small",{children:["Automatically show translation for posts in timeline. Only works for ",e("b",{children:"short"})," posts without content warning, media and poll."]})})]})]})]}),!!ni&&e("li",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.mediaAltGenerator,onChange:f=>{k.settings.mediaAltGenerator=f.target.checked}})," ","Image description generator"," ",e(w,{icon:"sparkles2",class:"more-insignificant"})]}),e("div",{class:"sub-section insignificant",children:e("small",{children:"Only for new images while composing new posts."})}),e("div",{class:"sub-section insignificant",children:e("small",{children:["Note: This feature uses external AI service, powered by"," ",e("a",{href:"https://github.com/cheeaun/img-alt-api",target:"_blank",rel:"noopener noreferrer",children:"img-alt-api"}),". May not work well. Only for images and in English."]})})]}),e("li",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.cloakMode,onChange:f=>{k.settings.cloakMode=f.target.checked}})," ","Cloak mode"," ",e("span",{class:"insignificant",children:["(",e("samp",{children:"Text"})," → ",e("samp",{children:"████"}),")"]})]}),e("div",{class:"sub-section insignificant",children:e("small",{children:"Replace text as blocks, useful when taking screenshots, for privacy reasons."})})]}),r&&e("li",{children:e("button",{type:"button",class:"light",onClick:()=>{k.showDrafts=!0,k.showSettings=!1},children:"Unsent drafts"})})]})}),r&&e(ii,{onClose:t}),e("h3",{children:"About"}),e("section",{children:[e("div",{style:{display:"flex",flexWrap:"wrap",gap:8,lineHeight:1.25,alignItems:"center",marginTop:8},children:[e("img",{src:Gt,alt:"",width:"64",height:"64",style:{aspectRatio:"1/1",verticalAlign:"middle",background:"#b7cdf9",borderRadius:12}}),e("div",{children:[e("b",{children:"Phanpy"})," ",e("a",{href:"https://hachyderm.io/@phanpy",rel:"noopener noreferrer",onClick:f=>{f.preventDefault(),k.showAccount="phanpy@hachyderm.io"},children:"@phanpy"}),e("br",{}),e("a",{href:"https://github.com/cheeaun/phanpy",target:"_blank",rel:"noopener noreferrer",children:"Built"})," ","by"," ",e("a",{href:"https://mastodon.social/@cheeaun",rel:"noopener noreferrer",onClick:f=>{f.preventDefault(),k.showAccount="cheeaun@mastodon.social"},children:"@cheeaun"})]})]}),e("p",{children:[e("a",{href:"https://github.com/sponsors/cheeaun",target:"_blank",rel:"noopener noreferrer",children:"Sponsor"})," ","·"," ",e("a",{href:"https://www.buymeacoffee.com/cheeaun",target:"_blank",rel:"noopener noreferrer",children:"Donate"})," ","·"," ",e("a",{href:ti,target:"_blank",rel:"noopener noreferrer",children:"Privacy Policy"})]}),e("p",{children:[hn&&e(A,{children:[e("span",{class:"insignificant",children:"Site:"})," ",hn.replace(/https?:\/\//g,"").replace(/\/$/,""),e("br",{})]}),e("span",{class:"insignificant",children:"Version:"})," ",e("input",{type:"text",class:"version-string",readOnly:!0,size:"18",value:`${"2024-01-05T02:16:32.524Z".slice(0,10).replace(/-/g,".")}.adf0b35`,onClick:f=>{f.target.select();try{navigator.clipboard.writeText(f.target.value),pe("Version string copied")}catch{pe("Unable to copy version string")}}})," ",e("span",{class:"ib insignificant",children:["(",e("a",{href:"https://github.com/cheeaun/phanpy/commit/adf0b35",target:"_blank",rel:"noopener noreferrer",children:e($t,{datetime:new Date("2024-01-05T02:16:32.524Z")})}),")"]})]})]})]})]})}function ii({onClose:t}){if(!At())return null;const{instance:n}=z(),[i,o]=$("default"),a=D(),[s,u]=$(!1),[l,c]=$(!1),d=D();B(()=>{(async()=>{o("loading");try{const{subscription:r,backendSubscription:p}=await Qs();if(p!=null&&p.policy&&p.policy!=="none"){u(!0);const{alerts:f,policy:b}=p;d.current=b;const{elements:g}=a.current,v=g.namedItem(b);v&&(v.value=b),Object.keys(f).forEach(m=>{const y=g.namedItem(m);(y==null?void 0:y.type)==="checkbox"&&(y.checked=!0)})}o("default")}catch(r){/outside.*authorized/i.test(r.message)?c(!0):alert((r==null?void 0:r.message)||r),o("error")}})()},[]);const h=i==="loading";return e("form",{ref:a,onChange:()=>{const r=Object.fromEntries(new FormData(a.current)),p=!!r["policy-allow"],f={policy:r.policy,data:{alerts:{mention:!!r.mention,favourite:!!r.favourite,reblog:!!r.reblog,follow:!!r.follow,follow_request:!!r.followRequest,poll:!!r.poll,update:!!r.update,status:!!r.status}}};let b=0;Object.keys(f.data.alerts).forEach(v=>{f.data.alerts[v]?b++:delete f.data.alerts[v]});const g=d.current!==f.policy;p&&b>0?g?dn().then(()=>{ln(f)}).catch(v=>{alert("Failed to update subscription. Please try again.")}):ln(f).catch(v=>{alert("Failed to update subscription. Please try again.")}):dn().catch(v=>{alert("Failed to remove subscription. Please try again.")})},children:[e("h3",{children:"Push Notifications (beta)"}),e("section",{children:e("ul",{children:e("li",{children:[e("label",{children:[e("input",{type:"checkbox",disabled:h||l,name:"policy-allow",checked:s,onChange:async r=>{const{checked:p}=r.target;if(p){const f=await Notification.requestPermission();f==="granted"?u(!0):(u(!1),f==="denied"&&alert("Push notifications are blocked. Please enable them in your browser settings."))}else u(!1)}})," ","Allow from"," ",e("select",{name:"policy",disabled:h||l||!s,children:[{value:"all",label:"anyone"},{value:"followed",label:"people I follow"},{value:"follower",label:"followers"}].map(r=>e("option",{value:r.value,children:r.label}))})]}),e("div",{class:"shazam-container no-animation",style:{width:"100%"},hidden:!s,children:e("div",{class:"shazam-container-inner",children:e("div",{class:"sub-section",children:e("ul",{children:[{value:"mention",label:"Mentions"},{value:"favourite",label:"Likes"},{value:"reblog",label:"Boosts"},{value:"follow",label:"Follows"},{value:"followRequest",label:"Follow requests"},{value:"poll",label:"Polls"},{value:"update",label:"Post edits"},{value:"status",label:"New posts"}].map(r=>e("li",{children:e("label",{children:[e("input",{type:"checkbox",name:r.value})," ",r.label]})}))})})})}),l&&e("div",{class:"sub-section",children:e("p",{children:["Push permission was not granted since your last login. You'll need to"," ",e(ee,{to:`/login?instance=${n}`,onClick:t,children:[e("b",{children:"log in"})," again to grant push permission"]}),"."]})})]})})}),e("p",{class:"section-postnote",children:e("small",{children:["NOTE: Push notifications only work for ",e("b",{children:"one account"}),"."]})})]})}const Dt=()=>{let t=setTimeout(()=>{if(!document.getElementById("columns")){const i=document.querySelectorAll("#modal-container > *");if(i!=null&&i.length){const u=i[i.length-1],l=u.querySelector('[tabindex="-1"]')||u;if(l){l.focus();return}}if(document.querySelector(".deck-backdrop"))return;const a=document.querySelectorAll(".deck-container"),s=a[a.length-1];s&&s.tabIndex===-1&&s.focus()}},100);return()=>clearTimeout(t)};function Kn(t){if(!t)return;const n=lt(),i=D(n.pathname);B(()=>{i.current&&n.pathname!==i.current&&(t==null||t())},[n.pathname,t])}function Yt({list:t,onClose:n}){const{masto:i}=z(),[o,a]=$("default"),s=!!t,u=D(),l=D(),c=D();B(()=>{s&&(u.current.value=t.title,l.current.value=t.repliesPolicy,c.current&&(c.current.checked=t.exclusive))},[s]);const d=bs("@mastodon/list-exclusive");return e("div",{class:"sheet",children:[!!n&&e("button",{type:"button",class:"sheet-close",onClick:n,children:e(w,{icon:"x"})})," ",e("header",{children:e("h2",{children:s?"Edit list":"New list"})}),e("main",{children:e("form",{class:"list-form",onSubmit:h=>{h.preventDefault();const r=new FormData(h.target),p=r.get("title"),f=r.get("replies_policy"),b=r.get("exclusive")==="on";a("loading"),(async()=>{try{let g;s?g=await i.v1.lists.$select(t.id).update({title:p,replies_policy:f,exclusive:b}):g=await i.v1.lists.create({title:p,replies_policy:f,exclusive:b}),a("default"),n==null||n({state:"success",list:g})}catch{a("error"),alert(s?"Unable to edit list.":"Unable to create list.")}})()},children:[e("div",{class:"list-form-row",children:e("label",{for:"list-title",children:["Name"," ",e("input",{ref:u,type:"text",id:"list-title",name:"title",required:!0,disabled:o==="loading",dir:"auto"})]})}),e("div",{class:"list-form-row",children:e("select",{ref:l,name:"replies_policy",required:!0,disabled:o==="loading",children:[e("option",{value:"list",children:"Show replies to list members"}),e("option",{value:"followed",children:"Show replies to people I follow"}),e("option",{value:"none",children:"Don't show replies"})]})}),d&&e("div",{class:"list-form-row",children:e("label",{class:"label-block",children:[e("input",{ref:c,type:"checkbox",name:"exclusive",disabled:o==="loading"})," ","Hide posts on this list from Home/Following"]})}),e("div",{class:"list-form-footer",children:[e("button",{type:"submit",disabled:o==="loading",children:s?"Save":"Create"}),s&&e(Be,{disabled:o==="loading",align:"end",menuItemClassName:"danger",confirmLabel:"Delete this list?",onClick:()=>{a("loading"),(async()=>{try{await i.v1.lists.$select(t.id).remove(),a("default"),n==null||n({state:"deleted"})}catch{a("error"),alert("Unable to delete list.")}})()},children:e("button",{type:"button",class:"light danger",disabled:o==="loading",children:"Delete…"})})]})]})})]})}const oi=[60*5,60*30,60*60,60*60*6,60*60*24,60*60*24*3,60*60*24*7,0],fn={0:"Forever",300:"5 minutes",1800:"30 minutes",3600:"1 hour",21600:"6 hours",86400:"1 day",259200:"3 days",604800:"1 week"},pn=80,Zn=1e3*60*10;function ai(t,n){return n.v1.accounts.familiarFollowers.fetch({id:[t]})}const ci=tt(ai,{maxAge:Zn});async function ri(t,n){const i=n.v1.accounts.$select(t).statuses.list({limit:20}).next(),{value:o}=await i,a={total:o.length,originals:0,replies:0,boosts:0};return o.forEach(s=>{s.reblog?a.boosts++:s.inReplyToId&&s.inReplyToAccountId!==s.account.id?a.replies++:a.originals++}),o.length&&(a.daysSinceLastPost=Math.ceil((Date.now()-new Date(o[o.length-1].createdAt))/864e5)),a}const li=tt(ri,{maxAge:Zn});function Jn({account:t,fetchAccount:n=()=>{},standalone:i,instance:o,authenticated:a}){const{masto:s}=z({instance:o}),{masto:u,instance:l}=z(),[c,d]=$("default"),h=typeof t=="string",[r,p]=$(h?null:t),f=he(()=>o===l,[o,l]);B(()=>{if(!h){p(t);return}d("loading"),(async()=>{try{const q=await n();k.accounts[`${q.id}@${o}`]=q,p(q),d("default")}catch{p(null),d("error")}})()},[h,t,n]);const{acct:b,avatar:g,avatarStatic:v,bot:m,createdAt:y,displayName:S,emojis:I,fields:T,followersCount:x,followingCount:L,group:N,id:O,lastStatusAt:U,locked:P,note:M,statusesCount:C,url:_,username:F,memorial:Y,moved:te,roles:W}=r||{};let ke=!1,{header:re,headerStatic:X}=r||{};(!re||/missing\.png$/.test(re))&&g&&!/missing\.png$/.test(g)&&(re=g,ke=!0,v&&!/missing\.png$/.test(v)&&(X=v));const E=he(()=>O===se.session.get("currentAccount"),[O]);B(()=>{const q=!!(r!=null&&r.id&&(r!=null&&r.username)&&(r!=null&&r.acct)&&(r!=null&&r.avatar)&&(r!=null&&r.avatarStatic)&&(r!=null&&r.displayName)&&(r!=null&&r.url));if(E&&o&&q){const ge=se.local.getJSON("accounts");let be=!1;ge.forEach(ue=>{ue.info.id===r.id&&ue.instanceURL===o&&(ue.info=r,be=!0)}),be&&se.local.setJSON("accounts",ge)}},[E,r,o]);const j=he(()=>_?new URL(_).hostname:null,[_]),[ne,le]=$([]),H=D(),ae=D([]);async function Q(q){(q||!H.current)&&(H.current=s.v1.accounts.$select(O).followers.list({limit:pn}));const ge=await H.current.next();if(E||!f)return ge;const{value:be}=ge;let ue=[];if(q){const xe=await s.v1.accounts.familiarFollowers.fetch({id:[O]});ae.current=xe[0].accounts,ue=[...ae.current,...be.filter(Pe=>!ae.current.some(Ne=>Ne.id===Pe.id))]}else be!=null&&be.length&&(ue=be.filter(xe=>!ae.current.some(Pe=>Pe.id===xe.id)));return{...ge,value:ue}}const ye=D();async function V(q){return(q||!ye.current)&&(ye.current=s.v1.accounts.$select(O).following.list({limit:pn})),await ye.current.next()}const Z=i?"div":ee,ce=o?`/${o}/a/${O}`:`/a/${O}`,[fe,me]=$([]),[de,R]=$(),[G,K]=$("default"),ie=!!(de!=null&&de.total),we=async q=>{try{const ge=await ci(q,u);me(ge[0].accounts.slice(0,di))}catch{}},Le=async()=>{if(O){K("loading");try{const q=await li(O,s);R(q),K("default")}catch{K("error")}}},$e=Ve(({relationship:q,currentID:ge})=>{q.following||(we(ge),!i&&C>0&&Le())},[i,O,C]);return e("div",{tabIndex:"-1",class:`account-container ${c==="loading"?"skeleton":""}`,style:{"--header-color-1":ne[0],"--header-color-2":ne[1],"--header-color-3":ne[2],"--header-color-4":ne[3]},children:[c==="error"&&e("div",{class:"ui-state",children:[e("p",{children:"Unable to load account."}),e("p",{children:e("a",{href:h?t:_,target:"_blank",rel:"noopener noreferrer",children:["Go to account page ",e(w,{icon:"external"})]})})]}),c==="loading"?e(A,{children:[e("header",{children:e(He,{avatarSize:"xxxl",skeleton:!0})}),e("main",{children:[e("div",{class:"note",children:[e("p",{children:"███████ ████ ████"}),e("p",{children:"████ ████████ ██████ █████████ ████ ██"})]}),e("div",{class:"account-metadata-box",children:[e("div",{class:"profile-metadata",children:[e("div",{class:"profile-field",children:[e("b",{class:"more-insignificant",children:"███"}),e("p",{children:"██████"})]}),e("div",{class:"profile-field",children:[e("b",{class:"more-insignificant",children:"████"}),e("p",{children:"███████████"})]})]}),e("div",{class:"stats",children:[e("div",{children:[e("span",{children:"██"})," Followers"]}),e("div",{children:[e("span",{children:"██"})," Following"]}),e("div",{children:[e("span",{children:"██"})," Posts"]})]})]}),e("div",{class:"actions",children:[e("span",{}),e("span",{class:"buttons",children:e("button",{type:"button",title:"More",class:"plain",disabled:!0,children:e(w,{icon:"more",size:"l",alt:"More"})})})]})]})]}):r&&e(A,{children:[!!te&&e("div",{class:"account-moved",children:[e("p",{children:[e("b",{children:S})," has indicated that their new account is now:"]}),e(He,{account:te,instance:o,onClick:q=>{q.stopPropagation(),k.showAccount=te}})]}),!!re&&!/missing\.png$/.test(re)&&e("img",{src:re,alt:"",class:`header-banner ${ke?"header-is-avatar":""}`,onError:q=>{q.target.crossOrigin?q.target.src!==X?q.target.src=X:(q.target.removeAttribute("crossorigin"),q.target.src=re):q.target.src!==X?q.target.src=X:q.target.remove()},crossOrigin:"anonymous",onLoad:q=>{q.target.classList.add("loaded");try{const ge=document.createElement("canvas"),be=ge.getContext("2d",{willReadFrequently:!0});ge.width=q.target.width,ge.height=q.target.height,be.drawImage(q.target,0,0);const ue=10,Pe=[be.getImageData(0,0,ue,ue).data,be.getImageData(q.target.width-ue,0,ue,ue).data,be.getImageData(0,q.target.height-ue,ue,ue).data,be.getImageData(q.target.width-ue,q.target.height-ue,ue,ue).data].map(Ne=>{let st=0,Oe=0,We=0,Xe=0;for(let ve=0;ve{const[st,Oe,We,Xe]=hi(Ne);return`rgba(${st}, ${Oe}, ${We}, ${Xe})`});le(Pe)}catch{}}}),e("header",{children:e(He,{account:r,instance:o,avatarSize:"xxxl",external:i,internal:!i})}),e("div",{class:"faux-header-bg","aria-hidden":"true"}),e("main",{children:[!!Y&&e("span",{class:"tag",children:"In Memoriam"}),!!m&&e("span",{class:"tag",children:[e(w,{icon:"bot"})," Automated"]}),!!N&&e("span",{class:"tag",children:[e(w,{icon:"group"})," Group"]}),W==null?void 0:W.map(q=>e("span",{class:"tag",children:[q.name,!!j&&e(A,{children:[" ",e("span",{class:"more-insignificant",children:j})]})]})),e("div",{class:"note",dir:"auto",onClick:Pn({instance:l}),dangerouslySetInnerHTML:{__html:Pt(M,{emojis:I})}}),e("div",{class:"account-metadata-box",children:[(T==null?void 0:T.length)>0&&e("div",{class:"profile-metadata",children:T.map(({name:q,value:ge,verifiedAt:be},ue)=>e("div",{class:`profile-field ${be?"profile-verified":""}`,dir:"auto",children:[e("b",{children:[e(Nn,{text:q,emojis:I})," ",!!be&&e(w,{icon:"check-circle",size:"s"})]}),e("p",{dangerouslySetInnerHTML:{__html:Pt(ge,{emojis:I})}})]},q+ue))}),e("div",{class:"stats",children:[e(Z,{tabIndex:0,to:ce,onClick:()=>{setTimeout(()=>{k.showGenericAccounts={heading:"Followers",fetchAccounts:Q,instance:o,excludeRelationshipAttrs:E?["followedBy"]:[]}},0)},children:[!!fe.length&&e("span",{class:"shazam-container-horizontal",children:e("span",{class:"shazam-container-inner stats-avatars-bunch",children:fe.map(q=>e(et,{url:q.avatarStatic,size:"s",alt:`${q.displayName} @${q.acct}`,squircle:q==null?void 0:q.bot}))})}),e("span",{title:x,children:Ue(x)})," ","Followers"]}),e(Z,{class:"insignificant",tabIndex:0,to:ce,onClick:()=>{setTimeout(()=>{k.showGenericAccounts={heading:"Following",fetchAccounts:V,instance:o,excludeRelationshipAttrs:E?["following"]:[]}},0)},children:[e("span",{title:L,children:Ue(L)})," ","Following",e("br",{})]}),e(Z,{class:"insignificant",to:ce,children:[e("span",{title:C,children:Ue(C)})," ","Posts"]}),!!y&&e("div",{class:"insignificant",children:["Joined"," ",e("time",{datetime:y,children:Ke(y,{hideTime:!0})})]})]})]}),!!de&&e(Z,{to:ce,class:"account-metadata-box",children:e("div",{class:"shazam-container",children:e("div",{class:"shazam-container-inner",children:ie?e("div",{class:"posting-stats",title:`${Math.round(de.originals/de.total*100)}% original posts, ${Math.round(de.replies/de.total*100)}% replies, ${Math.round(de.boosts/de.total*100)}% boosts`,children:[e("div",{children:de.daysSinceLastPost<365?`Last ${de.total} post${de.total>1?"s":""} in the past
+import{s as k,a as z,b as Ae,u as _n,c as pe,o as ms,I as w,M as Ce,d as se,A as et,N as It,e as Fe,f as Be,L as ee,g as at,h as En,l as gs,t as Qt,R as $t,i as bs,p as tt,j as He,k as Pn,m as Pt,E as Nn,n as Ue,q as Ke,r as ys,v as Ie,w as en,T as Dn,x as ht,y as Un,z as tn,B as ws,C as vs,D as Fn,F as Ee,G as Ss,S as Me,H as ks,J as Is,K as Ge,O as On,P as Nt,Q as Ts,U as rt,V as Bn,W as _e,X as zn,Y as Cs,Z as $s,_ as xs,$ as gt,a0 as As,a1 as nn,a2 as Ls,a3 as sn,a4 as on}from"./useTitle-60DQEO3r.js";import{_ as D,p as B,h as $,u as Re,w as ze,a as e,b as Se,g as A,s as xt,c as Ht,M as oe,d as De,e as lt,F as he,T as Ve,S as Ms,I as je,y as Je,f as qn,l as an,i as Hn,j as Vn,k as qe,A as Rs,N as _s,m as Es,q as Ps,J as Ns,C as Gn,n as Ds,o as nt,r as jn,t as Us,v as Fs,x as Os,z as pt,B as Yn,D as cn,E as Bs,R as Vt,G as Te,H as zs,K as qs}from"./vendor-jabuMAqb.js";function ct(t=()=>{},n=[]){const i=D(t);B(()=>{i.current=t},[n]),B(()=>{const o=()=>{const a=document.hidden||document.visibilityState==="hidden";i.current(!a)};return document.addEventListener("visibilitychange",o),()=>document.removeEventListener("visibilitychange",o)},[])}const Hs=1e3*3,Vs=15e3,Gs=ze(function({isLoggedIn:n}){const[i,o]=$(!0);ct(o);const a=async(l,c,d)=>{var h;if(k.notificationsLast){const r=l.v1.notifications.list({limit:1,sinceId:k.notificationsLast.id}),{value:p}=await r.next();if(p!=null&&p.length)if(d)k.notificationsShowNew=!0;else{let f;try{const b=await l.v1.markers.fetch({timeline:"notifications"});f=(h=b==null?void 0:b.notifications)==null?void 0:h.lastReadId}catch{}f?k.notificationsShowNew=p[0].id!==f:k.notificationsShowNew=!0}}};B(()=>{let l,c;if(n&&i){const{masto:d,streaming:h,instance:r}=z();(async()=>{await a(d,r);let p=!1;h&&(c=setTimeout(()=>{(async()=>{try{p=!0,l=h.user.notification.subscribe();for await(const f of l){if(!l||!i)break;f.event==="notification"&&Ae(f.payload,r,{skipThreading:!0}),k.notificationsShowNew=!0}}catch{p=!1}p||(c=setInterval(()=>{a(d,r,!0)},Vs))})()},Hs))})()}return()=>{var d;(d=l==null?void 0:l.unsubscribe)==null||d.call(l),l=null,clearTimeout(c),clearInterval(c)}},[i,n]);const s=D(),u=()=>{s.current=Date.now(),fetch("./version.json").then(l=>l.json()).then(l=>{l&&(k.appVersion=l)}).catch(l=>{})};return _n(u,i&&1e3*60*30),ct(l=>{l&&(s.current?Date.now()-s.current>1e3*60*60&&u():u())}),Re("shift+alt+k",()=>{const l=k.settings.cloakMode;k.settings.cloakMode=!l,pe({text:`Cloak mode ${l?"disabled":"enabled"}`})}),null});function js(){function t(n){n.shiftKey?ms()||(k.showCompose=!0):k.showCompose=!0}return Re("c, shift+c",t,{ignoreEventWhen:n=>!!document.querySelector("#modal-container > *")}),e("button",{type:"button",id:"compose-button",onClick:t,children:e(w,{icon:"quill",size:"xl",alt:"Compose"})})}const Ys=ze(function(){const n=Se(k);function i(){k.showKeyboardShortcutsHelp=!1}return Re("?, shift+?",o=>{k.showKeyboardShortcutsHelp=!0},{ignoreEventWhen:o=>!!document.querySelector("#modal-container > *")}),!!n.showKeyboardShortcutsHelp&&e(Ce,{class:"light",onClose:i,children:e("div",{id:"keyboard-shortcuts-help-container",class:"sheet",tabindex:"-1",children:[e("button",{type:"button",class:"sheet-close",onClick:i,children:e(w,{icon:"x"})}),e("header",{children:e("h2",{children:"Keyboard shortcuts"})}),e("main",{children:e("table",{children:[{action:"Keyboard shortcuts help",keys:e("kbd",{children:"?"})},{action:"Next post",keys:e("kbd",{children:"j"})},{action:"Previous post",keys:e("kbd",{children:"k"})},{action:"Skip carousel to next post",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"j"})]})},{action:"Skip carousel to previous post",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"k"})]})},{action:"Open post details",keys:e(A,{children:[e("kbd",{children:"Enter"})," or ",e("kbd",{children:"o"})]})},{action:e(A,{children:["Expand content warning or",e("br",{}),"toggle expanded/collapsed thread"]}),keys:e("kbd",{children:"x"})},{action:"Close post or dialogs",keys:e(A,{children:[e("kbd",{children:"Esc"})," or ",e("kbd",{children:"Backspace"})]})},{action:"Focus column in multi-column mode",keys:e(A,{children:[e("kbd",{children:"1"})," to ",e("kbd",{children:"9"})]})},{action:"Compose new post",keys:e("kbd",{children:"c"})},{action:"Compose new post (new window)",className:"insignificant",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"c"})]})},{action:"Send post",keys:e(A,{children:[e("kbd",{children:"Ctrl"})," + ",e("kbd",{children:"Enter"})," or ",e("kbd",{children:"⌘"})," +"," ",e("kbd",{children:"Enter"})]})},{action:"Search",keys:e("kbd",{children:"/"})},{action:"Reply",keys:e("kbd",{children:"r"})},{action:"Reply (new window)",className:"insignificant",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"r"})]})},{action:"Like (favourite)",keys:e(A,{children:[e("kbd",{children:"l"})," or ",e("kbd",{children:"f"})]})},{action:"Boost",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"b"})]})},{action:"Bookmark",keys:e("kbd",{children:"d"})},{action:"Toggle Cloak mode",keys:e(A,{children:[e("kbd",{children:"Shift"})," + ",e("kbd",{children:"Alt"})," + ",e("kbd",{children:"k"})]})}].map(({action:o,className:a,keys:s})=>e("tr",{children:[e("th",{class:a,children:o}),e("td",{children:s})]},o))})})]})})});function Ws({onClose:t}){const{masto:n}=z(),i=se.local.getJSON("accounts"),o=se.session.get("currentAccount"),a=i.length>1,[s,u]=xt(c=>c+1,0),[l]=Ht();return e("div",{id:"accounts-container",class:"sheet",tabIndex:"-1",children:[!!t&&e("button",{type:"button",class:"sheet-close",onClick:t,children:e(w,{icon:"x"})}),e("header",{class:"header-grid",children:e("h2",{children:"Accounts"})}),e("main",{children:e("section",{children:[e("ul",{class:"accounts-list",ref:l,children:i.map((c,d)=>{const h=c.info.id===o,r=d===0;return e("li",{children:[e("div",{children:[a&&e("span",{class:`current ${h?"is-current":""}`,children:e(w,{icon:"check-circle",alt:"Current"})}),e(et,{url:c.info.avatarStatic,size:"xxl",onDblClick:async()=>{if(h)try{const p=await n.v1.accounts.$select(c.info.id).fetch();c.info=p,se.local.setJSON("accounts",i),u()}catch{}}}),e(It,{account:a?{...c.info,acct:/@/.test(c.info.acct)?c.info.acct:`${c.info.acct}@${c.instanceURL}`}:c.info,showAcct:!0,onClick:()=>{h?k.showAccount=`${c.info.username}@${c.instanceURL}`:(se.session.set("currentAccount",c.info.id),location.reload())}})]}),e("div",{class:"actions",children:[r&&a&&e(A,{children:[e("span",{class:"tag",children:"Default"})," "]}),e(Fe,{align:"end",menuButton:e("button",{type:"button",title:"More",class:"plain more-button",children:e(w,{icon:"more",size:"l",alt:"More"})}),children:[e(oe,{onClick:()=>{k.showAccount=`${c.info.username}@${c.instanceURL}`},children:[e(w,{icon:"user"}),e("span",{children:"View profile…"})]}),e(De,{}),a&&e(oe,{disabled:r,onClick:()=>{i.splice(d,1),i.unshift(c),se.local.setJSON("accounts",i),u()},children:[e(w,{icon:"check-circle"}),e("span",{children:"Set as default"})]}),e(Be,{subMenu:!0,confirmLabel:e(A,{children:[e(w,{icon:"exit"}),e("span",{children:["Log out @",c.info.acct,"?"]})]}),disabled:!h,menuItemClassName:"danger",onClick:()=>{i.splice(d,1),se.local.setJSON("accounts",i),location.href=location.pathname||"/"},children:[e(w,{icon:"exit"}),e("span",{children:"Log out…"})]})]})]})]},c.info.id)})}),e("p",{children:e(ee,{to:"/login",class:"button plain2",onClick:t,children:[e(w,{icon:"plus"})," ",e("span",{children:"Add an existing account"})]})}),a&&e("p",{children:e("small",{children:["Note: ",e("i",{children:"Default"})," account will always be used for first load. Switched accounts will persist during the session."]})})]})})]})}const Gt="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20xml:space='preserve'%20fill-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%20clip-rule='evenodd'%20viewBox='0%200%2064%2064'%3e%3cpath%20fill='none'%20d='M0%200h63.994v63.994H0z'/%3e%3cpath%20fill='%23a4bff7'%20d='M37.774%2011.471c14.639%203.752%2019.034%2016.557%2015.889%2031.304-.696%203.261-2.563%206.661-6.356%208.693-3.204%201.717-8.07%202.537-15.338.55l-9.634-2.404C11.651%2046.992%208.378%2038.733%2010.027%2031.823c3.627-15.201%2015.543-23.48%2027.747-20.352Z'/%3e%3cpath%20fill='%23d8e7fe'%20d='M36.76%2015.429c12.289%203.15%2015.547%2014.114%2012.907%2026.493-.947%204.44-4.937%209.365-16.664%206.143l-9.684-2.417c-7.854-1.923-10.53-7.8-9.318-12.877%203.016-12.639%2012.611-19.943%2022.759-17.342Z'/%3e%3cpath%20fill='%236081e6'%20d='M27.471%2024.991c-1.457-.698-7.229%203.213-7.663%208.926-.182%202.39%204.55%203.237%205.071-.169.725-4.743%203.715-8.218%202.592-8.757Zm10.746%202.005c-2.083.327-.382%205.901-.595%2010.727-.123%202.8%204.388%203.464%204.703%202.011%201.098-5.073-2.066-13.058-4.108-12.738Z'/%3e%3c/svg%3e";function rn(t){const{masto:n}=z();return n.v1.push.subscription.create(t)}function Ks(){const{masto:t}=z();return t.v1.push.subscription.fetch()}function Zs(t){const{masto:n}=z();return n.v1.push.subscription.update(t)}function Js(){const{masto:t}=z();return t.v1.push.subscription.remove()}function At(){return"serviceWorker"in navigator&&"PushManager"in window}function Xs(){return navigator.serviceWorker.getRegistration()}async function jt(){const t=await Xs(),n=t?await t.pushManager.getSubscription():void 0;return{registration:t,subscription:n}}function Wn(t){const n="=".repeat((4-t.length%4)%4),i=`${t}${n}`.replace(/-/g,"+").replace(/_/g,"/"),o=window.atob(i),a=new Uint8Array(o.length);for(let s=0;s{f.preventDefault();const g=new FormData(o.current).get("theme"),v=document.documentElement;if(g==="auto"){v.classList.remove("is-light","is-dark");const m=document.querySelector('meta[data-theme-setting="manual"]');m&&(m.name=""),document.querySelectorAll('meta[data-theme-setting="auto"]').forEach(S=>{S.name="theme-color"})}else{v.classList.toggle("is-light",g==="light"),v.classList.toggle("is-dark",g==="dark");const m=document.querySelector('meta[data-theme-setting="manual"]');m&&(m.name="theme-color",m.content=g==="light"?m.dataset.themeLightColor:m.dataset.themeDarkColor),document.querySelectorAll('meta[data-theme-setting="auto"]').forEach(S=>{S.name=""})}document.querySelector('meta[name="color-scheme"]').setAttribute("content",g==="auto"?"dark light":g),g==="auto"?se.local.del("theme"):se.local.set("theme",g)},children:e("div",{class:"radio-group",children:[e("label",{children:[e("input",{type:"radio",name:"theme",value:"light",defaultChecked:i==="light"}),e("span",{children:"Light"})]}),e("label",{children:[e("input",{type:"radio",name:"theme",value:"dark",defaultChecked:i==="dark"}),e("span",{children:"Dark"})]}),e("label",{children:[e("input",{type:"radio",name:"theme",value:"auto",defaultChecked:i!=="light"&&i!=="dark"}),e("span",{children:"Auto"})]})]})})})]}),e("li",{children:[e("div",{children:e("label",{children:"Text size"})}),e("div",{class:"range-group",children:[e("span",{style:{fontSize:Qe[0]},children:"A"})," ",e("input",{type:"range",min:Qe[0],max:Qe[Qe.length-1],step:"1",value:l,list:"sizes",onChange:f=>{const b=parseInt(f.target.value,10);document.documentElement.style.setProperty("--text-size",`${b}px`),b===un?se.local.del("textSize"):se.local.set("textSize",f.target.value)}})," ",e("span",{style:{fontSize:Qe[Qe.length-1]},children:"A"}),e("datalist",{id:"sizes",children:Qe.map(f=>e("option",{value:f}))})]})]})]})}),r&&e(A,{children:[e("h3",{children:"Posting"}),e("section",{children:e("ul",{children:e("li",{children:[e("div",{children:e("label",{for:"posting-privacy-field",children:["Default visibility"," ",e(w,{icon:"cloud",alt:"Synced",class:"synced-icon"})]})}),e("div",{children:e("select",{id:"posting-privacy-field",value:c["posting:default:visibility"]||"public",onChange:f=>{const{value:b}=f.target;(async()=>{try{await h.v1.accounts.updateCredentials({source:{privacy:b}}),d({...c,"posting:default:visibility":b}),se.account.set("preferences",{...c,"posting:default:visibility":b})}catch{alert("Failed to update posting privacy")}})()},children:[e("option",{value:"public",children:"Public"}),e("option",{value:"unlisted",children:"Unlisted"}),e("option",{value:"private",children:"Followers only"})]})})]})})}),e("p",{class:"section-postnote",children:[e(w,{icon:"cloud",alt:"Synced",class:"synced-icon"})," ",e("small",{children:["Synced to your instance server's settings."," ",e("a",{href:`https://${p}/`,target:"_blank",rel:"noopener noreferrer",children:["Go to your instance (",p,") for more settings."]})]})]})]}),e("h3",{children:"Experiments"}),e("section",{children:e("ul",{children:[e("li",{children:e("label",{children:[e("input",{type:"checkbox",checked:n.settings.autoRefresh,onChange:f=>{k.settings.autoRefresh=f.target.checked}})," ","Auto refresh timeline posts"]})}),e("li",{children:e("label",{children:[e("input",{type:"checkbox",checked:n.settings.boostsCarousel,onChange:f=>{k.settings.boostsCarousel=f.target.checked}})," ","Boosts carousel"]})}),e("li",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.contentTranslation,onChange:f=>{const{checked:b}=f.target;k.settings.contentTranslation=b,b||(k.settings.contentTranslationTargetLanguage=null)}})," ","Post translation"]}),e("div",{class:`sub-section ${n.settings.contentTranslation?"":"more-insignificant"}`,children:[e("div",{children:e("label",{children:["Translate to"," ",e("select",{value:a||"",disabled:!n.settings.contentTranslation,onChange:f=>{k.settings.contentTranslationTargetLanguage=f.target.value||null},children:[e("option",{value:"",children:["System language (",u,")"]}),e("option",{disabled:!0,children:"──────────"}),Qt.map(f=>e("option",{value:f.code,children:f.name}))]})]})}),e("hr",{}),e("p",{class:"checkbox-fieldset",children:['Hide "Translate" button for',n.settings.contentTranslationHideLanguages.length>0&&e(A,{children:[" ","(",n.settings.contentTranslationHideLanguages.length,")"]}),":",e("div",{class:"checkbox-fields",children:Qt.map(f=>e("label",{children:[e("input",{type:"checkbox",checked:n.settings.contentTranslationHideLanguages.includes(f.code),onChange:b=>{const{checked:g}=b.target;g?k.settings.contentTranslationHideLanguages.push(f.code):k.settings.contentTranslationHideLanguages=n.settings.contentTranslationHideLanguages.filter(v=>v!==f.code)}})," ",f.name]}))})]}),e("p",{class:"insignificant",children:e("small",{children:["Note: This feature uses external translation services, powered by"," ",e("a",{href:"https://github.com/cheeaun/lingva-api",target:"_blank",rel:"noopener noreferrer",children:"Lingva API"})," ","&"," ",e("a",{href:"https://github.com/thedaviddelta/lingva-translate",target:"_blank",rel:"noopener noreferrer",children:"Lingva Translate"}),"."]})}),e("hr",{}),e("div",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.contentTranslationAutoInline,disabled:!n.settings.contentTranslation,onChange:f=>{k.settings.contentTranslationAutoInline=f.target.checked}})," ","Auto inline translation"]}),e("p",{class:"insignificant",children:e("small",{children:["Automatically show translation for posts in timeline. Only works for ",e("b",{children:"short"})," posts without content warning, media and poll."]})})]})]})]}),!!ni&&e("li",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.mediaAltGenerator,onChange:f=>{k.settings.mediaAltGenerator=f.target.checked}})," ","Image description generator"," ",e(w,{icon:"sparkles2",class:"more-insignificant"})]}),e("div",{class:"sub-section insignificant",children:e("small",{children:"Only for new images while composing new posts."})}),e("div",{class:"sub-section insignificant",children:e("small",{children:["Note: This feature uses external AI service, powered by"," ",e("a",{href:"https://github.com/cheeaun/img-alt-api",target:"_blank",rel:"noopener noreferrer",children:"img-alt-api"}),". May not work well. Only for images and in English."]})})]}),e("li",{children:[e("label",{children:[e("input",{type:"checkbox",checked:n.settings.cloakMode,onChange:f=>{k.settings.cloakMode=f.target.checked}})," ","Cloak mode"," ",e("span",{class:"insignificant",children:["(",e("samp",{children:"Text"})," → ",e("samp",{children:"████"}),")"]})]}),e("div",{class:"sub-section insignificant",children:e("small",{children:"Replace text as blocks, useful when taking screenshots, for privacy reasons."})})]}),r&&e("li",{children:e("button",{type:"button",class:"light",onClick:()=>{k.showDrafts=!0,k.showSettings=!1},children:"Unsent drafts"})})]})}),r&&e(ii,{onClose:t}),e("h3",{children:"About"}),e("section",{children:[e("div",{style:{display:"flex",flexWrap:"wrap",gap:8,lineHeight:1.25,alignItems:"center",marginTop:8},children:[e("img",{src:Gt,alt:"",width:"64",height:"64",style:{aspectRatio:"1/1",verticalAlign:"middle",background:"#b7cdf9",borderRadius:12}}),e("div",{children:[e("b",{children:"Phanpy"})," ",e("a",{href:"https://hachyderm.io/@phanpy",rel:"noopener noreferrer",onClick:f=>{f.preventDefault(),k.showAccount="phanpy@hachyderm.io"},children:"@phanpy"}),e("br",{}),e("a",{href:"https://github.com/cheeaun/phanpy",target:"_blank",rel:"noopener noreferrer",children:"Built"})," ","by"," ",e("a",{href:"https://mastodon.social/@cheeaun",rel:"noopener noreferrer",onClick:f=>{f.preventDefault(),k.showAccount="cheeaun@mastodon.social"},children:"@cheeaun"})]})]}),e("p",{children:[e("a",{href:"https://github.com/sponsors/cheeaun",target:"_blank",rel:"noopener noreferrer",children:"Sponsor"})," ","·"," ",e("a",{href:"https://www.buymeacoffee.com/cheeaun",target:"_blank",rel:"noopener noreferrer",children:"Donate"})," ","·"," ",e("a",{href:ti,target:"_blank",rel:"noopener noreferrer",children:"Privacy Policy"})]}),e("p",{children:[hn&&e(A,{children:[e("span",{class:"insignificant",children:"Site:"})," ",hn.replace(/https?:\/\//g,"").replace(/\/$/,""),e("br",{})]}),e("span",{class:"insignificant",children:"Version:"})," ",e("input",{type:"text",class:"version-string",readOnly:!0,size:"18",value:`${"2024-01-05T19:24:44.622Z".slice(0,10).replace(/-/g,".")}.32c53b8`,onClick:f=>{f.target.select();try{navigator.clipboard.writeText(f.target.value),pe("Version string copied")}catch{pe("Unable to copy version string")}}})," ",e("span",{class:"ib insignificant",children:["(",e("a",{href:"https://github.com/cheeaun/phanpy/commit/32c53b8",target:"_blank",rel:"noopener noreferrer",children:e($t,{datetime:new Date("2024-01-05T19:24:44.622Z")})}),")"]})]})]})]})]})}function ii({onClose:t}){if(!At())return null;const{instance:n}=z(),[i,o]=$("default"),a=D(),[s,u]=$(!1),[l,c]=$(!1),d=D();B(()=>{(async()=>{o("loading");try{const{subscription:r,backendSubscription:p}=await Qs();if(p!=null&&p.policy&&p.policy!=="none"){u(!0);const{alerts:f,policy:b}=p;d.current=b;const{elements:g}=a.current,v=g.namedItem(b);v&&(v.value=b),Object.keys(f).forEach(m=>{const y=g.namedItem(m);(y==null?void 0:y.type)==="checkbox"&&(y.checked=!0)})}o("default")}catch(r){/outside.*authorized/i.test(r.message)?c(!0):alert((r==null?void 0:r.message)||r),o("error")}})()},[]);const h=i==="loading";return e("form",{ref:a,onChange:()=>{const r=Object.fromEntries(new FormData(a.current)),p=!!r["policy-allow"],f={policy:r.policy,data:{alerts:{mention:!!r.mention,favourite:!!r.favourite,reblog:!!r.reblog,follow:!!r.follow,follow_request:!!r.followRequest,poll:!!r.poll,update:!!r.update,status:!!r.status}}};let b=0;Object.keys(f.data.alerts).forEach(v=>{f.data.alerts[v]?b++:delete f.data.alerts[v]});const g=d.current!==f.policy;p&&b>0?g?dn().then(()=>{ln(f)}).catch(v=>{alert("Failed to update subscription. Please try again.")}):ln(f).catch(v=>{alert("Failed to update subscription. Please try again.")}):dn().catch(v=>{alert("Failed to remove subscription. Please try again.")})},children:[e("h3",{children:"Push Notifications (beta)"}),e("section",{children:e("ul",{children:e("li",{children:[e("label",{children:[e("input",{type:"checkbox",disabled:h||l,name:"policy-allow",checked:s,onChange:async r=>{const{checked:p}=r.target;if(p){const f=await Notification.requestPermission();f==="granted"?u(!0):(u(!1),f==="denied"&&alert("Push notifications are blocked. Please enable them in your browser settings."))}else u(!1)}})," ","Allow from"," ",e("select",{name:"policy",disabled:h||l||!s,children:[{value:"all",label:"anyone"},{value:"followed",label:"people I follow"},{value:"follower",label:"followers"}].map(r=>e("option",{value:r.value,children:r.label}))})]}),e("div",{class:"shazam-container no-animation",style:{width:"100%"},hidden:!s,children:e("div",{class:"shazam-container-inner",children:e("div",{class:"sub-section",children:e("ul",{children:[{value:"mention",label:"Mentions"},{value:"favourite",label:"Likes"},{value:"reblog",label:"Boosts"},{value:"follow",label:"Follows"},{value:"followRequest",label:"Follow requests"},{value:"poll",label:"Polls"},{value:"update",label:"Post edits"},{value:"status",label:"New posts"}].map(r=>e("li",{children:e("label",{children:[e("input",{type:"checkbox",name:r.value})," ",r.label]})}))})})})}),l&&e("div",{class:"sub-section",children:e("p",{children:["Push permission was not granted since your last login. You'll need to"," ",e(ee,{to:`/login?instance=${n}`,onClick:t,children:[e("b",{children:"log in"})," again to grant push permission"]}),"."]})})]})})}),e("p",{class:"section-postnote",children:e("small",{children:["NOTE: Push notifications only work for ",e("b",{children:"one account"}),"."]})})]})}const Dt=()=>{let t=setTimeout(()=>{if(!document.getElementById("columns")){const i=document.querySelectorAll("#modal-container > *");if(i!=null&&i.length){const u=i[i.length-1],l=u.querySelector('[tabindex="-1"]')||u;if(l){l.focus();return}}if(document.querySelector(".deck-backdrop"))return;const a=document.querySelectorAll(".deck-container"),s=a[a.length-1];s&&s.tabIndex===-1&&s.focus()}},100);return()=>clearTimeout(t)};function Kn(t){if(!t)return;const n=lt(),i=D(n.pathname);B(()=>{i.current&&n.pathname!==i.current&&(t==null||t())},[n.pathname,t])}function Yt({list:t,onClose:n}){const{masto:i}=z(),[o,a]=$("default"),s=!!t,u=D(),l=D(),c=D();B(()=>{s&&(u.current.value=t.title,l.current.value=t.repliesPolicy,c.current&&(c.current.checked=t.exclusive))},[s]);const d=bs("@mastodon/list-exclusive");return e("div",{class:"sheet",children:[!!n&&e("button",{type:"button",class:"sheet-close",onClick:n,children:e(w,{icon:"x"})})," ",e("header",{children:e("h2",{children:s?"Edit list":"New list"})}),e("main",{children:e("form",{class:"list-form",onSubmit:h=>{h.preventDefault();const r=new FormData(h.target),p=r.get("title"),f=r.get("replies_policy"),b=r.get("exclusive")==="on";a("loading"),(async()=>{try{let g;s?g=await i.v1.lists.$select(t.id).update({title:p,replies_policy:f,exclusive:b}):g=await i.v1.lists.create({title:p,replies_policy:f,exclusive:b}),a("default"),n==null||n({state:"success",list:g})}catch{a("error"),alert(s?"Unable to edit list.":"Unable to create list.")}})()},children:[e("div",{class:"list-form-row",children:e("label",{for:"list-title",children:["Name"," ",e("input",{ref:u,type:"text",id:"list-title",name:"title",required:!0,disabled:o==="loading",dir:"auto"})]})}),e("div",{class:"list-form-row",children:e("select",{ref:l,name:"replies_policy",required:!0,disabled:o==="loading",children:[e("option",{value:"list",children:"Show replies to list members"}),e("option",{value:"followed",children:"Show replies to people I follow"}),e("option",{value:"none",children:"Don't show replies"})]})}),d&&e("div",{class:"list-form-row",children:e("label",{class:"label-block",children:[e("input",{ref:c,type:"checkbox",name:"exclusive",disabled:o==="loading"})," ","Hide posts on this list from Home/Following"]})}),e("div",{class:"list-form-footer",children:[e("button",{type:"submit",disabled:o==="loading",children:s?"Save":"Create"}),s&&e(Be,{disabled:o==="loading",align:"end",menuItemClassName:"danger",confirmLabel:"Delete this list?",onClick:()=>{a("loading"),(async()=>{try{await i.v1.lists.$select(t.id).remove(),a("default"),n==null||n({state:"deleted"})}catch{a("error"),alert("Unable to delete list.")}})()},children:e("button",{type:"button",class:"light danger",disabled:o==="loading",children:"Delete…"})})]})]})})]})}const oi=[60*5,60*30,60*60,60*60*6,60*60*24,60*60*24*3,60*60*24*7,0],fn={0:"Forever",300:"5 minutes",1800:"30 minutes",3600:"1 hour",21600:"6 hours",86400:"1 day",259200:"3 days",604800:"1 week"},pn=80,Zn=1e3*60*10;function ai(t,n){return n.v1.accounts.familiarFollowers.fetch({id:[t]})}const ci=tt(ai,{maxAge:Zn});async function ri(t,n){const i=n.v1.accounts.$select(t).statuses.list({limit:20}).next(),{value:o}=await i,a={total:o.length,originals:0,replies:0,boosts:0};return o.forEach(s=>{s.reblog?a.boosts++:s.inReplyToId&&s.inReplyToAccountId!==s.account.id?a.replies++:a.originals++}),o.length&&(a.daysSinceLastPost=Math.ceil((Date.now()-new Date(o[o.length-1].createdAt))/864e5)),a}const li=tt(ri,{maxAge:Zn});function Jn({account:t,fetchAccount:n=()=>{},standalone:i,instance:o,authenticated:a}){const{masto:s}=z({instance:o}),{masto:u,instance:l}=z(),[c,d]=$("default"),h=typeof t=="string",[r,p]=$(h?null:t),f=he(()=>o===l,[o,l]);B(()=>{if(!h){p(t);return}d("loading"),(async()=>{try{const q=await n();k.accounts[`${q.id}@${o}`]=q,p(q),d("default")}catch{p(null),d("error")}})()},[h,t,n]);const{acct:b,avatar:g,avatarStatic:v,bot:m,createdAt:y,displayName:S,emojis:I,fields:T,followersCount:x,followingCount:L,group:N,id:O,lastStatusAt:U,locked:P,note:M,statusesCount:C,url:_,username:F,memorial:Y,moved:te,roles:W}=r||{};let ke=!1,{header:re,headerStatic:X}=r||{};(!re||/missing\.png$/.test(re))&&g&&!/missing\.png$/.test(g)&&(re=g,ke=!0,v&&!/missing\.png$/.test(v)&&(X=v));const E=he(()=>O===se.session.get("currentAccount"),[O]);B(()=>{const q=!!(r!=null&&r.id&&(r!=null&&r.username)&&(r!=null&&r.acct)&&(r!=null&&r.avatar)&&(r!=null&&r.avatarStatic)&&(r!=null&&r.displayName)&&(r!=null&&r.url));if(E&&o&&q){const ge=se.local.getJSON("accounts");let be=!1;ge.forEach(ue=>{ue.info.id===r.id&&ue.instanceURL===o&&(ue.info=r,be=!0)}),be&&se.local.setJSON("accounts",ge)}},[E,r,o]);const j=he(()=>_?new URL(_).hostname:null,[_]),[ne,le]=$([]),H=D(),ae=D([]);async function Q(q){(q||!H.current)&&(H.current=s.v1.accounts.$select(O).followers.list({limit:pn}));const ge=await H.current.next();if(E||!f)return ge;const{value:be}=ge;let ue=[];if(q){const xe=await s.v1.accounts.familiarFollowers.fetch({id:[O]});ae.current=xe[0].accounts,ue=[...ae.current,...be.filter(Pe=>!ae.current.some(Ne=>Ne.id===Pe.id))]}else be!=null&&be.length&&(ue=be.filter(xe=>!ae.current.some(Pe=>Pe.id===xe.id)));return{...ge,value:ue}}const ye=D();async function V(q){return(q||!ye.current)&&(ye.current=s.v1.accounts.$select(O).following.list({limit:pn})),await ye.current.next()}const Z=i?"div":ee,ce=o?`/${o}/a/${O}`:`/a/${O}`,[fe,me]=$([]),[de,R]=$(),[G,K]=$("default"),ie=!!(de!=null&&de.total),we=async q=>{try{const ge=await ci(q,u);me(ge[0].accounts.slice(0,di))}catch{}},Le=async()=>{if(O){K("loading");try{const q=await li(O,s);R(q),K("default")}catch{K("error")}}},$e=Ve(({relationship:q,currentID:ge})=>{q.following||(we(ge),!i&&C>0&&Le())},[i,O,C]);return e("div",{tabIndex:"-1",class:`account-container ${c==="loading"?"skeleton":""}`,style:{"--header-color-1":ne[0],"--header-color-2":ne[1],"--header-color-3":ne[2],"--header-color-4":ne[3]},children:[c==="error"&&e("div",{class:"ui-state",children:[e("p",{children:"Unable to load account."}),e("p",{children:e("a",{href:h?t:_,target:"_blank",rel:"noopener noreferrer",children:["Go to account page ",e(w,{icon:"external"})]})})]}),c==="loading"?e(A,{children:[e("header",{children:e(He,{avatarSize:"xxxl",skeleton:!0})}),e("main",{children:[e("div",{class:"note",children:[e("p",{children:"███████ ████ ████"}),e("p",{children:"████ ████████ ██████ █████████ ████ ██"})]}),e("div",{class:"account-metadata-box",children:[e("div",{class:"profile-metadata",children:[e("div",{class:"profile-field",children:[e("b",{class:"more-insignificant",children:"███"}),e("p",{children:"██████"})]}),e("div",{class:"profile-field",children:[e("b",{class:"more-insignificant",children:"████"}),e("p",{children:"███████████"})]})]}),e("div",{class:"stats",children:[e("div",{children:[e("span",{children:"██"})," Followers"]}),e("div",{children:[e("span",{children:"██"})," Following"]}),e("div",{children:[e("span",{children:"██"})," Posts"]})]})]}),e("div",{class:"actions",children:[e("span",{}),e("span",{class:"buttons",children:e("button",{type:"button",title:"More",class:"plain",disabled:!0,children:e(w,{icon:"more",size:"l",alt:"More"})})})]})]})]}):r&&e(A,{children:[!!te&&e("div",{class:"account-moved",children:[e("p",{children:[e("b",{children:S})," has indicated that their new account is now:"]}),e(He,{account:te,instance:o,onClick:q=>{q.stopPropagation(),k.showAccount=te}})]}),!!re&&!/missing\.png$/.test(re)&&e("img",{src:re,alt:"",class:`header-banner ${ke?"header-is-avatar":""}`,onError:q=>{q.target.crossOrigin?q.target.src!==X?q.target.src=X:(q.target.removeAttribute("crossorigin"),q.target.src=re):q.target.src!==X?q.target.src=X:q.target.remove()},crossOrigin:"anonymous",onLoad:q=>{q.target.classList.add("loaded");try{const ge=document.createElement("canvas"),be=ge.getContext("2d",{willReadFrequently:!0});ge.width=q.target.width,ge.height=q.target.height,be.drawImage(q.target,0,0);const ue=10,Pe=[be.getImageData(0,0,ue,ue).data,be.getImageData(q.target.width-ue,0,ue,ue).data,be.getImageData(0,q.target.height-ue,ue,ue).data,be.getImageData(q.target.width-ue,q.target.height-ue,ue,ue).data].map(Ne=>{let st=0,Oe=0,We=0,Xe=0;for(let ve=0;ve{const[st,Oe,We,Xe]=hi(Ne);return`rgba(${st}, ${Oe}, ${We}, ${Xe})`});le(Pe)}catch{}}}),e("header",{children:e(He,{account:r,instance:o,avatarSize:"xxxl",external:i,internal:!i})}),e("div",{class:"faux-header-bg","aria-hidden":"true"}),e("main",{children:[!!Y&&e("span",{class:"tag",children:"In Memoriam"}),!!m&&e("span",{class:"tag",children:[e(w,{icon:"bot"})," Automated"]}),!!N&&e("span",{class:"tag",children:[e(w,{icon:"group"})," Group"]}),W==null?void 0:W.map(q=>e("span",{class:"tag",children:[q.name,!!j&&e(A,{children:[" ",e("span",{class:"more-insignificant",children:j})]})]})),e("div",{class:"note",dir:"auto",onClick:Pn({instance:l}),dangerouslySetInnerHTML:{__html:Pt(M,{emojis:I})}}),e("div",{class:"account-metadata-box",children:[(T==null?void 0:T.length)>0&&e("div",{class:"profile-metadata",children:T.map(({name:q,value:ge,verifiedAt:be},ue)=>e("div",{class:`profile-field ${be?"profile-verified":""}`,dir:"auto",children:[e("b",{children:[e(Nn,{text:q,emojis:I})," ",!!be&&e(w,{icon:"check-circle",size:"s"})]}),e("p",{dangerouslySetInnerHTML:{__html:Pt(ge,{emojis:I})}})]},q+ue))}),e("div",{class:"stats",children:[e(Z,{tabIndex:0,to:ce,onClick:()=>{setTimeout(()=>{k.showGenericAccounts={heading:"Followers",fetchAccounts:Q,instance:o,excludeRelationshipAttrs:E?["followedBy"]:[]}},0)},children:[!!fe.length&&e("span",{class:"shazam-container-horizontal",children:e("span",{class:"shazam-container-inner stats-avatars-bunch",children:fe.map(q=>e(et,{url:q.avatarStatic,size:"s",alt:`${q.displayName} @${q.acct}`,squircle:q==null?void 0:q.bot}))})}),e("span",{title:x,children:Ue(x)})," ","Followers"]}),e(Z,{class:"insignificant",tabIndex:0,to:ce,onClick:()=>{setTimeout(()=>{k.showGenericAccounts={heading:"Following",fetchAccounts:V,instance:o,excludeRelationshipAttrs:E?["following"]:[]}},0)},children:[e("span",{title:L,children:Ue(L)})," ","Following",e("br",{})]}),e(Z,{class:"insignificant",to:ce,children:[e("span",{title:C,children:Ue(C)})," ","Posts"]}),!!y&&e("div",{class:"insignificant",children:["Joined"," ",e("time",{datetime:y,children:Ke(y,{hideTime:!0})})]})]})]}),!!de&&e(Z,{to:ce,class:"account-metadata-box",children:e("div",{class:"shazam-container",children:e("div",{class:"shazam-container-inner",children:ie?e("div",{class:"posting-stats",title:`${Math.round(de.originals/de.total*100)}% original posts, ${Math.round(de.replies/de.total*100)}% replies, ${Math.round(de.boosts/de.total*100)}% boosts`,children:[e("div",{children:de.daysSinceLastPost<365?`Last ${de.total} post${de.total>1?"s":""} in the past
${de.daysSinceLastPost} day${de.daysSinceLastPost>1?"s":""}`:`
Last ${de.total} posts in the past year(s)
`}),e("div",{class:"posting-stats-bar",style:{"--originals-percentage":`${de.originals/de.total*100}%`,"--replies-percentage":`${(de.originals+de.replies)/de.total*100}%`}}),e("div",{class:"posting-stats-legends",children:[e("span",{class:"ib",children:[e("span",{class:"posting-stats-legend-item posting-stats-legend-item-originals"})," ","Original"]})," ",e("span",{class:"ib",children:[e("span",{class:"posting-stats-legend-item posting-stats-legend-item-replies"})," ","Replies"]})," ",e("span",{class:"ib",children:[e("span",{class:"posting-stats-legend-item posting-stats-legend-item-boosts"})," ","Boosts"]})]})]}):e("div",{class:"posting-stats",children:"Post stats unavailable."})})})}),e("div",{class:"account-metadata-box",children:e("div",{class:"shazam-container no-animation",hidden:!!de,children:e("div",{class:"shazam-container-inner",children:e("button",{type:"button",class:"posting-stats-button",disabled:G==="loading",onClick:()=>{Le()},children:[e("div",{class:`posting-stats-bar posting-stats-icon ${G==="loading"?"loading":""}`,style:{"--originals-percentage":"33%","--replies-percentage":"66%"}}),"View post stats"," "]})})})})]}),e("footer",{children:e(ui,{info:r,instance:o,authenticated:a,onRelationshipChange:$e})})]})]})}const di=3;function ui({info:t,instance:n,authenticated:i,onRelationshipChange:o=()=>{}}){var ye;if(!t)return null;const{masto:a,instance:s,authenticated:u}=z(),l=n===s,[c,d]=$("default"),[h,r]=$(null),{id:p,acct:f,url:b,username:g,locked:v,lastStatusAt:m,note:y,fields:S,moved:I}=t,T=D(p),{following:x,showingReblogs:L,notifying:N,followedBy:O,blocking:U,blockedBy:P,muting:M,mutingNotifications:C,requested:_,domainBlocking:F,endorsed:Y,note:te}=h||{},[W,ke]=$(null),[re,X]=$(!1);B(()=>{if(t){const V=se.session.get("currentAccount");let Z;(async()=>{if(l&&i)Z=p;else if(!l&&u){const fe=t.acct.includes("@");try{const me=await a.v2.search.fetch({q:fe?t.acct:`${t.username}@${n}`,type:"accounts",limit:1,resolve:!0});me.accounts.length&&(Z=me.accounts[0].id,ke(me.accounts[0]))}catch{}}if(!Z)return;if(V===Z){X(!0);return}if(T.current=Z,I)return;d("loading");const ce=a.v1.accounts.relationships.fetch({id:[Z]});try{const fe=await ce;if(d("default"),fe.length){const me=fe[0];r(me),o({relationship:me,currentID:Z})}}catch{d("error")}})()}},[t,i]),B(()=>{t&&re&&ys(t)},[t,re]);const E=c==="loading",[j,ne]=$(!1),[le,H]=$(!1),[ae,Q]=$(!1);return e(A,{children:[e("div",{class:"actions",children:[e("span",{children:[O?e("span",{class:"tag",children:"Follows you"}):m?e("small",{class:"insignificant",children:["Last post:"," ",e("span",{class:"ib",children:Ke(m,{hideTime:!0})})]}):e("span",{}),M&&e("span",{class:"tag danger",children:"Muted"}),U&&e("span",{class:"tag danger",children:"Blocked"})]})," ",e("span",{class:"buttons",children:[!!te&&e("button",{type:"button",class:"private-note-tag",title:"Private note",onClick:()=>{Q(!0)},dir:"auto",children:e("span",{children:te})}),e(Fe,{portal:{target:document.body},containerProps:{style:{zIndex:1001}},align:"center",position:"anchor",overflow:"auto",menuButton:e("button",{type:"button",title:"More",class:"plain",disabled:E,children:e(w,{icon:"more",size:"l",alt:"More"})}),children:[u&&!re&&e(A,{children:[e(oe,{onClick:()=>{k.showCompose={draftStatus:{status:`@${(W==null?void 0:W.acct)||f} `}}},children:[e(w,{icon:"at"}),e("span",{children:["Mention @",g]})]}),e(oe,{onClick:()=>{ne(!0)},children:[e(w,{icon:"translate"}),e("span",{children:"Translate bio"})]}),e(oe,{onClick:()=>{Q(!0)},children:[e(w,{icon:"pencil"}),e("span",{children:te?"Edit private note":"Add private note"})]}),x&&e(oe,{onClick:()=>{H(!0)},children:[e(w,{icon:"list"}),e("span",{children:"Add/remove from Lists"})]}),e(De,{})]}),e(oe,{href:b,target:"_blank",children:[e(w,{icon:"external"}),e("small",{class:"menu-double-lines",children:fi(b)})]}),e("div",{class:"menu-horizontal",children:[e(oe,{onClick:()=>{try{navigator.clipboard.writeText(b),pe("Link copied")}catch{pe("Unable to copy link")}},children:[e(w,{icon:"link"}),e("span",{children:"Copy"})]}),(navigator==null?void 0:navigator.share)&&((ye=navigator==null?void 0:navigator.canShare)==null?void 0:ye.call(navigator,{url:b}))&&e(oe,{onClick:()=>{try{navigator.share({url:b})}catch{alert("Sharing doesn't seem to work.")}},children:[e(w,{icon:"share"}),e("span",{children:"Share…"})]})]}),!!h&&e(A,{children:[e(De,{}),M?e(oe,{onClick:()=>{d("loading"),(async()=>{try{const V=await a.v1.accounts.$select((W==null?void 0:W.id)||p).unmute();r(V),d("default"),pe(`Unmuted @${g}`),k.reloadGenericAccounts.id="mute",k.reloadGenericAccounts.counter++}catch{d("error")}})()},children:[e(w,{icon:"unmute"}),e("span",{children:["Unmute @",g]})]}):e(Ms,{openTrigger:"clickOnly",direction:"bottom",overflow:"auto",shift:16,label:e(A,{children:[e(w,{icon:"mute"}),e("span",{class:"menu-grow",children:["Mute @",g,"…"]}),e("span",{style:{textOverflow:"clip"},children:[e(w,{icon:"time"}),e(w,{icon:"chevron-right"})]})]}),children:e("div",{class:"menu-wrap",children:oi.map(V=>e(oe,{onClick:()=>{d("loading"),(async()=>{try{const Z=await a.v1.accounts.$select((W==null?void 0:W.id)||p).mute({duration:V});r(Z),d("default"),pe(`Muted @${g} for ${fn[V]}`),k.reloadGenericAccounts.id="mute",k.reloadGenericAccounts.counter++}catch{d("error"),pe(`Unable to mute @${g}`)}})()},children:fn[V]}))})}),e(Be,{subMenu:!0,confirm:!U,confirmLabel:e(A,{children:[e(w,{icon:"block"}),e("span",{children:["Block @",g,"?"]})]}),menuItemClassName:"danger",onClick:()=>{d("loading"),(async()=>{try{if(U){const V=await a.v1.accounts.$select((W==null?void 0:W.id)||p).unblock();r(V),d("default"),pe(`Unblocked @${g}`)}else{const V=await a.v1.accounts.$select((W==null?void 0:W.id)||p).block();r(V),d("default"),pe(`Blocked @${g}`)}k.reloadGenericAccounts.id="block",k.reloadGenericAccounts.counter++}catch{d("error"),U?pe(`Unable to unblock @${g}`):pe(`Unable to block @${g}`)}})()},children:U?e(A,{children:[e(w,{icon:"unblock"}),e("span",{children:["Unblock @",g]})]}):e(A,{children:[e(w,{icon:"block"}),e("span",{children:["Block @",g,"…"]})]})})]})]}),!h&&c==="loading"&&e(Ie,{abrupt:!0}),!!h&&e(Be,{confirm:x||_,confirmLabel:e("span",{children:_?"Withdraw follow request?":`Unfollow @${t.acct||t.username}?`}),menuItemClassName:"danger",align:"end",disabled:E,onClick:()=>{d("loading"),(async()=>{try{let V;x||_?V=await a.v1.accounts.$select(T.current).unfollow():V=await a.v1.accounts.$select(T.current).follow(),V&&r(V),d("default")}catch(V){alert(V),d("error")}})()},children:e("button",{type:"button",class:`${x||_?"light swap":""}`,"data-swap-state":x||_?"danger":"",disabled:E,children:x?e(A,{children:[e("span",{children:"Following"}),e("span",{children:"Unfollow…"})]}):_?e(A,{children:[e("span",{children:"Requested"}),e("span",{children:"Withdraw…"})]}):v?e(A,{children:[e(w,{icon:"lock"})," ",e("span",{children:"Follow"})]}):"Follow"})})]})]}),!!j&&e(Ce,{class:"light",onClose:()=>{ne(!1)},children:e(pi,{note:y,fields:S,onClose:()=>ne(!1)})}),!!le&&e(Ce,{class:"light",onClose:()=>{H(!1)},children:e(mi,{accountID:T.current,onClose:()=>H(!1)})}),!!ae&&e(Ce,{class:"light",onClose:()=>{Q(!1)},children:e(gi,{account:t,note:te,onRelationshipChange:V=>{r(V)},onClose:()=>Q(!1)})})]})}function hi([t,n,i]){const o=.2126*t+.7152*n+.0722*i;let a;return o>=220?a=1:o<=50?a=.1:a=o/255,a=Math.min(1,a),[t,n,i,a]}function fi(t){if(!t)return;const n=new URL(t),{host:i,pathname:o}=n,a=o.replace(/\/$/,"").replace(/^\//,"");return e(A,{children:[e("span",{class:"more-insignificant",children:[i,"/"]}),e("wbr",{}),e("span",{children:a})]})}function pi({note:t,fields:n,onClose:i}){const o=(n==null?void 0:n.map(({name:s,value:u})=>`${s}
@@ -18,5 +18,5 @@ ${o}`:"");return e("div",{class:"sheet",children:[!!i&&e("button",{type:"button"
${me?"filtered":""}
${de?"has-spoiler":""}
${G?"show-media":""}
- `,children:e(Fn,{class:t,media:ie,lang:_,to:`/${o}/s/${y}?media-only=${we+1}`,onClick:s?q=>s(q,we,ie,i):void 0})},Le)})}const vn=ze(Ji);function mt(t){var S,I,T,x,L;const n=Se(k),{masto:i,instance:o,authenticated:a}=z(),[s,u]=$(),[l,c]=$(!1);B(()=>{const N=se.local.getJSON("accounts")||[],O=N.find(U=>U.info.id===se.session.get("currentAccount"));O&&u(O),c(N.length>1)},[]);const d=(n.settings.shortcutsViewMode==="multi-column"||!n.settings.shortcutsViewMode&&n.settings.shortcutsColumnsMode)&&!n.shortcuts.find(N=>N.type==="following"),h=Ns(()=>{k.showAccounts=!0},{threshold:600,detect:"touch",cancelOnMovement:!0}),r=D(),[p,f]=$(void 0),b=Ts([0,0,n.settings.shortcutsViewMode==="tab-menu-bar"?50:0,0]),g=D();async function v(N){return(N||!g.current)&&(g.current=i.v1.mutes.list({limit:80})),await g.current.next()}const m=D();async function y(N){return(N||!m.current)&&(m.current=i.v1.blocks.list({limit:80})),await m.current.next()}return e(A,{children:[e("button",{ref:r,type:"button",class:`button plain nav-menu-button ${l?"with-avatar":""} ${open?"active":""}`,style:{position:"relative"},onClick:()=>{f(N=>N?void 0:"open")},onContextMenu:N=>{N.preventDefault(),k.showAccounts=!0},...h(),children:[l&&e(et,{url:((S=s==null?void 0:s.info)==null?void 0:S.avatar)||((I=s==null?void 0:s.info)==null?void 0:I.avatarStatic),size:"l",squircle:(T=s==null?void 0:s.info)==null?void 0:T.bot}),e(w,{icon:"menu",size:l?"s":"l"})]}),e(Gn,{menuClassName:"nav-menu",state:p,anchorRef:r,onClose:()=>{f(void 0)},containerProps:{style:{zIndex:10},onClick:()=>{f(void 0)}},portal:{target:document.body},...t,overflow:"auto",viewScroll:"close",position:"anchor",align:"center",boundingBoxPadding:b,unmountOnClose:!0,children:[!!((x=n.appVersion)!=null&&x.commitHash)&&n.appVersion.commitHash!=="adf0b35"&&e("div",{class:"top-menu",children:[e(oe,{onClick:()=>{confirm("Reload page now to update?")&&(async()=>{try{location.reload()}catch{}})()},children:[e(w,{icon:"sparkles",class:"sparkle-icon",size:"l"})," ",e("span",{children:"New update available…"})]}),e(De,{})]}),e("section",{children:[e(Ee,{to:"/",children:[e(w,{icon:"home",size:"l"})," ",e("span",{children:"Home"})]}),a&&e(A,{children:[d&&e(Ee,{to:"/following",children:[e(w,{icon:"following",size:"l"})," ",e("span",{children:"Following"})]}),e(Ee,{to:"/mentions",children:[e(w,{icon:"at",size:"l"})," ",e("span",{children:"Mentions"})]}),e(Ee,{to:"/notifications",children:[e(w,{icon:"notification",size:"l"})," ",e("span",{children:"Notifications"}),n.notificationsShowNew&&e("sup",{title:"New",style:{opacity:.5},children:[" ","•"]})]}),e(De,{}),e(Ee,{to:"/l",children:[e(w,{icon:"list",size:"l"})," ",e("span",{children:"Lists"})]}),e(Ee,{to:"/ft",children:[e(w,{icon:"hashtag",size:"l"})," ",e("span",{children:"Followed Hashtags"})]}),e(Ee,{to:"/b",children:[e(w,{icon:"bookmark",size:"l"})," ",e("span",{children:"Bookmarks"})]}),e(Ee,{to:"/f",children:[e(w,{icon:"heart",size:"l"})," ",e("span",{children:"Likes"})]})]}),e(De,{}),e(Ee,{to:"/search",children:[e(w,{icon:"search",size:"l"})," ",e("span",{children:"Search"})]}),e(Ee,{to:`/${o}/p/l`,children:[e(w,{icon:"building",size:"l"})," ",e("span",{children:"Local"})]}),e(Ee,{to:`/${o}/p`,children:[e(w,{icon:"earth",size:"l"})," ",e("span",{children:"Federated"})]}),e(Ee,{to:`/${o}/trending`,children:[e(w,{icon:"chart",size:"l"})," ",e("span",{children:"Trending"})]})]}),e("section",{children:a?e(A,{children:[e(De,{}),((L=s==null?void 0:s.info)==null?void 0:L.id)&&e(Ee,{to:`/${o}/a/${s.info.id}`,children:[e(w,{icon:"user",size:"l"})," ",e("span",{children:"Profile"})]}),e(oe,{onClick:()=>{k.showAccounts=!0},children:[e(w,{icon:"group",size:"l"})," ",e("span",{children:"Accounts…"})]}),e(oe,{onClick:()=>{k.showGenericAccounts={id:"mute",heading:"Muted users",fetchAccounts:v,excludeRelationshipAttrs:["muting"]}},children:[e(w,{icon:"mute",size:"l"})," Muted users…"]}),e(oe,{onClick:()=>{k.showGenericAccounts={id:"block",heading:"Blocked users",fetchAccounts:y,excludeRelationshipAttrs:["blocking"]}},children:[e(w,{icon:"block",size:"l"}),"Blocked users…"]}),e(De,{className:"divider-grow"}),e(oe,{onClick:()=>{k.showKeyboardShortcutsHelp=!0},children:[e(w,{icon:"keyboard",size:"l"})," ",e("span",{children:"Keyboard shortcuts"})]}),e(oe,{onClick:()=>{k.showShortcutsSettings=!0},children:[e(w,{icon:"shortcut",size:"l"})," ",e("span",{children:"Shortcuts / Columns…"})]}),e(oe,{onClick:()=>{k.showSettings=!0},children:[e(w,{icon:"gear",size:"l"})," ",e("span",{children:"Settings…"})]})]}):e(A,{children:[e(De,{}),e(Ee,{to:"/login",children:[e(w,{icon:"user",size:"l"})," ",e("span",{children:"Log in"})]}),e(oe,{onClick:()=>{k.showSettings=!0},children:[e(w,{icon:"gear",size:"l"})," ",e("span",{children:"Settings…"})]})]})})]})]})}const bt={block:"nearest",inline:"center",behavior:"smooth"};function Ye({title:t,titleComponent:n,id:i,instance:o,emptyText:a,errorText:s,useItemID:u,boostsCarousel:l,fetchItems:c=()=>{},checkForUpdates:d=()=>{},checkForUpdatesInterval:h=15e3,headerStart:r,headerEnd:p,timelineStart:f,refresh:b,view:g,filterContext:v,showFollowedTags:m}){const y=Se(k),[S,I]=$([]),[T,x]=$("default"),[L,N]=$(!1),[O,U]=$(!1),[P,M]=$(!0),C=D(),_=g!=="media",F=Ds(H=>{U(!1),T!=="loading"&&(x("loading"),(async()=>{try{let{done:ae,value:Q}=await c(H);if(Array.isArray(Q)){const[ye,V]=Q.reduce((Z,ce)=>(ce._pinned?Z[0].push(ce):Z[1].push(ce),Z),[[],[]]);Q=V,_&&(l&&(Q=Gi(Q)),Q=ji(Q)),ye.length&&(Q=ye.concat(Q)),I(H?Q:Z=>[...Z,...Q]),Q.length||(ae=!0),N(!ae)}else N(!1);x("default")}catch{x("error")}finally{F.cancel()}})())},1500,{leading:!0,trailing:!1}),Y=".timeline-item, .timeline-item-alt",te=Re("j, shift+j",(H,ae)=>{const Q=document.activeElement.closest(Y),ye=Q==null?void 0:Q.getBoundingClientRect(),V=Array.from(C.current.querySelectorAll(Y));if(Q&&ye.top0){const Z=V.indexOf(Q);let ce=V[Z+1];ae.shift&&(ce=V.find((fe,me)=>me>Z&&!fe.classList.contains("timeline-item-alt"))),ce&&(ce.focus(),ce.scrollIntoView(bt))}else{const Z=V.find(ce=>{const fe=ce.getBoundingClientRect();return fe.top>=44&&fe.left>=0});Z&&(Z.focus(),Z.scrollIntoView(bt))}}),W=Re("k, shift+k",(H,ae)=>{const Q=document.activeElement.closest(Y),ye=Q==null?void 0:Q.getBoundingClientRect(),V=Array.from(C.current.querySelectorAll(Y));if(Q&&ye.top0){const Z=V.indexOf(Q);let ce=V[Z-1];ae.shift&&(ce=V.findLast((fe,me)=>me{const fe=ce.getBoundingClientRect();return fe.top>=44&&fe.left>=0});Z&&(Z.focus(),Z.scrollIntoView(bt))}}),ke=Re(["enter","o"],()=>{const H=document.activeElement.closest(Y);H&&H.click()}),re=D(),[X,E]=$(!1);Zi({scrollableRef:C,distanceFromEnd:2,scrollThresholdStart:44},({scrollDirection:H,nearReachStart:ae,nearReachEnd:Q,reachStart:ye,reachEnd:V})=>{if(re.current){const Z=H==="end"&&!ae;re.current.hidden=Z}E(ae),ye&&F(!0)},[]),B(()=>{var H;(H=C.current)==null||H.scrollTo({top:0}),F(!0)},[]),B(()=>{F(!0)},[b]);const j=D(g);B(()=>{j.current!==g&&(j.current=g,I([]))},[g]);const ne=Ve(async({disableIdleCheck:H=!1}={})=>{const ae=C.current?getComputedStyle(C.current).pointerEvents==="none":!1;y.settings.autoRefresh&&C.current.scrollTop<16&&(H||window.__IDLE__)&&!to()&&!ae?F(!0):await d()&&U(!0)},[i,F,d,y.settings.autoRefresh]),le=D();return ct(H=>{if(H){const ae=Date.now()-le.current;(!le.current||ae>1e3*3)&&ne({disableIdleCheck:!0})}else le.current=Date.now();M(H)},[d,ne,y.settings.autoRefresh]),_n(ne,P&&!O?h*(X?1:2):null),e(On.Provider,{value:v,children:e("div",{id:`${i}-page`,class:"deck-container",ref:H=>{C.current=H,te.current=H,W.current=H,ke.current=H},tabIndex:"-1",children:e("div",{class:"timeline-deck deck",children:[e("header",{ref:re,onClick:H=>{var ae;H.target.closest("a, button")||(ae=C.current)==null||ae.scrollTo({top:0,behavior:"smooth"})},onDblClick:H=>{H.target.closest("a, button")||F(!0)},class:T==="loading"?"loading":"",children:[e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),r??e(ee,{to:"/",class:"button plain home-button",children:e(w,{icon:"home",size:"l"})})]}),t&&(n||e("h1",{children:t})),e("div",{class:"header-side",children:!!p&&p})]}),S.length>0&&T!=="loading"&&O&&e("button",{class:"updates-button shiny-pill",type:"button",onClick:()=>{var H;F(!0),(H=C.current)==null||H.scrollTo({top:0,behavior:"smooth"})},children:[e(w,{icon:"arrow-up"})," New posts"]})]}),!!f&&e("div",{class:`timeline-start ${T==="loading"?"loading":""}`,children:f}),S.length?e(A,{children:[e("ul",{class:`timeline ${g?`timeline-${g}`:""}`,children:[S.map(H=>e(Xi,{status:H,instance:o,useItemID:u,filterContext:v,view:g,showFollowedTags:m},H.id+(H==null?void 0:H._pinned)+g)),L&&T==="loading"&&(g==="media"?null:e(A,{children:[e("li",{style:{height:"20vh"},children:e(Me,{skeleton:!0})}),e("li",{style:{height:"25vh"},children:e(Me,{skeleton:!0})})]}))]}),T==="default"&&(L?e(je,{root:C.current,rootMargin:`0px 0px ${screen.height*1.5}px 0px`,onChange:H=>{H&&F()},children:e("button",{type:"button",class:"plain block",onClick:()=>F(),style:{marginBlockEnd:"6em"},children:"Show more…"})}):e("p",{class:"ui-state insignificant",children:"The end."}))]}):T==="loading"?e("ul",{class:"timeline",children:Array.from({length:5}).map((H,ae)=>g==="media"?e("div",{style:{height:"50vh"}}):e("li",{children:e(Me,{skeleton:!0})},ae))}):T!=="error"&&e("p",{class:"ui-state",children:a}),T==="error"&&e("p",{class:"ui-state",children:[s,e("br",{}),e("br",{}),e("button",{type:"button",onClick:()=>F(!S.length),children:"Try again"})]})]})})})}function Xi({status:t,instance:n,useItemID:i,filterContext:o,view:a,showFollowedTags:s}){const{id:u,reblog:l,items:c,type:d,_pinned:h}=t;h&&(i=!1);const r=(l==null?void 0:l.id)||u,p=n?`/${n}/s/${r}`:`/s/${r}`;let f="";d==="boosts"?f=`${c.length} Boosts`:d==="pinned"&&(f="Pinned posts");const b=d==="boosts"||d==="pinned";if(c){const v=rt(c,o);if(b)return v.sort((y,S)=>{const I=Nt(y.filtered,o),T=Nt(S.filtered,o);return I&&!T?1:!I&&T?-1:0}),e("li",{class:"timeline-item-carousel",children:e(Qi,{title:f,class:`${d}-carousel`,children:v.map(y=>{const{id:S,reblog:I,_pinned:T}=y,x=(I==null?void 0:I.id)||S,L=n?`/${n}/s/${x}`:`/s/${x}`;return T&&(i=!1),e("li",{children:e(ee,{class:"status-carousel-link timeline-item-alt",to:L,children:i?e(Me,{statusID:S,instance:n,size:"s",contentTextWeight:!0,enableCommentHint:!0}):e(Me,{status:y,instance:n,size:"s",contentTextWeight:!0,enableCommentHint:!0})})},S)})})},`timeline-${u}`);const m=v.length>3;return v.map((y,S)=>{const{id:I,_differentAuthor:T}=y,x=n?`/${n}/s/${I}`:`/s/${I}`,L=S>0&&S0||m&&L&&(d==="thread"||d==="conversation"&&!T&&!v[S-1]._differentAuthor&&!v[S+1]._differentAuthor),U=S===0,P=S===v.length-1;return e("li",{class:`timeline-item-container timeline-item-container-type-${d} timeline-item-container-${U?"start":P?"end":"middle"} ${T?"timeline-item-diff-author":""}`,children:e(ee,{class:"status-link timeline-item",to:x,children:O?e(eo,{status:y,instance:n}):i?e(Me,{statusID:I,instance:n,enableCommentHint:P,showFollowedTags:s}):e(Me,{status:y,instance:n,enableCommentHint:P,showFollowedTags:s})})},`timeline-${I}`)})}const g=`timeline-${u+h}`;return a==="media"?i?e(vn,{class:"timeline-item",parent:"li",statusID:u,instance:n},g):e(vn,{class:"timeline-item",parent:"li",status:t,instance:n},g):e("li",{children:e(ee,{class:"status-link timeline-item",to:p,children:i?e(Me,{statusID:u,instance:n,enableCommentHint:!0,showFollowedTags:s}):e(Me,{status:t,instance:n,enableCommentHint:!0,showFollowedTags:s})})},g)}function Qi({title:t,class:n,children:i}){const o=D(),a=D(),s=D(),[u,l]=$(!1);return B(()=>{setTimeout(()=>{l(!0)},1)},[]),e("div",{class:`status-carousel ${n}`,children:[e("header",{children:[e("h3",{children:t}),e("span",{children:[e("button",{ref:a,type:"button",class:"small plain2",onClick:()=>{var c,d;(d=o.current)==null||d.scrollBy({left:-Math.min(320,(c=o.current)==null?void 0:c.offsetWidth),behavior:"smooth"})},children:e(w,{icon:"chevron-left"})})," ",e("button",{ref:s,type:"button",class:"small plain2",onClick:()=>{var c,d;(d=o.current)==null||d.scrollBy({left:Math.min(320,(c=o.current)==null?void 0:c.offsetWidth),behavior:"smooth"})},children:e(w,{icon:"chevron-right"})})]})]}),e("ul",{ref:o,children:[e(je,{class:"status-carousel-beacon",onChange:c=>{a.current&&(a.current.disabled=c)}}),i[0],u&&i.slice(1),e(je,{class:"status-carousel-beacon",onChange:c=>{s.current&&(s.current.disabled=c)}})]})]})}function eo({status:t,instance:n}){const i=Se(k),{id:o,visibility:a}=t,s=Bn(t),u=Ge(o,n);return e("article",{class:`status compact-thread ${a==="direct"?"visibility-direct":""}`,tabindex:"-1",children:[i.statusThreadNumber[u]?e("div",{class:"status-thread-badge",children:[e(w,{icon:"thread",size:"s"}),i.statusThreadNumber[u]?` ${i.statusThreadNumber[u]}/X`:""]}):e("div",{class:"status-thread-badge",children:e(w,{icon:"thread",size:"s"})}),e("div",{class:"content-compact",title:s,children:[s,t.sensitive&&t.spoilerText&&e(A,{children:[" ",e("span",{class:"spoiler-badge",children:e(w,{icon:"eye-close",size:"s"})})]})]})]})}function to(){return!!document.querySelector(".deck-backdrop, #modal-container > *")}const ot=20,Zt=1983,Sn=`${Zt}-01`,no=(()=>{try{const t=document.createElement("input");return t.setAttribute("type","month"),t.type==="month"}catch{return!1}})();async function so(t){var o;const{masto:n}=z({instance:t}),i=await n.v2.search.fetch({q:"from:me",type:"statuses",limit:1});return!!((o=i==null?void 0:i.statuses)!=null&&o.length)}const io=tt(so);function oo(){const t=Se(k),{id:n,...i}=nt(),[o,a]=qe(),s=o.get("month"),u=!o.get("replies"),l=!!o.get("boosts"),c=o.get("tagged"),d=!!o.get("media"),{masto:h,instance:r,authenticated:p}=z({instance:i.instance}),{masto:f,instance:b}=z(),g=D(),v=[s,u,l,c,d],[m,y]=$(),S=D(0);B(()=>{S.current=0},v);const I=he(()=>r===b,[r,b]),[T,x]=$(!1);B(()=>{I&&m!=null&&m.acct&&(async()=>{const X=await io(r);x(X)})()},[r,I,m==null?void 0:m.acct]);async function L(X){var ae,Q,ye;const E=/^\d{4}-[01]\d$/.test(s),j=((Q=(ae=s==null?void 0:s.split)==null?void 0:ae.call(s,"-"))==null?void 0:Q[0])>=Zt;if(E&&j){if(!m)return{value:[],done:!0};const[V,Z]=s.split("-"),ce=parseInt(Z,10)-1,fe=new Date(V,ce,0),me=`${fe.getFullYear()}-${(fe.getMonth()+1).toString().padStart(2,"0")}-${fe.getDate().toString().padStart(2,"0")}`,de=new Date(V,ce+1,1),R=`${de.getFullYear()}-${(de.getMonth()+1).toString().padStart(2,"0")}-${de.getDate().toString().padStart(2,"0")}`;let G;X?(G=ot+1,S.current=0):(G=ot+S.current+1,S.current+=ot);const K=await h.v2.search.fetch({q:`from:${m.acct} after:${me} before:${R}`,type:"statuses",limit:G,offset:S.current});if((ye=K==null?void 0:K.statuses)!=null&&ye.length){const ie=K.statuses.slice(0,ot);ie.forEach(Le=>{Ae(Le,r)});const we=K.statuses.length<=ot;return{value:ie,done:we}}else return{value:[],done:!0}}const ne=[];if(X){const{value:V}=await h.v1.accounts.$select(n).statuses.list({pinned:!0}).next();if(V!=null&&V.length&&!c&&!d){const Z=V.map(ce=>(Ae(ce,r),{...ce,_pinned:!0}));if(Z.length>=3){const ce=Z.map(fe=>fe.id);ne.push({id:ce,items:Z,type:"pinned"})}else ne.push(...Z)}}(X||!g.current)&&(g.current=h.v1.accounts.$select(n).statuses.list({limit:ot,exclude_replies:u,exclude_reblogs:l,only_media:d,tagged:c}));const{value:le,done:H}=await g.current.next();return le!=null&&le.length&&(ne.push(...le),le.forEach(V=>{Ae(V,r)})),{value:ne,done:H}}const[N,O]=$([]);_e(m!=null&&m.acct?`${m!=null&&m.displayName?m.displayName+" ":""}@${m.acct}${u?l?" (- Boosts)":c?` (#${c})`:d?" (Media)":s?` (${new Date(s).toLocaleString("default",{month:"long",year:"numeric"})})`:"":" (+ Replies)"}`:"Account posts","/:instance?/a/:id");const U=D(),P=Ve(()=>{const X=U.current||h.v1.accounts.$select(n).fetch();return U.current=X,X},[n,h]);B(()=>{(async()=>{try{const X=await P();y(X)}catch{}try{const X=await h.v1.accounts.$select(n).featuredTags.list();O(X)}catch{}})()},[n]);const{displayName:M,acct:C,emojis:_}=m||{},F=he(()=>{const X=t.accounts[`${n}@${r}`];return e(Jn,{instance:r,account:X||n,fetchAccount:P,authenticated:p,standalone:!0})},[n,r,p,P]),Y=D(),te=he(()=>e(A,{children:[F,e("div",{class:"filter-bar",ref:Y,style:{position:"relative"},children:[!u||l||c||d||!!s?e(ee,{to:`/${r}/a/${n}`,class:"insignificant filter-clear",title:"Clear filters",children:e(w,{icon:"x",size:"l"})},"clear-filters"):e(w,{icon:"filter",class:"insignificant",size:"l"}),e(ee,{to:`/${r}/a/${n}${u?"?replies=1":""}`,onClick:()=>{u&&pe("Showing post with replies")},class:u?"":"is-active",children:"+ Replies"}),e(ee,{to:`/${r}/a/${n}${l?"":"?boosts=0"}`,onClick:()=>{l||pe("Showing posts without boosts")},class:l?"is-active":"",children:"- Boosts"}),e(ee,{to:`/${r}/a/${n}${d?"":"?media=1"}`,onClick:()=>{d||pe("Showing posts with media")},class:d?"is-active":"",children:"Media"}),N.map(E=>e(ee,{to:`/${r}/a/${n}${c===E.name?"":`?tagged=${encodeURIComponent(E.name)}`}`,onClick:()=>{c!==E.name&&pe(`Showing posts tagged with #${E.name}`)},class:c===E.name?"is-active":"",children:e("span",{children:[e("span",{class:"more-insignificant",children:"#"}),E.name]})},E.id)),T&&(no?e("label",{class:`filter-field ${s?"is-active":""}`,children:[e(w,{icon:"month",size:"l"}),e("input",{type:"month",disabled:!(m!=null&&m.acct),value:s||"",min:Sn,max:new Date().toISOString().slice(0,7),onInput:E=>{const{value:j,validity:ne}=E.currentTarget;if(!ne.valid)return;a(j?{month:j}:{});const[le,H]=j.split("-"),ae=parseInt(H,10)-1,Q=new Date(le,ae);pe(`Showing posts in ${Q.toLocaleString("default",{month:"long",year:"numeric"})}`)}})]}):e(ao,{class:`filter-field ${s?"is-active":""}`,disabled:!(m!=null&&m.acct),value:s||"",min:Sn,max:new Date().toISOString().slice(0,7),onInput:E=>{const{value:j,validity:ne}=E;ne.valid&&a(j?{month:j}:{})}}))]})]}),[n,r,p,N,T,...v]);B(()=>{var E;const X=(E=Y.current)==null?void 0:E.querySelector(".is-active");X&&Y.current.scrollTo({behavior:"smooth",left:X.offsetLeft-(Y.current.offsetWidth-X.offsetWidth)/2})},[N,T,...v]);const W=he(()=>m!=null&&m.url?new URL(m.url).hostname:null,[m]),re=!!m&&!(r===W);return e(Ye,{title:`${m!=null&&m.acct?"@"+m.acct:"Posts"}`,titleComponent:e("h1",{class:"header-double-lines header-account",children:[e("b",{children:e(Nn,{text:M,emojis:_})}),e("div",{children:e("span",{children:["@",C]})})]}),id:"account-statuses",instance:r,emptyText:"Nothing to see here yet.",errorText:"Unable to load posts",fetchItems:L,useItemID:!0,view:d?"media":void 0,boostsCarousel:t.settings.boostsCarousel,timelineStart:te,refresh:[u,l,c,d,s+(m==null?void 0:m.acct)].toString(),headerEnd:e(Fe,{portal:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{disabled:!re,onClick:()=>{(async()=>{try{const{masto:X}=z({instance:W}),E=await X.v1.accounts.lookup({acct:m.acct}),{id:j}=E;location.hash=`/${W}/a/${j}`}catch{alert("Unable to fetch account info")}})()},children:[e(w,{icon:"transfer"})," ",e("small",{class:"menu-double-lines",children:["Switch to account's instance (",e("b",{children:W}),")"]})]}),!I&&e(oe,{onClick:()=>{(async()=>{try{const X=await f.v1.accounts.lookup({acct:m.acct+"@"+r}),{id:E}=X;location.hash=`/${b}/a/${E}`}catch{alert("Unable to fetch account info")}})()},children:[e(w,{icon:"transfer"})," ",e("small",{class:"menu-double-lines",children:["Switch to my instance (",e("b",{children:b}),")"]})]})]})},n)}function ao(t){const{class:n,disabled:i,value:o,min:a,max:s,onInput:u=()=>{}}=t,[l,c]=(o==null?void 0:o.split("-"))||[],d=D(),h=D(),r=(p,f)=>{const[b,g]=(a==null?void 0:a.split("-"))||[],[v,m]=(s==null?void 0:s.split("-"))||[];return!(fv||f===b&&pm)};return e("div",{class:n,children:[e(w,{icon:"month",size:"l"}),e("select",{ref:d,disabled:i,value:c||"",onInput:p=>{const{value:f}=p.currentTarget,b=h.current.value;if(!r(f,b))return{value:"",validity:{valid:!1}};u({value:f?`${b}-${f}`:"",validity:{valid:!0}})},children:[e("option",{value:"",children:"Month"}),e("option",{disabled:!0,children:"-----"}),Array.from({length:12},(p,f)=>e("option",{value:(f+1).toString().padStart(2,"0"),children:new Date(0,f).toLocaleString("default",{month:"long"})},f))]})," ",e("input",{ref:h,type:"number",disabled:i,value:l||new Date().getFullYear(),min:(a==null?void 0:a.slice(0,4))||Zt,max:(s==null?void 0:s.slice(0,4))||new Date().getFullYear(),onInput:p=>{const{value:f,validity:b}=p.currentTarget,g=d.current.value;if(!b.valid||!r(g,f))return{value:"",validity:{valid:!1}};u({value:f?`${f}-${g}`:"",validity:{valid:!0}})},style:{width:"4.5em"}})]})}const co=20;function ss(){_e("Bookmarks","/b");const{masto:t,instance:n}=z(),i=D();async function o(a){return(a||!i.current)&&(i.current=t.v1.bookmarks.list({limit:co})),await i.current.next()}return e(Ye,{title:"Bookmarks",id:"bookmarks",emptyText:"No bookmarks yet. Go bookmark something!",errorText:"Unable to load bookmarks",instance:n,fetchItems:o})}const ro=20;function is(){_e("Likes","/f");const{masto:t,instance:n}=z(),i=D();async function o(a){return(a||!i.current)&&(i.current=t.v1.favourites.list({limit:ro})),await i.current.next()}return e(Ye,{title:"Likes",id:"favourites",emptyText:"No likes yet. Go like something!",errorText:"Unable to load likes",instance:n,fetchItems:o})}function lo(){const{masto:t,instance:n}=z();_e("Followed Hashtags","/ft");const[i,o]=$("default"),[a,s]=$([]);return B(()=>{o("loading"),(async()=>{try{const u=await Tt();s(u),o("default")}catch{o("error")}})()},[]),e("div",{id:"followed-hashtags-page",class:"deck-container",tabIndex:"-1",children:e("div",{class:"timeline-deck deck",children:[e("header",{children:e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),e(ee,{to:"/",class:"button plain",children:e(w,{icon:"home",size:"l"})})]}),e("h1",{children:"Followed Hashtags"}),e("div",{class:"header-side"})]})}),e("main",{children:a.length>0?e("ul",{class:"link-list",children:a.map(u=>e("li",{children:e(ee,{to:n?`/${n}/t/${u.name}`:`/t/${u.name}`,children:[e(w,{icon:"hashtag"})," ",e("span",{children:u.name})]})}))}):i==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):i==="error"?e("p",{class:"ui-state",children:"Unable to load followed hashtags."}):e("p",{class:"ui-state",children:"No hashtags followed yet."})})]})})}const uo=20;function Jt({title:t,path:n,id:i,...o}){_e(t||"Following",n||"/following");const{masto:a,streaming:s,instance:u}=z(),l=Se(k),c=D(),d=D();async function h(p){(p||!c.current)&&(c.current=a.v1.timelines.home.list({limit:uo}));const f=await c.current.next();let{value:b}=f;if(b!=null&&b.length){let g=!1;p&&(b[0].id!==d.current&&(g=!0),d.current=b[0].id),b.forEach(v=>{Ae(v,u)}),b=wn(b,u),p&&g&&Wi(),Yi(b,u),b.sort((v,m)=>{const y=new Date(v.createdAt);return new Date(m.createdAt)-y})}return{...f,value:b}}async function r(){try{const p=await a.v1.timelines.home.list({limit:5,since_id:d.current}).next();let{value:f}=p;return!!(f!=null&&f.length&&(d.current=f[0].id,f=wn(f,u),f=rt(f,"home"),f.some(b=>!b.reblog)))}catch{return!1}}return B(()=>{let p;return(async()=>{if(s){p=s.user.subscribe();for await(const f of p){if(!p)break;if(f.event==="status.update"){const b=f.payload;Ae(b,u)}else if(f.event==="delete"){const b=f.payload,g=zn(b,u);g&&(g._deleted=!0)}}}})(),()=>{var f;(f=p==null?void 0:p.unsubscribe)==null||f.call(p),p=null}},[s]),e(Ye,{title:t||"Following",id:i||"following",emptyText:"Nothing to see here.",errorText:"Unable to load posts.",instance:u,fetchItems:h,checkForUpdates:r,useItemID:!0,boostsCarousel:l.settings.boostsCarousel,...o,filterContext:"home",showFollowedTags:!0})}const ho=20,fo=4,kn=fo+1;function os({media:t,columnMode:n,...i}){let{hashtag:o,...a}=n?{}:nt();i.hashtag&&(o=i.hashtag);let s=o.trim().split(/[\s+]+/);s.sort(),o=s[0];const[u,l]=qe(),c=t||!!u.get("media"),d=c?"?media=1":"",{masto:h,instance:r,authenticated:p}=z({instance:(i==null?void 0:i.instance)||a.instance}),{masto:f,instance:b,authenticated:g}=z(),v=s.map(M=>`#${M}`).join(" "),m=c?" (Media only)":"",y=r?`${v}${m} on ${r}`:`${v}${m}`;_e(y,"/:instance?/t/:hashtag");const S=D(),I=D(void 0);async function T(M){const C=await h.v1.timelines.tag.$select(o).list({limit:ho,any:s.slice(1),maxId:M?void 0:I.current,onlyMedia:c}).next();let{value:_}=C;return _!=null&&_.length&&(M&&(S.current=_[0].id),_.forEach(F=>{Ae(F,r,{skipThreading:c})}),I.current=_[_.length-1].id),{...C,value:_}}async function x(){try{const M=await h.v1.timelines.tag.$select(o).list({limit:1,any:s.slice(1),since_id:S.current,onlyMedia:c}).next();let{value:C}=M;return C=rt(C,"public"),!!(C!=null&&C.length)}catch{return!1}}const[L,N]=$("default"),[O,U]=$();B(()=>{(async()=>{try{const M=await h.v1.tags.$select(o).fetch();U(M)}catch{}})()},[o]);const P=s.length>=kn;return e(Ye,{title:y,titleComponent:!!r&&e("h1",{class:"header-double-lines",children:[e("b",{children:v}),e("div",{children:r})]}),id:"hashtag",instance:r,emptyText:"No one has posted anything with this tag yet.",errorText:"Unable to load posts with this tag",fetchItems:T,checkForUpdates:x,useItemID:!0,view:c?"media":void 0,refresh:c,filterContext:"public",headerEnd:e(Fe,{portal:!0,setDownOverflow:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[!!O&&s.length===1&&e(A,{children:[e(Be,{subMenu:!0,confirm:O.following,confirmLabel:`Unfollow #${o}?`,disabled:L==="loading"||!p,onClick:()=>{N("loading"),O.following?h.v1.tags.$select(o).unfollow().then(()=>{U({...O,following:!1}),pe(`Unfollowed #${o}`)}).catch(M=>{alert(M)}).finally(()=>{N("default")}):h.v1.tags.$select(o).follow().then(()=>{U({...O,following:!0}),pe(`Followed #${o}`)}).catch(M=>{alert(M)}).finally(()=>{N("default")})},children:O.following?e(A,{children:[e(w,{icon:"check-circle"})," ",e("span",{children:"Following…"})]}):e(A,{children:[e(w,{icon:"plus"})," ",e("span",{children:"Follow"})]})}),e(De,{})]}),e(jn,{className:"plain",children:"Filters"}),e(oe,{type:"checkbox",checked:!!c,onClick:()=>{c?u.delete("media"):u.set("media","1"),l(u)},children:[e(w,{icon:"check-circle"})," ",e("span",{class:"menu-grow",children:"Media only"})]}),e(De,{}),e(Us,{className:"menu-field",disabled:P,children:({ref:M})=>e("form",{onSubmit:C=>{var F,Y;C.preventDefault();const _=(Y=(F=C.target[0].value)==null?void 0:F.trim)==null?void 0:Y.call(F);_&&!s.some(te=>te.toLowerCase()===_.toLowerCase())&&(s.push(_),s.sort(),location.hash=r?`/${r}/t/${s.join("+")}`:`/t/${s.join("+")}${d}`)},children:[e(w,{icon:"hashtag"}),e("input",{ref:M,type:"text",placeholder:P?`Max ${kn} tags`:"Add hashtag",required:!0,autocorrect:"off",autocapitalize:"off",spellcheck:!1,pattern:"[^#][^\\s#]+[^#]",disabled:P})]})}),e(Fs,{takeOverflow:!0,children:s.map((M,C)=>e(oe,{disabled:s.length===1,onClick:_=>{s.splice(C,1),s.sort(),location.hash=r?`/${r}/t/${s.join("+")}${d}`:`/t/${s.join("+")}${d}`},children:[e(w,{icon:"x",alt:"Remove hashtag",class:"danger-icon"}),e("span",{children:[e("span",{class:"more-insignificant",children:"#"}),M]})]},M))}),e(De,{}),e(oe,{disabled:!g,onClick:()=>{if(k.shortcuts.length>=Ze){alert(`Max ${Ze} shortcuts reached. Unable to add shortcut.`);return}const M={type:"hashtag",hashtag:s.join(" "),instance:r,media:c?"on":void 0};k.shortcuts.some(_=>_.type===M.type&&_.hashtag.split(/[\s+]+/).sort().join(" ")===M.hashtag.split(/[\s+]+/).sort().join(" ")&&(_.instance?_.instance===M.instance:!0)&&(_.media?!!_.media==!!M.media:!0))?alert("This shortcut already exists"):(k.shortcuts.push(M),pe("Hashtag shortcut added"))},children:[e(w,{icon:"shortcut"})," ",e("span",{children:"Add to Shorcuts"})]}),e(oe,{onClick:()=>{let M=prompt('Enter a new instance e.g. "mastodon.social"');if(!/\./.test(M)){M&&alert("Invalid instance");return}M&&(M=M.toLowerCase().trim(),location.hash=`/${M}/t/${s.join("+")}${d}`)},children:[e(w,{icon:"bus"})," ",e("span",{children:"Go to another instance…"})]}),b!==r&&e(oe,{onClick:()=>{location.hash=`/${b}/t/${s.join("+")}${d}`},children:[e(w,{icon:"bus"})," ",e("small",{class:"menu-double-lines",children:["Go to my instance (",e("b",{children:b}),")"]})]})]})},r+v)}const po=20;function as(t){var g;const n=Se(k),{masto:i,instance:o}=z(),a=(t==null?void 0:t.id)||((g=nt())==null?void 0:g.id),s=D(),u=D();async function l(v){(v||!u.current)&&(u.current=i.v1.timelines.list.$select(a).list({limit:po}));const m=await u.current.next();let{value:y}=m;return y!=null&&y.length&&(v&&(s.current=y[0].id),y.forEach(S=>{Ae(S,o)})),{...m,value:y}}async function c(){try{const v=await i.v1.timelines.list.$select(a).list({limit:1,since_id:s.current});let{value:m}=v;return m=rt(m,"home"),!!(m!=null&&m.length)}catch{return!1}}const[d,h]=$({title:"List"});_e(d.title,"/l/:id"),B(()=>{(async()=>{try{const v=await i.v1.lists.$select(a).fetch();h(v)}catch{}})()},[a]);const[r,p]=$(!1),[f,b]=$(!1);return e(A,{children:[e(Ye,{title:d.title,id:"list",emptyText:"Nothing yet.",errorText:"Unable to load posts.",instance:o,fetchItems:l,checkForUpdates:c,useItemID:!0,boostsCarousel:n.settings.boostsCarousel,filterContext:"home",headerStart:e(ee,{to:"/l",class:"button plain",children:e(w,{icon:"list",size:"l"})}),headerEnd:e(Fe,{portal:!0,setDownOverflow:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{onClick:()=>p({list:d}),children:[e(w,{icon:"pencil",size:"l"}),e("span",{children:"Edit"})]}),e(oe,{onClick:()=>b(!0),children:[e(w,{icon:"group",size:"l"}),e("span",{children:"Manage members"})]})]})},a),r&&e(Ce,{class:"light",onClick:v=>{v.target===v.currentTarget&&p(!1)},children:e(Yt,{list:r==null?void 0:r.list,onClose:v=>{v.state==="success"&&v.list?h(v.list):v.state==="deleted"&&(location.hash="/l"),p(!1)}})}),f&&e(Ce,{class:"light",onClick:v=>{v.target===v.currentTarget&&b(!1)},children:e(go,{listID:a,onClose:()=>b(!1)})})]})}const mo=40;function go({listID:t,onClose:n}){const{masto:i,instance:o}=z(),[a,s]=$([]),[u,l]=$("default"),[c,d]=$(!1),h=D();async function r(p){d(!1),l("loading"),(async()=>{try{(p||!h.current)&&(h.current=i.v1.lists.$select(t).accounts.list({limit:mo}));const f=await h.current.next();let{done:b,value:g}=f;g!=null&&g.length?(s(p?g:a.concat(g)),d(!b)):d(!1),l("default")}catch{l("error")}})()}return B(()=>{r(!0)},[]),e("div",{class:"sheet",id:"list-manage-members-container",children:[!!n&&e("button",{type:"button",class:"sheet-close",onClick:n,children:e(w,{icon:"x"})}),e("header",{children:e("h2",{children:"Manage members"})}),e("main",{children:e("ul",{children:[a.map(p=>e("li",{children:[e(He,{account:p,instance:o}),e(bo,{account:p,listID:t})]},p.id)),c&&u==="default"&&e(je,{as:"li",onChange:p=>p&&r(),children:e("button",{type:"button",class:"light block",onClick:r,children:"Show more…"})})]})})]})}function bo({account:t,listID:n}){const{masto:i}=z(),[o,a]=$("default"),[s,u]=$(!1);return e(Be,{confirm:!s,confirmLabel:e("span",{children:["Remove @",t.username," from list?"]}),align:"end",menuItemClassName:"danger",onClick:()=>{s?(a("loading"),(async()=>{try{await i.v1.lists.$select(n).accounts.create({accountIds:[t.id]}),a("default"),u(!1)}catch{a("error")}})()):(a("loading"),(async()=>{try{await i.v1.lists.$select(n).accounts.remove({accountIds:[t.id]}),a("default"),u(!0)}catch{a("error")}})())},children:e("button",{type:"button",class:`light ${s?"":"danger"}`,disabled:o==="loading",children:s?"Add":"Remove…"})})}const In=20,yo=new URLSearchParams;function cs({columnMode:t,...n}){const{masto:i,instance:o}=z(),[a]=t?[yo]:qe(),[s,u]=$(null),l=(n==null?void 0:n.type)||a.get("type")||s;_e(`Mentions${l==="private"?" (Private)":""}`,"/mentions");const c=D(),d=D();async function h(m){(m||!c.current)&&(c.current=i.v1.notifications.list({limit:In,types:["mention"]}));const y=await c.current.next();let{value:S}=y;return S!=null&&S.length&&(m&&(d.current=S[0].id),S.forEach(({status:I})=>{Ae(I,o)})),{...y,value:S==null?void 0:S.map(I=>I.status)}}const r=D(),p=D();async function f(m){(m||!r.current)&&(r.current=i.v1.conversations.list({limit:In}));const y=await r.current.next();let{value:S}=y;return S=S==null?void 0:S.filter(I=>I.lastStatus),S!=null&&S.length&&(m&&(p.current=S[0].lastStatus.id),S.forEach(({lastStatus:I})=>{Ae(I,o)})),{...y,value:S==null?void 0:S.map(I=>I.lastStatus)}}function b(...m){return l==="private"?f(...m):h(...m)}async function g(){if(l==="private")try{const m=await i.v1.conversations.list({limit:1,since_id:p.current}).next();let{value:y}=m;return y!=null&&y.length?(p.current=y[0].lastStatus.id,!0):!1}catch{return!1}else try{const m=await i.v1.notifications.list({limit:1,types:["mention"],since_id:d.current}).next();let{value:y}=m;return y!=null&&y.length?(d.current=y[0].id,!0):!1}catch{return!1}}const v=he(()=>e("div",{class:"filter-bar centered",children:[e(ee,{to:"/mentions",class:l?"":"is-active",onClick:m=>{t&&(m.preventDefault(),u(null))},children:"All"}),e(ee,{to:"/mentions?type=private",class:l==="private"?"is-active":"",onClick:m=>{t&&(m.preventDefault(),u("private"))},children:"Private"})]}),[l]);return e(Ye,{title:"Mentions",id:"mentions",emptyText:"No one mentioned you :(",errorText:"Unable to load mentions.",instance:o,fetchItems:b,checkForUpdates:g,useItemID:!0,timelineStart:v,refresh:l})}const wo={mention:["account","status"],status:["account","status"],reblog:["account","status"],follow:["account"],follow_request:["account"],favourite:["account","status"],poll:["status"],update:["status"]};function vo(t){return t.filter(n=>{const{type:i,id:o,createdAt:a}=n;if(!i)return!1;const s=wo[i];return s!=null&&s.length?s.every(u=>!!n[u]):!0})}function rs(t){t=vo(t);const n={},i=[];for(let s=0,u=0;sy.id===h.id);m?(m._types.push(r),m._types.sort().reverse(),v.id+=`-${c}`):(h._types=[r],v._accounts.push(h),v.id+=`-${c}`)}else{h._types=[r];let m=n[g]={...l,type:b,_accounts:[h]};i[u++]=m}}const o={},a=[];for(let s=0,u=0;s{Ae(H.status,i,{skipThreading:!0})});const le=rs(ne);E?(k.notificationsLast=ne[0],k.notifications=le,n.v1.markers.create({notifications:{lastReadId:ne[0].id}}).catch(()=>{})):k.notifications.push(...le)}return k.notificationsShowNew=!1,k.notificationsLastFetchTime=Date.now(),j}async function O(){try{return await n.v1.followRequests.list({limit:80})}catch{return[]}}const U=()=>{s("loading"),(async()=>{try{const E=await O();I(E),s("default")}catch{s("error")}})()};async function P(){try{return await n.v1.announcements.list()}catch{return[]}}const M=E=>{_(!1),s("loading"),(async()=>{try{const j=N(E);E&&(P().then(le=>{le.sort((H,ae)=>{const Q=new Date(H.updatedAt||H.createdAt);return new Date(ae.updatedAt||ae.createdAt)-Q}),x(le)}).catch(()=>{}),O().then(le=>{I(le)}).catch(()=>{}));const{done:ne}=await j;h(!ne),s("default")}catch{s("error")}})()};B(()=>{M(!0)},[]),B(()=>{v&&M(!0)},[v]);const[C,_]=$(!1),F=Ve(({disableIdleCheck:E=!1}={})=>{var j;a!=="loading"&&o.settings.autoRefresh&&((j=f.current)==null?void 0:j.scrollTop)<16&&(E||window.__IDLE__)&&!To()&&M(!0)},[o.notificationsShowNew,o.settings.autoRefresh,a]),Y=D();ct(E=>{let j;if(E){const ne=Date.now()-Y.current;!Y.current||ne>1e3*3?F({disableIdleCheck:!0}):Y.current=Date.now(),j=Os(k,"notificationsShowNew",le=>{le&&F(),_(le)})}return()=>{j==null||j()}});const te=new Date,W=new Date(te-24*60*60*1e3);let ke=new Date;const re=!o.notifications.some(E=>new Date(E.createdAt).toDateString()===te.toDateString()),X=D();return B(()=>{l&&(k.routeNotification={id:l,accessToken:atob(c)})},[l,c]),e("div",{id:"notifications-page",class:"deck-container",ref:f,tabIndex:"-1",children:e("div",{class:`timeline-deck deck ${r?"only-mentions":""}`,children:[e("header",{hidden:y,onClick:E=>{var j;E.target.closest("a, button")||(j=f.current)==null||j.scrollTo({top:0,behavior:"smooth"})},class:a==="loading"?"loading":"",children:[e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),e(ee,{to:"/",class:"button plain",children:e(w,{icon:"home",size:"l",alt:"Home"})})]}),e("h1",{children:"Notifications"}),e("div",{class:"header-side"})]}),C&&a!=="loading"&&e("button",{class:"updates-button shiny-pill",type:"button",onClick:()=>{var E;M(!0),(E=f.current)==null||E.scrollTo({top:0,behavior:"smooth"})},children:[e(w,{icon:"arrow-up"})," New notifications"]})]}),T.length>0&&e("div",{class:"shazam-container",children:e("div",{class:"shazam-container-inner",children:e("details",{class:"announcements",children:[e("summary",{children:[e("span",{children:[e(w,{icon:"announce",class:"announcement-icon",size:"l"})," ",e("b",{children:["Announcement",T.length>1?"s":""]})," ",e("small",{class:"insignificant",children:i})]}),T.length>1&&e("span",{class:"announcements-nav-buttons",children:T.map((E,j)=>e("button",{type:"button",class:"plain2 small",onClick:()=>{var ne;(ne=X.current)==null||ne.children[j].scrollIntoView({behavior:"smooth",block:"nearest"})},children:j+1}))})]}),e("ul",{class:`announcements-list-${T.length>1?"multiple":"single"}`,ref:X,children:T.map(E=>e("li",{children:e(Co,{announcement:E})}))})]})})}),S.length>0&&e("div",{class:"follow-requests",children:[e("h2",{class:"timeline-header",children:"Follow requests"}),S.length>5?e("details",{children:[e("summary",{children:[S.length," follow requests"]}),e("ul",{children:S.map(E=>e("li",{children:[e(He,{account:E}),e(Ft,{accountID:E.id,onChange:()=>{}})]},E.id))})]}):e("ul",{children:S.map(E=>e("li",{children:[e(He,{account:E}),e(Ft,{accountID:E.id,onChange:()=>{}})]},E.id))})]}),e("div",{id:"mentions-option",children:e("label",{children:[e("input",{type:"checkbox",checked:r,onChange:E=>{p(E.target.checked)}})," ","Only mentions"]})}),e("h2",{class:"timeline-header",children:"Today"}),re&&!!o.notifications.length&&e("p",{class:"ui-state insignificant",children:a==="default"?"You're all caught up.":e(A,{children:"…"})}),o.notifications.length?e(A,{children:o.notifications.filter(E=>E.type!=="follow_request").map(E=>{if(r&&E.type!=="mention")return null;const j=new Date(E.createdAt),ne=j.toDateString()!==ke.toDateString();ne&&(ke=j);const le=j.toDateString()===W.toDateString()?"Yesterday":Ke(ke,{hideTime:!0});return e(A,{children:[ne&&e("h2",{class:"timeline-header",children:le}),e(Kt,{instance:i,notification:E},E.id)]},E.id)})}):e(A,{children:[a==="loading"&&e(A,{children:e("ul",{class:"timeline flat",children:Array.from({length:5}).map((E,j)=>e("li",{class:"notification skeleton",children:[e("div",{class:"notification-type",children:e(w,{icon:"notification",size:"xl"})}),e("div",{class:"notification-content",children:e("p",{children:"███████████ ████"})})]}))})}),a==="error"&&e("p",{class:"ui-state",children:["Unable to load notifications",e("br",{}),e("br",{}),e("button",{type:"button",onClick:()=>M(!0),children:"Try again"})]})]}),d&&e(je,{onChange:E=>{E&&M()},children:e("button",{type:"button",class:"plain block",disabled:a==="loading",onClick:()=>M(),style:{marginBlockEnd:"6em"},children:a==="loading"?e(Ie,{abrupt:!0}):e(A,{children:"Show more…"})})})]})})}function To(){return!!document.querySelector(".deck-backdrop, #modal-container > *")}function Co({announcement:t}){const{instance:n}=z(),{contact:i}=Cs(),o=i==null?void 0:i.account,{id:a,content:s,startsAt:u,endsAt:l,published:c,allDay:d,publishedAt:h,updatedAt:r,read:p,mentions:f,statuses:b,tags:g,emojis:v,reactions:m}=t,y=new Date(h),S=Ke(y),I=new Date(r),T=Ke(I);return e("div",{class:"announcement-block",children:[e(He,{account:o}),e("div",{class:"announcement-content",onClick:Pn({mentions:f,instance:n}),dangerouslySetInnerHTML:{__html:Pt(s,{emojis:v})}}),e("p",{class:"insignificant",children:[e("time",{datetime:y.toISOString(),children:Ke(y)}),r&&T!==S&&e(A,{children:[" ","•"," ",e("span",{class:"ib",children:["Updated"," ",e("time",{datetime:I.toISOString(),children:Ke(I)})]})]})]}),e("div",{class:"announcement-reactions",hidden:!0,children:m.map(x=>{const{name:L,count:N,me:O,staticUrl:U,url:P}=x;return e("button",{type:"button",class:`plain4 small ${O?"reacted":""}`,children:[P||U?e("img",{src:P||U,alt:L,width:"16",height:"16"}):e("span",{children:L})," ",e("span",{class:"count",children:Ue(N)})]})})})]})}const ls=ze(Io),$o=20;function Ot({local:t,columnMode:n,...i}){const o=Se(k),a=!!t,s=n?{}:nt(),{masto:u,instance:l}=z({instance:(i==null?void 0:i.instance)||s.instance}),{masto:c,instance:d}=z(),h=`${a?"Local":"Federated"} timeline (${l})`;_e(h,a?"/:instance?/p/l":"/:instance?/p");const r=D(),p=D();async function f(g){(g||!p.current)&&(p.current=u.v1.timelines.public.list({limit:$o,local:a}));const v=await p.current.next();let{value:m}=v;return m!=null&&m.length&&(g&&(r.current=m[0].id),m.forEach(y=>{Ae(y,l)})),{...v,value:m}}async function b(){try{const g=await u.v1.timelines.public.list({limit:1,local:a,since_id:r.current}).next();let{value:v}=g;return v=rt(v,"public"),!!(v!=null&&v.length)}catch{return!1}}return e(Ye,{title:h,titleComponent:e("h1",{class:"header-double-lines",children:[e("b",{children:a?"Local timeline":"Federated timeline"}),e("div",{children:l})]}),id:"public",instance:l,emptyText:"No one has posted anything yet.",errorText:"Unable to load posts",fetchItems:f,checkForUpdates:b,useItemID:!0,headerStart:e(A,{}),boostsCarousel:o.settings.boostsCarousel,filterContext:"public",headerEnd:e(Fe,{portal:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{href:a?`/#/${l}/p`:`/#/${l}/p/l`,children:a?e(A,{children:[e(w,{icon:"transfer"})," ",e("span",{children:"Switch to Federated"})]}):e(A,{children:[e(w,{icon:"transfer"})," ",e("span",{children:"Switch to Local"})]})}),e(De,{}),e(oe,{onClick:()=>{let g=prompt('Enter a new instance e.g. "mastodon.social"');if(!/\./.test(g)){g&&alert("Invalid instance");return}g&&(g=g.toLowerCase().trim(),location.hash=a?`/${g}/p/l`:`/${g}/p`)},children:[e(w,{icon:"bus"})," ",e("span",{children:"Go to another instance…"})]}),d!==l&&e(oe,{onClick:()=>{location.hash=a?`/${d}/p/l`:`/${d}/p`},children:[e(w,{icon:"bus"})," ",e("small",{class:"menu-double-lines",children:["Go to my instance (",e("b",{children:d}),")"]})]})]})},l+a)}const yt=5,Et=40,xo=new URLSearchParams;function ds({columnMode:t,...n}){const i=t?{}:nt(),{masto:o,instance:a,authenticated:s}=z({instance:i.instance}),[u,l]=$("default"),[c]=t?[xo]:qe(),d=D(),h=(n==null?void 0:n.query)||c.get("q"),r=t?"statuses":(n==null?void 0:n.type)||c.get("type");_e(h?`Search: ${h}${r?` (${{statuses:"Posts",accounts:"Accounts",hashtags:"Hashtags"}[r]})`:""}`:"Search","/search");const[p,f]=$(!1),b=D(0);B(()=>{b.current=0},[h,r]);const g=D();Je(()=>{var C,_;(_=(C=g.current)==null?void 0:C.scrollTo)==null||_.call(C,0,0)},[h,r]);const[v,m]=$([]),[y,S]=$([]),[I,T]=$([]);B(()=>{m([]),S([]),T([])},[h]);const x={statuses:m,accounts:S,hashtags:T},[L,N]=$({}),O=async C=>{if(!(C!=null&&C.length))return;const _=await Wt(C,L);_&&N({...L,..._})};function U(C){C&&(b.current=0),!(!C&&!s)&&(l("loading"),C&&!r&&(m(v.slice(0,yt)),S(y.slice(0,yt)),T(I.slice(0,yt))),(async()=>{var F,Y;const _={q:h,resolve:s,limit:yt};r&&(_.limit=Et,_.type=r,s&&(_.offset=b.current));try{const te=await o.v2.search.fetch(_);if(r)if(C){x[r](te[r]);const W=(F=te[r])==null?void 0:F.length;b.current=Et,f(!!W)}else{x[r](ke=>[...ke,...te[r]]);const W=(Y=te[r])==null?void 0:Y.length;b.current=b.current+Et,f(!!W)}else m(te.statuses||[]),S(te.accounts||[]),T(te.hashtags||[]),b.current=0,f(!1);O(te.accounts),l("default")}catch{l("error")}})())}const P=D();ct(C=>{var F;const _=((F=g.current)==null?void 0:F.scrollTop)===0;if(C&&_){const Y=Date.now()-P.current;!P.current||Y>1e3*3?U(!0):P.current=Date.now()}}),B(()=>{var C,_,F,Y;(_=(C=d.current)==null?void 0:C.setValue)==null||_.call(C,h||""),h?U(!0):(Y=(F=d.current)==null?void 0:F.focus)==null||Y.call(F)},[h,r,a]),Re("/",C=>{var _,F;(F=(_=d.current)==null?void 0:_.focus)==null||F.call(_)},{preventDefault:!0});const[M]=Ht();return e("div",{id:"search-page",class:"deck-container",ref:g,children:e("div",{class:"timeline-deck deck",children:[e("header",{class:u==="loading"?"loading":"",children:e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:e(mt,{})}),e(ns,{ref:d}),e("div",{class:"header-side",children:e("button",{type:"button",class:"plain",onClick:()=>{U(!0)},disabled:u==="loading",children:e(w,{icon:"search",size:"l"})})})]})}),e("main",{children:[!!h&&!t&&e("div",{ref:M,class:`filter-bar ${u==="loading"?"loading":""}`,children:[!!r&&e(ee,{to:`/search${h?`?q=${encodeURIComponent(h)}`:""}`,children:"‹ All"}),[{label:"Accounts",type:"accounts",to:`/search?q=${encodeURIComponent(h)}&type=accounts`},{label:"Hashtags",type:"hashtags",to:`/search?q=${encodeURIComponent(h)}&type=hashtags`},{label:"Posts",type:"statuses",to:`/search?q=${encodeURIComponent(h)}&type=statuses`}].sort((C,_)=>C.type===r?-1:_.type===r?1:0).map(C=>e(ee,{to:C.to,children:C.label},C.type))]}),h?e(A,{children:[(!r||r==="accounts")&&e(A,{children:[r!=="accounts"&&e("h2",{class:"timeline-header",children:"Accounts"}),y.length>0?e(A,{children:[e("ul",{class:"timeline flat accounts-list",children:y.map(C=>e("li",{children:e(He,{account:C,instance:a,showStats:!0,relationship:L[C.id]})},C.id))}),r!=="accounts"&&e("div",{class:"ui-state",children:e(ee,{class:"plain button",to:`/search?q=${h}&type=accounts`,children:["See more accounts ",e(w,{icon:"arrow-right"})]})})]}):!r&&(u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"No accounts found."}))]}),(!r||r==="hashtags")&&e(A,{children:[r!=="hashtags"&&e("h2",{class:"timeline-header",children:"Hashtags"}),I.length>0?e(A,{children:[e("ul",{class:"link-list hashtag-list",children:I.map(C=>{var te;const{name:_,history:F}=C,Y=(te=F==null?void 0:F.reduce)==null?void 0:te.call(F,(W,ke)=>W+ +ke.uses,0);return e("li",{children:e(ee,{to:a?`/${a}/t/${_}`:`/t/${_}`,children:[e(w,{icon:"hashtag"}),e("span",{children:_}),!!Y&&e("span",{class:"count",children:Ue(Y)})]})},`${_}-${Y}`)})}),r!=="hashtags"&&e("div",{class:"ui-state",children:e(ee,{class:"plain button",to:`/search?q=${h}&type=hashtags`,children:["See more hashtags ",e(w,{icon:"arrow-right"})]})})]}):!r&&(u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"No hashtags found."}))]}),(!r||r==="statuses")&&e(A,{children:[r!=="statuses"&&e("h2",{class:"timeline-header",children:"Posts"}),v.length>0?e(A,{children:[e("ul",{class:"timeline",children:v.map(C=>e("li",{children:e(ee,{class:"status-link",to:a?`/${a}/s/${C.id}`:`/s/${C.id}`,children:e(Me,{status:C})})},C.id))}),r!=="statuses"&&e("div",{class:"ui-state",children:e(ee,{class:"plain button",to:`/search?q=${h}&type=statuses`,children:["See more posts ",e(w,{icon:"arrow-right"})]})})]}):!r&&(u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"No posts found."}))]}),!!r&&(u==="default"?p?e(je,{onChange:C=>{C&&U()},children:e("button",{type:"button",class:"plain block",onClick:()=>U(),style:{marginBlockEnd:"6em"},children:"Show more…"})}):e("p",{class:"ui-state insignificant",children:"The end."}):u==="loading"&&e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}))]}):u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"Enter your search term or paste a URL above to get started."})]})]})})}const Ao=20,Lo=tt(t=>t.v1.trends.links.list().next(),{maxAge:10*60*1e3});function us({columnMode:t,...n}){const i=Se(k),o=t?{}:nt(),{masto:a,instance:s}=z({instance:(n==null?void 0:n.instance)||o.instance}),{masto:u,instance:l}=z(),c=`Trending (${s})`;_e(c,"/:instance?/trending");const d=D(),[h,r]=$([]),[p,f]=$([]),b=D();async function g(y){var T;if(y||!b.current){b.current=a.v1.trends.statuses.list({limit:Ao});try{const x=a.v1.trends.tags.list(),{value:L}=await x.next();L!=null&&L.length&&r(L)}catch{}try{const{value:x}=await Lo(a),L=(T=x==null?void 0:x.filter)==null?void 0:T.call(x,N=>N.type==="link");L!=null&&L.length&&f(L)}catch{}}const S=await b.current.next();let{value:I}=S;return I!=null&&I.length&&(y&&(d.current=I[0].id),I.forEach(x=>{Ae(x,s)})),{...S,value:I}}async function v(){try{const y=await a.v1.trends.statuses.list({limit:1}).next();let{value:S}=y;return S=rt(S,"public"),S!=null&&S.length&&S[0].id!==d.current?(d.current=S[0].id,!0):!1}catch{return!1}}const m=he(()=>e(A,{children:[!!h.length&&e("div",{class:"filter-bar expandable",children:[e(w,{icon:"chart",class:"insignificant",size:"l"}),h.map((y,S)=>{const{name:I,history:T}=y,x=T.reduce((L,N)=>L+ +N.uses,0);return e(ee,{to:`/${s}/t/${I}`,children:[e("span",{children:[e("span",{class:"more-insignificant",children:"#"}),I]}),e("span",{class:"filter-count",children:Ue(x)})]},I)})]}),!!p.length&&e("div",{class:"links-bar",children:[e("header",{children:e("h3",{children:"Trending News"})}),p.map(y=>{const{authorName:S,authorUrl:I,blurhash:T,description:x,height:L,image:N,imageDescription:O,language:U,providerName:P,providerUrl:M,publishedAt:C,title:_,url:F,width:Y}=y,te=new URL(F).hostname.replace(/^www\./,"").replace(/\/$/,"");let W;if(T){const ke=qn(T),re=Xn(ke);W=Qn([.6,re[1],re[2]])}return e("a",{href:F,target:"_blank",rel:"noopener noreferrer",style:W?{"--accent-color":`rgb(${W.join(",")})`,"--accent-alpha-color":`rgba(${W.join(",")}, 0.4)`}:{},children:e("article",{children:[e("figure",{children:e("img",{src:N,alt:O,width:Y,height:L,loading:"lazy"})}),e("div",{class:"article-body",children:[e("header",{children:[e("div",{class:"article-meta",children:[e("span",{class:"domain",children:te})," ",!!C&&e(A,{children:"· "}),!!C&&e(A,{children:e($t,{datetime:C,format:"micro"})})]}),!!_&&e("h1",{class:"title",lang:U,dir:"auto",children:_})]}),!!x&&e("p",{class:"description",lang:U,dir:"auto",children:x})]})]})},F)})]})]}),[h,p]);return e(Ye,{title:c,titleComponent:e("h1",{class:"header-double-lines",children:[e("b",{children:"Trending"}),e("div",{children:s})]}),id:"trending",instance:s,emptyText:"No trending posts.",errorText:"Unable to load posts",fetchItems:g,checkForUpdates:v,checkForUpdatesInterval:5*60*1e3,useItemID:!0,headerStart:e(A,{}),boostsCarousel:i.settings.boostsCarousel,filterContext:"public",timelineStart:m,headerEnd:e(Fe,{portal:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{onClick:()=>{let y=prompt('Enter a new instance e.g. "mastodon.social"');if(!/\./.test(y)){y&&alert("Invalid instance");return}y&&(y=y.toLowerCase().trim(),location.hash=`/${y}/trending`)},children:[e(w,{icon:"bus"})," ",e("span",{children:"Go to another instance…"})]}),l!==s&&e(oe,{onClick:()=>{location.hash=`/${l}/trending`},children:[e(w,{icon:"bus"})," ",e("small",{class:"menu-double-lines",children:["Go to my instance (",e("b",{children:l}),")"]})]})]})},s)}function Mo(){_e("Home","/");const t=Se(k),{shortcuts:n}=t,i=n.map(o=>{if(!o)return null;const{type:a,...s}=o,u={following:Jt,notifications:ls,list:as,public:Ot,bookmarks:ss,favourites:is,hashtag:os,mentions:cs,trending:us,search:ds}[a];return!u||a==="search"&&!s.query?null:e(u,{...s,columnMode:!0},a+JSON.stringify(s))});return Re(["1","2","3","4","5","6","7","8","9"],(o,a)=>{try{const s=parseInt(a.keys[0],10)-1;document.querySelectorAll("#columns > *")[s].focus()}catch{}}),e("div",{id:"columns",onContextMenu:o=>{o.target.closest(".deck > header")&&!o.target.closest("a")&&!o.target.closest("button")&&(o.preventDefault(),k.showShortcutsSettings=!0)},children:i})}function Ro(){var n;const t=Se(k);return B(()=>{(async()=>{const i=await ht.drafts.keys();if(i.length){const o=Un();i.filter(s=>s.startsWith(o)).length&&(k.showDrafts=!0)}})()},[]),e(A,{children:(t.settings.shortcutsViewMode==="multi-column"||!t.settings.shortcutsViewMode&&t.settings.shortcutsColumnsMode)&&((n=t.shortcuts)!=null&&n.length)?e(Mo,{}):e(Jt,{title:"Home",path:"/",id:"home",headerStart:!1,headerEnd:e(_o,{})})})}function _o(){const t=Se(k),n=D(),[i,o]=$(void 0);return e(A,{children:[e(ee,{ref:n,to:"/notifications",class:`button plain notifications-button ${t.notificationsShowNew?"has-badge":""} ${i||""}`,onClick:a=>{a.stopPropagation(),window.matchMedia("(min-width: calc(40em))").matches&&(a.preventDefault(),o(s=>s?void 0:"open"))},children:e(w,{icon:"notification",size:"l",alt:"Notifications"})}),e(No,{state:i,anchorRef:n,onClose:()=>o(void 0)})]})}const Eo=30,Po=5;function No({anchorRef:t,state:n,onClose:i}){const{masto:o,instance:a}=z(),s=Se(k),[u,l]=$("default"),c=o.v1.notifications.list({limit:Eo});async function d(){const b=await c.next(),g=b.value;if(g!=null&&g.length){g.forEach(m=>{Ae(m.status,a,{skipThreading:!0})});const v=rs(g);k.notificationsLast=g[0],k.notifications=v,o.v1.markers.create({notifications:{lastReadId:g[0].id}}).catch(()=>{})}return k.notificationsShowNew=!1,k.notificationsLastFetchTime=Date.now(),b}const[h,r]=$(!1);function p(){return o.v1.followRequests.list({limit:1})}function f(){l("loading"),(async()=>{try{await d();const b=await p();r(!!(b!=null&&b.length)),l("default")}catch{l("error")}})()}return B(()=>{n==="open"&&f()},[n]),e(Gn,{menuClassName:"notifications-menu",state:n,anchorRef:t,onClose:i,portal:{target:document.body},overflow:"auto",viewScroll:"close",position:"anchor",align:"center",boundingBoxPadding:"8 8 8 8",children:[e("header",{children:e("h2",{children:"Notifications"})}),e("main",{children:s.notifications.length?e(A,{children:s.notifications.slice(0,Po).map(b=>e(Kt,{instance:a,notification:b,disableContextMenu:!0},b.id))}):u==="loading"?e("div",{class:"ui-state",children:e(Ie,{abrupt:!0})}):u==="error"&&e("div",{class:"ui-state",children:[e("p",{children:"Unable to fetch notifications."}),e("p",{children:e("button",{type:"button",onClick:f,children:"Try again"})})]})}),e("footer",{children:[e(ee,{to:"/mentions",class:"button plain",children:[e(w,{icon:"at"})," ",e("span",{children:"Mentions"})]}),e(ee,{to:"/notifications",class:"button plain2",children:[h?e(A,{children:[e("span",{class:"tag collapsed",children:"New"})," ",e("span",{children:"Follow Requests"})]}):e("b",{children:"See all"})," ",e(w,{icon:"arrow-right"})]})]})]})}const Do=ze(Ro),Uo=[/^\/@[^@\/]+\/(?:statuses|posts)\/([^\/]+)/i,/\/notes\/([^\/]+)/i,/^\/(?:notice|objects)\/([a-z0-9-]+)/i,/\/@[^@\/]+@?[^\/]+?\/([^\/]+)/i];function hs(t){const{hostname:n,pathname:i}=new URL(t);for(const o of Uo){const[,a]=i.match(o)||[];if(a)return{instance:n,id:a}}return{}}function Fo(t){const{instance:n,id:i}=hs(t);return n&&i?`/${n}/s/${i}`:null}function Oo(){const n=lt().pathname.replace(/^\//,""),i=hs(n),o=i!=null&&i.instance?`/${i.instance}/s/${i.id}`:null,[a,s]=$("loading");return Je(()=>{s("loading"),(async()=>{try{const{instance:u,id:l}=i,{masto:c}=z({instance:u});if(await c.v1.statuses.$select(l).fetch()){window.location.hash=o+"?view=full";return}}catch{}{const{masto:u,instance:l}=z(),c=await u.v2.search.fetch({q:n,type:"statuses",limit:1,resolve:!0});if(c.statuses.length){const d=c.statuses[0];window.location.hash=`/${l}/s/${d.id}?view=full`}else window.location.hash=o+"?view=full"}})()},[o]),e("div",{class:"ui-state",tabIndex:"-1",children:[a==="loading"?e(A,{children:[e(Ie,{abrupt:!0}),e("h2",{children:"Resolving…"}),e("p",{children:e("a",{href:n,target:"_blank",rel:"noopener noreferrer",children:n})})]}):e(A,{children:[e("h2",{children:"Unable to resolve URL"}),e("p",{children:e("a",{href:n,target:"_blank",rel:"noopener noreferrer",children:n})})]}),e("hr",{}),e("p",{children:e(ee,{to:"/",children:"Go home"})})]})}function Bo(){const{masto:t}=z();_e("Lists","/l");const[n,i]=$("default"),[o,a]=xt(d=>d+1,0),[s,u]=$([]);B(()=>{i("loading"),(async()=>{try{const d=await t.v1.lists.list();d.sort((h,r)=>h.title.localeCompare(r.title)),u(d),i("default")}catch{i("error")}})()},[o]);const[l,c]=$(!1);return e("div",{id:"lists-page",class:"deck-container",tabIndex:"-1",children:[e("div",{class:"timeline-deck deck",children:[e("header",{children:e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),e(ee,{to:"/",class:"button plain",children:e(w,{icon:"home",size:"l"})})]}),e("h1",{children:"Lists"}),e("div",{class:"header-side",children:e("button",{type:"button",class:"plain",onClick:()=>c(!0),children:e(w,{icon:"plus",size:"l",alt:"New list"})})})]})}),e("main",{children:s.length>0?e("ul",{class:"link-list",children:s.map(d=>e("li",{children:e(ee,{to:`/l/${d.id}`,children:e("span",{children:[e(w,{icon:"list"})," ",e("span",{children:d.title})]})})}))}):n==="loading"?e("p",{class:"ui-state",children:e(Ie,{})}):n==="error"?e("p",{class:"ui-state",children:"Unable to load lists."}):e("p",{class:"ui-state",children:"No lists yet."})})]}),l&&e(Ce,{class:"light",onClick:d=>{d.target===d.currentTarget&&c(!1)},children:e(Yt,{list:l==null?void 0:l.list,onClose:d=>{d.state==="success"&&a(),c(!1)}})})]})}const zo=""+new URL("instances-cddSOnAA.json",import.meta.url).href;var qo={PHANPY_CLIENT_NAME:"Phanpy",PHANPY_WEBSITE:"https://phanpy.social",PHANPY_LINGVA_INSTANCES:"lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud",PHANPY_PRIVACY_POLICY_URL:"https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD",VITE_APP_ENV:"production",BASE_URL:"./",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const{PHANPY_CLIENT_NAME:Ho,PHANPY_WEBSITE:Vo}=qo,Xt="read write follow push";async function Go({instanceURL:t}){const n=new URLSearchParams({client_name:Ho,redirect_uris:location.origin+location.pathname,scopes:Xt,website:Vo});return await(await fetch(`https://${t}/api/v1/apps`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()})).json()}async function jo({instanceURL:t,client_id:n}){const i=new URLSearchParams({client_id:n,scope:Xt,redirect_uri:location.origin+location.pathname,response_type:"code"});return`https://${t}/oauth/authorize?${i.toString()}`}async function Yo({instanceURL:t,client_id:n,client_secret:i,code:o}){const a=new URLSearchParams({client_id:n,client_secret:i,redirect_uri:location.origin+location.pathname,grant_type:"authorization_code",code:o,scope:Xt});return await(await fetch(`https://${t}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:a.toString()})).json()}var Wo={PHANPY_CLIENT_NAME:"Phanpy",PHANPY_WEBSITE:"https://phanpy.social",PHANPY_LINGVA_INSTANCES:"lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud",PHANPY_PRIVACY_POLICY_URL:"https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD",VITE_APP_ENV:"production",BASE_URL:"./",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const{PHANPY_DEFAULT_INSTANCE:Ko}=Wo;function Zo(){_e("Log in");const t=D(),n=se.local.get("instanceURL"),[i,o]=$("default"),[a]=qe(),s=a.get("instance"),u=a.get("submit"),[l,c]=$(s||(n==null?void 0:n.toLowerCase())||""),[d,h]=$([]);B(()=>{(async()=>{try{const y=await(await fetch(zo)).json();h(y)}catch{}})()},[]);const r=m=>{m&&(se.local.set("instanceURL",m),(async()=>{o("loading");try{const{client_id:y,client_secret:S,vapid_key:I}=await Go({instanceURL:m});y&&S?(se.session.set("clientID",y),se.session.set("clientSecret",S),se.session.set("vapidKey",I),location.href=await jo({instanceURL:m,client_id:y})):alert("Failed to register application"),o("default")}catch{o("error")}})())},p=l?l.replace(/^https?:\/\//,"").replace(/\/+$/,"").replace(/^@?[^@]+@/,"").trim():null,f=/[^\s\r\n\t\/\\]+\.[^\s\r\n\t\/\\]+/.test(p)&&!/[\s\/\\@]/.test(p),b=p?d.filter(m=>m.includes(l)).sort((m,y)=>{const S=m.toLowerCase().startsWith(l.toLowerCase()),I=y.toLowerCase().startsWith(l.toLowerCase());return S&&!I?-1:!S&&I?1:0}).slice(0,10):[],g=f?p:b!=null&&b.length?b[0]:l?d.find(m=>m.includes(l)):null,v=m=>{m.preventDefault(),r(g)};return u&&B(()=>{r(s||g)},[]),e("main",{id:"login",style:{textAlign:"center"},children:e("form",{onSubmit:v,children:[e("h1",{children:[e("img",{src:Gt,alt:"",width:"80",height:"80"}),e("br",{}),"Log in"]}),e("label",{children:[e("p",{children:"Instance"}),e("input",{value:l,required:!0,type:"text",class:"large",id:"instanceURL",ref:t,disabled:i==="loading",autocorrect:"off",autocapitalize:"off",autocomplete:"off",spellcheck:!1,placeholder:"instance domain",onInput:m=>{c(m.target.value)}}),(b==null?void 0:b.length)>0?e("ul",{id:"instances-suggestions",children:b.map((m,y)=>e("li",{children:e("button",{type:"button",class:"plain5",onClick:()=>{r(m)},children:m})}))}):e("div",{id:"instances-eg",children:"e.g. “mastodon.social”"})]}),i==="error"&&e("p",{class:"error",children:"Failed to log in. Please try again or another instance."}),e("div",{children:[e("button",{disabled:i==="loading"||!l||!g,children:g?`Continue with ${g}`:"Continue"})," "]}),e(Ie,{hidden:i!=="loading"}),e("hr",{}),!Ko&&e("p",{children:e("a",{href:"https://joinmastodon.org/servers",target:"_blank",children:"Don't have an account? Create one!"})}),e("p",{children:e(ee,{to:"/",children:"Go home"})})]})})}const wt=40,Jo=10,Xo=5;let Bt={},St={},kt={};function zt(t){delete St[t],delete kt[t]}const dt={block:"nearest",inline:"center",behavior:"smooth"},Tn=".status-link:not(details:not([open]) > summary ~ *, details:not([open]) > summary ~ * *), .status-focus:not(details:not([open]) > summary ~ *, details:not([open]) > summary ~ * *)",Cn=/\/s\//i;function Qo(t){const{id:n}=t,{masto:i,instance:o}=z({instance:t.instance}),a=Se(k),[s,u]=qe(),l=s.get("media"),c=s.get("media-only"),d=parseInt(l||c,10);let h=d>0;const r=s.get("mediaStatusID"),p=zn(r,o);r&&!p&&(h=!1);const f=h&&!!c,b=Ge(n,o),[g,v]=$(k.statuses[b]);B(()=>{k.statuses[b]&&v(k.statuses[b])},[b]);const m=he(()=>{const{prevLocation:I}=k,T=((I==null?void 0:I.pathname)||"")+((I==null?void 0:I.search)||""),x=pt("/:instance/s/:id",T)||pt("/s/:id",T);return!T||x?"/":T},[]);B(()=>{!g&&h&&(async()=>{try{const I=await i.v1.statuses.$select(n).fetch();Ae(I,o),v(I)}catch{alert("Unable to load post."),location.hash=m}})()},[h]);const y=r?p==null?void 0:p.mediaAttachments:g==null?void 0:g.mediaAttachments,S=Ve(()=>{!window.matchMedia("(min-width: calc(40em + 350px))").matches&&a.prevLocation?history.back():f?location.hash=m:(s.delete("media"),s.delete("mediaStatusID"),u(s))},[f,m,a.prevLocation]);return B(()=>{let I=setTimeout(()=>{const T=document.querySelector(".carousel");T&&T.focus()},100);return()=>clearTimeout(I)},[f]),e("div",{class:"deck-backdrop",children:[h?y!=null&&y.length?e(es,{mediaAttachments:y,statusID:r||n,instance:o,lang:g==null?void 0:g.language,index:d-1,onClose:S}):e("div",{class:"media-modal-container loading",children:e(Ie,{abrupt:!0})}):e(ee,{to:m}),!f&&e(ea,{id:n,instance:t.instance,closeLink:m})]})}function ea({id:t,closeLink:n="/",instance:i}){var me,de;const[o,a]=qe(),s=o.get("media"),u=o.get("mediaStatusID"),l=parseInt(s,10)>0,c=D(!k.prevLocation&&(history.length===1||"navigation"in window&&((de=(me=navigation==null?void 0:navigation.entries)==null?void 0:me.call(navigation))==null?void 0:de.length)===1)),[d,h]=$(o.get("view")||c.current?"full":null),r=!!parseInt(o.get("translate")),{masto:p,instance:f}=z({instance:i}),{masto:b,instance:g,authenticated:v}=z(),m=f===g,y=Se(k),[S,I]=$([]),[T,x]=$("default"),L=D(),N=Ge(t,f),O=D(0),U=D();B(()=>{var R;(R=U.current)==null||R.focus()},[]),B(()=>{var G;const R=Yn(()=>{if(!U.current)return;const{scrollTop:K}=U.current;T!=="loading"&&(kt[t]=K)},50);return(G=U.current)==null||G.addEventListener("scroll",R,{passive:!0}),R(),()=>{var K;R.cancel(),(K=U.current)==null||K.removeEventListener("scroll",R)}},[t,T!=="loading"]);const P=D(),M=({reloadHero:R}={})=>{x("loading");let G;const K=St[t];if(K){const ie=K.filter(we=>k.statuses[N]);I(ie)}else I([{id:t}]);return(async()=>{var q,ge;const ie=()=>cn(()=>p.v1.statuses.$select(t).fetch(),{retries:4}),we=cn(()=>p.v1.statuses.$select(t).context.fetch(),{retries:8}),Le=!!y.statuses[N];let $e=y.statuses[N];if(!(Le&&!R))try{$e=await ie(),Ae($e,f),await new Promise(be=>{setTimeout(be,100)})}catch{x("error");return}try{let be=function(J){return J==null?void 0:J.map(ve=>({id:ve.id,account:ve.account,repliesCount:ve.repliesCount,content:ve.content,weight:ft(ve),replies:be(ve.__replies)}))};const ue=await we,{ancestors:xe,descendants:Pe}=ue;O.current=(Pe==null?void 0:Pe.length)||0;const Ne=new Set;xe.forEach(J=>{Ae(J,f,{skipThreading:!0}),J.inReplyToId&&!xe.find(ve=>ve.id===J.inReplyToId)&&Ne.add(J.inReplyToId)});const st=xe.every(J=>J.account.id===$e.account.id),Oe=[];Pe.forEach(J=>{if(Ae(J,f,{skipThreading:!0}),J.inReplyToId&&!Pe.find(ve=>ve.id===J.inReplyToId)&&J.inReplyToId!==$e.id&&Ne.add(J.inReplyToId),J.inReplyToAccountId===J.account.id)Oe.push(J);else if(J.inReplyToId===$e.id)Oe.push(J);else if(!J.inReplyToAccountId&&Oe.find(ve=>ve.id===J.inReplyToId)&&J.account.id===$e.account.id)Oe.push(J);else{const ve=Pe.find(ps=>ps.id===J.inReplyToId);ve&&(ve.__replies||(ve.__replies=[]),ve.__replies.push(J))}}),Ne.size;const We=[...xe.map(J=>({id:J.id,ancestor:!0,isThread:st,accountID:J.account.id,account:J.account,repliesCount:J.repliesCount,weight:ft(J)})),{id:t,accountID:$e.account.id,weight:ft($e)},...Oe.map(J=>({id:J.id,account:J.account,accountID:J.account.id,descendant:!0,thread:J.account.id===$e.account.id,weight:ft(J),replies:be(J.__replies)}))];x("default"),P.current={offsetTop:(q=L.current)==null?void 0:q.offsetTop,scrollTop:(ge=U.current)==null?void 0:ge.scrollTop};const Xe=We.findIndex(J=>J.id===t);Xe>=W&&ke(Xe+1),I(We),St[t]=We,$s($e,f)}catch{x("error")}})(),()=>{clearTimeout(G)}};B(M,[t,p]),B(()=>{var G,K;if(!S.length)return;const R=kt[t];if(R)U.current.scrollTop=R;else if(P.current){const ie={offsetTop:(G=L.current)==null?void 0:G.offsetTop,scrollTop:(K=U.current)==null?void 0:K.scrollTop},we=ie.offsetTop-P.current.offsetTop+ie.scrollTop;U.current.scrollTop=we}else S.length===1&&(U.current.scrollTop=0);P.current=null},[S]),B(()=>{y.reloadStatusPage<=0||(async()=>{try{const{instanceURL:R}=at(),G=`https://${R}/api/v1/statuses/${t}/context`;return await(await caches.open("api")).delete(G,{ignoreVary:!0}),M({reloadHero:!0})}catch{}})()},[y.reloadStatusPage]),B(()=>()=>{kt={},k.reloadStatusPage=0,St={},Bt={},qt.clear()},[]);const C=y.statuses[N]||y.statuses[t],_=he(()=>{if(!C)return"";const{account:R}=C,G=document.createElement("div");return G.innerHTML=R.displayName,G.innerText.trim()},[C]),F=he(()=>{if(!C)return"";let R=Bn(C);return R.length>64&&(R=R.slice(0,64)+"…"),R},[C]);_e(_&&F?`${_}: "${F}"`:"Status","/:instance?/s/:id");const Y=he(()=>{if(!C)return;const{url:R}=C;if(R)return new URL(R).hostname},[C]),te=he(()=>{if(Y)return Y===f},[Y,f]),[W,ke]=$(wt),re=he(()=>S.length-W,[S.length,W]),X=S.some(R=>R.descendant),E=S.filter(R=>R.ancestor),[j,ne]=$(!0),le=he(()=>{if(!L.current||j)return null;const{top:R}=L.current.getBoundingClientRect();return R>0?"down":"up"},[j]);Re("esc",()=>{location.hash=n},{enabled:!l,ignoreEventWhen:R=>!!document.querySelector("#modal-container > *")}),Re("backspace",()=>{location.hash=n}),Re("j",()=>{const R=document.activeElement.closest(".status-link, .status-focus"),G=R==null?void 0:R.getBoundingClientRect(),K=Array.from(U.current.querySelectorAll(Tn));if(R&&G.top0){const ie=K.indexOf(R);let we=K[ie+1];we&&(we.focus(),we.scrollIntoView(dt))}else{const ie=K.find(we=>{const Le=we.getBoundingClientRect();return Le.top>=44&&Le.left>=0});ie&&(ie.focus(),ie.scrollIntoView(dt))}}),Re("k",()=>{const R=document.activeElement.closest(".status-link, .status-focus"),G=R==null?void 0:R.getBoundingClientRect(),K=Array.from(U.current.querySelectorAll(Tn));if(R&&G.top0){const ie=K.indexOf(R);let we=K[ie-1];we&&(we.focus(),we.scrollIntoView(dt))}else{const ie=K.find(we=>{const Le=we.getBoundingClientRect();return Le.top>=44&&Le.left>=0});ie&&(ie.focus(),ie.scrollIntoView(dt))}}),Re("x",()=>{const R=document.activeElement.closest(".status-link, .status-focus");if(R){const G=R.nextElementSibling;G&&G.tagName.toLowerCase()==="details"&&(G.open=!G.open)}});const[H,ae]=$(!1),Q=D(l?"media+status":"status"),ye=Ve((R,G,K,ie)=>{R.preventDefault(),R.stopPropagation(),a({media:G+1,mediaStatusID:ie.id})},[t]),V=Ve((R,G)=>{zt(G.id)},[]);B(()=>{let R;return u&&l&&(R=setTimeout(()=>{var K;const G=(K=U.current)==null?void 0:K.querySelector(`.status-link[href*="/${u}"]`);G&&G.scrollIntoView(dt)},400)),()=>{clearTimeout(R)}},[u,l]);const Z=Ve((R,G)=>{const{id:K,ancestor:ie,isThread:we,descendant:Le,thread:$e,replies:q,repliesCount:ge,weight:be}=R,ue=K===t;return e("li",{ref:ue?L:null,class:`${ie?"ancestor":""} ${Le?"descendant":""} ${$e?"thread":""} ${ue?"hero":""}`,children:[ue?e(A,{children:[e(je,{threshold:.1,onChange:xe=>{queueMicrotask(()=>{requestAnimationFrame(()=>{ne(xe)})})},class:"status-focus",tabIndex:0,children:e(Me,{statusID:K,instance:f,withinContext:!0,size:"l",enableTranslate:!0,forceTranslate:r})}),T!=="loading"&&!v?e("div",{class:"post-status-banner",children:[e("p",{children:"You're not logged in. Interactions (reply, boost, etc) are not possible."}),e(ee,{to:"/login",class:"button",children:"Log in"})]}):!m&&e("div",{class:"post-status-banner",children:[e("p",{children:["This post is from another instance (",e("b",{children:f}),"). Interactions (reply, boost, etc) are not possible."]}),e("button",{type:"button",disabled:T==="loading",onClick:()=>{x("loading"),(async()=>{try{const xe=await b.v2.search.fetch({q:C.url,type:"statuses",resolve:!0,limit:1});if(xe.statuses.length){const Pe=xe.statuses[0];location.hash=g?`/${g}/s/${Pe.id}`:`/s/${Pe.id}`}else throw new Error("No results")}catch(xe){x("default"),alert("Error: "+xe)}})()},children:[e(w,{icon:"transfer"})," Switch to my instance to enable interactions"]})]})]}):e(ee,{class:"status-link",to:f?`/${f}/s/${K}`:`/s/${K}`,onClick:()=>{zt(K)},children:[e(je,{skip:G!==0||!ie,threshold:.5,onChange:xe=>{queueMicrotask(()=>{requestAnimationFrame(()=>{ae(xe)})})},children:e(Me,{statusID:K,instance:f,withinContext:!0,size:$e||ie?"m":"s",enableTranslate:!0,onMediaClick:ye,onStatusLinkClick:V})}),ie&&ge>1&&e("div",{class:"replies-link",children:[e(w,{icon:"comment2"})," ",e("span",{title:ge,children:Ue(ge)})]})," "]}),Le&&(q==null?void 0:q.length)>0&&e(fs,{instance:f,replies:q,hasParentThread:$e,level:1,accWeight:be,openAll:O.current{k.reloadStatusPage++},children:"Try again"})]})]},K)},[t,f,T,v,m,r,ye,V,X]),ce=he(()=>{var R;if("navigation"in window&&(navigation!=null&&navigation.entries)){const G=navigation.entries()[navigation.currentEntry.index-1];if(G!=null&&G.url)return Cn.test(G.url)}return Cn.test((R=k.prevLocation)==null?void 0:R.pathname)},[N]),fe=he(()=>{if(!re)return[];const R=[];function G(K){R.push(K.id),K.replies&&K.replies.forEach(G)}return S.slice(W).forEach(G),R.map(K=>Ge(K,f))},[re,S,W,f]);return e("div",{tabIndex:"-1",ref:U,class:`status-deck deck contained ${S.length>1?"padded-bottom":""} ${Q.current==="status"&&!c.current?"slide-in":""} ${d?`deck-view-${d}`:""}`,onAnimationEnd:R=>{Q.current==="status"&&(Q.current=null)},children:[e("header",{class:`${T==="loading"?"loading":""}`,onDblClick:R=>{k.reloadStatusPage++},children:e("div",{class:"header-grid header-grid-2",children:[e("h1",{children:[ce&&e("button",{type:"button",class:"plain deck-back",onClick:()=>{history.back()},children:e(w,{icon:"chevron-left",size:"xl"})}),!j&&C&&T!=="loading"?e(A,{children:[e("span",{class:"hero-heading",children:[e(It,{account:C.account,instance:f,showAvatar:!0,short:!0})," ",e("span",{class:"insignificant",children:["•"," ",e($t,{datetime:C.createdAt,format:"micro"})]})]})," ",e("button",{type:"button",class:"ancestors-indicator light small",onClick:R=>{R.preventDefault(),R.stopPropagation(),L.current.scrollIntoView({behavior:"smooth",block:"start"})},title:"Go to main post",children:e(w,{icon:le==="down"?"arrow-down":"arrow-up"})})]}):e(A,{children:["Post"," ",e("button",{type:"button",class:"ancestors-indicator light small",onClick:R=>{R.preventDefault(),R.stopPropagation(),U.current.scrollTo({top:0,behavior:"smooth"})},hidden:!E.length||H,title:`${E.length} posts above ‒ Go to top`,children:[e(w,{icon:"arrow-up"}),E.filter((R,G,K)=>K.findIndex(ie=>ie.accountID===R.accountID)===G).slice(0,3).map(R=>e(et,{url:R.account.avatar,alt:R.account.displayName},R.account.id)),E.length>3&&e(A,{children:[" ",e("span",{class:"insignificant",children:Ue(E.length)})]})]})]})]}),e("div",{class:"header-side",children:[e("button",{type:"button",class:"plain4 button-switch-view",style:{display:d==="full"?"":"none"},onClick:()=>{h(null),o.delete("media"),o.delete("media-only"),o.delete("view"),a(o)},title:"Switch to Side Peek view",children:e(w,{icon:"layout4",size:"l"})}),e(Fe,{align:"end",portal:{target:U.current},menuButton:e("button",{type:"button",class:"button plain4",children:e(w,{icon:"more",alt:"Actions",size:"xl"})}),children:[e(oe,{disabled:T==="loading",onClick:()=>{k.reloadStatusPage++},children:[e(w,{icon:"refresh"}),e("span",{children:"Refresh"})]}),e(oe,{className:"menu-switch-view",onClick:()=>{h(d==="full"?null:"full"),o.delete("media"),o.delete("media-only"),d==="full"?o.delete("view"):o.set("view","full"),a(o)},children:[e(w,{icon:{"":"layout5",full:"layout4"}[d||""]}),e("span",{children:["Switch to ",d==="full"?"Side Peek":"Full"," view"]})]}),e(oe,{onClick:()=>{Array.from(U.current.querySelectorAll(".spoiler-button:not(.spoiling), .spoiler-media-button:not(.spoiling)")).forEach(G=>{G.click()})},children:[e(w,{icon:"eye-open"})," ",e("span",{children:"Show all sensitive content"})]}),e(De,{}),e(jn,{className:"plain",children:"Experimental"}),e(oe,{disabled:!Y||te,onClick:()=>{const R=Fo(C.url);R?location.hash=R:alert("Unable to switch")},children:[e(w,{icon:"transfer"}),e("small",{class:"menu-double-lines",children:["Switch to post's instance",Y?e(A,{children:[" ","(",e("b",{children:Y}),")"]}):""]})]})]}),e(ee,{class:"button plain deck-close",to:n,children:e(w,{icon:"x",size:"xl"})})]})]})}),S.length&&C?e("ul",{class:`timeline flat contextual grow ${T==="loading"?"loading":""}`,children:[S.slice(0,W).map(Z),re>0&&e("li",{children:e("button",{type:"button",class:"plain block show-more",disabled:T==="loading",onClick:()=>ke(R=>R+wt),style:{marginBlockEnd:"6em"},"data-state-post-ids":fe.join(" "),children:[e("div",{class:"ib avatars-bunch",children:S.slice(W,W+5).map(R=>e(et,{url:R.account.avatarStatic},R.id))})," ",e("div",{class:"ib",children:["Show more…"," ",e("span",{class:"tag",children:re>wt?`${wt}+`:re})]})]})})]}):e(A,{children:[T==="loading"&&e("ul",{class:"timeline flat contextual grow loading",children:e("li",{children:e(Me,{skeleton:!0,size:"l"})})}),T==="error"&&e("p",{class:"ui-state",children:["Unable to load post",e("br",{}),e("br",{}),e("button",{type:"button",onClick:()=>{k.reloadStatusPage++},children:"Try again"})]})]})]})}function fs({replies:t,instance:n,hasParentThread:i,level:o,accWeight:a,openAll:s}){const[u,l]=qe(),c=m=>m.reduce((y,S)=>{const{repliesCount:I,replies:T}=S,x=(T==null?void 0:T.length)||I;return y+x+c(T||[])},0),d=t.length+c(t),h=t.length===d,r=t.map(m=>m.account).filter((m,y,S)=>S.findIndex(I=>I.id===m.id)===y).slice(0,3),p=he(()=>t==null?void 0:t.reduce((m,y)=>m+(y==null?void 0:y.weight),a),[a,t==null?void 0:t.length]);let f=!1;(s||p<=Xo||!i&&d===1&&ft(t[0])<2)&&(f=!0);const b=Bt[t[0].id],g=Ve((m,y,S,I)=>{m.preventDefault(),m.stopPropagation(),l({media:y+1,mediaStatusID:I.id})},[]),v=D();return Je(()=>{var y;function m(S){S.target.dataset.scrollLeft=S.target.scrollLeft}return(y=v.current)==null||y.addEventListener("scroll",m,{passive:!0}),()=>{var S;(S=v.current)==null||S.removeEventListener("scroll",m)}},[]),e("details",{ref:v,class:"replies",open:b||f,onToggle:m=>{const{open:y}=m.target;Bt[t[0].id]=y},style:{"--comments-level":o},"data-comments-level":o,"data-comments-level-overflow":o>4,children:[e("summary",{class:"replies-summary",hidden:f,children:[e("span",{class:"avatars",children:r.map(m=>e(et,{url:m.avatarStatic,title:`${m.displayName} @${m.username}`,squircle:m==null?void 0:m.bot},m.id))}),e("b",{children:[e("span",{title:t.length,children:Ue(t.length)})," ","repl",t.length===1?"y":"ies"]}),!h&&d>1&&e(A,{children:[" ","·"," ",e("span",{children:[e("span",{title:d,children:Ue(d)})," ","comment",d===1?"":"s"]})]})]}),e("ul",{children:t.map(m=>{var y,S;return e("li",{children:[e(ee,{class:"status-link",to:n?`/${n}/s/${m.id}`:`/s/${m.id}`,onClick:()=>{zt(m.id)},children:[e(Me,{statusID:m.id,instance:n,withinContext:!0,size:"s",enableTranslate:!0,onMediaClick:g}),!((y=m.replies)!=null&&y.length)&&m.repliesCount>0&&e("div",{class:"replies-link",children:[e(w,{icon:"comment2"})," ",e("span",{title:m.repliesCount,children:Ue(m.repliesCount)})]})]}),((S=m.replies)==null?void 0:S.length)&&e(fs,{instance:n,replies:m.replies,level:o+1,accWeight:f?p:m.weight,openAll:s})]},m.id)})})]})}const ta=140,na=35,sa=70,ia=140,qt=new Map;function ft(t){var f,b;const n=qt.get(t.id);if(n)return n;const{spoilerText:i,content:o,mediaAttachments:a,poll:s,card:u}=t,l=xs(i+o),c=a!=null&&a.length?ta:0,d=(((f=s==null?void 0:s.options)==null?void 0:f.length)||0)*na,h=u&&(a!=null&&a.length||(b=s==null?void 0:s.options)!=null&&b.length)?0:sa,p=(l+c+d+h)/ia;return qt.set(t.id,p),p}const oa=ze(Qo);function aa(){const t=nt(),{id:n,instance:i}=t;return e(oa,{id:n,instance:i})}const ca=""+new URL("boosts-carousel-YjmjXTE6.jpg",import.meta.url).href,ra=""+new URL("grouped-notifications-xYMFVY91.jpg",import.meta.url).href,la=""+new URL("multi-column-ETnJNDVb.jpg",import.meta.url).href,da=""+new URL("multi-hashtag-timeline-x-SDVR4g.jpg",import.meta.url).href,ua=""+new URL("nested-comments-thread-Ib-fZGS3.jpg",import.meta.url).href,ha="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20xml:space='preserve'%20fill-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%20clip-rule='evenodd'%20viewBox='0%200%20102%2028'%3e%3cpath%20fill='none'%20d='M0%200h101.5v27.5H0z'/%3e%3cg%20fill-rule='nonzero'%3e%3cpath%20fill='url(%23a)'%20d='M2.32%2021.85c1.4%200%202.21-.85%202.21-2.3v-4.64H8.5c4.45%200%207.54-2.9%207.54-7.24%200-4.35-2.98-7.24-7.32-7.24h-6.4C.93.43.11%201.28.11%202.73v16.82c0%201.45.82%202.3%202.21%202.3Zm2.21-10.4V3.94h3c2.54%200%204%201.34%204%203.75s-1.47%203.76-4%203.76h-3Z'/%3e%3cpath%20fill='url(%23b)'%20d='M20.52%2021.88c1.25%200%202.13-.76%202.13-2.23v-7.04c0-2.07%201.2-3.49%203.21-3.49%201.95%200%202.95%201.23%202.95%203.25v7.28c0%201.47.89%202.23%202.13%202.23%201.26%200%202.14-.76%202.14-2.23v-8.18c0-3.64-1.99-5.9-5.48-5.9-2.38%200-4.1%201.12-4.93%203.1h-.09V2.3c0-1.38-.78-2.2-2.1-2.2-1.31%200-2.1.82-2.1%202.2v17.34c0%201.47.9%202.23%202.14%202.23Z'/%3e%3cpath%20fill='url(%23c)'%20d='M40.45%2021.82c1.96%200%203.93-.98%204.8-2.65h.1v.8c.08%201.27.89%201.91%202.05%201.91%201.21%200%202.08-.73%202.08-2.15v-8.95c0-3.17-2.63-5.25-6.65-5.25-3.26%200-5.78%201.16-6.5%203.04-.15.32-.23.63-.23.96%200%20.97.75%201.64%201.79%201.64.69%200%201.23-.26%201.7-.79.95-1.23%201.74-1.65%203.04-1.65%201.62%200%202.64.85%202.64%202.31v1.04l-3.95.24c-3.93.23-6.13%201.88-6.13%204.74%200%202.83%202.27%204.76%205.26%204.76Zm1.4-3.09c-1.43%200-2.4-.73-2.4-1.9%200-1.12.91-1.83%202.51-1.95l3.31-.2v1.14c0%201.7-1.54%202.91-3.41%202.91Z'/%3e%3cpath%20fill='url(%23d)'%20d='M54.37%2021.88c1.26%200%202.14-.76%202.14-2.23v-7.09c0-2.03%201.21-3.44%203.13-3.44s2.89%201.17%202.89%203.22v7.31c0%201.47.88%202.23%202.14%202.23%201.24%200%202.13-.76%202.13-2.23v-8.2c0-3.68-1.96-5.87-5.45-5.87-2.41%200-4%201.07-4.83%203.01h-.09v-.87c0-1.35-.85-2.17-2.14-2.17-1.28%200-2.06.82-2.06%202.15v11.95c0%201.47.9%202.23%202.14%202.23Z'/%3e%3cpath%20fill='url(%23e)'%20d='M71.65%2027.17c1.26%200%202.14-.76%202.14-2.23v-6h.09a5.15%205.15%200%200%200%204.88%202.88c3.92%200%206.35-3.05%206.35-8.1%200-5.07-2.44-8.1-6.43-8.1a5.12%205.12%200%200%200-4.86%202.99h-.09v-.85c0-1.45-.88-2.21-2.1-2.21-1.24%200-2.11.76-2.11%202.2v17.2c0%201.46.89%202.22%202.13%202.22Zm5.6-8.8c-2.1%200-3.47-1.8-3.47-4.65%200-2.81%201.37-4.67%203.47-4.67%202.14%200%203.49%201.83%203.49%204.67%200%202.86-1.35%204.66-3.5%204.66Z'/%3e%3cpath%20fill='url(%23f)'%20d='M89.61%2027.39c3.44%200%205.26-1.5%206.73-5.55l4.81-13.1a4%204%200%200%200%20.24-1.26c0-1.13-.85-1.93-2.08-1.93-1.1%200-1.71.51-2.07%201.7l-3.4%2010.9h-.08L90.35%207.28c-.36-1.25-.94-1.73-2.07-1.73-1.26%200-2.21.83-2.21%201.99%200%20.35.09.82.25%201.26l5%2013.21-.21.56c-.52%201.1-1.32%201.42-2.07%201.42l-.75-.01c-.96%200-1.56.54-1.56%201.4%200%201.29%201%202%202.88%202Z'/%3e%3c/g%3e%3cdefs%3e%3cradialGradient%20id='a'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='b'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='c'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='d'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='e'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='f'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3c/defs%3e%3c/svg%3e";var fa={PHANPY_CLIENT_NAME:"Phanpy",PHANPY_WEBSITE:"https://phanpy.social",PHANPY_LINGVA_INSTANCES:"lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud",PHANPY_PRIVACY_POLICY_URL:"https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD",VITE_APP_ENV:"production",BASE_URL:"./",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const{PHANPY_DEFAULT_INSTANCE:ut,PHANPY_WEBSITE:$n,PHANPY_PRIVACY_POLICY_URL:pa,PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL:xn}=fa,An=$n?$n.replace(/https?:\/\//g,"").replace(/\/$/,""):null,Ln=`${"2024-01-05T02:16:32.524Z".slice(0,10).replace(/-/g,".")}.adf0b35`;function Mn(){return _e(null,["/","/welcome"]),e("main",{id:"welcome",children:[e("div",{class:"hero-container",children:[e("div",{class:"hero-content",children:[e("h1",{children:[e("img",{src:Gt,alt:"",width:"160",height:"160",style:{aspectRatio:"1/1",marginBlockEnd:-16}}),e("img",{src:ha,alt:"Phanpy",width:"200"})]}),e("p",{class:"desc",children:"A minimalistic opinionated Mastodon web client."}),e("p",{children:e(ee,{to:ut?`/login?instance=${ut}&submit=1`:"/login",class:"button",children:ut?"Log in":"Log in with Mastodon"})}),ut&&xn&&e("p",{children:e("a",{href:xn,class:"button plain5",children:"Sign up"})}),!ut&&e("p",{class:"insignificant",children:e("small",{children:["Connect your existing Mastodon/Fediverse account.",e("br",{}),"Your credentials are not stored on this server."]})})]}),(An||Ln)&&e("p",{class:"app-site-version",children:e("small",{children:[An," ",Ln]})}),e("p",{children:[e("a",{href:"https://github.com/cheeaun/phanpy",target:"_blank",children:"Built"})," ","by"," ",e("a",{href:"https://mastodon.social/@cheeaun",target:"_blank",onClick:t=>{t.preventDefault(),k.showAccount="cheeaun@mastodon.social"},children:"@cheeaun"}),"."," ",e("a",{href:pa,target:"_blank",children:"Privacy Policy"}),"."]})]}),e("div",{id:"why-container",children:e("div",{class:"sections",children:[e("section",{children:[e("img",{src:ca,alt:"Screenshot of Boosts Carousel",loading:"lazy"}),e("h4",{children:"Boosts Carousel"}),e("p",{children:"Visually separate original posts and re-shared posts (boosted posts)."})]}),e("section",{children:[e("img",{src:ua,alt:"Screenshot of nested comments thread",loading:"lazy"}),e("h4",{children:"Nested comments thread"}),e("p",{children:"Effortlessly follow conversations. Semi-collapsible replies."})]}),e("section",{children:[e("img",{src:ra,alt:"Screenshot of grouped notifications",loading:"lazy"}),e("h4",{children:"Grouped notifications"}),e("p",{children:"Similar notifications are grouped and collapsed to reduce clutter."})]}),e("section",{children:[e("img",{src:la,alt:"Screenshot of multi-column UI",loading:"lazy"}),e("h4",{children:"Single or multi-column"}),e("p",{children:"By default, single column for zen-mode seekers. Configurable multi-column for power users."})]}),e("section",{children:[e("img",{src:da,alt:"Screenshot of multi-hashtag timeline with a form to add more hashtags",loading:"lazy"}),e("h4",{children:"Multi-hashtag timeline"}),e("p",{children:"Up to 5 hashtags combined into a single timeline."})]})]})})]})}const ma=window.alert;window.__nativeAlert||(window.__nativeAlert=ma);window.alert=function(t){t instanceof Error&&(t!=null&&t.message)&&(t=t.message),typeof t!="string"&&(t=JSON.stringify(t));const n=Bs({text:t,className:"alert",gravity:"top",position:"center",duration:1e4,offset:{y:48},onClick:()=>{n.hideToast()}});n.showToast()};window.__STATES__=k;window.__STATES_STATS__=()=>{const t=["statuses","accounts","spoilers","unfurledLinks","statusQuotes"],n={};t.forEach(a=>{n[a]=Object.keys(k[a]).length});const{statuses:i}=k,o=[];for(const a in i)document.querySelector(`[data-state-post-id~="${a}"], [data-state-post-ids~="${a}"]`)||o.push(a)};setInterval(()=>{if(!window.__IDLE__)return;const{statuses:t,unfurledLinks:n,notifications:i}=k;let o=0;const{instance:a}=z();for(const s in t){if(!window.__IDLE__)break;try{const u=document.querySelector(`[data-state-post-id~="${s}"], [data-state-post-ids~="${s}"]`),l=i.some(c=>{var d;return s===Ge((d=c.status)==null?void 0:d.id,a)});if(!u&&!l){delete k.statuses[s],delete k.statusQuotes[s];for(const c in n){const d=n[c];if(Ge(d.id,d.instance)===s){delete k.unfurledLinks[c];break}}o++}}catch{}}},15*60*1e3);setTimeout(()=>{for(const t in gt)queueMicrotask(()=>{var n,i,o,a;Array.isArray(gt[t])?(i=(n=gt[t])[0])==null||i.call(n):(a=(o=gt)[t])==null||a.call(o)})},5e3);(()=>{window.__IDLE__=!0;const t=["mousemove","mousedown","resize","keydown","touchstart","pointerdown","pointermove","wheel"],n=()=>{window.__IDLE__=!0},o=Yn(n,3e3),a=()=>{window.__IDLE__=!1,o()};t.forEach(s=>{window.addEventListener(s,a,{passive:!0,capture:!0})}),window.addEventListener("blur",n,{passive:!0}),document.documentElement.addEventListener("mouseleave",s=>{!s.relatedTarget&&!s.toElement&&n()},{passive:!0})})();const ga=/iPad|iPhone|iPod/.test(navigator.userAgent);ga&&document.addEventListener("visibilitychange",()=>{if(document.visibilityState==="visible"){const t=se.local.get("theme");let n;if(t){if(n=document.querySelector('meta[name="theme-color"][data-theme-setting="manual"]'),n){const i=n.content,o=t==="light"?n.dataset.themeLightColorTemp:n.dataset.themeDarkColorTemp;n.content=o||"",setTimeout(()=>{n.content=i},10)}}else{const i=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";if(n=document.querySelector(`meta[name="theme-color"][media*="${i}"]`),n){const o=n.dataset.content,a=n.dataset.contentTemp;n.content=a||"",setTimeout(()=>{n.content=o},10)}}}});{const t=se.local.get("theme");if(t){document.documentElement.classList.add(`is-${t}`),document.querySelector('meta[name="color-scheme"]').setAttribute("content",t||"dark light");const i=document.querySelector('meta[data-theme-setting="manual"]');i&&(i.name="theme-color",i.content=t==="light"?i.dataset.themeLightColor:i.dataset.themeDarkColor),document.querySelectorAll('meta[data-theme-setting="auto"]').forEach(a=>{a.name=""})}const n=se.local.get("textSize");n&&document.documentElement.style.setProperty("--text-size",`${n}px`)}Hn(k,t=>{var n;for(const[i,o,a,s]of t){if(o.join(".")==="settings.shortcutsViewMode"){const u=document.getElementById("app");u&&(u.dataset.shortcutsViewMode=(n=k.shortcuts)!=null&&n.length?a:"")}o.join(".")==="settings.cloakMode"&&document.body.classList.toggle("cloak",a)}});function ba(){const[t,n]=$(!1),[i,o]=$("loading");B(()=>{const s=se.local.get("instanceURL"),u=decodeURIComponent((window.location.search.match(/code=([^&]+)/)||[,""])[1]);if(u){window.history.replaceState({},document.title,window.location.pathname||"/");const l=se.session.get("clientID"),c=se.session.get("clientSecret"),d=se.session.get("vapidKey");(async()=>{o("loading");const{access_token:h}=await Yo({instanceURL:s,client_id:l,client_secret:c,code:u}),r=As({instance:s,accessToken:h});await Promise.allSettled([nn(r,s),Ls(r,s,h,d)]),sn(),on(r),n(!0),o("default")})()}else{window.__IGNORE_GET_ACCOUNT_ERROR__=!0;const l=at();if(l){se.session.set("currentAccount",l.info.id);const{client:c}=z({account:l}),{instance:d}=c;sn(),on(c),o("loading"),(async()=>{try{await nn(c,d)}catch{}finally{n(!0),o("default")}})()}else o("default")}},[]);let a=lt();return k.currentLocation=a.pathname,B(Dt,[a,t]),/\/https?:/.test(a.pathname)?e(Oo,{}):e(A,{children:[e(ya,{isLoggedIn:t,loading:i==="loading"}),e(wa,{isLoggedIn:t}),i==="default"&&e(Vt,{children:e(Te,{path:"/:instance?/s/:id",element:e(aa,{})})}),t&&e(js,{}),t&&e(Vi,{}),e(Oi,{}),t&&e(zi,{}),e(Gs,{isLoggedIn:t}),i!=="loading"&&e(qi,{onClose:Dt}),e(Ys,{})]})}function ya({isLoggedIn:t,loading:n}){const i=lt(),o=he(()=>{const{pathname:a}=i;return!/^\/(login|welcome)/.test(a)},[i]);return e(Vt,{location:o||i,children:[e(Te,{path:"/",element:t?e(Do,{}):n?e(Ie,{id:"loader-root"}):e(Mn,{})}),e(Te,{path:"/login",element:e(Zo,{})}),e(Te,{path:"/welcome",element:e(Mn,{})})]})}function Rn(){return k.prevLocation||null}function wa({isLoggedIn:t}){const n=lt(),i=D(Rn());return he(()=>pt("/:instance/s/:id",n.pathname)||pt("/s/:id",n.pathname),[n.pathname,pt])?i.current||(i.current=Rn()):i.current=null,e(Vt,{location:i.current||n,children:[t&&e(A,{children:[e(Te,{path:"/notifications",element:e(ls,{})}),e(Te,{path:"/mentions",element:e(cs,{})}),e(Te,{path:"/following",element:e(Jt,{})}),e(Te,{path:"/b",element:e(ss,{})}),e(Te,{path:"/f",element:e(is,{})}),e(Te,{path:"/l",children:[e(Te,{index:!0,element:e(Bo,{})}),e(Te,{path:":id",element:e(as,{})})]}),e(Te,{path:"/ft",element:e(lo,{})})]}),e(Te,{path:"/:instance?/t/:hashtag",element:e(os,{})}),e(Te,{path:"/:instance?/a/:id",element:e(oo,{})}),e(Te,{path:"/:instance?/p",children:[e(Te,{index:!0,element:e(Ot,{})}),e(Te,{path:"l",element:e(Ot,{local:!0})})]}),e(Te,{path:"/:instance?/trending",element:e(us,{})}),e(Te,{path:"/:instance?/search",element:e(ds,{})})]})}"AbortSignal"in window&&(AbortSignal.timeout=AbortSignal.timeout||(t=>{const n=new AbortController;return setTimeout(()=>n.abort(),t),n.signal}));qs(e(zs,{children:e(ba,{})}),document.getElementById("app"));setTimeout(()=>{try{Object.keys(localStorage).forEach(t=>{t.startsWith("iconify")&&localStorage.removeItem(t)}),Object.keys(sessionStorage).forEach(t=>{t.startsWith("iconify")&&sessionStorage.removeItem(t)}),localStorage.removeItem("settings:boostsCarousel")}catch{}},5e3);window.__CLOAK__=()=>{document.body.classList.toggle("cloak")};
-//# sourceMappingURL=main-93nxKW6L.js.map
+ `,children:e(Fn,{class:t,media:ie,lang:_,to:`/${o}/s/${y}?media-only=${we+1}`,onClick:s?q=>s(q,we,ie,i):void 0})},Le)})}const vn=ze(Ji);function mt(t){var S,I,T,x,L;const n=Se(k),{masto:i,instance:o,authenticated:a}=z(),[s,u]=$(),[l,c]=$(!1);B(()=>{const N=se.local.getJSON("accounts")||[],O=N.find(U=>U.info.id===se.session.get("currentAccount"));O&&u(O),c(N.length>1)},[]);const d=(n.settings.shortcutsViewMode==="multi-column"||!n.settings.shortcutsViewMode&&n.settings.shortcutsColumnsMode)&&!n.shortcuts.find(N=>N.type==="following"),h=Ns(()=>{k.showAccounts=!0},{threshold:600,detect:"touch",cancelOnMovement:!0}),r=D(),[p,f]=$(void 0),b=Ts([0,0,n.settings.shortcutsViewMode==="tab-menu-bar"?50:0,0]),g=D();async function v(N){return(N||!g.current)&&(g.current=i.v1.mutes.list({limit:80})),await g.current.next()}const m=D();async function y(N){return(N||!m.current)&&(m.current=i.v1.blocks.list({limit:80})),await m.current.next()}return e(A,{children:[e("button",{ref:r,type:"button",class:`button plain nav-menu-button ${l?"with-avatar":""} ${open?"active":""}`,style:{position:"relative"},onClick:()=>{f(N=>N?void 0:"open")},onContextMenu:N=>{N.preventDefault(),k.showAccounts=!0},...h(),children:[l&&e(et,{url:((S=s==null?void 0:s.info)==null?void 0:S.avatar)||((I=s==null?void 0:s.info)==null?void 0:I.avatarStatic),size:"l",squircle:(T=s==null?void 0:s.info)==null?void 0:T.bot}),e(w,{icon:"menu",size:l?"s":"l"})]}),e(Gn,{menuClassName:"nav-menu",state:p,anchorRef:r,onClose:()=>{f(void 0)},containerProps:{style:{zIndex:10},onClick:()=>{f(void 0)}},portal:{target:document.body},...t,overflow:"auto",viewScroll:"close",position:"anchor",align:"center",boundingBoxPadding:b,unmountOnClose:!0,children:[!!((x=n.appVersion)!=null&&x.commitHash)&&n.appVersion.commitHash!=="32c53b8"&&e("div",{class:"top-menu",children:[e(oe,{onClick:()=>{confirm("Reload page now to update?")&&(async()=>{try{location.reload()}catch{}})()},children:[e(w,{icon:"sparkles",class:"sparkle-icon",size:"l"})," ",e("span",{children:"New update available…"})]}),e(De,{})]}),e("section",{children:[e(Ee,{to:"/",children:[e(w,{icon:"home",size:"l"})," ",e("span",{children:"Home"})]}),a&&e(A,{children:[d&&e(Ee,{to:"/following",children:[e(w,{icon:"following",size:"l"})," ",e("span",{children:"Following"})]}),e(Ee,{to:"/mentions",children:[e(w,{icon:"at",size:"l"})," ",e("span",{children:"Mentions"})]}),e(Ee,{to:"/notifications",children:[e(w,{icon:"notification",size:"l"})," ",e("span",{children:"Notifications"}),n.notificationsShowNew&&e("sup",{title:"New",style:{opacity:.5},children:[" ","•"]})]}),e(De,{}),e(Ee,{to:"/l",children:[e(w,{icon:"list",size:"l"})," ",e("span",{children:"Lists"})]}),e(Ee,{to:"/ft",children:[e(w,{icon:"hashtag",size:"l"})," ",e("span",{children:"Followed Hashtags"})]}),e(Ee,{to:"/b",children:[e(w,{icon:"bookmark",size:"l"})," ",e("span",{children:"Bookmarks"})]}),e(Ee,{to:"/f",children:[e(w,{icon:"heart",size:"l"})," ",e("span",{children:"Likes"})]})]}),e(De,{}),e(Ee,{to:"/search",children:[e(w,{icon:"search",size:"l"})," ",e("span",{children:"Search"})]}),e(Ee,{to:`/${o}/p/l`,children:[e(w,{icon:"building",size:"l"})," ",e("span",{children:"Local"})]}),e(Ee,{to:`/${o}/p`,children:[e(w,{icon:"earth",size:"l"})," ",e("span",{children:"Federated"})]}),e(Ee,{to:`/${o}/trending`,children:[e(w,{icon:"chart",size:"l"})," ",e("span",{children:"Trending"})]})]}),e("section",{children:a?e(A,{children:[e(De,{}),((L=s==null?void 0:s.info)==null?void 0:L.id)&&e(Ee,{to:`/${o}/a/${s.info.id}`,children:[e(w,{icon:"user",size:"l"})," ",e("span",{children:"Profile"})]}),e(oe,{onClick:()=>{k.showAccounts=!0},children:[e(w,{icon:"group",size:"l"})," ",e("span",{children:"Accounts…"})]}),e(oe,{onClick:()=>{k.showGenericAccounts={id:"mute",heading:"Muted users",fetchAccounts:v,excludeRelationshipAttrs:["muting"]}},children:[e(w,{icon:"mute",size:"l"})," Muted users…"]}),e(oe,{onClick:()=>{k.showGenericAccounts={id:"block",heading:"Blocked users",fetchAccounts:y,excludeRelationshipAttrs:["blocking"]}},children:[e(w,{icon:"block",size:"l"}),"Blocked users…"]}),e(De,{className:"divider-grow"}),e(oe,{onClick:()=>{k.showKeyboardShortcutsHelp=!0},children:[e(w,{icon:"keyboard",size:"l"})," ",e("span",{children:"Keyboard shortcuts"})]}),e(oe,{onClick:()=>{k.showShortcutsSettings=!0},children:[e(w,{icon:"shortcut",size:"l"})," ",e("span",{children:"Shortcuts / Columns…"})]}),e(oe,{onClick:()=>{k.showSettings=!0},children:[e(w,{icon:"gear",size:"l"})," ",e("span",{children:"Settings…"})]})]}):e(A,{children:[e(De,{}),e(Ee,{to:"/login",children:[e(w,{icon:"user",size:"l"})," ",e("span",{children:"Log in"})]}),e(oe,{onClick:()=>{k.showSettings=!0},children:[e(w,{icon:"gear",size:"l"})," ",e("span",{children:"Settings…"})]})]})})]})]})}const bt={block:"nearest",inline:"center",behavior:"smooth"};function Ye({title:t,titleComponent:n,id:i,instance:o,emptyText:a,errorText:s,useItemID:u,boostsCarousel:l,fetchItems:c=()=>{},checkForUpdates:d=()=>{},checkForUpdatesInterval:h=15e3,headerStart:r,headerEnd:p,timelineStart:f,refresh:b,view:g,filterContext:v,showFollowedTags:m}){const y=Se(k),[S,I]=$([]),[T,x]=$("default"),[L,N]=$(!1),[O,U]=$(!1),[P,M]=$(!0),C=D(),_=g!=="media",F=Ds(H=>{U(!1),T!=="loading"&&(x("loading"),(async()=>{try{let{done:ae,value:Q}=await c(H);if(Array.isArray(Q)){const[ye,V]=Q.reduce((Z,ce)=>(ce._pinned?Z[0].push(ce):Z[1].push(ce),Z),[[],[]]);Q=V,_&&(l&&(Q=Gi(Q)),Q=ji(Q)),ye.length&&(Q=ye.concat(Q)),I(H?Q:Z=>[...Z,...Q]),Q.length||(ae=!0),N(!ae)}else N(!1);x("default")}catch{x("error")}finally{F.cancel()}})())},1500,{leading:!0,trailing:!1}),Y=".timeline-item, .timeline-item-alt",te=Re("j, shift+j",(H,ae)=>{const Q=document.activeElement.closest(Y),ye=Q==null?void 0:Q.getBoundingClientRect(),V=Array.from(C.current.querySelectorAll(Y));if(Q&&ye.top0){const Z=V.indexOf(Q);let ce=V[Z+1];ae.shift&&(ce=V.find((fe,me)=>me>Z&&!fe.classList.contains("timeline-item-alt"))),ce&&(ce.focus(),ce.scrollIntoView(bt))}else{const Z=V.find(ce=>{const fe=ce.getBoundingClientRect();return fe.top>=44&&fe.left>=0});Z&&(Z.focus(),Z.scrollIntoView(bt))}}),W=Re("k, shift+k",(H,ae)=>{const Q=document.activeElement.closest(Y),ye=Q==null?void 0:Q.getBoundingClientRect(),V=Array.from(C.current.querySelectorAll(Y));if(Q&&ye.top0){const Z=V.indexOf(Q);let ce=V[Z-1];ae.shift&&(ce=V.findLast((fe,me)=>me{const fe=ce.getBoundingClientRect();return fe.top>=44&&fe.left>=0});Z&&(Z.focus(),Z.scrollIntoView(bt))}}),ke=Re(["enter","o"],()=>{const H=document.activeElement.closest(Y);H&&H.click()}),re=D(),[X,E]=$(!1);Zi({scrollableRef:C,distanceFromEnd:2,scrollThresholdStart:44},({scrollDirection:H,nearReachStart:ae,nearReachEnd:Q,reachStart:ye,reachEnd:V})=>{if(re.current){const Z=H==="end"&&!ae;re.current.hidden=Z}E(ae),ye&&F(!0)},[]),B(()=>{var H;(H=C.current)==null||H.scrollTo({top:0}),F(!0)},[]),B(()=>{F(!0)},[b]);const j=D(g);B(()=>{j.current!==g&&(j.current=g,I([]))},[g]);const ne=Ve(async({disableIdleCheck:H=!1}={})=>{const ae=C.current?getComputedStyle(C.current).pointerEvents==="none":!1;y.settings.autoRefresh&&C.current.scrollTop<16&&(H||window.__IDLE__)&&!to()&&!ae?F(!0):await d()&&U(!0)},[i,F,d,y.settings.autoRefresh]),le=D();return ct(H=>{if(H){const ae=Date.now()-le.current;(!le.current||ae>1e3*3)&&ne({disableIdleCheck:!0})}else le.current=Date.now();M(H)},[d,ne,y.settings.autoRefresh]),_n(ne,P&&!O?h*(X?1:2):null),e(On.Provider,{value:v,children:e("div",{id:`${i}-page`,class:"deck-container",ref:H=>{C.current=H,te.current=H,W.current=H,ke.current=H},tabIndex:"-1",children:e("div",{class:"timeline-deck deck",children:[e("header",{ref:re,onClick:H=>{var ae;H.target.closest("a, button")||(ae=C.current)==null||ae.scrollTo({top:0,behavior:"smooth"})},onDblClick:H=>{H.target.closest("a, button")||F(!0)},class:T==="loading"?"loading":"",children:[e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),r??e(ee,{to:"/",class:"button plain home-button",children:e(w,{icon:"home",size:"l"})})]}),t&&(n||e("h1",{children:t})),e("div",{class:"header-side",children:!!p&&p})]}),S.length>0&&T!=="loading"&&O&&e("button",{class:"updates-button shiny-pill",type:"button",onClick:()=>{var H;F(!0),(H=C.current)==null||H.scrollTo({top:0,behavior:"smooth"})},children:[e(w,{icon:"arrow-up"})," New posts"]})]}),!!f&&e("div",{class:`timeline-start ${T==="loading"?"loading":""}`,children:f}),S.length?e(A,{children:[e("ul",{class:`timeline ${g?`timeline-${g}`:""}`,children:[S.map(H=>e(Xi,{status:H,instance:o,useItemID:u,filterContext:v,view:g,showFollowedTags:m},H.id+(H==null?void 0:H._pinned)+g)),L&&T==="loading"&&(g==="media"?null:e(A,{children:[e("li",{style:{height:"20vh"},children:e(Me,{skeleton:!0})}),e("li",{style:{height:"25vh"},children:e(Me,{skeleton:!0})})]}))]}),T==="default"&&(L?e(je,{root:C.current,rootMargin:`0px 0px ${screen.height*1.5}px 0px`,onChange:H=>{H&&F()},children:e("button",{type:"button",class:"plain block",onClick:()=>F(),style:{marginBlockEnd:"6em"},children:"Show more…"})}):e("p",{class:"ui-state insignificant",children:"The end."}))]}):T==="loading"?e("ul",{class:"timeline",children:Array.from({length:5}).map((H,ae)=>g==="media"?e("div",{style:{height:"50vh"}}):e("li",{children:e(Me,{skeleton:!0})},ae))}):T!=="error"&&e("p",{class:"ui-state",children:a}),T==="error"&&e("p",{class:"ui-state",children:[s,e("br",{}),e("br",{}),e("button",{type:"button",onClick:()=>F(!S.length),children:"Try again"})]})]})})})}function Xi({status:t,instance:n,useItemID:i,filterContext:o,view:a,showFollowedTags:s}){const{id:u,reblog:l,items:c,type:d,_pinned:h}=t;h&&(i=!1);const r=(l==null?void 0:l.id)||u,p=n?`/${n}/s/${r}`:`/s/${r}`;let f="";d==="boosts"?f=`${c.length} Boosts`:d==="pinned"&&(f="Pinned posts");const b=d==="boosts"||d==="pinned";if(c){const v=rt(c,o);if(b)return v.sort((y,S)=>{const I=Nt(y.filtered,o),T=Nt(S.filtered,o);return I&&!T?1:!I&&T?-1:0}),e("li",{class:"timeline-item-carousel",children:e(Qi,{title:f,class:`${d}-carousel`,children:v.map(y=>{const{id:S,reblog:I,_pinned:T}=y,x=(I==null?void 0:I.id)||S,L=n?`/${n}/s/${x}`:`/s/${x}`;return T&&(i=!1),e("li",{children:e(ee,{class:"status-carousel-link timeline-item-alt",to:L,children:i?e(Me,{statusID:S,instance:n,size:"s",contentTextWeight:!0,enableCommentHint:!0}):e(Me,{status:y,instance:n,size:"s",contentTextWeight:!0,enableCommentHint:!0})})},S)})})},`timeline-${u}`);const m=v.length>3;return v.map((y,S)=>{const{id:I,_differentAuthor:T}=y,x=n?`/${n}/s/${I}`:`/s/${I}`,L=S>0&&S0||m&&L&&(d==="thread"||d==="conversation"&&!T&&!v[S-1]._differentAuthor&&!v[S+1]._differentAuthor),U=S===0,P=S===v.length-1;return e("li",{class:`timeline-item-container timeline-item-container-type-${d} timeline-item-container-${U?"start":P?"end":"middle"} ${T?"timeline-item-diff-author":""}`,children:e(ee,{class:"status-link timeline-item",to:x,children:O?e(eo,{status:y,instance:n}):i?e(Me,{statusID:I,instance:n,enableCommentHint:P,showFollowedTags:s}):e(Me,{status:y,instance:n,enableCommentHint:P,showFollowedTags:s})})},`timeline-${I}`)})}const g=`timeline-${u+h}`;return a==="media"?i?e(vn,{class:"timeline-item",parent:"li",statusID:u,instance:n},g):e(vn,{class:"timeline-item",parent:"li",status:t,instance:n},g):e("li",{children:e(ee,{class:"status-link timeline-item",to:p,children:i?e(Me,{statusID:u,instance:n,enableCommentHint:!0,showFollowedTags:s}):e(Me,{status:t,instance:n,enableCommentHint:!0,showFollowedTags:s})})},g)}function Qi({title:t,class:n,children:i}){const o=D(),a=D(),s=D(),[u,l]=$(!1);return B(()=>{setTimeout(()=>{l(!0)},1)},[]),e("div",{class:`status-carousel ${n}`,children:[e("header",{children:[e("h3",{children:t}),e("span",{children:[e("button",{ref:a,type:"button",class:"small plain2",onClick:()=>{var c,d;(d=o.current)==null||d.scrollBy({left:-Math.min(320,(c=o.current)==null?void 0:c.offsetWidth),behavior:"smooth"})},children:e(w,{icon:"chevron-left"})})," ",e("button",{ref:s,type:"button",class:"small plain2",onClick:()=>{var c,d;(d=o.current)==null||d.scrollBy({left:Math.min(320,(c=o.current)==null?void 0:c.offsetWidth),behavior:"smooth"})},children:e(w,{icon:"chevron-right"})})]})]}),e("ul",{ref:o,children:[e(je,{class:"status-carousel-beacon",onChange:c=>{a.current&&(a.current.disabled=c)}}),i[0],u&&i.slice(1),e(je,{class:"status-carousel-beacon",onChange:c=>{s.current&&(s.current.disabled=c)}})]})]})}function eo({status:t,instance:n}){const i=Se(k),{id:o,visibility:a}=t,s=Bn(t),u=Ge(o,n);return e("article",{class:`status compact-thread ${a==="direct"?"visibility-direct":""}`,tabindex:"-1",children:[i.statusThreadNumber[u]?e("div",{class:"status-thread-badge",children:[e(w,{icon:"thread",size:"s"}),i.statusThreadNumber[u]?` ${i.statusThreadNumber[u]}/X`:""]}):e("div",{class:"status-thread-badge",children:e(w,{icon:"thread",size:"s"})}),e("div",{class:"content-compact",title:s,children:[s,t.sensitive&&t.spoilerText&&e(A,{children:[" ",e("span",{class:"spoiler-badge",children:e(w,{icon:"eye-close",size:"s"})})]})]})]})}function to(){return!!document.querySelector(".deck-backdrop, #modal-container > *")}const ot=20,Zt=1983,Sn=`${Zt}-01`,no=(()=>{try{const t=document.createElement("input");return t.setAttribute("type","month"),t.type==="month"}catch{return!1}})();async function so(t){var o;const{masto:n}=z({instance:t}),i=await n.v2.search.fetch({q:"from:me",type:"statuses",limit:1});return!!((o=i==null?void 0:i.statuses)!=null&&o.length)}const io=tt(so);function oo(){const t=Se(k),{id:n,...i}=nt(),[o,a]=qe(),s=o.get("month"),u=!o.get("replies"),l=!!o.get("boosts"),c=o.get("tagged"),d=!!o.get("media"),{masto:h,instance:r,authenticated:p}=z({instance:i.instance}),{masto:f,instance:b}=z(),g=D(),v=[s,u,l,c,d],[m,y]=$(),S=D(0);B(()=>{S.current=0},v);const I=he(()=>r===b,[r,b]),[T,x]=$(!1);B(()=>{I&&m!=null&&m.acct&&(async()=>{const X=await io(r);x(X)})()},[r,I,m==null?void 0:m.acct]);async function L(X){var ae,Q,ye;const E=/^\d{4}-[01]\d$/.test(s),j=((Q=(ae=s==null?void 0:s.split)==null?void 0:ae.call(s,"-"))==null?void 0:Q[0])>=Zt;if(E&&j){if(!m)return{value:[],done:!0};const[V,Z]=s.split("-"),ce=parseInt(Z,10)-1,fe=new Date(V,ce,0),me=`${fe.getFullYear()}-${(fe.getMonth()+1).toString().padStart(2,"0")}-${fe.getDate().toString().padStart(2,"0")}`,de=new Date(V,ce+1,1),R=`${de.getFullYear()}-${(de.getMonth()+1).toString().padStart(2,"0")}-${de.getDate().toString().padStart(2,"0")}`;let G;X?(G=ot+1,S.current=0):(G=ot+S.current+1,S.current+=ot);const K=await h.v2.search.fetch({q:`from:${m.acct} after:${me} before:${R}`,type:"statuses",limit:G,offset:S.current});if((ye=K==null?void 0:K.statuses)!=null&&ye.length){const ie=K.statuses.slice(0,ot);ie.forEach(Le=>{Ae(Le,r)});const we=K.statuses.length<=ot;return{value:ie,done:we}}else return{value:[],done:!0}}const ne=[];if(X){const{value:V}=await h.v1.accounts.$select(n).statuses.list({pinned:!0}).next();if(V!=null&&V.length&&!c&&!d){const Z=V.map(ce=>(Ae(ce,r),{...ce,_pinned:!0}));if(Z.length>=3){const ce=Z.map(fe=>fe.id);ne.push({id:ce,items:Z,type:"pinned"})}else ne.push(...Z)}}(X||!g.current)&&(g.current=h.v1.accounts.$select(n).statuses.list({limit:ot,exclude_replies:u,exclude_reblogs:l,only_media:d,tagged:c}));const{value:le,done:H}=await g.current.next();return le!=null&&le.length&&(ne.push(...le),le.forEach(V=>{Ae(V,r)})),{value:ne,done:H}}const[N,O]=$([]);_e(m!=null&&m.acct?`${m!=null&&m.displayName?m.displayName+" ":""}@${m.acct}${u?l?" (- Boosts)":c?` (#${c})`:d?" (Media)":s?` (${new Date(s).toLocaleString("default",{month:"long",year:"numeric"})})`:"":" (+ Replies)"}`:"Account posts","/:instance?/a/:id");const U=D(),P=Ve(()=>{const X=U.current||h.v1.accounts.$select(n).fetch();return U.current=X,X},[n,h]);B(()=>{(async()=>{try{const X=await P();y(X)}catch{}try{const X=await h.v1.accounts.$select(n).featuredTags.list();O(X)}catch{}})()},[n]);const{displayName:M,acct:C,emojis:_}=m||{},F=he(()=>{const X=t.accounts[`${n}@${r}`];return e(Jn,{instance:r,account:X||n,fetchAccount:P,authenticated:p,standalone:!0})},[n,r,p,P]),Y=D(),te=he(()=>e(A,{children:[F,e("div",{class:"filter-bar",ref:Y,style:{position:"relative"},children:[!u||l||c||d||!!s?e(ee,{to:`/${r}/a/${n}`,class:"insignificant filter-clear",title:"Clear filters",children:e(w,{icon:"x",size:"l"})},"clear-filters"):e(w,{icon:"filter",class:"insignificant",size:"l"}),e(ee,{to:`/${r}/a/${n}${u?"?replies=1":""}`,onClick:()=>{u&&pe("Showing post with replies")},class:u?"":"is-active",children:"+ Replies"}),e(ee,{to:`/${r}/a/${n}${l?"":"?boosts=0"}`,onClick:()=>{l||pe("Showing posts without boosts")},class:l?"is-active":"",children:"- Boosts"}),e(ee,{to:`/${r}/a/${n}${d?"":"?media=1"}`,onClick:()=>{d||pe("Showing posts with media")},class:d?"is-active":"",children:"Media"}),N.map(E=>e(ee,{to:`/${r}/a/${n}${c===E.name?"":`?tagged=${encodeURIComponent(E.name)}`}`,onClick:()=>{c!==E.name&&pe(`Showing posts tagged with #${E.name}`)},class:c===E.name?"is-active":"",children:e("span",{children:[e("span",{class:"more-insignificant",children:"#"}),E.name]})},E.id)),T&&(no?e("label",{class:`filter-field ${s?"is-active":""}`,children:[e(w,{icon:"month",size:"l"}),e("input",{type:"month",disabled:!(m!=null&&m.acct),value:s||"",min:Sn,max:new Date().toISOString().slice(0,7),onInput:E=>{const{value:j,validity:ne}=E.currentTarget;if(!ne.valid)return;a(j?{month:j}:{});const[le,H]=j.split("-"),ae=parseInt(H,10)-1,Q=new Date(le,ae);pe(`Showing posts in ${Q.toLocaleString("default",{month:"long",year:"numeric"})}`)}})]}):e(ao,{class:`filter-field ${s?"is-active":""}`,disabled:!(m!=null&&m.acct),value:s||"",min:Sn,max:new Date().toISOString().slice(0,7),onInput:E=>{const{value:j,validity:ne}=E;ne.valid&&a(j?{month:j}:{})}}))]})]}),[n,r,p,N,T,...v]);B(()=>{var E;const X=(E=Y.current)==null?void 0:E.querySelector(".is-active");X&&Y.current.scrollTo({behavior:"smooth",left:X.offsetLeft-(Y.current.offsetWidth-X.offsetWidth)/2})},[N,T,...v]);const W=he(()=>m!=null&&m.url?new URL(m.url).hostname:null,[m]),re=!!m&&!(r===W);return e(Ye,{title:`${m!=null&&m.acct?"@"+m.acct:"Posts"}`,titleComponent:e("h1",{class:"header-double-lines header-account",children:[e("b",{children:e(Nn,{text:M,emojis:_})}),e("div",{children:e("span",{children:["@",C]})})]}),id:"account-statuses",instance:r,emptyText:"Nothing to see here yet.",errorText:"Unable to load posts",fetchItems:L,useItemID:!0,view:d?"media":void 0,boostsCarousel:t.settings.boostsCarousel,timelineStart:te,refresh:[u,l,c,d,s+(m==null?void 0:m.acct)].toString(),headerEnd:e(Fe,{portal:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{disabled:!re,onClick:()=>{(async()=>{try{const{masto:X}=z({instance:W}),E=await X.v1.accounts.lookup({acct:m.acct}),{id:j}=E;location.hash=`/${W}/a/${j}`}catch{alert("Unable to fetch account info")}})()},children:[e(w,{icon:"transfer"})," ",e("small",{class:"menu-double-lines",children:["Switch to account's instance (",e("b",{children:W}),")"]})]}),!I&&e(oe,{onClick:()=>{(async()=>{try{const X=await f.v1.accounts.lookup({acct:m.acct+"@"+r}),{id:E}=X;location.hash=`/${b}/a/${E}`}catch{alert("Unable to fetch account info")}})()},children:[e(w,{icon:"transfer"})," ",e("small",{class:"menu-double-lines",children:["Switch to my instance (",e("b",{children:b}),")"]})]})]})},n)}function ao(t){const{class:n,disabled:i,value:o,min:a,max:s,onInput:u=()=>{}}=t,[l,c]=(o==null?void 0:o.split("-"))||[],d=D(),h=D(),r=(p,f)=>{const[b,g]=(a==null?void 0:a.split("-"))||[],[v,m]=(s==null?void 0:s.split("-"))||[];return!(fv||f===b&&pm)};return e("div",{class:n,children:[e(w,{icon:"month",size:"l"}),e("select",{ref:d,disabled:i,value:c||"",onInput:p=>{const{value:f}=p.currentTarget,b=h.current.value;if(!r(f,b))return{value:"",validity:{valid:!1}};u({value:f?`${b}-${f}`:"",validity:{valid:!0}})},children:[e("option",{value:"",children:"Month"}),e("option",{disabled:!0,children:"-----"}),Array.from({length:12},(p,f)=>e("option",{value:(f+1).toString().padStart(2,"0"),children:new Date(0,f).toLocaleString("default",{month:"long"})},f))]})," ",e("input",{ref:h,type:"number",disabled:i,value:l||new Date().getFullYear(),min:(a==null?void 0:a.slice(0,4))||Zt,max:(s==null?void 0:s.slice(0,4))||new Date().getFullYear(),onInput:p=>{const{value:f,validity:b}=p.currentTarget,g=d.current.value;if(!b.valid||!r(g,f))return{value:"",validity:{valid:!1}};u({value:f?`${f}-${g}`:"",validity:{valid:!0}})},style:{width:"4.5em"}})]})}const co=20;function ss(){_e("Bookmarks","/b");const{masto:t,instance:n}=z(),i=D();async function o(a){return(a||!i.current)&&(i.current=t.v1.bookmarks.list({limit:co})),await i.current.next()}return e(Ye,{title:"Bookmarks",id:"bookmarks",emptyText:"No bookmarks yet. Go bookmark something!",errorText:"Unable to load bookmarks",instance:n,fetchItems:o})}const ro=20;function is(){_e("Likes","/f");const{masto:t,instance:n}=z(),i=D();async function o(a){return(a||!i.current)&&(i.current=t.v1.favourites.list({limit:ro})),await i.current.next()}return e(Ye,{title:"Likes",id:"favourites",emptyText:"No likes yet. Go like something!",errorText:"Unable to load likes",instance:n,fetchItems:o})}function lo(){const{masto:t,instance:n}=z();_e("Followed Hashtags","/ft");const[i,o]=$("default"),[a,s]=$([]);return B(()=>{o("loading"),(async()=>{try{const u=await Tt();s(u),o("default")}catch{o("error")}})()},[]),e("div",{id:"followed-hashtags-page",class:"deck-container",tabIndex:"-1",children:e("div",{class:"timeline-deck deck",children:[e("header",{children:e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),e(ee,{to:"/",class:"button plain",children:e(w,{icon:"home",size:"l"})})]}),e("h1",{children:"Followed Hashtags"}),e("div",{class:"header-side"})]})}),e("main",{children:a.length>0?e("ul",{class:"link-list",children:a.map(u=>e("li",{children:e(ee,{to:n?`/${n}/t/${u.name}`:`/t/${u.name}`,children:[e(w,{icon:"hashtag"})," ",e("span",{children:u.name})]})}))}):i==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):i==="error"?e("p",{class:"ui-state",children:"Unable to load followed hashtags."}):e("p",{class:"ui-state",children:"No hashtags followed yet."})})]})})}const uo=20;function Jt({title:t,path:n,id:i,...o}){_e(t||"Following",n||"/following");const{masto:a,streaming:s,instance:u}=z(),l=Se(k),c=D(),d=D();async function h(p){(p||!c.current)&&(c.current=a.v1.timelines.home.list({limit:uo}));const f=await c.current.next();let{value:b}=f;if(b!=null&&b.length){let g=!1;p&&(b[0].id!==d.current&&(g=!0),d.current=b[0].id),b.forEach(v=>{Ae(v,u)}),b=wn(b,u),p&&g&&Wi(),Yi(b,u),b.sort((v,m)=>{const y=new Date(v.createdAt);return new Date(m.createdAt)-y})}return{...f,value:b}}async function r(){try{const p=await a.v1.timelines.home.list({limit:5,since_id:d.current}).next();let{value:f}=p;return!!(f!=null&&f.length&&(d.current=f[0].id,f=wn(f,u),f=rt(f,"home"),f.some(b=>!b.reblog)))}catch{return!1}}return B(()=>{let p;return(async()=>{if(s){p=s.user.subscribe();for await(const f of p){if(!p)break;if(f.event==="status.update"){const b=f.payload;Ae(b,u)}else if(f.event==="delete"){const b=f.payload,g=zn(b,u);g&&(g._deleted=!0)}}}})(),()=>{var f;(f=p==null?void 0:p.unsubscribe)==null||f.call(p),p=null}},[s]),e(Ye,{title:t||"Following",id:i||"following",emptyText:"Nothing to see here.",errorText:"Unable to load posts.",instance:u,fetchItems:h,checkForUpdates:r,useItemID:!0,boostsCarousel:l.settings.boostsCarousel,...o,filterContext:"home",showFollowedTags:!0})}const ho=20,fo=4,kn=fo+1;function os({media:t,columnMode:n,...i}){let{hashtag:o,...a}=n?{}:nt();i.hashtag&&(o=i.hashtag);let s=o.trim().split(/[\s+]+/);s.sort(),o=s[0];const[u,l]=qe(),c=t||!!u.get("media"),d=c?"?media=1":"",{masto:h,instance:r,authenticated:p}=z({instance:(i==null?void 0:i.instance)||a.instance}),{masto:f,instance:b,authenticated:g}=z(),v=s.map(M=>`#${M}`).join(" "),m=c?" (Media only)":"",y=r?`${v}${m} on ${r}`:`${v}${m}`;_e(y,"/:instance?/t/:hashtag");const S=D(),I=D(void 0);async function T(M){const C=await h.v1.timelines.tag.$select(o).list({limit:ho,any:s.slice(1),maxId:M?void 0:I.current,onlyMedia:c}).next();let{value:_}=C;return _!=null&&_.length&&(M&&(S.current=_[0].id),_.forEach(F=>{Ae(F,r,{skipThreading:c})}),I.current=_[_.length-1].id),{...C,value:_}}async function x(){try{const M=await h.v1.timelines.tag.$select(o).list({limit:1,any:s.slice(1),since_id:S.current,onlyMedia:c}).next();let{value:C}=M;return C=rt(C,"public"),!!(C!=null&&C.length)}catch{return!1}}const[L,N]=$("default"),[O,U]=$();B(()=>{(async()=>{try{const M=await h.v1.tags.$select(o).fetch();U(M)}catch{}})()},[o]);const P=s.length>=kn;return e(Ye,{title:y,titleComponent:!!r&&e("h1",{class:"header-double-lines",children:[e("b",{children:v}),e("div",{children:r})]}),id:"hashtag",instance:r,emptyText:"No one has posted anything with this tag yet.",errorText:"Unable to load posts with this tag",fetchItems:T,checkForUpdates:x,useItemID:!0,view:c?"media":void 0,refresh:c,filterContext:"public",headerEnd:e(Fe,{portal:!0,setDownOverflow:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[!!O&&s.length===1&&e(A,{children:[e(Be,{subMenu:!0,confirm:O.following,confirmLabel:`Unfollow #${o}?`,disabled:L==="loading"||!p,onClick:()=>{N("loading"),O.following?h.v1.tags.$select(o).unfollow().then(()=>{U({...O,following:!1}),pe(`Unfollowed #${o}`)}).catch(M=>{alert(M)}).finally(()=>{N("default")}):h.v1.tags.$select(o).follow().then(()=>{U({...O,following:!0}),pe(`Followed #${o}`)}).catch(M=>{alert(M)}).finally(()=>{N("default")})},children:O.following?e(A,{children:[e(w,{icon:"check-circle"})," ",e("span",{children:"Following…"})]}):e(A,{children:[e(w,{icon:"plus"})," ",e("span",{children:"Follow"})]})}),e(De,{})]}),e(jn,{className:"plain",children:"Filters"}),e(oe,{type:"checkbox",checked:!!c,onClick:()=>{c?u.delete("media"):u.set("media","1"),l(u)},children:[e(w,{icon:"check-circle"})," ",e("span",{class:"menu-grow",children:"Media only"})]}),e(De,{}),e(Us,{className:"menu-field",disabled:P,children:({ref:M})=>e("form",{onSubmit:C=>{var F,Y;C.preventDefault();const _=(Y=(F=C.target[0].value)==null?void 0:F.trim)==null?void 0:Y.call(F);_&&!s.some(te=>te.toLowerCase()===_.toLowerCase())&&(s.push(_),s.sort(),location.hash=r?`/${r}/t/${s.join("+")}`:`/t/${s.join("+")}${d}`)},children:[e(w,{icon:"hashtag"}),e("input",{ref:M,type:"text",placeholder:P?`Max ${kn} tags`:"Add hashtag",required:!0,autocorrect:"off",autocapitalize:"off",spellcheck:!1,pattern:"[^#][^\\s#]+[^#]",disabled:P})]})}),e(Fs,{takeOverflow:!0,children:s.map((M,C)=>e(oe,{disabled:s.length===1,onClick:_=>{s.splice(C,1),s.sort(),location.hash=r?`/${r}/t/${s.join("+")}${d}`:`/t/${s.join("+")}${d}`},children:[e(w,{icon:"x",alt:"Remove hashtag",class:"danger-icon"}),e("span",{children:[e("span",{class:"more-insignificant",children:"#"}),M]})]},M))}),e(De,{}),e(oe,{disabled:!g,onClick:()=>{if(k.shortcuts.length>=Ze){alert(`Max ${Ze} shortcuts reached. Unable to add shortcut.`);return}const M={type:"hashtag",hashtag:s.join(" "),instance:r,media:c?"on":void 0};k.shortcuts.some(_=>_.type===M.type&&_.hashtag.split(/[\s+]+/).sort().join(" ")===M.hashtag.split(/[\s+]+/).sort().join(" ")&&(_.instance?_.instance===M.instance:!0)&&(_.media?!!_.media==!!M.media:!0))?alert("This shortcut already exists"):(k.shortcuts.push(M),pe("Hashtag shortcut added"))},children:[e(w,{icon:"shortcut"})," ",e("span",{children:"Add to Shorcuts"})]}),e(oe,{onClick:()=>{let M=prompt('Enter a new instance e.g. "mastodon.social"');if(!/\./.test(M)){M&&alert("Invalid instance");return}M&&(M=M.toLowerCase().trim(),location.hash=`/${M}/t/${s.join("+")}${d}`)},children:[e(w,{icon:"bus"})," ",e("span",{children:"Go to another instance…"})]}),b!==r&&e(oe,{onClick:()=>{location.hash=`/${b}/t/${s.join("+")}${d}`},children:[e(w,{icon:"bus"})," ",e("small",{class:"menu-double-lines",children:["Go to my instance (",e("b",{children:b}),")"]})]})]})},r+v)}const po=20;function as(t){var g;const n=Se(k),{masto:i,instance:o}=z(),a=(t==null?void 0:t.id)||((g=nt())==null?void 0:g.id),s=D(),u=D();async function l(v){(v||!u.current)&&(u.current=i.v1.timelines.list.$select(a).list({limit:po}));const m=await u.current.next();let{value:y}=m;return y!=null&&y.length&&(v&&(s.current=y[0].id),y.forEach(S=>{Ae(S,o)})),{...m,value:y}}async function c(){try{const v=await i.v1.timelines.list.$select(a).list({limit:1,since_id:s.current});let{value:m}=v;return m=rt(m,"home"),!!(m!=null&&m.length)}catch{return!1}}const[d,h]=$({title:"List"});_e(d.title,"/l/:id"),B(()=>{(async()=>{try{const v=await i.v1.lists.$select(a).fetch();h(v)}catch{}})()},[a]);const[r,p]=$(!1),[f,b]=$(!1);return e(A,{children:[e(Ye,{title:d.title,id:"list",emptyText:"Nothing yet.",errorText:"Unable to load posts.",instance:o,fetchItems:l,checkForUpdates:c,useItemID:!0,boostsCarousel:n.settings.boostsCarousel,filterContext:"home",headerStart:e(ee,{to:"/l",class:"button plain",children:e(w,{icon:"list",size:"l"})}),headerEnd:e(Fe,{portal:!0,setDownOverflow:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{onClick:()=>p({list:d}),children:[e(w,{icon:"pencil",size:"l"}),e("span",{children:"Edit"})]}),e(oe,{onClick:()=>b(!0),children:[e(w,{icon:"group",size:"l"}),e("span",{children:"Manage members"})]})]})},a),r&&e(Ce,{class:"light",onClick:v=>{v.target===v.currentTarget&&p(!1)},children:e(Yt,{list:r==null?void 0:r.list,onClose:v=>{v.state==="success"&&v.list?h(v.list):v.state==="deleted"&&(location.hash="/l"),p(!1)}})}),f&&e(Ce,{class:"light",onClick:v=>{v.target===v.currentTarget&&b(!1)},children:e(go,{listID:a,onClose:()=>b(!1)})})]})}const mo=40;function go({listID:t,onClose:n}){const{masto:i,instance:o}=z(),[a,s]=$([]),[u,l]=$("default"),[c,d]=$(!1),h=D();async function r(p){d(!1),l("loading"),(async()=>{try{(p||!h.current)&&(h.current=i.v1.lists.$select(t).accounts.list({limit:mo}));const f=await h.current.next();let{done:b,value:g}=f;g!=null&&g.length?(s(p?g:a.concat(g)),d(!b)):d(!1),l("default")}catch{l("error")}})()}return B(()=>{r(!0)},[]),e("div",{class:"sheet",id:"list-manage-members-container",children:[!!n&&e("button",{type:"button",class:"sheet-close",onClick:n,children:e(w,{icon:"x"})}),e("header",{children:e("h2",{children:"Manage members"})}),e("main",{children:e("ul",{children:[a.map(p=>e("li",{children:[e(He,{account:p,instance:o}),e(bo,{account:p,listID:t})]},p.id)),c&&u==="default"&&e(je,{as:"li",onChange:p=>p&&r(),children:e("button",{type:"button",class:"light block",onClick:r,children:"Show more…"})})]})})]})}function bo({account:t,listID:n}){const{masto:i}=z(),[o,a]=$("default"),[s,u]=$(!1);return e(Be,{confirm:!s,confirmLabel:e("span",{children:["Remove @",t.username," from list?"]}),align:"end",menuItemClassName:"danger",onClick:()=>{s?(a("loading"),(async()=>{try{await i.v1.lists.$select(n).accounts.create({accountIds:[t.id]}),a("default"),u(!1)}catch{a("error")}})()):(a("loading"),(async()=>{try{await i.v1.lists.$select(n).accounts.remove({accountIds:[t.id]}),a("default"),u(!0)}catch{a("error")}})())},children:e("button",{type:"button",class:`light ${s?"":"danger"}`,disabled:o==="loading",children:s?"Add":"Remove…"})})}const In=20,yo=new URLSearchParams;function cs({columnMode:t,...n}){const{masto:i,instance:o}=z(),[a]=t?[yo]:qe(),[s,u]=$(null),l=(n==null?void 0:n.type)||a.get("type")||s;_e(`Mentions${l==="private"?" (Private)":""}`,"/mentions");const c=D(),d=D();async function h(m){(m||!c.current)&&(c.current=i.v1.notifications.list({limit:In,types:["mention"]}));const y=await c.current.next();let{value:S}=y;return S!=null&&S.length&&(m&&(d.current=S[0].id),S.forEach(({status:I})=>{Ae(I,o)})),{...y,value:S==null?void 0:S.map(I=>I.status)}}const r=D(),p=D();async function f(m){(m||!r.current)&&(r.current=i.v1.conversations.list({limit:In}));const y=await r.current.next();let{value:S}=y;return S=S==null?void 0:S.filter(I=>I.lastStatus),S!=null&&S.length&&(m&&(p.current=S[0].lastStatus.id),S.forEach(({lastStatus:I})=>{Ae(I,o)})),{...y,value:S==null?void 0:S.map(I=>I.lastStatus)}}function b(...m){return l==="private"?f(...m):h(...m)}async function g(){if(l==="private")try{const m=await i.v1.conversations.list({limit:1,since_id:p.current}).next();let{value:y}=m;return y!=null&&y.length?(p.current=y[0].lastStatus.id,!0):!1}catch{return!1}else try{const m=await i.v1.notifications.list({limit:1,types:["mention"],since_id:d.current}).next();let{value:y}=m;return y!=null&&y.length?(d.current=y[0].id,!0):!1}catch{return!1}}const v=he(()=>e("div",{class:"filter-bar centered",children:[e(ee,{to:"/mentions",class:l?"":"is-active",onClick:m=>{t&&(m.preventDefault(),u(null))},children:"All"}),e(ee,{to:"/mentions?type=private",class:l==="private"?"is-active":"",onClick:m=>{t&&(m.preventDefault(),u("private"))},children:"Private"})]}),[l]);return e(Ye,{title:"Mentions",id:"mentions",emptyText:"No one mentioned you :(",errorText:"Unable to load mentions.",instance:o,fetchItems:b,checkForUpdates:g,useItemID:!0,timelineStart:v,refresh:l})}const wo={mention:["account","status"],status:["account","status"],reblog:["account","status"],follow:["account"],follow_request:["account"],favourite:["account","status"],poll:["status"],update:["status"]};function vo(t){return t.filter(n=>{const{type:i,id:o,createdAt:a}=n;if(!i)return!1;const s=wo[i];return s!=null&&s.length?s.every(u=>!!n[u]):!0})}function rs(t){t=vo(t);const n={},i=[];for(let s=0,u=0;sy.id===h.id);m?(m._types.push(r),m._types.sort().reverse(),v.id+=`-${c}`):(h._types=[r],v._accounts.push(h),v.id+=`-${c}`)}else{h._types=[r];let m=n[g]={...l,type:b,_accounts:[h]};i[u++]=m}}const o={},a=[];for(let s=0,u=0;s{Ae(H.status,i,{skipThreading:!0})});const le=rs(ne);E?(k.notificationsLast=ne[0],k.notifications=le,n.v1.markers.create({notifications:{lastReadId:ne[0].id}}).catch(()=>{})):k.notifications.push(...le)}return k.notificationsShowNew=!1,k.notificationsLastFetchTime=Date.now(),j}async function O(){try{return await n.v1.followRequests.list({limit:80})}catch{return[]}}const U=()=>{s("loading"),(async()=>{try{const E=await O();I(E),s("default")}catch{s("error")}})()};async function P(){try{return await n.v1.announcements.list()}catch{return[]}}const M=E=>{_(!1),s("loading"),(async()=>{try{const j=N(E);E&&(P().then(le=>{le.sort((H,ae)=>{const Q=new Date(H.updatedAt||H.createdAt);return new Date(ae.updatedAt||ae.createdAt)-Q}),x(le)}).catch(()=>{}),O().then(le=>{I(le)}).catch(()=>{}));const{done:ne}=await j;h(!ne),s("default")}catch{s("error")}})()};B(()=>{M(!0)},[]),B(()=>{v&&M(!0)},[v]);const[C,_]=$(!1),F=Ve(({disableIdleCheck:E=!1}={})=>{var j;a!=="loading"&&o.settings.autoRefresh&&((j=f.current)==null?void 0:j.scrollTop)<16&&(E||window.__IDLE__)&&!To()&&M(!0)},[o.notificationsShowNew,o.settings.autoRefresh,a]),Y=D();ct(E=>{let j;if(E){const ne=Date.now()-Y.current;!Y.current||ne>1e3*3?F({disableIdleCheck:!0}):Y.current=Date.now(),j=Os(k,"notificationsShowNew",le=>{le&&F(),_(le)})}return()=>{j==null||j()}});const te=new Date,W=new Date(te-24*60*60*1e3);let ke=new Date;const re=!o.notifications.some(E=>new Date(E.createdAt).toDateString()===te.toDateString()),X=D();return B(()=>{l&&(k.routeNotification={id:l,accessToken:atob(c)})},[l,c]),e("div",{id:"notifications-page",class:"deck-container",ref:f,tabIndex:"-1",children:e("div",{class:`timeline-deck deck ${r?"only-mentions":""}`,children:[e("header",{hidden:y,onClick:E=>{var j;E.target.closest("a, button")||(j=f.current)==null||j.scrollTo({top:0,behavior:"smooth"})},class:a==="loading"?"loading":"",children:[e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),e(ee,{to:"/",class:"button plain",children:e(w,{icon:"home",size:"l",alt:"Home"})})]}),e("h1",{children:"Notifications"}),e("div",{class:"header-side"})]}),C&&a!=="loading"&&e("button",{class:"updates-button shiny-pill",type:"button",onClick:()=>{var E;M(!0),(E=f.current)==null||E.scrollTo({top:0,behavior:"smooth"})},children:[e(w,{icon:"arrow-up"})," New notifications"]})]}),T.length>0&&e("div",{class:"shazam-container",children:e("div",{class:"shazam-container-inner",children:e("details",{class:"announcements",children:[e("summary",{children:[e("span",{children:[e(w,{icon:"announce",class:"announcement-icon",size:"l"})," ",e("b",{children:["Announcement",T.length>1?"s":""]})," ",e("small",{class:"insignificant",children:i})]}),T.length>1&&e("span",{class:"announcements-nav-buttons",children:T.map((E,j)=>e("button",{type:"button",class:"plain2 small",onClick:()=>{var ne;(ne=X.current)==null||ne.children[j].scrollIntoView({behavior:"smooth",block:"nearest"})},children:j+1}))})]}),e("ul",{class:`announcements-list-${T.length>1?"multiple":"single"}`,ref:X,children:T.map(E=>e("li",{children:e(Co,{announcement:E})}))})]})})}),S.length>0&&e("div",{class:"follow-requests",children:[e("h2",{class:"timeline-header",children:"Follow requests"}),S.length>5?e("details",{children:[e("summary",{children:[S.length," follow requests"]}),e("ul",{children:S.map(E=>e("li",{children:[e(He,{account:E}),e(Ft,{accountID:E.id,onChange:()=>{}})]},E.id))})]}):e("ul",{children:S.map(E=>e("li",{children:[e(He,{account:E}),e(Ft,{accountID:E.id,onChange:()=>{}})]},E.id))})]}),e("div",{id:"mentions-option",children:e("label",{children:[e("input",{type:"checkbox",checked:r,onChange:E=>{p(E.target.checked)}})," ","Only mentions"]})}),e("h2",{class:"timeline-header",children:"Today"}),re&&!!o.notifications.length&&e("p",{class:"ui-state insignificant",children:a==="default"?"You're all caught up.":e(A,{children:"…"})}),o.notifications.length?e(A,{children:o.notifications.filter(E=>E.type!=="follow_request").map(E=>{if(r&&E.type!=="mention")return null;const j=new Date(E.createdAt),ne=j.toDateString()!==ke.toDateString();ne&&(ke=j);const le=j.toDateString()===W.toDateString()?"Yesterday":Ke(ke,{hideTime:!0});return e(A,{children:[ne&&e("h2",{class:"timeline-header",children:le}),e(Kt,{instance:i,notification:E},E.id)]},E.id)})}):e(A,{children:[a==="loading"&&e(A,{children:e("ul",{class:"timeline flat",children:Array.from({length:5}).map((E,j)=>e("li",{class:"notification skeleton",children:[e("div",{class:"notification-type",children:e(w,{icon:"notification",size:"xl"})}),e("div",{class:"notification-content",children:e("p",{children:"███████████ ████"})})]}))})}),a==="error"&&e("p",{class:"ui-state",children:["Unable to load notifications",e("br",{}),e("br",{}),e("button",{type:"button",onClick:()=>M(!0),children:"Try again"})]})]}),d&&e(je,{onChange:E=>{E&&M()},children:e("button",{type:"button",class:"plain block",disabled:a==="loading",onClick:()=>M(),style:{marginBlockEnd:"6em"},children:a==="loading"?e(Ie,{abrupt:!0}):e(A,{children:"Show more…"})})})]})})}function To(){return!!document.querySelector(".deck-backdrop, #modal-container > *")}function Co({announcement:t}){const{instance:n}=z(),{contact:i}=Cs(),o=i==null?void 0:i.account,{id:a,content:s,startsAt:u,endsAt:l,published:c,allDay:d,publishedAt:h,updatedAt:r,read:p,mentions:f,statuses:b,tags:g,emojis:v,reactions:m}=t,y=new Date(h),S=Ke(y),I=new Date(r),T=Ke(I);return e("div",{class:"announcement-block",children:[e(He,{account:o}),e("div",{class:"announcement-content",onClick:Pn({mentions:f,instance:n}),dangerouslySetInnerHTML:{__html:Pt(s,{emojis:v})}}),e("p",{class:"insignificant",children:[e("time",{datetime:y.toISOString(),children:Ke(y)}),r&&T!==S&&e(A,{children:[" ","•"," ",e("span",{class:"ib",children:["Updated"," ",e("time",{datetime:I.toISOString(),children:Ke(I)})]})]})]}),e("div",{class:"announcement-reactions",hidden:!0,children:m.map(x=>{const{name:L,count:N,me:O,staticUrl:U,url:P}=x;return e("button",{type:"button",class:`plain4 small ${O?"reacted":""}`,children:[P||U?e("img",{src:P||U,alt:L,width:"16",height:"16"}):e("span",{children:L})," ",e("span",{class:"count",children:Ue(N)})]})})})]})}const ls=ze(Io),$o=20;function Ot({local:t,columnMode:n,...i}){const o=Se(k),a=!!t,s=n?{}:nt(),{masto:u,instance:l}=z({instance:(i==null?void 0:i.instance)||s.instance}),{masto:c,instance:d}=z(),h=`${a?"Local":"Federated"} timeline (${l})`;_e(h,a?"/:instance?/p/l":"/:instance?/p");const r=D(),p=D();async function f(g){(g||!p.current)&&(p.current=u.v1.timelines.public.list({limit:$o,local:a}));const v=await p.current.next();let{value:m}=v;return m!=null&&m.length&&(g&&(r.current=m[0].id),m.forEach(y=>{Ae(y,l)})),{...v,value:m}}async function b(){try{const g=await u.v1.timelines.public.list({limit:1,local:a,since_id:r.current}).next();let{value:v}=g;return v=rt(v,"public"),!!(v!=null&&v.length)}catch{return!1}}return e(Ye,{title:h,titleComponent:e("h1",{class:"header-double-lines",children:[e("b",{children:a?"Local timeline":"Federated timeline"}),e("div",{children:l})]}),id:"public",instance:l,emptyText:"No one has posted anything yet.",errorText:"Unable to load posts",fetchItems:f,checkForUpdates:b,useItemID:!0,headerStart:e(A,{}),boostsCarousel:o.settings.boostsCarousel,filterContext:"public",headerEnd:e(Fe,{portal:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{href:a?`/#/${l}/p`:`/#/${l}/p/l`,children:a?e(A,{children:[e(w,{icon:"transfer"})," ",e("span",{children:"Switch to Federated"})]}):e(A,{children:[e(w,{icon:"transfer"})," ",e("span",{children:"Switch to Local"})]})}),e(De,{}),e(oe,{onClick:()=>{let g=prompt('Enter a new instance e.g. "mastodon.social"');if(!/\./.test(g)){g&&alert("Invalid instance");return}g&&(g=g.toLowerCase().trim(),location.hash=a?`/${g}/p/l`:`/${g}/p`)},children:[e(w,{icon:"bus"})," ",e("span",{children:"Go to another instance…"})]}),d!==l&&e(oe,{onClick:()=>{location.hash=a?`/${d}/p/l`:`/${d}/p`},children:[e(w,{icon:"bus"})," ",e("small",{class:"menu-double-lines",children:["Go to my instance (",e("b",{children:d}),")"]})]})]})},l+a)}const yt=5,Et=40,xo=new URLSearchParams;function ds({columnMode:t,...n}){const i=t?{}:nt(),{masto:o,instance:a,authenticated:s}=z({instance:i.instance}),[u,l]=$("default"),[c]=t?[xo]:qe(),d=D(),h=(n==null?void 0:n.query)||c.get("q"),r=t?"statuses":(n==null?void 0:n.type)||c.get("type");_e(h?`Search: ${h}${r?` (${{statuses:"Posts",accounts:"Accounts",hashtags:"Hashtags"}[r]})`:""}`:"Search","/search");const[p,f]=$(!1),b=D(0);B(()=>{b.current=0},[h,r]);const g=D();Je(()=>{var C,_;(_=(C=g.current)==null?void 0:C.scrollTo)==null||_.call(C,0,0)},[h,r]);const[v,m]=$([]),[y,S]=$([]),[I,T]=$([]);B(()=>{m([]),S([]),T([])},[h]);const x={statuses:m,accounts:S,hashtags:T},[L,N]=$({}),O=async C=>{if(!(C!=null&&C.length))return;const _=await Wt(C,L);_&&N({...L,..._})};function U(C){C&&(b.current=0),!(!C&&!s)&&(l("loading"),C&&!r&&(m(v.slice(0,yt)),S(y.slice(0,yt)),T(I.slice(0,yt))),(async()=>{var F,Y;const _={q:h,resolve:s,limit:yt};r&&(_.limit=Et,_.type=r,s&&(_.offset=b.current));try{const te=await o.v2.search.fetch(_);if(r)if(C){x[r](te[r]);const W=(F=te[r])==null?void 0:F.length;b.current=Et,f(!!W)}else{x[r](ke=>[...ke,...te[r]]);const W=(Y=te[r])==null?void 0:Y.length;b.current=b.current+Et,f(!!W)}else m(te.statuses||[]),S(te.accounts||[]),T(te.hashtags||[]),b.current=0,f(!1);O(te.accounts),l("default")}catch{l("error")}})())}const P=D();ct(C=>{var F;const _=((F=g.current)==null?void 0:F.scrollTop)===0;if(C&&_){const Y=Date.now()-P.current;!P.current||Y>1e3*3?U(!0):P.current=Date.now()}}),B(()=>{var C,_,F,Y;(_=(C=d.current)==null?void 0:C.setValue)==null||_.call(C,h||""),h?U(!0):(Y=(F=d.current)==null?void 0:F.focus)==null||Y.call(F)},[h,r,a]),Re("/",C=>{var _,F;(F=(_=d.current)==null?void 0:_.focus)==null||F.call(_)},{preventDefault:!0});const[M]=Ht();return e("div",{id:"search-page",class:"deck-container",ref:g,children:e("div",{class:"timeline-deck deck",children:[e("header",{class:u==="loading"?"loading":"",children:e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:e(mt,{})}),e(ns,{ref:d}),e("div",{class:"header-side",children:e("button",{type:"button",class:"plain",onClick:()=>{U(!0)},disabled:u==="loading",children:e(w,{icon:"search",size:"l"})})})]})}),e("main",{children:[!!h&&!t&&e("div",{ref:M,class:`filter-bar ${u==="loading"?"loading":""}`,children:[!!r&&e(ee,{to:`/search${h?`?q=${encodeURIComponent(h)}`:""}`,children:"‹ All"}),[{label:"Accounts",type:"accounts",to:`/search?q=${encodeURIComponent(h)}&type=accounts`},{label:"Hashtags",type:"hashtags",to:`/search?q=${encodeURIComponent(h)}&type=hashtags`},{label:"Posts",type:"statuses",to:`/search?q=${encodeURIComponent(h)}&type=statuses`}].sort((C,_)=>C.type===r?-1:_.type===r?1:0).map(C=>e(ee,{to:C.to,children:C.label},C.type))]}),h?e(A,{children:[(!r||r==="accounts")&&e(A,{children:[r!=="accounts"&&e("h2",{class:"timeline-header",children:"Accounts"}),y.length>0?e(A,{children:[e("ul",{class:"timeline flat accounts-list",children:y.map(C=>e("li",{children:e(He,{account:C,instance:a,showStats:!0,relationship:L[C.id]})},C.id))}),r!=="accounts"&&e("div",{class:"ui-state",children:e(ee,{class:"plain button",to:`/search?q=${h}&type=accounts`,children:["See more accounts ",e(w,{icon:"arrow-right"})]})})]}):!r&&(u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"No accounts found."}))]}),(!r||r==="hashtags")&&e(A,{children:[r!=="hashtags"&&e("h2",{class:"timeline-header",children:"Hashtags"}),I.length>0?e(A,{children:[e("ul",{class:"link-list hashtag-list",children:I.map(C=>{var te;const{name:_,history:F}=C,Y=(te=F==null?void 0:F.reduce)==null?void 0:te.call(F,(W,ke)=>W+ +ke.uses,0);return e("li",{children:e(ee,{to:a?`/${a}/t/${_}`:`/t/${_}`,children:[e(w,{icon:"hashtag"}),e("span",{children:_}),!!Y&&e("span",{class:"count",children:Ue(Y)})]})},`${_}-${Y}`)})}),r!=="hashtags"&&e("div",{class:"ui-state",children:e(ee,{class:"plain button",to:`/search?q=${h}&type=hashtags`,children:["See more hashtags ",e(w,{icon:"arrow-right"})]})})]}):!r&&(u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"No hashtags found."}))]}),(!r||r==="statuses")&&e(A,{children:[r!=="statuses"&&e("h2",{class:"timeline-header",children:"Posts"}),v.length>0?e(A,{children:[e("ul",{class:"timeline",children:v.map(C=>e("li",{children:e(ee,{class:"status-link",to:a?`/${a}/s/${C.id}`:`/s/${C.id}`,children:e(Me,{status:C})})},C.id))}),r!=="statuses"&&e("div",{class:"ui-state",children:e(ee,{class:"plain button",to:`/search?q=${h}&type=statuses`,children:["See more posts ",e(w,{icon:"arrow-right"})]})})]}):!r&&(u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"No posts found."}))]}),!!r&&(u==="default"?p?e(je,{onChange:C=>{C&&U()},children:e("button",{type:"button",class:"plain block",onClick:()=>U(),style:{marginBlockEnd:"6em"},children:"Show more…"})}):e("p",{class:"ui-state insignificant",children:"The end."}):u==="loading"&&e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}))]}):u==="loading"?e("p",{class:"ui-state",children:e(Ie,{abrupt:!0})}):e("p",{class:"ui-state",children:"Enter your search term or paste a URL above to get started."})]})]})})}const Ao=20,Lo=tt(t=>t.v1.trends.links.list().next(),{maxAge:10*60*1e3});function us({columnMode:t,...n}){const i=Se(k),o=t?{}:nt(),{masto:a,instance:s}=z({instance:(n==null?void 0:n.instance)||o.instance}),{masto:u,instance:l}=z(),c=`Trending (${s})`;_e(c,"/:instance?/trending");const d=D(),[h,r]=$([]),[p,f]=$([]),b=D();async function g(y){var T;if(y||!b.current){b.current=a.v1.trends.statuses.list({limit:Ao});try{const x=a.v1.trends.tags.list(),{value:L}=await x.next();L!=null&&L.length&&r(L)}catch{}try{const{value:x}=await Lo(a),L=(T=x==null?void 0:x.filter)==null?void 0:T.call(x,N=>N.type==="link");L!=null&&L.length&&f(L)}catch{}}const S=await b.current.next();let{value:I}=S;return I!=null&&I.length&&(y&&(d.current=I[0].id),I.forEach(x=>{Ae(x,s)})),{...S,value:I}}async function v(){try{const y=await a.v1.trends.statuses.list({limit:1}).next();let{value:S}=y;return S=rt(S,"public"),S!=null&&S.length&&S[0].id!==d.current?(d.current=S[0].id,!0):!1}catch{return!1}}const m=he(()=>e(A,{children:[!!h.length&&e("div",{class:"filter-bar expandable",children:[e(w,{icon:"chart",class:"insignificant",size:"l"}),h.map((y,S)=>{const{name:I,history:T}=y,x=T.reduce((L,N)=>L+ +N.uses,0);return e(ee,{to:`/${s}/t/${I}`,children:[e("span",{children:[e("span",{class:"more-insignificant",children:"#"}),I]}),e("span",{class:"filter-count",children:Ue(x)})]},I)})]}),!!p.length&&e("div",{class:"links-bar",children:[e("header",{children:e("h3",{children:"Trending News"})}),p.map(y=>{const{authorName:S,authorUrl:I,blurhash:T,description:x,height:L,image:N,imageDescription:O,language:U,providerName:P,providerUrl:M,publishedAt:C,title:_,url:F,width:Y}=y,te=new URL(F).hostname.replace(/^www\./,"").replace(/\/$/,"");let W;if(T){const ke=qn(T),re=Xn(ke);W=Qn([.6,re[1],re[2]])}return e("a",{href:F,target:"_blank",rel:"noopener noreferrer",style:W?{"--accent-color":`rgb(${W.join(",")})`,"--accent-alpha-color":`rgba(${W.join(",")}, 0.4)`}:{},children:e("article",{children:[e("figure",{children:e("img",{src:N,alt:O,width:Y,height:L,loading:"lazy"})}),e("div",{class:"article-body",children:[e("header",{children:[e("div",{class:"article-meta",children:[e("span",{class:"domain",children:te})," ",!!C&&e(A,{children:"· "}),!!C&&e(A,{children:e($t,{datetime:C,format:"micro"})})]}),!!_&&e("h1",{class:"title",lang:U,dir:"auto",children:_})]}),!!x&&e("p",{class:"description",lang:U,dir:"auto",children:x})]})]})},F)})]})]}),[h,p]);return e(Ye,{title:c,titleComponent:e("h1",{class:"header-double-lines",children:[e("b",{children:"Trending"}),e("div",{children:s})]}),id:"trending",instance:s,emptyText:"No trending posts.",errorText:"Unable to load posts",fetchItems:g,checkForUpdates:v,checkForUpdatesInterval:5*60*1e3,useItemID:!0,headerStart:e(A,{}),boostsCarousel:i.settings.boostsCarousel,filterContext:"public",timelineStart:m,headerEnd:e(Fe,{portal:!0,overflow:"auto",viewScroll:"close",position:"anchor",menuButton:e("button",{type:"button",class:"plain",children:e(w,{icon:"more",size:"l"})}),children:[e(oe,{onClick:()=>{let y=prompt('Enter a new instance e.g. "mastodon.social"');if(!/\./.test(y)){y&&alert("Invalid instance");return}y&&(y=y.toLowerCase().trim(),location.hash=`/${y}/trending`)},children:[e(w,{icon:"bus"})," ",e("span",{children:"Go to another instance…"})]}),l!==s&&e(oe,{onClick:()=>{location.hash=`/${l}/trending`},children:[e(w,{icon:"bus"})," ",e("small",{class:"menu-double-lines",children:["Go to my instance (",e("b",{children:l}),")"]})]})]})},s)}function Mo(){_e("Home","/");const t=Se(k),{shortcuts:n}=t,i=n.map(o=>{if(!o)return null;const{type:a,...s}=o,u={following:Jt,notifications:ls,list:as,public:Ot,bookmarks:ss,favourites:is,hashtag:os,mentions:cs,trending:us,search:ds}[a];return!u||a==="search"&&!s.query?null:e(u,{...s,columnMode:!0},a+JSON.stringify(s))});return Re(["1","2","3","4","5","6","7","8","9"],(o,a)=>{try{const s=parseInt(a.keys[0],10)-1;document.querySelectorAll("#columns > *")[s].focus()}catch{}}),e("div",{id:"columns",onContextMenu:o=>{o.target.closest(".deck > header")&&!o.target.closest("a")&&!o.target.closest("button")&&(o.preventDefault(),k.showShortcutsSettings=!0)},children:i})}function Ro(){var n;const t=Se(k);return B(()=>{(async()=>{const i=await ht.drafts.keys();if(i.length){const o=Un();i.filter(s=>s.startsWith(o)).length&&(k.showDrafts=!0)}})()},[]),e(A,{children:(t.settings.shortcutsViewMode==="multi-column"||!t.settings.shortcutsViewMode&&t.settings.shortcutsColumnsMode)&&((n=t.shortcuts)!=null&&n.length)?e(Mo,{}):e(Jt,{title:"Home",path:"/",id:"home",headerStart:!1,headerEnd:e(_o,{})})})}function _o(){const t=Se(k),n=D(),[i,o]=$(void 0);return e(A,{children:[e(ee,{ref:n,to:"/notifications",class:`button plain notifications-button ${t.notificationsShowNew?"has-badge":""} ${i||""}`,onClick:a=>{a.stopPropagation(),window.matchMedia("(min-width: calc(40em))").matches&&(a.preventDefault(),o(s=>s?void 0:"open"))},children:e(w,{icon:"notification",size:"l",alt:"Notifications"})}),e(No,{state:i,anchorRef:n,onClose:()=>o(void 0)})]})}const Eo=30,Po=5;function No({anchorRef:t,state:n,onClose:i}){const{masto:o,instance:a}=z(),s=Se(k),[u,l]=$("default"),c=o.v1.notifications.list({limit:Eo});async function d(){const b=await c.next(),g=b.value;if(g!=null&&g.length){g.forEach(m=>{Ae(m.status,a,{skipThreading:!0})});const v=rs(g);k.notificationsLast=g[0],k.notifications=v,o.v1.markers.create({notifications:{lastReadId:g[0].id}}).catch(()=>{})}return k.notificationsShowNew=!1,k.notificationsLastFetchTime=Date.now(),b}const[h,r]=$(!1);function p(){return o.v1.followRequests.list({limit:1})}function f(){l("loading"),(async()=>{try{await d();const b=await p();r(!!(b!=null&&b.length)),l("default")}catch{l("error")}})()}return B(()=>{n==="open"&&f()},[n]),e(Gn,{menuClassName:"notifications-menu",state:n,anchorRef:t,onClose:i,portal:{target:document.body},overflow:"auto",viewScroll:"close",position:"anchor",align:"center",boundingBoxPadding:"8 8 8 8",children:[e("header",{children:e("h2",{children:"Notifications"})}),e("main",{children:s.notifications.length?e(A,{children:s.notifications.slice(0,Po).map(b=>e(Kt,{instance:a,notification:b,disableContextMenu:!0},b.id))}):u==="loading"?e("div",{class:"ui-state",children:e(Ie,{abrupt:!0})}):u==="error"&&e("div",{class:"ui-state",children:[e("p",{children:"Unable to fetch notifications."}),e("p",{children:e("button",{type:"button",onClick:f,children:"Try again"})})]})}),e("footer",{children:[e(ee,{to:"/mentions",class:"button plain",children:[e(w,{icon:"at"})," ",e("span",{children:"Mentions"})]}),e(ee,{to:"/notifications",class:"button plain2",children:[h?e(A,{children:[e("span",{class:"tag collapsed",children:"New"})," ",e("span",{children:"Follow Requests"})]}):e("b",{children:"See all"})," ",e(w,{icon:"arrow-right"})]})]})]})}const Do=ze(Ro),Uo=[/^\/@[^@\/]+\/(?:statuses|posts)\/([^\/]+)/i,/\/notes\/([^\/]+)/i,/^\/(?:notice|objects)\/([a-z0-9-]+)/i,/\/@[^@\/]+@?[^\/]+?\/([^\/]+)/i];function hs(t){const{hostname:n,pathname:i}=new URL(t);for(const o of Uo){const[,a]=i.match(o)||[];if(a)return{instance:n,id:a}}return{}}function Fo(t){const{instance:n,id:i}=hs(t);return n&&i?`/${n}/s/${i}`:null}function Oo(){const n=lt().pathname.replace(/^\//,""),i=hs(n),o=i!=null&&i.instance?`/${i.instance}/s/${i.id}`:null,[a,s]=$("loading");return Je(()=>{s("loading"),(async()=>{try{const{instance:u,id:l}=i,{masto:c}=z({instance:u});if(await c.v1.statuses.$select(l).fetch()){window.location.hash=o+"?view=full";return}}catch{}{const{masto:u,instance:l}=z(),c=await u.v2.search.fetch({q:n,type:"statuses",limit:1,resolve:!0});if(c.statuses.length){const d=c.statuses[0];window.location.hash=`/${l}/s/${d.id}?view=full`}else window.location.hash=o+"?view=full"}})()},[o]),e("div",{class:"ui-state",tabIndex:"-1",children:[a==="loading"?e(A,{children:[e(Ie,{abrupt:!0}),e("h2",{children:"Resolving…"}),e("p",{children:e("a",{href:n,target:"_blank",rel:"noopener noreferrer",children:n})})]}):e(A,{children:[e("h2",{children:"Unable to resolve URL"}),e("p",{children:e("a",{href:n,target:"_blank",rel:"noopener noreferrer",children:n})})]}),e("hr",{}),e("p",{children:e(ee,{to:"/",children:"Go home"})})]})}function Bo(){const{masto:t}=z();_e("Lists","/l");const[n,i]=$("default"),[o,a]=xt(d=>d+1,0),[s,u]=$([]);B(()=>{i("loading"),(async()=>{try{const d=await t.v1.lists.list();d.sort((h,r)=>h.title.localeCompare(r.title)),u(d),i("default")}catch{i("error")}})()},[o]);const[l,c]=$(!1);return e("div",{id:"lists-page",class:"deck-container",tabIndex:"-1",children:[e("div",{class:"timeline-deck deck",children:[e("header",{children:e("div",{class:"header-grid",children:[e("div",{class:"header-side",children:[e(mt,{}),e(ee,{to:"/",class:"button plain",children:e(w,{icon:"home",size:"l"})})]}),e("h1",{children:"Lists"}),e("div",{class:"header-side",children:e("button",{type:"button",class:"plain",onClick:()=>c(!0),children:e(w,{icon:"plus",size:"l",alt:"New list"})})})]})}),e("main",{children:s.length>0?e("ul",{class:"link-list",children:s.map(d=>e("li",{children:e(ee,{to:`/l/${d.id}`,children:e("span",{children:[e(w,{icon:"list"})," ",e("span",{children:d.title})]})})}))}):n==="loading"?e("p",{class:"ui-state",children:e(Ie,{})}):n==="error"?e("p",{class:"ui-state",children:"Unable to load lists."}):e("p",{class:"ui-state",children:"No lists yet."})})]}),l&&e(Ce,{class:"light",onClick:d=>{d.target===d.currentTarget&&c(!1)},children:e(Yt,{list:l==null?void 0:l.list,onClose:d=>{d.state==="success"&&a(),c(!1)}})})]})}const zo=""+new URL("instances-cddSOnAA.json",import.meta.url).href;var qo={PHANPY_CLIENT_NAME:"Phanpy",PHANPY_WEBSITE:"https://phanpy.social",PHANPY_LINGVA_INSTANCES:"lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud",PHANPY_PRIVACY_POLICY_URL:"https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD",VITE_APP_ENV:"production",BASE_URL:"./",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const{PHANPY_CLIENT_NAME:Ho,PHANPY_WEBSITE:Vo}=qo,Xt="read write follow push";async function Go({instanceURL:t}){const n=new URLSearchParams({client_name:Ho,redirect_uris:location.origin+location.pathname,scopes:Xt,website:Vo});return await(await fetch(`https://${t}/api/v1/apps`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()})).json()}async function jo({instanceURL:t,client_id:n}){const i=new URLSearchParams({client_id:n,scope:Xt,redirect_uri:location.origin+location.pathname,response_type:"code"});return`https://${t}/oauth/authorize?${i.toString()}`}async function Yo({instanceURL:t,client_id:n,client_secret:i,code:o}){const a=new URLSearchParams({client_id:n,client_secret:i,redirect_uri:location.origin+location.pathname,grant_type:"authorization_code",code:o,scope:Xt});return await(await fetch(`https://${t}/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:a.toString()})).json()}var Wo={PHANPY_CLIENT_NAME:"Phanpy",PHANPY_WEBSITE:"https://phanpy.social",PHANPY_LINGVA_INSTANCES:"lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud",PHANPY_PRIVACY_POLICY_URL:"https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD",VITE_APP_ENV:"production",BASE_URL:"./",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const{PHANPY_DEFAULT_INSTANCE:Ko}=Wo;function Zo(){_e("Log in");const t=D(),n=se.local.get("instanceURL"),[i,o]=$("default"),[a]=qe(),s=a.get("instance"),u=a.get("submit"),[l,c]=$(s||(n==null?void 0:n.toLowerCase())||""),[d,h]=$([]);B(()=>{(async()=>{try{const y=await(await fetch(zo)).json();h(y)}catch{}})()},[]);const r=m=>{m&&(se.local.set("instanceURL",m),(async()=>{o("loading");try{const{client_id:y,client_secret:S,vapid_key:I}=await Go({instanceURL:m});y&&S?(se.session.set("clientID",y),se.session.set("clientSecret",S),se.session.set("vapidKey",I),location.href=await jo({instanceURL:m,client_id:y})):alert("Failed to register application"),o("default")}catch{o("error")}})())},p=l?l.replace(/^https?:\/\//,"").replace(/\/+$/,"").replace(/^@?[^@]+@/,"").trim():null,f=/[^\s\r\n\t\/\\]+\.[^\s\r\n\t\/\\]+/.test(p)&&!/[\s\/\\@]/.test(p),b=p?d.filter(m=>m.includes(l)).sort((m,y)=>{const S=m.toLowerCase().startsWith(l.toLowerCase()),I=y.toLowerCase().startsWith(l.toLowerCase());return S&&!I?-1:!S&&I?1:0}).slice(0,10):[],g=f?p:b!=null&&b.length?b[0]:l?d.find(m=>m.includes(l)):null,v=m=>{m.preventDefault(),r(g)};return u&&B(()=>{r(s||g)},[]),e("main",{id:"login",style:{textAlign:"center"},children:e("form",{onSubmit:v,children:[e("h1",{children:[e("img",{src:Gt,alt:"",width:"80",height:"80"}),e("br",{}),"Log in"]}),e("label",{children:[e("p",{children:"Instance"}),e("input",{value:l,required:!0,type:"text",class:"large",id:"instanceURL",ref:t,disabled:i==="loading",autocorrect:"off",autocapitalize:"off",autocomplete:"off",spellcheck:!1,placeholder:"instance domain",onInput:m=>{c(m.target.value)}}),(b==null?void 0:b.length)>0?e("ul",{id:"instances-suggestions",children:b.map((m,y)=>e("li",{children:e("button",{type:"button",class:"plain5",onClick:()=>{r(m)},children:m})}))}):e("div",{id:"instances-eg",children:"e.g. “mastodon.social”"})]}),i==="error"&&e("p",{class:"error",children:"Failed to log in. Please try again or another instance."}),e("div",{children:[e("button",{disabled:i==="loading"||!l||!g,children:g?`Continue with ${g}`:"Continue"})," "]}),e(Ie,{hidden:i!=="loading"}),e("hr",{}),!Ko&&e("p",{children:e("a",{href:"https://joinmastodon.org/servers",target:"_blank",children:"Don't have an account? Create one!"})}),e("p",{children:e(ee,{to:"/",children:"Go home"})})]})})}const wt=40,Jo=10,Xo=5;let Bt={},St={},kt={};function zt(t){delete St[t],delete kt[t]}const dt={block:"nearest",inline:"center",behavior:"smooth"},Tn=".status-link:not(details:not([open]) > summary ~ *, details:not([open]) > summary ~ * *), .status-focus:not(details:not([open]) > summary ~ *, details:not([open]) > summary ~ * *)",Cn=/\/s\//i;function Qo(t){const{id:n}=t,{masto:i,instance:o}=z({instance:t.instance}),a=Se(k),[s,u]=qe(),l=s.get("media"),c=s.get("media-only"),d=parseInt(l||c,10);let h=d>0;const r=s.get("mediaStatusID"),p=zn(r,o);r&&!p&&(h=!1);const f=h&&!!c,b=Ge(n,o),[g,v]=$(k.statuses[b]);B(()=>{k.statuses[b]&&v(k.statuses[b])},[b]);const m=he(()=>{const{prevLocation:I}=k,T=((I==null?void 0:I.pathname)||"")+((I==null?void 0:I.search)||""),x=pt("/:instance/s/:id",T)||pt("/s/:id",T);return!T||x?"/":T},[]);B(()=>{!g&&h&&(async()=>{try{const I=await i.v1.statuses.$select(n).fetch();Ae(I,o),v(I)}catch{alert("Unable to load post."),location.hash=m}})()},[h]);const y=r?p==null?void 0:p.mediaAttachments:g==null?void 0:g.mediaAttachments,S=Ve(()=>{!window.matchMedia("(min-width: calc(40em + 350px))").matches&&a.prevLocation?history.back():f?location.hash=m:(s.delete("media"),s.delete("mediaStatusID"),u(s))},[f,m,a.prevLocation]);return B(()=>{let I=setTimeout(()=>{const T=document.querySelector(".carousel");T&&T.focus()},100);return()=>clearTimeout(I)},[f]),e("div",{class:"deck-backdrop",children:[h?y!=null&&y.length?e(es,{mediaAttachments:y,statusID:r||n,instance:o,lang:g==null?void 0:g.language,index:d-1,onClose:S}):e("div",{class:"media-modal-container loading",children:e(Ie,{abrupt:!0})}):e(ee,{to:m}),!f&&e(ea,{id:n,instance:t.instance,closeLink:m})]})}function ea({id:t,closeLink:n="/",instance:i}){var me,de;const[o,a]=qe(),s=o.get("media"),u=o.get("mediaStatusID"),l=parseInt(s,10)>0,c=D(!k.prevLocation&&(history.length===1||"navigation"in window&&((de=(me=navigation==null?void 0:navigation.entries)==null?void 0:me.call(navigation))==null?void 0:de.length)===1)),[d,h]=$(o.get("view")||c.current?"full":null),r=!!parseInt(o.get("translate")),{masto:p,instance:f}=z({instance:i}),{masto:b,instance:g,authenticated:v}=z(),m=f===g,y=Se(k),[S,I]=$([]),[T,x]=$("default"),L=D(),N=Ge(t,f),O=D(0),U=D();B(()=>{var R;(R=U.current)==null||R.focus()},[]),B(()=>{var G;const R=Yn(()=>{if(!U.current)return;const{scrollTop:K}=U.current;T!=="loading"&&(kt[t]=K)},50);return(G=U.current)==null||G.addEventListener("scroll",R,{passive:!0}),R(),()=>{var K;R.cancel(),(K=U.current)==null||K.removeEventListener("scroll",R)}},[t,T!=="loading"]);const P=D(),M=({reloadHero:R}={})=>{x("loading");let G;const K=St[t];if(K){const ie=K.filter(we=>k.statuses[N]);I(ie)}else I([{id:t}]);return(async()=>{var q,ge;const ie=()=>cn(()=>p.v1.statuses.$select(t).fetch(),{retries:4}),we=cn(()=>p.v1.statuses.$select(t).context.fetch(),{retries:8}),Le=!!y.statuses[N];let $e=y.statuses[N];if(!(Le&&!R))try{$e=await ie(),Ae($e,f),await new Promise(be=>{setTimeout(be,100)})}catch{x("error");return}try{let be=function(J){return J==null?void 0:J.map(ve=>({id:ve.id,account:ve.account,repliesCount:ve.repliesCount,content:ve.content,weight:ft(ve),replies:be(ve.__replies)}))};const ue=await we,{ancestors:xe,descendants:Pe}=ue;O.current=(Pe==null?void 0:Pe.length)||0;const Ne=new Set;xe.forEach(J=>{Ae(J,f,{skipThreading:!0}),J.inReplyToId&&!xe.find(ve=>ve.id===J.inReplyToId)&&Ne.add(J.inReplyToId)});const st=xe.every(J=>J.account.id===$e.account.id),Oe=[];Pe.forEach(J=>{if(Ae(J,f,{skipThreading:!0}),J.inReplyToId&&!Pe.find(ve=>ve.id===J.inReplyToId)&&J.inReplyToId!==$e.id&&Ne.add(J.inReplyToId),J.inReplyToAccountId===J.account.id)Oe.push(J);else if(J.inReplyToId===$e.id)Oe.push(J);else if(!J.inReplyToAccountId&&Oe.find(ve=>ve.id===J.inReplyToId)&&J.account.id===$e.account.id)Oe.push(J);else{const ve=Pe.find(ps=>ps.id===J.inReplyToId);ve&&(ve.__replies||(ve.__replies=[]),ve.__replies.push(J))}}),Ne.size;const We=[...xe.map(J=>({id:J.id,ancestor:!0,isThread:st,accountID:J.account.id,account:J.account,repliesCount:J.repliesCount,weight:ft(J)})),{id:t,accountID:$e.account.id,weight:ft($e)},...Oe.map(J=>({id:J.id,account:J.account,accountID:J.account.id,descendant:!0,thread:J.account.id===$e.account.id,weight:ft(J),replies:be(J.__replies)}))];x("default"),P.current={offsetTop:(q=L.current)==null?void 0:q.offsetTop,scrollTop:(ge=U.current)==null?void 0:ge.scrollTop};const Xe=We.findIndex(J=>J.id===t);Xe>=W&&ke(Xe+1),I(We),St[t]=We,$s($e,f)}catch{x("error")}})(),()=>{clearTimeout(G)}};B(M,[t,p]),B(()=>{var G,K;if(!S.length)return;const R=kt[t];if(R)U.current.scrollTop=R;else if(P.current){const ie={offsetTop:(G=L.current)==null?void 0:G.offsetTop,scrollTop:(K=U.current)==null?void 0:K.scrollTop},we=ie.offsetTop-P.current.offsetTop+ie.scrollTop;U.current.scrollTop=we}else S.length===1&&(U.current.scrollTop=0);P.current=null},[S]),B(()=>{y.reloadStatusPage<=0||(async()=>{try{const{instanceURL:R}=at(),G=`https://${R}/api/v1/statuses/${t}/context`;return await(await caches.open("api")).delete(G,{ignoreVary:!0}),M({reloadHero:!0})}catch{}})()},[y.reloadStatusPage]),B(()=>()=>{kt={},k.reloadStatusPage=0,St={},Bt={},qt.clear()},[]);const C=y.statuses[N]||y.statuses[t],_=he(()=>{if(!C)return"";const{account:R}=C,G=document.createElement("div");return G.innerHTML=R.displayName,G.innerText.trim()},[C]),F=he(()=>{if(!C)return"";let R=Bn(C);return R.length>64&&(R=R.slice(0,64)+"…"),R},[C]);_e(_&&F?`${_}: "${F}"`:"Status","/:instance?/s/:id");const Y=he(()=>{if(!C)return;const{url:R}=C;if(R)return new URL(R).hostname},[C]),te=he(()=>{if(Y)return Y===f},[Y,f]),[W,ke]=$(wt),re=he(()=>S.length-W,[S.length,W]),X=S.some(R=>R.descendant),E=S.filter(R=>R.ancestor),[j,ne]=$(!0),le=he(()=>{if(!L.current||j)return null;const{top:R}=L.current.getBoundingClientRect();return R>0?"down":"up"},[j]);Re("esc",()=>{location.hash=n},{enabled:!l,ignoreEventWhen:R=>!!document.querySelector("#modal-container > *")}),Re("backspace",()=>{location.hash=n}),Re("j",()=>{const R=document.activeElement.closest(".status-link, .status-focus"),G=R==null?void 0:R.getBoundingClientRect(),K=Array.from(U.current.querySelectorAll(Tn));if(R&&G.top0){const ie=K.indexOf(R);let we=K[ie+1];we&&(we.focus(),we.scrollIntoView(dt))}else{const ie=K.find(we=>{const Le=we.getBoundingClientRect();return Le.top>=44&&Le.left>=0});ie&&(ie.focus(),ie.scrollIntoView(dt))}}),Re("k",()=>{const R=document.activeElement.closest(".status-link, .status-focus"),G=R==null?void 0:R.getBoundingClientRect(),K=Array.from(U.current.querySelectorAll(Tn));if(R&&G.top0){const ie=K.indexOf(R);let we=K[ie-1];we&&(we.focus(),we.scrollIntoView(dt))}else{const ie=K.find(we=>{const Le=we.getBoundingClientRect();return Le.top>=44&&Le.left>=0});ie&&(ie.focus(),ie.scrollIntoView(dt))}}),Re("x",()=>{const R=document.activeElement.closest(".status-link, .status-focus");if(R){const G=R.nextElementSibling;G&&G.tagName.toLowerCase()==="details"&&(G.open=!G.open)}});const[H,ae]=$(!1),Q=D(l?"media+status":"status"),ye=Ve((R,G,K,ie)=>{R.preventDefault(),R.stopPropagation(),a({media:G+1,mediaStatusID:ie.id})},[t]),V=Ve((R,G)=>{zt(G.id)},[]);B(()=>{let R;return u&&l&&(R=setTimeout(()=>{var K;const G=(K=U.current)==null?void 0:K.querySelector(`.status-link[href*="/${u}"]`);G&&G.scrollIntoView(dt)},400)),()=>{clearTimeout(R)}},[u,l]);const Z=Ve((R,G)=>{const{id:K,ancestor:ie,isThread:we,descendant:Le,thread:$e,replies:q,repliesCount:ge,weight:be}=R,ue=K===t;return e("li",{ref:ue?L:null,class:`${ie?"ancestor":""} ${Le?"descendant":""} ${$e?"thread":""} ${ue?"hero":""}`,children:[ue?e(A,{children:[e(je,{threshold:.1,onChange:xe=>{queueMicrotask(()=>{requestAnimationFrame(()=>{ne(xe)})})},class:"status-focus",tabIndex:0,children:e(Me,{statusID:K,instance:f,withinContext:!0,size:"l",enableTranslate:!0,forceTranslate:r})}),T!=="loading"&&!v?e("div",{class:"post-status-banner",children:[e("p",{children:"You're not logged in. Interactions (reply, boost, etc) are not possible."}),e(ee,{to:"/login",class:"button",children:"Log in"})]}):!m&&e("div",{class:"post-status-banner",children:[e("p",{children:["This post is from another instance (",e("b",{children:f}),"). Interactions (reply, boost, etc) are not possible."]}),e("button",{type:"button",disabled:T==="loading",onClick:()=>{x("loading"),(async()=>{try{const xe=await b.v2.search.fetch({q:C.url,type:"statuses",resolve:!0,limit:1});if(xe.statuses.length){const Pe=xe.statuses[0];location.hash=g?`/${g}/s/${Pe.id}`:`/s/${Pe.id}`}else throw new Error("No results")}catch(xe){x("default"),alert("Error: "+xe)}})()},children:[e(w,{icon:"transfer"})," Switch to my instance to enable interactions"]})]})]}):e(ee,{class:"status-link",to:f?`/${f}/s/${K}`:`/s/${K}`,onClick:()=>{zt(K)},children:[e(je,{skip:G!==0||!ie,threshold:.5,onChange:xe=>{queueMicrotask(()=>{requestAnimationFrame(()=>{ae(xe)})})},children:e(Me,{statusID:K,instance:f,withinContext:!0,size:$e||ie?"m":"s",enableTranslate:!0,onMediaClick:ye,onStatusLinkClick:V})}),ie&&ge>1&&e("div",{class:"replies-link",children:[e(w,{icon:"comment2"})," ",e("span",{title:ge,children:Ue(ge)})]})," "]}),Le&&(q==null?void 0:q.length)>0&&e(fs,{instance:f,replies:q,hasParentThread:$e,level:1,accWeight:be,openAll:O.current{k.reloadStatusPage++},children:"Try again"})]})]},K)},[t,f,T,v,m,r,ye,V,X]),ce=he(()=>{var R;if("navigation"in window&&(navigation!=null&&navigation.entries)){const G=navigation.entries()[navigation.currentEntry.index-1];if(G!=null&&G.url)return Cn.test(G.url)}return Cn.test((R=k.prevLocation)==null?void 0:R.pathname)},[N]),fe=he(()=>{if(!re)return[];const R=[];function G(K){R.push(K.id),K.replies&&K.replies.forEach(G)}return S.slice(W).forEach(G),R.map(K=>Ge(K,f))},[re,S,W,f]);return e("div",{tabIndex:"-1",ref:U,class:`status-deck deck contained ${S.length>1?"padded-bottom":""} ${Q.current==="status"&&!c.current?"slide-in":""} ${d?`deck-view-${d}`:""}`,onAnimationEnd:R=>{Q.current==="status"&&(Q.current=null)},children:[e("header",{class:`${T==="loading"?"loading":""}`,onDblClick:R=>{k.reloadStatusPage++},children:e("div",{class:"header-grid header-grid-2",children:[e("h1",{children:[ce&&e("button",{type:"button",class:"plain deck-back",onClick:()=>{history.back()},children:e(w,{icon:"chevron-left",size:"xl"})}),!j&&C&&T!=="loading"?e(A,{children:[e("span",{class:"hero-heading",children:[e(It,{account:C.account,instance:f,showAvatar:!0,short:!0})," ",e("span",{class:"insignificant",children:["•"," ",e($t,{datetime:C.createdAt,format:"micro"})]})]})," ",e("button",{type:"button",class:"ancestors-indicator light small",onClick:R=>{R.preventDefault(),R.stopPropagation(),L.current.scrollIntoView({behavior:"smooth",block:"start"})},title:"Go to main post",children:e(w,{icon:le==="down"?"arrow-down":"arrow-up"})})]}):e(A,{children:["Post"," ",e("button",{type:"button",class:"ancestors-indicator light small",onClick:R=>{R.preventDefault(),R.stopPropagation(),U.current.scrollTo({top:0,behavior:"smooth"})},hidden:!E.length||H,title:`${E.length} posts above ‒ Go to top`,children:[e(w,{icon:"arrow-up"}),E.filter((R,G,K)=>K.findIndex(ie=>ie.accountID===R.accountID)===G).slice(0,3).map(R=>e(et,{url:R.account.avatar,alt:R.account.displayName},R.account.id)),E.length>3&&e(A,{children:[" ",e("span",{class:"insignificant",children:Ue(E.length)})]})]})]})]}),e("div",{class:"header-side",children:[e("button",{type:"button",class:"plain4 button-switch-view",style:{display:d==="full"?"":"none"},onClick:()=>{h(null),o.delete("media"),o.delete("media-only"),o.delete("view"),a(o)},title:"Switch to Side Peek view",children:e(w,{icon:"layout4",size:"l"})}),e(Fe,{align:"end",portal:{target:U.current},menuButton:e("button",{type:"button",class:"button plain4",children:e(w,{icon:"more",alt:"Actions",size:"xl"})}),children:[e(oe,{disabled:T==="loading",onClick:()=>{k.reloadStatusPage++},children:[e(w,{icon:"refresh"}),e("span",{children:"Refresh"})]}),e(oe,{className:"menu-switch-view",onClick:()=>{h(d==="full"?null:"full"),o.delete("media"),o.delete("media-only"),d==="full"?o.delete("view"):o.set("view","full"),a(o)},children:[e(w,{icon:{"":"layout5",full:"layout4"}[d||""]}),e("span",{children:["Switch to ",d==="full"?"Side Peek":"Full"," view"]})]}),e(oe,{onClick:()=>{Array.from(U.current.querySelectorAll(".spoiler-button:not(.spoiling), .spoiler-media-button:not(.spoiling)")).forEach(G=>{G.click()})},children:[e(w,{icon:"eye-open"})," ",e("span",{children:"Show all sensitive content"})]}),e(De,{}),e(jn,{className:"plain",children:"Experimental"}),e(oe,{disabled:!Y||te,onClick:()=>{const R=Fo(C.url);R?location.hash=R:alert("Unable to switch")},children:[e(w,{icon:"transfer"}),e("small",{class:"menu-double-lines",children:["Switch to post's instance",Y?e(A,{children:[" ","(",e("b",{children:Y}),")"]}):""]})]})]}),e(ee,{class:"button plain deck-close",to:n,children:e(w,{icon:"x",size:"xl"})})]})]})}),S.length&&C?e("ul",{class:`timeline flat contextual grow ${T==="loading"?"loading":""}`,children:[S.slice(0,W).map(Z),re>0&&e("li",{children:e("button",{type:"button",class:"plain block show-more",disabled:T==="loading",onClick:()=>ke(R=>R+wt),style:{marginBlockEnd:"6em"},"data-state-post-ids":fe.join(" "),children:[e("div",{class:"ib avatars-bunch",children:S.slice(W,W+5).map(R=>e(et,{url:R.account.avatarStatic},R.id))})," ",e("div",{class:"ib",children:["Show more…"," ",e("span",{class:"tag",children:re>wt?`${wt}+`:re})]})]})})]}):e(A,{children:[T==="loading"&&e("ul",{class:"timeline flat contextual grow loading",children:e("li",{children:e(Me,{skeleton:!0,size:"l"})})}),T==="error"&&e("p",{class:"ui-state",children:["Unable to load post",e("br",{}),e("br",{}),e("button",{type:"button",onClick:()=>{k.reloadStatusPage++},children:"Try again"})]})]})]})}function fs({replies:t,instance:n,hasParentThread:i,level:o,accWeight:a,openAll:s}){const[u,l]=qe(),c=m=>m.reduce((y,S)=>{const{repliesCount:I,replies:T}=S,x=(T==null?void 0:T.length)||I;return y+x+c(T||[])},0),d=t.length+c(t),h=t.length===d,r=t.map(m=>m.account).filter((m,y,S)=>S.findIndex(I=>I.id===m.id)===y).slice(0,3),p=he(()=>t==null?void 0:t.reduce((m,y)=>m+(y==null?void 0:y.weight),a),[a,t==null?void 0:t.length]);let f=!1;(s||p<=Xo||!i&&d===1&&ft(t[0])<2)&&(f=!0);const b=Bt[t[0].id],g=Ve((m,y,S,I)=>{m.preventDefault(),m.stopPropagation(),l({media:y+1,mediaStatusID:I.id})},[]),v=D();return Je(()=>{var y;function m(S){S.target.dataset.scrollLeft=S.target.scrollLeft}return(y=v.current)==null||y.addEventListener("scroll",m,{passive:!0}),()=>{var S;(S=v.current)==null||S.removeEventListener("scroll",m)}},[]),e("details",{ref:v,class:"replies",open:b||f,onToggle:m=>{const{open:y}=m.target;Bt[t[0].id]=y},style:{"--comments-level":o},"data-comments-level":o,"data-comments-level-overflow":o>4,children:[e("summary",{class:"replies-summary",hidden:f,children:[e("span",{class:"avatars",children:r.map(m=>e(et,{url:m.avatarStatic,title:`${m.displayName} @${m.username}`,squircle:m==null?void 0:m.bot},m.id))}),e("b",{children:[e("span",{title:t.length,children:Ue(t.length)})," ","repl",t.length===1?"y":"ies"]}),!h&&d>1&&e(A,{children:[" ","·"," ",e("span",{children:[e("span",{title:d,children:Ue(d)})," ","comment",d===1?"":"s"]})]})]}),e("ul",{children:t.map(m=>{var y,S;return e("li",{children:[e(ee,{class:"status-link",to:n?`/${n}/s/${m.id}`:`/s/${m.id}`,onClick:()=>{zt(m.id)},children:[e(Me,{statusID:m.id,instance:n,withinContext:!0,size:"s",enableTranslate:!0,onMediaClick:g}),!((y=m.replies)!=null&&y.length)&&m.repliesCount>0&&e("div",{class:"replies-link",children:[e(w,{icon:"comment2"})," ",e("span",{title:m.repliesCount,children:Ue(m.repliesCount)})]})]}),((S=m.replies)==null?void 0:S.length)&&e(fs,{instance:n,replies:m.replies,level:o+1,accWeight:f?p:m.weight,openAll:s})]},m.id)})})]})}const ta=140,na=35,sa=70,ia=140,qt=new Map;function ft(t){var f,b;const n=qt.get(t.id);if(n)return n;const{spoilerText:i,content:o,mediaAttachments:a,poll:s,card:u}=t,l=xs(i+o),c=a!=null&&a.length?ta:0,d=(((f=s==null?void 0:s.options)==null?void 0:f.length)||0)*na,h=u&&(a!=null&&a.length||(b=s==null?void 0:s.options)!=null&&b.length)?0:sa,p=(l+c+d+h)/ia;return qt.set(t.id,p),p}const oa=ze(Qo);function aa(){const t=nt(),{id:n,instance:i}=t;return e(oa,{id:n,instance:i})}const ca=""+new URL("boosts-carousel-YjmjXTE6.jpg",import.meta.url).href,ra=""+new URL("grouped-notifications-xYMFVY91.jpg",import.meta.url).href,la=""+new URL("multi-column-ETnJNDVb.jpg",import.meta.url).href,da=""+new URL("multi-hashtag-timeline-x-SDVR4g.jpg",import.meta.url).href,ua=""+new URL("nested-comments-thread-Ib-fZGS3.jpg",import.meta.url).href,ha="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20xml:space='preserve'%20fill-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%20clip-rule='evenodd'%20viewBox='0%200%20102%2028'%3e%3cpath%20fill='none'%20d='M0%200h101.5v27.5H0z'/%3e%3cg%20fill-rule='nonzero'%3e%3cpath%20fill='url(%23a)'%20d='M2.32%2021.85c1.4%200%202.21-.85%202.21-2.3v-4.64H8.5c4.45%200%207.54-2.9%207.54-7.24%200-4.35-2.98-7.24-7.32-7.24h-6.4C.93.43.11%201.28.11%202.73v16.82c0%201.45.82%202.3%202.21%202.3Zm2.21-10.4V3.94h3c2.54%200%204%201.34%204%203.75s-1.47%203.76-4%203.76h-3Z'/%3e%3cpath%20fill='url(%23b)'%20d='M20.52%2021.88c1.25%200%202.13-.76%202.13-2.23v-7.04c0-2.07%201.2-3.49%203.21-3.49%201.95%200%202.95%201.23%202.95%203.25v7.28c0%201.47.89%202.23%202.13%202.23%201.26%200%202.14-.76%202.14-2.23v-8.18c0-3.64-1.99-5.9-5.48-5.9-2.38%200-4.1%201.12-4.93%203.1h-.09V2.3c0-1.38-.78-2.2-2.1-2.2-1.31%200-2.1.82-2.1%202.2v17.34c0%201.47.9%202.23%202.14%202.23Z'/%3e%3cpath%20fill='url(%23c)'%20d='M40.45%2021.82c1.96%200%203.93-.98%204.8-2.65h.1v.8c.08%201.27.89%201.91%202.05%201.91%201.21%200%202.08-.73%202.08-2.15v-8.95c0-3.17-2.63-5.25-6.65-5.25-3.26%200-5.78%201.16-6.5%203.04-.15.32-.23.63-.23.96%200%20.97.75%201.64%201.79%201.64.69%200%201.23-.26%201.7-.79.95-1.23%201.74-1.65%203.04-1.65%201.62%200%202.64.85%202.64%202.31v1.04l-3.95.24c-3.93.23-6.13%201.88-6.13%204.74%200%202.83%202.27%204.76%205.26%204.76Zm1.4-3.09c-1.43%200-2.4-.73-2.4-1.9%200-1.12.91-1.83%202.51-1.95l3.31-.2v1.14c0%201.7-1.54%202.91-3.41%202.91Z'/%3e%3cpath%20fill='url(%23d)'%20d='M54.37%2021.88c1.26%200%202.14-.76%202.14-2.23v-7.09c0-2.03%201.21-3.44%203.13-3.44s2.89%201.17%202.89%203.22v7.31c0%201.47.88%202.23%202.14%202.23%201.24%200%202.13-.76%202.13-2.23v-8.2c0-3.68-1.96-5.87-5.45-5.87-2.41%200-4%201.07-4.83%203.01h-.09v-.87c0-1.35-.85-2.17-2.14-2.17-1.28%200-2.06.82-2.06%202.15v11.95c0%201.47.9%202.23%202.14%202.23Z'/%3e%3cpath%20fill='url(%23e)'%20d='M71.65%2027.17c1.26%200%202.14-.76%202.14-2.23v-6h.09a5.15%205.15%200%200%200%204.88%202.88c3.92%200%206.35-3.05%206.35-8.1%200-5.07-2.44-8.1-6.43-8.1a5.12%205.12%200%200%200-4.86%202.99h-.09v-.85c0-1.45-.88-2.21-2.1-2.21-1.24%200-2.11.76-2.11%202.2v17.2c0%201.46.89%202.22%202.13%202.22Zm5.6-8.8c-2.1%200-3.47-1.8-3.47-4.65%200-2.81%201.37-4.67%203.47-4.67%202.14%200%203.49%201.83%203.49%204.67%200%202.86-1.35%204.66-3.5%204.66Z'/%3e%3cpath%20fill='url(%23f)'%20d='M89.61%2027.39c3.44%200%205.26-1.5%206.73-5.55l4.81-13.1a4%204%200%200%200%20.24-1.26c0-1.13-.85-1.93-2.08-1.93-1.1%200-1.71.51-2.07%201.7l-3.4%2010.9h-.08L90.35%207.28c-.36-1.25-.94-1.73-2.07-1.73-1.26%200-2.21.83-2.21%201.99%200%20.35.09.82.25%201.26l5%2013.21-.21.56c-.52%201.1-1.32%201.42-2.07%201.42l-.75-.01c-.96%200-1.56.54-1.56%201.4%200%201.29%201%202%202.88%202Z'/%3e%3c/g%3e%3cdefs%3e%3cradialGradient%20id='a'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='b'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='c'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='d'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='e'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3cradialGradient%20id='f'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='rotate(28.51%20.06%20.22)%20scale(57.6252)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='%23a4bff7'/%3e%3cstop%20offset='1'%20stop-color='%236081e6'/%3e%3c/radialGradient%3e%3c/defs%3e%3c/svg%3e";var fa={PHANPY_CLIENT_NAME:"Phanpy",PHANPY_WEBSITE:"https://phanpy.social",PHANPY_LINGVA_INSTANCES:"lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud",PHANPY_PRIVACY_POLICY_URL:"https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD",VITE_APP_ENV:"production",BASE_URL:"./",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const{PHANPY_DEFAULT_INSTANCE:ut,PHANPY_WEBSITE:$n,PHANPY_PRIVACY_POLICY_URL:pa,PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL:xn}=fa,An=$n?$n.replace(/https?:\/\//g,"").replace(/\/$/,""):null,Ln=`${"2024-01-05T19:24:44.622Z".slice(0,10).replace(/-/g,".")}.32c53b8`;function Mn(){return _e(null,["/","/welcome"]),e("main",{id:"welcome",children:[e("div",{class:"hero-container",children:[e("div",{class:"hero-content",children:[e("h1",{children:[e("img",{src:Gt,alt:"",width:"160",height:"160",style:{aspectRatio:"1/1",marginBlockEnd:-16}}),e("img",{src:ha,alt:"Phanpy",width:"200"})]}),e("p",{class:"desc",children:"A minimalistic opinionated Mastodon web client."}),e("p",{children:e(ee,{to:ut?`/login?instance=${ut}&submit=1`:"/login",class:"button",children:ut?"Log in":"Log in with Mastodon"})}),ut&&xn&&e("p",{children:e("a",{href:xn,class:"button plain5",children:"Sign up"})}),!ut&&e("p",{class:"insignificant",children:e("small",{children:["Connect your existing Mastodon/Fediverse account.",e("br",{}),"Your credentials are not stored on this server."]})})]}),(An||Ln)&&e("p",{class:"app-site-version",children:e("small",{children:[An," ",Ln]})}),e("p",{children:[e("a",{href:"https://github.com/cheeaun/phanpy",target:"_blank",children:"Built"})," ","by"," ",e("a",{href:"https://mastodon.social/@cheeaun",target:"_blank",onClick:t=>{t.preventDefault(),k.showAccount="cheeaun@mastodon.social"},children:"@cheeaun"}),"."," ",e("a",{href:pa,target:"_blank",children:"Privacy Policy"}),"."]})]}),e("div",{id:"why-container",children:e("div",{class:"sections",children:[e("section",{children:[e("img",{src:ca,alt:"Screenshot of Boosts Carousel",loading:"lazy"}),e("h4",{children:"Boosts Carousel"}),e("p",{children:"Visually separate original posts and re-shared posts (boosted posts)."})]}),e("section",{children:[e("img",{src:ua,alt:"Screenshot of nested comments thread",loading:"lazy"}),e("h4",{children:"Nested comments thread"}),e("p",{children:"Effortlessly follow conversations. Semi-collapsible replies."})]}),e("section",{children:[e("img",{src:ra,alt:"Screenshot of grouped notifications",loading:"lazy"}),e("h4",{children:"Grouped notifications"}),e("p",{children:"Similar notifications are grouped and collapsed to reduce clutter."})]}),e("section",{children:[e("img",{src:la,alt:"Screenshot of multi-column UI",loading:"lazy"}),e("h4",{children:"Single or multi-column"}),e("p",{children:"By default, single column for zen-mode seekers. Configurable multi-column for power users."})]}),e("section",{children:[e("img",{src:da,alt:"Screenshot of multi-hashtag timeline with a form to add more hashtags",loading:"lazy"}),e("h4",{children:"Multi-hashtag timeline"}),e("p",{children:"Up to 5 hashtags combined into a single timeline."})]})]})})]})}const ma=window.alert;window.__nativeAlert||(window.__nativeAlert=ma);window.alert=function(t){t instanceof Error&&(t!=null&&t.message)&&(t=t.message),typeof t!="string"&&(t=JSON.stringify(t));const n=Bs({text:t,className:"alert",gravity:"top",position:"center",duration:1e4,offset:{y:48},onClick:()=>{n.hideToast()}});n.showToast()};window.__STATES__=k;window.__STATES_STATS__=()=>{const t=["statuses","accounts","spoilers","unfurledLinks","statusQuotes"],n={};t.forEach(a=>{n[a]=Object.keys(k[a]).length});const{statuses:i}=k,o=[];for(const a in i)document.querySelector(`[data-state-post-id~="${a}"], [data-state-post-ids~="${a}"]`)||o.push(a)};setInterval(()=>{if(!window.__IDLE__)return;const{statuses:t,unfurledLinks:n,notifications:i}=k;let o=0;const{instance:a}=z();for(const s in t){if(!window.__IDLE__)break;try{const u=document.querySelector(`[data-state-post-id~="${s}"], [data-state-post-ids~="${s}"]`),l=i.some(c=>{var d;return s===Ge((d=c.status)==null?void 0:d.id,a)});if(!u&&!l){delete k.statuses[s],delete k.statusQuotes[s];for(const c in n){const d=n[c];if(Ge(d.id,d.instance)===s){delete k.unfurledLinks[c];break}}o++}}catch{}}},15*60*1e3);setTimeout(()=>{for(const t in gt)queueMicrotask(()=>{var n,i,o,a;Array.isArray(gt[t])?(i=(n=gt[t])[0])==null||i.call(n):(a=(o=gt)[t])==null||a.call(o)})},5e3);(()=>{window.__IDLE__=!0;const t=["mousemove","mousedown","resize","keydown","touchstart","pointerdown","pointermove","wheel"],n=()=>{window.__IDLE__=!0},o=Yn(n,3e3),a=()=>{window.__IDLE__=!1,o()};t.forEach(s=>{window.addEventListener(s,a,{passive:!0,capture:!0})}),window.addEventListener("blur",n,{passive:!0}),document.documentElement.addEventListener("mouseleave",s=>{!s.relatedTarget&&!s.toElement&&n()},{passive:!0})})();const ga=/iPad|iPhone|iPod/.test(navigator.userAgent);ga&&document.addEventListener("visibilitychange",()=>{if(document.visibilityState==="visible"){const t=se.local.get("theme");let n;if(t){if(n=document.querySelector('meta[name="theme-color"][data-theme-setting="manual"]'),n){const i=n.content,o=t==="light"?n.dataset.themeLightColorTemp:n.dataset.themeDarkColorTemp;n.content=o||"",setTimeout(()=>{n.content=i},10)}}else{const i=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";if(n=document.querySelector(`meta[name="theme-color"][media*="${i}"]`),n){const o=n.dataset.content,a=n.dataset.contentTemp;n.content=a||"",setTimeout(()=>{n.content=o},10)}}}});{const t=se.local.get("theme");if(t){document.documentElement.classList.add(`is-${t}`),document.querySelector('meta[name="color-scheme"]').setAttribute("content",t||"dark light");const i=document.querySelector('meta[data-theme-setting="manual"]');i&&(i.name="theme-color",i.content=t==="light"?i.dataset.themeLightColor:i.dataset.themeDarkColor),document.querySelectorAll('meta[data-theme-setting="auto"]').forEach(a=>{a.name=""})}const n=se.local.get("textSize");n&&document.documentElement.style.setProperty("--text-size",`${n}px`)}Hn(k,t=>{var n;for(const[i,o,a,s]of t){if(o.join(".")==="settings.shortcutsViewMode"){const u=document.getElementById("app");u&&(u.dataset.shortcutsViewMode=(n=k.shortcuts)!=null&&n.length?a:"")}o.join(".")==="settings.cloakMode"&&document.body.classList.toggle("cloak",a)}});function ba(){const[t,n]=$(!1),[i,o]=$("loading");B(()=>{const s=se.local.get("instanceURL"),u=decodeURIComponent((window.location.search.match(/code=([^&]+)/)||[,""])[1]);if(u){window.history.replaceState({},document.title,window.location.pathname||"/");const l=se.session.get("clientID"),c=se.session.get("clientSecret"),d=se.session.get("vapidKey");(async()=>{o("loading");const{access_token:h}=await Yo({instanceURL:s,client_id:l,client_secret:c,code:u}),r=As({instance:s,accessToken:h});await Promise.allSettled([nn(r,s),Ls(r,s,h,d)]),sn(),on(r),n(!0),o("default")})()}else{window.__IGNORE_GET_ACCOUNT_ERROR__=!0;const l=at();if(l){se.session.set("currentAccount",l.info.id);const{client:c}=z({account:l}),{instance:d}=c;sn(),on(c),o("loading"),(async()=>{try{await nn(c,d)}catch{}finally{n(!0),o("default")}})()}else o("default")}},[]);let a=lt();return k.currentLocation=a.pathname,B(Dt,[a,t]),/\/https?:/.test(a.pathname)?e(Oo,{}):e(A,{children:[e(ya,{isLoggedIn:t,loading:i==="loading"}),e(wa,{isLoggedIn:t}),i==="default"&&e(Vt,{children:e(Te,{path:"/:instance?/s/:id",element:e(aa,{})})}),t&&e(js,{}),t&&e(Vi,{}),e(Oi,{}),t&&e(zi,{}),e(Gs,{isLoggedIn:t}),i!=="loading"&&e(qi,{onClose:Dt}),e(Ys,{})]})}function ya({isLoggedIn:t,loading:n}){const i=lt(),o=he(()=>{const{pathname:a}=i;return!/^\/(login|welcome)/.test(a)},[i]);return e(Vt,{location:o||i,children:[e(Te,{path:"/",element:t?e(Do,{}):n?e(Ie,{id:"loader-root"}):e(Mn,{})}),e(Te,{path:"/login",element:e(Zo,{})}),e(Te,{path:"/welcome",element:e(Mn,{})})]})}function Rn(){return k.prevLocation||null}function wa({isLoggedIn:t}){const n=lt(),i=D(Rn());return he(()=>pt("/:instance/s/:id",n.pathname)||pt("/s/:id",n.pathname),[n.pathname,pt])?i.current||(i.current=Rn()):i.current=null,e(Vt,{location:i.current||n,children:[t&&e(A,{children:[e(Te,{path:"/notifications",element:e(ls,{})}),e(Te,{path:"/mentions",element:e(cs,{})}),e(Te,{path:"/following",element:e(Jt,{})}),e(Te,{path:"/b",element:e(ss,{})}),e(Te,{path:"/f",element:e(is,{})}),e(Te,{path:"/l",children:[e(Te,{index:!0,element:e(Bo,{})}),e(Te,{path:":id",element:e(as,{})})]}),e(Te,{path:"/ft",element:e(lo,{})})]}),e(Te,{path:"/:instance?/t/:hashtag",element:e(os,{})}),e(Te,{path:"/:instance?/a/:id",element:e(oo,{})}),e(Te,{path:"/:instance?/p",children:[e(Te,{index:!0,element:e(Ot,{})}),e(Te,{path:"l",element:e(Ot,{local:!0})})]}),e(Te,{path:"/:instance?/trending",element:e(us,{})}),e(Te,{path:"/:instance?/search",element:e(ds,{})})]})}"AbortSignal"in window&&(AbortSignal.timeout=AbortSignal.timeout||(t=>{const n=new AbortController;return setTimeout(()=>n.abort(),t),n.signal}));qs(e(zs,{children:e(ba,{})}),document.getElementById("app"));setTimeout(()=>{try{Object.keys(localStorage).forEach(t=>{t.startsWith("iconify")&&localStorage.removeItem(t)}),Object.keys(sessionStorage).forEach(t=>{t.startsWith("iconify")&&sessionStorage.removeItem(t)}),localStorage.removeItem("settings:boostsCarousel")}catch{}},5e3);window.__CLOAK__=()=>{document.body.classList.toggle("cloak")};
+//# sourceMappingURL=main-9vVntYq7.js.map
diff --git a/assets/main-93nxKW6L.js.map b/assets/main-9vVntYq7.js.map
similarity index 99%
rename from assets/main-93nxKW6L.js.map
rename to assets/main-9vVntYq7.js.map
index 46f09ad..9f06731 100644
--- a/assets/main-93nxKW6L.js.map
+++ b/assets/main-9vVntYq7.js.map
@@ -1 +1 @@
-{"version":3,"file":"main-93nxKW6L.js","sources":["../../src/utils/usePageVisibility.js","../../src/components/background-service.jsx","../../src/components/compose-button.jsx","../../src/components/keyboard-shortcuts-help.jsx","../../src/pages/accounts.jsx","../../src/assets/logo.svg","../../src/utils/push-notifications.js","../../src/pages/settings.jsx","../../src/utils/focus-deck.jsx","../../src/utils/useLocationChange.js","../../src/components/list-add-edit.jsx","../../src/components/account-info.jsx","../../src/components/account-sheet.jsx","../../src/components/drafts.jsx","../../src/utils/relationships.js","../../src/components/generic-accounts.jsx","../../src/components/media-alt-modal.jsx","../../src/utils/color-utils.js","../../src/components/media-modal.jsx","../../src/assets/floating-button.svg","../../src/assets/multi-column.svg","../../src/assets/tab-menu-bar.svg","../../src/utils/followed-tags.js","../../src/components/AsyncText.jsx","../../src/components/shortcuts-settings.jsx","../../src/components/modals.jsx","../../src/components/follow-request-buttons.jsx","../../src/components/notification.jsx","../../src/components/notification-service.jsx","../../src/components/search-form.jsx","../../src/components/search-command.jsx","../../src/components/shortcuts.jsx","../../src/utils/timeline-utils.jsx","../../src/utils/useScroll.js","../../src/utils/useScrollFn.js","../../src/components/media-post.jsx","../../src/components/nav-menu.jsx","../../src/components/timeline.jsx","../../src/pages/account-statuses.jsx","../../src/pages/bookmarks.jsx","../../src/pages/favourites.jsx","../../src/pages/followed-hashtags.jsx","../../src/pages/following.jsx","../../src/pages/hashtag.jsx","../../src/pages/list.jsx","../../src/pages/mentions.jsx","../../src/utils/group-notifications.jsx","../../src/pages/notifications.jsx","../../src/pages/public.jsx","../../src/pages/search.jsx","../../src/pages/trending.jsx","../../src/components/columns.jsx","../../src/pages/home.jsx","../../src/utils/get-instance-status-url.js","../../src/pages/http-route.jsx","../../src/pages/lists.jsx","../../src/data/instances.json?url","../../src/utils/auth.js","../../src/pages/login.jsx","../../src/pages/status.jsx","../../src/pages/status-route.jsx","../../src/assets/features/boosts-carousel.jpg","../../src/assets/features/grouped-notifications.jpg","../../src/assets/features/multi-column.jpg","../../src/assets/features/multi-hashtag-timeline.jpg","../../src/assets/features/nested-comments-thread.jpg","../../src/assets/logo-text.svg","../../src/pages/welcome.jsx","../../src/utils/toast-alert.js","../../src/app.jsx","../../src/main.jsx"],"sourcesContent":["import { useEffect, useRef } from 'preact/hooks';\n\nexport default function usePageVisibility(fn = () => {}, deps = []) {\n const savedCallback = useRef(fn);\n useEffect(() => {\n savedCallback.current = fn;\n }, [deps]);\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n const hidden = document.hidden || document.visibilityState === 'hidden';\n console.log('👀 Page visibility changed', hidden ? 'hidden' : 'visible');\n savedCallback.current(!hidden);\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n return () =>\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n }, []);\n}\n","import { memo } from 'preact/compat';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\n\nimport { api } from '../utils/api';\nimport showToast from '../utils/show-toast';\nimport states, { saveStatus } from '../utils/states';\nimport useInterval from '../utils/useInterval';\nimport usePageVisibility from '../utils/usePageVisibility';\n\nconst STREAMING_TIMEOUT = 1000 * 3; // 3 seconds\nconst POLL_INTERVAL = 15_000; // 15 seconds\n\nexport default memo(function BackgroundService({ isLoggedIn }) {\n // Notifications service\n // - WebSocket to receive notifications when page is visible\n const [visible, setVisible] = useState(true);\n usePageVisibility(setVisible);\n const checkLatestNotification = async (masto, instance, skipCheckMarkers) => {\n if (states.notificationsLast) {\n const notificationsIterator = masto.v1.notifications.list({\n limit: 1,\n sinceId: states.notificationsLast.id,\n });\n const { value: notifications } = await notificationsIterator.next();\n if (notifications?.length) {\n if (skipCheckMarkers) {\n states.notificationsShowNew = true;\n } else {\n let lastReadId;\n try {\n const markers = await masto.v1.markers.fetch({\n timeline: 'notifications',\n });\n lastReadId = markers?.notifications?.lastReadId;\n } catch (e) {}\n if (lastReadId) {\n states.notificationsShowNew = notifications[0].id !== lastReadId;\n } else {\n states.notificationsShowNew = true;\n }\n }\n }\n }\n };\n\n useEffect(() => {\n let sub;\n let pollNotifications;\n if (isLoggedIn && visible) {\n const { masto, streaming, instance } = api();\n (async () => {\n // 1. Get the latest notification\n await checkLatestNotification(masto, instance);\n\n let hasStreaming = false;\n // 2. Start streaming\n if (streaming) {\n pollNotifications = setTimeout(() => {\n (async () => {\n try {\n hasStreaming = true;\n sub = streaming.user.notification.subscribe();\n console.log('🎏 Streaming notification', sub);\n for await (const entry of sub) {\n if (!sub) break;\n if (!visible) break;\n console.log('🔔🔔 Notification entry', entry);\n if (entry.event === 'notification') {\n console.log('🔔🔔 Notification', entry);\n saveStatus(entry.payload, instance, {\n skipThreading: true,\n });\n }\n states.notificationsShowNew = true;\n }\n console.log('💥 Streaming notification loop STOPPED');\n } catch (e) {\n hasStreaming = false;\n console.error(e);\n }\n\n if (!hasStreaming) {\n console.log('🎏 Streaming failed, fallback to polling');\n pollNotifications = setInterval(() => {\n checkLatestNotification(masto, instance, true);\n }, POLL_INTERVAL);\n }\n })();\n }, STREAMING_TIMEOUT);\n }\n })();\n }\n return () => {\n sub?.unsubscribe?.();\n sub = null;\n clearTimeout(pollNotifications);\n clearInterval(pollNotifications);\n };\n }, [visible, isLoggedIn]);\n\n // Check for updates service\n const lastCheckDate = useRef();\n const checkForUpdates = () => {\n lastCheckDate.current = Date.now();\n console.log('✨ Check app update');\n fetch('./version.json')\n .then((r) => r.json())\n .then((info) => {\n if (info) states.appVersion = info;\n })\n .catch((e) => {\n console.error(e);\n });\n };\n useInterval(checkForUpdates, visible && 1000 * 60 * 30); // 30 minutes\n usePageVisibility((visible) => {\n if (visible) {\n if (!lastCheckDate.current) {\n checkForUpdates();\n } else {\n const diff = Date.now() - lastCheckDate.current;\n if (diff > 1000 * 60 * 60) {\n // 1 hour\n checkForUpdates();\n }\n }\n }\n });\n\n // Global keyboard shortcuts \"service\"\n useHotkeys('shift+alt+k', () => {\n const currentCloakMode = states.settings.cloakMode;\n states.settings.cloakMode = !currentCloakMode;\n showToast({\n text: `Cloak mode ${currentCloakMode ? 'disabled' : 'enabled'}`,\n });\n });\n\n return null;\n});\n","import { useHotkeys } from 'react-hotkeys-hook';\n\nimport openCompose from '../utils/open-compose';\nimport states from '../utils/states';\n\nimport Icon from './icon';\n\nexport default function ComposeButton() {\n function handleButton(e) {\n if (e.shiftKey) {\n const newWin = openCompose();\n\n if (!newWin) {\n states.showCompose = true;\n }\n } else {\n states.showCompose = true;\n }\n }\n\n useHotkeys('c, shift+c', handleButton, {\n ignoreEventWhen: (e) => {\n const hasModal = !!document.querySelector('#modal-container > *');\n return hasModal;\n },\n });\n\n return (\n \n \n \n );\n}\n","import './keyboard-shortcuts-help.css';\n\nimport { memo } from 'preact/compat';\nimport { useHotkeys } from 'react-hotkeys-hook';\nimport { useSnapshot } from 'valtio';\n\nimport states from '../utils/states';\n\nimport Icon from './icon';\nimport Modal from './modal';\n\nexport default memo(function KeyboardShortcutsHelp() {\n const snapStates = useSnapshot(states);\n\n function onClose() {\n states.showKeyboardShortcutsHelp = false;\n }\n\n useHotkeys(\n '?, shift+?',\n (e) => {\n console.log('help');\n states.showKeyboardShortcutsHelp = true;\n },\n {\n ignoreEventWhen: (e) => {\n const hasModal = !!document.querySelector('#modal-container > *');\n return hasModal;\n },\n },\n );\n\n return (\n !!snapStates.showKeyboardShortcutsHelp && (\n \n \n
\n \n \n
\n
\n \n {[\n {\n action: 'Keyboard shortcuts help',\n keys: ? ,\n },\n {\n action: 'Next post',\n keys: j ,\n },\n {\n action: 'Previous post',\n keys: k ,\n },\n {\n action: 'Skip carousel to next post',\n keys: (\n <>\n Shift + j \n >\n ),\n },\n {\n action: 'Skip carousel to previous post',\n keys: (\n <>\n Shift + k \n >\n ),\n },\n {\n action: 'Open post details',\n keys: (\n <>\n Enter or o \n >\n ),\n },\n {\n action: (\n <>\n Expand content warning or\n \n toggle expanded/collapsed thread\n >\n ),\n keys: x ,\n },\n {\n action: 'Close post or dialogs',\n keys: (\n <>\n Esc or Backspace \n >\n ),\n },\n {\n action: 'Focus column in multi-column mode',\n keys: (\n <>\n 1 to 9 \n >\n ),\n },\n {\n action: 'Compose new post',\n keys: c ,\n },\n {\n action: 'Compose new post (new window)',\n className: 'insignificant',\n keys: (\n <>\n Shift + c \n >\n ),\n },\n {\n action: 'Send post',\n keys: (\n <>\n Ctrl + Enter or ⌘ +{' '}\n Enter \n >\n ),\n },\n {\n action: 'Search',\n keys: / ,\n },\n {\n action: 'Reply',\n keys: r ,\n },\n {\n action: 'Reply (new window)',\n className: 'insignificant',\n keys: (\n <>\n Shift + r \n >\n ),\n },\n {\n action: 'Like (favourite)',\n keys: (\n <>\n l or f \n >\n ),\n },\n {\n action: 'Boost',\n keys: (\n <>\n Shift + b \n >\n ),\n },\n {\n action: 'Bookmark',\n keys: d ,\n },\n {\n action: 'Toggle Cloak mode',\n keys: (\n <>\n Shift + Alt + k \n >\n ),\n },\n ].map(({ action, className, keys }) => (\n \n {action} \n {keys} \n \n ))}\n
\n \n
\n \n )\n );\n});\n","import './accounts.css';\n\nimport { useAutoAnimate } from '@formkit/auto-animate/preact';\nimport { Menu, MenuDivider, MenuItem } from '@szhsin/react-menu';\nimport { useReducer } from 'preact/hooks';\n\nimport Avatar from '../components/avatar';\nimport Icon from '../components/icon';\nimport Link from '../components/link';\nimport Menu2 from '../components/menu2';\nimport MenuConfirm from '../components/menu-confirm';\nimport NameText from '../components/name-text';\nimport { api } from '../utils/api';\nimport states from '../utils/states';\nimport store from '../utils/store';\n\nfunction Accounts({ onClose }) {\n const { masto } = api();\n // Accounts\n const accounts = store.local.getJSON('accounts');\n const currentAccount = store.session.get('currentAccount');\n const moreThanOneAccount = accounts.length > 1;\n\n const [_, reload] = useReducer((x) => x + 1, 0);\n const [accountsListParent] = useAutoAnimate();\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n \n
\n \n \n {accounts.map((account, i) => {\n const isCurrent = account.info.id === currentAccount;\n const isDefault = i === 0; // first account is always default\n return (\n \n \n {moreThanOneAccount && (\n
\n \n \n )}\n
{\n if (isCurrent) {\n try {\n const info = await masto.v1.accounts\n .$select(account.info.id)\n .fetch();\n console.log('fetched account info', info);\n account.info = info;\n store.local.setJSON('accounts', accounts);\n reload();\n } catch (e) {}\n }\n }}\n />\n {\n if (isCurrent) {\n states.showAccount = `${account.info.username}@${account.instanceURL}`;\n } else {\n store.session.set('currentAccount', account.info.id);\n location.reload();\n }\n }}\n />\n \n \n {isDefault && moreThanOneAccount && (\n <>\n Default {' '}\n >\n )}\n \n \n \n }\n >\n {\n states.showAccount = `${account.info.username}@${account.instanceURL}`;\n }}\n >\n \n View profile… \n \n \n {moreThanOneAccount && (\n {\n // Move account to the top of the list\n accounts.splice(i, 1);\n accounts.unshift(account);\n store.local.setJSON('accounts', accounts);\n reload();\n }}\n >\n \n Set as default \n \n )}\n \n \n Log out @{account.info.acct}? \n >\n }\n disabled={!isCurrent}\n menuItemClassName=\"danger\"\n onClick={() => {\n // const yes = confirm('Log out?');\n // if (!yes) return;\n accounts.splice(i, 1);\n store.local.setJSON('accounts', accounts);\n // location.reload();\n location.href = location.pathname || '/';\n }}\n >\n \n Log out… \n \n \n
\n \n );\n })}\n \n \n \n Add an existing account \n \n
\n {moreThanOneAccount && (\n \n \n Note: Default account will always be used for first load.\n Switched accounts will persist during the session.\n \n
\n )}\n \n \n
\n );\n}\n\nexport default Accounts;\n","export default \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20xml:space='preserve'%20fill-rule='evenodd'%20stroke-linejoin='round'%20stroke-miterlimit='2'%20clip-rule='evenodd'%20viewBox='0%200%2064%2064'%3e%3cpath%20fill='none'%20d='M0%200h63.994v63.994H0z'/%3e%3cpath%20fill='%23a4bff7'%20d='M37.774%2011.471c14.639%203.752%2019.034%2016.557%2015.889%2031.304-.696%203.261-2.563%206.661-6.356%208.693-3.204%201.717-8.07%202.537-15.338.55l-9.634-2.404C11.651%2046.992%208.378%2038.733%2010.027%2031.823c3.627-15.201%2015.543-23.48%2027.747-20.352Z'/%3e%3cpath%20fill='%23d8e7fe'%20d='M36.76%2015.429c12.289%203.15%2015.547%2014.114%2012.907%2026.493-.947%204.44-4.937%209.365-16.664%206.143l-9.684-2.417c-7.854-1.923-10.53-7.8-9.318-12.877%203.016-12.639%2012.611-19.943%2022.759-17.342Z'/%3e%3cpath%20fill='%236081e6'%20d='M27.471%2024.991c-1.457-.698-7.229%203.213-7.663%208.926-.182%202.39%204.55%203.237%205.071-.169.725-4.743%203.715-8.218%202.592-8.757Zm10.746%202.005c-2.083.327-.382%205.901-.595%2010.727-.123%202.8%204.388%203.464%204.703%202.011%201.098-5.073-2.066-13.058-4.108-12.738Z'/%3e%3c/svg%3e\"","// Utils for push notifications\nimport { api } from './api';\nimport { getCurrentAccount } from './store-utils';\n\n// Subscription is an object with the following structure:\n// {\n// data: {\n// alerts: {\n// admin: {\n// report: boolean,\n// signUp: boolean,\n// },\n// favourite: boolean,\n// follow: boolean,\n// mention: boolean,\n// poll: boolean,\n// reblog: boolean,\n// status: boolean,\n// update: boolean,\n// }\n// },\n// policy: \"all\" | \"followed\" | \"follower\" | \"none\",\n// subscription: {\n// endpoint: string,\n// keys: {\n// auth: string,\n// p256dh: string,\n// },\n// },\n// }\n\n// Back-end CRUD\n// =============\n\nfunction createBackendPushSubscription(subscription) {\n const { masto } = api();\n return masto.v1.push.subscription.create(subscription);\n}\n\nfunction fetchBackendPushSubscription() {\n const { masto } = api();\n return masto.v1.push.subscription.fetch();\n}\n\nfunction updateBackendPushSubscription(subscription) {\n const { masto } = api();\n return masto.v1.push.subscription.update(subscription);\n}\n\nfunction removeBackendPushSubscription() {\n const { masto } = api();\n return masto.v1.push.subscription.remove();\n}\n\n// Front-end\n// =========\n\nexport function isPushSupported() {\n return 'serviceWorker' in navigator && 'PushManager' in window;\n}\n\nexport function getRegistration() {\n // return navigator.serviceWorker.ready;\n return navigator.serviceWorker.getRegistration();\n}\n\nasync function getSubscription() {\n const registration = await getRegistration();\n const subscription = registration\n ? await registration.pushManager.getSubscription()\n : undefined;\n return { registration, subscription };\n}\n\nfunction urlBase64ToUint8Array(base64String) {\n const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n const base64 = `${base64String}${padding}`\n .replace(/-/g, '+')\n .replace(/_/g, '/');\n\n const rawData = window.atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n\n for (let i = 0; i < rawData.length; ++i) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n\n return outputArray;\n}\n\n// Front-end <-> back-end\n// ======================\n\nexport async function initSubscription() {\n if (!isPushSupported()) return;\n const { subscription } = await getSubscription();\n let backendSubscription = null;\n try {\n backendSubscription = await fetchBackendPushSubscription();\n } catch (err) {\n if (/(not found|unknown)/i.test(err.message)) {\n // No subscription found\n } else {\n // Other error\n throw err;\n }\n }\n console.log('INIT subscription', {\n subscription,\n backendSubscription,\n });\n\n // Check if the subscription changed\n if (backendSubscription && subscription) {\n const sameEndpoint = backendSubscription.endpoint === subscription.endpoint;\n const { vapidKey } = getCurrentAccount();\n const sameKey = backendSubscription.serverKey === vapidKey;\n if (!sameEndpoint) {\n throw new Error('Backend subscription endpoint changed');\n }\n if (sameKey) {\n // Subscription didn't change\n } else {\n // Subscription changed\n console.error('🔔 Subscription changed', {\n sameEndpoint,\n serverKey: backendSubscription.serverKey,\n vapIdKey: vapidKey,\n endpoint1: backendSubscription.endpoint,\n endpoint2: subscription.endpoint,\n sameKey,\n key1: backendSubscription.serverKey,\n key2: vapidKey,\n });\n throw new Error('Backend subscription key and vapid key changed');\n // Only unsubscribe from backend, not from browser\n // await removeBackendPushSubscription();\n // // Now let's resubscribe\n // // NOTE: I have no idea if this works\n // return await updateSubscription({\n // data: backendSubscription.data,\n // policy: backendSubscription.policy,\n // });\n }\n }\n\n if (subscription && !backendSubscription) {\n // check if account's vapidKey is same as subscription's applicationServerKey\n const { vapidKey } = getCurrentAccount();\n const { applicationServerKey } = subscription.options;\n const vapidKeyStr = urlBase64ToUint8Array(vapidKey).toString();\n const applicationServerKeyStr = new Uint8Array(\n applicationServerKey,\n ).toString();\n const sameKey = vapidKeyStr === applicationServerKeyStr;\n if (sameKey) {\n // Subscription didn't change\n } else {\n // Subscription changed\n console.error('🔔 Subscription changed', {\n vapidKeyStr,\n applicationServerKeyStr,\n sameKey,\n });\n // Unsubscribe since backend doesn't have a subscription\n await subscription.unsubscribe();\n throw new Error('Subscription key and vapid key changed');\n }\n }\n\n // Check if backend subscription returns 404\n // if (subscription && !backendSubscription) {\n // // Re-subscribe to backend\n // backendSubscription = await createBackendPushSubscription({\n // subscription,\n // data: {},\n // policy: 'all',\n // });\n // }\n\n return { subscription, backendSubscription };\n}\n\nexport async function updateSubscription({ data, policy }) {\n console.log('🔔 Updating subscription', { data, policy });\n if (!isPushSupported()) return;\n let { registration, subscription } = await getSubscription();\n let backendSubscription = null;\n\n if (subscription) {\n try {\n backendSubscription = await updateBackendPushSubscription({\n data,\n policy,\n });\n // TODO: save subscription in user settings\n } catch (error) {\n // Backend doesn't have a subscription for this user\n // Create a new one\n backendSubscription = await createBackendPushSubscription({\n subscription,\n data,\n policy,\n });\n // TODO: save subscription in user settings\n }\n } else {\n // User is not subscribed\n const { vapidKey } = getCurrentAccount();\n if (!vapidKey) throw new Error('No server key found');\n subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(vapidKey),\n });\n backendSubscription = await createBackendPushSubscription({\n subscription,\n data,\n policy,\n });\n // TODO: save subscription in user settings\n }\n\n return { subscription, backendSubscription };\n}\n\nexport async function removeSubscription() {\n if (!isPushSupported()) return;\n const { subscription } = await getSubscription();\n if (subscription) {\n await removeBackendPushSubscription();\n await subscription.unsubscribe();\n }\n}\n","import './settings.css';\n\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useSnapshot } from 'valtio';\n\nimport logo from '../assets/logo.svg';\n\nimport Icon from '../components/icon';\nimport Link from '../components/link';\nimport RelativeTime from '../components/relative-time';\nimport targetLanguages from '../data/lingva-target-languages';\nimport { api } from '../utils/api';\nimport getTranslateTargetLanguage from '../utils/get-translate-target-language';\nimport localeCode2Text from '../utils/localeCode2Text';\nimport {\n initSubscription,\n isPushSupported,\n removeSubscription,\n updateSubscription,\n} from '../utils/push-notifications';\nimport showToast from '../utils/show-toast';\nimport states from '../utils/states';\nimport store from '../utils/store';\n\nconst DEFAULT_TEXT_SIZE = 16;\nconst TEXT_SIZES = [15, 16, 17, 18, 19, 20];\nconst {\n PHANPY_WEBSITE: WEBSITE,\n PHANPY_PRIVACY_POLICY_URL: PRIVACY_POLICY_URL,\n PHANPY_IMG_ALT_API_URL: IMG_ALT_API_URL,\n} = import.meta.env;\n\nfunction Settings({ onClose }) {\n const snapStates = useSnapshot(states);\n const currentTheme = store.local.get('theme') || 'auto';\n const themeFormRef = useRef();\n const targetLanguage =\n snapStates.settings.contentTranslationTargetLanguage || null;\n const systemTargetLanguage = getTranslateTargetLanguage();\n const systemTargetLanguageText = localeCode2Text(systemTargetLanguage);\n const currentTextSize = store.local.get('textSize') || DEFAULT_TEXT_SIZE;\n\n const [prefs, setPrefs] = useState(store.account.get('preferences') || {});\n const { masto, authenticated, instance } = api();\n // Get preferences every time Settings is opened\n // NOTE: Disabled for now because I don't expect this to change often. Also for some reason, the /api/v1/preferences endpoint is cached for a while and return old prefs if refresh immediately after changing them.\n // useEffect(() => {\n // const { masto } = api();\n // (async () => {\n // try {\n // const preferences = await masto.v1.preferences.fetch();\n // setPrefs(preferences);\n // store.account.set('preferences', preferences);\n // } catch (e) {\n // // Silently fail\n // console.error(e);\n // }\n // })();\n // }, []);\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n
\n
\n \n \n \n \n Appearance \n
\n \n \n \n \n Text size \n
\n \n A {' '}\n {\n const value = parseInt(e.target.value, 10);\n const html = document.documentElement;\n // set CSS variable\n html.style.setProperty('--text-size', `${value}px`);\n // save to local storage\n if (value === DEFAULT_TEXT_SIZE) {\n store.local.del('textSize');\n } else {\n store.local.set('textSize', e.target.value);\n }\n }}\n />{' '}\n \n A\n \n \n {TEXT_SIZES.map((size) => (\n \n ))}\n \n
\n \n \n \n {authenticated && (\n <>\n Posting \n \n \n \n \n \n Default visibility{' '}\n \n \n
\n \n {\n const { value } = e.target;\n (async () => {\n try {\n await masto.v1.accounts.updateCredentials({\n source: {\n privacy: value,\n },\n });\n setPrefs({\n ...prefs,\n 'posting:default:visibility': value,\n });\n store.account.set('preferences', {\n ...prefs,\n 'posting:default:visibility': value,\n });\n } catch (e) {\n alert('Failed to update posting privacy');\n console.error(e);\n }\n })();\n }}\n >\n Public \n Unlisted \n Followers only \n \n
\n \n \n \n \n {' '}\n \n Synced to your instance server's settings.{' '}\n \n Go to your instance ({instance}) for more settings.\n \n \n
\n >\n )}\n Experiments \n \n {authenticated && }\n About \n \n \n
\n
\n
\n \n \n Sponsor\n {' '}\n ·{' '}\n \n Donate\n {' '}\n ·{' '}\n \n Privacy Policy\n \n
\n {__BUILD_TIME__ && (\n \n {WEBSITE && (\n <>\n Site: {' '}\n {WEBSITE.replace(/https?:\\/\\//g, '').replace(/\\/$/, '')}\n \n >\n )}\n Version: {' '}\n {\n e.target.select();\n // Copy to clipboard\n try {\n navigator.clipboard.writeText(e.target.value);\n showToast('Version string copied');\n } catch (e) {\n console.warn(e);\n showToast('Unable to copy version string');\n }\n }}\n />{' '}\n {!__FAKE_COMMIT_HASH__ && (\n \n (\n \n \n \n )\n \n )}\n
\n )}\n \n \n
\n );\n}\n\nfunction PushNotificationsSection({ onClose }) {\n if (!isPushSupported()) return null;\n\n const { instance } = api();\n const [uiState, setUIState] = useState('default');\n const pushFormRef = useRef();\n const [allowNofitications, setAllowNotifications] = useState(false);\n const [needRelogin, setNeedRelogin] = useState(false);\n const previousPolicyRef = useRef();\n useEffect(() => {\n (async () => {\n setUIState('loading');\n try {\n const { subscription, backendSubscription } = await initSubscription();\n if (\n backendSubscription?.policy &&\n backendSubscription.policy !== 'none'\n ) {\n setAllowNotifications(true);\n const { alerts, policy } = backendSubscription;\n previousPolicyRef.current = policy;\n const { elements } = pushFormRef.current;\n const policyEl = elements.namedItem(policy);\n if (policyEl) policyEl.value = policy;\n // alerts is {}, iterate it\n Object.keys(alerts).forEach((alert) => {\n const el = elements.namedItem(alert);\n if (el?.type === 'checkbox') {\n el.checked = true;\n }\n });\n }\n setUIState('default');\n } catch (err) {\n console.warn(err);\n if (/outside.*authorized/i.test(err.message)) {\n setNeedRelogin(true);\n } else {\n alert(err?.message || err);\n }\n setUIState('error');\n }\n })();\n }, []);\n\n const isLoading = uiState === 'loading';\n\n return (\n \n );\n}\n\nexport default Settings;\n","const focusDeck = () => {\n let timer = setTimeout(() => {\n const columns = document.getElementById('columns');\n if (columns) {\n // Focus first column\n // columns.querySelector('.deck-container')?.focus?.();\n } else {\n const modals = document.querySelectorAll('#modal-container > *');\n if (modals?.length) {\n // Focus last modal\n const modal = modals[modals.length - 1]; // last one\n const modalFocusElement =\n modal.querySelector('[tabindex=\"-1\"]') || modal;\n if (modalFocusElement) {\n modalFocusElement.focus();\n return;\n }\n }\n const backDrop = document.querySelector('.deck-backdrop');\n if (backDrop) return;\n // Focus last deck\n const pages = document.querySelectorAll('.deck-container');\n const page = pages[pages.length - 1]; // last one\n if (page && page.tabIndex === -1) {\n console.log('FOCUS', page);\n page.focus();\n }\n }\n }, 100);\n return () => clearTimeout(timer);\n};\n\nexport default focusDeck;\n","import { useEffect, useRef } from 'preact/hooks';\nimport { useLocation } from 'react-router-dom';\n\n// Hook that runs a callback when the location changes\n// Won't run on the first render\n\nexport default function useLocationChange(fn) {\n if (!fn) return;\n const location = useLocation();\n const currentLocationRef = useRef(location.pathname);\n useEffect(() => {\n // console.log('location', {\n // current: currentLocationRef.current,\n // next: location.pathname,\n // });\n if (\n currentLocationRef.current &&\n location.pathname !== currentLocationRef.current\n ) {\n fn?.();\n }\n }, [location.pathname, fn]);\n}\n","import { useEffect, useRef, useState } from 'preact/hooks';\n\nimport { api } from '../utils/api';\nimport supports from '../utils/supports';\n\nimport Icon from './icon';\nimport MenuConfirm from './menu-confirm';\n\nfunction ListAddEdit({ list, onClose }) {\n const { masto } = api();\n const [uiState, setUIState] = useState('default');\n const editMode = !!list;\n const nameFieldRef = useRef();\n const repliesPolicyFieldRef = useRef();\n const exclusiveFieldRef = useRef();\n useEffect(() => {\n if (editMode) {\n nameFieldRef.current.value = list.title;\n repliesPolicyFieldRef.current.value = list.repliesPolicy;\n if (exclusiveFieldRef.current) {\n exclusiveFieldRef.current.checked = list.exclusive;\n }\n }\n }, [editMode]);\n const supportsExclusive = supports('@mastodon/list-exclusive');\n\n return (\n \n {!!onClose && (\n
\n \n \n )}{' '}\n
\n {editMode ? 'Edit list' : 'New list'} \n \n
\n \n \n
\n );\n}\n\nexport default ListAddEdit;\n","import './account-info.css';\n\nimport { Menu, MenuDivider, MenuItem, SubMenu } from '@szhsin/react-menu';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n} from 'preact/hooks';\n\nimport { api } from '../utils/api';\nimport enhanceContent from '../utils/enhance-content';\nimport getHTMLText from '../utils/getHTMLText';\nimport handleContentLinks from '../utils/handle-content-links';\nimport niceDateTime from '../utils/nice-date-time';\nimport pmem from '../utils/pmem';\nimport shortenNumber from '../utils/shorten-number';\nimport showToast from '../utils/show-toast';\nimport states, { hideAllModals } from '../utils/states';\nimport store from '../utils/store';\nimport { updateAccount } from '../utils/store-utils';\n\nimport AccountBlock from './account-block';\nimport Avatar from './avatar';\nimport EmojiText from './emoji-text';\nimport Icon from './icon';\nimport Link from './link';\nimport ListAddEdit from './list-add-edit';\nimport Loader from './loader';\nimport Menu2 from './menu2';\nimport MenuConfirm from './menu-confirm';\nimport Modal from './modal';\nimport TranslationBlock from './translation-block';\n\nconst MUTE_DURATIONS = [\n 60 * 5, // 5 minutes\n 60 * 30, // 30 minutes\n 60 * 60, // 1 hour\n 60 * 60 * 6, // 6 hours\n 60 * 60 * 24, // 1 day\n 60 * 60 * 24 * 3, // 3 days\n 60 * 60 * 24 * 7, // 1 week\n 0, // forever\n];\nconst MUTE_DURATIONS_LABELS = {\n 0: 'Forever',\n 300: '5 minutes',\n 1_800: '30 minutes',\n 3_600: '1 hour',\n 21_600: '6 hours',\n 86_400: '1 day',\n 259_200: '3 days',\n 604_800: '1 week',\n};\n\nconst LIMIT = 80;\n\nconst ACCOUNT_INFO_MAX_AGE = 1000 * 60 * 10; // 10 mins\n\nfunction fetchFamiliarFollowers(currentID, masto) {\n return masto.v1.accounts.familiarFollowers.fetch({\n id: [currentID],\n });\n}\nconst memFetchFamiliarFollowers = pmem(fetchFamiliarFollowers, {\n maxAge: ACCOUNT_INFO_MAX_AGE,\n});\n\nasync function fetchPostingStats(accountID, masto) {\n const fetchStatuses = masto.v1.accounts\n .$select(accountID)\n .statuses.list({\n limit: 20,\n })\n .next();\n\n const { value: statuses } = await fetchStatuses;\n console.log('fetched statuses', statuses);\n const stats = {\n total: statuses.length,\n originals: 0,\n replies: 0,\n boosts: 0,\n };\n // Categories statuses by type\n // - Original posts (not replies to others)\n // - Threads (self-replies + 1st original post)\n // - Boosts (reblogs)\n // - Replies (not-self replies)\n statuses.forEach((status) => {\n if (status.reblog) {\n stats.boosts++;\n } else if (\n !!status.inReplyToId &&\n status.inReplyToAccountId !== status.account.id // Not self-reply\n ) {\n stats.replies++;\n } else {\n stats.originals++;\n }\n });\n\n // Count days since last post\n if (statuses.length) {\n stats.daysSinceLastPost = Math.ceil(\n (Date.now() - new Date(statuses[statuses.length - 1].createdAt)) /\n 86400000,\n );\n }\n\n console.log('posting stats', stats);\n return stats;\n}\nconst memFetchPostingStats = pmem(fetchPostingStats, {\n maxAge: ACCOUNT_INFO_MAX_AGE,\n});\n\nfunction AccountInfo({\n account,\n fetchAccount = () => {},\n standalone,\n instance,\n authenticated,\n}) {\n const { masto } = api({\n instance,\n });\n const { masto: currentMasto, instance: currentInstance } = api();\n const [uiState, setUIState] = useState('default');\n const isString = typeof account === 'string';\n const [info, setInfo] = useState(isString ? null : account);\n\n const sameCurrentInstance = useMemo(\n () => instance === currentInstance,\n [instance, currentInstance],\n );\n\n useEffect(() => {\n if (!isString) {\n setInfo(account);\n return;\n }\n setUIState('loading');\n (async () => {\n try {\n const info = await fetchAccount();\n states.accounts[`${info.id}@${instance}`] = info;\n setInfo(info);\n setUIState('default');\n } catch (e) {\n console.error(e);\n setInfo(null);\n setUIState('error');\n }\n })();\n }, [isString, account, fetchAccount]);\n\n const {\n acct,\n avatar,\n avatarStatic,\n bot,\n createdAt,\n displayName,\n emojis,\n fields,\n followersCount,\n followingCount,\n group,\n // header,\n // headerStatic,\n id,\n lastStatusAt,\n locked,\n note,\n statusesCount,\n url,\n username,\n memorial,\n moved,\n roles,\n } = info || {};\n let headerIsAvatar = false;\n let { header, headerStatic } = info || {};\n if (!header || /missing\\.png$/.test(header)) {\n if (avatar && !/missing\\.png$/.test(avatar)) {\n header = avatar;\n headerIsAvatar = true;\n if (avatarStatic && !/missing\\.png$/.test(avatarStatic)) {\n headerStatic = avatarStatic;\n }\n }\n }\n\n const isSelf = useMemo(\n () => id === store.session.get('currentAccount'),\n [id],\n );\n\n useEffect(() => {\n const infoHasEssentials = !!(\n info?.id &&\n info?.username &&\n info?.acct &&\n info?.avatar &&\n info?.avatarStatic &&\n info?.displayName &&\n info?.url\n );\n if (isSelf && instance && infoHasEssentials) {\n const accounts = store.local.getJSON('accounts');\n let updated = false;\n accounts.forEach((account) => {\n if (account.info.id === info.id && account.instanceURL === instance) {\n account.info = info;\n updated = true;\n }\n });\n if (updated) {\n console.log('Updated account info', info);\n store.local.setJSON('accounts', accounts);\n }\n }\n }, [isSelf, info, instance]);\n\n const accountInstance = useMemo(() => {\n if (!url) return null;\n const domain = new URL(url).hostname;\n return domain;\n }, [url]);\n\n const [headerCornerColors, setHeaderCornerColors] = useState([]);\n\n const followersIterator = useRef();\n const familiarFollowersCache = useRef([]);\n async function fetchFollowers(firstLoad) {\n if (firstLoad || !followersIterator.current) {\n followersIterator.current = masto.v1.accounts.$select(id).followers.list({\n limit: LIMIT,\n });\n }\n const results = await followersIterator.current.next();\n if (isSelf) return results;\n if (!sameCurrentInstance) return results;\n\n const { value } = results;\n let newValue = [];\n // On first load, fetch familiar followers, merge to top of results' `value`\n // Remove dups on every fetch\n if (firstLoad) {\n const familiarFollowers = await masto.v1.accounts.familiarFollowers.fetch(\n {\n id: [id],\n },\n );\n familiarFollowersCache.current = familiarFollowers[0].accounts;\n newValue = [\n ...familiarFollowersCache.current,\n ...value.filter(\n (account) =>\n !familiarFollowersCache.current.some(\n (familiar) => familiar.id === account.id,\n ),\n ),\n ];\n } else if (value?.length) {\n newValue = value.filter(\n (account) =>\n !familiarFollowersCache.current.some(\n (familiar) => familiar.id === account.id,\n ),\n );\n }\n\n return {\n ...results,\n value: newValue,\n };\n }\n\n const followingIterator = useRef();\n async function fetchFollowing(firstLoad) {\n if (firstLoad || !followingIterator.current) {\n followingIterator.current = masto.v1.accounts.$select(id).following.list({\n limit: LIMIT,\n });\n }\n const results = await followingIterator.current.next();\n return results;\n }\n\n const LinkOrDiv = standalone ? 'div' : Link;\n const accountLink = instance ? `/${instance}/a/${id}` : `/a/${id}`;\n\n const [familiarFollowers, setFamiliarFollowers] = useState([]);\n const [postingStats, setPostingStats] = useState();\n const [postingStatsUIState, setPostingStatsUIState] = useState('default');\n const hasPostingStats = !!postingStats?.total;\n\n const renderFamiliarFollowers = async (currentID) => {\n try {\n const followers = await memFetchFamiliarFollowers(\n currentID,\n currentMasto,\n );\n console.log('fetched familiar followers', followers);\n setFamiliarFollowers(\n followers[0].accounts.slice(0, FAMILIAR_FOLLOWERS_LIMIT),\n );\n } catch (e) {\n console.error(e);\n }\n };\n\n const renderPostingStats = async () => {\n if (!id) return;\n setPostingStatsUIState('loading');\n try {\n const stats = await memFetchPostingStats(id, masto);\n setPostingStats(stats);\n setPostingStatsUIState('default');\n } catch (e) {\n console.error(e);\n setPostingStatsUIState('error');\n }\n };\n\n const onRelationshipChange = useCallback(\n ({ relationship, currentID }) => {\n if (!relationship.following) {\n renderFamiliarFollowers(currentID);\n if (!standalone && statusesCount > 0) {\n // Only render posting stats if not standalone and has posts\n renderPostingStats();\n }\n }\n },\n [standalone, id, statusesCount],\n );\n\n return (\n \n {uiState === 'error' && (\n
\n )}\n {uiState === 'loading' ? (\n <>\n
\n
\n \n
███████ ████ ████
\n
████ ████████ ██████ █████████ ████ ██
\n
\n \n \n \n \n \n \n \n \n
\n \n >\n ) : (\n info && (\n <>\n {!!moved && (\n
\n
\n {displayName} has indicated that their new account is\n now:\n
\n
{\n e.stopPropagation();\n states.showAccount = moved;\n }}\n />\n \n )}\n {!!header && !/missing\\.png$/.test(header) && (\n {\n if (e.target.crossOrigin) {\n if (e.target.src !== headerStatic) {\n e.target.src = headerStatic;\n } else {\n e.target.removeAttribute('crossorigin');\n e.target.src = header;\n }\n } else if (e.target.src !== headerStatic) {\n e.target.src = headerStatic;\n } else {\n e.target.remove();\n }\n }}\n crossOrigin=\"anonymous\"\n onLoad={(e) => {\n e.target.classList.add('loaded');\n try {\n // Get color from four corners of image\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d', {\n willReadFrequently: true,\n });\n canvas.width = e.target.width;\n canvas.height = e.target.height;\n ctx.drawImage(e.target, 0, 0);\n // const colors = [\n // ctx.getImageData(0, 0, 1, 1).data,\n // ctx.getImageData(e.target.width - 1, 0, 1, 1).data,\n // ctx.getImageData(0, e.target.height - 1, 1, 1).data,\n // ctx.getImageData(\n // e.target.width - 1,\n // e.target.height - 1,\n // 1,\n // 1,\n // ).data,\n // ];\n // Get 10x10 pixels from corners, get average color from each\n const pixelDimension = 10;\n const colors = [\n ctx.getImageData(0, 0, pixelDimension, pixelDimension)\n .data,\n ctx.getImageData(\n e.target.width - pixelDimension,\n 0,\n pixelDimension,\n pixelDimension,\n ).data,\n ctx.getImageData(\n 0,\n e.target.height - pixelDimension,\n pixelDimension,\n pixelDimension,\n ).data,\n ctx.getImageData(\n e.target.width - pixelDimension,\n e.target.height - pixelDimension,\n pixelDimension,\n pixelDimension,\n ).data,\n ].map((data) => {\n let r = 0;\n let g = 0;\n let b = 0;\n let a = 0;\n for (let i = 0; i < data.length; i += 4) {\n r += data[i];\n g += data[i + 1];\n b += data[i + 2];\n a += data[i + 3];\n }\n const dataLength = data.length / 4;\n return [\n r / dataLength,\n g / dataLength,\n b / dataLength,\n a / dataLength,\n ];\n });\n const rgbColors = colors.map((color) => {\n const [r, g, b, a] = lightenRGB(color);\n return `rgba(${r}, ${g}, ${b}, ${a})`;\n });\n setHeaderCornerColors(rgbColors);\n console.log({ colors, rgbColors });\n } catch (e) {\n // Silently fail\n }\n }}\n />\n )}\n
\n \n
\n {!!memorial && In Memoriam }\n {!!bot && (\n \n Automated\n \n )}\n {!!group && (\n \n Group\n \n )}\n {roles?.map((role) => (\n \n {role.name}\n {!!accountInstance && (\n <>\n {' '}\n {accountInstance} \n >\n )}\n \n ))}\n
\n \n {!!postingStats && (\n {\n // states.showAccount = false;\n // }}\n >\n \n
\n {hasPostingStats ? (\n
\n
\n {postingStats.daysSinceLastPost < 365\n ? `Last ${postingStats.total} post${\n postingStats.total > 1 ? 's' : ''\n } in the past \n ${postingStats.daysSinceLastPost} day${\n postingStats.daysSinceLastPost > 1 ? 's' : ''\n }`\n : `\n Last ${postingStats.total} posts in the past year(s)\n `}\n
\n
\n
\n \n {' '}\n Original\n {' '}\n \n {' '}\n Replies\n {' '}\n \n {' '}\n Boosts\n \n
\n
\n ) : (\n
Post stats unavailable.
\n )}\n
\n
\n \n )}\n \n \n
\n >\n )\n )}\n
\n );\n}\n\nconst FAMILIAR_FOLLOWERS_LIMIT = 3;\n\nfunction RelatedActions({\n info,\n instance,\n authenticated,\n onRelationshipChange = () => {},\n}) {\n if (!info) return null;\n const {\n masto: currentMasto,\n instance: currentInstance,\n authenticated: currentAuthenticated,\n } = api();\n const sameInstance = instance === currentInstance;\n\n const [relationshipUIState, setRelationshipUIState] = useState('default');\n const [relationship, setRelationship] = useState(null);\n\n const { id, acct, url, username, locked, lastStatusAt, note, fields, moved } =\n info;\n const accountID = useRef(id);\n\n const {\n following,\n showingReblogs,\n notifying,\n followedBy,\n blocking,\n blockedBy,\n muting,\n mutingNotifications,\n requested,\n domainBlocking,\n endorsed,\n note: privateNote,\n } = relationship || {};\n\n const [currentInfo, setCurrentInfo] = useState(null);\n const [isSelf, setIsSelf] = useState(false);\n\n useEffect(() => {\n if (info) {\n const currentAccount = store.session.get('currentAccount');\n let currentID;\n (async () => {\n if (sameInstance && authenticated) {\n currentID = id;\n } else if (!sameInstance && currentAuthenticated) {\n // Grab this account from my logged-in instance\n const acctHasInstance = info.acct.includes('@');\n try {\n const results = await currentMasto.v2.search.fetch({\n q: acctHasInstance ? info.acct : `${info.username}@${instance}`,\n type: 'accounts',\n limit: 1,\n resolve: true,\n });\n console.log('🥏 Fetched account from logged-in instance', results);\n if (results.accounts.length) {\n currentID = results.accounts[0].id;\n setCurrentInfo(results.accounts[0]);\n }\n } catch (e) {\n console.error(e);\n }\n }\n\n if (!currentID) return;\n\n if (currentAccount === currentID) {\n // It's myself!\n setIsSelf(true);\n return;\n }\n\n accountID.current = currentID;\n\n if (moved) return;\n\n setRelationshipUIState('loading');\n\n const fetchRelationships = currentMasto.v1.accounts.relationships.fetch(\n {\n id: [currentID],\n },\n );\n\n try {\n const relationships = await fetchRelationships;\n console.log('fetched relationship', relationships);\n setRelationshipUIState('default');\n\n if (relationships.length) {\n const relationship = relationships[0];\n setRelationship(relationship);\n onRelationshipChange({ relationship, currentID });\n }\n } catch (e) {\n console.error(e);\n setRelationshipUIState('error');\n }\n })();\n }\n }, [info, authenticated]);\n\n useEffect(() => {\n if (info && isSelf) {\n updateAccount(info);\n }\n }, [info, isSelf]);\n\n const loading = relationshipUIState === 'loading';\n\n const [showTranslatedBio, setShowTranslatedBio] = useState(false);\n const [showAddRemoveLists, setShowAddRemoveLists] = useState(false);\n const [showPrivateNoteModal, setShowPrivateNoteModal] = useState(false);\n\n return (\n <>\n \n \n {followedBy ? (\n Follows you \n ) : !!lastStatusAt ? (\n \n Last post:{' '}\n \n {niceDateTime(lastStatusAt, {\n hideTime: true,\n })}\n \n \n ) : (\n \n )}\n {muting && Muted }\n {blocking && Blocked }\n {' '}\n \n {!!privateNote && (\n {\n setShowPrivateNoteModal(true);\n }}\n dir=\"auto\"\n >\n {privateNote} \n \n )}\n \n \n \n }\n >\n {currentAuthenticated && !isSelf && (\n <>\n {\n states.showCompose = {\n draftStatus: {\n status: `@${currentInfo?.acct || acct} `,\n },\n };\n }}\n >\n \n Mention @{username} \n \n {\n setShowTranslatedBio(true);\n }}\n >\n \n Translate bio \n \n {\n setShowPrivateNoteModal(true);\n }}\n >\n \n \n {privateNote ? 'Edit private note' : 'Add private note'}\n \n \n {/* Add/remove from lists is only possible if following the account */}\n {following && (\n {\n setShowAddRemoveLists(true);\n }}\n >\n \n Add/remove from Lists \n \n )}\n \n >\n )}\n \n \n \n \n \n {!!relationship && (\n <>\n \n {muting ? (\n {\n setRelationshipUIState('loading');\n (async () => {\n try {\n const newRelationship = await currentMasto.v1.accounts\n .$select(currentInfo?.id || id)\n .unmute();\n console.log('unmuting', newRelationship);\n setRelationship(newRelationship);\n setRelationshipUIState('default');\n showToast(`Unmuted @${username}`);\n states.reloadGenericAccounts.id = 'mute';\n states.reloadGenericAccounts.counter++;\n } catch (e) {\n console.error(e);\n setRelationshipUIState('error');\n }\n })();\n }}\n >\n \n Unmute @{username} \n \n ) : (\n \n \n \n \n \n \n \n >\n }\n >\n \n \n )}\n \n \n Block @{username}? \n >\n }\n menuItemClassName=\"danger\"\n onClick={() => {\n // if (!blocking && !confirm(`Block @${username}?`)) {\n // return;\n // }\n setRelationshipUIState('loading');\n (async () => {\n try {\n if (blocking) {\n const newRelationship = await currentMasto.v1.accounts\n .$select(currentInfo?.id || id)\n .unblock();\n console.log('unblocking', newRelationship);\n setRelationship(newRelationship);\n setRelationshipUIState('default');\n showToast(`Unblocked @${username}`);\n } else {\n const newRelationship = await currentMasto.v1.accounts\n .$select(currentInfo?.id || id)\n .block();\n console.log('blocking', newRelationship);\n setRelationship(newRelationship);\n setRelationshipUIState('default');\n showToast(`Blocked @${username}`);\n }\n states.reloadGenericAccounts.id = 'block';\n states.reloadGenericAccounts.counter++;\n } catch (e) {\n console.error(e);\n setRelationshipUIState('error');\n if (blocking) {\n showToast(`Unable to unblock @${username}`);\n } else {\n showToast(`Unable to block @${username}`);\n }\n }\n })();\n }}\n >\n {blocking ? (\n <>\n \n Unblock @{username} \n >\n ) : (\n <>\n \n Block @{username}… \n >\n )}\n \n {/* \n \n Report @{username}… \n */}\n >\n )}\n \n {!relationship && relationshipUIState === 'loading' && (\n \n )}\n {!!relationship && (\n \n {requested\n ? 'Withdraw follow request?'\n : `Unfollow @${info.acct || info.username}?`}\n \n }\n menuItemClassName=\"danger\"\n align=\"end\"\n disabled={loading}\n onClick={() => {\n setRelationshipUIState('loading');\n (async () => {\n try {\n let newRelationship;\n\n if (following || requested) {\n // const yes = confirm(\n // requested\n // ? 'Withdraw follow request?'\n // : `Unfollow @${info.acct || info.username}?`,\n // );\n\n // if (yes) {\n newRelationship = await currentMasto.v1.accounts\n .$select(accountID.current)\n .unfollow();\n // }\n } else {\n newRelationship = await currentMasto.v1.accounts\n .$select(accountID.current)\n .follow();\n }\n\n if (newRelationship) setRelationship(newRelationship);\n setRelationshipUIState('default');\n } catch (e) {\n alert(e);\n setRelationshipUIState('error');\n }\n })();\n }}\n >\n \n {following ? (\n <>\n Following \n Unfollow… \n >\n ) : requested ? (\n <>\n Requested \n Withdraw… \n >\n ) : locked ? (\n <>\n Follow \n >\n ) : (\n 'Follow'\n )}\n \n \n )}\n \n
\n {!!showTranslatedBio && (\n {\n setShowTranslatedBio(false);\n }}\n >\n setShowTranslatedBio(false)}\n />\n \n )}\n {!!showAddRemoveLists && (\n {\n setShowAddRemoveLists(false);\n }}\n >\n setShowAddRemoveLists(false)}\n />\n \n )}\n {!!showPrivateNoteModal && (\n {\n setShowPrivateNoteModal(false);\n }}\n >\n {\n setRelationship(relationship);\n // onRelationshipChange({ relationship, currentID: accountID.current });\n }}\n onClose={() => setShowPrivateNoteModal(false)}\n />\n \n )}\n >\n );\n}\n\n// Apply more alpha if high luminence\nfunction lightenRGB([r, g, b]) {\n const luminence = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n console.log('luminence', luminence);\n let alpha;\n if (luminence >= 220) {\n alpha = 1;\n } else if (luminence <= 50) {\n alpha = 0.1;\n } else {\n alpha = luminence / 255;\n }\n alpha = Math.min(1, alpha);\n return [r, g, b, alpha];\n}\n\nfunction niceAccountURL(url) {\n if (!url) return;\n const urlObj = new URL(url);\n const { host, pathname } = urlObj;\n const path = pathname.replace(/\\/$/, '').replace(/^\\//, '');\n return (\n <>\n {host}/ \n \n {path} \n >\n );\n}\n\nfunction TranslatedBioSheet({ note, fields, onClose }) {\n const fieldsText =\n fields\n ?.map(({ name, value }) => `${name}\\n${getHTMLText(value)}`)\n .join('\\n\\n') || '';\n\n const text = getHTMLText(note) + (fieldsText ? `\\n\\n${fieldsText}` : '');\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n
\n
\n \n {text}\n
\n \n \n
\n );\n}\n\nfunction AddRemoveListsSheet({ accountID, onClose }) {\n const { masto } = api();\n const [uiState, setUIState] = useState('default');\n const [lists, setLists] = useState([]);\n const [listsContainingAccount, setListsContainingAccount] = useState([]);\n const [reloadCount, reload] = useReducer((c) => c + 1, 0);\n\n useEffect(() => {\n setUIState('loading');\n (async () => {\n try {\n const lists = await masto.v1.lists.list();\n lists.sort((a, b) => a.title.localeCompare(b.title));\n const listsContainingAccount = await masto.v1.accounts\n .$select(accountID)\n .lists.list();\n console.log({ lists, listsContainingAccount });\n setLists(lists);\n setListsContainingAccount(listsContainingAccount);\n setUIState('default');\n } catch (e) {\n console.error(e);\n setUIState('error');\n }\n })();\n }, [reloadCount]);\n\n const [showListAddEditModal, setShowListAddEditModal] = useState(false);\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n
\n Add/Remove from Lists \n \n
\n {lists.length > 0 ? (\n \n {lists.map((list) => {\n const inList = listsContainingAccount.some(\n (l) => l.id === list.id,\n );\n return (\n \n {\n setUIState('loading');\n (async () => {\n try {\n if (inList) {\n await masto.v1.lists\n .$select(list.id)\n .accounts.remove({\n accountIds: [accountID],\n });\n } else {\n await masto.v1.lists\n .$select(list.id)\n .accounts.create({\n accountIds: [accountID],\n });\n }\n // setUIState('default');\n reload();\n } catch (e) {\n console.error(e);\n setUIState('error');\n alert(\n inList\n ? 'Unable to remove from list.'\n : 'Unable to add to list.',\n );\n }\n })();\n }}\n >\n \n {list.title} \n \n \n );\n })}\n \n ) : uiState === 'loading' ? (\n \n \n
\n ) : uiState === 'error' ? (\n Unable to load lists.
\n ) : (\n No lists.
\n )}\n setShowListAddEditModal(true)}\n disabled={uiState !== 'default'}\n >\n New list \n \n \n {showListAddEditModal && (\n
{\n if (e.target === e.currentTarget) {\n setShowListAddEditModal(false);\n }\n }}\n >\n {\n if (result.state === 'success') {\n reload();\n }\n setShowListAddEditModal(false);\n }}\n />\n \n )}\n
\n );\n}\n\nfunction PrivateNoteSheet({\n account,\n note: initialNote,\n onRelationshipChange = () => {},\n onClose = () => {},\n}) {\n const { masto } = api();\n const [uiState, setUIState] = useState('default');\n const textareaRef = useRef(null);\n\n useEffect(() => {\n let timer;\n if (textareaRef.current && !initialNote) {\n timer = setTimeout(() => {\n textareaRef.current.focus?.();\n }, 100);\n }\n return () => {\n clearTimeout(timer);\n };\n }, []);\n\n return (\n \n {!!onClose && (\n \n \n \n )}\n \n Private note about @{account?.username || account?.acct} \n \n \n \n \n
\n );\n}\n\nexport default AccountInfo;\n","import { useEffect } from 'preact/hooks';\n\nimport { api } from '../utils/api';\nimport states from '../utils/states';\nimport useLocationChange from '../utils/useLocationChange';\n\nimport AccountInfo from './account-info';\nimport Icon from './icon';\n\nfunction AccountSheet({ account, instance: propInstance, onClose }) {\n const { masto, instance, authenticated } = api({ instance: propInstance });\n const isString = typeof account === 'string';\n\n useEffect(() => {\n if (!isString) {\n states.accounts[`${account.id}@${instance}`] = account;\n }\n }, [account]);\n\n useLocationChange(onClose);\n\n return (\n {\n // const accountBlock = e.target.closest('.account-block');\n // if (accountBlock) {\n // onClose({\n // destination: 'account-statuses',\n // });\n // }\n // }}\n >\n {!!onClose && (\n
\n \n \n )}\n
{\n if (isString) {\n try {\n const info = await masto.v1.accounts.lookup({\n acct: account,\n skip_webfinger: false,\n });\n return info;\n } catch (e) {\n const result = await masto.v2.search.fetch({\n q: account,\n type: 'accounts',\n limit: 1,\n resolve: authenticated,\n });\n if (result.accounts.length) {\n return result.accounts[0];\n } else if (/https?:\\/\\/[^/]+\\/@/.test(account)) {\n const accountURL = new URL(account);\n const acct = accountURL.pathname.replace(/^\\//, '');\n const result = await masto.v2.search.fetch({\n q: acct,\n type: 'accounts',\n limit: 1,\n resolve: authenticated,\n });\n if (result.accounts.length) {\n return result.accounts[0];\n }\n }\n }\n } else {\n return account;\n }\n }}\n />\n \n );\n}\n\nexport default AccountSheet;\n","import './drafts.css';\n\nimport { useEffect, useMemo, useReducer, useState } from 'react';\n\nimport { api } from '../utils/api';\nimport db from '../utils/db';\nimport niceDateTime from '../utils/nice-date-time';\nimport states from '../utils/states';\nimport { getCurrentAccountNS } from '../utils/store-utils';\n\nimport Icon from './icon';\nimport Loader from './loader';\nimport MenuConfirm from './menu-confirm';\n\nfunction Drafts({ onClose }) {\n const { masto } = api();\n const [uiState, setUIState] = useState('default');\n const [drafts, setDrafts] = useState([]);\n const [reloadCount, reload] = useReducer((c) => c + 1, 0);\n\n useEffect(() => {\n setUIState('loading');\n (async () => {\n try {\n const keys = await db.drafts.keys();\n if (keys.length) {\n const ns = getCurrentAccountNS();\n const ownKeys = keys.filter((key) => key.startsWith(ns));\n if (ownKeys.length) {\n const drafts = await db.drafts.getMany(ownKeys);\n drafts.sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() -\n new Date(a.updatedAt).getTime(),\n );\n setDrafts(drafts);\n } else {\n setDrafts([]);\n }\n } else {\n setDrafts([]);\n }\n setUIState('default');\n } catch (e) {\n console.error(e);\n setUIState('error');\n }\n })();\n }, [reloadCount]);\n\n const hasDrafts = drafts?.length > 0;\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n
\n
\n {hasDrafts ? (\n <>\n \n {drafts.length > 1 && (\n \n Delete all drafts?}\n menuItemClassName=\"danger\"\n disabled={uiState === 'loading'}\n onClick={() => {\n (async () => {\n // const yes = confirm('Delete all drafts?');\n // if (yes) {\n setUIState('loading');\n try {\n await db.drafts.delMany(\n drafts.map((draft) => draft.key),\n );\n setUIState('default');\n reload();\n } catch (e) {\n console.error(e);\n alert('Error deleting drafts! Please try again.');\n setUIState('error');\n }\n // }\n })();\n }}\n >\n \n Delete all…\n \n \n
\n )}\n >\n ) : (\n No drafts found.
\n )}\n \n
\n );\n}\n\nfunction MiniDraft({ draft }) {\n const { draftStatus, replyTo } = draft;\n const { status, spoilerText, poll, mediaAttachments } = draftStatus;\n const hasPoll = poll?.options?.length > 0;\n const hasMedia = mediaAttachments?.length > 0;\n const hasPollOrMedia = hasPoll || hasMedia;\n const firstImageMedia = useMemo(() => {\n if (!hasMedia) return;\n const image = mediaAttachments.find((media) => /image/.test(media.type));\n if (!image) return;\n const { file } = image;\n const objectURL = URL.createObjectURL(file);\n return objectURL;\n }, [hasMedia, mediaAttachments]);\n return (\n <>\n \n {hasPollOrMedia && (\n
\n {hasPoll && }\n {hasMedia && (\n \n {' '}\n {mediaAttachments?.length} \n \n )}\n
\n )}\n
\n {!!spoilerText &&
{spoilerText}
}\n {!!status &&
{status}
}\n
\n
\n >\n );\n}\n\nexport default Drafts;\n","import { api } from './api';\nimport store from './store';\n\nexport async function fetchRelationships(accounts, relationshipsMap = {}) {\n if (!accounts?.length) return;\n const { masto } = api();\n\n const currentAccount = store.session.get('currentAccount');\n const uniqueAccountIds = accounts.reduce((acc, a) => {\n // 1. Ignore duplicate accounts\n // 2. Ignore accounts that are already inside relationshipsMap\n // 3. Ignore currently logged in account\n if (\n !acc.includes(a.id) &&\n !relationshipsMap[a.id] &&\n a.id !== currentAccount\n ) {\n acc.push(a.id);\n }\n return acc;\n }, []);\n if (!uniqueAccountIds.length) return null;\n\n try {\n const relationships = await masto.v1.accounts.relationships.fetch({\n id: uniqueAccountIds,\n });\n const newRelationshipsMap = relationships.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {});\n return newRelationshipsMap;\n } catch (e) {\n console.error(e);\n // It's okay to fail\n return null;\n }\n}\n","import './generic-accounts.css';\n\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { InView } from 'react-intersection-observer';\nimport { useSnapshot } from 'valtio';\n\nimport { api } from '../utils/api';\nimport { fetchRelationships } from '../utils/relationships';\nimport states from '../utils/states';\nimport useLocationChange from '../utils/useLocationChange';\n\nimport AccountBlock from './account-block';\nimport Icon from './icon';\nimport Loader from './loader';\n\nexport default function GenericAccounts({\n instance,\n excludeRelationshipAttrs = [],\n onClose = () => {},\n}) {\n const { masto, instance: currentInstance } = api();\n const isCurrentInstance = instance ? instance === currentInstance : true;\n const snapStates = useSnapshot(states);\n ``;\n const [uiState, setUIState] = useState('default');\n const [accounts, setAccounts] = useState([]);\n const [showMore, setShowMore] = useState(false);\n\n useLocationChange(onClose);\n\n if (!snapStates.showGenericAccounts) {\n return null;\n }\n\n const {\n id,\n heading,\n fetchAccounts,\n accounts: staticAccounts,\n showReactions,\n } = snapStates.showGenericAccounts;\n\n const [relationshipsMap, setRelationshipsMap] = useState({});\n\n const loadRelationships = async (accounts) => {\n if (!accounts?.length) return;\n if (!isCurrentInstance) return;\n const relationships = await fetchRelationships(accounts, relationshipsMap);\n if (relationships) {\n setRelationshipsMap({\n ...relationshipsMap,\n ...relationships,\n });\n }\n };\n\n const loadAccounts = (firstLoad) => {\n if (!fetchAccounts) return;\n if (firstLoad) setAccounts([]);\n setUIState('loading');\n (async () => {\n try {\n const { done, value } = await fetchAccounts(firstLoad);\n if (Array.isArray(value)) {\n if (firstLoad) {\n const accounts = [];\n for (let i = 0; i < value.length; i++) {\n const account = value[i];\n const theAccount = accounts.find(\n (a, j) => a.id === account.id && i !== j,\n );\n if (!theAccount) {\n accounts.push({\n _types: [],\n ...account,\n });\n } else {\n theAccount._types.push(...account._types);\n }\n }\n setAccounts(accounts);\n } else {\n // setAccounts((prev) => [...prev, ...value]);\n // Merge accounts by id and _types\n setAccounts((prev) => {\n const newAccounts = prev;\n for (const account of value) {\n const theAccount = newAccounts.find((a) => a.id === account.id);\n if (!theAccount) {\n newAccounts.push(account);\n } else {\n theAccount._types.push(...account._types);\n }\n }\n return newAccounts;\n });\n }\n setShowMore(!done);\n\n loadRelationships(value);\n } else {\n setShowMore(false);\n }\n setUIState('default');\n } catch (e) {\n console.error(e);\n setUIState('error');\n }\n })();\n };\n\n const firstLoad = useRef(true);\n useEffect(() => {\n if (staticAccounts?.length > 0) {\n setAccounts(staticAccounts);\n loadRelationships(staticAccounts);\n } else {\n loadAccounts(true);\n firstLoad.current = false;\n }\n }, [staticAccounts, fetchAccounts]);\n\n useEffect(() => {\n if (firstLoad.current) return;\n // reloadGenericAccounts contains value like {id: 'mute', counter: 1}\n // We only need to reload if the id matches\n if (snapStates.reloadGenericAccounts?.id === id) {\n loadAccounts(true);\n }\n }, [snapStates.reloadGenericAccounts.counter]);\n\n return (\n \n
\n \n \n
\n {heading || 'Accounts'} \n \n
\n {accounts.length > 0 ? (\n <>\n \n {uiState === 'default' ? (\n showMore ? (\n {\n if (inView) {\n loadAccounts();\n }\n }}\n >\n loadAccounts()}\n >\n Show more…\n \n \n ) : (\n The end.
\n )\n ) : (\n uiState === 'loading' && (\n \n \n
\n )\n )}\n >\n ) : uiState === 'loading' ? (\n \n \n
\n ) : uiState === 'error' ? (\n Error loading accounts
\n ) : (\n Nothing to show
\n )}\n \n
\n );\n}\n","import { Menu, MenuItem } from '@szhsin/react-menu';\nimport { useState } from 'preact/hooks';\nimport { useSnapshot } from 'valtio';\n\nimport getTranslateTargetLanguage from '../utils/get-translate-target-language';\nimport localeMatch from '../utils/locale-match';\nimport { speak, supportsTTS } from '../utils/speech';\nimport states from '../utils/states';\n\nimport Icon from './icon';\nimport Menu2 from './menu2';\nimport TranslationBlock from './translation-block';\n\nexport default function MediaAltModal({ alt, lang, onClose }) {\n const snapStates = useSnapshot(states);\n const [forceTranslate, setForceTranslate] = useState(false);\n const targetLanguage = getTranslateTargetLanguage(true);\n const contentTranslationHideLanguages =\n snapStates.settings.contentTranslationHideLanguages || [];\n const differentLanguage =\n !!lang &&\n lang !== targetLanguage &&\n !localeMatch([lang], [targetLanguage]) &&\n !contentTranslationHideLanguages.find(\n (l) => lang === l || localeMatch([lang], [l]),\n );\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n \n
\n \n {alt}\n
\n {(differentLanguage || forceTranslate) && (\n \n )}\n \n
\n );\n}\n","// https://gist.github.com/earthbound19/e7fe15fdf8ca3ef814750a61bc75b5ce\nfunction clamp(value, min, max) {\n return Math.max(Math.min(value, max), min);\n}\n\nconst gammaToLinear = (c) =>\n c >= 0.04045 ? Math.pow((c + 0.055) / 1.055, 2.4) : c / 12.92;\nconst linearToGamma = (c) =>\n c >= 0.0031308 ? 1.055 * Math.pow(c, 1 / 2.4) - 0.055 : 12.92 * c;\n\nexport function rgb2oklab([r, g, b]) {\n r = gammaToLinear(r / 255);\n g = gammaToLinear(g / 255);\n b = gammaToLinear(b / 255);\n var l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;\n var m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;\n var s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;\n l = Math.cbrt(l);\n m = Math.cbrt(m);\n s = Math.cbrt(s);\n return [\n l * +0.2104542553 + m * +0.793617785 + s * -0.0040720468,\n l * +1.9779984951 + m * -2.428592205 + s * +0.4505937099,\n l * +0.0259040371 + m * +0.7827717662 + s * -0.808675766,\n ];\n}\n\nexport function oklab2rgb([L, a, b]) {\n var l = L + a * +0.3963377774 + b * +0.2158037573;\n var m = L + a * -0.1055613458 + b * -0.0638541728;\n var s = L + a * -0.0894841775 + b * -1.291485548;\n // The ** operator here cubes; same as l_*l_*l_ in the C++ example:\n l = l ** 3;\n m = m ** 3;\n s = s ** 3;\n var r = l * +4.0767416621 + m * -3.3077115913 + s * +0.2309699292;\n var g = l * -1.2684380046 + m * +2.6097574011 + s * -0.3413193965;\n var b = l * -0.0041960863 + m * -0.7034186147 + s * +1.707614701;\n // Convert linear RGB values returned from oklab math to sRGB for our use before returning them:\n r = 255 * linearToGamma(r);\n g = 255 * linearToGamma(g);\n b = 255 * linearToGamma(b);\n // OPTION: clamp r g and b values to the range 0-255; but if you use the values immediately to draw, JavaScript clamps them on use:\n r = clamp(r, 0, 255);\n g = clamp(g, 0, 255);\n b = clamp(b, 0, 255);\n // OPTION: round the values. May not be necessary if you use them immediately for rendering in JavaScript, as JavaScript (also) discards decimals on render:\n r = Math.round(r);\n g = Math.round(g);\n b = Math.round(b);\n return [r, g, b];\n}\n","import { MenuDivider, MenuItem } from '@szhsin/react-menu';\nimport { getBlurHashAverageColor } from 'fast-blurhash';\nimport {\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\n\nimport { oklab2rgb, rgb2oklab } from '../utils/color-utils';\nimport showToast from '../utils/show-toast';\nimport states from '../utils/states';\n\nimport Icon from './icon';\nimport Link from './link';\nimport Media from './media';\nimport Menu2 from './menu2';\nimport MenuLink from './menu-link';\n\nconst { PHANPY_IMG_ALT_API_URL: IMG_ALT_API_URL } = import.meta.env;\n\nfunction MediaModal({\n mediaAttachments,\n statusID,\n instance,\n lang,\n index = 0,\n onClose = () => {},\n}) {\n const [uiState, setUIState] = useState('default');\n const carouselRef = useRef(null);\n\n const [currentIndex, setCurrentIndex] = useState(index);\n const carouselFocusItem = useRef(null);\n useLayoutEffect(() => {\n carouselFocusItem.current?.scrollIntoView();\n\n // history.pushState({ mediaModal: true }, '');\n // const handlePopState = (e) => {\n // if (e.state?.mediaModal) {\n // onClose();\n // }\n // };\n // window.addEventListener('popstate', handlePopState);\n // return () => {\n // window.removeEventListener('popstate', handlePopState);\n // };\n }, []);\n const prevStatusID = useRef(statusID);\n useEffect(() => {\n const scrollLeft = index * carouselRef.current.clientWidth;\n const differentStatusID = prevStatusID.current !== statusID;\n if (differentStatusID) prevStatusID.current = statusID;\n carouselRef.current.scrollTo({\n left: scrollLeft,\n behavior: differentStatusID ? 'auto' : 'smooth',\n });\n carouselRef.current.focus();\n }, [index, statusID]);\n\n const [showControls, setShowControls] = useState(true);\n\n useEffect(() => {\n let handleSwipe = () => {\n onClose();\n };\n if (carouselRef.current) {\n carouselRef.current.addEventListener('swiped-down', handleSwipe);\n }\n return () => {\n if (carouselRef.current) {\n carouselRef.current.removeEventListener('swiped-down', handleSwipe);\n }\n };\n }, []);\n\n useHotkeys(\n 'esc',\n onClose,\n {\n ignoreEventWhen: (e) => {\n const hasModal = !!document.querySelector('#modal-container > *');\n return hasModal;\n },\n },\n [onClose],\n );\n\n useEffect(() => {\n let handleScroll = () => {\n const { clientWidth, scrollLeft } = carouselRef.current;\n const index = Math.round(scrollLeft / clientWidth);\n setCurrentIndex(index);\n };\n if (carouselRef.current) {\n carouselRef.current.addEventListener('scroll', handleScroll, {\n passive: true,\n });\n }\n return () => {\n if (carouselRef.current) {\n carouselRef.current.removeEventListener('scroll', handleScroll);\n }\n };\n }, []);\n\n useEffect(() => {\n let timer = setTimeout(() => {\n carouselRef.current?.focus?.();\n }, 100);\n return () => clearTimeout(timer);\n }, []);\n\n const mediaAccentColors = useMemo(() => {\n return mediaAttachments?.map((media) => {\n const { blurhash } = media;\n if (blurhash) {\n const averageColor = getBlurHashAverageColor(blurhash);\n const labAverageColor = rgb2oklab(averageColor);\n return oklab2rgb([0.6, labAverageColor[1], labAverageColor[2]]);\n }\n return null;\n });\n }, [mediaAttachments]);\n const mediaAccentGradient = useMemo(() => {\n const gap = 5;\n const range = 100 / mediaAccentColors.length;\n return (\n mediaAccentColors\n ?.map((color, i) => {\n const start = i * range + gap;\n const end = (i + 1) * range - gap;\n if (color) {\n return `\n rgba(${color?.join(',')}, 0.4) ${start}%,\n rgba(${color?.join(',')}, 0.4) ${end}%\n `;\n }\n\n return `\n transparent ${start}%,\n transparent ${end}%\n `;\n })\n ?.join(', ') || 'transparent'\n );\n }, [mediaAccentColors]);\n\n let toastRef = useRef(null);\n useEffect(() => {\n return () => {\n toastRef.current?.hideToast?.();\n };\n }, []);\n\n return (\n \n );\n}\n\nexport default MediaModal;\n","export default \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20fill='none'%20viewBox='0%200%2084%2062'%3e%3crect%20width='64'%20height='48'%20x='18'%20y='2'%20fill='%23fff'%20stroke='%23999'%20stroke-width='3'%20rx='4'/%3e%3crect%20width='32'%20height='48'%20x='2'%20y='12'%20fill='%23fff'%20stroke='%23999'%20stroke-width='3'%20rx='4'/%3e%3cpath%20fill='%234169E1'%20d='M14%2052a4%204%200%201%201-8%200%204%204%200%200%201%208%200Zm64-42a4%204%200%201%201-8%200%204%204%200%200%201%208%200Z'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20fill='none'%20viewBox='0%200%2082%2062'%3e%3crect%20width='78'%20height='58'%20x='2'%20y='2'%20fill='%23999'%20fill-opacity='.3'%20stroke='%23999'%20stroke-width='3'%20rx='4'/%3e%3crect%20width='18'%20height='46'%20x='8'%20y='8'%20fill='%23fff'%20stroke='%23999'%20stroke-width='2'%20rx='1'/%3e%3crect%20width='18'%20height='46'%20x='32'%20y='8'%20fill='%23fff'%20stroke='%23999'%20stroke-width='2'%20rx='1'/%3e%3crect%20width='18'%20height='46'%20x='56'%20y='8'%20fill='%23fff'%20stroke='%23999'%20stroke-width='2'%20rx='1'/%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20fill='none'%20viewBox='0%200%2084%2062'%3e%3crect%20width='64'%20height='48'%20x='18'%20y='2'%20fill='%23fff'%20stroke='%23999'%20stroke-width='3'%20rx='4'/%3e%3cpath%20fill='%23999'%20fill-opacity='.3'%20d='M19%203h62v10H19z'/%3e%3cpath%20stroke='%234169E1'%20stroke-width='2'%20d='M43%208a2%202%200%201%201-4%200%202%202%200%200%201%204%200Z'/%3e%3cpath%20stroke='%23999'%20stroke-width='2'%20d='M52%208a2%202%200%201%201-4%200%202%202%200%200%201%204%200Zm9%200a2%202%200%201%201-4%200%202%202%200%200%201%204%200Z'/%3e%3crect%20width='32'%20height='48'%20x='2'%20y='12'%20fill='%23fff'%20stroke='%23999'%20stroke-width='3'%20rx='4'/%3e%3cpath%20fill='%23999'%20fill-opacity='.3'%20d='M3%2049h30v10H3z'/%3e%3cpath%20stroke='%234169E1'%20stroke-width='2'%20d='M11%2054a2%202%200%201%201-4%200%202%202%200%200%201%204%200Z'/%3e%3cpath%20stroke='%23999'%20stroke-width='2'%20d='M20%2054a2%202%200%201%201-4%200%202%202%200%200%201%204%200Zm9%200a2%202%200%201%201-4%200%202%202%200%200%201%204%200Z'/%3e%3c/svg%3e\"","import { api } from '../utils/api';\nimport store from '../utils/store';\n\nconst LIMIT = 200;\nconst MAX_FETCH = 10;\n\nexport async function fetchFollowedTags() {\n const { masto } = api();\n const iterator = masto.v1.followedTags.list({\n limit: LIMIT,\n });\n const tags = [];\n let fetchCount = 0;\n do {\n const { value, done } = await iterator.next();\n if (done || value?.length === 0) break;\n tags.push(...value);\n fetchCount++;\n } while (fetchCount < MAX_FETCH);\n tags.sort((a, b) => a.name.localeCompare(b.name));\n console.log(tags);\n\n if (tags.length) {\n setTimeout(() => {\n // Save to local storage, with saved timestamp\n store.account.set('followedTags', {\n tags,\n updatedAt: Date.now(),\n });\n }, 1);\n }\n\n return tags;\n}\n\nconst MAX_AGE = 24 * 60 * 60 * 1000; // 1 day\nexport async function getFollowedTags() {\n try {\n const { tags, updatedAt } = store.account.get('followedTags') || {};\n if (!tags?.length) return await fetchFollowedTags();\n if (Date.now() - updatedAt > MAX_AGE) {\n // Stale-while-revalidate\n fetchFollowedTags();\n return tags;\n }\n return tags;\n } catch (e) {\n return [];\n }\n}\n\nconst fauxDiv = document.createElement('div');\nexport const extractTagsFromStatus = (content) => {\n if (!content) return [];\n if (content.indexOf('#') === -1) return [];\n fauxDiv.innerHTML = content;\n const hashtagLinks = fauxDiv.querySelectorAll('a.hashtag');\n if (!hashtagLinks.length) return [];\n return Array.from(hashtagLinks).map((a) =>\n a.innerText.trim().replace(/^[^#]*#+/, ''),\n );\n};\n","import { useEffect, useState } from 'preact/hooks';\n\nfunction AsyncText({ children }) {\n if (typeof children === 'string') return children;\n const [text, setText] = useState('');\n useEffect(() => {\n Promise.resolve(children).then(setText);\n }, [children]);\n return text;\n}\n\nexport default AsyncText;\n","import './shortcuts-settings.css';\n\nimport { useAutoAnimate } from '@formkit/auto-animate/preact';\nimport {\n compressToEncodedURIComponent,\n decompressFromEncodedURIComponent,\n} from 'lz-string';\nimport { useEffect, useMemo, useRef, useState } from 'preact/hooks';\nimport { useSnapshot } from 'valtio';\n\nimport floatingButtonUrl from '../assets/floating-button.svg';\nimport multiColumnUrl from '../assets/multi-column.svg';\nimport tabMenuBarUrl from '../assets/tab-menu-bar.svg';\n\nimport { api } from '../utils/api';\nimport { fetchFollowedTags } from '../utils/followed-tags';\nimport pmem from '../utils/pmem';\nimport showToast from '../utils/show-toast';\nimport states from '../utils/states';\n\nimport AsyncText from './AsyncText';\nimport Icon from './icon';\nimport MenuConfirm from './menu-confirm';\nimport Modal from './modal';\n\nexport const SHORTCUTS_LIMIT = 9;\n\nconst TYPES = [\n 'following',\n 'mentions',\n 'notifications',\n 'list',\n 'public',\n 'trending',\n 'search',\n 'hashtag',\n 'bookmarks',\n 'favourites',\n // NOTE: Hide for now\n // 'account-statuses', // Need @acct search first\n];\nconst TYPE_TEXT = {\n following: 'Home / Following',\n notifications: 'Notifications',\n list: 'List',\n public: 'Public (Local / Federated)',\n search: 'Search',\n 'account-statuses': 'Account',\n bookmarks: 'Bookmarks',\n favourites: 'Likes',\n hashtag: 'Hashtag',\n trending: 'Trending',\n mentions: 'Mentions',\n};\nconst TYPE_PARAMS = {\n list: [\n {\n text: 'List ID',\n name: 'id',\n },\n ],\n public: [\n {\n text: 'Local only',\n name: 'local',\n type: 'checkbox',\n },\n {\n text: 'Instance',\n name: 'instance',\n type: 'text',\n placeholder: 'Optional, e.g. mastodon.social',\n notRequired: true,\n },\n ],\n trending: [\n {\n text: 'Instance',\n name: 'instance',\n type: 'text',\n placeholder: 'Optional, e.g. mastodon.social',\n notRequired: true,\n },\n ],\n search: [\n {\n text: 'Search term',\n name: 'query',\n type: 'text',\n placeholder: 'Optional, unless for multi-column mode',\n notRequired: true,\n },\n ],\n 'account-statuses': [\n {\n text: '@',\n name: 'id',\n type: 'text',\n placeholder: 'cheeaun@mastodon.social',\n },\n ],\n hashtag: [\n {\n text: '#',\n name: 'hashtag',\n type: 'text',\n placeholder: 'e.g. PixelArt (Max 5, space-separated)',\n pattern: '[^#]+',\n },\n {\n text: 'Media only',\n name: 'media',\n type: 'checkbox',\n },\n {\n text: 'Instance',\n name: 'instance',\n type: 'text',\n placeholder: 'Optional, e.g. mastodon.social',\n notRequired: true,\n },\n ],\n};\nconst fetchListTitle = pmem(async ({ id }) => {\n const list = await api().masto.v1.lists.$select(id).fetch();\n return list.title;\n});\nconst fetchAccountTitle = pmem(async ({ id }) => {\n const account = await api().masto.v1.accounts.$select(id).fetch();\n return account.username || account.acct || account.displayName;\n});\nexport const SHORTCUTS_META = {\n following: {\n id: 'home',\n title: (_, index) => (index === 0 ? 'Home' : 'Following'),\n path: '/',\n icon: 'home',\n },\n mentions: {\n id: 'mentions',\n title: 'Mentions',\n path: '/mentions',\n icon: 'at',\n },\n notifications: {\n id: 'notifications',\n title: 'Notifications',\n path: '/notifications',\n icon: 'notification',\n },\n list: {\n id: 'list',\n title: fetchListTitle,\n path: ({ id }) => `/l/${id}`,\n icon: 'list',\n },\n public: {\n id: 'public',\n title: ({ local }) => (local ? 'Local' : 'Federated'),\n subtitle: ({ instance }) => instance || api().instance,\n path: ({ local, instance }) => `/${instance}/p${local ? '/l' : ''}`,\n icon: ({ local }) => (local ? 'building' : 'earth'),\n },\n trending: {\n id: 'trending',\n title: 'Trending',\n subtitle: ({ instance }) => instance || api().instance,\n path: ({ instance }) => `/${instance}/trending`,\n icon: 'chart',\n },\n search: {\n id: 'search',\n title: ({ query }) => (query ? `\"${query}\"` : 'Search'),\n path: ({ query }) =>\n query\n ? `/search?q=${encodeURIComponent(query)}&type=statuses`\n : '/search',\n icon: 'search',\n excludeViewMode: ({ query }) => (!query ? ['multi-column'] : []),\n },\n 'account-statuses': {\n id: 'account-statuses',\n title: fetchAccountTitle,\n path: ({ id }) => `/a/${id}`,\n icon: 'user',\n },\n bookmarks: {\n id: 'bookmarks',\n title: 'Bookmarks',\n path: '/b',\n icon: 'bookmark',\n },\n favourites: {\n id: 'favourites',\n title: 'Likes',\n path: '/f',\n icon: 'heart',\n },\n hashtag: {\n id: 'hashtag',\n title: ({ hashtag }) => hashtag,\n subtitle: ({ instance }) => instance || api().instance,\n path: ({ hashtag, instance, media }) =>\n `${instance ? `/${instance}` : ''}/t/${hashtag.split(/\\s+/).join('+')}${\n media ? '?media=1' : ''\n }`,\n icon: 'hashtag',\n },\n};\n\nfunction ShortcutsSettings({ onClose }) {\n const snapStates = useSnapshot(states);\n const { shortcuts } = snapStates;\n const [showForm, setShowForm] = useState(false);\n const [showImportExport, setShowImportExport] = useState(false);\n\n const [shortcutsListParent] = useAutoAnimate();\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n
\n \n Shortcuts{' '}\n \n beta\n \n \n \n
\n Specify a list of shortcuts that'll appear as:
\n \n {[\n {\n value: 'float-button',\n label: 'Floating button',\n imgURL: floatingButtonUrl,\n },\n {\n value: 'tab-menu-bar',\n label: 'Tab/Menu bar',\n imgURL: tabMenuBarUrl,\n },\n {\n value: 'multi-column',\n label: 'Multi-column',\n imgURL: multiColumnUrl,\n },\n ].map(({ value, label, imgURL }) => {\n const checked =\n snapStates.settings.shortcutsViewMode === value ||\n (value === 'float-button' &&\n !snapStates.settings.shortcutsViewMode);\n return (\n
\n {\n states.settings.shortcutsViewMode = e.target.value;\n }}\n />{' '}\n {' '}\n {label} \n \n );\n })}\n
\n {shortcuts.length > 0 ? (\n \n {shortcuts.filter(Boolean).map((shortcut, i) => {\n // const key = i + Object.values(shortcut);\n const key = Object.values(shortcut).join('-');\n const { type } = shortcut;\n if (!SHORTCUTS_META[type]) return null;\n let { icon, title, subtitle, excludeViewMode } =\n SHORTCUTS_META[type];\n if (typeof title === 'function') {\n title = title(shortcut, i);\n }\n if (typeof subtitle === 'function') {\n subtitle = subtitle(shortcut, i);\n }\n if (typeof icon === 'function') {\n icon = icon(shortcut, i);\n }\n if (typeof excludeViewMode === 'function') {\n excludeViewMode = excludeViewMode(shortcut, i);\n }\n const excludedViewMode = excludeViewMode?.includes(\n snapStates.settings.shortcutsViewMode,\n );\n return (\n \n \n \n {title} \n {subtitle && (\n <>\n {' '}\n {subtitle} \n >\n )}\n {excludedViewMode && (\n \n Not available in current view mode\n \n )}\n \n \n {\n const shortcutsArr = Array.from(states.shortcuts);\n if (i > 0) {\n const temp = states.shortcuts[i - 1];\n shortcutsArr[i - 1] = shortcut;\n shortcutsArr[i] = temp;\n states.shortcuts = shortcutsArr;\n }\n }}\n >\n \n \n {\n const shortcutsArr = Array.from(states.shortcuts);\n if (i < states.shortcuts.length - 1) {\n const temp = states.shortcuts[i + 1];\n shortcutsArr[i + 1] = shortcut;\n shortcutsArr[i] = temp;\n states.shortcuts = shortcutsArr;\n }\n }}\n >\n \n \n {\n setShowForm({\n shortcut,\n shortcutIndex: i,\n });\n }}\n >\n \n \n {/* {\n states.shortcuts.splice(i, 1);\n }}\n >\n \n */}\n \n \n );\n })}\n \n ) : (\n \n )}\n \n {shortcuts.length >= SHORTCUTS_LIMIT &&\n `Max ${SHORTCUTS_LIMIT} shortcuts`}\n
\n \n setShowImportExport(true)}\n >\n Import/export\n \n = SHORTCUTS_LIMIT}\n onClick={() => setShowForm(true)}\n >\n Add shortcut \n \n
\n \n {showForm && (\n
{\n if (e.target === e.currentTarget) {\n setShowForm(false);\n }\n }}\n >\n {\n console.log('onSubmit', result);\n if (mode === 'edit') {\n states.shortcuts[showForm.shortcutIndex] = result;\n } else {\n states.shortcuts.push(result);\n }\n }}\n onClose={() => setShowForm(false)}\n />\n \n )}\n {showImportExport && (\n
{\n if (e.target === e.currentTarget) {\n setShowImportExport(false);\n }\n }}\n >\n setShowImportExport(false)}\n />\n \n )}\n
\n );\n}\n\nconst FETCH_MAX_AGE = 1000 * 60; // 1 minute\nconst fetchLists = pmem(\n () => {\n const { masto } = api();\n return masto.v1.lists.list();\n },\n {\n maxAge: FETCH_MAX_AGE,\n },\n);\n\nconst FORM_NOTES = {\n search: `For multi-column mode, search term is required, else the column will not be shown.`,\n hashtag: 'Multiple hashtags are supported. Space-separated.',\n};\n\nfunction ShortcutForm({\n onSubmit,\n disabled,\n shortcut,\n shortcutIndex,\n onClose,\n}) {\n console.log('shortcut', shortcut);\n const editMode = !!shortcut;\n const [currentType, setCurrentType] = useState(shortcut?.type || null);\n const { masto } = api();\n\n const [uiState, setUIState] = useState('default');\n const [lists, setLists] = useState([]);\n const [followedHashtags, setFollowedHashtags] = useState([]);\n useEffect(() => {\n (async () => {\n if (currentType !== 'list') return;\n try {\n setUIState('loading');\n const lists = await fetchLists();\n lists.sort((a, b) => a.title.localeCompare(b.title));\n setLists(lists);\n setUIState('default');\n } catch (e) {\n console.error(e);\n setUIState('error');\n }\n })();\n\n (async () => {\n if (currentType !== 'hashtag') return;\n try {\n const tags = await fetchFollowedTags();\n setFollowedHashtags(tags);\n } catch (e) {\n console.error(e);\n }\n })();\n }, [currentType]);\n\n const formRef = useRef();\n useEffect(() => {\n if (editMode && currentType && TYPE_PARAMS[currentType]) {\n // Populate form\n const form = formRef.current;\n TYPE_PARAMS[currentType].forEach(({ name, type }) => {\n const input = form.querySelector(`[name=\"${name}\"]`);\n if (input && shortcut[name]) {\n if (type === 'checkbox') {\n input.checked = shortcut[name] === 'on' ? true : false;\n } else {\n input.value = shortcut[name];\n }\n }\n });\n }\n }, [editMode, currentType]);\n\n return (\n \n );\n}\n\nfunction ImportExport({ shortcuts, onClose }) {\n const shortcutsStr = useMemo(() => {\n if (!shortcuts) return '';\n if (!shortcuts.filter(Boolean).length) return '';\n return compressToEncodedURIComponent(\n JSON.stringify(shortcuts.filter(Boolean)),\n );\n }, [shortcuts]);\n const [importShortcutStr, setImportShortcutStr] = useState('');\n const [importUIState, setImportUIState] = useState('default');\n const parsedImportShortcutStr = useMemo(() => {\n if (!importShortcutStr) {\n setImportUIState('default');\n return null;\n }\n try {\n const parsed = JSON.parse(\n decompressFromEncodedURIComponent(importShortcutStr),\n );\n // Very basic validation, I know\n if (!Array.isArray(parsed)) throw new Error('Not an array');\n setImportUIState('default');\n return parsed;\n } catch (err) {\n // Fallback to JSON string parsing\n // There's a chance that someone might want to import a JSON string instead of the compressed version\n try {\n const parsed = JSON.parse(importShortcutStr);\n if (!Array.isArray(parsed)) throw new Error('Not an array');\n setImportUIState('default');\n return parsed;\n } catch (err) {\n setImportUIState('error');\n return null;\n }\n }\n }, [importShortcutStr]);\n const hasCurrentSettings = states.shortcuts.length > 0;\n\n return (\n \n {!!onClose && (\n
\n \n \n )}\n
\n \n Import/Export Shortcuts \n \n \n
\n \n \n {' '}\n Import \n \n \n {\n setImportShortcutStr(e.target.value);\n }}\n />\n
\n {!!parsedImportShortcutStr &&\n Array.isArray(parsedImportShortcutStr) && (\n <>\n \n {parsedImportShortcutStr.length} shortcut\n {parsedImportShortcutStr.length > 1 ? 's' : ''}{' '}\n \n ({importShortcutStr.length} characters)\n \n
\n \n {parsedImportShortcutStr.map((shortcut) => (\n \n \n // Compare all properties\n Object.keys(s).every(\n (key) => s[key] === shortcut[key],\n ),\n )\n ? 1\n : 0,\n }}\n >\n *\n \n \n {TYPE_TEXT[shortcut.type]}\n {shortcut.type === 'list' && ' ⚠️'}{' '}\n {TYPE_PARAMS[shortcut.type]?.map?.(\n ({ text, name, type }) =>\n shortcut[name] ? (\n <>\n \n {text}:{' '}\n {type === 'checkbox'\n ? shortcut[name] === 'on'\n ? '✅'\n : '❌'\n : shortcut[name]}\n {' '}\n >\n ) : null,\n )}\n \n \n ))}\n \n \n * Exists in current shortcuts \n \n \n ⚠️ List may not work if it's from a different account.\n \n
\n >\n )}\n {importUIState === 'error' && (\n \n ⚠️ Invalid settings format \n
\n )}\n \n {hasCurrentSettings && (\n <>\n
\n }\n onClick={() => {\n // states.shortcuts = [\n // ...states.shortcuts,\n // ...parsedImportShortcutStr,\n // ];\n // Append non-unique shortcuts only\n const nonUniqueShortcuts = parsedImportShortcutStr.filter(\n (shortcut) =>\n !states.shortcuts.some((s) =>\n // Compare all properties\n Object.keys(s).every(\n (key) => s[key] === shortcut[key],\n ),\n ),\n );\n if (!nonUniqueShortcuts.length) {\n showToast('No new shortcuts to import');\n return;\n }\n let newShortcuts = [\n ...states.shortcuts,\n ...nonUniqueShortcuts,\n ];\n const exceededLimit = newShortcuts.length > SHORTCUTS_LIMIT;\n if (exceededLimit) {\n // If exceeded, trim it\n newShortcuts = newShortcuts.slice(0, SHORTCUTS_LIMIT);\n }\n states.shortcuts = newShortcuts;\n showToast(\n exceededLimit\n ? `Shortcuts imported. Exceeded max ${SHORTCUTS_LIMIT}, so the rest are not imported.`\n : 'Shortcuts imported',\n );\n onClose?.();\n }}\n >\n \n Import & append…\n \n {' '}\n >\n )}\n {\n states.shortcuts = parsedImportShortcutStr;\n showToast('Shortcuts imported');\n onClose?.();\n }}\n >\n \n {hasCurrentSettings ? 'or override…' : 'Import…'}\n \n \n
\n \n \n \n \n );\n}\n\nexport default ShortcutsSettings;\n","import { useLocation, useNavigate } from 'react-router-dom';\nimport { subscribe, useSnapshot } from 'valtio';\n\nimport Accounts from '../pages/accounts';\nimport Settings from '../pages/settings';\nimport focusDeck from '../utils/focus-deck';\nimport showToast from '../utils/show-toast';\nimport states from '../utils/states';\n\nimport AccountSheet from './account-sheet';\nimport Compose from './compose';\nimport Drafts from './drafts';\nimport GenericAccounts from './generic-accounts';\nimport MediaAltModal from './media-alt-modal';\nimport MediaModal from './media-modal';\nimport Modal from './modal';\nimport ShortcutsSettings from './shortcuts-settings';\n\nsubscribe(states, (changes) => {\n for (const [action, path, value, prevValue] of changes) {\n // When closing modal, focus on deck\n if (/^show/i.test(path) && !value) {\n focusDeck();\n }\n }\n});\n\nexport default function Modals() {\n const snapStates = useSnapshot(states);\n const navigate = useNavigate();\n const location = useLocation();\n\n return (\n <>\n {!!snapStates.showCompose && (\n \n {\n const { newStatus, instance, type } = results || {};\n states.showCompose = false;\n window.__COMPOSE__ = null;\n if (newStatus) {\n states.reloadStatusPage++;\n showToast({\n text: {\n post: 'Post published. Check it out.',\n reply: 'Reply posted. Check it out.',\n edit: 'Post updated. Check it out.',\n }[type || 'post'],\n delay: 1000,\n duration: 10_000, // 10 seconds\n onClick: (toast) => {\n toast.hideToast();\n states.prevLocation = location;\n navigate(\n instance\n ? `/${instance}/s/${newStatus.id}`\n : `/s/${newStatus.id}`,\n );\n },\n });\n }\n }}\n />\n \n )}\n {!!snapStates.showSettings && (\n {\n states.showSettings = false;\n }}\n >\n {\n states.showSettings = false;\n }}\n />\n \n )}\n {!!snapStates.showAccounts && (\n {\n states.showAccounts = false;\n }}\n >\n {\n states.showAccounts = false;\n }}\n />\n \n )}\n {!!snapStates.showAccount && (\n {\n states.showAccount = false;\n }}\n >\n {\n states.showAccount = false;\n // states.showGenericAccounts = false;\n // if (destination) {\n // states.showAccounts = false;\n // }\n }}\n />\n \n )}\n {!!snapStates.showDrafts && (\n {\n states.showDrafts = false;\n }}\n >\n (states.showDrafts = false)} />\n \n )}\n {!!snapStates.showMediaModal && (\n {\n if (\n e.target === e.currentTarget ||\n e.target.classList.contains('media')\n ) {\n states.showMediaModal = false;\n }\n }}\n >\n {\n states.showMediaModal = false;\n }}\n />\n \n )}\n {!!snapStates.showShortcutsSettings && (\n {\n states.showShortcutsSettings = false;\n }}\n >\n (states.showShortcutsSettings = false)}\n />\n \n )}\n {!!snapStates.showGenericAccounts && (\n {\n states.showGenericAccounts = false;\n }}\n >\n (states.showGenericAccounts = false)}\n />\n \n )}\n {!!snapStates.showMediaAlt && (\n {\n states.showMediaAlt = false;\n }}\n >\n {\n states.showMediaAlt = false;\n }}\n />\n \n )}\n >\n );\n}\n","import { useState } from 'preact/hooks';\n\nimport { api } from '../utils/api';\n\nimport Icon from './icon';\nimport Loader from './loader';\n\nfunction FollowRequestButtons({ accountID, onChange }) {\n const { masto } = api();\n const [uiState, setUIState] = useState('default');\n const [requestState, setRequestState] = useState(null); // accept, reject\n const [relationship, setRelationship] = useState(null);\n\n const hasRelationship = relationship !== null;\n\n return (\n \n {\n setUIState('loading');\n setRequestState('accept');\n (async () => {\n try {\n const rel = await masto.v1.followRequests\n .$select(accountID)\n .authorize();\n if (!rel?.followedBy) {\n throw new Error('Follow request not accepted');\n }\n setRelationship(rel);\n onChange();\n } catch (e) {\n console.error(e);\n }\n setUIState('default');\n })();\n }}\n >\n Accept\n {' '}\n {\n setUIState('loading');\n setRequestState('reject');\n (async () => {\n try {\n const rel = await masto.v1.followRequests\n .$select(accountID)\n .reject();\n if (rel?.followedBy) {\n throw new Error('Follow request not rejected');\n }\n setRelationship(rel);\n onChange();\n } catch (e) {\n console.error(e);\n setUIState('default');\n }\n })();\n }}\n >\n Reject\n \n \n {hasRelationship && requestState ? (\n requestState === 'accept' ? (\n \n ) : (\n \n )\n ) : (\n \n )}\n \n
\n );\n}\n\nexport default FollowRequestButtons;\n","import { Fragment } from 'preact';\nimport { memo } from 'preact/compat';\n\nimport shortenNumber from '../utils/shorten-number';\nimport states from '../utils/states';\nimport store from '../utils/store';\nimport useTruncated from '../utils/useTruncated';\n\nimport Avatar from './avatar';\nimport FollowRequestButtons from './follow-request-buttons';\nimport Icon from './icon';\nimport Link from './link';\nimport NameText from './name-text';\nimport RelativeTime from './relative-time';\nimport Status from './status';\n\nconst NOTIFICATION_ICONS = {\n mention: 'comment',\n status: 'notification',\n reblog: 'rocket',\n follow: 'follow',\n follow_request: 'follow-add',\n favourite: 'heart',\n poll: 'poll',\n update: 'pencil',\n 'admin.signup': 'account-edit',\n 'admin.report': 'account-warning',\n};\n\n/*\nNotification types\n==================\nmention = Someone mentioned you in their status\nstatus = Someone you enabled notifications for has posted a status\nreblog = Someone boosted one of your statuses\nfollow = Someone followed you\nfollow_request = Someone requested to follow you\nfavourite = Someone favourited one of your statuses\npoll = A poll you have voted in or created has ended\nupdate = A status you interacted with has been edited\nadmin.sign_up = Someone signed up (optionally sent to admins)\nadmin.report = A new report has been filed\n*/\n\nconst contentText = {\n mention: 'mentioned you in their post.',\n status: 'published a post.',\n reblog: 'boosted your post.',\n 'reblog+account': (count) => `boosted ${count} of your posts.`,\n reblog_reply: 'boosted your reply.',\n follow: 'followed you.',\n follow_request: 'requested to follow you.',\n favourite: 'liked your post.',\n 'favourite+account': (count) => `liked ${count} of your posts.`,\n favourite_reply: 'liked your reply.',\n poll: 'A poll you have voted in or created has ended.',\n 'poll-self': 'A poll you have created has ended.',\n 'poll-voted': 'A poll you have voted in has ended.',\n update: 'A post you interacted with has been edited.',\n 'favourite+reblog': 'boosted & liked your post.',\n 'favourite+reblog+account': (count) =>\n `boosted & liked ${count} of your posts.`,\n 'favourite+reblog_reply': 'boosted & liked your reply.',\n 'admin.sign_up': 'signed up.',\n 'admin.report': (targetAccount) => <>reported {targetAccount}>,\n};\n\nconst AVATARS_LIMIT = 50;\n\nfunction Notification({\n notification,\n instance,\n isStatic,\n disableContextMenu,\n}) {\n const { id, status, account, report, _accounts, _statuses } = notification;\n let { type } = notification;\n\n // status = Attached when type of the notification is favourite, reblog, status, mention, poll, or update\n const actualStatus = status?.reblog || status;\n const actualStatusID = actualStatus?.id;\n\n const currentAccount = store.session.get('currentAccount');\n const isSelf = currentAccount === account?.id;\n const isVoted = status?.poll?.voted;\n const isReplyToOthers =\n !!status?.inReplyToAccountId &&\n status?.inReplyToAccountId !== currentAccount &&\n status?.account?.id === currentAccount;\n\n let favsCount = 0;\n let reblogsCount = 0;\n if (type === 'favourite+reblog') {\n for (const account of _accounts) {\n if (account._types?.includes('favourite')) {\n favsCount++;\n }\n if (account._types?.includes('reblog')) {\n reblogsCount++;\n }\n }\n if (!reblogsCount && favsCount) type = 'favourite';\n if (!favsCount && reblogsCount) type = 'reblog';\n }\n\n let text;\n if (type === 'poll') {\n text = contentText[isSelf ? 'poll-self' : isVoted ? 'poll-voted' : 'poll'];\n } else if (\n type === 'reblog' ||\n type === 'favourite' ||\n type === 'favourite+reblog'\n ) {\n if (_statuses?.length > 1) {\n text = contentText[`${type}+account`];\n } else if (isReplyToOthers) {\n text = contentText[`${type}_reply`];\n } else {\n text = contentText[type];\n }\n } else if (contentText[type]) {\n text = contentText[type];\n } else {\n // Anticipate unhandled notification types, possibly from Mastodon forks or non-Mastodon instances\n // This surfaces the error to the user, hoping that users will report it\n text = `[Unknown notification type: ${type}]`;\n }\n\n if (typeof text === 'function') {\n const count = _statuses?.length || _accounts?.length;\n if (count) {\n text = text(count);\n } else if (type === 'admin.report') {\n const targetAccount = report?.targetAccount;\n if (targetAccount) {\n text = text( );\n }\n }\n }\n\n if (type === 'mention' && !status) {\n // Could be deleted\n return null;\n }\n\n const formattedCreatedAt =\n notification.createdAt && new Date(notification.createdAt).toLocaleString();\n\n const genericAccountsHeading =\n {\n 'favourite+reblog': 'Boosted/Liked by…',\n favourite: 'Liked by…',\n reblog: 'Boosted by…',\n follow: 'Followed by…',\n }[type] || 'Accounts';\n const handleOpenGenericAccounts = () => {\n states.showGenericAccounts = {\n heading: genericAccountsHeading,\n accounts: _accounts,\n showReactions: type === 'favourite+reblog',\n excludeRelationshipAttrs: type === 'follow' ? ['followedBy'] : [],\n };\n };\n\n console.debug('RENDER Notification', notification.id);\n\n return (\n \n
\n {type === 'favourite+reblog' ? (\n <>\n \n \n >\n ) : (\n \n )}\n
\n
\n {type !== 'mention' && (\n <>\n
\n {!/poll|update/i.test(type) && (\n <>\n {_accounts?.length > 1 ? (\n <>\n \n \n {shortenNumber(_accounts.length)}\n {' '}\n people\n {' '}\n >\n ) : (\n <>\n {' '}\n >\n )}\n >\n )}\n {text}\n {type === 'mention' && (\n \n {' '}\n •{' '}\n \n \n )}\n
\n {type === 'follow_request' && (\n
\n )}\n >\n )}\n {_accounts?.length > 1 && (\n
\n {_accounts.slice(0, AVATARS_LIMIT).map((account) => (\n \n {\n e.preventDefault();\n states.showAccount = account;\n }}\n >\n \n {type === 'favourite+reblog' && (\n \n {account._types.map((type) => (\n \n ))}\n
\n )}\n {' '}\n \n ))}\n \n {_accounts.length > AVATARS_LIMIT &&\n `+${_accounts.length - AVATARS_LIMIT}`}\n \n \n
\n )}\n {_statuses?.length > 1 && (\n
\n {_statuses.map((status) => (\n \n \n \n \n \n ))}\n \n )}\n {status && (!_statuses?.length || _statuses?.length <= 1) && (\n
{\n const post = e.target.querySelector('.status');\n if (post) {\n // Fire a custom event to open the context menu\n if (e.metaKey) return;\n e.preventDefault();\n post.dispatchEvent(\n new MouseEvent('contextmenu', {\n clientX: e.clientX,\n clientY: e.clientY,\n }),\n );\n }\n }\n : undefined\n }\n >\n {isStatic ? (\n \n ) : (\n \n )}\n \n )}\n
\n
\n );\n}\n\nfunction TruncatedLink(props) {\n const ref = useTruncated();\n return ;\n}\n\nexport default memo(Notification);\n","import { memo } from 'preact/compat';\nimport { useLayoutEffect, useState } from 'preact/hooks';\nimport { useSnapshot } from 'valtio';\n\nimport { api } from '../utils/api';\nimport states from '../utils/states';\nimport {\n getAccountByAccessToken,\n getCurrentAccount,\n} from '../utils/store-utils';\nimport usePageVisibility from '../utils/usePageVisibility';\n\nimport Icon from './icon';\nimport Link from './link';\nimport Modal from './modal';\nimport Notification from './notification';\n\n{\n if ('serviceWorker' in navigator) {\n console.log('👂👂👂 Listen to message');\n navigator.serviceWorker.addEventListener('message', (event) => {\n console.log('💥💥💥 Message event', event);\n const { type, id, accessToken } = event?.data || {};\n if (type === 'notification') {\n states.routeNotification = {\n id,\n accessToken,\n };\n }\n });\n }\n}\n\nexport default memo(function NotificationService() {\n if (!('serviceWorker' in navigator)) return null;\n\n const snapStates = useSnapshot(states);\n const { routeNotification } = snapStates;\n\n console.log('🛎️ Notification service', routeNotification);\n\n const { id, accessToken } = routeNotification || {};\n const [showNotificationSheet, setShowNotificationSheet] = useState(false);\n\n useLayoutEffect(() => {\n if (!id || !accessToken) return;\n const { instance: currentInstance } = api();\n const { masto, instance } = api({\n accessToken,\n });\n console.log('API', { accessToken, currentInstance, instance });\n const sameInstance = currentInstance === instance;\n const account = accessToken\n ? getAccountByAccessToken(accessToken)\n : getCurrentAccount();\n (async () => {\n const notification = await masto.v1.notifications.$select(id).fetch();\n if (notification && account) {\n console.log('🛎️ Notification', { id, notification, account });\n const accountInstance = account.instanceURL;\n const { type, status, account: notificationAccount } = notification;\n const hasModal = !!document.querySelector('#modal-container > *');\n const isFollow = type === 'follow' && !!notificationAccount?.id;\n const hasAccount = !!notificationAccount?.id;\n const hasStatus = !!status?.id;\n if (isFollow && sameInstance) {\n // Show account sheet, can handle different instances\n states.showAccount = {\n account: notificationAccount,\n instance: accountInstance,\n };\n } else if (hasModal || !sameInstance || (hasAccount && hasStatus)) {\n // Show sheet of notification, if\n // - there is a modal open\n // - the notification is from another instance\n // - the notification has both account and status, gives choice for users to go to account or status\n setShowNotificationSheet({\n id,\n account,\n notification,\n sameInstance,\n });\n } else {\n if (hasStatus) {\n // Go to status page\n location.hash = `/${currentInstance}/s/${status.id}`;\n } else if (isFollow) {\n // Go to profile page\n location.hash = `/${currentInstance}/a/${notificationAccount.id}`;\n } else {\n // Go to notifications page\n location.hash = '/notifications';\n }\n }\n } else {\n console.warn('🛎️ Notification not found', id);\n }\n })();\n }, [id, accessToken]);\n\n // useLayoutEffect(() => {\n // // Listen to message from service worker\n // const handleMessage = (event) => {\n // console.log('💥💥💥 Message event', event);\n // const { type, id, accessToken } = event?.data || {};\n // if (type === 'notification') {\n // states.routeNotification = {\n // id,\n // accessToken,\n // };\n // }\n // };\n // console.log('👂👂👂 Listen to message');\n // navigator.serviceWorker.addEventListener('message', handleMessage);\n // return () => {\n // console.log('👂👂👂 Remove listen to message');\n // navigator.serviceWorker.removeEventListener('message', handleMessage);\n // };\n // }, []);\n\n useLayoutEffect(() => {\n if (navigator?.clearAppBadge) {\n navigator.clearAppBadge();\n }\n }, []);\n usePageVisibility((visible) => {\n if (visible && navigator?.clearAppBadge) {\n console.log('🔰 Clear app badge');\n navigator.clearAppBadge();\n }\n });\n\n const onClose = () => {\n setShowNotificationSheet(false);\n states.routeNotification = null;\n\n // If url is #/notifications?id=123, go to #/notifications\n if (/\\/notifications\\?id=/i.test(location.hash)) {\n location.hash = '/notifications';\n }\n };\n\n if (showNotificationSheet) {\n const { id, account, notification, sameInstance } = showNotificationSheet;\n return (\n {\n if (e.target === e.currentTarget) {\n onClose();\n }\n }}\n >\n \n
\n \n \n
\n
\n {!sameInstance && (\n This notification is from your other account.
\n )}\n {\n const { target } = e;\n // If button or links\n if (e.target.tagName === 'BUTTON' || e.target.tagName === 'A') {\n onClose();\n }\n }}\n >\n \n
\n \n \n View all notifications \n \n
\n \n
\n \n );\n }\n\n return null;\n});\n","import { forwardRef } from 'preact/compat';\nimport { useImperativeHandle, useRef, useState } from 'preact/hooks';\nimport { useSearchParams } from 'react-router-dom';\n\nimport { api } from '../utils/api';\n\nimport Icon from './icon';\nimport Link from './link';\n\nconst SearchForm = forwardRef((props, ref) => {\n const { instance } = api();\n const [searchParams, setSearchParams] = useSearchParams();\n const [searchMenuOpen, setSearchMenuOpen] = useState(false);\n const [query, setQuery] = useState(searchParams.get('q') || '');\n const type = searchParams.get('type');\n const formRef = useRef(null);\n\n const searchFieldRef = useRef(null);\n useImperativeHandle(ref, () => ({\n setValue: (value) => {\n setQuery(value);\n },\n focus: () => {\n searchFieldRef.current.focus();\n },\n select: () => {\n searchFieldRef.current.select();\n },\n blur: () => {\n searchFieldRef.current.blur();\n },\n }));\n\n return (\n {\n e.preventDefault();\n\n const isSearchPage = /\\/search/.test(location.hash);\n if (isSearchPage) {\n if (query) {\n const params = {\n q: query,\n };\n if (type) params.type = type; // Preserve type\n setSearchParams(params);\n } else {\n setSearchParams({});\n }\n } else {\n if (query) {\n location.hash = `/search?q=${encodeURIComponent(query)}${\n type ? `&type=${type}` : ''\n }`;\n } else {\n location.hash = `/search`;\n }\n }\n\n props?.onSubmit?.(e);\n }}\n >\n {\n if (!e.target.value) {\n setSearchParams({});\n }\n }}\n onInput={(e) => {\n setQuery(e.target.value);\n setSearchMenuOpen(true);\n }}\n onFocus={() => {\n setSearchMenuOpen(true);\n }}\n onBlur={() => {\n setTimeout(() => {\n setSearchMenuOpen(false);\n }, 100);\n formRef.current\n ?.querySelector('.search-popover-item.focus')\n ?.classList.remove('focus');\n }}\n onKeyDown={(e) => {\n const { key } = e;\n switch (key) {\n case 'Escape':\n setSearchMenuOpen(false);\n break;\n case 'Down':\n case 'ArrowDown':\n e.preventDefault();\n if (searchMenuOpen) {\n const focusItem = formRef.current.querySelector(\n '.search-popover-item.focus',\n );\n if (focusItem) {\n let nextItem = focusItem.nextElementSibling;\n while (nextItem && nextItem.hidden) {\n nextItem = nextItem.nextElementSibling;\n }\n if (nextItem) {\n nextItem.classList.add('focus');\n const siblings = Array.from(\n nextItem.parentElement.children,\n ).filter((el) => el !== nextItem);\n siblings.forEach((el) => {\n el.classList.remove('focus');\n });\n }\n } else {\n const firstItem = formRef.current.querySelector(\n '.search-popover-item',\n );\n if (firstItem) {\n firstItem.classList.add('focus');\n }\n }\n }\n break;\n case 'Up':\n case 'ArrowUp':\n e.preventDefault();\n if (searchMenuOpen) {\n const focusItem = document.querySelector(\n '.search-popover-item.focus',\n );\n if (focusItem) {\n let prevItem = focusItem.previousElementSibling;\n while (prevItem && prevItem.hidden) {\n prevItem = prevItem.previousElementSibling;\n }\n if (prevItem) {\n prevItem.classList.add('focus');\n const siblings = Array.from(\n prevItem.parentElement.children,\n ).filter((el) => el !== prevItem);\n siblings.forEach((el) => {\n el.classList.remove('focus');\n });\n }\n } else {\n const lastItem = document.querySelector(\n '.search-popover-item:last-child',\n );\n if (lastItem) {\n lastItem.classList.add('focus');\n }\n }\n }\n break;\n case 'Enter':\n if (searchMenuOpen) {\n const focusItem = document.querySelector(\n '.search-popover-item.focus',\n );\n if (focusItem) {\n e.preventDefault();\n focusItem.click();\n }\n setSearchMenuOpen(false);\n props?.onSubmit?.(e);\n }\n break;\n }\n }}\n />\n \n {!!query &&\n [\n {\n label: (\n <>\n Posts with {query} \n >\n ),\n to: `/search?q=${encodeURIComponent(query)}&type=statuses`,\n hidden: /^https?:/.test(query),\n },\n {\n label: (\n <>\n Posts tagged with #{query.replace(/^#/, '')} \n >\n ),\n to: `/${instance}/t/${query.replace(/^#/, '')}`,\n hidden:\n /^@/.test(query) || /^https?:/.test(query) || /\\s/.test(query),\n top: /^#/.test(query),\n type: 'link',\n },\n {\n label: (\n <>\n Look up {query} \n >\n ),\n to: `/${query}`,\n hidden: !/^https?:/.test(query),\n top: /^https?:/.test(query),\n type: 'link',\n },\n {\n label: (\n <>\n Accounts with {query} \n >\n ),\n to: `/search?q=${encodeURIComponent(query)}&type=accounts`,\n },\n ]\n .sort((a, b) => {\n if (a.top && !b.top) return -1;\n if (!a.top && b.top) return 1;\n return 0;\n })\n .map(({ label, to, hidden, type }) => (\n {\n props?.onSubmit?.(e);\n }}\n >\n \n {label} {' '}\n \n ))}\n
\n \n );\n});\n\nexport default SearchForm;\n","import './search-command.css';\n\nimport { memo } from 'preact/compat';\nimport { useRef, useState } from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\n\nimport SearchForm from './search-form';\n\nexport default memo(function SearchCommand({ onClose = () => {} }) {\n const [showSearch, setShowSearch] = useState(false);\n const searchFormRef = useRef(null);\n\n useHotkeys(\n '/',\n (e) => {\n setShowSearch(true);\n setTimeout(() => {\n searchFormRef.current?.focus?.();\n searchFormRef.current?.select?.();\n }, 0);\n },\n {\n preventDefault: true,\n ignoreEventWhen: (e) => {\n const isSearchPage = /\\/search/.test(location.hash);\n const hasModal = !!document.querySelector('#modal-container > *');\n return isSearchPage || hasModal;\n },\n },\n );\n\n const closeSearch = () => {\n setShowSearch(false);\n onClose();\n };\n\n useHotkeys(\n 'esc',\n (e) => {\n searchFormRef.current?.blur?.();\n closeSearch();\n },\n {\n enabled: showSearch,\n enableOnFormTags: true,\n preventDefault: true,\n },\n );\n\n return (\n {\n console.log(e);\n if (e.target === e.currentTarget) {\n closeSearch();\n }\n }}\n >\n {\n closeSearch();\n }}\n />\n
\n );\n});\n","import './shortcuts.css';\n\nimport { Menu, MenuItem } from '@szhsin/react-menu';\nimport { memo } from 'preact/compat';\nimport { useMemo, useRef } from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\nimport { useNavigate } from 'react-router-dom';\nimport { useSnapshot } from 'valtio';\n\nimport { SHORTCUTS_META } from '../components/shortcuts-settings';\nimport { api } from '../utils/api';\nimport states from '../utils/states';\n\nimport AsyncText from './AsyncText';\nimport Icon from './icon';\nimport Link from './link';\nimport Menu2 from './menu2';\nimport MenuLink from './menu-link';\n\nfunction Shortcuts() {\n const { instance } = api();\n const snapStates = useSnapshot(states);\n const { shortcuts, settings } = snapStates;\n\n if (!shortcuts.length) {\n return null;\n }\n if (\n settings.shortcutsViewMode === 'multi-column' ||\n (!settings.shortcutsViewMode && settings.shortcutsColumnsMode)\n ) {\n return null;\n }\n\n const menuRef = useRef();\n\n const formattedShortcuts = useMemo(\n () =>\n shortcuts\n .map((pin, i) => {\n const { type, ...data } = pin;\n if (!SHORTCUTS_META[type]) return null;\n let { id, path, title, subtitle, icon } = SHORTCUTS_META[type];\n\n if (typeof id === 'function') {\n id = id(data, i);\n }\n if (typeof path === 'function') {\n path = path(\n {\n ...data,\n instance: data.instance || instance,\n },\n i,\n );\n }\n if (typeof title === 'function') {\n title = title(data, i);\n }\n if (typeof subtitle === 'function') {\n subtitle = subtitle(data, i);\n }\n if (typeof icon === 'function') {\n icon = icon(data, i);\n }\n\n return {\n id,\n path,\n title,\n subtitle,\n icon,\n };\n })\n .filter(Boolean),\n [shortcuts],\n );\n\n const navigate = useNavigate();\n useHotkeys(['1', '2', '3', '4', '5', '6', '7', '8', '9'], (e, handler) => {\n const index = parseInt(handler.keys[0], 10) - 1;\n if (index < formattedShortcuts.length) {\n const { path } = formattedShortcuts[index];\n if (path) {\n navigate(path);\n menuRef.current?.closeMenu?.();\n }\n }\n });\n\n return (\n \n {snapStates.settings.shortcutsViewMode === 'tab-menu-bar' ? (\n
{\n e.preventDefault();\n states.showShortcutsSettings = true;\n }}\n >\n \n {formattedShortcuts.map(\n ({ id, path, title, subtitle, icon }, i) => {\n return (\n \n {\n if (e.target.classList.contains('is-active')) {\n e.preventDefault();\n const page = document.getElementById(`${id}-page`);\n console.log(id, page);\n if (page) {\n page.scrollTop = 0;\n const updatesButton =\n page.querySelector('.updates-button');\n if (updatesButton) {\n updatesButton.click();\n }\n }\n }\n }}\n >\n \n \n {title} \n {subtitle && (\n <>\n \n {subtitle} \n >\n )}\n \n \n \n );\n },\n )}\n \n \n ) : (\n
{\n e.preventDefault();\n states.showShortcutsSettings = true;\n }}\n onTransitionStart={(e) => {\n // Close menu if the button disappears\n try {\n const { target } = e;\n if (getComputedStyle(target).pointerEvents === 'none') {\n menuRef.current?.closeMenu?.();\n }\n } catch (e) {}\n }}\n >\n \n \n }\n >\n {formattedShortcuts.map(({ id, path, title, subtitle, icon }, i) => {\n return (\n \n );\n })}\n \n )}\n
\n );\n}\n\nexport default memo(Shortcuts);\n","import { extractTagsFromStatus, getFollowedTags } from './followed-tags';\nimport { fetchRelationships } from './relationships';\nimport states, { statusKey } from './states';\nimport store from './store';\n\nexport function groupBoosts(values) {\n let newValues = [];\n let boostStash = [];\n let serialBoosts = 0;\n for (let i = 0; i < values.length; i++) {\n const item = values[i];\n if (item.reblog && !item.account?.group) {\n boostStash.push(item);\n serialBoosts++;\n } else {\n newValues.push(item);\n if (serialBoosts < 3) {\n serialBoosts = 0;\n }\n }\n }\n // if boostStash is more than quarter of values\n // or if there are 3 or more boosts in a row\n if (\n values.length > 10 &&\n (boostStash.length > values.length / 4 || serialBoosts >= 3)\n ) {\n // if boostStash is more than 3 quarter of values\n const boostStashID = boostStash.map((status) => status.id);\n if (boostStash.length > (values.length * 3) / 4) {\n // insert boost array at the end of specialHome list\n newValues = [\n ...newValues,\n { id: boostStashID, items: boostStash, type: 'boosts' },\n ];\n } else {\n // insert boosts array in the middle of specialHome list\n const half = Math.floor(newValues.length / 2);\n newValues = [\n ...newValues.slice(0, half),\n {\n id: boostStashID,\n items: boostStash,\n type: 'boosts',\n },\n ...newValues.slice(half),\n ];\n }\n return newValues;\n } else {\n return values;\n }\n}\n\nexport function dedupeBoosts(items, instance) {\n const boostedStatusIDs = store.account.get('boostedStatusIDs') || {};\n const filteredItems = items.filter((item) => {\n if (!item.reblog) return true;\n const statusKey = `${instance}-${item.reblog.id}`;\n const boosterID = boostedStatusIDs[statusKey];\n if (boosterID && boosterID !== item.id) {\n console.warn(\n `🚫 Duplicate boost by ${item.account.displayName}`,\n item,\n item.reblog,\n );\n return false;\n } else {\n boostedStatusIDs[statusKey] = item.id;\n }\n return true;\n });\n // Limit to 50\n const keys = Object.keys(boostedStatusIDs);\n if (keys.length > 50) {\n keys.slice(0, keys.length - 50).forEach((key) => {\n delete boostedStatusIDs[key];\n });\n }\n store.account.set('boostedStatusIDs', boostedStatusIDs);\n return filteredItems;\n}\n\nexport function groupContext(items) {\n const contexts = [];\n let contextIndex = 0;\n items.forEach((item) => {\n for (let i = 0; i < contexts.length; i++) {\n if (contexts[i].find((t) => t.id === item.id)) return;\n if (\n contexts[i].find((t) => t.id === item.inReplyToId) ||\n contexts[i].find((t) => t.inReplyToId === item.id)\n ) {\n contexts[i].push(item);\n return;\n }\n }\n const repliedItem = items.find((i) => i.id === item.inReplyToId);\n if (repliedItem) {\n contexts[contextIndex++] = [item, repliedItem];\n }\n });\n\n // Check for cross-item contexts\n // Merge contexts into one if they have a common item (same id)\n for (let i = 0; i < contexts.length; i++) {\n for (let j = i + 1; j < contexts.length; j++) {\n const commonItem = contexts[i].find((t) => contexts[j].includes(t));\n if (commonItem) {\n contexts[i] = [...contexts[i], ...contexts[j]];\n // Remove duplicate items\n contexts[i] = contexts[i].filter(\n (item, index, self) =>\n self.findIndex((t) => t.id === item.id) === index,\n );\n contexts.splice(j, 1);\n j--;\n }\n }\n }\n\n // Sort items by checking inReplyToId\n contexts.forEach((context) => {\n context.sort((a, b) => {\n if (!a.inReplyToId && !b.inReplyToId) {\n return new Date(a.createdAt) - new Date(b.createdAt);\n }\n if (a.inReplyToId === b.id) return 1;\n if (b.inReplyToId === a.id) return -1;\n if (!a.inReplyToId) return -1;\n if (!b.inReplyToId) return 1;\n return new Date(a.createdAt) - new Date(b.createdAt);\n });\n });\n\n // Tag items that has different author than first post's author\n contexts.forEach((context) => {\n const firstItemAccountID = context[0].account.id;\n context.forEach((item) => {\n if (item.account.id !== firstItemAccountID) {\n item._differentAuthor = true;\n }\n });\n });\n\n if (contexts.length) console.log('🧵 Contexts', contexts);\n\n const newItems = [];\n const appliedContextIndices = [];\n items.forEach((item) => {\n if (item.reblog) {\n newItems.push(item);\n return;\n }\n for (let i = 0; i < contexts.length; i++) {\n if (contexts[i].find((t) => t.id === item.id)) {\n if (appliedContextIndices.includes(i)) return;\n const contextItems = contexts[i];\n contextItems.sort((a, b) => {\n const aDate = new Date(a.createdAt);\n const bDate = new Date(b.createdAt);\n return aDate - bDate;\n });\n const firstItemAccountID = contextItems[0].account.id;\n newItems.push({\n id: contextItems.map((i) => i.id),\n items: contextItems,\n type: contextItems.every((it) => it.account.id === firstItemAccountID)\n ? 'thread'\n : 'conversation',\n });\n appliedContextIndices.push(i);\n return;\n }\n }\n newItems.push(item);\n });\n\n return newItems;\n}\n\nexport async function assignFollowedTags(items, instance) {\n const followedTags = await getFollowedTags(); // [{name: 'tag'}, {...}]\n if (!followedTags.length) return;\n const { statusFollowedTags } = states;\n console.log('statusFollowedTags', statusFollowedTags);\n const statusWithFollowedTags = [];\n items.forEach((item) => {\n if (item.reblog) return;\n const { id, content, tags = [] } = item;\n const sKey = statusKey(id, instance);\n if (statusFollowedTags[sKey]?.length) return;\n const extractedTags = extractTagsFromStatus(content);\n if (!extractedTags.length && !tags.length) return;\n const itemFollowedTags = followedTags.reduce((acc, tag) => {\n if (\n extractedTags.some((t) => t.toLowerCase() === tag.name.toLowerCase()) ||\n tags.some((t) => t.name.toLowerCase() === tag.name.toLowerCase())\n ) {\n acc.push(tag.name);\n }\n return acc;\n }, []);\n if (itemFollowedTags.length) {\n // statusFollowedTags[sKey] = itemFollowedTags;\n statusWithFollowedTags.push({\n item,\n sKey,\n followedTags: itemFollowedTags,\n });\n }\n });\n\n if (statusWithFollowedTags.length) {\n const accounts = statusWithFollowedTags.map((s) => s.item.account);\n const relationships = await fetchRelationships(accounts);\n if (!relationships) return;\n\n statusWithFollowedTags.forEach((s) => {\n const { item, sKey, followedTags } = s;\n const r = relationships[item.account.id];\n if (!r.following) {\n statusFollowedTags[sKey] = followedTags;\n }\n });\n }\n}\n\nexport function clearFollowedTagsState() {\n states.statusFollowedTags = {};\n}\n","import { useLayoutEffect, useState } from 'preact/hooks';\n\nexport default function useScroll({\n scrollableRef,\n distanceFromStart = 1, // ratio of clientHeight/clientWidth\n distanceFromEnd = 1, // ratio of clientHeight/clientWidth\n scrollThresholdStart = 10,\n scrollThresholdEnd = 10,\n direction = 'vertical',\n distanceFromStartPx: _distanceFromStartPx,\n distanceFromEndPx: _distanceFromEndPx,\n} = {}) {\n const [scrollDirection, setScrollDirection] = useState(null);\n const [reachStart, setReachStart] = useState(false);\n const [reachEnd, setReachEnd] = useState(false);\n const [nearReachStart, setNearReachStart] = useState(false);\n const [nearReachEnd, setNearReachEnd] = useState(false);\n const isVertical = direction === 'vertical';\n\n useLayoutEffect(() => {\n const scrollableElement = scrollableRef.current;\n if (!scrollableElement) return {};\n let previousScrollStart = isVertical\n ? scrollableElement.scrollTop\n : scrollableElement.scrollLeft;\n\n function onScroll() {\n const {\n scrollTop,\n scrollLeft,\n scrollHeight,\n scrollWidth,\n clientHeight,\n clientWidth,\n } = scrollableElement;\n const scrollStart = isVertical ? scrollTop : scrollLeft;\n const scrollDimension = isVertical ? scrollHeight : scrollWidth;\n const clientDimension = isVertical ? clientHeight : clientWidth;\n const scrollDistance = Math.abs(scrollStart - previousScrollStart);\n const distanceFromStartPx =\n _distanceFromStartPx ||\n Math.min(\n clientDimension * distanceFromStart,\n scrollDimension,\n scrollStart,\n );\n const distanceFromEndPx =\n _distanceFromEndPx ||\n Math.min(\n clientDimension * distanceFromEnd,\n scrollDimension,\n scrollDimension - scrollStart - clientDimension,\n );\n\n if (\n scrollDistance >=\n (previousScrollStart < scrollStart\n ? scrollThresholdEnd\n : scrollThresholdStart)\n ) {\n setScrollDirection(previousScrollStart < scrollStart ? 'end' : 'start');\n previousScrollStart = scrollStart;\n }\n\n setReachStart(scrollStart <= 0);\n setReachEnd(scrollStart + clientDimension >= scrollDimension);\n setNearReachStart(scrollStart <= distanceFromStartPx);\n setNearReachEnd(\n scrollStart + clientDimension >= scrollDimension - distanceFromEndPx,\n );\n }\n\n scrollableElement.addEventListener('scroll', onScroll, { passive: true });\n\n return () => scrollableElement.removeEventListener('scroll', onScroll);\n }, [\n distanceFromStart,\n distanceFromEnd,\n scrollThresholdStart,\n scrollThresholdEnd,\n ]);\n\n return {\n scrollDirection,\n reachStart,\n reachEnd,\n nearReachStart,\n nearReachEnd,\n init: () => {\n if (scrollableRef.current) {\n scrollableRef.current.dispatchEvent(new Event('scroll'));\n }\n },\n };\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';\nimport { useThrottledCallback } from 'use-debounce';\n\nexport default function useScrollFn(\n {\n scrollableRef,\n distanceFromStart = 1, // ratio of clientHeight/clientWidth\n distanceFromEnd = 1, // ratio of clientHeight/clientWidth\n scrollThresholdStart = 10,\n scrollThresholdEnd = 10,\n direction = 'vertical',\n distanceFromStartPx: _distanceFromStartPx,\n distanceFromEndPx: _distanceFromEndPx,\n init,\n } = {},\n callback,\n deps,\n) {\n if (!callback) return;\n const [scrollDirection, setScrollDirection] = useState(null);\n const [reachStart, setReachStart] = useState(false);\n const [reachEnd, setReachEnd] = useState(false);\n const [nearReachStart, setNearReachStart] = useState(false);\n const [nearReachEnd, setNearReachEnd] = useState(false);\n const isVertical = direction === 'vertical';\n const previousScrollStart = useRef(null);\n\n const onScroll = useThrottledCallback(() => {\n const scrollableElement = scrollableRef.current;\n const {\n scrollTop,\n scrollLeft,\n scrollHeight,\n scrollWidth,\n clientHeight,\n clientWidth,\n } = scrollableElement;\n const scrollStart = isVertical ? scrollTop : scrollLeft;\n const scrollDimension = isVertical ? scrollHeight : scrollWidth;\n const clientDimension = isVertical ? clientHeight : clientWidth;\n const scrollDistance = Math.abs(scrollStart - previousScrollStart.current);\n const distanceFromStartPx =\n _distanceFromStartPx ||\n Math.min(\n clientDimension * distanceFromStart,\n scrollDimension,\n scrollStart,\n );\n const distanceFromEndPx =\n _distanceFromEndPx ||\n Math.min(\n clientDimension * distanceFromEnd,\n scrollDimension,\n scrollDimension - scrollStart - clientDimension,\n );\n\n if (\n scrollDistance >=\n (previousScrollStart.current < scrollStart\n ? scrollThresholdEnd\n : scrollThresholdStart)\n ) {\n setScrollDirection(\n previousScrollStart.current < scrollStart ? 'end' : 'start',\n );\n previousScrollStart.current = scrollStart;\n }\n\n setReachStart(scrollStart <= 0);\n setReachEnd(scrollStart + clientDimension >= scrollDimension);\n setNearReachStart(scrollStart <= distanceFromStartPx);\n setNearReachEnd(\n scrollStart + clientDimension >= scrollDimension - distanceFromEndPx,\n );\n }, 500);\n\n useLayoutEffect(() => {\n const scrollableElement = scrollableRef.current;\n if (!scrollableElement) return {};\n previousScrollStart.current =\n scrollableElement[isVertical ? 'scrollTop' : 'scrollLeft'];\n\n scrollableElement.addEventListener('scroll', onScroll, { passive: true });\n\n return () => scrollableElement.removeEventListener('scroll', onScroll);\n }, [\n distanceFromStart,\n distanceFromEnd,\n scrollThresholdStart,\n scrollThresholdEnd,\n ]);\n\n useEffect(() => {\n callback({\n scrollDirection,\n reachStart,\n reachEnd,\n nearReachStart,\n nearReachEnd,\n });\n }, [\n scrollDirection,\n reachStart,\n reachEnd,\n nearReachStart,\n nearReachEnd,\n ...deps,\n ]);\n\n useEffect(() => {\n if (init && scrollableRef.current) {\n queueMicrotask(() => {\n scrollableRef.current.dispatchEvent(new Event('scroll'));\n });\n }\n }, [init]);\n\n // return {\n // scrollDirection,\n // reachStart,\n // reachEnd,\n // nearReachStart,\n // nearReachEnd,\n // init: () => {\n // if (scrollableRef.current) {\n // scrollableRef.current.dispatchEvent(new Event('scroll'));\n // }\n // },\n // };\n}\n","import './media-post.css';\n\nimport { memo } from 'preact/compat';\nimport { useContext, useMemo } from 'preact/hooks';\nimport { useSnapshot } from 'valtio';\n\nimport FilterContext from '../utils/filter-context';\nimport { isFiltered } from '../utils/filters';\nimport states, { statusKey } from '../utils/states';\nimport store from '../utils/store';\n\nimport Media from './media';\n\nfunction MediaPost({\n class: className,\n statusID,\n status,\n instance,\n parent,\n // allowFilters,\n onMediaClick,\n}) {\n let sKey = statusKey(statusID, instance);\n const snapStates = useSnapshot(states);\n if (!status) {\n status = snapStates.statuses[sKey] || snapStates.statuses[statusID];\n sKey = statusKey(status?.id, instance);\n }\n if (!status) {\n return null;\n }\n\n const {\n account: {\n acct,\n avatar,\n avatarStatic,\n id: accountId,\n url: accountURL,\n displayName,\n username,\n emojis: accountEmojis,\n bot,\n group,\n },\n id,\n repliesCount,\n reblogged,\n reblogsCount,\n favourited,\n favouritesCount,\n bookmarked,\n poll,\n muted,\n sensitive,\n spoilerText,\n visibility, // public, unlisted, private, direct\n language,\n editedAt,\n filtered,\n card,\n createdAt,\n inReplyToId,\n inReplyToAccountId,\n content,\n mentions,\n mediaAttachments,\n reblog,\n uri,\n url,\n emojis,\n // Non-API props\n _deleted,\n _pinned,\n // _filtered,\n } = status;\n\n if (!mediaAttachments?.length) {\n return null;\n }\n\n const debugHover = (e) => {\n if (e.shiftKey) {\n console.log({\n ...status,\n });\n }\n };\n\n const currentAccount = useMemo(() => {\n return store.session.get('currentAccount');\n }, []);\n const isSelf = useMemo(() => {\n return currentAccount && currentAccount === accountId;\n }, [accountId, currentAccount]);\n\n const filterContext = useContext(FilterContext);\n const filterInfo = !isSelf && isFiltered(filtered, filterContext);\n\n if (filterInfo?.action === 'hide') {\n return null;\n }\n\n console.debug('RENDER Media post', id, status?.account.displayName);\n\n const hasSpoiler = sensitive;\n const readingExpandMedia = useMemo(() => {\n // default | show_all | hide_all\n const prefs = store.account.get('preferences') || {};\n return prefs['reading:expand:media'] || 'default';\n }, []);\n const showSpoilerMedia = readingExpandMedia === 'show_all';\n\n const Parent = parent || 'div';\n\n return mediaAttachments.map((media, i) => {\n const mediaKey = `${sKey}-${media.id}`;\n const filterTitleStr = filterInfo?.titlesStr;\n return (\n \n onMediaClick(e, i, media, status) : undefined\n }\n />\n \n );\n });\n}\n\nexport default memo(MediaPost);\n","import './nav-menu.css';\n\nimport { ControlledMenu, MenuDivider, MenuItem } from '@szhsin/react-menu';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useLongPress } from 'use-long-press';\nimport { useSnapshot } from 'valtio';\n\nimport { api } from '../utils/api';\nimport safeBoundingBoxPadding from '../utils/safe-bounding-box-padding';\nimport states from '../utils/states';\nimport store from '../utils/store';\n\nimport Avatar from './avatar';\nimport Icon from './icon';\nimport MenuLink from './menu-link';\n\nfunction NavMenu(props) {\n const snapStates = useSnapshot(states);\n const { masto, instance, authenticated } = api();\n\n const [currentAccount, setCurrentAccount] = useState();\n const [moreThanOneAccount, setMoreThanOneAccount] = useState(false);\n\n useEffect(() => {\n const accounts = store.local.getJSON('accounts') || [];\n const acc = accounts.find(\n (account) => account.info.id === store.session.get('currentAccount'),\n );\n if (acc) setCurrentAccount(acc);\n setMoreThanOneAccount(accounts.length > 1);\n }, []);\n\n // Home = Following\n // But when in multi-column mode, Home becomes columns of anything\n // User may choose pin or not to pin Following\n // If user doesn't pin Following, we show it in the menu\n const showFollowing =\n (snapStates.settings.shortcutsViewMode === 'multi-column' ||\n (!snapStates.settings.shortcutsViewMode &&\n snapStates.settings.shortcutsColumnsMode)) &&\n !snapStates.shortcuts.find((pin) => pin.type === 'following');\n\n const bindLongPress = useLongPress(\n () => {\n states.showAccounts = true;\n },\n {\n threshold: 600,\n detect: 'touch',\n cancelOnMovement: true,\n },\n );\n\n const buttonRef = useRef();\n const [menuState, setMenuState] = useState(undefined);\n\n const boundingBoxPadding = safeBoundingBoxPadding([\n 0,\n 0,\n snapStates.settings.shortcutsViewMode === 'tab-menu-bar' ? 50 : 0,\n 0,\n ]);\n\n const mutesIterator = useRef();\n async function fetchMutes(firstLoad) {\n if (firstLoad || !mutesIterator.current) {\n mutesIterator.current = masto.v1.mutes.list({\n limit: 80,\n });\n }\n const results = await mutesIterator.current.next();\n return results;\n }\n\n const blocksIterator = useRef();\n async function fetchBlocks(firstLoad) {\n if (firstLoad || !blocksIterator.current) {\n blocksIterator.current = masto.v1.blocks.list({\n limit: 80,\n });\n }\n const results = await blocksIterator.current.next();\n return results;\n }\n\n return (\n <>\n {\n setMenuState((state) => (!state ? 'open' : undefined));\n }}\n onContextMenu={(e) => {\n e.preventDefault();\n states.showAccounts = true;\n }}\n {...bindLongPress()}\n >\n {moreThanOneAccount && (\n \n )}\n \n \n {\n setMenuState(undefined);\n }}\n containerProps={{\n style: {\n zIndex: 10,\n },\n onClick: () => {\n setMenuState(undefined);\n },\n }}\n portal={{\n target: document.body,\n }}\n {...props}\n overflow=\"auto\"\n viewScroll=\"close\"\n position=\"anchor\"\n align=\"center\"\n boundingBoxPadding={boundingBoxPadding}\n unmountOnClose\n >\n {!!snapStates.appVersion?.commitHash &&\n __COMMIT_HASH__ !== snapStates.appVersion.commitHash && (\n \n )}\n \n \n Home \n \n {authenticated && (\n <>\n {showFollowing && (\n \n Following \n \n )}\n \n Mentions \n \n \n Notifications \n {snapStates.notificationsShowNew && (\n \n {' '}\n •\n \n )}\n \n \n \n Lists \n \n \n Followed Hashtags \n \n \n Bookmarks \n \n \n Likes \n \n >\n )}\n \n \n Search \n \n \n Local \n \n \n Federated \n \n \n Trending \n \n \n \n {authenticated ? (\n <>\n \n {currentAccount?.info?.id && (\n \n Profile \n \n )}\n {\n states.showAccounts = true;\n }}\n >\n Accounts… \n \n {\n states.showGenericAccounts = {\n id: 'mute',\n heading: 'Muted users',\n fetchAccounts: fetchMutes,\n excludeRelationshipAttrs: ['muting'],\n };\n }}\n >\n Muted users…\n \n {\n states.showGenericAccounts = {\n id: 'block',\n heading: 'Blocked users',\n fetchAccounts: fetchBlocks,\n excludeRelationshipAttrs: ['blocking'],\n };\n }}\n >\n \n Blocked users…\n \n \n {\n states.showKeyboardShortcutsHelp = true;\n }}\n >\n {' '}\n Keyboard shortcuts \n \n {\n states.showShortcutsSettings = true;\n }}\n >\n {' '}\n Shortcuts / Columns… \n \n {\n states.showSettings = true;\n }}\n >\n Settings… \n \n >\n ) : (\n <>\n \n \n Log in \n \n {\n states.showSettings = true;\n }}\n >\n Settings… \n \n >\n )}\n \n \n >\n );\n}\n\nexport default NavMenu;\n","import { useCallback, useEffect, useRef, useState } from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\nimport { InView } from 'react-intersection-observer';\nimport { useDebouncedCallback } from 'use-debounce';\nimport { useSnapshot } from 'valtio';\n\nimport FilterContext from '../utils/filter-context';\nimport { filteredItems, isFiltered } from '../utils/filters';\nimport states, { statusKey } from '../utils/states';\nimport statusPeek from '../utils/status-peek';\nimport { groupBoosts, groupContext } from '../utils/timeline-utils';\nimport useInterval from '../utils/useInterval';\nimport usePageVisibility from '../utils/usePageVisibility';\nimport useScroll from '../utils/useScroll';\nimport useScrollFn from '../utils/useScrollFn';\n\nimport Icon from './icon';\nimport Link from './link';\nimport MediaPost from './media-post';\nimport NavMenu from './nav-menu';\nimport Status from './status';\n\nconst scrollIntoViewOptions = {\n block: 'nearest',\n inline: 'center',\n behavior: 'smooth',\n};\n\nfunction Timeline({\n title,\n titleComponent,\n id,\n instance,\n emptyText,\n errorText,\n useItemID, // use statusID instead of status object, assuming it's already in states\n boostsCarousel,\n fetchItems = () => {},\n checkForUpdates = () => {},\n checkForUpdatesInterval = 15_000, // 15 seconds\n headerStart,\n headerEnd,\n timelineStart,\n // allowFilters,\n refresh,\n view,\n filterContext,\n showFollowedTags,\n}) {\n const snapStates = useSnapshot(states);\n const [items, setItems] = useState([]);\n const [uiState, setUIState] = useState('default');\n const [showMore, setShowMore] = useState(false);\n const [showNew, setShowNew] = useState(false);\n const [visible, setVisible] = useState(true);\n const scrollableRef = useRef();\n\n console.debug('RENDER Timeline', id, refresh);\n\n const allowGrouping = view !== 'media';\n const loadItems = useDebouncedCallback(\n (firstLoad) => {\n setShowNew(false);\n if (uiState === 'loading') return;\n setUIState('loading');\n (async () => {\n try {\n let { done, value } = await fetchItems(firstLoad);\n if (Array.isArray(value)) {\n // Avoid grouping for pinned posts\n const [pinnedPosts, otherPosts] = value.reduce(\n (acc, item) => {\n if (item._pinned) {\n acc[0].push(item);\n } else {\n acc[1].push(item);\n }\n return acc;\n },\n [[], []],\n );\n value = otherPosts;\n if (allowGrouping) {\n if (boostsCarousel) {\n value = groupBoosts(value);\n }\n value = groupContext(value);\n }\n if (pinnedPosts.length) {\n value = pinnedPosts.concat(value);\n }\n console.log(value);\n if (firstLoad) {\n setItems(value);\n } else {\n setItems((items) => [...items, ...value]);\n }\n if (!value.length) done = true;\n setShowMore(!done);\n } else {\n setShowMore(false);\n }\n setUIState('default');\n } catch (e) {\n console.error(e);\n setUIState('error');\n } finally {\n loadItems.cancel();\n }\n })();\n },\n 1500,\n {\n leading: true,\n trailing: false,\n },\n );\n\n const itemsSelector = '.timeline-item, .timeline-item-alt';\n\n const jRef = useHotkeys('j, shift+j', (_, handler) => {\n // focus on next status after active item\n const activeItem = document.activeElement.closest(itemsSelector);\n const activeItemRect = activeItem?.getBoundingClientRect();\n const allItems = Array.from(\n scrollableRef.current.querySelectorAll(itemsSelector),\n );\n if (\n activeItem &&\n activeItemRect.top < scrollableRef.current.clientHeight &&\n activeItemRect.bottom > 0\n ) {\n const activeItemIndex = allItems.indexOf(activeItem);\n let nextItem = allItems[activeItemIndex + 1];\n if (handler.shift) {\n // get next status that's not .timeline-item-alt\n nextItem = allItems.find(\n (item, index) =>\n index > activeItemIndex &&\n !item.classList.contains('timeline-item-alt'),\n );\n }\n if (nextItem) {\n nextItem.focus();\n nextItem.scrollIntoView(scrollIntoViewOptions);\n }\n } else {\n // If active status is not in viewport, get the topmost status-link in viewport\n const topmostItem = allItems.find((item) => {\n const itemRect = item.getBoundingClientRect();\n return itemRect.top >= 44 && itemRect.left >= 0; // 44 is the magic number for header height, not real\n });\n if (topmostItem) {\n topmostItem.focus();\n topmostItem.scrollIntoView(scrollIntoViewOptions);\n }\n }\n });\n\n const kRef = useHotkeys('k, shift+k', (_, handler) => {\n // focus on previous status after active item\n const activeItem = document.activeElement.closest(itemsSelector);\n const activeItemRect = activeItem?.getBoundingClientRect();\n const allItems = Array.from(\n scrollableRef.current.querySelectorAll(itemsSelector),\n );\n if (\n activeItem &&\n activeItemRect.top < scrollableRef.current.clientHeight &&\n activeItemRect.bottom > 0\n ) {\n const activeItemIndex = allItems.indexOf(activeItem);\n let prevItem = allItems[activeItemIndex - 1];\n if (handler.shift) {\n // get prev status that's not .timeline-item-alt\n prevItem = allItems.findLast(\n (item, index) =>\n index < activeItemIndex &&\n !item.classList.contains('timeline-item-alt'),\n );\n }\n if (prevItem) {\n prevItem.focus();\n prevItem.scrollIntoView(scrollIntoViewOptions);\n }\n } else {\n // If active status is not in viewport, get the topmost status-link in viewport\n const topmostItem = allItems.find((item) => {\n const itemRect = item.getBoundingClientRect();\n return itemRect.top >= 44 && itemRect.left >= 0; // 44 is the magic number for header height, not real\n });\n if (topmostItem) {\n topmostItem.focus();\n topmostItem.scrollIntoView(scrollIntoViewOptions);\n }\n }\n });\n\n const oRef = useHotkeys(['enter', 'o'], () => {\n // open active status\n const activeItem = document.activeElement.closest(itemsSelector);\n if (activeItem) {\n activeItem.click();\n }\n });\n\n // const {\n // scrollDirection,\n // nearReachStart,\n // nearReachEnd,\n // reachStart,\n // reachEnd,\n // } = useScroll({\n // scrollableRef,\n // distanceFromEnd: 2,\n // scrollThresholdStart: 44,\n // });\n const headerRef = useRef();\n // const [hiddenUI, setHiddenUI] = useState(false);\n const [nearReachStart, setNearReachStart] = useState(false);\n useScrollFn(\n {\n scrollableRef,\n distanceFromEnd: 2,\n scrollThresholdStart: 44,\n },\n ({\n scrollDirection,\n nearReachStart,\n nearReachEnd,\n reachStart,\n reachEnd,\n }) => {\n // setHiddenUI(scrollDirection === 'end' && !nearReachEnd);\n if (headerRef.current) {\n const hiddenUI = scrollDirection === 'end' && !nearReachStart;\n headerRef.current.hidden = hiddenUI;\n }\n setNearReachStart(nearReachStart);\n if (reachStart) {\n loadItems(true);\n }\n // else if (nearReachEnd || (reachEnd && showMore)) {\n // loadItems();\n // }\n },\n [],\n );\n\n useEffect(() => {\n scrollableRef.current?.scrollTo({ top: 0 });\n loadItems(true);\n }, []);\n useEffect(() => {\n loadItems(true);\n }, [refresh]);\n\n // useEffect(() => {\n // if (reachStart) {\n // loadItems(true);\n // }\n // }, [reachStart]);\n\n // useEffect(() => {\n // if (nearReachEnd || (reachEnd && showMore)) {\n // loadItems();\n // }\n // }, [nearReachEnd, showMore]);\n\n const prevView = useRef(view);\n useEffect(() => {\n if (prevView.current !== view) {\n prevView.current = view;\n setItems([]);\n }\n }, [view]);\n\n const loadOrCheckUpdates = useCallback(\n async ({ disableIdleCheck = false } = {}) => {\n const noPointers = scrollableRef.current\n ? getComputedStyle(scrollableRef.current).pointerEvents === 'none'\n : false;\n console.log('✨ Load or check updates', id, {\n autoRefresh: snapStates.settings.autoRefresh,\n scrollTop: scrollableRef.current.scrollTop,\n disableIdleCheck,\n idle: window.__IDLE__,\n inBackground: inBackground(),\n noPointers,\n });\n if (\n snapStates.settings.autoRefresh &&\n scrollableRef.current.scrollTop < 16 &&\n (disableIdleCheck || window.__IDLE__) &&\n !inBackground() &&\n !noPointers\n ) {\n console.log('✨ Load updates', id, snapStates.settings.autoRefresh);\n loadItems(true);\n } else {\n console.log('✨ Check updates', id, snapStates.settings.autoRefresh);\n const hasUpdate = await checkForUpdates();\n if (hasUpdate) {\n console.log('✨ Has new updates', id);\n setShowNew(true);\n }\n }\n },\n [id, loadItems, checkForUpdates, snapStates.settings.autoRefresh],\n );\n\n const lastHiddenTime = useRef();\n usePageVisibility(\n (visible) => {\n if (visible) {\n const timeDiff = Date.now() - lastHiddenTime.current;\n if (!lastHiddenTime.current || timeDiff > 1000 * 3) {\n // 3 seconds\n loadOrCheckUpdates({\n disableIdleCheck: true,\n });\n }\n } else {\n lastHiddenTime.current = Date.now();\n }\n setVisible(visible);\n },\n [checkForUpdates, loadOrCheckUpdates, snapStates.settings.autoRefresh],\n );\n\n // checkForUpdates interval\n useInterval(\n loadOrCheckUpdates,\n visible && !showNew\n ? checkForUpdatesInterval * (nearReachStart ? 1 : 2)\n : null,\n );\n\n // const hiddenUI = scrollDirection === 'end' && !nearReachStart;\n\n return (\n \n {\n scrollableRef.current = node;\n jRef.current = node;\n kRef.current = node;\n oRef.current = node;\n }}\n tabIndex=\"-1\"\n >\n
\n
{\n if (!e.target.closest('a, button')) {\n scrollableRef.current?.scrollTo({\n top: 0,\n behavior: 'smooth',\n });\n }\n }}\n onDblClick={(e) => {\n if (!e.target.closest('a, button')) {\n loadItems(true);\n }\n }}\n class={uiState === 'loading' ? 'loading' : ''}\n >\n \n {items.length > 0 &&\n uiState !== 'loading' &&\n // !hiddenUI &&\n showNew && (\n {\n loadItems(true);\n scrollableRef.current?.scrollTo({\n top: 0,\n behavior: 'smooth',\n });\n }}\n >\n New posts\n \n )}\n \n {!!timelineStart && (\n
\n {timelineStart}\n
\n )}\n {!!items.length ? (\n <>\n
\n {items.map((status) => (\n \n ))}\n {showMore &&\n uiState === 'loading' &&\n (view === 'media' ? null : (\n <>\n \n \n \n \n \n \n >\n ))}\n \n {uiState === 'default' &&\n (showMore ? (\n
{\n if (inView) {\n loadItems();\n }\n }}\n >\n loadItems()}\n style={{ marginBlockEnd: '6em' }}\n >\n Show more…\n \n \n ) : (\n
The end.
\n ))}\n >\n ) : uiState === 'loading' ? (\n
\n {Array.from({ length: 5 }).map((_, i) =>\n view === 'media' ? (\n
\n ) : (\n \n \n \n ),\n )}\n \n ) : (\n uiState !== 'error' &&
{emptyText}
\n )}\n {uiState === 'error' && (\n
\n {errorText}\n \n \n loadItems(!items.length)}>\n Try again\n \n
\n )}\n
\n
\n \n );\n}\n\nfunction TimelineItem({\n status,\n instance,\n useItemID,\n // allowFilters,\n filterContext,\n view,\n showFollowedTags,\n}) {\n const { id: statusID, reblog, items, type, _pinned } = status;\n if (_pinned) useItemID = false;\n const actualStatusID = reblog?.id || statusID;\n const url = instance\n ? `/${instance}/s/${actualStatusID}`\n : `/s/${actualStatusID}`;\n let title = '';\n if (type === 'boosts') {\n title = `${items.length} Boosts`;\n } else if (type === 'pinned') {\n title = 'Pinned posts';\n }\n const isCarousel = type === 'boosts' || type === 'pinned';\n if (items) {\n const fItems = filteredItems(items, filterContext);\n if (isCarousel) {\n // Here, we don't hide filtered posts, but we sort them last\n fItems.sort((a, b) => {\n // if (a._filtered && !b._filtered) {\n // return 1;\n // }\n // if (!a._filtered && b._filtered) {\n // return -1;\n // }\n const aFiltered = isFiltered(a.filtered, filterContext);\n const bFiltered = isFiltered(b.filtered, filterContext);\n if (aFiltered && !bFiltered) {\n return 1;\n }\n if (!aFiltered && bFiltered) {\n return -1;\n }\n return 0;\n });\n return (\n \n \n {fItems.map((item) => {\n const { id: statusID, reblog, _pinned } = item;\n const actualStatusID = reblog?.id || statusID;\n const url = instance\n ? `/${instance}/s/${actualStatusID}`\n : `/s/${actualStatusID}`;\n if (_pinned) useItemID = false;\n return (\n \n \n {useItemID ? (\n \n ) : (\n \n )}\n \n \n );\n })}\n \n \n );\n }\n const manyItems = fItems.length > 3;\n return fItems.map((item, i) => {\n const { id: statusID, _differentAuthor } = item;\n const url = instance ? `/${instance}/s/${statusID}` : `/s/${statusID}`;\n const isMiddle = i > 0 && i < fItems.length - 1;\n const isSpoiler = item.sensitive && !!item.spoilerText;\n const showCompact =\n (!_differentAuthor && isSpoiler && i > 0) ||\n (manyItems &&\n isMiddle &&\n (type === 'thread' ||\n (type === 'conversation' &&\n !_differentAuthor &&\n !fItems[i - 1]._differentAuthor &&\n !fItems[i + 1]._differentAuthor)));\n const isStart = i === 0;\n const isEnd = i === fItems.length - 1;\n return (\n \n \n {showCompact ? (\n \n ) : useItemID ? (\n \n ) : (\n \n )}\n \n \n );\n });\n }\n\n const itemKey = `timeline-${statusID + _pinned}`;\n\n if (view === 'media') {\n return useItemID ? (\n \n ) : (\n \n );\n }\n\n return (\n \n \n {useItemID ? (\n \n ) : (\n \n )}\n \n \n );\n}\n\nfunction StatusCarousel({ title, class: className, children }) {\n const carouselRef = useRef();\n // const { reachStart, reachEnd, init } = useScroll({\n // scrollableRef: carouselRef,\n // direction: 'horizontal',\n // });\n const startButtonRef = useRef();\n const endButtonRef = useRef();\n // useScrollFn(\n // {\n // scrollableRef: carouselRef,\n // direction: 'horizontal',\n // init: true,\n // },\n // ({ reachStart, reachEnd }) => {\n // if (startButtonRef.current) startButtonRef.current.disabled = reachStart;\n // if (endButtonRef.current) endButtonRef.current.disabled = reachEnd;\n // },\n // [],\n // );\n // useEffect(() => {\n // init?.();\n // }, []);\n\n const [render, setRender] = useState(false);\n useEffect(() => {\n setTimeout(() => {\n setRender(true);\n }, 1);\n }, []);\n\n return (\n \n
\n {title} \n \n {\n carouselRef.current?.scrollBy({\n left: -Math.min(320, carouselRef.current?.offsetWidth),\n behavior: 'smooth',\n });\n }}\n >\n \n {' '}\n {\n carouselRef.current?.scrollBy({\n left: Math.min(320, carouselRef.current?.offsetWidth),\n behavior: 'smooth',\n });\n }}\n >\n \n \n \n \n
\n {\n if (startButtonRef.current)\n startButtonRef.current.disabled = inView;\n }}\n />\n {children[0]}\n {render && children.slice(1)}\n {\n if (endButtonRef.current) endButtonRef.current.disabled = inView;\n }}\n />\n \n
\n );\n}\n\nfunction TimelineStatusCompact({ status, instance }) {\n const snapStates = useSnapshot(states);\n const { id, visibility } = status;\n const statusPeekText = statusPeek(status);\n const sKey = statusKey(id, instance);\n return (\n \n {!!snapStates.statusThreadNumber[sKey] ? (\n \n \n {snapStates.statusThreadNumber[sKey]\n ? ` ${snapStates.statusThreadNumber[sKey]}/X`\n : ''}\n
\n ) : (\n \n \n
\n )}\n \n {statusPeekText}\n {status.sensitive && status.spoilerText && (\n <>\n {' '}\n \n \n \n >\n )}\n
\n \n );\n}\n\nfunction inBackground() {\n return !!document.querySelector('.deck-backdrop, #modal-container > *');\n}\n\nexport default Timeline;\n","import { MenuItem } from '@szhsin/react-menu';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { useSnapshot } from 'valtio';\n\nimport AccountInfo from '../components/account-info';\nimport EmojiText from '../components/emoji-text';\nimport Icon from '../components/icon';\nimport Link from '../components/link';\nimport Menu2 from '../components/menu2';\nimport Timeline from '../components/timeline';\nimport { api } from '../utils/api';\nimport pmem from '../utils/pmem';\nimport showToast from '../utils/show-toast';\nimport states from '../utils/states';\nimport { saveStatus } from '../utils/states';\nimport useTitle from '../utils/useTitle';\n\nconst LIMIT = 20;\nconst MIN_YEAR = 1983;\nconst MIN_YEAR_MONTH = `${MIN_YEAR}-01`; // Birth of the Internet\n\nconst supportsInputMonth = (() => {\n try {\n const input = document.createElement('input');\n input.setAttribute('type', 'month');\n return input.type === 'month';\n } catch (e) {\n return false;\n }\n})();\n\nasync function _isSearchEnabled(instance) {\n const { masto } = api({ instance });\n const results = await masto.v2.search.fetch({\n q: 'from:me',\n type: 'statuses',\n limit: 1,\n });\n return !!results?.statuses?.length;\n}\nconst isSearchEnabled = pmem(_isSearchEnabled);\n\nfunction AccountStatuses() {\n const snapStates = useSnapshot(states);\n const { id, ...params } = useParams();\n const [searchParams, setSearchParams] = useSearchParams();\n const month = searchParams.get('month');\n const excludeReplies = !searchParams.get('replies');\n const excludeBoosts = !!searchParams.get('boosts');\n const tagged = searchParams.get('tagged');\n const media = !!searchParams.get('media');\n const { masto, instance, authenticated } = api({ instance: params.instance });\n const { masto: currentMasto, instance: currentInstance } = api();\n const accountStatusesIterator = useRef();\n\n const allSearchParams = [month, excludeReplies, excludeBoosts, tagged, media];\n const [account, setAccount] = useState();\n const searchOffsetRef = useRef(0);\n useEffect(() => {\n searchOffsetRef.current = 0;\n }, allSearchParams);\n\n const sameCurrentInstance = useMemo(\n () => instance === currentInstance,\n [instance, currentInstance],\n );\n const [searchEnabled, setSearchEnabled] = useState(false);\n useEffect(() => {\n // Only enable for current logged-in instance\n // Most remote instances don't allow unauthenticated searches\n if (!sameCurrentInstance) return;\n if (!account?.acct) return;\n (async () => {\n const enabled = await isSearchEnabled(instance);\n console.log({ enabled });\n setSearchEnabled(enabled);\n })();\n }, [instance, sameCurrentInstance, account?.acct]);\n\n async function fetchAccountStatuses(firstLoad) {\n const isValidMonth = /^\\d{4}-[01]\\d$/.test(month);\n const isValidYear = month?.split?.('-')?.[0] >= MIN_YEAR;\n if (isValidMonth && isValidYear) {\n if (!account) {\n return {\n value: [],\n done: true,\n };\n }\n const [_year, _month] = month.split('-');\n const monthIndex = parseInt(_month, 10) - 1;\n // YYYY-MM (no day)\n // Search options:\n // - from:account\n // - after:YYYY-MM-DD (non-inclusive)\n // - before:YYYY-MM-DD (non-inclusive)\n\n // Last day of previous month\n const after = new Date(_year, monthIndex, 0);\n const afterStr = `${after.getFullYear()}-${(after.getMonth() + 1)\n .toString()\n .padStart(2, '0')}-${after.getDate().toString().padStart(2, '0')}`;\n // First day of next month\n const before = new Date(_year, monthIndex + 1, 1);\n const beforeStr = `${before.getFullYear()}-${(before.getMonth() + 1)\n .toString()\n .padStart(2, '0')}-${before.getDate().toString().padStart(2, '0')}`;\n console.log({\n month,\n _year,\n _month,\n monthIndex,\n after,\n before,\n afterStr,\n beforeStr,\n });\n\n let limit;\n if (firstLoad) {\n limit = LIMIT + 1;\n searchOffsetRef.current = 0;\n } else {\n limit = LIMIT + searchOffsetRef.current + 1;\n searchOffsetRef.current += LIMIT;\n }\n\n const searchResults = await masto.v2.search.fetch({\n q: `from:${account.acct} after:${afterStr} before:${beforeStr}`,\n type: 'statuses',\n limit,\n offset: searchOffsetRef.current,\n });\n if (searchResults?.statuses?.length) {\n const value = searchResults.statuses.slice(0, LIMIT);\n value.forEach((item) => {\n saveStatus(item, instance);\n });\n const done = searchResults.statuses.length <= LIMIT;\n return { value, done };\n } else {\n return { value: [], done: true };\n }\n }\n\n const results = [];\n if (firstLoad) {\n const { value } = await masto.v1.accounts\n .$select(id)\n .statuses.list({\n pinned: true,\n })\n .next();\n if (value?.length && !tagged && !media) {\n const pinnedStatuses = value.map((status) => {\n saveStatus(status, instance);\n return {\n ...status,\n _pinned: true,\n };\n });\n if (pinnedStatuses.length >= 3) {\n const pinnedStatusesIds = pinnedStatuses.map((status) => status.id);\n results.push({\n id: pinnedStatusesIds,\n items: pinnedStatuses,\n type: 'pinned',\n });\n } else {\n results.push(...pinnedStatuses);\n }\n }\n }\n if (firstLoad || !accountStatusesIterator.current) {\n accountStatusesIterator.current = masto.v1.accounts\n .$select(id)\n .statuses.list({\n limit: LIMIT,\n exclude_replies: excludeReplies,\n exclude_reblogs: excludeBoosts,\n only_media: media,\n tagged,\n });\n }\n const { value, done } = await accountStatusesIterator.current.next();\n if (value?.length) {\n results.push(...value);\n\n value.forEach((item) => {\n saveStatus(item, instance);\n });\n }\n return {\n value: results,\n done,\n };\n }\n\n const [featuredTags, setFeaturedTags] = useState([]);\n useTitle(\n account?.acct\n ? `${account?.displayName ? account.displayName + ' ' : ''}@${\n account.acct\n }${\n !excludeReplies\n ? ' (+ Replies)'\n : excludeBoosts\n ? ' (- Boosts)'\n : tagged\n ? ` (#${tagged})`\n : media\n ? ' (Media)'\n : month\n ? ` (${new Date(month).toLocaleString('default', {\n month: 'long',\n year: 'numeric',\n })})`\n : ''\n }`\n : 'Account posts',\n '/:instance?/a/:id',\n );\n\n const fetchAccountPromiseRef = useRef();\n const fetchAccount = useCallback(() => {\n const fetchPromise =\n fetchAccountPromiseRef.current || masto.v1.accounts.$select(id).fetch();\n fetchAccountPromiseRef.current = fetchPromise;\n return fetchPromise;\n }, [id, masto]);\n\n useEffect(() => {\n (async () => {\n try {\n const acc = await fetchAccount();\n console.log(acc);\n setAccount(acc);\n } catch (e) {\n console.error(e);\n }\n try {\n const featuredTags = await masto.v1.accounts\n .$select(id)\n .featuredTags.list();\n console.log({ featuredTags });\n setFeaturedTags(featuredTags);\n } catch (e) {\n console.error(e);\n }\n })();\n }, [id]);\n\n const { displayName, acct, emojis } = account || {};\n\n const accountInfoMemo = useMemo(() => {\n const cachedAccount = snapStates.accounts[`${id}@${instance}`];\n return (\n \n );\n }, [id, instance, authenticated, fetchAccount]);\n\n const filterBarRef = useRef();\n const TimelineStart = useMemo(() => {\n const filtered =\n !excludeReplies || excludeBoosts || tagged || media || !!month;\n\n return (\n <>\n {accountInfoMemo}\n \n {filtered ? (\n \n \n \n ) : (\n \n )}\n {\n if (excludeReplies) {\n showToast('Showing post with replies');\n }\n }}\n class={excludeReplies ? '' : 'is-active'}\n >\n + Replies\n \n {\n if (!excludeBoosts) {\n showToast('Showing posts without boosts');\n }\n }}\n class={!excludeBoosts ? '' : 'is-active'}\n >\n - Boosts\n \n {\n if (!media) {\n showToast('Showing posts with media');\n }\n }}\n class={media ? 'is-active' : ''}\n >\n Media\n \n {featuredTags.map((tag) => (\n {\n if (tagged !== tag.name) {\n showToast(`Showing posts tagged with #${tag.name}`);\n }\n }}\n class={tagged === tag.name ? 'is-active' : ''}\n >\n \n # \n {tag.name}\n \n {\n // The count differs based on instance 😅\n }\n {/* {tag.statusesCount} */}\n \n ))}\n {searchEnabled &&\n (supportsInputMonth ? (\n \n \n {\n const { value, validity } = e.currentTarget;\n if (!validity.valid) return;\n setSearchParams(\n value\n ? {\n month: value,\n }\n : {},\n );\n const [year, month] = value.split('-');\n const monthIndex = parseInt(month, 10) - 1;\n const date = new Date(year, monthIndex);\n showToast(\n `Showing posts in ${date.toLocaleString('default', {\n month: 'long',\n year: 'numeric',\n })}`,\n );\n }}\n />\n \n ) : (\n // Fallback to for month and for year\n {\n const { value, validity } = e;\n if (!validity.valid) return;\n setSearchParams(\n value\n ? {\n month: value,\n }\n : {},\n );\n }}\n />\n ))}\n
\n >\n );\n }, [\n id,\n instance,\n authenticated,\n featuredTags,\n searchEnabled,\n ...allSearchParams,\n ]);\n\n useEffect(() => {\n // Focus on .is-active\n const active = filterBarRef.current?.querySelector('.is-active');\n if (active) {\n console.log('active', active, active.offsetLeft);\n filterBarRef.current.scrollTo({\n behavior: 'smooth',\n left:\n active.offsetLeft -\n (filterBarRef.current.offsetWidth - active.offsetWidth) / 2,\n });\n }\n }, [featuredTags, searchEnabled, ...allSearchParams]);\n\n const accountInstance = useMemo(() => {\n if (!account?.url) return null;\n const domain = new URL(account.url).hostname;\n return domain;\n }, [account]);\n const sameInstance = instance === accountInstance;\n const allowSwitch = !!account && !sameInstance;\n\n return (\n