@serifpersia/dango 3.9.2 → 3.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/client/dist/assets/{AnimeCard-DV3CayVB.js → AnimeCard-BOrGtplc.js} +1 -1
- package/client/dist/assets/{AnimeInfo-C_yN40WV.js → AnimeInfo-C-PPfut4.js} +1 -1
- package/client/dist/assets/{AnimeInfoPage-Dr9zOOq1.js → AnimeInfoPage-BFY38gcp.js} +2 -2
- package/client/dist/assets/{Asmr-BzVhO0PK.js → Asmr-CRt4Q_2a.js} +1 -1
- package/client/dist/assets/{AsmrPopup-CfCdTvhx.js → AsmrPopup-Bg0CeGCm.js} +1 -1
- package/client/dist/assets/{AsmrResetProgressModal-CLjzhb4H.js → AsmrResetProgressModal-ij785NHe.js} +1 -1
- package/client/dist/assets/{Home-wtyG5fKA.js → Home-BFjoIVUt.js} +1 -1
- package/client/dist/assets/{Insights-DGTqzxXr.js → Insights-Cd3fz8RQ.js} +1 -1
- package/client/dist/assets/{LibraryListPage-DhsV2n64.js → LibraryListPage-BbSb5u6S.js} +1 -1
- package/client/dist/assets/{ListeningList-BPD9igfn.js → ListeningList-CncJ_BUB.js} +1 -1
- package/client/dist/assets/{Manga-ClgoT4qk.js → Manga-BBi76zXr.js} +1 -1
- package/client/dist/assets/{MangaInfoPage-B8fttN1T.js → MangaInfoPage-DgDDd23Z.js} +1 -1
- package/client/dist/assets/{MangaReadPage-BTAVFeJH.js → MangaReadPage-DUxP_V9q.js} +1 -1
- package/client/dist/assets/{MangaResetProgressModal-CshoUUBm.js → MangaResetProgressModal-CdLYwWHZ.js} +1 -1
- package/client/dist/assets/{Mature-DAgfZt9Q.js → Mature-BACq3Kc4.js} +1 -1
- package/client/dist/assets/{MatureConsentModal-BhpY2wdn.js → MatureConsentModal-yectlds9.js} +1 -1
- package/client/dist/assets/{MediaCard-Czkyxqgb.js → MediaCard-CpvY5GuT.js} +1 -1
- package/client/dist/assets/{OptionListMenu-HllK8Z_u.js → OptionListMenu-BzRHsU6c.js} +1 -1
- package/client/dist/assets/Player-c3ZtthSI.js +56 -0
- package/client/dist/assets/{PlayerProvider-DGtOX3e2.js → PlayerProvider-Bll6epmz.js} +1 -1
- package/client/dist/assets/{PlayerSettings-9iBVbWNR.js → PlayerSettings-CjE5s-vS.js} +1 -1
- package/client/dist/assets/{QueueOptionsButton-C3ptca9g.js → QueueOptionsButton-5UHmZLgC.js} +1 -1
- package/client/dist/assets/{QueueRail-De3oifUM.js → QueueRail-o5cgpFg4.js} +1 -1
- package/client/dist/assets/{ReadingList-Bco6T_Jh.js → ReadingList-Q1-e3_GW.js} +1 -1
- package/client/dist/assets/{ResetProgressModal-Cx1SaMad.js → ResetProgressModal-TMqEVVii.js} +1 -1
- package/client/dist/assets/{Search-B6dgK2Zu.js → Search-ByFLr1Ki.js} +1 -1
- package/client/dist/assets/{Settings-DvOx960h.js → Settings-O0h8SHQu.js} +1 -1
- package/client/dist/assets/{SkeletonGrid-B2s8ytI8.js → SkeletonGrid-DXPv28BD.js} +1 -1
- package/client/dist/assets/{Trackers-Bp-U_jYN.js → Trackers-DOnb92AU.js} +1 -1
- package/client/dist/assets/Tv-C-bNPNTQ.css +1 -0
- package/client/dist/assets/Tv-CZleItJh.js +4 -0
- package/client/dist/assets/{TvInfo-BiUMbdN7.js → TvInfo-DHSDQz21.js} +1 -1
- package/client/dist/assets/{TvPopup-DnwmyRRE.js → TvPopup-BCUEPv0r.js} +1 -1
- package/client/dist/assets/{TvSearch-C9VNflnp.js → TvSearch-D_6kW_NT.js} +1 -1
- package/client/dist/assets/{TvWatchlist-Bt39ymiP.js → TvWatchlist-CyOlz9IC.js} +1 -1
- package/client/dist/assets/{VirtualKeyboard-BSILqgeU.js → VirtualKeyboard-DhtUWsN_.js} +1 -1
- package/client/dist/assets/{WatchAlong-GtXJ-2Qq.js → WatchAlong-BE5l6tqm.js} +1 -1
- package/client/dist/assets/{WatchAlongPanel-CxkbtjKg.js → WatchAlongPanel-Brkp7UMD.js} +1 -1
- package/client/dist/assets/{Watchlist-CQ57yp82.js → Watchlist-JaLhOL0z.js} +1 -1
- package/client/dist/assets/{index-BYGDqzEf.js → index-CD7a-Eff.js} +2 -2
- package/client/dist/assets/{libraryInvalidation-CHW51Kbi.js → libraryInvalidation-nAOuYLiR.js} +1 -1
- package/client/dist/assets/{playbackCompletion-DrDOXJXe.js → playbackCompletion-BXBBtgdB.js} +1 -1
- package/client/dist/assets/{useAnimeInfoData-CZY3Ui-u.js → useAnimeInfoData-rUxvbr-T.js} +1 -1
- package/client/dist/assets/{useMangaLibrary-x8zL6mOh.js → useMangaLibrary-BEkb8jwc.js} +1 -1
- package/client/dist/assets/{useMangaPopup-DdrgbIw-.js → useMangaPopup-DR3qXoYv.js} +1 -1
- package/client/dist/assets/{useProviders-Dk2T31ho.js → useProviders-Cc8CTUYM.js} +1 -1
- package/client/dist/assets/{useTv-CDh-n25T.js → useTv-de0-A2mW.js} +1 -1
- package/client/dist/assets/{useTvLibrary-Dec7yfKF.js → useTvLibrary-BsGpheKM.js} +1 -1
- package/client/dist/assets/useWatchAlongPlayer-BZs3033g.js +10 -0
- package/client/dist/assets/useWatchAlongPlayer-Dk7zB7P4.css +1 -0
- package/client/dist/index.html +1 -1
- package/package.json +2 -2
- package/server/package.json +1 -1
- package/client/dist/assets/Player-BVGxVSGv.js +0 -56
- package/client/dist/assets/Tv-CDALArd3.css +0 -1
- package/client/dist/assets/Tv-t2tt4jji.js +0 -4
- package/client/dist/assets/useWatchAlongPlayer-D1o2zDEn.css +0 -1
- package/client/dist/assets/useWatchAlongPlayer-DpUPA4jD.js +0 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{d as r,u as e,S as me,A as Z,h as G,q as pe,T as Ee,p as Ke,g as Ce,_ as Ue}from"./vendor-core-DfaOB3Rn.js";import{b as fe,u as te}from"./vendor-query-BBT5_sHx.js";import{R as ee,S as J,U as E,V as ke,B as k,W as Fe,Q as U,d as $e,L as Ie,t as b,v as Le,o as We,J as Se,X,q as H,Y as Ne,Z as He,_ as Be,u as je,e as Qe,$ as Ve,K as ce,p as Ye,a0 as Je,a1 as Xe}from"./index-BYGDqzEf.js";import{I as j}from"./vendor-icons-DrybRNxP.js";import{T as F}from"./ToggleSwitch-CN_ppEc9.js";import{l as Ze,s as et}from"./playbackCompletion-DrDOXJXe.js";import{M as tt}from"./MatureConsentModal-BhpY2wdn.js";const at="_sectionCard_1vuib_1",nt="_dangerCard_1vuib_20",rt="_settingRow_1vuib_31",_={sectionCard:at,dangerCard:nt,settingRow:rt};function st(){const{data:t}=fe(ee),{data:i}=fe({queryKey:["profiles"],queryFn:()=>J("/api/profiles/status"),enabled:!!t?.owner}),l=te(),[g,f]=r(null),[d,C]=r(""),[m,o]=r(""),[a,p]=r(""),[y,u]=r(""),[L,c]=r(""),[v,T]=r(!1),[I,A]=r(null),P=async s=>{T(!0),c("");try{await J("/api/profiles/update",{method:"POST",body:JSON.stringify(s)}),await l.invalidateQueries({queryKey:ee.queryKey}),C(""),o(""),c("Profile saved")}catch(N){c(N.message)}finally{T(!1)}};return t?e("section",{className:_.sectionCard,children:[e("h3",{children:"Your profile"}),e("p",{children:"Keep using this profile, rename it, or add another person with their own library and connections."}),e("div",{className:E.avatarRow,children:[e(ke,{image:t.image,name:t.name}),e("label",{className:E.uploadButton,children:[e(j,{name:"upload"}),e("span",{children:"Upload image"}),e("input",{className:E.fileInput,type:"file",accept:"image/png,image/jpeg,image/webp,image/gif",disabled:v,onChange:async s=>{const N=s.currentTarget.files?.[0];if(s.currentTarget.value="",!N)return;if(N.size>2*1024*1024){c("Image must be smaller than 2 MB");return}const R=new FileReader;R.onerror=()=>c("Could not read image"),R.onload=()=>{P({avatar:R.result})},R.readAsDataURL(N)}})]}),t.avatar&&e(k,{variant:"secondary",disabled:v,onClick:()=>P({avatar:null}),children:"Clear uploaded image"})]}),e("p",{children:"Your uploaded image takes priority, followed by your active cloud account image, then the default user icon."}),e("form",{className:E.form,onSubmit:s=>{s.preventDefault(),P({name:g??t.name})},children:[e("label",{className:E.field,children:["Profile name",e("input",{value:g??t.name,maxLength:60,required:!0,onChange:s=>f(s.currentTarget.value)})]}),e(k,{type:"submit",disabled:v,children:"Save name"})]}),e("form",{className:E.form,onSubmit:s=>{s.preventDefault(),P({password:d,currentPassword:m})},children:[t.protected&&e("label",{className:E.field,children:["Current password",e("input",{type:"password",autoComplete:"current-password",value:m,required:!0,maxLength:256,onChange:s=>o(s.currentTarget.value)})]}),e("label",{className:E.field,children:[t.protected?"New password (empty removes protection)":"Protect this profile",e("input",{type:"password",autoComplete:"new-password",value:d,minLength:8,maxLength:256,onChange:s=>C(s.currentTarget.value)})]}),e(k,{type:"submit",disabled:v,children:"Save password"})]}),e(k,{variant:"secondary",disabled:v,onClick:async()=>{T(!0);try{await J("/api/profiles/logout",{method:"POST"}),Fe()}catch(s){c(s.message),T(!1)}},children:"Switch profile / sign out"}),t.owner&&e("form",{className:E.form,onSubmit:async s=>{s.preventDefault(),T(!0),c("");try{await J("/api/profiles/create",{method:"POST",body:JSON.stringify({name:a,password:y})}),p(""),u(""),await l.invalidateQueries({queryKey:["profiles"]}),c("Profile created. Sign out to switch to it.")}catch(N){c(N.message)}finally{T(!1)}},children:[e("h3",{children:"Add another profile"}),e("p",{children:"Protect your owner profile first. New profiles start empty and do not inherit your accounts. A profile without a password is accessible to anyone who passes the LAN lock."}),e("label",{className:E.field,children:["Name",e("input",{required:!0,maxLength:60,value:a,onChange:s=>p(s.currentTarget.value)})]}),e("label",{className:E.field,children:["Password (optional)",e("input",{type:"password",autoComplete:"new-password",minLength:8,maxLength:256,value:y,onChange:s=>u(s.currentTarget.value)})]}),e(k,{type:"submit",disabled:v||!t.protected,children:"Create profile"})]}),t.owner&&i?.profiles.some(s=>!s.owner)&&e(me,{children:[e("h3",{children:"Other profiles"}),e("ul",{className:E.profileList,children:i.profiles.filter(s=>!s.owner).map(s=>e("li",{children:[e("span",{className:E.smallAvatar,children:e(ke,{image:s.avatar??s.cloudAvatar,name:s.name})}),e("span",{className:E.profileName,children:s.name}),e(k,{variant:"danger",size:"sm",disabled:v,onClick:()=>{c(""),A(s)},children:"Delete"})]},s.id))})]}),e(U,{isOpen:!!I,onClose:v?void 0:()=>A(null),title:"Delete profile?",width:"sm",footer:e(me,{children:[e(k,{variant:"secondary",disabled:v,onClick:()=>A(null),children:"Cancel"}),e(k,{variant:"danger",loading:v,onClick:async()=>{if(I){T(!0);try{await J("/api/profiles/delete",{method:"POST",body:JSON.stringify({id:I.id,confirm:!0})}),await l.invalidateQueries({queryKey:["profiles"]}),A(null),c("Profile deleted. Local files will be removed when Dango restarts.")}catch(s){c(s.message),A(null)}finally{T(!1)}}},children:"Delete profile"})]}),children:[e("p",{children:["Delete ",e("strong",{children:I?.name}),"? This signs them out immediately. Their local libraries, settings and connections will be removed when Dango next restarts."]}),e("p",{children:"Cloud backups and tracker lists will stay intact. Export any library you want to keep before deleting."})]}),L&&e("p",{role:"status",children:L})]}):null}const de={"title-preference-container":"_title-preference-container_sdqgs_1","toggle-button":"_toggle-button_sdqgs_21","toggle-label":"_toggle-label_sdqgs_51"},ue=["name","nativeName","englishName"],he={name:"Default (Romaji)",nativeName:"Native",englishName:"English"},it=()=>{const{titlePreference:t,setTitlePreference:i,loading:l}=$e(),g=Ie(),[f,d]=r(he[t]),[C,m]=r(!1),o=Z(null);G(()=>{l||d(he[t])},[t,l]);const a=async()=>{if(C)return;m(!0);const y=(ue.indexOf(t)+1)%ue.length,u=ue[y],L=he[u];o.current&&(o.current.style.transform="translateX(-100%)",o.current.style.opacity="0"),setTimeout(async()=>{d(L),i(u),o.current&&(o.current.style.transition="none",o.current.style.transform="translateX(100%)",o.current.style.opacity="0",o.current.offsetWidth,o.current.style.transition="transform 0.3s ease-out, opacity 0.3s ease-out",o.current.style.transform="translateX(0)",o.current.style.opacity="1");try{await g.mutateAsync({key:"titlePreference",value:u})}catch(c){console.error("Error saving title preference:",c)}finally{m(!1)}},300)};return l?e("p",{children:"Loading title preference..."}):e("div",{className:de["title-preference-container"],children:[e("h4",{children:"Anime Title Display Preference"}),e("button",{onClick:a,className:de["toggle-button"],disabled:C,children:e("span",{ref:o,className:de["toggle-label"],children:f})})]})},ot="_settingsHeader_gfwoa_1",lt="_pageTitle_gfwoa_6",ct="_pageSubtitle_gfwoa_14",dt="_settingsLayout_gfwoa_20",ut="_sidebar_gfwoa_27",ht="_sidebarIndicator_gfwoa_35",gt="_sidebarItem_gfwoa_50",mt="_active_gfwoa_72",pt="_mainContent_gfwoa_80",ft="_tabContent_gfwoa_85",yt="_settingItem_gfwoa_103",vt="_shortcutContainer_gfwoa_108",wt="_shortcutGroup_gfwoa_115",bt="_shortcutGroupTitle_gfwoa_121",Ct="_shortcutGrid_gfwoa_130",kt="_shortcutCard_gfwoa_136",St="_controls_gfwoa_170",Nt="_status_gfwoa_176",h={settingsHeader:ot,pageTitle:lt,pageSubtitle:ct,settingsLayout:dt,sidebar:ut,sidebarIndicator:ht,sidebarItem:gt,active:mt,mainContent:pt,tabContent:ft,settingItem:yt,shortcutContainer:vt,shortcutGroup:wt,shortcutGroupTitle:bt,shortcutGrid:Ct,shortcutCard:kt,controls:St,status:Nt},_t="_title_tm30b_11",Tt="_signIn_tm30b_18",It="_userInfo_tm30b_25",Lt="_warning_tm30b_47",Pt="_formGroup_tm30b_54",xt="_label_tm30b_58",Rt="_inputWrapper_tm30b_68",Dt="_input_tm30b_68",At="_select_tm30b_92",Ot="_actions_tm30b_109",Gt="_hr_tm30b_117",w={title:_t,signIn:Tt,userInfo:It,warning:Lt,formGroup:Pt,label:xt,inputWrapper:Rt,input:Dt,select:At,actions:Ot,hr:Gt},Mt=()=>{const t=te(),[i,l]=r(!0),[g,f]=r(!1),[d,C]=r(!1),[m,o]=r(null),[a,p]=r({status:"idle"}),[y,u]=r(!1),[L,c]=r(""),[v,T]=r(!1),I=Z(null),[A,P]=r({show:!1,message:"",type:"info"}),s=()=>{I.current&&(window.clearInterval(I.current),I.current=null)},N=pe(S=>{C(S.authenticated),o(S.user||S.device.user||null),p(S.device),u(!!S.hasCustomClientId)},[]),R=pe(async()=>{const S=await b.auth.githubStatus.query();N(S)},[N]),K=async()=>{try{const S=await b.auth.githubPoll.query();p(S),S.status==="success"?(s(),await t.invalidateQueries({queryKey:ee.queryKey}),await R(),P({show:!0,message:"GitHub authentication complete. Sync has been initialized.",type:"success"})):S.status==="error"&&(s(),P({show:!0,message:S.error||"GitHub authentication failed.",type:"error"}))}catch{s(),P({show:!0,message:"Failed to poll GitHub authentication status.",type:"error"})}},x=(S=5)=>{s(),I.current=window.setInterval(K,Math.max(S,5)*1e3)};G(()=>(R().catch(()=>{P({show:!0,message:"Failed to load GitHub sync status.",type:"error"})}).finally(()=>l(!1)),s),[R]);const M=async()=>{f(!0);try{const S=await b.auth.githubStart.mutate();p(S),x(S.verification?.interval)}catch(S){P({show:!0,message:S instanceof Error?S.message:"Failed to start GitHub authentication.",type:"error"})}finally{f(!1)}},q=async()=>{try{await b.auth.githubLogout.mutate(),await t.invalidateQueries({queryKey:ee.queryKey}),C(!1),o(null),p({status:"idle"}),P({show:!0,message:"Signed out of GitHub sync.",type:"success"})}catch{P({show:!0,message:"Failed to sign out of GitHub.",type:"error"})}},$=async()=>{T(!0);try{await b.auth.saveGithubAuth.mutate({clientId:L}),c(""),await R(),P({show:!0,message:"Custom GitHub auth saved.",type:"success"})}catch{P({show:!0,message:"Failed to save override.",type:"error"})}finally{T(!1)}},Q=async()=>{T(!0);try{await b.auth.saveGithubAuth.mutate({clientId:""}),c(""),await R(),P({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{P({show:!0,message:"Failed to clear override.",type:"error"})}finally{T(!1)}};return i?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:_.sectionCard,children:[e("h3",{className:w.title,children:"GitHub Cloud Sync"}),e("p",{className:w.signIn,children:"Sync local data through a private GitHub repository named dango-sync-data."}),d&&m?e("div",{className:w.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:m.name||m.login})]}),e(k,{variant:"danger",onClick:q,children:"Sign Out"})]}):e("div",{className:w.signIn,children:e(k,{onClick:M,disabled:g||a.status==="pending",children:g||a.status==="pending"?"Waiting for GitHub...":"Sign in with GitHub"})}),a.status==="pending"&&a.verification&&e(me,{children:[e("hr",{className:w.hr}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Verification URL"}),e("div",{className:w.inputWrapper,children:[e("input",{className:w.input,value:a.verification.verification_uri,readOnly:!0}),e(k,{onClick:()=>{const S=a.verification?.verification_uri;S&&/^https?:\/\//i.test(S)&&window.open(S,"_blank","noopener,noreferrer")},children:"Open"})]})]}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Device Code"}),e("input",{className:w.input,value:a.verification.user_code,readOnly:!0})]})]}),a.status==="error"&&e("p",{className:w.warning,children:a.error}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",y?"(override active)":""]}),e("div",{className:w.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:w.label,children:"Client ID (optional)"}),e("input",{className:w.input,value:L,onChange:S=>c(S.currentTarget.value),placeholder:"Your GitHub OAuth app ID"})]}),e("div",{className:w.actions,children:[e(k,{onClick:$,disabled:v,children:"Save override"}),e(k,{variant:"secondary",onClick:Q,disabled:v,children:"Use dango defaults"})]})]}),e(U,{isOpen:A.show,onClose:()=>P(S=>({...S,show:!1})),width:"sm",children:[e(U.Body,{children:e("p",{children:A.message})}),e(U.Actions,{children:e(k,{onClick:()=>P(S=>({...S,show:!1})),children:"OK"})})]})]})},qt=()=>{const[t,i]=r(!0),[l,g]=r(null),[f,d]=r(!1),[C,m]=r(!1),[o,a]=r(""),[p,y]=r(""),[u,L]=r(""),[c,v]=r(!1),[T,I]=r({show:!1,message:"",type:"info"}),A=async()=>{try{const M=await b.auth.user.query();g(M?.email?M:null)}catch{g(null)}},P=async()=>{try{const[x,M]=await Promise.all([b.auth.configStatus.query(),b.auth.googleAuth.query()]);d(!!x.hasConfig),m(!!(M.hasCustomWorkerUrl||M.hasCustomClientId||M.hasClientSecret))}catch(x){console.error("Failed to fetch config status",x)}};G(()=>{(async()=>{i(!0),await Promise.all([A(),P()]);try{new URLSearchParams(window.location.search).get("google_auth")==="success"&&(await A(),window.history.replaceState(null,"",window.location.pathname))}catch{}i(!1)})();const M=q=>{q.origin===window.location.origin&&typeof q.data=="object"&&q.data!==null&&q.data.type==="GOOGLE_AUTH_SUCCESS"&&(g(q.data.user),window.location.reload())};return window.addEventListener("message",M),()=>window.removeEventListener("message",M)},[]);const s=async()=>{try{const x=await b.auth.googleLogin.mutate();if(x.authenticated){window.location.reload();return}if(x.url){if(typeof window.DangoBridge<"u"){window.location.href=x.url;return}const q=600,$=700,Q=window.innerWidth/2-q/2,S=window.innerHeight/2-$/2;window.open(x.url,"GoogleAuth",`width=${q},height=${$},top=${S},left=${Q}`)}else throw new Error("Auth URL not available")}catch{I({show:!0,message:"Authentication failed. Ensure server is configured correctly.",type:"error"})}},N=async()=>{try{await b.auth.logout.mutate(),g(null),I({show:!0,message:"Successfully signed out.",type:"success"}),window.location.reload()}catch(x){console.error("Sign out failed",x),I({show:!0,message:"Failed to sign out.",type:"error"})}},R=async()=>{v(!0);try{await b.auth.saveGoogleAuth.mutate({workerUrl:o,clientId:p,clientSecret:u}),a(""),y(""),L(""),await P(),I({show:!0,message:"Custom auth saved. Restart may be required.",type:"success"})}catch{I({show:!0,message:"Failed to save override.",type:"error"})}finally{v(!1)}},K=async()=>{v(!0);try{await b.auth.saveGoogleAuth.mutate({workerUrl:"",clientId:"",clientSecret:""}),a(""),y(""),L(""),await P(),I({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{I({show:!0,message:"Failed to clear override.",type:"error"})}finally{v(!1)}};return t?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:_.sectionCard,children:[e("h3",{className:w.title,children:"Google Drive Sync"}),l?e("div",{className:w.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:l.name})," (",l.email,")"]}),e(k,{variant:"danger",onClick:N,children:"Sign Out"})]}):e("div",{className:w.signIn,children:[e("p",{children:"Sign in with your Google account to enable synchronization features."}),e(k,{onClick:s,disabled:!f,children:"Sign in with Google"}),!f&&e("p",{className:w.warning,children:"Google sync is not configured on the server."})]}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",C?"(override active)":""]}),e("div",{className:w.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:w.label,children:"Worker URL (optional)"}),e("input",{className:w.input,value:o,onChange:x=>a(x.currentTarget.value),placeholder:"https://your-worker.workers.dev"})]}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Client ID (optional)"}),e("input",{className:w.input,value:p,onChange:x=>y(x.currentTarget.value),placeholder:"Your Google OAuth client ID"})]}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Client Secret (optional)"}),e("input",{type:"password",className:w.input,value:u,onChange:x=>L(x.currentTarget.value),placeholder:"Your Google OAuth secret"})]}),e("div",{className:w.actions,children:[e(k,{onClick:R,disabled:c,children:"Save override"}),e(k,{variant:"secondary",onClick:K,disabled:c,children:"Use dango defaults"})]})]}),e(U,{isOpen:T.show,onClose:()=>I(x=>({...x,show:!1})),width:"sm",children:[e(U.Body,{children:e("p",{children:T.message})}),e(U.Actions,{children:e(k,{onClick:()=>I(x=>({...x,show:!1})),children:"OK"})})]})]})},zt="_settingItem_3qq0n_1",Et="_modalOverlay_3qq0n_6",Kt="_modal_3qq0n_6",Ut="_modalActions_3qq0n_41",Ft="_modalSecondary_3qq0n_47",$t="_modalPrimary_3qq0n_57",B={settingItem:zt,modalOverlay:Et,modal:Kt,modalActions:Ut,modalSecondary:Ft,modalPrimary:$t},Wt={anime:{heading:"Watchlist Preferences",blurb:"Customize your experience when managing your watchlist and series entries.",skipKey:"skipRemoveConfirmation",ignoreKey:"ignoreAdultContent",listOnlyKey:"cwWatchlistOnly",skipLabel:"Skip confirmation when removing from watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in watchlist",listNoun:"watchlist",continueNoun:"continue watching",adultCountUrl:"/api/continue-watching/adult-count",purgeUrl:"/api/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["allContinueWatching"]]},manga:{heading:"Reading List Preferences",blurb:"Customize your experience when managing your reading list and manga entries.",skipKey:"mangaSkipRemoveConfirmation",ignoreKey:"mangaIgnoreAdultContent",listOnlyKey:"mangaCwWatchlistOnly",skipLabel:"Skip confirmation when removing from reading list",ignoreLabel:"Hide adult content from continue reading",listOnlyLabel:"Only show continue reading for manga in reading list",listNoun:"reading list",continueNoun:"continue reading",adultCountUrl:"/api/manga/continue-reading/adult-count",purgeUrl:"/api/manga/continue-reading/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue reading`,invalidateKeys:[["manga-continue-reading"]]},tv:{heading:"TV Watchlist Preferences",blurb:"Customize your experience when managing your TV watchlist and series entries.",skipKey:"tvSkipRemoveConfirmation",ignoreKey:"tvIgnoreAdultContent",listOnlyKey:"tvCwWatchlistOnly",skipLabel:"Skip confirmation when removing from TV watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in TV watchlist",listNoun:"TV watchlist",continueNoun:"continue watching",adultCountUrl:"/api/tv/continue-watching/adult-count",purgeUrl:"/api/tv/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["tv-continue-watching"]]},asmr:{heading:"Listening List Preferences",blurb:"Customize your experience when managing your listening list and work entries.",skipKey:"asmrSkipRemoveConfirmation",ignoreKey:"asmrIgnoreAdultContent",listOnlyKey:"asmrCwWatchlistOnly",skipLabel:"Skip confirmation when removing from listening list",ignoreLabel:"Hide adult content from continue listening",listOnlyLabel:"Only show continue listening for works in listening list",listNoun:"listening list",continueNoun:"continue listening",adultCountUrl:"/api/asmr/continue-listening/adult-count",purgeUrl:"/api/asmr/continue-listening/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue listening`,invalidateKeys:[["asmr-continue-listening"]]}},Ht=(t,i)=>{if(t==null)return i;const l=String(t);return l==="true"||l==="1"?!0:l==="false"||l==="0"?!1:i},_e=(t,i,l)=>{const[g,f]=r(i),[d,C]=r(!1),m=te();return G(()=>{(async()=>{try{const p=await b.settings.getByKey.query({key:t});f(Ht(p.value,i))}catch(p){console.error("Failed to fetch setting",p)}})()},[t,i]),{value:g,setValue:f,isUpdating:d,toggle:async()=>{if(d)return;C(!0);const a=!g;f(a);try{await b.settings.set.mutate({key:t,value:a});for(const p of l)m.invalidateQueries({queryKey:p})}catch(p){console.error("Error saving setting:",p),f(!a)}finally{C(!1)}}}},Bt=()=>{const{contentType:t}=Le(),i=Wt[t],[l,g]=r(!1),[f,d]=r(!0),[C,m]=r(!1),o=_e(i.ignoreKey,!0,i.invalidateKeys),a=_e(i.listOnlyKey,!1,i.invalidateKeys),[p,y]=r(null),[u,L]=r(!1),c=te(),v=We();G(()=>{d(!0),(async()=>{try{const N=await b.settings.getByKey.query({key:i.skipKey});String(N.value)==="true"||String(N.value)==="1"?g(!0):g(!1)}catch(N){console.error("Failed to fetch setting",N)}finally{d(!1)}})()},[i.skipKey]);const T=async()=>{if(C)return;m(!0);const s=!l;g(s);try{await b.settings.set.mutate({key:i.skipKey,value:s})}catch(N){console.error("Error saving setting:",N),g(!s)}finally{m(!1)}},I=async()=>{if(!o.isUpdating){if(o.value)try{let s;if(t==="anime"?s=(await b.continueWatching.adultCount.query()).count:t==="manga"?s=(await b.mangaProgress.adultCount.query()).count:t==="asmr"?s=(await b.asmrProgress.adultCount.query()).count:s=(await b.tvProgress.adultCount.query()).count,typeof s=="number"&&s>0){y(s);return}}catch(s){console.error("Failed to fetch adult count",s)}o.toggle()}},A=()=>{y(null),o.toggle()},P=async()=>{if(!u){L(!0);try{let s;t==="anime"?s=(await b.continueWatching.purgeAdult.mutate()).removed:t==="manga"?s=(await b.mangaProgress.purgeAdult.mutate()).removed:t==="asmr"?s=(await b.asmrProgress.purgeAdult.mutate()).removed:s=(await b.tvProgress.purgeAdult.mutate()).removed,Se.success(i.purgeDoneText(s??0));for(const N of i.invalidateKeys)c.invalidateQueries({queryKey:N});t==="anime"&&c.invalidateQueries(v.continueWatching.pathFilter()),t==="manga"&&c.invalidateQueries(v.mangaProgress.pathFilter()),t==="asmr"&&c.invalidateQueries(v.asmrProgress.pathFilter()),t==="tv"&&c.invalidateQueries(v.tvProgress.pathFilter())}catch(s){console.error("Failed to purge adult entries",s),Se.error("Failed to remove adult entries")}finally{L(!1),y(null)}o.toggle()}};return f?e("div",{children:"Loading settings..."}):e("div",{className:_.sectionCard,children:[e("h3",{children:i.heading}),e("p",{children:i.blurb}),e("div",{className:B.settingItem,children:e("div",{className:_.settingRow,children:[e("label",{htmlFor:"skip-confirmation-toggle",children:i.skipLabel}),e(F,{isChecked:l,onChange:T,id:"skip-confirmation-toggle",disabled:C})]})}),e("div",{className:B.settingItem,children:e("div",{className:_.settingRow,children:[e("label",{htmlFor:"ignore-adult-toggle",children:i.ignoreLabel}),e(F,{isChecked:o.value,onChange:I,id:"ignore-adult-toggle",disabled:o.isUpdating})]})}),e("div",{className:B.settingItem,children:e("div",{className:_.settingRow,children:[e("label",{htmlFor:"cw-watchlist-only-toggle",children:i.listOnlyLabel}),e(F,{isChecked:a.value,onChange:a.toggle,id:"cw-watchlist-only-toggle",disabled:a.isUpdating})]})}),p!==null&&e("div",{className:B.modalOverlay,onClick:()=>y(null),children:e("div",{className:B.modal,onClick:s=>s.stopPropagation(),children:[e("h4",{children:"Show adult entries?"}),e("p",{children:[p," adult ",p===1?"entry":"entries"," not in your"," ",i.listNoun," ",p===1?"is":"are"," currently hidden from"," ",i.continueNoun,". You can purge ",p===1?"it":"them"," from the database instead of showing ",p===1?"it":"them","."]}),e("div",{className:B.modalActions,children:[e("button",{type:"button",className:B.modalSecondary,onClick:A,disabled:u,children:"Show them"}),e("button",{type:"button",className:B.modalPrimary,onClick:P,disabled:u,children:u?"Purging...":`Purge ${p}`})]})]})})]})},jt="_statsGrid_o4nf0_1",Qt="_statCard_o4nf0_8",Vt="_statLabel_o4nf0_18",Yt="_statValue_o4nf0_26",Jt="_statMeta_o4nf0_32",Xt="_statusBanner_o4nf0_38",Zt="_statusSuccess_o4nf0_49",ea="_statusUpdating_o4nf0_55",ta="_statusError_o4nf0_61",aa="_sha_o4nf0_67",na="_settingItem_o4nf0_74",ra="_settingTitle_o4nf0_79",sa="_settingSubtitle_o4nf0_85",ia="_actionsRow_o4nf0_92",D={statsGrid:jt,statCard:Qt,statLabel:Vt,statValue:Yt,statMeta:Jt,statusBanner:Xt,statusSuccess:Zt,statusUpdating:ea,statusError:ta,sha:aa,settingItem:na,settingTitle:ra,settingSubtitle:sa,actionsRow:ia},oa=()=>{const[t,i]=r(null),[l,g]=r(!0),[f,d]=r(!1),[C,m]=r(!1),o=Z(null),a=async()=>{try{const c=await b.settings.offlineDbInfo.query();return i(c),c}catch(c){console.error("Failed to fetch offline DB info:",c)}finally{g(!1)}return null};G(()=>(a(),()=>{o.current&&window.clearInterval(o.current)}),[]),G(()=>{t?.isRefreshing?o.current||(o.current=window.setInterval(async()=>{const c=await a();c&&!c.isRefreshing&&o.current&&(window.clearInterval(o.current),o.current=null)},2e3)):o.current&&(window.clearInterval(o.current),o.current=null)},[t?.isRefreshing]);const p=async()=>{if(!t||f)return;const c=!t.autoUpdateEnabled;d(!0),i({...t,autoUpdateEnabled:c});try{await b.settings.setOfflineDbAutoUpdate.mutate({enabled:c})}catch(v){console.error("Failed to update auto update setting:",v),i({...t,autoUpdateEnabled:!c})}finally{d(!1)}},y=async()=>{if(!(t?.isRefreshing||C)){m(!0);try{await b.settings.triggerOfflineDbUpdate.mutate(),i(c=>c?{...c,isRefreshing:!0,lastStatus:"updating",lastMessage:"Downloading database..."}:null)}catch(c){console.error("Failed to trigger offline DB update:",c)}finally{m(!1)}}},u=c=>{if(!c)return"Never";try{return new Date(c).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"})}catch{return c}},L=t?.isRefreshing||C;return e("div",{className:_.sectionCard,children:[e("h3",{children:"Offline Metadata Database"}),e("p",{children:"Local MAL to AniList ID map used for instant imports and metadata enrichment without hitting rate-limited APIs. Updates automatically every Saturday in the background."}),e("div",{className:D.statsGrid,children:[e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"MAL Mapped"}),e("span",{className:D.statValue,children:l?"-":(t?.totalMalMapped??0).toLocaleString()})]}),e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"Release"}),e("span",{className:D.statMeta,children:l?"-":t?.releaseTag??"Never"})]}),e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"Last Checked"}),e("span",{className:D.statMeta,children:l?"-":u(t?.lastCheckedAt??null)})]}),e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"Last Updated"}),e("span",{className:D.statMeta,children:l?"-":u(t?.lastUpdatedAt??null)})]})]}),t?.lastMessage&&e("div",{className:`${D.statusBanner} ${t.lastStatus==="failed"?D.statusError:t.lastStatus==="updating"?D.statusUpdating:D.statusSuccess}`,children:[e("span",{children:t.lastMessage}),t.contentSha256&&e("span",{className:D.sha,children:["sha:",t.contentSha256.slice(0,12)]})]}),e("div",{className:D.settingItem,children:e("div",{className:_.settingRow,children:[e("div",{children:[e("span",{className:D.settingTitle,children:"Weekly Automatic Updates (Saturdays)"}),e("div",{className:D.settingSubtitle,children:"Download and index new database releases in the background. Catches up on startup if the server was offline."})]}),e(F,{id:"offline-db-auto-update-toggle",isChecked:t?t.autoUpdateEnabled:!0,onChange:p,disabled:l||f})]})}),e("div",{className:D.actionsRow,children:e(k,{onClick:y,disabled:l||L,children:L?"Updating Database...":"Update Offline Database Now"})})]})},la="_status_1wbo0_1",ca="_warningText_1wbo0_7",da="_ackLabel_1wbo0_11",ge={status:la,warningText:ca,ackLabel:da},ua=()=>{const t=te(),[i,l]=r(!1),[g,f]=r(!1),[d,C]=r(!1),[m,o]=r(""),a=()=>{f(!1),o(""),l(!0)},p=()=>{d||(l(!1),f(!1))},y=async()=>{if(!(!g||d)){C(!0),o("");try{const u=await X("/api/database/clear",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({confirm:!0})}),L=await u.json();if(!u.ok)throw new Error(L.error||"Failed to clear database");const c=L.deleted,v=L.deletedManga,T=L.deletedTv,I=L.deletedAsmr,A=Object.values(c).reduce((R,K)=>R+(K||0),0)+Object.values(v??{}).reduce((R,K)=>R+(K||0),0)+Object.values(T??{}).reduce((R,K)=>R+(K||0),0)+Object.values(I??{}).reduce((R,K)=>R+(K||0),0),P=(v?.manga_library??0)+(v?.manga_progress??0),s=(T?.tv_library??0)+(T?.tv_progress??0),N=(I?.asmr_library??0)+(I?.asmr_progress??0);o(`Library cleared - ${c.watchlist??0} watchlist entries, ${P} manga rows, ${s} TV rows, ${N} ASMR rows and ${A} total rows removed.`),t.invalidateQueries({queryKey:[H.watchlist]}),t.invalidateQueries({queryKey:[H.continueWatching]}),t.invalidateQueries({queryKey:[H.mangaLibrary]}),t.invalidateQueries({queryKey:[H.mangaContinueReading]}),t.invalidateQueries({queryKey:[H.tvLibrary]}),t.invalidateQueries({queryKey:[H.tvContinueWatching]}),t.invalidateQueries({queryKey:[H.asmrLibrary]}),t.invalidateQueries({queryKey:[H.asmrContinueListening]}),l(!1)}catch(u){o(u.message)}finally{C(!1),f(!1)}}};return e("div",{className:`${_.sectionCard} ${_.dangerCard}`,children:[e("h3",{children:"Danger Zone"}),e("p",{children:"Permanently delete your library (watchlist, watched episodes, queue, cached show metadata, manga reading list and reading progress, TV watchlist and watch progress, ASMR listening list and listening progress) to start fresh. Your settings, sync state and the offline metadata cache are preserved."}),e(k,{variant:"danger",onClick:a,children:"Clear Library Data"}),m&&e("p",{className:ge.status,children:m}),e(U,{isOpen:i,onClose:p,title:"Clear library data?",width:"sm",children:[e(U.Body,{children:[e("p",{className:ge.warningText,children:"This permanently deletes everything in your library. It acts on the active database (dev or prod, per server config) and cannot be undone. Settings, sync state and the offline metadata cache are kept."}),e("label",{className:ge.ackLabel,children:[e("input",{type:"checkbox",checked:g,onChange:u=>f(u.currentTarget.checked),disabled:d}),e("span",{children:"I understand this permanently deletes my library"})]})]}),e(U.Actions,{children:[e(k,{variant:"secondary",onClick:p,disabled:d,children:"Cancel"}),e(k,{variant:"danger",onClick:y,disabled:!g||d,children:d?"Clearing...":"Yes, delete everything"})]})]})]})},ha=()=>{const[t,i]=r(""),[l,g]=r([]),[f,d]=r(null),[C,m]=r(!0),[o,a]=r({show:!1,message:"",type:"info"}),p=async()=>{try{m(!0);const u=await b.auth.rcloneSettings.query();i(u.remote||""),g(u.availableRemotes||[]),d(u.activeRemote||null)}catch(u){console.error("Failed to fetch Rclone settings",u)}finally{m(!1)}};G(()=>{p()},[]);const y=async()=>{try{await b.auth.saveRclone.mutate({remote:t}),a({show:!0,message:"Rclone configuration saved successfully. You must restart the server for these changes to take effect.",type:"success"}),p()}catch{a({show:!0,message:"Failed to save Rclone configuration.",type:"error"})}};return C?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:_.sectionCard,children:[e("h3",{className:w.title,children:"Rclone Cloud Sync"}),e("p",{className:w.signIn,children:"Configure which Rclone remote to use for database synchronization."}),f?e("div",{className:w.userInfo,children:e("p",{children:["Current Active Remote: ",e("strong",{children:f})]})}):e("p",{className:w.warning,style:{marginBottom:"1.5rem"},children:"Rclone sync is not currently active. Ensure rclone is installed and a remote is configured."}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Remote Name"}),e("div",{className:w.inputWrapper,children:e("select",{className:w.select,value:t,onChange:u=>i(u.currentTarget.value),children:[e("option",{value:"",children:"(Disabled / None)"}),l.map(u=>e("option",{value:u,children:u},u)),t&&!l.includes(t)&&e("option",{value:t,children:[t," (Manual)"]})]})}),e("p",{className:w.warning,style:{marginTop:"12px"},children:[e("strong",{children:"Note:"})," You can choose which provider is active using the selector at the top of the page."]})]}),e("div",{className:w.actions,children:e(k,{onClick:y,children:"Save Rclone Settings"})}),e(U,{isOpen:o.show,onClose:()=>a(u=>({...u,show:!1})),width:"sm",children:[e(U.Body,{children:e("p",{children:o.message})}),e(U.Actions,{children:e(k,{onClick:()=>a(u=>({...u,show:!1})),children:"OK"})})]})]})},ga=()=>{const t=te(),[i,l]=r(null),[g,f]=r(!0),d=async()=>{try{const a=await b.auth.syncSettings.query();l(a)}catch(a){console.error("Failed to fetch sync settings",a)}finally{f(!1)}};G(()=>{d()},[]);const C=async a=>{const p=a.currentTarget.value;try{const y=await b.auth.saveSyncProvider.mutate({provider:p});l(u=>u?{...u,activeProvider:y.activeProvider}:null),await d(),await t.invalidateQueries({queryKey:ee.queryKey}),Ne.success(`Sync provider updated to ${p==="default"?"Default Order":p}`)}catch{Ne.error("Failed to update sync provider")}};if(g||!i)return null;const m=[{value:"default",label:"Default (Priority Based)"}];i.authenticatedProviders.github&&m.push({value:"github",label:"GitHub"}),i.authenticatedProviders.google&&m.push({value:"google",label:"Google Drive"}),i.authenticatedProviders.rclone&&m.push({value:"rclone",label:"Rclone"}),m.push({value:"none",label:"None (Local Only)"});const o=a=>a==="none"?"Local Only (No Sync)":a==="google"?"Google Drive":a==="github"?"GitHub":a==="rclone"?"Rclone":a;return e("div",{className:_.sectionCard,children:[e("h3",{children:"Active Sync Provider"}),e("p",{children:'Choose which provider to use for synchronization. "Default" uses the first available provider you are logged into.'}),e("div",{style:{marginBottom:"1.5rem",padding:"0.75rem",background:"rgba(255, 255, 255, 0.03)",borderRadius:"var(--radius-md)",borderLeft:"4px solid var(--accent)",fontSize:"var(--font-size-sm)"},children:["Current Status:"," ",e("strong",{style:{color:"var(--accent-light)",textTransform:"capitalize"},children:o(i.actualActiveProvider)})]}),e("div",{className:_.settingRow,children:[e("label",{htmlFor:"sync-provider-select",children:"Selected Preference"}),e("select",{id:"sync-provider-select",value:i.activeProvider,onChange:C,style:{padding:"0.5rem",borderRadius:"var(--radius-md)",background:"rgba(255, 255, 255, 0.05)",color:"var(--text-primary)",border:"1px solid var(--glass-border)",fontSize:"var(--font-size-sm)",minWidth:"220px",outline:"none",cursor:"pointer"},children:m.map(a=>e("option",{value:a.value,children:a.label},a.value))})]})]})};function ma(){return"javascript:"+encodeURIComponent(`(function(){
|
|
1
|
+
import{d as r,u as e,S as me,A as Z,h as G,q as pe,T as Ee,p as Ke,g as Ce,_ as Ue}from"./vendor-core-DfaOB3Rn.js";import{b as fe,u as te}from"./vendor-query-BBT5_sHx.js";import{R as ee,S as J,U as E,V as ke,B as k,W as Fe,Q as U,d as $e,L as Ie,t as b,v as Le,o as We,J as Se,X,q as H,Y as Ne,Z as He,_ as Be,u as je,e as Qe,$ as Ve,K as ce,p as Ye,a0 as Je,a1 as Xe}from"./index-CD7a-Eff.js";import{I as j}from"./vendor-icons-DrybRNxP.js";import{T as F}from"./ToggleSwitch-CN_ppEc9.js";import{l as Ze,s as et}from"./playbackCompletion-BXBBtgdB.js";import{M as tt}from"./MatureConsentModal-yectlds9.js";const at="_sectionCard_1vuib_1",nt="_dangerCard_1vuib_20",rt="_settingRow_1vuib_31",_={sectionCard:at,dangerCard:nt,settingRow:rt};function st(){const{data:t}=fe(ee),{data:i}=fe({queryKey:["profiles"],queryFn:()=>J("/api/profiles/status"),enabled:!!t?.owner}),l=te(),[g,f]=r(null),[d,C]=r(""),[m,o]=r(""),[a,p]=r(""),[y,u]=r(""),[L,c]=r(""),[v,T]=r(!1),[I,A]=r(null),P=async s=>{T(!0),c("");try{await J("/api/profiles/update",{method:"POST",body:JSON.stringify(s)}),await l.invalidateQueries({queryKey:ee.queryKey}),C(""),o(""),c("Profile saved")}catch(N){c(N.message)}finally{T(!1)}};return t?e("section",{className:_.sectionCard,children:[e("h3",{children:"Your profile"}),e("p",{children:"Keep using this profile, rename it, or add another person with their own library and connections."}),e("div",{className:E.avatarRow,children:[e(ke,{image:t.image,name:t.name}),e("label",{className:E.uploadButton,children:[e(j,{name:"upload"}),e("span",{children:"Upload image"}),e("input",{className:E.fileInput,type:"file",accept:"image/png,image/jpeg,image/webp,image/gif",disabled:v,onChange:async s=>{const N=s.currentTarget.files?.[0];if(s.currentTarget.value="",!N)return;if(N.size>2*1024*1024){c("Image must be smaller than 2 MB");return}const R=new FileReader;R.onerror=()=>c("Could not read image"),R.onload=()=>{P({avatar:R.result})},R.readAsDataURL(N)}})]}),t.avatar&&e(k,{variant:"secondary",disabled:v,onClick:()=>P({avatar:null}),children:"Clear uploaded image"})]}),e("p",{children:"Your uploaded image takes priority, followed by your active cloud account image, then the default user icon."}),e("form",{className:E.form,onSubmit:s=>{s.preventDefault(),P({name:g??t.name})},children:[e("label",{className:E.field,children:["Profile name",e("input",{value:g??t.name,maxLength:60,required:!0,onChange:s=>f(s.currentTarget.value)})]}),e(k,{type:"submit",disabled:v,children:"Save name"})]}),e("form",{className:E.form,onSubmit:s=>{s.preventDefault(),P({password:d,currentPassword:m})},children:[t.protected&&e("label",{className:E.field,children:["Current password",e("input",{type:"password",autoComplete:"current-password",value:m,required:!0,maxLength:256,onChange:s=>o(s.currentTarget.value)})]}),e("label",{className:E.field,children:[t.protected?"New password (empty removes protection)":"Protect this profile",e("input",{type:"password",autoComplete:"new-password",value:d,minLength:8,maxLength:256,onChange:s=>C(s.currentTarget.value)})]}),e(k,{type:"submit",disabled:v,children:"Save password"})]}),e(k,{variant:"secondary",disabled:v,onClick:async()=>{T(!0);try{await J("/api/profiles/logout",{method:"POST"}),Fe()}catch(s){c(s.message),T(!1)}},children:"Switch profile / sign out"}),t.owner&&e("form",{className:E.form,onSubmit:async s=>{s.preventDefault(),T(!0),c("");try{await J("/api/profiles/create",{method:"POST",body:JSON.stringify({name:a,password:y})}),p(""),u(""),await l.invalidateQueries({queryKey:["profiles"]}),c("Profile created. Sign out to switch to it.")}catch(N){c(N.message)}finally{T(!1)}},children:[e("h3",{children:"Add another profile"}),e("p",{children:"Protect your owner profile first. New profiles start empty and do not inherit your accounts. A profile without a password is accessible to anyone who passes the LAN lock."}),e("label",{className:E.field,children:["Name",e("input",{required:!0,maxLength:60,value:a,onChange:s=>p(s.currentTarget.value)})]}),e("label",{className:E.field,children:["Password (optional)",e("input",{type:"password",autoComplete:"new-password",minLength:8,maxLength:256,value:y,onChange:s=>u(s.currentTarget.value)})]}),e(k,{type:"submit",disabled:v||!t.protected,children:"Create profile"})]}),t.owner&&i?.profiles.some(s=>!s.owner)&&e(me,{children:[e("h3",{children:"Other profiles"}),e("ul",{className:E.profileList,children:i.profiles.filter(s=>!s.owner).map(s=>e("li",{children:[e("span",{className:E.smallAvatar,children:e(ke,{image:s.avatar??s.cloudAvatar,name:s.name})}),e("span",{className:E.profileName,children:s.name}),e(k,{variant:"danger",size:"sm",disabled:v,onClick:()=>{c(""),A(s)},children:"Delete"})]},s.id))})]}),e(U,{isOpen:!!I,onClose:v?void 0:()=>A(null),title:"Delete profile?",width:"sm",footer:e(me,{children:[e(k,{variant:"secondary",disabled:v,onClick:()=>A(null),children:"Cancel"}),e(k,{variant:"danger",loading:v,onClick:async()=>{if(I){T(!0);try{await J("/api/profiles/delete",{method:"POST",body:JSON.stringify({id:I.id,confirm:!0})}),await l.invalidateQueries({queryKey:["profiles"]}),A(null),c("Profile deleted. Local files will be removed when Dango restarts.")}catch(s){c(s.message),A(null)}finally{T(!1)}}},children:"Delete profile"})]}),children:[e("p",{children:["Delete ",e("strong",{children:I?.name}),"? This signs them out immediately. Their local libraries, settings and connections will be removed when Dango next restarts."]}),e("p",{children:"Cloud backups and tracker lists will stay intact. Export any library you want to keep before deleting."})]}),L&&e("p",{role:"status",children:L})]}):null}const de={"title-preference-container":"_title-preference-container_sdqgs_1","toggle-button":"_toggle-button_sdqgs_21","toggle-label":"_toggle-label_sdqgs_51"},ue=["name","nativeName","englishName"],he={name:"Default (Romaji)",nativeName:"Native",englishName:"English"},it=()=>{const{titlePreference:t,setTitlePreference:i,loading:l}=$e(),g=Ie(),[f,d]=r(he[t]),[C,m]=r(!1),o=Z(null);G(()=>{l||d(he[t])},[t,l]);const a=async()=>{if(C)return;m(!0);const y=(ue.indexOf(t)+1)%ue.length,u=ue[y],L=he[u];o.current&&(o.current.style.transform="translateX(-100%)",o.current.style.opacity="0"),setTimeout(async()=>{d(L),i(u),o.current&&(o.current.style.transition="none",o.current.style.transform="translateX(100%)",o.current.style.opacity="0",o.current.offsetWidth,o.current.style.transition="transform 0.3s ease-out, opacity 0.3s ease-out",o.current.style.transform="translateX(0)",o.current.style.opacity="1");try{await g.mutateAsync({key:"titlePreference",value:u})}catch(c){console.error("Error saving title preference:",c)}finally{m(!1)}},300)};return l?e("p",{children:"Loading title preference..."}):e("div",{className:de["title-preference-container"],children:[e("h4",{children:"Anime Title Display Preference"}),e("button",{onClick:a,className:de["toggle-button"],disabled:C,children:e("span",{ref:o,className:de["toggle-label"],children:f})})]})},ot="_settingsHeader_gfwoa_1",lt="_pageTitle_gfwoa_6",ct="_pageSubtitle_gfwoa_14",dt="_settingsLayout_gfwoa_20",ut="_sidebar_gfwoa_27",ht="_sidebarIndicator_gfwoa_35",gt="_sidebarItem_gfwoa_50",mt="_active_gfwoa_72",pt="_mainContent_gfwoa_80",ft="_tabContent_gfwoa_85",yt="_settingItem_gfwoa_103",vt="_shortcutContainer_gfwoa_108",wt="_shortcutGroup_gfwoa_115",bt="_shortcutGroupTitle_gfwoa_121",Ct="_shortcutGrid_gfwoa_130",kt="_shortcutCard_gfwoa_136",St="_controls_gfwoa_170",Nt="_status_gfwoa_176",h={settingsHeader:ot,pageTitle:lt,pageSubtitle:ct,settingsLayout:dt,sidebar:ut,sidebarIndicator:ht,sidebarItem:gt,active:mt,mainContent:pt,tabContent:ft,settingItem:yt,shortcutContainer:vt,shortcutGroup:wt,shortcutGroupTitle:bt,shortcutGrid:Ct,shortcutCard:kt,controls:St,status:Nt},_t="_title_tm30b_11",Tt="_signIn_tm30b_18",It="_userInfo_tm30b_25",Lt="_warning_tm30b_47",Pt="_formGroup_tm30b_54",xt="_label_tm30b_58",Rt="_inputWrapper_tm30b_68",Dt="_input_tm30b_68",At="_select_tm30b_92",Ot="_actions_tm30b_109",Gt="_hr_tm30b_117",w={title:_t,signIn:Tt,userInfo:It,warning:Lt,formGroup:Pt,label:xt,inputWrapper:Rt,input:Dt,select:At,actions:Ot,hr:Gt},Mt=()=>{const t=te(),[i,l]=r(!0),[g,f]=r(!1),[d,C]=r(!1),[m,o]=r(null),[a,p]=r({status:"idle"}),[y,u]=r(!1),[L,c]=r(""),[v,T]=r(!1),I=Z(null),[A,P]=r({show:!1,message:"",type:"info"}),s=()=>{I.current&&(window.clearInterval(I.current),I.current=null)},N=pe(S=>{C(S.authenticated),o(S.user||S.device.user||null),p(S.device),u(!!S.hasCustomClientId)},[]),R=pe(async()=>{const S=await b.auth.githubStatus.query();N(S)},[N]),K=async()=>{try{const S=await b.auth.githubPoll.query();p(S),S.status==="success"?(s(),await t.invalidateQueries({queryKey:ee.queryKey}),await R(),P({show:!0,message:"GitHub authentication complete. Sync has been initialized.",type:"success"})):S.status==="error"&&(s(),P({show:!0,message:S.error||"GitHub authentication failed.",type:"error"}))}catch{s(),P({show:!0,message:"Failed to poll GitHub authentication status.",type:"error"})}},x=(S=5)=>{s(),I.current=window.setInterval(K,Math.max(S,5)*1e3)};G(()=>(R().catch(()=>{P({show:!0,message:"Failed to load GitHub sync status.",type:"error"})}).finally(()=>l(!1)),s),[R]);const M=async()=>{f(!0);try{const S=await b.auth.githubStart.mutate();p(S),x(S.verification?.interval)}catch(S){P({show:!0,message:S instanceof Error?S.message:"Failed to start GitHub authentication.",type:"error"})}finally{f(!1)}},q=async()=>{try{await b.auth.githubLogout.mutate(),await t.invalidateQueries({queryKey:ee.queryKey}),C(!1),o(null),p({status:"idle"}),P({show:!0,message:"Signed out of GitHub sync.",type:"success"})}catch{P({show:!0,message:"Failed to sign out of GitHub.",type:"error"})}},$=async()=>{T(!0);try{await b.auth.saveGithubAuth.mutate({clientId:L}),c(""),await R(),P({show:!0,message:"Custom GitHub auth saved.",type:"success"})}catch{P({show:!0,message:"Failed to save override.",type:"error"})}finally{T(!1)}},Q=async()=>{T(!0);try{await b.auth.saveGithubAuth.mutate({clientId:""}),c(""),await R(),P({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{P({show:!0,message:"Failed to clear override.",type:"error"})}finally{T(!1)}};return i?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:_.sectionCard,children:[e("h3",{className:w.title,children:"GitHub Cloud Sync"}),e("p",{className:w.signIn,children:"Sync local data through a private GitHub repository named dango-sync-data."}),d&&m?e("div",{className:w.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:m.name||m.login})]}),e(k,{variant:"danger",onClick:q,children:"Sign Out"})]}):e("div",{className:w.signIn,children:e(k,{onClick:M,disabled:g||a.status==="pending",children:g||a.status==="pending"?"Waiting for GitHub...":"Sign in with GitHub"})}),a.status==="pending"&&a.verification&&e(me,{children:[e("hr",{className:w.hr}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Verification URL"}),e("div",{className:w.inputWrapper,children:[e("input",{className:w.input,value:a.verification.verification_uri,readOnly:!0}),e(k,{onClick:()=>{const S=a.verification?.verification_uri;S&&/^https?:\/\//i.test(S)&&window.open(S,"_blank","noopener,noreferrer")},children:"Open"})]})]}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Device Code"}),e("input",{className:w.input,value:a.verification.user_code,readOnly:!0})]})]}),a.status==="error"&&e("p",{className:w.warning,children:a.error}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",y?"(override active)":""]}),e("div",{className:w.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:w.label,children:"Client ID (optional)"}),e("input",{className:w.input,value:L,onChange:S=>c(S.currentTarget.value),placeholder:"Your GitHub OAuth app ID"})]}),e("div",{className:w.actions,children:[e(k,{onClick:$,disabled:v,children:"Save override"}),e(k,{variant:"secondary",onClick:Q,disabled:v,children:"Use dango defaults"})]})]}),e(U,{isOpen:A.show,onClose:()=>P(S=>({...S,show:!1})),width:"sm",children:[e(U.Body,{children:e("p",{children:A.message})}),e(U.Actions,{children:e(k,{onClick:()=>P(S=>({...S,show:!1})),children:"OK"})})]})]})},qt=()=>{const[t,i]=r(!0),[l,g]=r(null),[f,d]=r(!1),[C,m]=r(!1),[o,a]=r(""),[p,y]=r(""),[u,L]=r(""),[c,v]=r(!1),[T,I]=r({show:!1,message:"",type:"info"}),A=async()=>{try{const M=await b.auth.user.query();g(M?.email?M:null)}catch{g(null)}},P=async()=>{try{const[x,M]=await Promise.all([b.auth.configStatus.query(),b.auth.googleAuth.query()]);d(!!x.hasConfig),m(!!(M.hasCustomWorkerUrl||M.hasCustomClientId||M.hasClientSecret))}catch(x){console.error("Failed to fetch config status",x)}};G(()=>{(async()=>{i(!0),await Promise.all([A(),P()]);try{new URLSearchParams(window.location.search).get("google_auth")==="success"&&(await A(),window.history.replaceState(null,"",window.location.pathname))}catch{}i(!1)})();const M=q=>{q.origin===window.location.origin&&typeof q.data=="object"&&q.data!==null&&q.data.type==="GOOGLE_AUTH_SUCCESS"&&(g(q.data.user),window.location.reload())};return window.addEventListener("message",M),()=>window.removeEventListener("message",M)},[]);const s=async()=>{try{const x=await b.auth.googleLogin.mutate();if(x.authenticated){window.location.reload();return}if(x.url){if(typeof window.DangoBridge<"u"){window.location.href=x.url;return}const q=600,$=700,Q=window.innerWidth/2-q/2,S=window.innerHeight/2-$/2;window.open(x.url,"GoogleAuth",`width=${q},height=${$},top=${S},left=${Q}`)}else throw new Error("Auth URL not available")}catch{I({show:!0,message:"Authentication failed. Ensure server is configured correctly.",type:"error"})}},N=async()=>{try{await b.auth.logout.mutate(),g(null),I({show:!0,message:"Successfully signed out.",type:"success"}),window.location.reload()}catch(x){console.error("Sign out failed",x),I({show:!0,message:"Failed to sign out.",type:"error"})}},R=async()=>{v(!0);try{await b.auth.saveGoogleAuth.mutate({workerUrl:o,clientId:p,clientSecret:u}),a(""),y(""),L(""),await P(),I({show:!0,message:"Custom auth saved. Restart may be required.",type:"success"})}catch{I({show:!0,message:"Failed to save override.",type:"error"})}finally{v(!1)}},K=async()=>{v(!0);try{await b.auth.saveGoogleAuth.mutate({workerUrl:"",clientId:"",clientSecret:""}),a(""),y(""),L(""),await P(),I({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{I({show:!0,message:"Failed to clear override.",type:"error"})}finally{v(!1)}};return t?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:_.sectionCard,children:[e("h3",{className:w.title,children:"Google Drive Sync"}),l?e("div",{className:w.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:l.name})," (",l.email,")"]}),e(k,{variant:"danger",onClick:N,children:"Sign Out"})]}):e("div",{className:w.signIn,children:[e("p",{children:"Sign in with your Google account to enable synchronization features."}),e(k,{onClick:s,disabled:!f,children:"Sign in with Google"}),!f&&e("p",{className:w.warning,children:"Google sync is not configured on the server."})]}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",C?"(override active)":""]}),e("div",{className:w.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:w.label,children:"Worker URL (optional)"}),e("input",{className:w.input,value:o,onChange:x=>a(x.currentTarget.value),placeholder:"https://your-worker.workers.dev"})]}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Client ID (optional)"}),e("input",{className:w.input,value:p,onChange:x=>y(x.currentTarget.value),placeholder:"Your Google OAuth client ID"})]}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Client Secret (optional)"}),e("input",{type:"password",className:w.input,value:u,onChange:x=>L(x.currentTarget.value),placeholder:"Your Google OAuth secret"})]}),e("div",{className:w.actions,children:[e(k,{onClick:R,disabled:c,children:"Save override"}),e(k,{variant:"secondary",onClick:K,disabled:c,children:"Use dango defaults"})]})]}),e(U,{isOpen:T.show,onClose:()=>I(x=>({...x,show:!1})),width:"sm",children:[e(U.Body,{children:e("p",{children:T.message})}),e(U.Actions,{children:e(k,{onClick:()=>I(x=>({...x,show:!1})),children:"OK"})})]})]})},zt="_settingItem_3qq0n_1",Et="_modalOverlay_3qq0n_6",Kt="_modal_3qq0n_6",Ut="_modalActions_3qq0n_41",Ft="_modalSecondary_3qq0n_47",$t="_modalPrimary_3qq0n_57",B={settingItem:zt,modalOverlay:Et,modal:Kt,modalActions:Ut,modalSecondary:Ft,modalPrimary:$t},Wt={anime:{heading:"Watchlist Preferences",blurb:"Customize your experience when managing your watchlist and series entries.",skipKey:"skipRemoveConfirmation",ignoreKey:"ignoreAdultContent",listOnlyKey:"cwWatchlistOnly",skipLabel:"Skip confirmation when removing from watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in watchlist",listNoun:"watchlist",continueNoun:"continue watching",adultCountUrl:"/api/continue-watching/adult-count",purgeUrl:"/api/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["allContinueWatching"]]},manga:{heading:"Reading List Preferences",blurb:"Customize your experience when managing your reading list and manga entries.",skipKey:"mangaSkipRemoveConfirmation",ignoreKey:"mangaIgnoreAdultContent",listOnlyKey:"mangaCwWatchlistOnly",skipLabel:"Skip confirmation when removing from reading list",ignoreLabel:"Hide adult content from continue reading",listOnlyLabel:"Only show continue reading for manga in reading list",listNoun:"reading list",continueNoun:"continue reading",adultCountUrl:"/api/manga/continue-reading/adult-count",purgeUrl:"/api/manga/continue-reading/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue reading`,invalidateKeys:[["manga-continue-reading"]]},tv:{heading:"TV Watchlist Preferences",blurb:"Customize your experience when managing your TV watchlist and series entries.",skipKey:"tvSkipRemoveConfirmation",ignoreKey:"tvIgnoreAdultContent",listOnlyKey:"tvCwWatchlistOnly",skipLabel:"Skip confirmation when removing from TV watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in TV watchlist",listNoun:"TV watchlist",continueNoun:"continue watching",adultCountUrl:"/api/tv/continue-watching/adult-count",purgeUrl:"/api/tv/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["tv-continue-watching"]]},asmr:{heading:"Listening List Preferences",blurb:"Customize your experience when managing your listening list and work entries.",skipKey:"asmrSkipRemoveConfirmation",ignoreKey:"asmrIgnoreAdultContent",listOnlyKey:"asmrCwWatchlistOnly",skipLabel:"Skip confirmation when removing from listening list",ignoreLabel:"Hide adult content from continue listening",listOnlyLabel:"Only show continue listening for works in listening list",listNoun:"listening list",continueNoun:"continue listening",adultCountUrl:"/api/asmr/continue-listening/adult-count",purgeUrl:"/api/asmr/continue-listening/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue listening`,invalidateKeys:[["asmr-continue-listening"]]}},Ht=(t,i)=>{if(t==null)return i;const l=String(t);return l==="true"||l==="1"?!0:l==="false"||l==="0"?!1:i},_e=(t,i,l)=>{const[g,f]=r(i),[d,C]=r(!1),m=te();return G(()=>{(async()=>{try{const p=await b.settings.getByKey.query({key:t});f(Ht(p.value,i))}catch(p){console.error("Failed to fetch setting",p)}})()},[t,i]),{value:g,setValue:f,isUpdating:d,toggle:async()=>{if(d)return;C(!0);const a=!g;f(a);try{await b.settings.set.mutate({key:t,value:a});for(const p of l)m.invalidateQueries({queryKey:p})}catch(p){console.error("Error saving setting:",p),f(!a)}finally{C(!1)}}}},Bt=()=>{const{contentType:t}=Le(),i=Wt[t],[l,g]=r(!1),[f,d]=r(!0),[C,m]=r(!1),o=_e(i.ignoreKey,!0,i.invalidateKeys),a=_e(i.listOnlyKey,!1,i.invalidateKeys),[p,y]=r(null),[u,L]=r(!1),c=te(),v=We();G(()=>{d(!0),(async()=>{try{const N=await b.settings.getByKey.query({key:i.skipKey});String(N.value)==="true"||String(N.value)==="1"?g(!0):g(!1)}catch(N){console.error("Failed to fetch setting",N)}finally{d(!1)}})()},[i.skipKey]);const T=async()=>{if(C)return;m(!0);const s=!l;g(s);try{await b.settings.set.mutate({key:i.skipKey,value:s})}catch(N){console.error("Error saving setting:",N),g(!s)}finally{m(!1)}},I=async()=>{if(!o.isUpdating){if(o.value)try{let s;if(t==="anime"?s=(await b.continueWatching.adultCount.query()).count:t==="manga"?s=(await b.mangaProgress.adultCount.query()).count:t==="asmr"?s=(await b.asmrProgress.adultCount.query()).count:s=(await b.tvProgress.adultCount.query()).count,typeof s=="number"&&s>0){y(s);return}}catch(s){console.error("Failed to fetch adult count",s)}o.toggle()}},A=()=>{y(null),o.toggle()},P=async()=>{if(!u){L(!0);try{let s;t==="anime"?s=(await b.continueWatching.purgeAdult.mutate()).removed:t==="manga"?s=(await b.mangaProgress.purgeAdult.mutate()).removed:t==="asmr"?s=(await b.asmrProgress.purgeAdult.mutate()).removed:s=(await b.tvProgress.purgeAdult.mutate()).removed,Se.success(i.purgeDoneText(s??0));for(const N of i.invalidateKeys)c.invalidateQueries({queryKey:N});t==="anime"&&c.invalidateQueries(v.continueWatching.pathFilter()),t==="manga"&&c.invalidateQueries(v.mangaProgress.pathFilter()),t==="asmr"&&c.invalidateQueries(v.asmrProgress.pathFilter()),t==="tv"&&c.invalidateQueries(v.tvProgress.pathFilter())}catch(s){console.error("Failed to purge adult entries",s),Se.error("Failed to remove adult entries")}finally{L(!1),y(null)}o.toggle()}};return f?e("div",{children:"Loading settings..."}):e("div",{className:_.sectionCard,children:[e("h3",{children:i.heading}),e("p",{children:i.blurb}),e("div",{className:B.settingItem,children:e("div",{className:_.settingRow,children:[e("label",{htmlFor:"skip-confirmation-toggle",children:i.skipLabel}),e(F,{isChecked:l,onChange:T,id:"skip-confirmation-toggle",disabled:C})]})}),e("div",{className:B.settingItem,children:e("div",{className:_.settingRow,children:[e("label",{htmlFor:"ignore-adult-toggle",children:i.ignoreLabel}),e(F,{isChecked:o.value,onChange:I,id:"ignore-adult-toggle",disabled:o.isUpdating})]})}),e("div",{className:B.settingItem,children:e("div",{className:_.settingRow,children:[e("label",{htmlFor:"cw-watchlist-only-toggle",children:i.listOnlyLabel}),e(F,{isChecked:a.value,onChange:a.toggle,id:"cw-watchlist-only-toggle",disabled:a.isUpdating})]})}),p!==null&&e("div",{className:B.modalOverlay,onClick:()=>y(null),children:e("div",{className:B.modal,onClick:s=>s.stopPropagation(),children:[e("h4",{children:"Show adult entries?"}),e("p",{children:[p," adult ",p===1?"entry":"entries"," not in your"," ",i.listNoun," ",p===1?"is":"are"," currently hidden from"," ",i.continueNoun,". You can purge ",p===1?"it":"them"," from the database instead of showing ",p===1?"it":"them","."]}),e("div",{className:B.modalActions,children:[e("button",{type:"button",className:B.modalSecondary,onClick:A,disabled:u,children:"Show them"}),e("button",{type:"button",className:B.modalPrimary,onClick:P,disabled:u,children:u?"Purging...":`Purge ${p}`})]})]})})]})},jt="_statsGrid_o4nf0_1",Qt="_statCard_o4nf0_8",Vt="_statLabel_o4nf0_18",Yt="_statValue_o4nf0_26",Jt="_statMeta_o4nf0_32",Xt="_statusBanner_o4nf0_38",Zt="_statusSuccess_o4nf0_49",ea="_statusUpdating_o4nf0_55",ta="_statusError_o4nf0_61",aa="_sha_o4nf0_67",na="_settingItem_o4nf0_74",ra="_settingTitle_o4nf0_79",sa="_settingSubtitle_o4nf0_85",ia="_actionsRow_o4nf0_92",D={statsGrid:jt,statCard:Qt,statLabel:Vt,statValue:Yt,statMeta:Jt,statusBanner:Xt,statusSuccess:Zt,statusUpdating:ea,statusError:ta,sha:aa,settingItem:na,settingTitle:ra,settingSubtitle:sa,actionsRow:ia},oa=()=>{const[t,i]=r(null),[l,g]=r(!0),[f,d]=r(!1),[C,m]=r(!1),o=Z(null),a=async()=>{try{const c=await b.settings.offlineDbInfo.query();return i(c),c}catch(c){console.error("Failed to fetch offline DB info:",c)}finally{g(!1)}return null};G(()=>(a(),()=>{o.current&&window.clearInterval(o.current)}),[]),G(()=>{t?.isRefreshing?o.current||(o.current=window.setInterval(async()=>{const c=await a();c&&!c.isRefreshing&&o.current&&(window.clearInterval(o.current),o.current=null)},2e3)):o.current&&(window.clearInterval(o.current),o.current=null)},[t?.isRefreshing]);const p=async()=>{if(!t||f)return;const c=!t.autoUpdateEnabled;d(!0),i({...t,autoUpdateEnabled:c});try{await b.settings.setOfflineDbAutoUpdate.mutate({enabled:c})}catch(v){console.error("Failed to update auto update setting:",v),i({...t,autoUpdateEnabled:!c})}finally{d(!1)}},y=async()=>{if(!(t?.isRefreshing||C)){m(!0);try{await b.settings.triggerOfflineDbUpdate.mutate(),i(c=>c?{...c,isRefreshing:!0,lastStatus:"updating",lastMessage:"Downloading database..."}:null)}catch(c){console.error("Failed to trigger offline DB update:",c)}finally{m(!1)}}},u=c=>{if(!c)return"Never";try{return new Date(c).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"})}catch{return c}},L=t?.isRefreshing||C;return e("div",{className:_.sectionCard,children:[e("h3",{children:"Offline Metadata Database"}),e("p",{children:"Local MAL to AniList ID map used for instant imports and metadata enrichment without hitting rate-limited APIs. Updates automatically every Saturday in the background."}),e("div",{className:D.statsGrid,children:[e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"MAL Mapped"}),e("span",{className:D.statValue,children:l?"-":(t?.totalMalMapped??0).toLocaleString()})]}),e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"Release"}),e("span",{className:D.statMeta,children:l?"-":t?.releaseTag??"Never"})]}),e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"Last Checked"}),e("span",{className:D.statMeta,children:l?"-":u(t?.lastCheckedAt??null)})]}),e("div",{className:D.statCard,children:[e("span",{className:D.statLabel,children:"Last Updated"}),e("span",{className:D.statMeta,children:l?"-":u(t?.lastUpdatedAt??null)})]})]}),t?.lastMessage&&e("div",{className:`${D.statusBanner} ${t.lastStatus==="failed"?D.statusError:t.lastStatus==="updating"?D.statusUpdating:D.statusSuccess}`,children:[e("span",{children:t.lastMessage}),t.contentSha256&&e("span",{className:D.sha,children:["sha:",t.contentSha256.slice(0,12)]})]}),e("div",{className:D.settingItem,children:e("div",{className:_.settingRow,children:[e("div",{children:[e("span",{className:D.settingTitle,children:"Weekly Automatic Updates (Saturdays)"}),e("div",{className:D.settingSubtitle,children:"Download and index new database releases in the background. Catches up on startup if the server was offline."})]}),e(F,{id:"offline-db-auto-update-toggle",isChecked:t?t.autoUpdateEnabled:!0,onChange:p,disabled:l||f})]})}),e("div",{className:D.actionsRow,children:e(k,{onClick:y,disabled:l||L,children:L?"Updating Database...":"Update Offline Database Now"})})]})},la="_status_1wbo0_1",ca="_warningText_1wbo0_7",da="_ackLabel_1wbo0_11",ge={status:la,warningText:ca,ackLabel:da},ua=()=>{const t=te(),[i,l]=r(!1),[g,f]=r(!1),[d,C]=r(!1),[m,o]=r(""),a=()=>{f(!1),o(""),l(!0)},p=()=>{d||(l(!1),f(!1))},y=async()=>{if(!(!g||d)){C(!0),o("");try{const u=await X("/api/database/clear",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({confirm:!0})}),L=await u.json();if(!u.ok)throw new Error(L.error||"Failed to clear database");const c=L.deleted,v=L.deletedManga,T=L.deletedTv,I=L.deletedAsmr,A=Object.values(c).reduce((R,K)=>R+(K||0),0)+Object.values(v??{}).reduce((R,K)=>R+(K||0),0)+Object.values(T??{}).reduce((R,K)=>R+(K||0),0)+Object.values(I??{}).reduce((R,K)=>R+(K||0),0),P=(v?.manga_library??0)+(v?.manga_progress??0),s=(T?.tv_library??0)+(T?.tv_progress??0),N=(I?.asmr_library??0)+(I?.asmr_progress??0);o(`Library cleared - ${c.watchlist??0} watchlist entries, ${P} manga rows, ${s} TV rows, ${N} ASMR rows and ${A} total rows removed.`),t.invalidateQueries({queryKey:[H.watchlist]}),t.invalidateQueries({queryKey:[H.continueWatching]}),t.invalidateQueries({queryKey:[H.mangaLibrary]}),t.invalidateQueries({queryKey:[H.mangaContinueReading]}),t.invalidateQueries({queryKey:[H.tvLibrary]}),t.invalidateQueries({queryKey:[H.tvContinueWatching]}),t.invalidateQueries({queryKey:[H.asmrLibrary]}),t.invalidateQueries({queryKey:[H.asmrContinueListening]}),l(!1)}catch(u){o(u.message)}finally{C(!1),f(!1)}}};return e("div",{className:`${_.sectionCard} ${_.dangerCard}`,children:[e("h3",{children:"Danger Zone"}),e("p",{children:"Permanently delete your library (watchlist, watched episodes, queue, cached show metadata, manga reading list and reading progress, TV watchlist and watch progress, ASMR listening list and listening progress) to start fresh. Your settings, sync state and the offline metadata cache are preserved."}),e(k,{variant:"danger",onClick:a,children:"Clear Library Data"}),m&&e("p",{className:ge.status,children:m}),e(U,{isOpen:i,onClose:p,title:"Clear library data?",width:"sm",children:[e(U.Body,{children:[e("p",{className:ge.warningText,children:"This permanently deletes everything in your library. It acts on the active database (dev or prod, per server config) and cannot be undone. Settings, sync state and the offline metadata cache are kept."}),e("label",{className:ge.ackLabel,children:[e("input",{type:"checkbox",checked:g,onChange:u=>f(u.currentTarget.checked),disabled:d}),e("span",{children:"I understand this permanently deletes my library"})]})]}),e(U.Actions,{children:[e(k,{variant:"secondary",onClick:p,disabled:d,children:"Cancel"}),e(k,{variant:"danger",onClick:y,disabled:!g||d,children:d?"Clearing...":"Yes, delete everything"})]})]})]})},ha=()=>{const[t,i]=r(""),[l,g]=r([]),[f,d]=r(null),[C,m]=r(!0),[o,a]=r({show:!1,message:"",type:"info"}),p=async()=>{try{m(!0);const u=await b.auth.rcloneSettings.query();i(u.remote||""),g(u.availableRemotes||[]),d(u.activeRemote||null)}catch(u){console.error("Failed to fetch Rclone settings",u)}finally{m(!1)}};G(()=>{p()},[]);const y=async()=>{try{await b.auth.saveRclone.mutate({remote:t}),a({show:!0,message:"Rclone configuration saved successfully. You must restart the server for these changes to take effect.",type:"success"}),p()}catch{a({show:!0,message:"Failed to save Rclone configuration.",type:"error"})}};return C?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:_.sectionCard,children:[e("h3",{className:w.title,children:"Rclone Cloud Sync"}),e("p",{className:w.signIn,children:"Configure which Rclone remote to use for database synchronization."}),f?e("div",{className:w.userInfo,children:e("p",{children:["Current Active Remote: ",e("strong",{children:f})]})}):e("p",{className:w.warning,style:{marginBottom:"1.5rem"},children:"Rclone sync is not currently active. Ensure rclone is installed and a remote is configured."}),e("div",{className:w.formGroup,children:[e("label",{className:w.label,children:"Remote Name"}),e("div",{className:w.inputWrapper,children:e("select",{className:w.select,value:t,onChange:u=>i(u.currentTarget.value),children:[e("option",{value:"",children:"(Disabled / None)"}),l.map(u=>e("option",{value:u,children:u},u)),t&&!l.includes(t)&&e("option",{value:t,children:[t," (Manual)"]})]})}),e("p",{className:w.warning,style:{marginTop:"12px"},children:[e("strong",{children:"Note:"})," You can choose which provider is active using the selector at the top of the page."]})]}),e("div",{className:w.actions,children:e(k,{onClick:y,children:"Save Rclone Settings"})}),e(U,{isOpen:o.show,onClose:()=>a(u=>({...u,show:!1})),width:"sm",children:[e(U.Body,{children:e("p",{children:o.message})}),e(U.Actions,{children:e(k,{onClick:()=>a(u=>({...u,show:!1})),children:"OK"})})]})]})},ga=()=>{const t=te(),[i,l]=r(null),[g,f]=r(!0),d=async()=>{try{const a=await b.auth.syncSettings.query();l(a)}catch(a){console.error("Failed to fetch sync settings",a)}finally{f(!1)}};G(()=>{d()},[]);const C=async a=>{const p=a.currentTarget.value;try{const y=await b.auth.saveSyncProvider.mutate({provider:p});l(u=>u?{...u,activeProvider:y.activeProvider}:null),await d(),await t.invalidateQueries({queryKey:ee.queryKey}),Ne.success(`Sync provider updated to ${p==="default"?"Default Order":p}`)}catch{Ne.error("Failed to update sync provider")}};if(g||!i)return null;const m=[{value:"default",label:"Default (Priority Based)"}];i.authenticatedProviders.github&&m.push({value:"github",label:"GitHub"}),i.authenticatedProviders.google&&m.push({value:"google",label:"Google Drive"}),i.authenticatedProviders.rclone&&m.push({value:"rclone",label:"Rclone"}),m.push({value:"none",label:"None (Local Only)"});const o=a=>a==="none"?"Local Only (No Sync)":a==="google"?"Google Drive":a==="github"?"GitHub":a==="rclone"?"Rclone":a;return e("div",{className:_.sectionCard,children:[e("h3",{children:"Active Sync Provider"}),e("p",{children:'Choose which provider to use for synchronization. "Default" uses the first available provider you are logged into.'}),e("div",{style:{marginBottom:"1.5rem",padding:"0.75rem",background:"rgba(255, 255, 255, 0.03)",borderRadius:"var(--radius-md)",borderLeft:"4px solid var(--accent)",fontSize:"var(--font-size-sm)"},children:["Current Status:"," ",e("strong",{style:{color:"var(--accent-light)",textTransform:"capitalize"},children:o(i.actualActiveProvider)})]}),e("div",{className:_.settingRow,children:[e("label",{htmlFor:"sync-provider-select",children:"Selected Preference"}),e("select",{id:"sync-provider-select",value:i.activeProvider,onChange:C,style:{padding:"0.5rem",borderRadius:"var(--radius-md)",background:"rgba(255, 255, 255, 0.05)",color:"var(--text-primary)",border:"1px solid var(--glass-border)",fontSize:"var(--font-size-sm)",minWidth:"220px",outline:"none",cursor:"pointer"},children:m.map(a=>e("option",{value:a.value,children:a.label},a.value))})]})]})};function ma(){return"javascript:"+encodeURIComponent(`(function(){
|
|
2
2
|
if(!/(^|\\.)discord\\.com$/.test(location.hostname)){alert('Dango: use this bookmarklet while on discord.com');return}
|
|
3
3
|
var t=null;
|
|
4
4
|
try{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as o,g as r}from"./vendor-core-DfaOB3Rn.js";import{u as l}from"./index-
|
|
1
|
+
import{u as o,g as r}from"./vendor-core-DfaOB3Rn.js";import{u as l}from"./index-CD7a-Eff.js";const a="_skeletonCard_qtypb_1",i="_poster_qtypb_11",d="_line_qtypb_20",c="_info_qtypb_38",_="_short_qtypb_54",m="_lowEnd_qtypb_69",e={skeletonCard:a,poster:i,line:d,"skeleton-wave":"_skeleton-wave_qtypb_1",info:c,short:_,lowEnd:m},p=({layout:n="vertical"})=>{const{lowEndMode:t}=l();return o("div",{className:`${e.skeletonCard} ${e[n]} ${t?e.lowEnd:""}`,children:[o("div",{className:e.poster}),o("div",{className:e.info,children:[o("div",{className:e.line}),o("div",{className:`${e.line} ${e.short}`})]})]})},v=({count:n=14,layout:t="vertical"})=>o("div",{className:"grid-container",children:Array.from({length:n}).map((k,s)=>o(p,{layout:t},s))}),w=r.memo(v);export{p as A,w as S};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{h as Y,d as i,A as ye,u as e,S as g,g as ea,q as De}from"./vendor-core-DfaOB3Rn.js";import{u as V,b as R,a as S}from"./vendor-query-BBT5_sHx.js";import{J as r,q as s,t as c,ap as aa,v as na,X as qe,B as ge}from"./index-BYGDqzEf.js";import{I as m}from"./vendor-icons-DrybRNxP.js";function ta(){const N=V();Y(()=>{const C=new URLSearchParams(window.location.search),h=C.get("mal");if(!h)return;const t=C.get("user"),y=C.get("reason");window.history.replaceState(null,"",window.location.pathname),h==="success"?(r.success(t?`Connected to MyAnimeList as ${decodeURIComponent(t)}`:"Connected to MyAnimeList"),N.invalidateQueries({queryKey:[s.trackerStatus]})):r.error(y?decodeURIComponent(y):"MyAnimeList authentication failed")},[N])}function sa(){const N=V(),[C,h]=i(!1);return Y(()=>{const t=new URLSearchParams(window.location.search),y=t.get("anilist");if(y){const k=t.get("user"),u=t.get("reason");window.history.replaceState(null,"",window.location.pathname),y==="success"?(r.success(k?`Connected to AniList as ${decodeURIComponent(k)}`:"Connected to AniList"),N.invalidateQueries({queryKey:[s.trackerStatus]})):r.error(u?decodeURIComponent(u):"AniList authentication failed");return}const b=new URLSearchParams(window.location.hash.substring(1)),l=b.get("access_token"),L=t.get("code");if(!l&&!L){const k=b.get("error");k&&(r.error(`AniList error: ${k}`),window.history.replaceState(null,"",window.location.pathname));return}const d=window.location.origin+window.location.pathname;window.history.replaceState(null,"",window.location.pathname),h(!0),r("Connecting to AniList..."),c.tracker.anilistAuth.mutate(l?{token:l}:{code:L,redirectUri:d}).then(async k=>{const u=k.user;r.success(`Connected to AniList as ${u?.name??"AniList user"}`),N.invalidateQueries({queryKey:[s.trackerStatus]})}).catch(k=>{r.error(k instanceof Error?k.message:"Failed to authenticate with AniList")}).finally(()=>{h(!1)})},[N]),C}const ia="_header_azjok_1",ra="_fadeIn_azjok_1",ca="_pageTitle_azjok_6",oa="_pageSubtitle_azjok_14",la="_importCard_azjok_20",da="_cardHeader_azjok_31",ma="_uploadArea_azjok_49",ua="_fileInputWrapper_azjok_53",pa="_fileInput_azjok_53",ha="_fileDisplay_azjok_71",ga="_fileIcon_azjok_79",ya="_fileName_azjok_84",ka="_browseButton_azjok_93",fa="_optionsArea_azjok_104",_a="_checkboxLabel_azjok_112",ba="_checkbox_azjok_112",va="_checkboxCustom_azjok_125",Na="_optionText_azjok_153",wa="_optionTitle_azjok_159",Ca="_optionDesc_azjok_165",Ia="_actions_azjok_171",Sa="_importBtn_azjok_179",La="_cancelBtn_azjok_185",Ma="_statusMessage_azjok_199",xa="_success_azjok_209",Ta="_error_azjok_215",Aa="_progressSection_azjok_221",za="_progressBar_azjok_226",Pa="_progressFill_azjok_234",ja="_progressInfo_azjok_241",Ba="_progressCount_azjok_248",Ea="_progressTitle_azjok_255",Fa="_sourceBadge_azjok_273",Da="_anilist_azjok_285",qa="_kitsu_azjok_291",$a="_offline_azjok_297",Ka="_skipped_azjok_303",Ra="_cardTitleRow_azjok_308",Ua="_anilistIcon_azjok_318",Qa="_malIcon_azjok_324",Oa="_badgeOnline_azjok_330",Ha="_badgeOffline_azjok_342",Ga="_connectedProfile_azjok_354",Wa="_avatar_azjok_361",Xa="_connectedInfo_azjok_368",Ja="_connectedName_azjok_376",Ya="_connectedHint_azjok_382",Va="_loginPrompt_azjok_387",Za="_loginSection_azjok_395",en="_primaryBtn_azjok_401",an="_fieldLabel_azjok_405",nn="_helpText_azjok_424",tn="_resetBtn_azjok_431",sn="_loginText_azjok_461",rn="_secondaryBtn_azjok_471",cn="_syncBtn_azjok_472",on="_divider_azjok_525",ln="_actionSection_azjok_531",dn="_inputGroup_azjok_545",mn="_credentialFields_azjok_551",un="_credentialField_azjok_551",pn="_input_azjok_545",hn="_syncSummary_azjok_587",gn="_syncErrors_azjok_593",yn="_spin_azjok_597",kn="_radioGroup_azjok_616",fn="_radioLabel_azjok_623",_n="_syncHint_azjok_661",bn="_importLoading_azjok_668",a={header:ia,fadeIn:ra,pageTitle:ca,pageSubtitle:oa,importCard:la,cardHeader:da,uploadArea:ma,fileInputWrapper:ua,fileInput:pa,fileDisplay:ha,fileIcon:ga,fileName:ya,browseButton:ka,optionsArea:fa,checkboxLabel:_a,checkbox:ba,checkboxCustom:va,optionText:Na,optionTitle:wa,optionDesc:Ca,actions:Ia,importBtn:Sa,cancelBtn:La,statusMessage:Ma,success:xa,error:Ta,progressSection:Aa,progressBar:za,progressFill:Pa,progressInfo:ja,progressCount:Ba,progressTitle:Ea,sourceBadge:Fa,anilist:Da,kitsu:qa,offline:$a,skipped:Ka,cardTitleRow:Ra,anilistIcon:Ua,malIcon:Qa,badgeOnline:Oa,badgeOffline:Ha,connectedProfile:Ga,avatar:Wa,connectedInfo:Xa,connectedName:Ja,connectedHint:Ya,loginPrompt:Va,loginSection:Za,primaryBtn:en,fieldLabel:an,helpText:nn,resetBtn:tn,loginText:sn,secondaryBtn:rn,syncBtn:cn,divider:on,actionSection:ln,inputGroup:dn,credentialFields:mn,credentialField:un,input:pn,syncSummary:hn,syncErrors:gn,spin:yn,radioGroup:kn,radioLabel:fn,syncHint:_n,importLoading:bn},ie="tracker_anilist_client_id",Re="49887".trim(),re=!!Re;function $e(){const N=V(),[C,h]=i(""),t=ye(!1),y=sa(),{data:b}=R({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query()}),{data:l}=R({queryKey:[s.anilistClientId],queryFn:async()=>(await c.settings.getByKey.query({key:ie})).value||""});Y(()=>{t.current||l===void 0||(l&&h(l),t.current=!0)},[l]);const L=S({mutationFn:()=>c.tracker.anilistDisconnect.mutate(),onSuccess:()=>{N.invalidateQueries({queryKey:[s.trackerStatus]}),r.success("Disconnected from AniList")},onError:_=>r.error(_.message)}),d=S({mutationFn:()=>c.settings.set.mutate({key:ie,value:""}),onSuccess:()=>{h(""),N.invalidateQueries({queryKey:[s.anilistClientId]}),r.success("Switched to dango's AniList app")},onError:_=>r.error(_.message)}),k=async()=>{const _=C.trim(),o=_||Re;if(!o){r.error("Enter your AniList client ID first");return}const P=(l||"").trim();try{_?_!==l&&await c.settings.set.mutate({key:ie,value:_}):re&&P&&await c.settings.set.mutate({key:ie,value:""}),N.invalidateQueries({queryKey:[s.anilistClientId]})}catch(M){r.error(M.message);return}const p=encodeURIComponent(window.location.origin+window.location.pathname);window.location.href=`https://anilist.co/api/v2/oauth/authorize?client_id=${encodeURIComponent(o)}&response_type=token&state=${p}`},u=b?.anilist?.user??null;return b?.anilist?.connected&&u?e("div",{className:a.connectedProfile,children:[u.avatar&&e("img",{src:u.avatar,alt:"Avatar",className:a.avatar,loading:"lazy",decoding:"async"}),e("div",{className:a.connectedInfo,children:[e("span",{className:a.connectedName,children:u.name}),e("span",{className:a.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:a.secondaryBtn,onClick:()=>L.mutate(),disabled:L.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}):e("div",{className:a.loginSection,children:[e("p",{className:a.loginText,children:["Log in with AniList to enable bidirectional progress & status synchronization.",y&&e("span",{style:{marginLeft:8,color:"var(--accent)"},children:"Finishing login…"})]}),e("div",{className:a.fieldLabel,children:["AniList client ID - defaults to dango's app"," ",e("a",{href:"https://anilist.co/settings/developer",target:"_blank",rel:"noopener noreferrer",children:["create your own app ",e(m,{name:"external-link-alt",size:9})]})]}),e("div",{className:a.inputGroup,children:[e("input",{type:"text",placeholder:"Client ID",value:C,onChange:_=>h(_.currentTarget.value),className:a.input}),e("button",{className:a.primaryBtn,onClick:k,disabled:!(C.trim()||re),children:[e(m,{name:"external-link-alt"})," Connect"]})]}),re&&l&&e("button",{className:a.resetBtn,onClick:()=>d.mutate(),disabled:d.isPending,children:"Use dango's app instead"}),e("p",{className:a.helpText,children:re?e(g,{children:["By default uses dango's client. To use your own AniList app: create it at"," ",e("a",{href:"https://anilist.co/settings/developer",target:"_blank",rel:"noopener noreferrer",children:"anilist.co/settings/developer"}),", set its ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:`${window.location.origin}/api/tracker/anilist/callback`}),", then paste only the ",e("strong",{children:"Client ID"})," above (leave empty to use dango's)."]}):e(g,{children:["No shipped client in this build - create your own app at"," ",e("a",{href:"https://anilist.co/settings/developer",target:"_blank",rel:"noopener noreferrer",children:"anilist.co/settings/developer"}),", set ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:`${window.location.origin}/api/tracker/anilist/callback`}),", then paste the"," ",e("strong",{children:"Client ID"})," above."]})})]})}function Ke({kind:N="anime",active:C=!0}){const h=V(),[t,y]=i(""),[b,l]=i(""),[L,d]=i(""),[k,u]=i(""),_=ye(!1),{data:o}=R({queryKey:[s.malClientConfig],queryFn:()=>c.tracker.malConfig.query()}),{data:P}=R({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query(),refetchInterval:15e3});Y(()=>{o&&!_.current&&(y(o.clientId),_.current=!0)},[o]);const p=S({mutationFn:async()=>{d(""),(b.trim()||t.trim()&&t.trim()!==o?.clientId)&&await c.tracker.malSaveConfig.mutate({clientId:t.trim(),clientSecret:b.trim()||void 0}),l("");const f=await c.tracker.malLogin.mutate({redirectUri:`${window.location.origin}/api/tracker/mal/callback`});window.location.assign(f.url)},onError:f=>d(f.message)}),M=S({mutationFn:()=>c.tracker.malDisconnect.mutate(),onSuccess:()=>{h.invalidateQueries({queryKey:[s.trackerStatus]}),u(""),d(""),r.success("Disconnected from MyAnimeList")},onError:f=>d(f.message)}),B=S({mutationFn:()=>c.tracker.malClearConfig.mutate(),onSuccess:()=>{y(""),l(""),u(""),d(""),h.invalidateQueries({queryKey:[s.trackerStatus]}),h.invalidateQueries({queryKey:[s.malClientConfig]}),r.success("Switched to dango's MyAnimeList app - reconnect to finish")},onError:f=>d(f.message)}),D=S({mutationFn:()=>N==="manga"?c.tracker.mangaMalSync.mutate():c.tracker.sync.mutate({provider:"mal"}),onSuccess:f=>{const T=f.summary;u(`Pushed: ${T.pushed} · Pulled: ${T.pulled} · Merged: ${T.merged} · Unchanged: ${T.unchanged}`+(T.errors.length>0?` · ${T.errors.length} error${T.errors.length>1?"s":""}`:""));for(const E of N==="manga"?[[s.trackerStatus],[s.mangaLibrary],[s.mangaContinueReading]]:[[s.trackerStatus],[s.watchlist],[s.continueWatching]])h.invalidateQueries({queryKey:E})},onError:f=>d(f.message)}),x=P?.mal;return e("div",{children:[x?.connected?e(g,{children:[e("div",{className:a.connectedProfile,children:[x.user?.avatar&&e("img",{src:x.user.avatar,alt:"Avatar",className:a.avatar,loading:"lazy",decoding:"async"}),e("div",{className:a.connectedInfo,children:[e("span",{className:a.connectedName,children:x.user?.name||"MyAnimeList user"}),e("span",{className:a.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:a.secondaryBtn,onClick:()=>M.mutate(),disabled:M.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}),C?e(g,{children:[e("button",{className:a.syncBtn,onClick:()=>D.mutate(),disabled:D.isPending,children:[e(m,{name:"sync-alt",className:D.isPending?a.spin:""}),D.isPending?"Syncing...":"Start Sync"]}),k&&e("div",{className:a.syncSummary,children:k})]}):e("p",{className:a.connectedHint,style:{color:"var(--color-warning)"},children:"Not the active tracker - sync disabled."})]}):e("div",{className:a.loginSection,children:[e("p",{className:a.loginText,children:"Log in with MyAnimeList to enable bidirectional progress & status synchronization."}),e("div",{className:a.credentialFields,children:[e("label",{className:`${a.fieldLabel} ${a.credentialField}`,children:[e("span",{children:["Client ID"," ",e("a",{href:"https://myanimelist.net/apiconfig",target:"_blank",rel:"noopener noreferrer",children:["create your own app ",e(m,{name:"external-link-alt",size:9})]}),o?.mode==="worker"&&e("span",{className:a.helpText,children:" — defaults to dango's app"})]}),e("input",{className:a.input,placeholder:o?.mode==="worker"?"dango's app (leave empty)":"Client ID",value:t,onChange:f=>y(f.currentTarget.value),autoComplete:"off"})]}),e("label",{className:`${a.fieldLabel} ${a.credentialField}`,children:[e("span",{children:["Client secret"," ",o?.hasSecret&&!b&&e("span",{className:a.helpText,children:"— saved"})]}),e("input",{className:a.input,type:"password",value:b,onChange:f=>l(f.currentTarget.value),placeholder:o?.mode==="worker"?"dango's app (leave empty)":o?.hasSecret?"Saved — leave blank to keep":"Client secret",autoComplete:"new-password"})]})]}),o?.hasCustomId&&o?.hasWorker&&e("button",{className:a.resetBtn,onClick:()=>B.mutate(),disabled:B.isPending,children:"Use dango's app instead"}),e("p",{className:a.helpText,children:o?.mode==="worker"?e(g,{children:["By default uses dango's client. To use your own MyAnimeList app: create it at"," ",e("a",{href:"https://myanimelist.net/apiconfig",target:"_blank",rel:"noopener noreferrer",children:"myanimelist.net/apiconfig"}),", set its ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:[window.location.origin,"/api/tracker/mal/callback"]}),", then paste its"," ",e("strong",{children:"Client ID"})," and ",e("strong",{children:"Client secret"})," above (leave both empty to use dango's)."]}):e(g,{children:["No shipped client in this build - create your own app at"," ",e("a",{href:"https://myanimelist.net/apiconfig",target:"_blank",rel:"noopener noreferrer",children:"myanimelist.net/apiconfig"}),", set its ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:[window.location.origin,"/api/tracker/mal/callback"]}),", then paste the"," ",e("strong",{children:"Client ID"})," and ",e("strong",{children:"Client secret"})," above. MAL requires the secret even for PKCE apps; it stays on your dango server and is never returned to the browser."]})}),e("button",{className:a.primaryBtn,onClick:()=>p.mutate(),disabled:!(t.trim()&&b.trim()||o?.clientId&&t.trim()===o.clientId&&o.hasSecret||!t.trim()&&!b.trim()&&o?.mode==="worker")||p.isPending,children:p.isPending?"Connecting...":"Connect to MyAnimeList"})]}),L&&e("p",{className:`${a.helpText} ${a.syncErrors}`,role:"alert",children:L}),e("hr",{className:a.divider}),e("p",{className:a.syncHint,children:"You can also import a public list or XML file without connecting an account:"})]})}const In=()=>{const{setIsOpen:N}=aa(),{contentType:C}=na(),h=C==="manga",t=V();ea.useEffect(()=>{document.title="Trackers - dango"},[]);const[y,b]=i(""),[l,L]=i("username"),[d,k]=i(null),[u,_]=i(!1);ta();const{data:o,isLoading:P}=R({queryKey:[s.trackerStatus],queryFn:async()=>await c.tracker.status.query()}),p=o?.anilist?.connected??!1,M=o?.mal?.connected??!1,{data:B}=R({queryKey:["activeTrackerProvider"],queryFn:async()=>(await c.settings.getByKey.query({key:"active_tracker_provider"}))?.value||""}),D=S({mutationFn:async n=>(await c.settings.set.mutate({key:"active_tracker_provider",value:n}),n),onSuccess:n=>{t.invalidateQueries({queryKey:["activeTrackerProvider"]}),r.success(`Active tracker set to ${n==="mal"?"MyAnimeList":"AniList"}`)},onError:()=>r.error("Failed to update active tracker")}),x=B&&(B==="anilist"&&p||B==="mal"&&M)?B:p&&!M?"anilist":M&&!p?"mal":p?"anilist":"",f=p||M;Y(()=>{p&&L("sync")},[p]);const T=S({mutationFn:async()=>(await c.tracker.sync.mutate({provider:"anilist"})).summary,onSuccess:n=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),k(n),r.success(`Sync complete - pushed ${n.pushed}, pulled ${n.pulled}, merged ${n.merged}, unchanged ${n.unchanged}`,{duration:6e3})},onError:n=>r.error(n.message)}),[E,ke]=i(""),[Z,fe]=i("sync"),[ce,_e]=i("two-way"),[w,Ue]=i(null),ee=S({mutationFn:async()=>(await c.tracker.mangaSync.mutate({direction:ce})).summary,onSuccess:n=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),Ue(n);const v=(n.warnings?.length??0)>0?`, ${n.warnings.length} warning(s)`:"";r.success(`Manga sync complete - pushed ${n.pushed}, pulled ${n.pulled}, merged ${n.merged}, unchanged ${n.unchanged}${v}`,{duration:6e3})},onError:n=>r.error(n.message)}),q=S({mutationFn:async()=>{if(!E.trim())throw new Error("Please enter a username");return(await c.tracker.mangaImport.mutate({username:E.trim(),erase:u})).count},onSuccess:n=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${n} manga entries from AniList`),ke("")},onError:n=>r.error(n.message)}),[U,be]=i(""),[ae,ve]=i("username"),[oe,Ne]=i(null),[ne,we]=i(!1),[Ce,le]=i(""),[Ie,Qe]=i(""),j=S({mutationFn:async()=>{if(!U.trim())throw new Error("Please enter a MAL username");const n=await c.tracker.mangaMalImport.mutate({username:U.trim(),erase:u});return{imported:n.imported??0,skipped:n.skipped??0}},onSuccess:({imported:n,skipped:v})=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${n} manga entries from MAL${v>0?`, skipped ${v}`:""}`),be("")},onError:n=>r.error(n.message)}),Oe=De(async()=>{const n=document.getElementById("malMangaFile");if(!n.files||n.files.length===0){le("Please select a file first.");return}we(!0),le(""),Ne(null);try{const v=new FormData;v.append("xmlfile",n.files[0]),v.append("erase",String(u));const W=await qe("/api/import/mal-xml-manga",{method:"POST",body:v}),I=await W.json().catch(()=>({}));if(!W.ok)throw new Error(I.error||"Import failed");Ne({imported:I.imported??0,skipped:I.skipped??0}),t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]})}catch(v){le(v.message)}finally{we(!1)}},[u,t]),$=S({mutationFn:async()=>{if(!y.trim())throw new Error("Please enter a username");return(await c.tracker.anilistImport.mutate({username:y.trim(),erase:F})).count},onSuccess:n=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${n} anime entries from AniList`),b("")},onError:n=>r.error(n.message)}),[Q,Se]=i(""),z=S({mutationFn:async n=>{if(!Q.trim())throw new Error("Please enter a MAL username");return(await c.tracker.malImport.mutate({username:Q.trim(),erase:n.erase,useOfflineDb:n.useOfflineDb,skipFallback:n.skipFallback})).count},onSuccess:n=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${n} anime entries from MAL`),Se("")},onError:n=>r.error(n.message)}),[F,Le]=i(!1),[O,He]=i(!0),[H,Ge]=i(!1),[Me,xe]=i(""),[K,Te]=i(!1),[A,Ae]=i(null),[de,ze]=i(null),[Pe,te]=i(""),me=ye(null),We=n=>{n.currentTarget.files&&n.currentTarget.files.length>0?xe(n.currentTarget.files[0].name):xe("")},Xe=De(async()=>{const n=document.getElementById("malFile");if(!n.files||n.files.length===0){te("Please select a file first.");return}const v=n.files[0];Te(!0),Ae(null),ze(null),te("");const W=new AbortController;me.current=W;try{const I=new FormData;I.append("xmlfile",v),I.append("erase",String(F)),I.append("useOfflineDb",String(O)),I.append("skipFallback",String(H));const ue=await qe("/api/import/mal-xml",{method:"POST",body:I,signal:W.signal});if(!ue.ok){const he=await ue.text();let X="Failed to import";try{X=JSON.parse(he).error||X}catch{}throw new Error(X)}const Be=ue.body?.getReader();if(!Be)throw new Error("No response stream");const Ve=new TextDecoder;let pe="",se="";for(;;){const{done:he,value:X}=await Be.read();if(he)break;pe+=Ve.decode(X,{stream:!0});const Ee=pe.split(`
|
|
1
|
+
import{h as Y,d as i,A as ye,u as e,S as g,g as ea,q as De}from"./vendor-core-DfaOB3Rn.js";import{u as V,b as R,a as S}from"./vendor-query-BBT5_sHx.js";import{J as r,q as s,t as c,ap as aa,v as na,X as qe,B as ge}from"./index-CD7a-Eff.js";import{I as m}from"./vendor-icons-DrybRNxP.js";function ta(){const N=V();Y(()=>{const C=new URLSearchParams(window.location.search),h=C.get("mal");if(!h)return;const t=C.get("user"),y=C.get("reason");window.history.replaceState(null,"",window.location.pathname),h==="success"?(r.success(t?`Connected to MyAnimeList as ${decodeURIComponent(t)}`:"Connected to MyAnimeList"),N.invalidateQueries({queryKey:[s.trackerStatus]})):r.error(y?decodeURIComponent(y):"MyAnimeList authentication failed")},[N])}function sa(){const N=V(),[C,h]=i(!1);return Y(()=>{const t=new URLSearchParams(window.location.search),y=t.get("anilist");if(y){const k=t.get("user"),u=t.get("reason");window.history.replaceState(null,"",window.location.pathname),y==="success"?(r.success(k?`Connected to AniList as ${decodeURIComponent(k)}`:"Connected to AniList"),N.invalidateQueries({queryKey:[s.trackerStatus]})):r.error(u?decodeURIComponent(u):"AniList authentication failed");return}const b=new URLSearchParams(window.location.hash.substring(1)),l=b.get("access_token"),L=t.get("code");if(!l&&!L){const k=b.get("error");k&&(r.error(`AniList error: ${k}`),window.history.replaceState(null,"",window.location.pathname));return}const d=window.location.origin+window.location.pathname;window.history.replaceState(null,"",window.location.pathname),h(!0),r("Connecting to AniList..."),c.tracker.anilistAuth.mutate(l?{token:l}:{code:L,redirectUri:d}).then(async k=>{const u=k.user;r.success(`Connected to AniList as ${u?.name??"AniList user"}`),N.invalidateQueries({queryKey:[s.trackerStatus]})}).catch(k=>{r.error(k instanceof Error?k.message:"Failed to authenticate with AniList")}).finally(()=>{h(!1)})},[N]),C}const ia="_header_azjok_1",ra="_fadeIn_azjok_1",ca="_pageTitle_azjok_6",oa="_pageSubtitle_azjok_14",la="_importCard_azjok_20",da="_cardHeader_azjok_31",ma="_uploadArea_azjok_49",ua="_fileInputWrapper_azjok_53",pa="_fileInput_azjok_53",ha="_fileDisplay_azjok_71",ga="_fileIcon_azjok_79",ya="_fileName_azjok_84",ka="_browseButton_azjok_93",fa="_optionsArea_azjok_104",_a="_checkboxLabel_azjok_112",ba="_checkbox_azjok_112",va="_checkboxCustom_azjok_125",Na="_optionText_azjok_153",wa="_optionTitle_azjok_159",Ca="_optionDesc_azjok_165",Ia="_actions_azjok_171",Sa="_importBtn_azjok_179",La="_cancelBtn_azjok_185",Ma="_statusMessage_azjok_199",xa="_success_azjok_209",Ta="_error_azjok_215",Aa="_progressSection_azjok_221",za="_progressBar_azjok_226",Pa="_progressFill_azjok_234",ja="_progressInfo_azjok_241",Ba="_progressCount_azjok_248",Ea="_progressTitle_azjok_255",Fa="_sourceBadge_azjok_273",Da="_anilist_azjok_285",qa="_kitsu_azjok_291",$a="_offline_azjok_297",Ka="_skipped_azjok_303",Ra="_cardTitleRow_azjok_308",Ua="_anilistIcon_azjok_318",Qa="_malIcon_azjok_324",Oa="_badgeOnline_azjok_330",Ha="_badgeOffline_azjok_342",Ga="_connectedProfile_azjok_354",Wa="_avatar_azjok_361",Xa="_connectedInfo_azjok_368",Ja="_connectedName_azjok_376",Ya="_connectedHint_azjok_382",Va="_loginPrompt_azjok_387",Za="_loginSection_azjok_395",en="_primaryBtn_azjok_401",an="_fieldLabel_azjok_405",nn="_helpText_azjok_424",tn="_resetBtn_azjok_431",sn="_loginText_azjok_461",rn="_secondaryBtn_azjok_471",cn="_syncBtn_azjok_472",on="_divider_azjok_525",ln="_actionSection_azjok_531",dn="_inputGroup_azjok_545",mn="_credentialFields_azjok_551",un="_credentialField_azjok_551",pn="_input_azjok_545",hn="_syncSummary_azjok_587",gn="_syncErrors_azjok_593",yn="_spin_azjok_597",kn="_radioGroup_azjok_616",fn="_radioLabel_azjok_623",_n="_syncHint_azjok_661",bn="_importLoading_azjok_668",a={header:ia,fadeIn:ra,pageTitle:ca,pageSubtitle:oa,importCard:la,cardHeader:da,uploadArea:ma,fileInputWrapper:ua,fileInput:pa,fileDisplay:ha,fileIcon:ga,fileName:ya,browseButton:ka,optionsArea:fa,checkboxLabel:_a,checkbox:ba,checkboxCustom:va,optionText:Na,optionTitle:wa,optionDesc:Ca,actions:Ia,importBtn:Sa,cancelBtn:La,statusMessage:Ma,success:xa,error:Ta,progressSection:Aa,progressBar:za,progressFill:Pa,progressInfo:ja,progressCount:Ba,progressTitle:Ea,sourceBadge:Fa,anilist:Da,kitsu:qa,offline:$a,skipped:Ka,cardTitleRow:Ra,anilistIcon:Ua,malIcon:Qa,badgeOnline:Oa,badgeOffline:Ha,connectedProfile:Ga,avatar:Wa,connectedInfo:Xa,connectedName:Ja,connectedHint:Ya,loginPrompt:Va,loginSection:Za,primaryBtn:en,fieldLabel:an,helpText:nn,resetBtn:tn,loginText:sn,secondaryBtn:rn,syncBtn:cn,divider:on,actionSection:ln,inputGroup:dn,credentialFields:mn,credentialField:un,input:pn,syncSummary:hn,syncErrors:gn,spin:yn,radioGroup:kn,radioLabel:fn,syncHint:_n,importLoading:bn},ie="tracker_anilist_client_id",Re="49887".trim(),re=!!Re;function $e(){const N=V(),[C,h]=i(""),t=ye(!1),y=sa(),{data:b}=R({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query()}),{data:l}=R({queryKey:[s.anilistClientId],queryFn:async()=>(await c.settings.getByKey.query({key:ie})).value||""});Y(()=>{t.current||l===void 0||(l&&h(l),t.current=!0)},[l]);const L=S({mutationFn:()=>c.tracker.anilistDisconnect.mutate(),onSuccess:()=>{N.invalidateQueries({queryKey:[s.trackerStatus]}),r.success("Disconnected from AniList")},onError:_=>r.error(_.message)}),d=S({mutationFn:()=>c.settings.set.mutate({key:ie,value:""}),onSuccess:()=>{h(""),N.invalidateQueries({queryKey:[s.anilistClientId]}),r.success("Switched to dango's AniList app")},onError:_=>r.error(_.message)}),k=async()=>{const _=C.trim(),o=_||Re;if(!o){r.error("Enter your AniList client ID first");return}const P=(l||"").trim();try{_?_!==l&&await c.settings.set.mutate({key:ie,value:_}):re&&P&&await c.settings.set.mutate({key:ie,value:""}),N.invalidateQueries({queryKey:[s.anilistClientId]})}catch(M){r.error(M.message);return}const p=encodeURIComponent(window.location.origin+window.location.pathname);window.location.href=`https://anilist.co/api/v2/oauth/authorize?client_id=${encodeURIComponent(o)}&response_type=token&state=${p}`},u=b?.anilist?.user??null;return b?.anilist?.connected&&u?e("div",{className:a.connectedProfile,children:[u.avatar&&e("img",{src:u.avatar,alt:"Avatar",className:a.avatar,loading:"lazy",decoding:"async"}),e("div",{className:a.connectedInfo,children:[e("span",{className:a.connectedName,children:u.name}),e("span",{className:a.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:a.secondaryBtn,onClick:()=>L.mutate(),disabled:L.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}):e("div",{className:a.loginSection,children:[e("p",{className:a.loginText,children:["Log in with AniList to enable bidirectional progress & status synchronization.",y&&e("span",{style:{marginLeft:8,color:"var(--accent)"},children:"Finishing login…"})]}),e("div",{className:a.fieldLabel,children:["AniList client ID - defaults to dango's app"," ",e("a",{href:"https://anilist.co/settings/developer",target:"_blank",rel:"noopener noreferrer",children:["create your own app ",e(m,{name:"external-link-alt",size:9})]})]}),e("div",{className:a.inputGroup,children:[e("input",{type:"text",placeholder:"Client ID",value:C,onChange:_=>h(_.currentTarget.value),className:a.input}),e("button",{className:a.primaryBtn,onClick:k,disabled:!(C.trim()||re),children:[e(m,{name:"external-link-alt"})," Connect"]})]}),re&&l&&e("button",{className:a.resetBtn,onClick:()=>d.mutate(),disabled:d.isPending,children:"Use dango's app instead"}),e("p",{className:a.helpText,children:re?e(g,{children:["By default uses dango's client. To use your own AniList app: create it at"," ",e("a",{href:"https://anilist.co/settings/developer",target:"_blank",rel:"noopener noreferrer",children:"anilist.co/settings/developer"}),", set its ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:`${window.location.origin}/api/tracker/anilist/callback`}),", then paste only the ",e("strong",{children:"Client ID"})," above (leave empty to use dango's)."]}):e(g,{children:["No shipped client in this build - create your own app at"," ",e("a",{href:"https://anilist.co/settings/developer",target:"_blank",rel:"noopener noreferrer",children:"anilist.co/settings/developer"}),", set ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:`${window.location.origin}/api/tracker/anilist/callback`}),", then paste the"," ",e("strong",{children:"Client ID"})," above."]})})]})}function Ke({kind:N="anime",active:C=!0}){const h=V(),[t,y]=i(""),[b,l]=i(""),[L,d]=i(""),[k,u]=i(""),_=ye(!1),{data:o}=R({queryKey:[s.malClientConfig],queryFn:()=>c.tracker.malConfig.query()}),{data:P}=R({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query(),refetchInterval:15e3});Y(()=>{o&&!_.current&&(y(o.clientId),_.current=!0)},[o]);const p=S({mutationFn:async()=>{d(""),(b.trim()||t.trim()&&t.trim()!==o?.clientId)&&await c.tracker.malSaveConfig.mutate({clientId:t.trim(),clientSecret:b.trim()||void 0}),l("");const f=await c.tracker.malLogin.mutate({redirectUri:`${window.location.origin}/api/tracker/mal/callback`});window.location.assign(f.url)},onError:f=>d(f.message)}),M=S({mutationFn:()=>c.tracker.malDisconnect.mutate(),onSuccess:()=>{h.invalidateQueries({queryKey:[s.trackerStatus]}),u(""),d(""),r.success("Disconnected from MyAnimeList")},onError:f=>d(f.message)}),B=S({mutationFn:()=>c.tracker.malClearConfig.mutate(),onSuccess:()=>{y(""),l(""),u(""),d(""),h.invalidateQueries({queryKey:[s.trackerStatus]}),h.invalidateQueries({queryKey:[s.malClientConfig]}),r.success("Switched to dango's MyAnimeList app - reconnect to finish")},onError:f=>d(f.message)}),D=S({mutationFn:()=>N==="manga"?c.tracker.mangaMalSync.mutate():c.tracker.sync.mutate({provider:"mal"}),onSuccess:f=>{const T=f.summary;u(`Pushed: ${T.pushed} · Pulled: ${T.pulled} · Merged: ${T.merged} · Unchanged: ${T.unchanged}`+(T.errors.length>0?` · ${T.errors.length} error${T.errors.length>1?"s":""}`:""));for(const E of N==="manga"?[[s.trackerStatus],[s.mangaLibrary],[s.mangaContinueReading]]:[[s.trackerStatus],[s.watchlist],[s.continueWatching]])h.invalidateQueries({queryKey:E})},onError:f=>d(f.message)}),x=P?.mal;return e("div",{children:[x?.connected?e(g,{children:[e("div",{className:a.connectedProfile,children:[x.user?.avatar&&e("img",{src:x.user.avatar,alt:"Avatar",className:a.avatar,loading:"lazy",decoding:"async"}),e("div",{className:a.connectedInfo,children:[e("span",{className:a.connectedName,children:x.user?.name||"MyAnimeList user"}),e("span",{className:a.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:a.secondaryBtn,onClick:()=>M.mutate(),disabled:M.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}),C?e(g,{children:[e("button",{className:a.syncBtn,onClick:()=>D.mutate(),disabled:D.isPending,children:[e(m,{name:"sync-alt",className:D.isPending?a.spin:""}),D.isPending?"Syncing...":"Start Sync"]}),k&&e("div",{className:a.syncSummary,children:k})]}):e("p",{className:a.connectedHint,style:{color:"var(--color-warning)"},children:"Not the active tracker - sync disabled."})]}):e("div",{className:a.loginSection,children:[e("p",{className:a.loginText,children:"Log in with MyAnimeList to enable bidirectional progress & status synchronization."}),e("div",{className:a.credentialFields,children:[e("label",{className:`${a.fieldLabel} ${a.credentialField}`,children:[e("span",{children:["Client ID"," ",e("a",{href:"https://myanimelist.net/apiconfig",target:"_blank",rel:"noopener noreferrer",children:["create your own app ",e(m,{name:"external-link-alt",size:9})]}),o?.mode==="worker"&&e("span",{className:a.helpText,children:" — defaults to dango's app"})]}),e("input",{className:a.input,placeholder:o?.mode==="worker"?"dango's app (leave empty)":"Client ID",value:t,onChange:f=>y(f.currentTarget.value),autoComplete:"off"})]}),e("label",{className:`${a.fieldLabel} ${a.credentialField}`,children:[e("span",{children:["Client secret"," ",o?.hasSecret&&!b&&e("span",{className:a.helpText,children:"— saved"})]}),e("input",{className:a.input,type:"password",value:b,onChange:f=>l(f.currentTarget.value),placeholder:o?.mode==="worker"?"dango's app (leave empty)":o?.hasSecret?"Saved — leave blank to keep":"Client secret",autoComplete:"new-password"})]})]}),o?.hasCustomId&&o?.hasWorker&&e("button",{className:a.resetBtn,onClick:()=>B.mutate(),disabled:B.isPending,children:"Use dango's app instead"}),e("p",{className:a.helpText,children:o?.mode==="worker"?e(g,{children:["By default uses dango's client. To use your own MyAnimeList app: create it at"," ",e("a",{href:"https://myanimelist.net/apiconfig",target:"_blank",rel:"noopener noreferrer",children:"myanimelist.net/apiconfig"}),", set its ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:[window.location.origin,"/api/tracker/mal/callback"]}),", then paste its"," ",e("strong",{children:"Client ID"})," and ",e("strong",{children:"Client secret"})," above (leave both empty to use dango's)."]}):e(g,{children:["No shipped client in this build - create your own app at"," ",e("a",{href:"https://myanimelist.net/apiconfig",target:"_blank",rel:"noopener noreferrer",children:"myanimelist.net/apiconfig"}),", set its ",e("strong",{children:"Redirect URL"})," to"," ",e("code",{children:[window.location.origin,"/api/tracker/mal/callback"]}),", then paste the"," ",e("strong",{children:"Client ID"})," and ",e("strong",{children:"Client secret"})," above. MAL requires the secret even for PKCE apps; it stays on your dango server and is never returned to the browser."]})}),e("button",{className:a.primaryBtn,onClick:()=>p.mutate(),disabled:!(t.trim()&&b.trim()||o?.clientId&&t.trim()===o.clientId&&o.hasSecret||!t.trim()&&!b.trim()&&o?.mode==="worker")||p.isPending,children:p.isPending?"Connecting...":"Connect to MyAnimeList"})]}),L&&e("p",{className:`${a.helpText} ${a.syncErrors}`,role:"alert",children:L}),e("hr",{className:a.divider}),e("p",{className:a.syncHint,children:"You can also import a public list or XML file without connecting an account:"})]})}const In=()=>{const{setIsOpen:N}=aa(),{contentType:C}=na(),h=C==="manga",t=V();ea.useEffect(()=>{document.title="Trackers - dango"},[]);const[y,b]=i(""),[l,L]=i("username"),[d,k]=i(null),[u,_]=i(!1);ta();const{data:o,isLoading:P}=R({queryKey:[s.trackerStatus],queryFn:async()=>await c.tracker.status.query()}),p=o?.anilist?.connected??!1,M=o?.mal?.connected??!1,{data:B}=R({queryKey:["activeTrackerProvider"],queryFn:async()=>(await c.settings.getByKey.query({key:"active_tracker_provider"}))?.value||""}),D=S({mutationFn:async n=>(await c.settings.set.mutate({key:"active_tracker_provider",value:n}),n),onSuccess:n=>{t.invalidateQueries({queryKey:["activeTrackerProvider"]}),r.success(`Active tracker set to ${n==="mal"?"MyAnimeList":"AniList"}`)},onError:()=>r.error("Failed to update active tracker")}),x=B&&(B==="anilist"&&p||B==="mal"&&M)?B:p&&!M?"anilist":M&&!p?"mal":p?"anilist":"",f=p||M;Y(()=>{p&&L("sync")},[p]);const T=S({mutationFn:async()=>(await c.tracker.sync.mutate({provider:"anilist"})).summary,onSuccess:n=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),k(n),r.success(`Sync complete - pushed ${n.pushed}, pulled ${n.pulled}, merged ${n.merged}, unchanged ${n.unchanged}`,{duration:6e3})},onError:n=>r.error(n.message)}),[E,ke]=i(""),[Z,fe]=i("sync"),[ce,_e]=i("two-way"),[w,Ue]=i(null),ee=S({mutationFn:async()=>(await c.tracker.mangaSync.mutate({direction:ce})).summary,onSuccess:n=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),Ue(n);const v=(n.warnings?.length??0)>0?`, ${n.warnings.length} warning(s)`:"";r.success(`Manga sync complete - pushed ${n.pushed}, pulled ${n.pulled}, merged ${n.merged}, unchanged ${n.unchanged}${v}`,{duration:6e3})},onError:n=>r.error(n.message)}),q=S({mutationFn:async()=>{if(!E.trim())throw new Error("Please enter a username");return(await c.tracker.mangaImport.mutate({username:E.trim(),erase:u})).count},onSuccess:n=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${n} manga entries from AniList`),ke("")},onError:n=>r.error(n.message)}),[U,be]=i(""),[ae,ve]=i("username"),[oe,Ne]=i(null),[ne,we]=i(!1),[Ce,le]=i(""),[Ie,Qe]=i(""),j=S({mutationFn:async()=>{if(!U.trim())throw new Error("Please enter a MAL username");const n=await c.tracker.mangaMalImport.mutate({username:U.trim(),erase:u});return{imported:n.imported??0,skipped:n.skipped??0}},onSuccess:({imported:n,skipped:v})=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${n} manga entries from MAL${v>0?`, skipped ${v}`:""}`),be("")},onError:n=>r.error(n.message)}),Oe=De(async()=>{const n=document.getElementById("malMangaFile");if(!n.files||n.files.length===0){le("Please select a file first.");return}we(!0),le(""),Ne(null);try{const v=new FormData;v.append("xmlfile",n.files[0]),v.append("erase",String(u));const W=await qe("/api/import/mal-xml-manga",{method:"POST",body:v}),I=await W.json().catch(()=>({}));if(!W.ok)throw new Error(I.error||"Import failed");Ne({imported:I.imported??0,skipped:I.skipped??0}),t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]})}catch(v){le(v.message)}finally{we(!1)}},[u,t]),$=S({mutationFn:async()=>{if(!y.trim())throw new Error("Please enter a username");return(await c.tracker.anilistImport.mutate({username:y.trim(),erase:F})).count},onSuccess:n=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${n} anime entries from AniList`),b("")},onError:n=>r.error(n.message)}),[Q,Se]=i(""),z=S({mutationFn:async n=>{if(!Q.trim())throw new Error("Please enter a MAL username");return(await c.tracker.malImport.mutate({username:Q.trim(),erase:n.erase,useOfflineDb:n.useOfflineDb,skipFallback:n.skipFallback})).count},onSuccess:n=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${n} anime entries from MAL`),Se("")},onError:n=>r.error(n.message)}),[F,Le]=i(!1),[O,He]=i(!0),[H,Ge]=i(!1),[Me,xe]=i(""),[K,Te]=i(!1),[A,Ae]=i(null),[de,ze]=i(null),[Pe,te]=i(""),me=ye(null),We=n=>{n.currentTarget.files&&n.currentTarget.files.length>0?xe(n.currentTarget.files[0].name):xe("")},Xe=De(async()=>{const n=document.getElementById("malFile");if(!n.files||n.files.length===0){te("Please select a file first.");return}const v=n.files[0];Te(!0),Ae(null),ze(null),te("");const W=new AbortController;me.current=W;try{const I=new FormData;I.append("xmlfile",v),I.append("erase",String(F)),I.append("useOfflineDb",String(O)),I.append("skipFallback",String(H));const ue=await qe("/api/import/mal-xml",{method:"POST",body:I,signal:W.signal});if(!ue.ok){const he=await ue.text();let X="Failed to import";try{X=JSON.parse(he).error||X}catch{}throw new Error(X)}const Be=ue.body?.getReader();if(!Be)throw new Error("No response stream");const Ve=new TextDecoder;let pe="",se="";for(;;){const{done:he,value:X}=await Be.read();if(he)break;pe+=Ve.decode(X,{stream:!0});const Ee=pe.split(`
|
|
2
2
|
`);pe=Ee.pop()||"";for(const J of Ee)if(J.startsWith("event: "))se=J.slice(7).trim();else if(J.startsWith("data: ")){const Ze=J.slice(6);try{const Fe=JSON.parse(Ze);se==="progress"?Ae(Fe):se==="complete"&&ze(Fe)}catch{}}else J===""&&(se="")}t.invalidateQueries({queryKey:[s.watchlist]})}catch(I){I instanceof DOMException&&I.name==="AbortError"?te("Import cancelled."):te(I.message)}finally{Te(!1),me.current=null}},[F,O,H,t]),Je=()=>{me.current?.abort(),c.settings.malImportCancel.mutate().catch(()=>{})},Ye=A?Math.round(A.current/A.total*100):0,[G,je]=i("username");return e("div",{className:"page-container",children:[e("div",{className:a.header,children:[e("h1",{className:a.pageTitle,children:"Trackers"}),e("p",{className:a.pageSubtitle,children:"Import & sync your anime watchlists and manga reading lists with tracking services"})]}),e("div",{style:{marginBottom:"16px",fontSize:"0.8rem",color:"var(--color-warning)",borderBottom:"1px solid var(--border-primary)",paddingBottom:"12px"},children:"⚠ Syncing writes directly to your AniList and MyAnimeList entries, and dango may not always handle anime/manga lists correctly - always keep a backup of your lists before syncing."}),f&&e("div",{style:{marginBottom:"16px",display:"flex",alignItems:"center",gap:"10px",fontSize:"0.85rem"},children:[e("label",{htmlFor:"active-tracker-select",style:{fontWeight:600,color:"var(--text-secondary)"},children:"Active tracker:"}),e("select",{id:"active-tracker-select",value:x,onChange:n=>D.mutate(n.currentTarget.value),style:{padding:"0.3rem 0.5rem",borderRadius:"var(--radius-md)",background:"var(--bg-tertiary)",color:"var(--text-primary)",border:"1px solid var(--border-primary)",fontSize:"var(--font-size-sm)",cursor:"pointer"},children:[p&&e("option",{value:"anilist",children:"AniList"}),M&&e("option",{value:"mal",children:"MyAnimeList"})]})]}),!h&&e(g,{children:e("div",{className:a.importCard,children:[e("div",{className:a.cardHeader,children:e("div",{className:a.cardTitleRow,children:[e(m,{name:"anilist",className:a.anilistIcon}),e("h3",{children:"AniList"}),P?null:p?e("span",{className:a.badgeOnline,children:"Connected"}):e("span",{className:a.badgeOffline,children:"Not connected"})]})}),e($e,{}),p&&x!=="anilist"&&e("p",{style:{color:"var(--color-warning)",marginTop:"8px",fontSize:"0.85rem"},children:"Not the active tracker - sync disabled."}),p&&x==="anilist"&&e(g,{children:[e("hr",{className:a.divider}),e("div",{className:a.radioGroup,children:[e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"anilistMode",value:"username",checked:l==="username",onChange:()=>L("username")}),e("span",{children:"Quick Import"})]}),e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"anilistMode",value:"sync",checked:l==="sync",onChange:()=>L("sync")}),e("span",{children:"Two-way Sync"})]})]}),l==="username"?e("div",{className:a.inputGroup,children:e("input",{type:"text",placeholder:"Enter AniList username",value:y,onChange:n=>b(n.currentTarget.value),className:a.input,disabled:$.isPending,onKeyDown:n=>{n.key==="Enter"&&y.trim()&&$.mutate()}})}):e("p",{className:a.syncHint,children:"Merges progress non-destructively: pushes shows and episodes you watched on dango to AniList, and pulls anything you updated on AniList into dango."}),l==="username"&&e("div",{className:a.optionsArea,children:e("label",{className:a.checkboxLabel,children:[e("input",{type:"checkbox",checked:F,onChange:n=>Le(n.currentTarget.checked),className:a.checkbox,disabled:$.isPending}),e("span",{className:a.checkboxCustom}),e("div",{className:a.optionText,children:[e("span",{className:a.optionTitle,children:"Erase current watchlist"}),e("span",{className:a.optionDesc,children:"Delete existing watchlist before importing."})]})]})}),l==="username"?e("button",{className:a.syncBtn,onClick:()=>$.mutate(),disabled:!y.trim()||$.isPending,children:[e(m,{name:"download"}),$.isPending?"Importing...":"Start Import"]}):e(g,{children:[e("button",{className:a.syncBtn,onClick:()=>T.mutate(),disabled:T.isPending,children:[e(m,{name:"sync-alt",className:T.isPending?a.spin:""}),T.isPending?"Syncing...":"Start Sync"]}),d&&e("div",{className:a.syncSummary,children:["Pushed: ",d.pushed," · Pulled: ",d.pulled," · Merged:"," ",d.merged," · Unchanged: ",d.unchanged,d.errors.length>0&&e("span",{className:a.syncErrors,children:[" ","· ",d.errors.length," error",d.errors.length>1?"s":""]})]})]})]})]})}),h&&e(g,{children:e("div",{className:a.importCard,children:[e("div",{className:a.cardHeader,children:e("div",{className:a.cardTitleRow,children:[e(m,{name:"anilist",className:a.anilistIcon}),e("h3",{children:"AniList Manga"}),P?null:p?e("span",{className:a.badgeOnline,children:"Connected"}):e("span",{className:a.badgeOffline,children:"Not connected"})]})}),e($e,{}),p&&x!=="anilist"&&e("p",{style:{color:"var(--color-warning)",marginTop:"8px",fontSize:"0.85rem"},children:"Not the active tracker - sync disabled."}),p&&x==="anilist"&&e(g,{children:[e("hr",{className:a.divider}),e("div",{className:a.radioGroup,children:[e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"mangaMode",value:"username",checked:Z==="username",onChange:()=>fe("username")}),e("span",{children:"Quick Import"})]}),e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"mangaMode",value:"sync",checked:Z==="sync",onChange:()=>fe("sync")}),e("span",{children:"Two-way Sync"})]})]}),Z==="username"?e(g,{children:[e("div",{className:a.inputGroup,children:e("input",{type:"text",placeholder:"Enter AniList username",value:E,onChange:n=>ke(n.currentTarget.value),className:a.input,disabled:q.isPending,onKeyDown:n=>{n.key==="Enter"&&E.trim()&&q.mutate()}})}),e("div",{className:a.optionsArea,children:e("label",{className:a.checkboxLabel,children:[e("input",{type:"checkbox",checked:u,onChange:n=>_(n.currentTarget.checked),className:a.checkbox,disabled:q.isPending}),e("span",{className:a.checkboxCustom}),e("div",{className:a.optionText,children:[e("span",{className:a.optionTitle,children:"Replace AniList-linked manga"}),e("span",{className:a.optionDesc,children:"Clears previously imported (anilist:) entries before importing. Your provider bookmarks are never touched."})]})]})})]}):e(g,{children:[e("p",{className:a.syncHint,children:"Merges chapter progress non-destructively: pushes manga and chapters you read on dango to AniList, and pulls anything you updated on AniList into dango. Local titles are linked only on exact title matches, and bookmarks with no chapters read are never pushed."}),e("div",{className:a.radioGroup,children:[e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"mangaDirection",value:"two-way",checked:ce==="two-way",onChange:()=>_e("two-way")}),e("span",{children:"Two-way"})]}),e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"mangaDirection",value:"pull-only",checked:ce==="pull-only",onChange:()=>_e("pull-only")}),e("span",{children:"Pull only (never writes to AniList)"})]})]})]}),Z==="username"?e("button",{className:a.syncBtn,onClick:()=>q.mutate(),disabled:!E.trim()||q.isPending,children:[e(m,{name:"download"}),q.isPending?"Importing...":"Start Import"]}):e(g,{children:[e("button",{className:a.syncBtn,onClick:()=>ee.mutate(),disabled:ee.isPending,children:[e(m,{name:"sync-alt",className:ee.isPending?a.spin:""}),ee.isPending?"Syncing...":"Start Manga Sync"]}),w&&e(g,{children:[e("div",{className:a.syncSummary,children:["Pushed: ",w.pushed," · Pulled: ",w.pulled," · Merged: ",w.merged," · Unchanged:"," ",w.unchanged,(w.skipped??0)>0&&e("span",{children:[" · Skipped: ",w.skipped]}),w.errors.length>0&&e("span",{className:a.syncErrors,children:[" ","· ",w.errors.length," error",w.errors.length>1?"s":""]})]}),(w.warnings?.length??0)>0&&e("div",{className:a.syncErrors,style:{marginTop:"8px"},children:[(w.warnings??[]).slice(0,5).map((n,v)=>e("div",{children:["⚠ ",n]},v)),(w.warnings?.length??0)>5&&e("div",{children:["+",(w.warnings?.length??0)-5," more warning(s)"]})]})]})]})]})]})}),!h&&e(g,{children:e("div",{className:a.importCard,children:[e("div",{className:a.cardHeader,children:e("div",{className:a.cardTitleRow,children:[e(m,{name:"myanimelist",className:a.malIcon}),e("h3",{children:"MyAnimeList"}),P?null:M?e("span",{className:a.badgeOnline,children:"Connected"}):e("span",{className:a.badgeOffline,children:"Not connected"})]})}),e(Ke,{active:x==="mal"}),e("div",{className:a.radioGroup,children:[e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"malMode",value:"username",checked:G==="username",onChange:()=>je("username")}),e("span",{children:"Username"})]}),e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"malMode",value:"xml",checked:G==="xml",onChange:()=>je("xml")}),e("span",{children:"XML File"})]})]}),G==="username"?e(g,{children:[e("div",{className:a.inputGroup,children:e("input",{type:"text",placeholder:"Enter MAL username",value:Q,onChange:n=>Se(n.currentTarget.value),className:a.input,disabled:z.isPending,onKeyDown:n=>{n.key==="Enter"&&Q.trim()&&z.mutate({erase:F,useOfflineDb:O,skipFallback:H})}})}),z.isPending&&e("div",{className:a.importLoading,children:[e(m,{name:"sync-alt",className:a.spin}),e("span",{children:"Importing from MAL..."})]})]}):e("div",{className:a.uploadArea,children:e("div",{className:a.fileInputWrapper,children:[e("input",{type:"file",id:"malFile",accept:".xml,application/xml",className:a.fileInput,onChange:We,disabled:K}),e("div",{className:a.fileDisplay,children:[e(m,{name:"file-alt",className:a.fileIcon}),e("span",{className:a.fileName,children:Me||"Choose XML file..."})]}),e("label",{htmlFor:"malFile",className:a.browseButton,children:"Browse"})]})}),e("div",{className:a.optionsArea,children:[e("label",{className:a.checkboxLabel,children:[e("input",{type:"checkbox",checked:F,onChange:n=>Le(n.currentTarget.checked),className:a.checkbox,disabled:K||z.isPending}),e("span",{className:a.checkboxCustom}),e("div",{className:a.optionText,children:[e("span",{className:a.optionTitle,children:"Erase current watchlist"}),e("span",{className:a.optionDesc,children:"Delete existing watchlist before importing."})]})]}),e("label",{className:a.checkboxLabel,children:[e("input",{type:"checkbox",checked:O,onChange:n=>He(n.currentTarget.checked),className:a.checkbox,disabled:K||z.isPending}),e("span",{className:a.checkboxCustom}),e("div",{className:a.optionText,children:[e("span",{className:a.optionTitle,children:"Use offline database (fast)"}),e("span",{className:a.optionDesc,children:"Match by MAL ID locally first - instant and avoids AniList rate limits."})]})]}),e("label",{className:a.checkboxLabel,children:[e("input",{type:"checkbox",checked:H,onChange:n=>Ge(n.currentTarget.checked),className:a.checkbox,disabled:K||z.isPending}),e("span",{className:a.checkboxCustom}),e("div",{className:a.optionText,children:[e("span",{className:a.optionTitle,children:"Skip online fallback"}),e("span",{className:a.optionDesc,children:"Only import offline matches. Unmatched titles are skipped without API calls."})]})]})]}),G==="username"?e("button",{className:a.syncBtn,onClick:()=>z.mutate({erase:F,useOfflineDb:O,skipFallback:H}),disabled:!Q.trim()||z.isPending,children:[e(m,{name:"download"}),z.isPending?"Importing...":"Start Import"]}):e("div",{className:a.actions,children:K?e(ge,{onClick:Je,className:a.cancelBtn,children:"Cancel Import"}):e(ge,{onClick:Xe,className:a.importBtn,disabled:!Me,children:[e(m,{name:"upload"})," Start Import"]})}),G==="username"&&z.isError&&e("div",{className:`${a.statusMessage} ${a.error}`,children:z.error.message}),K&&A&&e("div",{className:a.progressSection,children:[e("div",{className:a.progressBar,children:e("div",{className:a.progressFill,style:{width:`${Ye}%`}})}),e("div",{className:a.progressInfo,children:[e("span",{className:a.progressCount,children:[A.current," / ",A.total]}),e("span",{className:a.progressTitle,children:A.found?e(g,{children:[A.matchedTitle,e("span",{className:`${a.sourceBadge} ${a[A.source||"anilist"]}`,children:A.source==="kitsu"?"Kitsu":A.source==="offline"?"Offline DB":"AniList"})]}):e("span",{className:a.skipped,children:["Skipped: ",A.title]})})]})]}),de&&e("div",{className:`${a.statusMessage} ${a.success}`,children:["Import complete! Imported: ",de.imported,", Skipped: ",de.skipped,"."]}),Pe&&e("div",{className:`${a.statusMessage} ${a.error}`,children:Pe})]})}),h&&e("div",{className:a.importCard,children:[e("div",{className:a.cardHeader,children:e("div",{className:a.cardTitleRow,children:[e(m,{name:"myanimelist",className:a.malIcon}),e("h3",{children:"MyAnimeList Manga"}),P?null:M?e("span",{className:a.badgeOnline,children:"Connected"}):e("span",{className:a.badgeOffline,children:"Not connected"})]})}),e(Ke,{kind:"manga",active:x==="mal"}),e("div",{className:a.radioGroup,children:[e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"malMangaMode",value:"username",checked:ae==="username",onChange:()=>ve("username")}),e("span",{children:"Username"})]}),e("label",{className:a.radioLabel,children:[e("input",{type:"radio",name:"malMangaMode",value:"xml",checked:ae==="xml",onChange:()=>ve("xml")}),e("span",{children:"XML File"})]})]}),ae==="username"?e("div",{className:a.inputGroup,children:e("input",{type:"text",placeholder:"Enter MAL username",value:U,onChange:n=>be(n.currentTarget.value),className:a.input,disabled:j.isPending,onKeyDown:n=>{n.key==="Enter"&&U.trim()&&j.mutate()}})}):e("div",{className:a.uploadArea,children:e("div",{className:a.fileInputWrapper,children:[e("input",{type:"file",id:"malMangaFile",accept:".xml,application/xml",className:a.fileInput,onChange:n=>Qe(n.currentTarget.files?.[0]?.name??""),disabled:ne}),e("div",{className:a.fileDisplay,children:[e(m,{name:"file-alt",className:a.fileIcon}),e("span",{className:a.fileName,children:Ie||"Choose XML file..."})]}),e("label",{htmlFor:"malMangaFile",className:a.browseButton,children:"Browse"})]})}),e("div",{className:a.optionsArea,children:e("label",{className:a.checkboxLabel,children:[e("input",{type:"checkbox",checked:u,onChange:n=>_(n.currentTarget.checked),className:a.checkbox,disabled:j.isPending||ne}),e("span",{className:a.checkboxCustom}),e("div",{className:a.optionText,children:[e("span",{className:a.optionTitle,children:"Replace AniList-linked manga"}),e("span",{className:a.optionDesc,children:"Clears previously imported (anilist:) entries before importing. Your provider bookmarks are never touched."})]})]})}),ae==="username"?e("button",{className:a.syncBtn,onClick:()=>j.mutate(),disabled:!U.trim()||j.isPending,children:[e(m,{name:"download"}),j.isPending?"Importing...":"Start Import"]}):e("div",{className:a.actions,children:e(ge,{onClick:Oe,className:a.importBtn,disabled:ne||!Ie,children:[e(m,{name:"upload"})," ",ne?"Importing...":"Start Import"]})}),j.isError&&e("div",{className:`${a.statusMessage} ${a.error}`,children:j.error.message}),Ce&&e("div",{className:`${a.statusMessage} ${a.error}`,children:Ce}),oe&&e("div",{className:`${a.statusMessage} ${a.success}`,children:["Import complete! Imported: ",oe.imported,", Skipped:"," ",oe.skipped,"."]}),e("p",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginTop:"8px"},children:"MAL manga is matched to AniList by MAL ID with a title fallback. Unmatched titles are skipped. Imports land as AniList-linked entries alongside your provider bookmarks."})]})]})};export{In as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._fullscreenFlat_n2elb_1{border-radius:0}@media(max-width:900px)and (orientation:landscape){._fullscreenFlat_n2elb_1{border-radius:0}}@container (max-width: 26rem){._timeDisplay_n2elb_12{display:none}._bottomControls_n2elb_16{padding:0 .75rem .75rem}._leftControls_n2elb_20,._rightControls_n2elb_21{gap:.2rem}._controlBtn_n2elb_25{padding:5px;min-width:2.125rem;min-height:2.125rem}}._controlsOverlay_n2elb_32{position:absolute;inset:0;opacity:1;transition:opacity .4s cubic-bezier(.4,0,.2,1);z-index:50;pointer-events:none;display:flex;flex-direction:column;justify-content:space-between;background:radial-gradient(circle,transparent 20%,rgba(0,0,0,.4) 100%)}._controlsOverlay_n2elb_32>*{pointer-events:auto}._controlsOverlay_n2elb_32._hidden_n2elb_52{opacity:0;pointer-events:none;cursor:none}._topControls_n2elb_58{position:absolute;top:0;left:0;right:0;display:flex;align-items:center;gap:var(--space-6);background:linear-gradient(to bottom,rgba(0,0,0,.85) 0%,rgba(0,0,0,.45) 60%,transparent 100%);padding:var(--space-8) var(--space-10);transition:transform .4s cubic-bezier(.2,.8,.2,1);z-index:10;pointer-events:auto}._backBtn_n2elb_78{background:transparent;border:none;color:#ffffffd9;font-size:1.6rem;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--transition-fast);padding:8px;border-radius:50%}._backBtn_n2elb_78:hover{background:#0f0f1199;color:#fff;transform:scale(1.1)}._videoTitleInfo_n2elb_98{display:flex;flex-direction:column;gap:.25rem}._animeTitle_n2elb_104{font-size:1.4rem;font-weight:800;color:#fff;letter-spacing:-.01em;text-shadow:0 2px 4px rgba(0,0,0,.5)}._episodeLabel_n2elb_112{font-size:.85rem;font-weight:600;color:#ffffffbf;text-shadow:0 2px 4px rgba(0,0,0,.5)}._speedBoostBadge_n2elb_119{position:absolute;top:1.5rem;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:.7rem;padding:.65rem 1rem;border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);border-radius:var(--radius-md);background:#121216eb;color:#f5f3ff;font-size:.85rem;font-weight:800;letter-spacing:.06em;z-index:11;pointer-events:none}._speedBoostBadge_n2elb_119 span{line-height:1}._speedBoostBadge_n2elb_119 svg{display:block;flex-shrink:0}._bottomControls_n2elb_16{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(to top,rgba(0,0,0,.85) 0%,rgba(0,0,0,.45) 60%,transparent 100%);padding:0 clamp(.5rem,1.5cqw,.75rem) clamp(.75rem,2.5cqw,1.5rem);z-index:10;pointer-events:auto;transition:transform .4s cubic-bezier(.2,.8,.2,1)}._progressBarContainer_n2elb_165{width:100%;height:20px;display:flex;align-items:center;cursor:pointer;position:relative;touch-action:none}@media(pointer:coarse){._progressBarContainer_n2elb_165{height:28px}._progressBarContainer_n2elb_165 ._progressBar_n2elb_165{height:6px}._progressBarContainer_n2elb_165 ._thumb_n2elb_184{opacity:1}}._progressBar_n2elb_165{width:100%;height:4px;background:#fff3;border-radius:2px;position:relative;transition:height .15s ease}._progressBarContainer_n2elb_165:hover ._progressBar_n2elb_165{height:6px}._bufferedBar_n2elb_202{position:absolute;top:0;left:0;height:100%;background:#ffffff4d;border-radius:2px;pointer-events:none}._watchedBar_n2elb_212{position:absolute;top:0;left:0;height:100%;background:var(--accent);border-radius:2px;pointer-events:none}._thumb_n2elb_184{position:absolute;top:50%;width:12px;height:12px;background:#fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 4px #0006;pointer-events:none;opacity:0;transition:opacity .15s ease}._progressBarContainer_n2elb_165:hover ._thumb_n2elb_184,._progressBarContainer_n2elb_165._scrubbing_n2elb_237 ._thumb_n2elb_184{opacity:1}._timeBubble_n2elb_241{position:absolute;bottom:24px;background:#000000d9;color:#fff;padding:4px 8px;border-radius:4px;font-size:.8rem;font-weight:500;transform:translate(-50%);pointer-events:none;white-space:nowrap}._bottomControlsRow_n2elb_255{display:flex;align-items:center;justify-content:space-between;gap:.75rem;margin-top:8px}._leftControls_n2elb_20{display:flex;align-items:center;gap:1rem;gap:clamp(.5rem,2.5cqw,1rem);min-width:0}._rightControls_n2elb_21{display:flex;align-items:center;gap:.75rem;gap:clamp(.5rem,2cqw,.75rem)}._nextEpisodeBtn_n2elb_278{background:#ffffff0f;border:1px solid rgba(255,255,255,.12);border-radius:var(--radius-md);padding:.45rem .8rem;color:#fffc;font-weight:600;font-size:.9rem;display:inline-flex;align-items:center;gap:.5rem;cursor:pointer;transition:all var(--transition-fast);white-space:nowrap}._nextEpisodeBtn_n2elb_278:hover{background:#ffffff1a;color:#fff;transform:translateY(-1px);border-color:#fff3}._controlBtn_n2elb_25{background:transparent;border:none;color:#ffffffd9;font-size:1.1rem;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:8px;border-radius:4px;transition:all var(--transition-fast);min-width:2.125rem;min-height:2.125rem;flex:0 0 auto}@media(pointer:coarse){._controlBtn_n2elb_25{padding:10px;min-width:2.75rem;min-height:2.75rem}}._controlBtn_n2elb_25:hover{color:#fff;background:#ffffff1a}._controlBtn_n2elb_25:focus{outline:none}._controlBtn_n2elb_25:focus-visible{outline:2px solid var(--accent-light);outline-offset:2px}._controlBtn_n2elb_25._active_n2elb_340{color:var(--accent)}._timeDisplay_n2elb_12{color:#fffc;font-size:.85rem;font-weight:500;font-variant-numeric:tabular-nums;min-width:100px}._settingsPanel_n2elb_352{position:absolute;bottom:clamp(6rem,15vh,8rem);right:clamp(1rem,3vw,2rem);background:#141418f2;border:1px solid var(--border-secondary);border-radius:var(--radius-md);width:max-content;min-width:12rem;max-width:min(19rem,calc(100vw - 1.5rem));font-size:.85rem;z-index:60;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 8px 32px #00000080;display:flex;flex-direction:column;overflow:hidden}._settingsHeader_n2elb_371{display:flex;align-items:center;padding:.55rem .75rem;border-bottom:1px solid var(--border-secondary);gap:.625rem}._settingsBackBtn_n2elb_379{background:transparent;border:none;color:#ffffffd9;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:4px;border-radius:4px;transition:all var(--transition-fast)}._settingsBackBtn_n2elb_379:hover{background:#ffffff1a;color:#fff}._settingsTitle_n2elb_397{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._settingsContent_n2elb_408{overflow-y:auto;padding:.375rem;display:flex;flex-direction:column;gap:.125rem;max-height:min(56vh,22rem)}._currentValue_n2elb_417{color:var(--text-tertiary);font-size:.8rem;font-weight:500}._menuItem_n2elb_423{display:flex;align-items:center;justify-content:space-between;gap:.75rem;width:100%;min-height:2rem;padding:.5rem .75rem;background:transparent;border:none;color:var(--text-primary);font-size:.85rem;cursor:pointer;border-radius:var(--radius-sm);transition:background-color var(--transition-fast);text-align:left;white-space:nowrap}._menuItem_n2elb_423:hover{background:var(--bg-tertiary)}._menuItem_n2elb_423._active_n2elb_340{background:color-mix(in srgb,var(--accent) 18%,transparent);color:var(--accent-lighter)}._currentValue_n2elb_417{color:var(--text-secondary);font-size:.85rem}._menuNote_n2elb_456{padding:.5rem .75rem;font-size:.7rem;line-height:1.5;color:var(--text-tertiary);white-space:normal;overflow-wrap:break-word}._loadingOverlay_n2elb_465{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;z-index:10;background:#00000080;border-radius:inherit}._loadingDots_n2elb_476{display:flex;gap:10px}._dot_n2elb_481{width:12px;height:12px;border-radius:50%;background-color:var(--accent);animation:_bounce_n2elb_1 1.4s infinite ease-in-out both;box-shadow:0 0 10px var(--accent-glow)}._dot_n2elb_481:nth-child(1){animation-delay:-.32s}._dot_n2elb_481:nth-child(2){animation-delay:-.16s}@keyframes _bounce_n2elb_1{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}._bufferingOverlay_n2elb_510{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);pointer-events:none;z-index:20}._bufferingSpinner_n2elb_519{width:var(--size-48);height:var(--size-48);border-radius:var(--radius-full);background:conic-gradient(from 0deg,transparent 0deg 160deg,var(--accent) 300deg,var(--accent-lighter) 360deg),var(--track-bg);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#000 calc(100% - 4px));mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#000 calc(100% - 4px));filter:drop-shadow(0 0 8px var(--accent-glow));animation:_spin_n2elb_1 var(--duration-spin) linear infinite}@keyframes _spin_n2elb_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media(pointer:coarse){._settingsPanel_n2elb_352{font-size:.9rem;bottom:calc(env(safe-area-inset-bottom,0px) + 7rem);right:max(.75rem,env(safe-area-inset-right,0px))}._menuItem_n2elb_423{min-height:2.75rem}._settingsContent_n2elb_408{max-height:52vh}}@media(max-width:480px){._settingsPanel_n2elb_352{min-width:9rem;max-width:calc(100vw - 2rem);font-size:.75rem;bottom:calc(env(safe-area-inset-bottom,0px) + 6rem)}._settingsHeader_n2elb_371{padding:.4rem .625rem}._settingsTitle_n2elb_397{font-size:.64rem}._menuItem_n2elb_423{min-height:2.25rem;padding:.45rem .625rem;font-size:.75rem;gap:.5rem}._settingsContent_n2elb_408{max-height:min(40vh,15rem)}}@media(max-height:500px)and (orientation:landscape){._settingsPanel_n2elb_352{bottom:7.25rem;right:2rem;min-width:10rem;max-width:min(15rem,calc(100vw - 1.5rem));font-size:.8rem}._menuItem_n2elb_423{min-height:2.5rem;font-size:.8rem}._settingsContent_n2elb_408{max-height:50vh;overflow-y:auto}}._statusMsg_vmhzm_1{padding:1rem;text-align:center;color:var(--text-secondary)}._statusMsg_vmhzm_1._error_vmhzm_7{color:#f87171}._spinner_vmhzm_11{animation:_spin_vmhzm_11 1s linear infinite;margin-right:.5rem}._sourceLoader_vmhzm_16{padding:.75rem;display:flex;justify-content:center}._ringSpinner_vmhzm_22{width:40px;height:40px;border:4px solid rgba(255,255,255,.1);border-left-color:var(--accent);border-radius:50%;animation:_spin_vmhzm_11 1s linear infinite}@keyframes _spin_vmhzm_11{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._meta_vmhzm_40{display:flex;align-items:center;gap:.75rem;margin:.5rem 0;flex-wrap:wrap}._year_vmhzm_48{color:var(--text-secondary);font-size:.9rem}._rating_vmhzm_53{display:inline-flex;align-items:center;gap:4px;color:var(--accent-lighter);font-weight:600;font-size:.9rem}._typeBadge_vmhzm_62{padding:2px 10px;border-radius:4px;font-size:.75rem;font-weight:600;text-transform:uppercase}._typeBadge_vmhzm_62._tv_vmhzm_70{background:color-mix(in srgb,var(--accent) 20%,transparent);color:var(--accent)}._typeBadge_vmhzm_62._movie_vmhzm_75{background:color-mix(in srgb,var(--accent-lighter) 20%,transparent);color:var(--accent-lighter)}._controlLabel_vmhzm_80{display:flex;align-items:center;gap:.6rem;font-size:.8rem;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em}._select_vmhzm_90{height:42px;padding:0 1rem;border-radius:var(--radius-md);border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);font-size:.9rem;cursor:pointer;min-width:160px}._playerSection_vmhzm_102{margin:0;border-radius:0;overflow:hidden;overflow:clip;isolation:isolate;background:#000;position:relative}._video_vmhzm_106{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;display:block;background:#000;border:none;border-radius:inherit}._videoHidden_vmhzm_128{opacity:0;pointer-events:none}._delayCanvas_vmhzm_133{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;opacity:0;pointer-events:none;z-index:2;border-radius:inherit}._delayCanvasActive_vmhzm_146{opacity:1}._subtitleOverlay_vmhzm_150{position:absolute;top:0;left:0;width:100%;height:100%;z-index:3;pointer-events:none;overflow:hidden;border-radius:inherit}@media(max-width:900px)and (orientation:landscape){._playerSection_vmhzm_102{margin:0;border-radius:0}}._videoIframe_vmhzm_169{width:100%;aspect-ratio:16 / 9;min-height:400px;border:none;background:#000}._retryButton_vmhzm_177{margin-left:8px;padding:4px 10px;border-radius:4px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);cursor:pointer;font-size:.8rem}._retryButton_vmhzm_177:hover{border-color:var(--accent)}._sidebarSeason_vmhzm_192{display:flex;flex-direction:column;gap:.4rem;font-size:.75rem;font-weight:700;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.1em;margin-bottom:var(--space-4)}._sidebarSeason_vmhzm_192 ._select_vmhzm_90{width:100%}._mobileSeasonRow_vmhzm_208{display:none}@media(max-width:768px){._mobileSeasonRow_vmhzm_208{display:block}._mobileSeasonRow_vmhzm_208 ._sidebarSeason_vmhzm_192{margin-bottom:0}._providerActions_vmhzm_221{width:100%;margin-left:0;justify-content:flex-start}}._providerRow_vmhzm_228{grid-column:1 / -1;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.75rem 1rem;min-width:0}._providerActions_vmhzm_221{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.75rem;margin-left:auto}._providerActions_vmhzm_221 ._autoplayActive_vmhzm_247{background:color-mix(in srgb,var(--color-info) 12%,transparent);border-color:color-mix(in srgb,var(--color-info) 45%,transparent);color:#dbeafe}._providerActions_vmhzm_221 ._autoplayActive_vmhzm_247:hover:not(:disabled){background:color-mix(in srgb,var(--color-info) 18%,transparent);border-color:color-mix(in srgb,var(--color-info) 65%,transparent)}._genreRow_vmhzm_258{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.6rem}._genreChip_vmhzm_265{padding:.2rem .7rem;border-radius:20px;border:1px solid var(--glass-border);background:#ffffff0d;color:var(--text-secondary);font-size:.78rem;font-weight:600}._metaRow_vmhzm_275{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.6rem;color:var(--text-secondary);font-size:.9rem}._detailGrid_vmhzm_284{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:1.1rem 1.25rem;align-content:start;min-width:0}._detailItem_vmhzm_292{display:flex;flex-direction:column;gap:.2rem;padding:0;border-radius:0;border:0;background:none}._detailItem_vmhzm_292 strong{font-size:.75rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-tertiary)}._detailItem_vmhzm_292 span{color:var(--text-primary);font-size:.9rem}._imdbLink_vmhzm_314{color:var(--accent-light);font-size:.9rem;text-decoration:none}._imdbLink_vmhzm_314:hover{text-decoration:underline}._watchedOverlay_vmhzm_324{position:absolute;inset:0;z-index:5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1.5rem;text-align:center;color:var(--text-primary);background:radial-gradient(circle at 50% 35%,color-mix(in srgb,var(--accent) 18%,transparent),transparent 60%),#000;border-radius:inherit}._watchedTitle_vmhzm_346{margin:0;font-size:1.2rem;font-weight:700}._watchedSubtext_vmhzm_352{margin:0;color:var(--text-secondary);font-size:.9rem}._watchedActions_vmhzm_358{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:10px;margin-top:.5rem;width:100%;max-width:560px}._watchedActions_vmhzm_358>:first-child{justify-self:end}._watchedActions_vmhzm_358>:last-child{justify-self:start}._watchedActionsCentered_vmhzm_376{display:flex;flex-wrap:wrap;justify-content:center}._watchedActionsCentered_vmhzm_376>div{display:contents}@media(max-width:480px){._watchedActions_vmhzm_358{display:flex;flex-wrap:wrap;justify-content:center}._watchedActions_vmhzm_358>div{display:contents}}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{u as t,d as g,A as U,h as b,S as tt,g as Ns,q as _,o as ws,p as As,a as Is,T as Ce}from"./vendor-core-DfaOB3Rn.js";import{h as jt,p as $,t as kt,ac as Ps,a6 as xs,S as tr,e as Rs,ak as Ls,J as Br,B as fe,a8 as Bs}from"./index-CD7a-Eff.js";import{P as Ms,a as $s,b as Ds,F as Os,f as zs,c as Fs}from"./PlayerProvider-Bll6epmz.js";import{u as Vs}from"./vendor-query-BBT5_sHx.js";import{I as ie}from"./vendor-icons-DrybRNxP.js";import{p as or,M as Us,z as zr,f as ar,c as Ws,C as Hs,a as qs,P as Ks,b as _n,u as Ys,i as Qs,j as js,n as Gs,h as Xs,k as Js,m as Zs,l as eo,s as nr,d as to,e as no,g as ro,r as so,o as Re,A as oo,t as ao,E as io,w as lo,x as co,v as Z,y as uo,R as mo,q as Mr}from"./useWatchAlongPlayer-BZs3033g.js";import{S as ho,O as rr,a as vo,A as po,b as fo}from"./OptionListMenu-BzRHsU6c.js";import{M as bo}from"./MatureConsentModal-yectlds9.js";import{u as go}from"./useProviders-Cc8CTUYM.js";import{e as yo,b as So,f as _o,g as Co,d as To,c as ko,h as Eo,i as No}from"./useTvLibrary-BsGpheKM.js";import{b as wo,i as Qt,l as Ao,a as Io,c as Po,h as $r}from"./playbackCompletion-BXBBtgdB.js";import{u as xo}from"./useIsMobile-Dvx1uJ82.js";import{S as Ro}from"./SynopsisText-B3Sa5pRv.js";import{W as Lo}from"./WatchAlongPanel-Brkp7UMD.js";import"./libraryInvalidation-nAOuYLiR.js";const Bo="_fullscreenFlat_n2elb_1",Mo="_timeDisplay_n2elb_12",$o="_bottomControls_n2elb_16",Do="_leftControls_n2elb_20",Oo="_rightControls_n2elb_21",zo="_controlBtn_n2elb_25",Fo="_controlsOverlay_n2elb_32",Vo="_hidden_n2elb_52",Uo="_topControls_n2elb_58",Wo="_backBtn_n2elb_78",Ho="_videoTitleInfo_n2elb_98",qo="_animeTitle_n2elb_104",Ko="_episodeLabel_n2elb_112",Yo="_speedBoostBadge_n2elb_119",Qo="_progressBarContainer_n2elb_165",jo="_progressBar_n2elb_165",Go="_thumb_n2elb_184",Xo="_bufferedBar_n2elb_202",Jo="_watchedBar_n2elb_212",Zo="_scrubbing_n2elb_237",ea="_timeBubble_n2elb_241",ta="_bottomControlsRow_n2elb_255",na="_nextEpisodeBtn_n2elb_278",ra="_active_n2elb_340",sa="_settingsPanel_n2elb_352",oa="_settingsHeader_n2elb_371",aa="_settingsBackBtn_n2elb_379",ia="_settingsTitle_n2elb_397",la="_settingsContent_n2elb_408",ca="_currentValue_n2elb_417",da="_menuItem_n2elb_423",ua="_menuNote_n2elb_456",ma="_loadingOverlay_n2elb_465",ha="_loadingDots_n2elb_476",va="_dot_n2elb_481",pa="_bufferingOverlay_n2elb_510",fa="_bufferingSpinner_n2elb_519",o={fullscreenFlat:Bo,timeDisplay:Mo,bottomControls:$o,leftControls:Do,rightControls:Oo,controlBtn:zo,controlsOverlay:Fo,hidden:Vo,topControls:Uo,backBtn:Wo,videoTitleInfo:Ho,animeTitle:qo,episodeLabel:Ko,speedBoostBadge:Yo,progressBarContainer:Qo,progressBar:jo,thumb:Go,bufferedBar:Xo,watchedBar:Jo,scrubbing:Zo,timeBubble:ea,bottomControlsRow:ta,nextEpisodeBtn:na,active:ra,settingsPanel:sa,settingsHeader:oa,settingsBackBtn:aa,settingsTitle:ia,settingsContent:la,currentValue:ca,menuItem:da,menuNote:ua,loadingOverlay:ma,loadingDots:ha,dot:va,bufferingOverlay:pa,bufferingSpinner:fa},ba=({player:s,visible:f,settingsOpen:z,onOpenSettings:x,onCloseSettings:M,hasSubtitles:k,isSubtitleActive:w,subtitles:d,onSubtitleChange:c,showNextEpisodeButton:C,onNextEpisode:r,isTheaterMode:R,onTheaterModeToggle:be,timeLabelRef:te})=>{const{state:u,actions:Ne}=s,Le=()=>{if(w){c(-1);return}let ge=null;try{ge=$.getItem("tvLastSubtitle")}catch{}c(or(d,{lastKey:ge,enabled:!0}))};return t("div",{className:`${o.controlsOverlay} ${f?"":o.hidden}`,"data-speed-boost-ignore":"true",style:{pointerEvents:"none",background:"none",justifyContent:"flex-end"},children:t("div",{className:o.bottomControls,onClick:ge=>ge.stopPropagation(),children:[t(Ms,{classes:{container:o.progressBarContainer,scrubbing:o.scrubbing,timeBubble:o.timeBubble,bar:o.progressBar,buffered:o.bufferedBar,watched:o.watchedBar,thumb:o.thumb},timeLabelRef:te}),t("div",{className:o.bottomControlsRow,children:[t("div",{className:o.leftControls,children:[t($s,{className:o.controlBtn}),t(Ds,{buttonClassName:o.controlBtn,onExpandedChange:Ne.setShowVolumeSlider}),t("span",{className:o.timeDisplay,ref:te,children:[jt(0)," / ",jt(u.duration)]})]}),t("div",{className:o.rightControls,children:[C&&t("button",{className:o.nextEpisodeBtn,onClick:r,title:"Play next episode",children:"Next EP"}),k&&t("button",{className:`${o.controlBtn} ${w?o.active:""}`,onClick:Le,"aria-label":w?"Turn subtitles off":"Turn subtitles on",children:t(ie,{name:"closed-captioning"})}),t("button",{className:`${o.controlBtn} ${z?o.active:""}`,onClick:()=>z?M():x(),"aria-label":"Settings",children:t(ie,{name:"cog"})}),t("button",{className:`${o.controlBtn} ${R?o.active:""}`,onClick:ge=>{ge.stopPropagation(),be()},title:R?"Exit Theater Mode":"Theater Mode","aria-label":R?"Exit Theater Mode":"Theater Mode",children:t(ie,{name:"tv"})}),t(Os,{className:o.controlBtn})]})]})]})})},Cn=-6e4,sr=6e4,Dr=500,ga=({classes:s,delayMs:f,onDelayChange:z})=>{const[x,M]=g(null),k=x??f,w=U(z);w.current=z;const d=U(f);d.current=f;const c=U(null);c.current=x,b(()=>{M(null)},[f]),b(()=>()=>{const R=c.current;R!==null&&R!==d.current&&w.current(R)},[]);const C=R=>{d.current=R,c.current=null,w.current(R),M(null)},r=R=>{const be=c.current??d.current,te=Math.max(Cn,Math.min(sr,be+R));C(te)};return t(tt,{children:[t("div",{style:{display:"flex",gap:6,padding:"0.5rem 0.75rem 0.25rem"},children:[t("button",{type:"button",className:s.item,onClick:()=>r(-Dr),"aria-label":"Show subtitles 0.5 seconds earlier",style:{flex:1,justifyContent:"center"},children:t("span",{children:"-0.5s"})}),t("button",{type:"button",className:s.item,onClick:()=>r(Dr),"aria-label":"Show subtitles 0.5 seconds later",style:{flex:1,justifyContent:"center"},children:t("span",{children:"+0.5s"})}),t("button",{type:"button",className:s.item,onClick:()=>C(0),disabled:k===0,"aria-label":"Reset subtitle timing",style:{flex:1,justifyContent:"center"},children:t("span",{children:"Reset"})})]}),t(Us,{label:"Subtitle timing",display:zr(k),min:Cn,max:sr,step:100,value:k,percent:(k-Cn)/(sr-Cn)*100,onChange:R=>{const be=Math.round(R);c.current=be,M(be)},onCommit:()=>{const R=c.current;R!==null&&C(R)}}),t("div",{className:s.note,children:"Positive delays subtitles (show later). Negative shows them earlier. 0.0s is default."})]})},ya=({view:s,onSelectView:f,onClose:z,player:x,onSubtitleStyleChange:M,streams:k,resolutionIdx:w,onResolutionChange:d,hasSubtitles:c,subtitles:C,selectedSubtitle:r,isSubtitleActive:R,onSubtitleChange:be,audioTracks:te,selectedAudioTrack:u,onAudioTrackChange:Ne,videoDelayEnabled:Le,onVideoDelayToggle:ge,videoDelayMs:ye,onVideoDelayChange:S,onCalibrate:Et,subtitleDelayMs:nt,onSubtitleDelayChange:E,ambientSettings:W,onAmbientChange:Y})=>{const{state:de}=x,Nt=()=>t(tt,{children:[k.length>1&&t("button",{className:o.menuItem,onClick:()=>f("resolution"),children:[t("span",{children:"Resolution"}),t("span",{className:o.currentValue,children:k[w]?.quality||"Auto"})]}),c&&t("button",{className:o.menuItem,onClick:()=>f("subtitles"),children:[t("span",{children:"Subtitles"}),t("span",{className:o.currentValue,children:R?C[r]?.label||C[r]?.language:"Off"})]}),c&&t("button",{className:o.menuItem,onClick:()=>f("subtitle-style"),children:[t("span",{children:"Subtitle Style"}),t("span",{className:o.currentValue,children:[de.subtitleFontSize.toFixed(1),"x · ",de.subtitlePosition]})]}),c&&t("button",{className:o.menuItem,onClick:()=>f("subtitle-timing"),children:[t("span",{children:"Subtitle Timing"}),t("span",{className:o.currentValue,children:zr(nt)})]}),te.length>0&&t("button",{className:o.menuItem,onClick:()=>f("audio"),children:[t("span",{children:"Audio Track"}),t("span",{className:o.currentValue,children:te[u]?.label||te[u]?.language})]}),t("button",{className:o.menuItem,onClick:()=>f("av-sync"),children:[t("span",{children:"A/V Sync"}),t("span",{className:o.currentValue,children:Le?`${ye}ms`:"Off"})]}),W&&Y&&t("button",{className:o.menuItem,onClick:()=>f("ambient"),children:[t("span",{children:"Ambient Light"}),t("span",{className:o.currentValue,children:W.enabled?"On":"Off"})]})]}),Be=()=>t(rr,{classes:{item:o.menuItem,active:o.active},options:k.map((A,re)=>({key:String(re),label:A.quality,selected:re===w})),onSelect:A=>d(Number(A))}),rt=()=>t(rr,{classes:{item:o.menuItem,active:o.active},options:[{key:"off",label:"Off",selected:!R},...C.map((A,re)=>({key:String(re),label:A.label||A.language,selected:re===r}))],onSelect:A=>be(A==="off"?-1:Number(A))}),pt=()=>t(vo,{classes:{item:o.menuItem,active:o.active},values:{fontSize:de.subtitleFontSize,position:de.subtitlePosition,bgOpacity:de.subtitleBgOpacity,bgColor:de.subtitleBgColor,textColor:de.subtitleTextColor,edge:de.subtitleEdge,bold:de.subtitleBold},onChange:M}),le=()=>t(ga,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},delayMs:nt,onDelayChange:A=>E?.(A)}),wt=()=>t(rr,{classes:{item:o.menuItem,active:o.active},options:te.map((A,re)=>({key:String(re),label:A.label||A.language,selected:re===u})),onSelect:A=>Ne(Number(A))}),st=()=>t(po,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},enabled:Le,delayMs:ye,onToggle:A=>ge?.(A),onDelayChange:A=>S?.(A),onCalibrate:Et}),Q=()=>W&&Y?t(fo,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},values:W,onChange:Y}):null;return t("div",{"data-speed-boost-ignore":"true",onClick:A=>A.stopPropagation(),children:t(ho,{classes:{panel:o.settingsPanel,header:o.settingsHeader,backBtn:o.settingsBackBtn,title:o.settingsTitle,content:o.settingsContent},title:s==="main"?"Settings":s==="subtitle-style"?"Subtitle Style":s==="subtitle-timing"?"Subtitle Timing":s==="audio"?"Audio Track":s==="resolution"?"Resolution":s==="av-sync"?"A/V Sync":s==="ambient"?"Ambient Light":s.charAt(0).toUpperCase()+s.slice(1),onBack:()=>s==="main"?z():f("main"),children:[s==="main"&&Nt(),s==="resolution"&&Be(),s==="subtitles"&&rt(),s==="subtitle-style"&&pt(),s==="subtitle-timing"&&le(),s==="audio"&&wt(),s==="av-sync"&&st(),s==="ambient"&&Q()]})})},Sa=({player:s,title:f,episodeLabel:z,server:x,audioTracks:M,selectedAudioTrack:k,onAudioTrackChange:w,subtitles:d,selectedSubtitle:c,onSubtitleChange:C,streams:r,resolutionIdx:R,onResolutionChange:be,onBack:te,children:u,videoDelayEnabled:Ne=!1,onVideoDelayToggle:Le,videoDelayMs:ge=0,onVideoDelayChange:ye,onCalibrateAvSync:S,subtitleDelayMs:Et=0,onSubtitleDelayChange:nt,showNextEpisodeButton:E=!1,onNextEpisode:W,isLoading:Y=!1,isTheaterMode:de,onTheaterModeToggle:Nt,ambientSettings:Be,onAmbientChange:rt,hideChrome:pt=!1})=>{const{state:le,refs:wt,actions:st}=s,Q=wt.videoRef,{subtitleFontSize:A,subtitlePosition:re,subtitleBgOpacity:ue,subtitleBgColor:Me,subtitleTextColor:$e,subtitleEdge:se,subtitleBold:At}=le,[Ue,Te]=g(null),It=U(null),[ke,Pt]=g(0);b(()=>{const he=Q.current;if(!he)return;const ne=()=>Pt(he.clientHeight||0);ne();const at=new ResizeObserver(ne);return at.observe(he),()=>at.disconnect()},[Q]);const me=st.setSubtitleStyle;b(()=>{const he="tv-player-subtitle-style";let ne=document.getElementById(he);ne||(ne=document.createElement("style"),ne.id=he,document.head.appendChild(ne));const at={fontSize:A,position:re,bgOpacity:ue,bgColor:Me,textColor:$e,edge:se,bold:At},oe=Q.current,gt=ar(A,ke||oe?.clientHeight||720);if(ne.textContent=Ws({...at,fontSize:gt}),oe){const Lt=()=>{const i=Number(re);return isNaN(i)?0:Math.max(0,Math.min(100,i))},it=(i,l)=>{try{const F=i;F.snapToLines=!1,F.line=l}catch{}},Se=()=>{const i=gt*16,l=oe.videoHeight||oe.clientHeight||720,F=oe.videoWidth||oe.clientWidth||1280;return{step:i*1.3/l*100,chars:Math.max(20,Math.floor(F/(i*.55)))}},Jt=i=>{const l=Math.max(0,Math.min(100,100-Lt())),F=Array.from(i.activeCues??[]);if(F.length<=1){F.forEach(Oe=>it(Oe,l));return}const{step:ce,chars:Zt}=Se();let $t=l;for(let Oe=F.length-1;Oe>=0;Oe--){const Tn=String(F[Oe].text??"").replace(/<[^>]*>/g,"").split(`
|
|
2
|
+
`).reduce((kn,ve)=>kn+Math.max(1,Math.ceil(ve.length/Zt)),0),Dt=$t-Tn*ce;it(F[Oe],Math.max(0,Dt)),$t=Dt-ce*.4}},Ae=()=>{const i=Math.max(0,Math.min(100,100-Lt()));Array.from(oe.textTracks).forEach(l=>{l.cues&&(Array.from(l.cues).forEach(F=>it(F,i)),l.mode==="showing"&&Jt(l))})};Ae();const lt=i=>{const l=i.target;l.mode==="showing"&&Jt(l)},Bt=()=>{Array.from(oe.textTracks).forEach(i=>{i.removeEventListener("cuechange",lt),i.addEventListener("cuechange",lt)}),Ae()};Array.from(oe.textTracks).forEach(i=>{i.addEventListener("cuechange",lt)}),oe.textTracks.addEventListener("addtrack",Bt);const Mt=Array.from(oe.querySelectorAll("track")),yt=()=>Ae();return Mt.forEach(i=>i.addEventListener("load",yt)),()=>{Array.from(oe.textTracks).forEach(i=>{i.removeEventListener("cuechange",lt)}),oe.textTracks.removeEventListener("addtrack",Bt),Mt.forEach(i=>i.removeEventListener("load",yt))}}},[A,re,ue,Me,$e,se,At,c,d,Q,ke]);const De=d.length>0,we=c>=0,ft=()=>{Te("main"),st.setShowControls(!0)},We=()=>{Te(null)},Gt=le.showControls||!!Ue,ot=zs(s.engine),He=ot.audioTracks.find(he=>he.id===ot.activeAudioTrack)??M[k],Xt=c>=0?d[c]??ot.subtitleTracks.find(he=>he.id===c):void 0,xt=t(Hs,{visible:Gt,title:f,episode:z,server:Y?void 0:x,audio:Y?void 0:He?.label||He?.language,subtitles:Y?void 0:Xt?.label||Xt?.language,onBack:te,classes:{overlay:o.controlsOverlay,hidden:o.hidden,top:o.topControls,backBtn:o.backBtn,titleInfo:o.videoTitleInfo,title:o.animeTitle,episode:o.episodeLabel}}),K=!Y&&!le.isBuffering&&le.duration>0?t(qs,{}):null,bt=t(ba,{player:s,visible:Gt,settingsOpen:!!Ue,onOpenSettings:ft,onCloseSettings:We,hasSubtitles:De,isSubtitleActive:we,subtitles:d,onSubtitleChange:C,showNextEpisodeButton:E,onNextEpisode:W,isTheaterMode:de,onTheaterModeToggle:Nt,timeLabelRef:It}),I=Ue?t(ya,{view:Ue,onSelectView:Te,onClose:We,player:s,onSubtitleStyleChange:me,streams:r,resolutionIdx:R,onResolutionChange:be,hasSubtitles:De,subtitles:d,selectedSubtitle:c,isSubtitleActive:we,onSubtitleChange:C,audioTracks:M,selectedAudioTrack:k,onAudioTrackChange:w,videoDelayEnabled:Ne,onVideoDelayToggle:Le,videoDelayMs:ge,onVideoDelayChange:ye,onCalibrate:()=>{Te(null),S?.()},subtitleDelayMs:Et,onSubtitleDelayChange:nt,ambientSettings:Be,onAmbientChange:rt}):null,Rt=t(tt,{children:[Y&&t("div",{className:o.loadingOverlay,"aria-hidden":"true",children:t("div",{className:o.loadingDots,children:[t("div",{className:o.dot}),t("div",{className:o.dot}),t("div",{className:o.dot})]})}),le.isBuffering&&!Y&&t("div",{className:o.bufferingOverlay,"aria-hidden":"true",children:t("div",{className:o.bufferingSpinner})}),le.isSpeedBoostActive&&t("div",{className:o.speedBoostBadge,"aria-hidden":"true",children:[t("span",{children:"2x"}),t(ie,{name:"forward",size:12})]})]});return t(Ks,{engine:s.engine,topBar:xt,centerControls:K,bottomBar:!Y&&le.duration>0?bt:null,settingsPanel:I,overlays:Rt,isInteracting:!!Ue||le.showVolumeSlider,nativeControls:le.useNativeControls,onStageClick:We,className:le.isFullscreen?o.fullscreenFlat:"",chromeDisabled:pt,children:u})},_a=({servers:s,selectedServer:f,onServerSelect:z})=>s.length===0?null:t("div",{className:_n.sourceSelectionContainer,children:[t("h4",{children:"Source"}),t("div",{className:_n.sourceButtons,children:s.map(x=>t("button",{className:`${_n.sourceButton} ${f===x?_n.active:""}`,onClick:()=>z(x),children:x},x))})]}),Ca=Ns.memo(_a);function Ta({details:s,isMovie:f,season:z,episode:x,videoRef:M,active:k}){const w=U("");w.current||(w.current=`tv-${Date.now()}-${Math.random().toString(36).slice(2)}`);const d=_(()=>{if(!s)return;const c=M.current,C=f?"":`S${String(z).padStart(2,"0")}E${String(x).padStart(2,"0")}`;kt.discord.tvPresence.mutate({title:s.title,episodeLabel:C,isPlaying:c?!c.paused&&!c.ended:!0,thumbnail:s.poster,currentTime:c?c.currentTime:0,duration:c&&c.duration||0,isAdult:s.adult===!0,sessionId:w.current}).catch(()=>{}),kt.discord.heartbeat.mutate({sessionId:w.current}).catch(()=>{})},[s,f,z,x,M]);return b(()=>{if(!s)return;d();const c=window.setInterval(()=>{const C=M.current;(!C||!C.paused)&&d()},15e3);return()=>window.clearInterval(c)},[d,s,M]),b(()=>{if(!s||!k)return;const c=M.current;if(!c)return;const C=()=>d();return c.addEventListener("play",C),c.addEventListener("pause",C),c.addEventListener("seeked",C),()=>{c.removeEventListener("play",C),c.removeEventListener("pause",C),c.removeEventListener("seeked",C)}},[s,k,d,M]),b(()=>{const c=w.current,C=()=>Ps(c),r=()=>C();return window.addEventListener("pagehide",r),window.addEventListener("beforeunload",r),()=>{window.removeEventListener("pagehide",r),window.removeEventListener("beforeunload",r),C()}},[]),{sendPresence:d}}function ka(s,f,z){const x=()=>{const k=Array.isArray(s.audioTracks)?s.audioTracks.length:0,w=z.getWant(),d=k>0?Math.min(Math.max(0,w),k-1):w;s.audioTrack=d,d!==w&&z.onResolve(d)},M=(k,w)=>{const d=z.getWant(),c=Array.isArray(s.audioTracks)?s.audioTracks.length:0;if(w.id!==d&&d>=0&&d<c){s.audioTrack!==d&&(s.audioTrack=d);return}z.onResolve(w.id)};return s.on(f.MANIFEST_PARSED,x),s.on(f.AUDIO_TRACK_SWITCHED,M),()=>{s.off(f.MANIFEST_PARSED,x),s.off(f.AUDIO_TRACK_SWITCHED,M)}}const Ea=/\b(SmartTV|SMART-TV|Tizen|Web0S|webOS|NetCast|HbbTV|AppleTV|CrKey|BRAVIA|AFT[A-Za-z]|Fire\s?TV|GoogleTV|Roku|VIDAA|DTV|PlayStation|Xbox|Opera TV|POV_TV)\b/i;function Na(){try{if(Ea.test(navigator.userAgent||""))return!0;const s=navigator.deviceMemory;if(typeof s=="number"&&s>0&&s<2)return!0}catch{}return!1}const wa="_statusMsg_vmhzm_1",Aa="_error_vmhzm_7",Ia="_spinner_vmhzm_11",Pa="_spin_vmhzm_11",xa="_sourceLoader_vmhzm_16",Ra="_ringSpinner_vmhzm_22",La="_meta_vmhzm_40",Ba="_year_vmhzm_48",Ma="_rating_vmhzm_53",$a="_typeBadge_vmhzm_62",Da="_tv_vmhzm_70",Oa="_movie_vmhzm_75",za="_controlLabel_vmhzm_80",Fa="_select_vmhzm_90",Va="_playerSection_vmhzm_102",Ua="_video_vmhzm_106",Wa="_videoHidden_vmhzm_128",Ha="_delayCanvas_vmhzm_133",qa="_delayCanvasActive_vmhzm_146",Ka="_subtitleOverlay_vmhzm_150",Ya="_videoIframe_vmhzm_169",Qa="_retryButton_vmhzm_177",ja="_sidebarSeason_vmhzm_192",Ga="_mobileSeasonRow_vmhzm_208",Xa="_providerActions_vmhzm_221",Ja="_providerRow_vmhzm_228",Za="_autoplayActive_vmhzm_247",ei="_genreRow_vmhzm_258",ti="_genreChip_vmhzm_265",ni="_metaRow_vmhzm_275",ri="_detailGrid_vmhzm_284",si="_detailItem_vmhzm_292",oi="_imdbLink_vmhzm_314",ai="_watchedOverlay_vmhzm_324",ii="_watchedTitle_vmhzm_346",li="_watchedSubtext_vmhzm_352",ci="_watchedActions_vmhzm_358",di="_watchedActionsCentered_vmhzm_376",p={statusMsg:wa,error:Aa,spinner:Ia,spin:Pa,sourceLoader:xa,ringSpinner:Ra,meta:La,year:Ba,rating:Ma,typeBadge:$a,tv:Da,movie:Oa,controlLabel:za,select:Fa,playerSection:Va,video:Ua,videoHidden:Wa,delayCanvas:Ha,delayCanvasActive:qa,subtitleOverlay:Ka,videoIframe:Ya,retryButton:Qa,sidebarSeason:ja,mobileSeasonRow:Ga,providerActions:Xa,providerRow:Ja,autoplayActive:Za,genreRow:ei,genreChip:ti,metaRow:ni,detailGrid:ri,detailItem:si,imdbLink:oi,watchedOverlay:ai,watchedTitle:ii,watchedSubtext:li,watchedActions:ci,watchedActionsCentered:di},ui=[],mi=[];function Or({error:s,onRetry:f}){return t("div",{className:`${p.statusMsg} ${p.error}`,style:{flexDirection:"column",alignItems:"stretch",gap:8},children:t("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[t("span",{style:{flex:1},children:s}),t("button",{className:p.retryButton,onClick:f,children:"Retry"})]})})}const Ai=()=>{const{id:s}=ws(),[f]=As(),z=U(f);z.current=f;const x=Is(),M=Vs(),k=f.get("type"),w=xs(),d=!!w.session,c=d&&!w.session?.host,C=c&&["tv","movie"].includes(w.room?.selection.kind||"")?w.room?.selection:null,[r,R]=g(null),[be,te]=g(()=>parseInt(f.get("s")||"1",10)||1),u=C?.season??be,[Ne,Le]=g([]),[ge,ye]=g(()=>parseInt(f.get("e")||"1",10)||1),S=C?Number(C.episode):ge,[Et,nt]=g(()=>{try{return $.getItem("tvProvider")||""}catch{return""}}),E=C?.provider??Et,[W,Y]=g([]),[de,Nt]=g(""),[Be,rt]=g(""),{options:pt,isFallback:le,isLoading:wt}=go(),st=Ce(()=>pt.filter(e=>(e.kind??"tv")==="tv").map(e=>({id:e.id,label:e.label,tier:e.tier==="embed"?"embed":"direct",servers:e.servers})),[pt]),Q=le||st.length===0?ui:st,A=Q.filter(e=>e.tier==="direct"),re=Q.filter(e=>e.tier==="embed"),[ue,Me]=g(!1),[$e,se]=g(""),[At,Ue]=g([]),[Te,It]=g(0),[ke,Pt]=g([]),[me,De]=g(-1),[we,ft]=g(0),[We,Gt]=g(""),[ot,He]=g(""),[Xt,xt]=g(()=>{try{return $.getItem("tvServer")||""}catch{return""}}),K=C?.source??Xt,bt=Ce(()=>Q.find(e=>e.id===E),[Q,E]),I=bt?.tier==="embed",[Rt,he]=g([]),[ne,at]=g(""),[oe,gt]=g(""),[Lt,it]=g(!1),Se=Ce(()=>Rt.length>0?Rt:bt?.servers??[],[Rt,bt]),Jt=Ce(()=>ne&&!d?["Embed",...Se]:Se,[Se,ne,d]),Ae=Lt&&!!ne,lt=Ae?oe||ne:"";b(()=>{if(!ne){gt("");return}let e=!1;return tr(`/api/resolve?url=${encodeURIComponent(ne)}`).then(n=>{!e&&n.finalUrl&>(n.finalUrl)}).catch(()=>{}),()=>{e=!0}},[ne]);const Bt=U([]);b(()=>{Bt.current=W},[W]);const Mt=U(Te);b(()=>{Mt.current=Te},[Te]);const yt=U(me);b(()=>{yt.current=me},[me]);const i=Ys({skipIntervals:mi}),l=i.refs.videoRef,F=U(null),ce=U([]),Zt=U(null),$t=U(null),{videoDelayMs:Oe,videoDelayEnabled:en,setDelayEnabled:Tn,handleVideoDelayChange:Dt,isCalibrating:kn,testClipActive:ve,stopCalibration:En,openAvSyncCalibrator:Fr,cancelAvSyncCalibrator:Vr,applyAvSyncCalibrator:Ur,toggleTestClip:Wr,calibReturnRef:tn,effectiveVideoDelayMs:Nn}=Qs(l),[St,Hr]=g(()=>{try{const e=Number($.getItem("tvSubtitleDelayMs"));if(Number.isFinite(e)&&e>=-6e4&&e<=6e4)return Math.round(e)}catch{}return 0}),wn=U(St);wn.current=St;const qr=_(e=>{const n=Math.max(-6e4,Math.min(6e4,Math.round(e)));if(wn.current!==n){wn.current=n,Hr(n);try{$.setItem("tvSubtitleDelayMs",String(n))}catch{}}},[]);js({videoRef:l,canvasRef:Zt,delayMs:Nn,enabled:en});const An=en,_e=An||St!==0,{settings:In,update:Kr}=Gs(),Pn=U(_e);Pn.current=_e;const xn=_(()=>{if(!Pn.current)return;const e=l.current;e&&Array.from(e.textTracks).forEach(n=>{n.mode!=="hidden"&&(n.mode="hidden")})},[l]),{hasConsent:Ot,grant:Yr}=Rs(),v=k==="movie";Ta({details:r,isMovie:v,season:u,episode:S,videoRef:l,active:!I&&!ue&&!$e&&W.length>0});const nn=s?Ls(k||"tv",s):"",j=nn,ze=`${j}:${u}:${S}:${E}:${K}`,rn=Ce(()=>!s||!r||I||Ae||ue||Be!==ze||W[we]?.type!=="hls"?null:{kind:v?"movie":"tv",...v?{}:{season:u},showId:s,episode:String(v?1:S),provider:E,source:K,mode:"sub",title:r.title},[s,r,I,Ae,ue,Be,ze,W,we,v,u,S,E,K]),ir=Xs(i.engine,rn,ue||!r),lr=yo(),Rn=So(),qe=_o(),Ke=Co(),{toggle:cr,bookmarkedIds:Qr,pending:jr}=To(),{data:dr}=ko(r?nn:void 0),zt=dr?!!dr.inLibrary:nn?Qr.has(nn):!1,Gr=_(()=>{!r||!s||cr({tmdbId:Number(s),mediaType:k||"tv",title:r.title,poster:r.poster,year:r.year,adult:r.adult})},[r,s,k,cr]),{data:Ye,isFetched:Ft,isFetching:Ln}=Eo(j||void 0,u,S),sn=Ce(()=>Ne.map(e=>e.episode_number).sort((e,n)=>e-n),[Ne]),Vt=sn.indexOf(S),Bn=Vt>0?sn[Vt-1]:null,P=Vt>=0&&Vt<sn.length-1?sn[Vt+1]:null,on=Ce(()=>(r?.seasons??[]).map(e=>e.season_number).filter(e=>Number.isFinite(e)).sort((e,n)=>e-n),[r]),G=Ce(()=>{if(v||P!=null)return null;const e=on.indexOf(u);return e>=0&&e<on.length-1?on[e+1]:(r?.number_of_seasons??0)>u?u+1:null},[v,P,on,u,r?.number_of_seasons]),Mn=wo(r?.status),ct=v||P==null&&G==null&&Mn,ur=P==null&&G==null&&!ct,Ie=Ye?.currentTime??0,an=U(null),[Qe,ln]=g(!1),[_t,mr]=g(0),[Ut,hr]=g(!1),[dt,ut]=g(!1),[Xr,$n]=g(!1),[Jr,Zr]=g(""),[cn,es]=g(!1),[ts,Dn]=g(!1),[On,zn]=g(!1),{isTheaterMode:Fe,toggleTheaterMode:Fn,handleLayoutClick:ns}=Js(),vr=Ye?.duration??0,pr=Ye?.completed===1,Wt=`${j}:${u}:${S}`,[fr,rs]=g(null);b(()=>{Ft&&rs(e=>e?.key===Wt?e:{key:Wt,watched:pr||Qt(Ie,vr)})},[Ft,Wt,pr,Ie,vr]);const ss=Ft&&fr?.key===Wt&&fr.watched,[dn]=g(Ao),[os,br]=g(!1);b(()=>{br(!1)},[Wt]);const gr=!d&&!ve&&ss&&!On,je=gr&&dn,mt=gr&&!dn&&!os,Ge=dt&&dn,as=dt&&!dn,yr=_(()=>{zn(!0),ut(!1)},[]);b(()=>{const e=n=>{n.defaultPrevented||n.ctrlKey||n.metaKey||n.altKey||n.repeat||n.target.closest('input, textarea, button, select, a, [role="button"], [contenteditable="true"]')||n.key.toLowerCase()==="t"&&Fn()};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[Fn]),Zs(i,(W.length>0||ot!=="")&&!Fe&&!Qe&&!dt&&!je&&!mt);const is=xo(),[Ct,ls]=g(Io),cs=_(e=>{ls(e),Po(e)},[]),ds=e=>t("div",{className:e,children:[t("button",{className:`${Z.episodeNavBtn} ${Z.secondary} ${Ct?p.autoplayActive:""}`,onClick:()=>cs(!Ct),type:"button","aria-pressed":Ct,children:Ct?"AUTOPLAY: ON":"AUTOPLAY: OFF"}),t("button",{className:`${Z.episodeNavBtn} ${Z.secondary}`,onClick:()=>Rn.mutate({mediaId:j??"",season:u,episode:S}),disabled:Rn.isPending,type:"button",children:[t(ie,{name:"undo",size:14}),Rn.isPending?"Resetting...":"Reset Progress"]}),t("button",{className:`${Z.episodeNavBtn} ${Z.secondary}`,onClick:()=>Bn!=null&&Tt(String(Bn)),disabled:c||Bn==null,type:"button",children:[t(ie,{name:"chevron-left",size:12}),"Prev EP"]}),t("button",{className:`${Z.episodeNavBtn} ${Z.primary}`,onClick:()=>P!=null&&Tt(String(P)),disabled:c||P==null,type:"button",children:["Next EP",t(ie,{name:"chevron-right",size:12})]}),is&&t("button",{className:`${Z.episodeNavBtn} ${Z.episodePickerBtn}`,onClick:()=>Dn(!0),type:"button",children:[t(ie,{name:"list-ul",size:12}),"Episodes"]})]}),Xe=U(!1),Ve=U(null),Vn=U(0),X=U(null),Sr=_(()=>{X.current=Ie,zn(!0),ut(!1)},[Ie]),un=U(""),us=$r(Ie),Ht=!d&&!Xe.current&&!On&&(Qe||dt||us||je||mt),mn=U(Ht);mn.current=Ht;const hn=U(!1);b(()=>{hn.current=Ut},[Ut]);const Je=_((e,n)=>{if(!j||!n||n<30)return;const a=Qt(e,n);Math.abs(e-Vn.current)<10&&!a||(Vn.current=e,lr.mutate({mediaId:j,season:u,episode:S,currentTime:Math.floor(e),duration:Math.floor(n),completed:a,title:r?.title??null,poster:r?.poster??null,backdrop:r?.backdrop??null,year:r?.year??null,overview:r?.overview??null,tmdbId:r?.id??null,mediaType:k||"tv",adult:r?.adult?1:0}))},[j,u,S,lr,r,k]),Pe=_((e,n)=>{En();const a=new URLSearchParams(f);a.set("type",f.get("type")||"tv"),a.set("s",String(e)),a.set("e",String(n)),x(`${window.location.pathname}?${a.toString()}`)},[f,x,En]),qt=_(()=>{const e=l.current;if(!e||v||P==null){$n(!1);return}const n=e.duration||0,a=e.currentTime||0;$n(n>0&&a/n>=.8)},[v,P,l]),vn=_((e,n)=>["tv-sources",E,v?"movie":"tv",s,e,n,K],[E,v,s,K]),pn=_(async(e,n)=>{if(!r||!s||!E)return{valid:!1,sources:[]};const a=v?"movie":"tv",m=await kt.tv.sources.query({provider:E,type:a,tmdbId:String(s),season:e,episode:n,title:r.title||"",year:r.year||"",totalSeasons:String(r.number_of_seasons||1),imdbId:r.imdb_id||"",...K?{server:K}:{}});return{valid:"valid"in m?m.valid:!1,error:"error"in m?m.error:void 0,sources:m.sources,referer:"referer"in m?m.referer:void 0,audioTracks:m.audioTracks,subtitles:"subtitles"in m?m.subtitles:void 0,servers:"servers"in m?m.servers:void 0,server:"server"in m?m.server:void 0,embedUrl:"embedUrl"in m?m.embedUrl:void 0}},[r,s,E,v,K]),_r=_(()=>{if(v||!r||!s||!E||I||P==null)return;const e=vn(u,P);M.getQueryState(e)?.status!=="success"&&M.prefetchQuery({queryKey:e,queryFn:()=>pn(u,P),staleTime:300*1e3,gcTime:1800*1e3})},[v,r,s,E,I,P,u,M,vn,pn]),ms=_(()=>{if(ve)return;qt();const e=l.current;!e||e.paused||e.ended||(e.duration>0&&e.duration-e.currentTime<=60&&_r(),!Ve.current&&(Ve.current=setTimeout(()=>{Ve.current=null,Je(e.currentTime,e.duration||0)},5e3)))},[Je,l,ve,qt,_r]),hs=_(()=>{const e=l.current;if(!(!e||!r)&&(Ve.current&&clearTimeout(Ve.current),Ve.current=null,Je(e.currentTime,e.duration||0),!c)){if(P!=null){Ct&&(ye(P),Pe(u,P));return}!v&&G==null&&!Mn||(Zr(v?r.title:`${r.title} - Season ${u}`),ut(!0),Xe.current=!0)}},[v,r,u,P,G,Mn,Ct,Je,Pe,l,c]),{checkEnd:fn,logDuration:Cr}=eo({videoRef:l,sourceType:I?"iframe":void 0,resetKey:`${j}:${u}:${S}:${On}`,onEnd:hs}),vs=_(()=>{i.actions.onPlay()},[i.actions]),ps=_(()=>{i.actions.onPause();const e=l.current;e&&!e.ended&&Je(e.currentTime,e.duration||0)},[i.actions,Je,l]),fs=_(()=>{const e=l.current;if(e){try{const n=parseFloat($.getItem("playerVolume")||"");isNaN(n)||(e.volume=Math.max(0,Math.min(1,n))),e.muted=$.getItem("playerMuted")==="true"}catch{}if(X.current!=null&&X.current>0){try{e.currentTime=X.current}catch{}X.current=null}qt()}},[l,qt]),Un=_(()=>{const e=l.current;if(e&&X.current!=null&&X.current>0){try{e.currentTime=X.current}catch{}X.current=null}},[l]),bs=_(()=>{_t>0&&(X.current=_t);const e=l.current;if(e&&_t>0){try{e.currentTime=_t,X.current=null}catch{}e.play().catch(()=>{})}ln(!1),Xe.current=!0},[_t,l]),Tr=_(()=>{X.current=null;const e=l.current;e&&(e.currentTime=0,e.play().catch(()=>{})),ln(!1),Xe.current=!0},[l]),Wn=_(()=>{P!=null&&(Xe.current=!0,ye(P),Pe(u,P))},[P,u,Pe]),Hn=_(()=>{G!=null&&(ut(!1),Xe.current=!0,te(G),ye(1),Pe(G,1))},[G,Pe]),qn=_(async()=>{if(j)try{zt?await qe.mutateAsync({id:j,status:"Completed"}):r&&s&&(await Ke.mutateAsync({tmdbId:Number(s),mediaType:k||"tv",title:r.title,poster:r.poster,backdrop:r.backdrop,year:r.year,overview:r.overview,adult:r.adult,status:"Completed",silent:!0}),Br.success("Moved to Completed")),ut(!1),x("/")}catch{}},[j,zt,qe,Ke,r,s,k,x]);b(()=>{Xe.current=!1,an.current=null,ln(!1),$n(!1),mr(0),hr(!1),zn(!1),hn.current=!1,X.current=null,Vn.current=0},[j,u,S]),b(()=>{un.current=ze},[ze]),b(()=>{Ft&&(hr(!0),hn.current=!0)},[Ft,j,u,S]),b(()=>{if(d||Ln||!Ye||Xe.current)return;const e=`${j}:${u}:${S}`;if(an.current===e)return;an.current=e;const n=Ye,a=n.currentTime??0;$r(a)&&n.completed!==1&&!Qt(a,n.duration??0)&&(mr(a),ln(!0))},[Ye,Ln,j,u,S,d]),b(()=>{!d&&Qe&&l.current&&l.current.pause()},[Qe,l,d]),b(()=>{!d&&mt&&l.current&&l.current.pause()},[mt,l,d]),b(()=>{(je||mt||Ge)&&i.state.isFullscreen&&i.actions.toggleFullscreen()},[je,mt,Ge,i.state.isFullscreen,i.actions]),b(()=>{const e=l.current;return()=>{Ve.current&&clearTimeout(Ve.current),Ve.current=null,!e?.ended&&i.engine.getState().duration>0&&Je(i.engine.getTimeline().currentTime,i.engine.getState().duration)}},[i.engine,Je,l]);const Kn=_(e=>{let n=null,a=!0;try{n=$.getItem("tvLastSubtitle"),a=$.getItem("tvSubtitlesEnabled")!=="false"}catch{}return or(e,{lastKey:n,enabled:a})},[]),Yn=_(e=>{if(!(e<0))try{$.setItem("tvSubtitlesEnabled","true"),$.setItem("tvSelectedSubtitle",String(e))}catch{}},[]),kr=_(e=>{if(e.length===0)return 0;let n=null;try{n=$.getItem("tvLastAudio")}catch{}if(n){const a=e.findIndex(L=>nr(L)===n);if(a>=0)return a;const m=n.indexOf("|||"),h=m>=0?n.slice(0,m):n,T=m>=0?n.slice(m+3):n,D=e.findIndex(L=>L.language===h||L.label===T);if(D>=0)return D}return or(e,{lastKey:null,enabled:!0})},[]),Er=_(e=>{let n=null;try{n=$.getItem("tvLastQuality")}catch{}if(!n||e.length===0)return 0;const a=e.findIndex(L=>(L.quality||"")===n);if(a>=0)return a;const m=L=>{const ee=/(\d{3,4})/.exec(L||"");return ee?parseInt(ee[1],10):0},h=m(n);if(!h)return 0;let T=0,D=1/0;return e.forEach((L,ee)=>{const y=m(L.quality),H=Math.abs(y-h);y>0&&H<D&&(D=H,T=ee)}),T},[]),{data:Nr}=No(j||void 0),wr=Ce(()=>(Nr?.progress??[]).filter(n=>n.season===u&&(n.completed===1||Qt(n.currentTime,n.duration))).map(n=>String(n.episode)),[Nr,u]),Ar=Ce(()=>Ne.map(e=>({id:String(e.episode_number),label:`Episode ${e.episode_number}`,sublabel:e.name||void 0,thumbnail:e.still_path?`https://image.tmdb.org/t/p/w185${e.still_path}`:void 0})),[Ne]),Ir=Ce(()=>(r?.genres??[]).map(e=>e.name).slice(0,5),[r]),Qn=Ce(()=>[r?.year,r?.status,r?.number_of_seasons?`${r.number_of_seasons} Season${r.number_of_seasons>1?"s":""}`:null,r?.number_of_episodes?`${r.number_of_episodes} Episodes`:null].filter(Boolean),[r]);b(()=>{if(!c&&Q.length!==0&&!Q.some(e=>e.id===E)){const e=Q.find(n=>n.tier==="direct")?.id??Q[0].id;nt(e);try{$.setItem("tvProvider",e)}catch{}}},[Q,E,c]),b(()=>{he([]),at(""),gt(""),it(!1)},[E]),b(()=>{if(!c&&Se.length!==0&&!Se.includes(K)){xt(Se[0]);try{$.setItem("tvServer",Se[0])}catch{}}},[Se,K,c]),b(()=>{if(!s){R(null),Y([]),rt(""),se(""),He("");return}const e=Number(s),n=k||"tv";R(null),Y([]),rt(""),se(""),He("");const a=parseInt(z.current.get("s")||"",10),m=parseInt(z.current.get("e")||"",10);te(isNaN(a)?1:a),ye(isNaN(m)?1:m),ft(0),kt.tv.details.query({type:n,id:String(e)}).then(h=>{const T={id:h.id,title:h.title||"",overview:h.overview||"",vote_average:h.vote_average,year:h.year,poster:h.poster,backdrop:h.backdrop,imdb_id:h.imdb_id||void 0,adult:h.adult,status:h.status,seasons:h.seasons,number_of_seasons:h.number_of_seasons};R(T),T.seasons&&T.seasons.length>0&&isNaN(a)&&te(T.seasons[0].season_number)}).catch(()=>{})},[s,k]),b(()=>{if(!r||!s)return;if(!(r.seasons!==void 0||r.number_of_seasons!==void 0)){Le([]);return}const n=parseInt(f.get("e")||"",10);kt.tv.episodes.query({id:String(s),season:String(u)}).then(a=>{const m=(a.episodes||[]).map(h=>({episode_number:h.episode_number,name:h.name||"",vote_average:h.vote_average,overview:h.overview||"",still_path:h.still_path||""}));Le(m),m.length!==0&&ye(h=>!isNaN(n)&&m.some(T=>T.episode_number===n)?n:m.some(T=>T.episode_number===h)?h:m[0].episode_number)}).catch(()=>{})},[r,s,u,f]),b(()=>{if(!I||!r||!s)return;tr(`/api/tv/embed/${E}/${v?"movie":"tv"}/${s}?season=${u}&episode=${S}`).then(n=>{if(n.url)return He(n.url),tr(`/api/resolve?url=${encodeURIComponent(n.url)}`).then(a=>{a.finalUrl&&He(a.finalUrl)})}).catch(()=>{})},[E,r,s,u,S,v,I]);const bn=_(async()=>{if(!r||!s||!E||I||r.adult&&!Ot)return;const e=ze;Me(!0),se(""),Bt.current.length===0&&(Y([]),ft(0),Ue([]),Pt([]));try{const n=await M.fetchQuery({queryKey:vn(u,S),queryFn:()=>pn(u,S),staleTime:3e5,gcTime:18e5});if(un.current!==e)return;if(Me(!1),!n.valid||!n.sources?.length){se(n.error?`${n.error}`:Se.length>0?`No streams from ${K}. Try another server.`:"No streams available.");return}if(d&&K&&n.server&&n.server!==K){Y([]),se("The host's selected server is unavailable. Automatic source switching is disabled in watch-along rooms.");return}!c&&!K&&n.server&&xt(n.server);const a=d?n.sources.filter(L=>L.type==="hls"):n.sources;if(d&&a.length===0){Y([]),se("The room requires a direct HLS source. No compatible stream is available here.");return}Y(a),Nt(n.server||K),rt(e),n.servers?.length&&he(n.servers),n.embedUrl&&at(n.embedUrl),ft(Er(a)),n.referer&&Gt(n.referer);const m=n.audioTracks||[];Ue(m),It(m.length>0?kr(m):0);const h=n.subtitles||[];if(Pt(h),h.length>0){const L=Kn(h);De(L),Yn(L)}else De(-1);const T=v?"movie":"tv",D=s;kt.tv.subtitles.query({type:T,tmdbId:String(D),season:String(u),episode:String(S)}).then(L=>{if(un.current!==e)return;const ee=Array.isArray(L.subtitles)?L.subtitles:[];ee.length!==0&&Pt(y=>{const H=[...y,...ee.filter(J=>!y.some(V=>V.url===J.url))];if(y.length===0){const J=Kn(H);De(J),Yn(J)}return H})}).catch(()=>{}),se("")}catch(n){if(un.current!==e)return;Me(!1),se(n instanceof Error?n.message:"Failed to load streams.")}},[r,s,E,u,S,v,I,Ot,Se,K,Kn,Yn,kr,Er,M,vn,pn,ze,d,c]),jn=_(()=>{const e=l.current;e&&!isNaN(e.currentTime)&&(X.current=e.currentTime)},[l]),gs=_(e=>{if(!(c||d&&e==="Embed")){if(e==="Embed"){it(!0);return}jn(),it(!1),xt(e);try{$.setItem("tvServer",e)}catch{}se("")}},[jn,c,d]),ys=_(e=>{nt(e);try{$.setItem("tvProvider",e)}catch{}},[]);b(()=>{E&&r&&!I&&bn()},[E,r,bn,I]),b(()=>{if(je){i.engine.unload();return}if(!l.current)return;if(F.current=null,I||Ae||d&&W[we]?.type!=="hls"){i.engine.unload();return}if(ve&&!d)return i.engine.loadSource({url:"/av-sync-test.mp4"},{autoPlay:!mn.current});if(tn.current!=null&&(X.current=tn.current,tn.current=null),Be===ze&&X.current==null&&!mn.current)try{const y=l.current;y&&!y.ended&&y.currentTime>1&&(X.current=y.currentTime)}catch{}const n=X.current??0,a=!ue&&Be===ze?Ae?"":W[we]?.url||"":"";if(!a){try{l.current?.pause(),l.current?.removeAttribute("src"),l.current?.load()}catch{}return}const m=l.current;m.pause(),m.removeAttribute("src"),m.load(),i.actions.resetMediaState();const h=`/api/tv/stream-proxy?url=${encodeURIComponent(a)}&referer=${encodeURIComponent(We)}&provider=${encodeURIComponent(E)}`,T=Na()||document.body.classList.contains("low-end"),D=T?60:180,L=i.engine.loadSource({url:h,hls:W[we]?.type==="hls"},{hlsConfig:{enableWorker:!0,lowLatencyMode:!1,startPosition:n>0?n:-1,maxBufferLength:D,maxMaxBufferLength:D+(T?30:60),backBufferLength:T?30:60,maxBufferSize:(T?120:360)*1e3*1e3,fragLoadPolicy:{default:{maxTimeToFirstByteMs:15e3,maxLoadTimeMs:45e3,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:3,retryDelayMs:800,maxRetryDelayMs:6e3}}},manifestLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:25e3,timeoutRetry:{maxNumRetry:1,retryDelayMs:500,maxRetryDelayMs:2e3},errorRetry:{maxNumRetry:2,retryDelayMs:800,maxRetryDelayMs:4e3}}}},onHls:(y,H)=>{F.current=y;const J=()=>{let O=!1,B=0;try{O=$.getItem("tvSubtitlesEnabled")==="true";const N=parseInt($.getItem("tvSelectedSubtitle")||"0",10);!isNaN(N)&&N>=0&&(B=N)}catch{}return{enabled:O,index:B}},V=()=>{if(typeof y.subtitleTrack!="number")return;if(ce.current.length>0){y.subtitleTrack=-1;return}const O=Array.isArray(y.subtitleTracks)?y.subtitleTracks:[];if(O.length===0){y.subtitleTrack=-1;return}const B=J();if(B.enabled){const N=B.index<O.length?B.index:0;y.subtitleTrack=N,De(N),xn()}else y.subtitleTrack=-1};ka(y,H.Events,{getWant:()=>Mt.current,onResolve:O=>It(O)}),y.on(H.Events.MANIFEST_PARSED,V),y.on(H.Events.SUBTITLE_TRACKS_UPDATED,()=>{V()}),y.on(H.Events.SUBTITLE_TRACK_SWITCH,(O,B)=>{if(ce.current.length>0){if(B.id!==-1)try{y.subtitleTrack=-1}catch{}return}const N=Array.isArray(y.subtitleTracks)?y.subtitleTracks:[];if(N.length!==0){if(B.id===-1){const Ee=J();if(Ee.enabled){const ae=Ee.index<N.length?Ee.index:0;y.subtitleTrack=ae;return}}De(B.id),xn()}})},onReady:()=>{(n>0||!mn.current&&hn.current)&&i.engine.play()},onError:y=>{se(y.message),Me(!1),F.current=null}}),ee=()=>{const J=m.error?.code===4?"Video source not supported or not found":"Failed to load video stream";se(`${J}. The source may be invalid or expired. Try switching source or reloading.`),Me(!1)};return m.addEventListener("error",ee),()=>{L(),F.current=null,m.removeEventListener("error",ee)}},[W,Be,ue,we,E,We,I,Ae,l,tn,ve,j,u,S,Un,xn,i.actions,i.engine,ze,d,je]),b(()=>{if(c||!Ut||Qe||dt||Ht||I||ve)return;const e=l.current;!e||!e.paused||e.ended||e.readyState<1||(Un(),i.engine.play())},[Ut,Qe,dt,Ht,I,ve,Un,l,c,i.engine]),b(()=>{const e=F.current;!e||typeof e.audioTrack!="number"||(e.audioTrack=Te)},[Te]),b(()=>{const e=F.current;!e||typeof e.subtitleTrack!="number"||!Array.isArray(e.subtitleTracks)||e.subtitleTracks.length===0||ce.current.length>0||(me>=0?e.subtitleTrack=me:e.subtitleTrack=-1)},[me]),b(()=>{const e=l.current;if(!(!e||I)&&(e.querySelectorAll("track").forEach(n=>n.remove()),ce.current=[],ke.length!==0&&(ke.forEach(n=>{const a=document.createElement("track");a.kind="subtitles",a.label=n.label||n.language||"Unknown",a.srclang=n.language||n.label||"en";const m=`/api/subtitle-proxy?url=${encodeURIComponent(n.url)}&referer=${encodeURIComponent(We)}`;a.src=m,a.addEventListener("load",()=>{const h=ce.current.indexOf(a),T=a.track;if(T&&h>=0){const D=h===yt.current;T.mode=D&&!Pn.current?"showing":"hidden"}}),e.appendChild(a),ce.current.push(a)}),ke.length>0)))try{const n=F.current;n&&typeof n.subtitleTrack=="number"&&n.subtitleTrack!==-1&&(n.subtitleTrack=-1)}catch{}},[ke,We,I,E,K,l]),b(()=>{const e=l.current;if(!e||I)return;const n=F.current;ce.current.length>0&&n&&typeof n.subtitleTrack=="number"&&Array.isArray(n.subtitleTracks)&&n.subtitleTracks.length>0&&(n.subtitleTrack=-1);const a=()=>{const T=ar(i.state.subtitleFontSize,e.clientHeight||720),D=Math.max(0,Math.min(100,100-i.state.subtitlePosition)),L=()=>{const V=T*16,O=e.videoHeight||e.clientHeight||720,B=e.videoWidth||e.clientWidth||1280;return{step:V*1.3/O*100,chars:Math.max(20,Math.floor(B/(V*.55)))}},ee=(V,O)=>{const B=V;B.snapToLines=!1,B.line=O},y=V=>{if(!V.cues)return;Array.from(V.cues).forEach(ae=>ee(ae,D));const O=Array.from(V.activeCues??[]);if(O.length<=1){O.forEach(ae=>ee(ae,D));return}const{step:B,chars:N}=L();let Ee=D;for(let ae=O.length-1;ae>=0;ae--){const Ze=String(O[ae].text??"").replace(/<[^>]*>/g,"").split(`
|
|
3
|
+
`).reduce((yn,Kt)=>yn+Math.max(1,Math.ceil(Kt.length/N)),0);Ee=Math.max(0,Ee-Ze*B),ee(O[ae],Ee),Ee-=B*.4}},H=ce.current;if(H.length>0){H.forEach((V,O)=>{const B=V.track;if(!B)return;const N=O===me;B.mode=N&&!_e?"showing":"hidden",N&&!_e&&y(B)});return}const J=Array.from(e.textTracks);J.length!==0&&J.forEach((V,O)=>{const B=O===me;V.mode=B&&!_e?"showing":"hidden",B&&!_e&&y(V)})};a();const m=()=>a();e.textTracks.addEventListener("addtrack",m),e.addEventListener("loadedmetadata",a,{once:!0});const h=window.setTimeout(a,600);return()=>{e.textTracks.removeEventListener("addtrack",m),e.removeEventListener("loadedmetadata",a),window.clearTimeout(h)}},[me,ke,I,E,l,_e,i.state.subtitleFontSize,i.state.subtitlePosition]),b(()=>{if(!_e)return;const e=l.current,n=$t.current;if(!e||!n)return;const a=St/1e3,m=Nn/1e3,h=new Set;let T=[],D=-1,L=-1,ee=-1,y=-1,H=0,J=0,V=!1;const O=()=>{const q=yt.current;if(q<0)return null;const et=ce.current;return et.length>0?et[q]?.track??null:Array.from(e.textTracks)[q]??null},B=(q,et)=>{const pe=q.cues;if(!pe||pe.length===0)return Array.from(q.activeCues??[]);let ht=0,vt=pe.length;for(;ht<vt;){const xe=ht+vt>>>1;pe[xe].endTime+a<et?ht=xe+1:vt=xe}const Yt=[];for(let xe=ht;xe<pe.length;xe++){const Sn=pe[xe];if(Sn.startTime+a>et)break;Sn.endTime+a>=et&&Yt.push(Sn)}return Yt},N=()=>{const q=O(),et=e.currentTime-m,pe=q?B(q,et):[],ht=e.clientWidth,vt=e.clientHeight,Yt=e.videoWidth,xe=e.videoHeight;if(pe.length===T.length&&pe.every((Jn,Zn)=>Jn===T[Zn])&&ht===D&&vt===L&&Yt===ee&&xe===y||(T=pe,D=ht,L=vt,ee=Yt,y=xe,n.textContent="",pe.length===0))return;const Rr={fontSize:ar(i.state.subtitleFontSize,vt),position:i.state.subtitlePosition,bgOpacity:i.state.subtitleBgOpacity,bgColor:i.state.subtitleBgColor,textColor:i.state.subtitleTextColor,edge:i.state.subtitleEdge,bold:i.state.subtitleBold},Ts=to(Rr),ks=no(e,Rr.position);pe.forEach((Jn,Zn)=>{const Lr=String(Jn.text??"");if(!ro(Lr).trim())return;const er=document.createElement("div"),Es=(pe.length-1-Zn)*1.7;er.style.cssText=`${Ts}
|
|
4
|
+
bottom: calc(${ks}px + ${Es}em);`,er.innerHTML=so(Lr),n.appendChild(er)})},Ee=()=>{Array.from(e.textTracks).forEach(q=>{h.has(q)||(h.add(q),q.addEventListener("cuechange",N))})},ae=()=>{Ee(),N()},Xn=()=>{if(V||J)return;const q=()=>{J=0,!(V||e.paused||e.ended)&&(N(),Xn())};J=window.requestAnimationFrame(q)},Ze=e,yn=()=>{H=0,N(),!V&&Ze.requestVideoFrameCallback&&(H=Ze.requestVideoFrameCallback(yn))},Kt=()=>{N(),Ze.requestVideoFrameCallback?H||(H=Ze.requestVideoFrameCallback(yn)):Xn()};Ee(),e.textTracks.addEventListener("addtrack",ae),e.textTracks.addEventListener("removetrack",ae),e.addEventListener("timeupdate",N),e.addEventListener("seeked",N),e.addEventListener("loadedmetadata",N),e.addEventListener("play",Kt);const Pr=Array.from(e.querySelectorAll("track"));Pr.forEach(q=>q.addEventListener("load",N));const xr=typeof ResizeObserver>"u"?null:new ResizeObserver(()=>N());return xr?.observe(e),N(),Kt(),()=>{V=!0,h.forEach(q=>q.removeEventListener("cuechange",N)),e.textTracks.removeEventListener("addtrack",ae),e.textTracks.removeEventListener("removetrack",ae),e.removeEventListener("timeupdate",N),e.removeEventListener("seeked",N),e.removeEventListener("loadedmetadata",N),e.removeEventListener("play",Kt),Pr.forEach(q=>q.removeEventListener("load",N)),xr?.disconnect(),J&&window.cancelAnimationFrame(J),H&&Ze.cancelVideoFrameCallback&&Ze.cancelVideoFrameCallback(H),n.textContent=""}},[_e,St,me,ke,Nn,l,i.state.subtitleFontSize,i.state.subtitlePosition,i.state.subtitleBgOpacity,i.state.subtitleBgColor,i.state.subtitleTextColor,i.state.subtitleEdge,i.state.subtitleBold]);const Gn=()=>{R(null),Y([]),He(""),x(-1)},Ss=_(e=>{c||(te(e),ye(1),Pe(e,1))},[Pe,c]),gn=!v&&r?.seasons&&r.seasons.length>1?t("label",{className:p.sidebarSeason,children:[t("span",{children:"Season"}),t("select",{disabled:c,value:u,onChange:e=>Ss(parseInt(e.currentTarget.value,10)||1),className:p.select,children:r.seasons.map(e=>t("option",{value:e.season_number,children:["Season ",e.season_number," (",e.episode_count," ep)"]},e.season_number))})]}):null,Tt=_(e=>{if(c)return;const n=parseInt(e,10);if(!isNaN(n)){try{l.current?.pause()}catch{}ye(n),Pe(u,n)}Dn(!1)},[u,Pe,l,c]);b(()=>{if(v)return;const e=n=>{n.target.closest('input, textarea, button, select, a, [role="button"], [contenteditable="true"]')||n.key.toLowerCase()==="n"&&(P!=null?Tt(String(P)):Br.error("No next episode available"))};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[v,P,Tt]);const _s=e=>{It(e);try{const a=At[e];a&&$.setItem("tvLastAudio",nr(a))}catch{}const n=F.current;n&&n.audioTrack!==void 0&&(n.audioTrack=e)},Cs=e=>{De(e);try{if(e===-1)$.setItem("tvSubtitlesEnabled","false");else{$.setItem("tvSubtitlesEnabled","true"),$.setItem("tvSelectedSubtitle",String(e));const h=ke[e];h&&$.setItem("tvLastSubtitle",nr(h))}}catch{}const n=l.current,a=F.current;if(a&&typeof a.subtitleTrack=="number"&&Array.isArray(a.subtitleTracks)&&a.subtitleTracks.length>0&&(a.subtitleTrack=ce.current.length>0||e<0?-1:e),!n)return;const m=ce.current;if(m.length>0){m.forEach((h,T)=>{const D=h.track;if(!D)return;const L=T===e;D.mode=L&&!_e?"showing":"hidden"});return}Array.from(n.textTracks).forEach((h,T)=>{const D=T===e;h.mode=D&&!_e?"showing":"hidden"})};return b(()=>{if(!r){document.title="TV & Movies - dango";return}document.title=v?`${r.title} - dango`:`${r.title} - Season ${u} Episode ${S} - dango`},[r,v,u,S]),b(()=>{if(!r||v)return;const e=new URLSearchParams(f),n=e.get("s"),a=e.get("e"),m=String(u),h=String(S);n===m&&a===h||(e.set("type",f.get("type")||"tv"),e.set("s",m),e.set("e",h),x(`${window.location.pathname}?${e.toString()}`,{replace:!0}))},[r,v,u,S,f,x]),t("div",{className:`${Re.playerPageLayout} ${Fe?Re.theaterMode:""} ${v?Re.noSidebar:""}`,onClick:ns,children:[Fe&&t(oo,{videoRef:l,active:In.enabled&&!I&&W.length>0&&!$e&&!(r?.adult&&!Ot),settings:In}),!Fe&&!v&&t("aside",{className:Re.episodeSidebar,children:r?t(ao,{episodes:Ar,currentEpisode:String(S),watchedEpisodes:wr,onEpisodeClick:Tt,header:gn}):t(io,{variant:"sidebar"})}),t("div",{className:Re.playerMain,children:[r&&t("div",{className:p.playerSection,onContextMenu:e=>e.preventDefault(),style:r.adult&&!Ot?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:I&&ot&&!d?t("iframe",{src:ot,className:p.videoIframe,allow:"autoplay; fullscreen",allowFullScreen:!0}):!I&<&&!d?t("iframe",{src:lt,className:p.videoIframe,allow:"autoplay; fullscreen",allowFullScreen:!0}):!I&&(W.length>0||ue)?t(tt,{children:[$e&&t(Or,{error:$e,onRetry:bn}),t(Sa,{player:i,title:r.title,episodeLabel:v?void 0:`S${u} E${S}`,server:de||bt?.label||E,audioTracks:At,selectedAudioTrack:Te,onAudioTrackChange:_s,subtitles:ke,selectedSubtitle:me,onSubtitleChange:Cs,streams:W,resolutionIdx:we,onResolutionChange:e=>{jn(),ft(e);try{const n=W[e]?.quality;n&&$.setItem("tvLastQuality",n)}catch{}},onBack:Gn,videoDelayEnabled:en,onVideoDelayToggle:Tn,videoDelayMs:Oe,onVideoDelayChange:Dt,onCalibrateAvSync:d?void 0:Fr,subtitleDelayMs:St,onSubtitleDelayChange:qr,showNextEpisodeButton:!c&&Xr&&!Qe&&!dt,onNextEpisode:Wn,isLoading:ue,isTheaterMode:Fe,onTheaterModeToggle:Fn,ambientSettings:In,onAmbientChange:Kr,hideChrome:je||Ge,children:t(tt,{children:[t(Fs,{autoPlay:!d&&Ut&&!Ht,playsInline:!0,disablePictureInPicture:!0,className:`${p.video} ${An?p.videoHidden:""}`,onTimeUpdate:()=>{ve||(ms(),fn())},onEnded:()=>{ve||fn(!0)},onPlay:vs,onPause:ps,onSeeked:()=>{ve||(qt(),fn())},onLoadedMetadata:()=>{fs(),Cr(),fn()},onDurationChange:()=>{Cr()},onContextMenu:e=>e.preventDefault(),onError:()=>{se("Video failed to load. Try another server or reload."),Me(!1)}}),t("canvas",{ref:Zt,className:`${p.delayCanvas} ${An?p.delayCanvasActive:""}`}),_e&&t("div",{ref:$t,className:p.subtitleOverlay}),t(lo,{isOpen:kn,ms:Oe,onChange:Dt,onApply:Ur,onClose:Vr,testClipActive:ve,onTestClip:Wr}),(je||Ge)&&t("div",{className:p.watchedOverlay,children:[t(ie,{name:"check-circle",size:48,style:{color:"var(--accent-lighter)"}}),t("p",{className:p.watchedTitle,children:Ge||ct?G!=null?"Season Complete!":v?"Movie Completed!":"Show Completed!":v?"Movie watched":`S${u} E${S} watched`}),t("p",{className:p.watchedSubtext,children:Ge||ct?G!=null?`You finished Season ${u}.`:v?"You finished this movie!":"Congratulations! You finished all available episodes.":"Resume where you left off, replay from the beginning, or continue with the next episode."}),t("div",{className:`${p.watchedActions} ${Ge?p.watchedActionsCentered:""}`,children:[t("div",{children:Ie>5&&!Ge&&t(fe,{variant:ur?void 0:"secondary",onClick:Sr,children:`Resume ${jt(Ie)}`})}),t("div",{children:P!=null?t(fe,{onClick:Wn,children:`Watch EP ${P}`}):G!=null?t(fe,{onClick:Hn,children:`Start Season ${G}`}):null}),t("div",{children:[t(fe,{variant:"secondary",onClick:yr,children:"Replay"}),ct&&t(fe,{onClick:qn,disabled:qe.isPending||Ke.isPending,children:qe.isPending||Ke.isPending?"Saving...":"Move to Completed"})]})]})]})]})})]}):$e&&!I?t(Or,{error:$e,onRetry:bn}):null}),t(Lo,{playback:rn?{selection:rn,position:l.current?.currentTime||0,playing:!1,rate:i.engine.getState().playbackRate}:null,onCreate:()=>{En(),i.engine.pause()},needsPlayback:ir.needsPlayback,onEnablePlayback:ir.enablePlayback}),d&&!ue&&r&&!rn&&t("p",{role:"alert",children:"The host's direct HLS source is unavailable here. Retry or leave the room to use another source."}),!Fe&&r&&t(co,{}),!Fe&&gn&&t("div",{className:p.mobileSeasonRow,children:gn}),!Fe&&r&&t("div",{className:Z.streamPanel,children:[t("div",{className:p.providerRow,children:[t("label",{className:p.controlLabel,children:["Provider",t("select",{value:E,onChange:e=>ys(e.currentTarget.value),className:p.select,disabled:c||Q.length===0,children:wt?t("option",{value:"",children:"Loading..."}):Q.length===0?t("option",{value:"",children:"No providers available"}):t(tt,{children:[A.length>0&&t("optgroup",{label:"Direct HLS",children:A.map(e=>t("option",{value:e.id,children:e.label},e.id))}),re.length>0&&t("optgroup",{label:"Embeds",children:re.map(e=>t("option",{value:e.id,children:e.label},e.id))})]})})]}),!v&&ds(p.providerActions)]}),!c&&!I&&(ue?t("div",{className:p.sourceLoader,children:t("div",{className:p.ringSpinner})}):t(Ca,{servers:Jt,selectedServer:Lt?"Embed":K,onServerSelect:gs}))]}),!Fe&&r&&t("div",{className:Re.playerInfoContainer,children:[t("div",{className:Re.playerInfoHeader,children:[t("div",{className:Re.playerAnimeCard,children:r.poster&&t(Bs,{src:`https://image.tmdb.org/t/p/w342${r.poster}`,alt:r.title,loading:"lazy",decoding:"async"})}),t("div",{className:Re.videoTitleSection,children:[t("div",{className:Z.titleContainer,children:[t("h1",{children:r.title}),t("div",{className:p.meta,children:[t("span",{className:p.year,children:r.year}),r.vote_average!=null&&r.vote_average>0&&t("span",{className:p.rating,children:[t(ie,{name:"star",size:12}),Number(r.vote_average).toFixed(1)]}),t("span",{className:`${p.typeBadge} ${p[v?"movie":"tv"]}`,children:v?"Movie":"TV Show"})]}),Ir.length>0&&t("div",{className:p.genreRow,children:Ir.map(e=>t("span",{className:p.genreChip,children:e},e))}),Qn.length>0&&t("div",{className:p.metaRow,children:Qn.map((e,n)=>t("span",{children:[e,n<Qn.length-1?" · ":""]},`${e}-${n}`))})]}),t("div",{className:Z.controls,children:t("button",{className:`${Z.watchlistBtn} ${zt?Z.inList:""}`,onClick:Gr,disabled:jr,type:"button",children:[zt?t(ie,{name:"check",size:14}):t(ie,{name:"plus",size:14}),zt?"In Watchlist":"Add to Watchlist"]})})]})]}),t("div",{className:Re.infoColumns,children:[t("div",{className:`${Z.descriptionSection} ${Z.synopsisFlat}`,children:[t("h3",{children:"Synopsis"}),t(Ro,{text:r.overview,emptyText:"No description available."}),t("button",{className:Z.detailsToggleBtn,onClick:()=>es(!cn),type:"button",children:[cn?t(ie,{name:"chevron-up"}):t(ie,{name:"chevron-down"}),cn?"Hide Details":"Show Details"]})]}),cn&&t("div",{className:p.detailGrid,children:[r.first_air_date&&t("div",{className:p.detailItem,children:[t("strong",{children:v?"Release Date":"First Air Date"}),t("span",{children:r.first_air_date})]}),r.last_air_date&&t("div",{className:p.detailItem,children:[t("strong",{children:"Last Air Date"}),t("span",{children:r.last_air_date})]}),r.networks&&r.networks.length>0&&t("div",{className:p.detailItem,children:[t("strong",{children:"Networks"}),t("span",{children:r.networks.map(e=>e.name).join(", ")})]}),r.created_by&&r.created_by.length>0&&t("div",{className:p.detailItem,children:[t("strong",{children:"Created By"}),t("span",{children:r.created_by.map(e=>e.name).join(", ")})]}),r.episode_run_time&&r.episode_run_time.length>0&&t("div",{className:p.detailItem,children:[t("strong",{children:"Episode Runtime"}),t("span",{children:[r.episode_run_time[0]," min"]})]}),r.imdb_id&&t("div",{className:p.detailItem,children:[t("strong",{children:"IMDb"}),t("a",{href:`https://www.imdb.com/title/${r.imdb_id}`,target:"_blank",rel:"noopener noreferrer",className:p.imdbLink,children:"View on IMDb"})]})]})]})]}),!v&&t(uo,{isOpen:ts,onClose:()=>Dn(!1),episodes:Ar,currentEpisode:String(S),watchedEpisodes:wr,onEpisodeClick:Tt,header:gn}),r?.adult&&!Ot&&t(bo,{isOpen:!0,onClose:Gn,onGrant:Yr}),t(mo,{isOpen:!d&&Qe&&!Ln&&an.current===`${j}:${u}:${S}`&&Ye?.completed!==1&&!Qt(Ie,Ye?.duration??0),onClose:Tr,title:"Resume Watching",message:t(tt,{children:["You were at ",t("strong",{children:jt(_t)})]}),restartLabel:"Start from Beginning",onResume:bs,onRestart:Tr}),t(Mr,{isOpen:mt,onClose:()=>br(!0),title:ct?v?"Movie Completed!":"Show Completed!":"Episode Completed",heading:v?r?.title??"Movie":`S${u} E${S}`,message:ct?v?"You finished this movie!":"Congratulations! You finished all available episodes.":v?"You've already watched this movie. Resume where you left off or replay it.":"You've already watched this episode. Resume where you left off, replay it, or continue with the next episode.",children:[Ie>5&&t(fe,{variant:ur?void 0:"secondary",onClick:Sr,children:`Resume ${jt(Ie)}`}),t(fe,{variant:"secondary",onClick:yr,children:"Replay"}),P!=null?t(fe,{onClick:Wn,children:["Watch EP ",P]}):G!=null?t(fe,{onClick:Hn,children:["Start Season ",G]}):ct?t(fe,{onClick:qn,disabled:qe.isPending||Ke.isPending,children:qe.isPending||Ke.isPending?"Saving...":"Move to Completed"}):null]}),t(Mr,{isOpen:as,onClose:()=>ut(!1),title:v?"Movie Completed!":G!=null?"Season Complete!":"Show Completed!",heading:Jr,message:v?"You finished this movie!":G!=null?`You finished Season ${u}.`:"Congratulations! You finished all available episodes.",children:G!=null?t(fe,{onClick:Hn,children:["Start Season ",G]}):t(tt,{children:[t(fe,{onClick:()=>{ut(!1),Gn()},children:"Back to Details"}),t(fe,{onClick:qn,disabled:qe.isPending||Ke.isPending,children:qe.isPending||Ke.isPending?"Saving...":"Move to Completed"})]})}),!r&&t("div",{className:p.statusMsg,children:[t(ie,{name:"spinner",className:p.spinner})," Loading..."]})]})]})};export{Ai as default};
|