@serifpersia/dango 3.7.9 → 3.8.0
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-DWnU-rCc.js → AnimeCard-BURLDiUV.js} +1 -1
- package/client/dist/assets/{AnimeInfo-Ck-fMvdY.js → AnimeInfo-D2coN_ZJ.js} +1 -1
- package/client/dist/assets/{AnimeInfoPage-_iM5y3E4.js → AnimeInfoPage-BfPP9trp.js} +2 -2
- package/client/dist/assets/{Asmr-CzqLNY2c.js → Asmr-CiuBtMGl.js} +1 -1
- package/client/dist/assets/{AsmrResetProgressModal-73jUOcAL.js → AsmrResetProgressModal-BDFeO6fQ.js} +1 -1
- package/client/dist/assets/{Home--RCZI3_q.js → Home-GShTLEbZ.js} +1 -1
- package/client/dist/assets/{Insights-B5oANHfN.js → Insights-CKk02Whw.js} +1 -1
- package/client/dist/assets/{LibraryListPage-CV2FpbUe.js → LibraryListPage-AGyVc7pR.js} +1 -1
- package/client/dist/assets/{ListeningList-Bb7qLeQy.js → ListeningList-DeAdvRjS.js} +1 -1
- package/client/dist/assets/{Manga-RzxC02lH.js → Manga-CiPWc8Ly.js} +1 -1
- package/client/dist/assets/{MangaInfoPage-DLANpxOs.js → MangaInfoPage-3jObt7zd.js} +1 -1
- package/client/dist/assets/{MangaReadPage-DuMOiKID.js → MangaReadPage-V5M2BLWG.js} +1 -1
- package/client/dist/assets/{MangaResetProgressModal-Y2PuLQHz.js → MangaResetProgressModal-CXRvdwD9.js} +1 -1
- package/client/dist/assets/{Mature-DfO3sop8.js → Mature-B9IEX0IP.js} +1 -1
- package/client/dist/assets/{MatureConsentModal-DiWSp3Of.js → MatureConsentModal-LTZSG_Kx.js} +1 -1
- package/client/dist/assets/{MediaCard-ChUKs5Sb.js → MediaCard-l2gAJctz.js} +1 -1
- package/client/dist/assets/{OptionListMenu-Cwb6MHoZ.js → OptionListMenu-CHJb3qot.js} +1 -1
- package/client/dist/assets/{Player-JA7rXoBD.js → Player-BTimy0Mp.js} +2 -2
- package/client/dist/assets/{PlayerProvider--aaVRFly.js → PlayerProvider-BXBzQc8G.js} +1 -1
- package/client/dist/assets/{PlayerSettings-CxlbcdU4.js → PlayerSettings-B-_QOjfP.js} +1 -1
- package/client/dist/assets/{QueueOptionsButton-C6ArqpM5.js → QueueOptionsButton-BCxERY1G.js} +1 -1
- package/client/dist/assets/{QueueRail-Derl5yzz.js → QueueRail-BX4CwNHY.js} +1 -1
- package/client/dist/assets/{ReadingList-BYbV0CvS.js → ReadingList-BLUM-leI.js} +1 -1
- package/client/dist/assets/{ResetProgressModal-DtUE-wCy.js → ResetProgressModal-DLs9yqI-.js} +1 -1
- package/client/dist/assets/{Search-CzTO0VVY.js → Search-tnIvsV_a.js} +1 -1
- package/client/dist/assets/{Settings-DKGEpLWL.js → Settings-CibKc1Rt.js} +1 -1
- package/client/dist/assets/{SkeletonGrid-BO0am1za.js → SkeletonGrid-nW7P1jQU.js} +1 -1
- package/client/dist/assets/{Trackers-uUzceJl6.js → Trackers-Cynvnhc3.js} +1 -1
- package/client/dist/assets/{Tv-CuM6Jhjn.js → Tv-BePMuQoo.js} +1 -1
- package/client/dist/assets/{TvInfo-4DOit0hL.js → TvInfo-DGIpvh-v.js} +1 -1
- package/client/dist/assets/{TvPopup-DYYtMp7D.js → TvPopup-BS4iiQMd.js} +1 -1
- package/client/dist/assets/{TvSearch-C-IYU0V4.js → TvSearch-p0kCDTee.js} +1 -1
- package/client/dist/assets/{TvWatchlist--kFfdVIF.js → TvWatchlist-CmXQkDQp.js} +1 -1
- package/client/dist/assets/{VirtualKeyboard-BYc_6hb4.js → VirtualKeyboard-CroH8QGP.js} +1 -1
- package/client/dist/assets/{WatchAlong-zZPGaH2D.js → WatchAlong-iCJlxiZA.js} +1 -1
- package/client/dist/assets/{WatchAlongPanel-DxC7pX1I.js → WatchAlongPanel-R7Nd5MXr.js} +1 -1
- package/client/dist/assets/{Watchlist-CX9qGh-b.js → Watchlist-D2sHodVo.js} +1 -1
- package/client/dist/assets/{index-DbRDs7tF.js → index-DYanm9eZ.js} +2 -2
- package/client/dist/assets/{libraryInvalidation-cJ1WjrJq.js → libraryInvalidation-DlwONLN-.js} +1 -1
- package/client/dist/assets/{playbackCompletion-CnxK6_Vz.js → playbackCompletion-CxGa4g7a.js} +1 -1
- package/client/dist/assets/{useAnimeInfoData-YbePqj-M.js → useAnimeInfoData-DMeGA3wY.js} +1 -1
- package/client/dist/assets/{useAsmr-DO5DUI_t.js → useAsmr-B88X71vs.js} +1 -1
- package/client/dist/assets/{useAsmrPopup-S_XfgKDh.js → useAsmrPopup-DEhKwHLC.js} +1 -1
- package/client/dist/assets/{useMangaLibrary-B4ZJLZXD.js → useMangaLibrary-CX_0zLJK.js} +1 -1
- package/client/dist/assets/{useMangaPopup-B4ntcNg0.js → useMangaPopup-Dkq2Yw-e.js} +1 -1
- package/client/dist/assets/{useProviders-Bnw0sBAP.js → useProviders-D9QoFCnY.js} +1 -1
- package/client/dist/assets/{useTv-gF7SJCl9.js → useTv-BGXZmuV8.js} +1 -1
- package/client/dist/assets/{useTvLibrary-DTWM3iOC.js → useTvLibrary-TnVQ2e21.js} +1 -1
- package/client/dist/assets/{useWatchAlongPlayer-Do0c9QsI.js → useWatchAlongPlayer-3HXJvQR2.js} +1 -1
- package/client/dist/index.html +1 -1
- package/package.json +2 -2
- package/server/dist/server.js +1 -1
- package/server/dist/shipped-defaults.js +1 -1
- package/server/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{h as j,d as i,A as ye,u as e,S as g,g as en,q as $e}from"./vendor-core-DfaOB3Rn.js";import{u as V,b as Q,a as I}from"./vendor-query-BBT5_sHx.js";import{F as r,q as s,t as c,ad as nn,n as an,S as Ke,B as ge}from"./index-DbRDs7tF.js";import{I as m}from"./vendor-icons-DrybRNxP.js";function tn(){const N=V();j(()=>{const x=new URLSearchParams(window.location.search),h=x.get("mal");if(!h)return;const t=x.get("user"),y=x.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 sn(){const N=V(),[x,h]=i(!1);return j(()=>{const t=new URLSearchParams(window.location.search),y=t.get("anilist");if(y){const f=t.get("user"),u=t.get("reason");window.history.replaceState(null,"",window.location.pathname),y==="success"?(r.success(f?`Connected to AniList as ${decodeURIComponent(f)}`:"Connected to AniList"),N.invalidateQueries({queryKey:[s.trackerStatus]})):r.error(u?decodeURIComponent(u):"AniList authentication failed");return}const k=new URLSearchParams(window.location.hash.substring(1)),l=k.get("access_token"),S=t.get("code");if(!l&&!S){const f=k.get("error");f&&(r.error(`AniList error: ${f}`),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:S,redirectUri:d}).then(async f=>{const u=f.user;r.success(`Connected to AniList as ${u?.name??"AniList user"}`),N.invalidateQueries({queryKey:[s.trackerStatus]})}).catch(f=>{r.error(f instanceof Error?f.message:"Failed to authenticate with AniList")}).finally(()=>{h(!1)})},[N]),x}const rn="_header_yx26o_1",cn="_fadeIn_yx26o_1",on="_pageTitle_yx26o_6",ln="_pageSubtitle_yx26o_14",dn="_importCard_yx26o_20",mn="_slideUpIn_yx26o_1",un="_cardHeader_yx26o_37",pn="_uploadArea_yx26o_55",hn="_fileInputWrapper_yx26o_59",gn="_fileInput_yx26o_59",yn="_fileDisplay_yx26o_87",fn="_fileIcon_yx26o_95",bn="_fileName_yx26o_100",_n="_browseButton_yx26o_109",kn="_optionsArea_yx26o_120",vn="_checkboxLabel_yx26o_128",Nn="_checkbox_yx26o_128",wn="_checkboxCustom_yx26o_141",xn="_optionText_yx26o_169",Cn="_optionTitle_yx26o_175",In="_optionDesc_yx26o_181",Sn="_actions_yx26o_187",Ln="_importBtn_yx26o_195",Mn="_cancelBtn_yx26o_201",Tn="_statusMessage_yx26o_215",An="_success_yx26o_225",Pn="_error_yx26o_231",Bn="_progressSection_yx26o_237",En="_progressBar_yx26o_242",Fn="_progressFill_yx26o_250",Dn="_progressInfo_yx26o_257",qn="_progressCount_yx26o_264",$n="_progressTitle_yx26o_271",Kn="_sourceBadge_yx26o_289",Rn="_anilist_yx26o_301",Un="_kitsu_yx26o_307",Qn="_offline_yx26o_313",On="_skipped_yx26o_319",Hn="_cardTitleRow_yx26o_324",zn="_anilistIcon_yx26o_334",Gn="_malIcon_yx26o_340",Wn="_badgeOnline_yx26o_346",Xn="_badgeOffline_yx26o_358",Yn="_connectedProfile_yx26o_370",Jn="_avatar_yx26o_379",jn="_connectedInfo_yx26o_386",Vn="_connectedName_yx26o_394",Zn="_connectedHint_yx26o_400",ea="_loginPrompt_yx26o_405",na="_loginSection_yx26o_413",aa="_primaryBtn_yx26o_419",ta="_fieldLabel_yx26o_423",sa="_helpText_yx26o_442",ia="_resetBtn_yx26o_449",ra="_loginText_yx26o_479",ca="_secondaryBtn_yx26o_489",oa="_syncBtn_yx26o_490",la="_divider_yx26o_542",da="_actionSection_yx26o_548",ma="_inputGroup_yx26o_562",ua="_credentialFields_yx26o_567",pa="_credentialField_yx26o_567",ha="_input_yx26o_562",ga="_syncSummary_yx26o_603",ya="_syncErrors_yx26o_609",fa="_spin_yx26o_613",ba="_radioGroup_yx26o_642",_a="_radioLabel_yx26o_648",ka="_syncHint_yx26o_686",va="_importLoading_yx26o_693",n={header:rn,fadeIn:cn,pageTitle:on,pageSubtitle:ln,importCard:dn,slideUpIn:mn,cardHeader:un,uploadArea:pn,fileInputWrapper:hn,fileInput:gn,fileDisplay:yn,fileIcon:fn,fileName:bn,browseButton:_n,optionsArea:kn,checkboxLabel:vn,checkbox:Nn,checkboxCustom:wn,optionText:xn,optionTitle:Cn,optionDesc:In,actions:Sn,importBtn:Ln,cancelBtn:Mn,statusMessage:Tn,success:An,error:Pn,progressSection:Bn,progressBar:En,progressFill:Fn,progressInfo:Dn,progressCount:qn,progressTitle:$n,sourceBadge:Kn,anilist:Rn,kitsu:Un,offline:Qn,skipped:On,cardTitleRow:Hn,anilistIcon:zn,malIcon:Gn,badgeOnline:Wn,badgeOffline:Xn,connectedProfile:Yn,avatar:Jn,connectedInfo:jn,connectedName:Vn,connectedHint:Zn,loginPrompt:ea,loginSection:na,primaryBtn:aa,fieldLabel:ta,helpText:sa,resetBtn:ia,loginText:ra,secondaryBtn:ca,syncBtn:oa,divider:la,actionSection:da,inputGroup:ma,credentialFields:ua,credentialField:pa,input:ha,syncSummary:ga,syncErrors:ya,spin:fa,radioGroup:ba,radioLabel:_a,syncHint:ka,importLoading:va},ie="tracker_anilist_client_id",Qe="49887".trim(),re=!!Qe;function Re(){const N=V(),[x,h]=i(""),t=ye(!1),y=sn(),{data:k}=Q({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query()}),{data:l}=Q({queryKey:[s.anilistClientId],queryFn:async()=>(await c.settings.getByKey.query({key:ie})).value||""});j(()=>{t.current||l===void 0||(l&&h(l),t.current=!0)},[l]);const S=I({mutationFn:()=>c.tracker.anilistDisconnect.mutate(),onSuccess:()=>{N.invalidateQueries({queryKey:[s.trackerStatus]}),r.success("Disconnected from AniList")},onError:_=>r.error(_.message)}),d=I({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)}),f=async()=>{const _=x.trim(),o=_||Qe;if(!o){r.error("Enter your AniList client ID first");return}const B=(l||"").trim();try{_?_!==l&&await c.settings.set.mutate({key:ie,value:_}):re&&B&&await c.settings.set.mutate({key:ie,value:""}),N.invalidateQueries({queryKey:[s.anilistClientId]})}catch(L){r.error(L.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=k?.anilist?.user??null;return k?.anilist?.connected&&u?e("div",{className:n.connectedProfile,children:[u.avatar&&e("img",{src:u.avatar,alt:"Avatar",className:n.avatar,loading:"lazy",decoding:"async"}),e("div",{className:n.connectedInfo,children:[e("span",{className:n.connectedName,children:u.name}),e("span",{className:n.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:n.secondaryBtn,onClick:()=>S.mutate(),disabled:S.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}):e("div",{className:n.loginSection,children:[e("p",{className:n.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:n.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:n.inputGroup,children:[e("input",{type:"text",placeholder:"Client ID",value:x,onChange:_=>h(_.currentTarget.value),className:n.input}),e("button",{className:n.primaryBtn,onClick:f,disabled:!(x.trim()||re),children:[e(m,{name:"external-link-alt"})," Connect"]})]}),re&&l&&e("button",{className:n.resetBtn,onClick:()=>d.mutate(),disabled:d.isPending,children:"Use dango's app instead"}),e("p",{className:n.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 Ue({kind:N="anime",active:x=!0}){const h=V(),[t,y]=i(""),[k,l]=i(""),[S,d]=i(""),[f,u]=i(""),_=ye(!1),{data:o}=Q({queryKey:[s.malClientConfig],queryFn:()=>c.tracker.malConfig.query()}),{data:B}=Q({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query(),refetchInterval:15e3});j(()=>{o&&!_.current&&(y(o.clientId),_.current=!0)},[o]);const p=I({mutationFn:async()=>{d(""),(k.trim()||t.trim()&&t.trim()!==o?.clientId)&&await c.tracker.malSaveConfig.mutate({clientId:t.trim(),clientSecret:k.trim()||void 0}),l("");const b=await c.tracker.malLogin.mutate({redirectUri:`${window.location.origin}/api/tracker/mal/callback`});window.location.assign(b.url)},onError:b=>d(b.message)}),L=I({mutationFn:()=>c.tracker.malDisconnect.mutate(),onSuccess:()=>{h.invalidateQueries({queryKey:[s.trackerStatus]}),u(""),d(""),r.success("Disconnected from MyAnimeList")},onError:b=>d(b.message)}),F=I({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:b=>d(b.message)}),$=I({mutationFn:()=>N==="manga"?c.tracker.mangaMalSync.mutate():c.tracker.sync.mutate({provider:"mal"}),onSuccess:b=>{const T=b.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 D of N==="manga"?[[s.trackerStatus],[s.mangaLibrary],[s.mangaContinueReading]]:[[s.trackerStatus],[s.watchlist],[s.continueWatching]])h.invalidateQueries({queryKey:D})},onError:b=>d(b.message)}),M=B?.mal;return e("div",{children:[M?.connected?e(g,{children:[e("div",{className:n.connectedProfile,children:[M.user?.avatar&&e("img",{src:M.user.avatar,alt:"Avatar",className:n.avatar,loading:"lazy",decoding:"async"}),e("div",{className:n.connectedInfo,children:[e("span",{className:n.connectedName,children:M.user?.name||"MyAnimeList user"}),e("span",{className:n.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:n.secondaryBtn,onClick:()=>L.mutate(),disabled:L.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}),x?e(g,{children:[e("button",{className:n.syncBtn,onClick:()=>$.mutate(),disabled:$.isPending,children:[e(m,{name:"sync-alt",className:$.isPending?n.spin:""}),$.isPending?"Syncing...":"Start Sync"]}),f&&e("div",{className:n.syncSummary,children:f})]}):e("p",{className:n.connectedHint,style:{color:"var(--color-warning)"},children:"Not the active tracker - sync disabled."})]}):e("div",{className:n.loginSection,children:[e("p",{className:n.loginText,children:"Log in with MyAnimeList to enable bidirectional progress & status synchronization."}),e("div",{className:n.credentialFields,children:[e("label",{className:`${n.fieldLabel} ${n.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:n.helpText,children:" — defaults to dango's app"})]}),e("input",{className:n.input,placeholder:o?.mode==="worker"?"dango's app (leave empty)":"Client ID",value:t,onChange:b=>y(b.currentTarget.value),autoComplete:"off"})]}),e("label",{className:`${n.fieldLabel} ${n.credentialField}`,children:[e("span",{children:["Client secret"," ",o?.hasSecret&&!k&&e("span",{className:n.helpText,children:"— saved"})]}),e("input",{className:n.input,type:"password",value:k,onChange:b=>l(b.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:n.resetBtn,onClick:()=>F.mutate(),disabled:F.isPending,children:"Use dango's app instead"}),e("p",{className:n.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:n.primaryBtn,onClick:()=>p.mutate(),disabled:!(t.trim()&&k.trim()||o?.clientId&&t.trim()===o.clientId&&o.hasSecret||!t.trim()&&!k.trim()&&o?.mode==="worker")||p.isPending,children:p.isPending?"Connecting...":"Connect to MyAnimeList"})]}),S&&e("p",{className:`${n.helpText} ${n.syncErrors}`,role:"alert",children:S}),e("hr",{className:n.divider}),e("p",{className:n.syncHint,children:"You can also import a public list or XML file without connecting an account:"})]})}const Ia=()=>{const{setIsOpen:N}=nn(),{contentType:x}=an(),h=x==="manga",t=V();en.useEffect(()=>{document.title="Trackers - dango"},[]);const[y,k]=i(""),[l,S]=i("username"),[d,f]=i(null),[u,_]=i(!1);tn();const{data:o,isLoading:B}=Q({queryKey:[s.trackerStatus],queryFn:async()=>await c.tracker.status.query()}),p=o?.anilist?.connected??!1,L=o?.mal?.connected??!1,{data:F}=Q({queryKey:["activeTrackerProvider"],queryFn:async()=>(await c.settings.getByKey.query({key:"active_tracker_provider"}))?.value||""}),$=I({mutationFn:async a=>(await c.settings.set.mutate({key:"active_tracker_provider",value:a}),a),onSuccess:a=>{t.invalidateQueries({queryKey:["activeTrackerProvider"]}),r.success(`Active tracker set to ${a==="mal"?"MyAnimeList":"AniList"}`)},onError:()=>r.error("Failed to update active tracker")}),M=F&&(F==="anilist"&&p||F==="mal"&&L)?F:p&&!L?"anilist":L&&!p?"mal":p?"anilist":"",b=p||L;j(()=>{p&&S("sync")},[p]);const T=I({mutationFn:async()=>(await c.tracker.sync.mutate({provider:"anilist"})).summary,onSuccess:a=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),f(a),r.success(`Sync complete - pushed ${a.pushed}, pulled ${a.pulled}, merged ${a.merged}, unchanged ${a.unchanged}`,{duration:6e3})},onError:a=>r.error(a.message)}),[D,fe]=i(""),[Z,be]=i("sync"),[ce,_e]=i("two-way"),[w,Oe]=i(null),ee=I({mutationFn:async()=>(await c.tracker.mangaSync.mutate({direction:ce})).summary,onSuccess:a=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),Oe(a);const v=(a.warnings?.length??0)>0?`, ${a.warnings.length} warning(s)`:"";r.success(`Manga sync complete - pushed ${a.pushed}, pulled ${a.pulled}, merged ${a.merged}, unchanged ${a.unchanged}${v}`,{duration:6e3})},onError:a=>r.error(a.message)}),K=I({mutationFn:async()=>{if(!D.trim())throw new Error("Please enter a username");return(await c.tracker.mangaImport.mutate({username:D.trim(),erase:u})).count},onSuccess:a=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${a} manga entries from AniList`),fe("")},onError:a=>r.error(a.message)}),[O,ke]=i(""),[ne,ve]=i("username"),[oe,Ne]=i(null),[ae,we]=i(!1),[xe,le]=i(""),[Ce,He]=i(""),E=I({mutationFn:async()=>{if(!O.trim())throw new Error("Please enter a MAL username");const a=await c.tracker.mangaMalImport.mutate({username:O.trim(),erase:u});return{imported:a.imported??0,skipped:a.skipped??0}},onSuccess:({imported:a,skipped:v})=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${a} manga entries from MAL${v>0?`, skipped ${v}`:""}`),ke("")},onError:a=>r.error(a.message)}),ze=$e(async()=>{const a=document.getElementById("malMangaFile");if(!a.files||a.files.length===0){le("Please select a file first.");return}we(!0),le(""),Ne(null);try{const v=new FormData;v.append("xmlfile",a.files[0]),v.append("erase",String(u));const X=await Ke("/api/import/mal-xml-manga",{method:"POST",body:v}),C=await X.json().catch(()=>({}));if(!X.ok)throw new Error(C.error||"Import failed");Ne({imported:C.imported??0,skipped:C.skipped??0}),t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]})}catch(v){le(v.message)}finally{we(!1)}},[u,t]),R=I({mutationFn:async()=>{if(!y.trim())throw new Error("Please enter a username");return(await c.tracker.anilistImport.mutate({username:y.trim(),erase:q})).count},onSuccess:a=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${a} anime entries from AniList`),k("")},onError:a=>r.error(a.message)}),[H,Ie]=i(""),P=I({mutationFn:async a=>{if(!H.trim())throw new Error("Please enter a MAL username");return(await c.tracker.malImport.mutate({username:H.trim(),erase:a.erase,useOfflineDb:a.useOfflineDb,skipFallback:a.skipFallback})).count},onSuccess:a=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${a} anime entries from MAL`),Ie("")},onError:a=>r.error(a.message)}),[q,Se]=i(!1),[z,Ge]=i(!0),[G,We]=i(!1),[Le,Me]=i(""),[U,Te]=i(!1),[A,Ae]=i(null),[de,Pe]=i(null),[Be,te]=i(""),me=ye(null),Xe=a=>{a.currentTarget.files&&a.currentTarget.files.length>0?Me(a.currentTarget.files[0].name):Me("")},Ye=$e(async()=>{const a=document.getElementById("malFile");if(!a.files||a.files.length===0){te("Please select a file first.");return}const v=a.files[0];Te(!0),Ae(null),Pe(null),te("");const X=new AbortController;me.current=X;try{const C=new FormData;C.append("xmlfile",v),C.append("erase",String(q)),C.append("useOfflineDb",String(z)),C.append("skipFallback",String(G));const ue=await Ke("/api/import/mal-xml",{method:"POST",body:C,signal:X.signal});if(!ue.ok){const he=await ue.text();let Y="Failed to import";try{Y=JSON.parse(he).error||Y}catch{}throw new Error(Y)}const Fe=ue.body?.getReader();if(!Fe)throw new Error("No response stream");const Ve=new TextDecoder;let pe="",se="";for(;;){const{done:he,value:Y}=await Fe.read();if(he)break;pe+=Ve.decode(Y,{stream:!0});const De=pe.split(`
|
|
1
|
+
import{h as j,d as i,A as ye,u as e,S as g,g as en,q as $e}from"./vendor-core-DfaOB3Rn.js";import{u as V,b as Q,a as I}from"./vendor-query-BBT5_sHx.js";import{F as r,q as s,t as c,ad as nn,n as an,S as Ke,B as ge}from"./index-DYanm9eZ.js";import{I as m}from"./vendor-icons-DrybRNxP.js";function tn(){const N=V();j(()=>{const x=new URLSearchParams(window.location.search),h=x.get("mal");if(!h)return;const t=x.get("user"),y=x.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 sn(){const N=V(),[x,h]=i(!1);return j(()=>{const t=new URLSearchParams(window.location.search),y=t.get("anilist");if(y){const f=t.get("user"),u=t.get("reason");window.history.replaceState(null,"",window.location.pathname),y==="success"?(r.success(f?`Connected to AniList as ${decodeURIComponent(f)}`:"Connected to AniList"),N.invalidateQueries({queryKey:[s.trackerStatus]})):r.error(u?decodeURIComponent(u):"AniList authentication failed");return}const k=new URLSearchParams(window.location.hash.substring(1)),l=k.get("access_token"),S=t.get("code");if(!l&&!S){const f=k.get("error");f&&(r.error(`AniList error: ${f}`),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:S,redirectUri:d}).then(async f=>{const u=f.user;r.success(`Connected to AniList as ${u?.name??"AniList user"}`),N.invalidateQueries({queryKey:[s.trackerStatus]})}).catch(f=>{r.error(f instanceof Error?f.message:"Failed to authenticate with AniList")}).finally(()=>{h(!1)})},[N]),x}const rn="_header_yx26o_1",cn="_fadeIn_yx26o_1",on="_pageTitle_yx26o_6",ln="_pageSubtitle_yx26o_14",dn="_importCard_yx26o_20",mn="_slideUpIn_yx26o_1",un="_cardHeader_yx26o_37",pn="_uploadArea_yx26o_55",hn="_fileInputWrapper_yx26o_59",gn="_fileInput_yx26o_59",yn="_fileDisplay_yx26o_87",fn="_fileIcon_yx26o_95",bn="_fileName_yx26o_100",_n="_browseButton_yx26o_109",kn="_optionsArea_yx26o_120",vn="_checkboxLabel_yx26o_128",Nn="_checkbox_yx26o_128",wn="_checkboxCustom_yx26o_141",xn="_optionText_yx26o_169",Cn="_optionTitle_yx26o_175",In="_optionDesc_yx26o_181",Sn="_actions_yx26o_187",Ln="_importBtn_yx26o_195",Mn="_cancelBtn_yx26o_201",Tn="_statusMessage_yx26o_215",An="_success_yx26o_225",Pn="_error_yx26o_231",Bn="_progressSection_yx26o_237",En="_progressBar_yx26o_242",Fn="_progressFill_yx26o_250",Dn="_progressInfo_yx26o_257",qn="_progressCount_yx26o_264",$n="_progressTitle_yx26o_271",Kn="_sourceBadge_yx26o_289",Rn="_anilist_yx26o_301",Un="_kitsu_yx26o_307",Qn="_offline_yx26o_313",On="_skipped_yx26o_319",Hn="_cardTitleRow_yx26o_324",zn="_anilistIcon_yx26o_334",Gn="_malIcon_yx26o_340",Wn="_badgeOnline_yx26o_346",Xn="_badgeOffline_yx26o_358",Yn="_connectedProfile_yx26o_370",Jn="_avatar_yx26o_379",jn="_connectedInfo_yx26o_386",Vn="_connectedName_yx26o_394",Zn="_connectedHint_yx26o_400",ea="_loginPrompt_yx26o_405",na="_loginSection_yx26o_413",aa="_primaryBtn_yx26o_419",ta="_fieldLabel_yx26o_423",sa="_helpText_yx26o_442",ia="_resetBtn_yx26o_449",ra="_loginText_yx26o_479",ca="_secondaryBtn_yx26o_489",oa="_syncBtn_yx26o_490",la="_divider_yx26o_542",da="_actionSection_yx26o_548",ma="_inputGroup_yx26o_562",ua="_credentialFields_yx26o_567",pa="_credentialField_yx26o_567",ha="_input_yx26o_562",ga="_syncSummary_yx26o_603",ya="_syncErrors_yx26o_609",fa="_spin_yx26o_613",ba="_radioGroup_yx26o_642",_a="_radioLabel_yx26o_648",ka="_syncHint_yx26o_686",va="_importLoading_yx26o_693",n={header:rn,fadeIn:cn,pageTitle:on,pageSubtitle:ln,importCard:dn,slideUpIn:mn,cardHeader:un,uploadArea:pn,fileInputWrapper:hn,fileInput:gn,fileDisplay:yn,fileIcon:fn,fileName:bn,browseButton:_n,optionsArea:kn,checkboxLabel:vn,checkbox:Nn,checkboxCustom:wn,optionText:xn,optionTitle:Cn,optionDesc:In,actions:Sn,importBtn:Ln,cancelBtn:Mn,statusMessage:Tn,success:An,error:Pn,progressSection:Bn,progressBar:En,progressFill:Fn,progressInfo:Dn,progressCount:qn,progressTitle:$n,sourceBadge:Kn,anilist:Rn,kitsu:Un,offline:Qn,skipped:On,cardTitleRow:Hn,anilistIcon:zn,malIcon:Gn,badgeOnline:Wn,badgeOffline:Xn,connectedProfile:Yn,avatar:Jn,connectedInfo:jn,connectedName:Vn,connectedHint:Zn,loginPrompt:ea,loginSection:na,primaryBtn:aa,fieldLabel:ta,helpText:sa,resetBtn:ia,loginText:ra,secondaryBtn:ca,syncBtn:oa,divider:la,actionSection:da,inputGroup:ma,credentialFields:ua,credentialField:pa,input:ha,syncSummary:ga,syncErrors:ya,spin:fa,radioGroup:ba,radioLabel:_a,syncHint:ka,importLoading:va},ie="tracker_anilist_client_id",Qe="49887".trim(),re=!!Qe;function Re(){const N=V(),[x,h]=i(""),t=ye(!1),y=sn(),{data:k}=Q({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query()}),{data:l}=Q({queryKey:[s.anilistClientId],queryFn:async()=>(await c.settings.getByKey.query({key:ie})).value||""});j(()=>{t.current||l===void 0||(l&&h(l),t.current=!0)},[l]);const S=I({mutationFn:()=>c.tracker.anilistDisconnect.mutate(),onSuccess:()=>{N.invalidateQueries({queryKey:[s.trackerStatus]}),r.success("Disconnected from AniList")},onError:_=>r.error(_.message)}),d=I({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)}),f=async()=>{const _=x.trim(),o=_||Qe;if(!o){r.error("Enter your AniList client ID first");return}const B=(l||"").trim();try{_?_!==l&&await c.settings.set.mutate({key:ie,value:_}):re&&B&&await c.settings.set.mutate({key:ie,value:""}),N.invalidateQueries({queryKey:[s.anilistClientId]})}catch(L){r.error(L.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=k?.anilist?.user??null;return k?.anilist?.connected&&u?e("div",{className:n.connectedProfile,children:[u.avatar&&e("img",{src:u.avatar,alt:"Avatar",className:n.avatar,loading:"lazy",decoding:"async"}),e("div",{className:n.connectedInfo,children:[e("span",{className:n.connectedName,children:u.name}),e("span",{className:n.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:n.secondaryBtn,onClick:()=>S.mutate(),disabled:S.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}):e("div",{className:n.loginSection,children:[e("p",{className:n.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:n.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:n.inputGroup,children:[e("input",{type:"text",placeholder:"Client ID",value:x,onChange:_=>h(_.currentTarget.value),className:n.input}),e("button",{className:n.primaryBtn,onClick:f,disabled:!(x.trim()||re),children:[e(m,{name:"external-link-alt"})," Connect"]})]}),re&&l&&e("button",{className:n.resetBtn,onClick:()=>d.mutate(),disabled:d.isPending,children:"Use dango's app instead"}),e("p",{className:n.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 Ue({kind:N="anime",active:x=!0}){const h=V(),[t,y]=i(""),[k,l]=i(""),[S,d]=i(""),[f,u]=i(""),_=ye(!1),{data:o}=Q({queryKey:[s.malClientConfig],queryFn:()=>c.tracker.malConfig.query()}),{data:B}=Q({queryKey:[s.trackerStatus],queryFn:()=>c.tracker.status.query(),refetchInterval:15e3});j(()=>{o&&!_.current&&(y(o.clientId),_.current=!0)},[o]);const p=I({mutationFn:async()=>{d(""),(k.trim()||t.trim()&&t.trim()!==o?.clientId)&&await c.tracker.malSaveConfig.mutate({clientId:t.trim(),clientSecret:k.trim()||void 0}),l("");const b=await c.tracker.malLogin.mutate({redirectUri:`${window.location.origin}/api/tracker/mal/callback`});window.location.assign(b.url)},onError:b=>d(b.message)}),L=I({mutationFn:()=>c.tracker.malDisconnect.mutate(),onSuccess:()=>{h.invalidateQueries({queryKey:[s.trackerStatus]}),u(""),d(""),r.success("Disconnected from MyAnimeList")},onError:b=>d(b.message)}),F=I({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:b=>d(b.message)}),$=I({mutationFn:()=>N==="manga"?c.tracker.mangaMalSync.mutate():c.tracker.sync.mutate({provider:"mal"}),onSuccess:b=>{const T=b.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 D of N==="manga"?[[s.trackerStatus],[s.mangaLibrary],[s.mangaContinueReading]]:[[s.trackerStatus],[s.watchlist],[s.continueWatching]])h.invalidateQueries({queryKey:D})},onError:b=>d(b.message)}),M=B?.mal;return e("div",{children:[M?.connected?e(g,{children:[e("div",{className:n.connectedProfile,children:[M.user?.avatar&&e("img",{src:M.user.avatar,alt:"Avatar",className:n.avatar,loading:"lazy",decoding:"async"}),e("div",{className:n.connectedInfo,children:[e("span",{className:n.connectedName,children:M.user?.name||"MyAnimeList user"}),e("span",{className:n.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:n.secondaryBtn,onClick:()=>L.mutate(),disabled:L.isPending,children:[e(m,{name:"sign-out-alt"})," Disconnect"]})]}),x?e(g,{children:[e("button",{className:n.syncBtn,onClick:()=>$.mutate(),disabled:$.isPending,children:[e(m,{name:"sync-alt",className:$.isPending?n.spin:""}),$.isPending?"Syncing...":"Start Sync"]}),f&&e("div",{className:n.syncSummary,children:f})]}):e("p",{className:n.connectedHint,style:{color:"var(--color-warning)"},children:"Not the active tracker - sync disabled."})]}):e("div",{className:n.loginSection,children:[e("p",{className:n.loginText,children:"Log in with MyAnimeList to enable bidirectional progress & status synchronization."}),e("div",{className:n.credentialFields,children:[e("label",{className:`${n.fieldLabel} ${n.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:n.helpText,children:" — defaults to dango's app"})]}),e("input",{className:n.input,placeholder:o?.mode==="worker"?"dango's app (leave empty)":"Client ID",value:t,onChange:b=>y(b.currentTarget.value),autoComplete:"off"})]}),e("label",{className:`${n.fieldLabel} ${n.credentialField}`,children:[e("span",{children:["Client secret"," ",o?.hasSecret&&!k&&e("span",{className:n.helpText,children:"— saved"})]}),e("input",{className:n.input,type:"password",value:k,onChange:b=>l(b.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:n.resetBtn,onClick:()=>F.mutate(),disabled:F.isPending,children:"Use dango's app instead"}),e("p",{className:n.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:n.primaryBtn,onClick:()=>p.mutate(),disabled:!(t.trim()&&k.trim()||o?.clientId&&t.trim()===o.clientId&&o.hasSecret||!t.trim()&&!k.trim()&&o?.mode==="worker")||p.isPending,children:p.isPending?"Connecting...":"Connect to MyAnimeList"})]}),S&&e("p",{className:`${n.helpText} ${n.syncErrors}`,role:"alert",children:S}),e("hr",{className:n.divider}),e("p",{className:n.syncHint,children:"You can also import a public list or XML file without connecting an account:"})]})}const Ia=()=>{const{setIsOpen:N}=nn(),{contentType:x}=an(),h=x==="manga",t=V();en.useEffect(()=>{document.title="Trackers - dango"},[]);const[y,k]=i(""),[l,S]=i("username"),[d,f]=i(null),[u,_]=i(!1);tn();const{data:o,isLoading:B}=Q({queryKey:[s.trackerStatus],queryFn:async()=>await c.tracker.status.query()}),p=o?.anilist?.connected??!1,L=o?.mal?.connected??!1,{data:F}=Q({queryKey:["activeTrackerProvider"],queryFn:async()=>(await c.settings.getByKey.query({key:"active_tracker_provider"}))?.value||""}),$=I({mutationFn:async a=>(await c.settings.set.mutate({key:"active_tracker_provider",value:a}),a),onSuccess:a=>{t.invalidateQueries({queryKey:["activeTrackerProvider"]}),r.success(`Active tracker set to ${a==="mal"?"MyAnimeList":"AniList"}`)},onError:()=>r.error("Failed to update active tracker")}),M=F&&(F==="anilist"&&p||F==="mal"&&L)?F:p&&!L?"anilist":L&&!p?"mal":p?"anilist":"",b=p||L;j(()=>{p&&S("sync")},[p]);const T=I({mutationFn:async()=>(await c.tracker.sync.mutate({provider:"anilist"})).summary,onSuccess:a=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),f(a),r.success(`Sync complete - pushed ${a.pushed}, pulled ${a.pulled}, merged ${a.merged}, unchanged ${a.unchanged}`,{duration:6e3})},onError:a=>r.error(a.message)}),[D,fe]=i(""),[Z,be]=i("sync"),[ce,_e]=i("two-way"),[w,Oe]=i(null),ee=I({mutationFn:async()=>(await c.tracker.mangaSync.mutate({direction:ce})).summary,onSuccess:a=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),Oe(a);const v=(a.warnings?.length??0)>0?`, ${a.warnings.length} warning(s)`:"";r.success(`Manga sync complete - pushed ${a.pushed}, pulled ${a.pulled}, merged ${a.merged}, unchanged ${a.unchanged}${v}`,{duration:6e3})},onError:a=>r.error(a.message)}),K=I({mutationFn:async()=>{if(!D.trim())throw new Error("Please enter a username");return(await c.tracker.mangaImport.mutate({username:D.trim(),erase:u})).count},onSuccess:a=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${a} manga entries from AniList`),fe("")},onError:a=>r.error(a.message)}),[O,ke]=i(""),[ne,ve]=i("username"),[oe,Ne]=i(null),[ae,we]=i(!1),[xe,le]=i(""),[Ce,He]=i(""),E=I({mutationFn:async()=>{if(!O.trim())throw new Error("Please enter a MAL username");const a=await c.tracker.mangaMalImport.mutate({username:O.trim(),erase:u});return{imported:a.imported??0,skipped:a.skipped??0}},onSuccess:({imported:a,skipped:v})=>{t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]}),r.success(`Imported ${a} manga entries from MAL${v>0?`, skipped ${v}`:""}`),ke("")},onError:a=>r.error(a.message)}),ze=$e(async()=>{const a=document.getElementById("malMangaFile");if(!a.files||a.files.length===0){le("Please select a file first.");return}we(!0),le(""),Ne(null);try{const v=new FormData;v.append("xmlfile",a.files[0]),v.append("erase",String(u));const X=await Ke("/api/import/mal-xml-manga",{method:"POST",body:v}),C=await X.json().catch(()=>({}));if(!X.ok)throw new Error(C.error||"Import failed");Ne({imported:C.imported??0,skipped:C.skipped??0}),t.invalidateQueries({queryKey:[s.mangaLibrary]}),t.invalidateQueries({queryKey:[s.mangaContinueReading]})}catch(v){le(v.message)}finally{we(!1)}},[u,t]),R=I({mutationFn:async()=>{if(!y.trim())throw new Error("Please enter a username");return(await c.tracker.anilistImport.mutate({username:y.trim(),erase:q})).count},onSuccess:a=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${a} anime entries from AniList`),k("")},onError:a=>r.error(a.message)}),[H,Ie]=i(""),P=I({mutationFn:async a=>{if(!H.trim())throw new Error("Please enter a MAL username");return(await c.tracker.malImport.mutate({username:H.trim(),erase:a.erase,useOfflineDb:a.useOfflineDb,skipFallback:a.skipFallback})).count},onSuccess:a=>{t.invalidateQueries({queryKey:[s.watchlist]}),t.invalidateQueries({queryKey:[s.continueWatching]}),r.success(`Imported ${a} anime entries from MAL`),Ie("")},onError:a=>r.error(a.message)}),[q,Se]=i(!1),[z,Ge]=i(!0),[G,We]=i(!1),[Le,Me]=i(""),[U,Te]=i(!1),[A,Ae]=i(null),[de,Pe]=i(null),[Be,te]=i(""),me=ye(null),Xe=a=>{a.currentTarget.files&&a.currentTarget.files.length>0?Me(a.currentTarget.files[0].name):Me("")},Ye=$e(async()=>{const a=document.getElementById("malFile");if(!a.files||a.files.length===0){te("Please select a file first.");return}const v=a.files[0];Te(!0),Ae(null),Pe(null),te("");const X=new AbortController;me.current=X;try{const C=new FormData;C.append("xmlfile",v),C.append("erase",String(q)),C.append("useOfflineDb",String(z)),C.append("skipFallback",String(G));const ue=await Ke("/api/import/mal-xml",{method:"POST",body:C,signal:X.signal});if(!ue.ok){const he=await ue.text();let Y="Failed to import";try{Y=JSON.parse(he).error||Y}catch{}throw new Error(Y)}const Fe=ue.body?.getReader();if(!Fe)throw new Error("No response stream");const Ve=new TextDecoder;let pe="",se="";for(;;){const{done:he,value:Y}=await Fe.read();if(he)break;pe+=Ve.decode(Y,{stream:!0});const De=pe.split(`
|
|
2
2
|
`);pe=De.pop()||"";for(const J of De)if(J.startsWith("event: "))se=J.slice(7).trim();else if(J.startsWith("data: ")){const Ze=J.slice(6);try{const qe=JSON.parse(Ze);se==="progress"?Ae(qe):se==="complete"&&Pe(qe)}catch{}}else J===""&&(se="")}t.invalidateQueries({queryKey:[s.watchlist]})}catch(C){C instanceof DOMException&&C.name==="AbortError"?te("Import cancelled."):te(C.message)}finally{Te(!1),me.current=null}},[q,z,G,t]),Je=()=>{me.current?.abort(),c.settings.malImportCancel.mutate().catch(()=>{})},je=A?Math.round(A.current/A.total*100):0,[W,Ee]=i("username");return e("div",{className:"page-container",children:[e("div",{className:n.header,children:[e("h1",{className:n.pageTitle,children:"Trackers"}),e("p",{className:n.pageSubtitle,children:"Import & sync your anime watchlists and manga reading lists with tracking services"})]}),e("div",{style:{marginBottom:"16px",padding:"10px 14px",borderRadius:"8px",fontSize:"0.85rem",background:"color-mix(in srgb, var(--color-warning) 8%, transparent)",border:"1px solid color-mix(in srgb, var(--color-warning) 25%, transparent)",color:"var(--text-secondary)"},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."}),b&&e("div",{style:{marginBottom:"16px",padding:"10px 14px",borderRadius:"8px",background:"rgba(255, 255, 255, 0.03)",border:"1px solid var(--glass-border)",display:"flex",alignItems:"center",gap:"12px",fontSize:"0.85rem"},children:[e("label",{htmlFor:"active-tracker-select",style:{fontWeight:600},children:"Active tracker:"}),e("select",{id:"active-tracker-select",value:M,onChange:a=>$.mutate(a.currentTarget.value),style:{padding:"0.4rem 0.6rem",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)",cursor:"pointer"},children:[p&&e("option",{value:"anilist",children:"AniList"}),L&&e("option",{value:"mal",children:"MyAnimeList"})]})]}),!h&&e(g,{children:e("div",{className:n.importCard,children:[e("div",{className:n.cardHeader,children:e("div",{className:n.cardTitleRow,children:[e(m,{name:"anilist",className:n.anilistIcon}),e("h3",{children:"AniList"}),B?null:p?e("span",{className:n.badgeOnline,children:"Connected"}):e("span",{className:n.badgeOffline,children:"Not connected"})]})}),e(Re,{}),p&&M!=="anilist"&&e("p",{style:{color:"var(--color-warning)",marginTop:"8px",fontSize:"0.85rem"},children:"Not the active tracker - sync disabled."}),p&&M==="anilist"&&e(g,{children:[e("hr",{className:n.divider}),e("div",{className:n.radioGroup,children:[e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"anilistMode",value:"username",checked:l==="username",onChange:()=>S("username")}),e("span",{children:"Quick Import"})]}),e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"anilistMode",value:"sync",checked:l==="sync",onChange:()=>S("sync")}),e("span",{children:"Two-way Sync"})]})]}),l==="username"?e("div",{className:n.inputGroup,children:e("input",{type:"text",placeholder:"Enter AniList username",value:y,onChange:a=>k(a.currentTarget.value),className:n.input,disabled:R.isPending,onKeyDown:a=>{a.key==="Enter"&&y.trim()&&R.mutate()}})}):e("p",{className:n.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:n.optionsArea,children:e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:q,onChange:a=>Se(a.currentTarget.checked),className:n.checkbox,disabled:R.isPending}),e("span",{className:n.checkboxCustom}),e("div",{className:n.optionText,children:[e("span",{className:n.optionTitle,children:"Erase current watchlist"}),e("span",{className:n.optionDesc,children:"Delete existing watchlist before importing."})]})]})}),l==="username"?e("button",{className:n.syncBtn,onClick:()=>R.mutate(),disabled:!y.trim()||R.isPending,children:[e(m,{name:"download"}),R.isPending?"Importing...":"Start Import"]}):e(g,{children:[e("button",{className:n.syncBtn,onClick:()=>T.mutate(),disabled:T.isPending,children:[e(m,{name:"sync-alt",className:T.isPending?n.spin:""}),T.isPending?"Syncing...":"Start Sync"]}),d&&e("div",{className:n.syncSummary,children:["Pushed: ",d.pushed," · Pulled: ",d.pulled," · Merged:"," ",d.merged," · Unchanged: ",d.unchanged,d.errors.length>0&&e("span",{className:n.syncErrors,children:[" ","· ",d.errors.length," error",d.errors.length>1?"s":""]})]})]})]})]})}),h&&e(g,{children:e("div",{className:n.importCard,children:[e("div",{className:n.cardHeader,children:e("div",{className:n.cardTitleRow,children:[e(m,{name:"anilist",className:n.anilistIcon}),e("h3",{children:"AniList Manga"}),B?null:p?e("span",{className:n.badgeOnline,children:"Connected"}):e("span",{className:n.badgeOffline,children:"Not connected"})]})}),e(Re,{}),p&&M!=="anilist"&&e("p",{style:{color:"var(--color-warning)",marginTop:"8px",fontSize:"0.85rem"},children:"Not the active tracker - sync disabled."}),p&&M==="anilist"&&e(g,{children:[e("hr",{className:n.divider}),e("div",{className:n.radioGroup,children:[e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"mangaMode",value:"username",checked:Z==="username",onChange:()=>be("username")}),e("span",{children:"Quick Import"})]}),e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"mangaMode",value:"sync",checked:Z==="sync",onChange:()=>be("sync")}),e("span",{children:"Two-way Sync"})]})]}),Z==="username"?e(g,{children:[e("div",{className:n.inputGroup,children:e("input",{type:"text",placeholder:"Enter AniList username",value:D,onChange:a=>fe(a.currentTarget.value),className:n.input,disabled:K.isPending,onKeyDown:a=>{a.key==="Enter"&&D.trim()&&K.mutate()}})}),e("div",{className:n.optionsArea,children:e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:u,onChange:a=>_(a.currentTarget.checked),className:n.checkbox,disabled:K.isPending}),e("span",{className:n.checkboxCustom}),e("div",{className:n.optionText,children:[e("span",{className:n.optionTitle,children:"Replace AniList-linked manga"}),e("span",{className:n.optionDesc,children:"Clears previously imported (anilist:) entries before importing. Your provider bookmarks are never touched."})]})]})})]}):e(g,{children:[e("p",{className:n.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:n.radioGroup,children:[e("label",{className:n.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:n.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:n.syncBtn,onClick:()=>K.mutate(),disabled:!D.trim()||K.isPending,children:[e(m,{name:"download"}),K.isPending?"Importing...":"Start Import"]}):e(g,{children:[e("button",{className:n.syncBtn,onClick:()=>ee.mutate(),disabled:ee.isPending,children:[e(m,{name:"sync-alt",className:ee.isPending?n.spin:""}),ee.isPending?"Syncing...":"Start Manga Sync"]}),w&&e(g,{children:[e("div",{className:n.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:n.syncErrors,children:[" ","· ",w.errors.length," error",w.errors.length>1?"s":""]})]}),(w.warnings?.length??0)>0&&e("div",{className:n.syncErrors,style:{marginTop:"8px"},children:[(w.warnings??[]).slice(0,5).map((a,v)=>e("div",{children:["⚠ ",a]},v)),(w.warnings?.length??0)>5&&e("div",{children:["+",(w.warnings?.length??0)-5," more warning(s)"]})]})]})]})]})]})}),!h&&e(g,{children:e("div",{className:n.importCard,children:[e("div",{className:n.cardHeader,children:e("div",{className:n.cardTitleRow,children:[e(m,{name:"myanimelist",className:n.malIcon}),e("h3",{children:"MyAnimeList"}),B?null:L?e("span",{className:n.badgeOnline,children:"Connected"}):e("span",{className:n.badgeOffline,children:"Not connected"})]})}),e(Ue,{active:M==="mal"}),e("div",{className:n.radioGroup,children:[e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"malMode",value:"username",checked:W==="username",onChange:()=>Ee("username")}),e("span",{children:"Username"})]}),e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"malMode",value:"xml",checked:W==="xml",onChange:()=>Ee("xml")}),e("span",{children:"XML File"})]})]}),W==="username"?e(g,{children:[e("div",{className:n.inputGroup,children:e("input",{type:"text",placeholder:"Enter MAL username",value:H,onChange:a=>Ie(a.currentTarget.value),className:n.input,disabled:P.isPending,onKeyDown:a=>{a.key==="Enter"&&H.trim()&&P.mutate({erase:q,useOfflineDb:z,skipFallback:G})}})}),P.isPending&&e("div",{className:n.importLoading,children:[e(m,{name:"sync-alt",className:n.spin}),e("span",{children:"Importing from MAL..."})]})]}):e("div",{className:n.uploadArea,children:e("div",{className:n.fileInputWrapper,children:[e("input",{type:"file",id:"malFile",accept:".xml,application/xml",className:n.fileInput,onChange:Xe,disabled:U}),e("div",{className:n.fileDisplay,children:[e(m,{name:"file-alt",className:n.fileIcon}),e("span",{className:n.fileName,children:Le||"Choose XML file..."})]}),e("label",{htmlFor:"malFile",className:n.browseButton,children:"Browse"})]})}),e("div",{className:n.optionsArea,children:[e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:q,onChange:a=>Se(a.currentTarget.checked),className:n.checkbox,disabled:U||P.isPending}),e("span",{className:n.checkboxCustom}),e("div",{className:n.optionText,children:[e("span",{className:n.optionTitle,children:"Erase current watchlist"}),e("span",{className:n.optionDesc,children:"Delete existing watchlist before importing."})]})]}),e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:z,onChange:a=>Ge(a.currentTarget.checked),className:n.checkbox,disabled:U||P.isPending}),e("span",{className:n.checkboxCustom}),e("div",{className:n.optionText,children:[e("span",{className:n.optionTitle,children:"Use offline database (fast)"}),e("span",{className:n.optionDesc,children:"Match by MAL ID locally first - instant and avoids AniList rate limits."})]})]}),e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:G,onChange:a=>We(a.currentTarget.checked),className:n.checkbox,disabled:U||P.isPending}),e("span",{className:n.checkboxCustom}),e("div",{className:n.optionText,children:[e("span",{className:n.optionTitle,children:"Skip online fallback"}),e("span",{className:n.optionDesc,children:"Only import offline matches. Unmatched titles are skipped without API calls."})]})]})]}),W==="username"?e("button",{className:n.syncBtn,onClick:()=>P.mutate({erase:q,useOfflineDb:z,skipFallback:G}),disabled:!H.trim()||P.isPending,children:[e(m,{name:"download"}),P.isPending?"Importing...":"Start Import"]}):e("div",{className:n.actions,children:U?e(ge,{onClick:Je,className:n.cancelBtn,children:"Cancel Import"}):e(ge,{onClick:Ye,className:n.importBtn,disabled:!Le,children:[e(m,{name:"upload"})," Start Import"]})}),W==="username"&&P.isError&&e("div",{className:`${n.statusMessage} ${n.error}`,children:P.error.message}),U&&A&&e("div",{className:n.progressSection,children:[e("div",{className:n.progressBar,children:e("div",{className:n.progressFill,style:{width:`${je}%`}})}),e("div",{className:n.progressInfo,children:[e("span",{className:n.progressCount,children:[A.current," / ",A.total]}),e("span",{className:n.progressTitle,children:A.found?e(g,{children:[A.matchedTitle,e("span",{className:`${n.sourceBadge} ${n[A.source||"anilist"]}`,children:A.source==="kitsu"?"Kitsu":A.source==="offline"?"Offline DB":"AniList"})]}):e("span",{className:n.skipped,children:["Skipped: ",A.title]})})]})]}),de&&e("div",{className:`${n.statusMessage} ${n.success}`,children:["Import complete! Imported: ",de.imported,", Skipped: ",de.skipped,"."]}),Be&&e("div",{className:`${n.statusMessage} ${n.error}`,children:Be})]})}),h&&e("div",{className:n.importCard,children:[e("div",{className:n.cardHeader,children:e("div",{className:n.cardTitleRow,children:[e(m,{name:"myanimelist",className:n.malIcon}),e("h3",{children:"MyAnimeList Manga"}),B?null:L?e("span",{className:n.badgeOnline,children:"Connected"}):e("span",{className:n.badgeOffline,children:"Not connected"})]})}),e(Ue,{kind:"manga",active:M==="mal"}),e("div",{className:n.radioGroup,children:[e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"malMangaMode",value:"username",checked:ne==="username",onChange:()=>ve("username")}),e("span",{children:"Username"})]}),e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"malMangaMode",value:"xml",checked:ne==="xml",onChange:()=>ve("xml")}),e("span",{children:"XML File"})]})]}),ne==="username"?e("div",{className:n.inputGroup,children:e("input",{type:"text",placeholder:"Enter MAL username",value:O,onChange:a=>ke(a.currentTarget.value),className:n.input,disabled:E.isPending,onKeyDown:a=>{a.key==="Enter"&&O.trim()&&E.mutate()}})}):e("div",{className:n.uploadArea,children:e("div",{className:n.fileInputWrapper,children:[e("input",{type:"file",id:"malMangaFile",accept:".xml,application/xml",className:n.fileInput,onChange:a=>He(a.currentTarget.files?.[0]?.name??""),disabled:ae}),e("div",{className:n.fileDisplay,children:[e(m,{name:"file-alt",className:n.fileIcon}),e("span",{className:n.fileName,children:Ce||"Choose XML file..."})]}),e("label",{htmlFor:"malMangaFile",className:n.browseButton,children:"Browse"})]})}),e("div",{className:n.optionsArea,children:e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:u,onChange:a=>_(a.currentTarget.checked),className:n.checkbox,disabled:E.isPending||ae}),e("span",{className:n.checkboxCustom}),e("div",{className:n.optionText,children:[e("span",{className:n.optionTitle,children:"Replace AniList-linked manga"}),e("span",{className:n.optionDesc,children:"Clears previously imported (anilist:) entries before importing. Your provider bookmarks are never touched."})]})]})}),ne==="username"?e("button",{className:n.syncBtn,onClick:()=>E.mutate(),disabled:!O.trim()||E.isPending,children:[e(m,{name:"download"}),E.isPending?"Importing...":"Start Import"]}):e("div",{className:n.actions,children:e(ge,{onClick:ze,className:n.importBtn,disabled:ae||!Ce,children:[e(m,{name:"upload"})," ",ae?"Importing...":"Start Import"]})}),E.isError&&e("div",{className:`${n.statusMessage} ${n.error}`,children:E.error.message}),xe&&e("div",{className:`${n.statusMessage} ${n.error}`,children:xe}),oe&&e("div",{className:`${n.statusMessage} ${n.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{Ia as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{u as t,d as _,A as V,h as g,S as Ge,g as Jr,q as N,o as es,p as ts,a as ns,T as ye}from"./vendor-core-DfaOB3Rn.js";import{g as On,p as O,t as mt,a6 as rs,a2 as ss,O as Rn,e as os,a9 as as,F as cr,B as sn}from"./index-DbRDs7tF.js";import{P as is,a as ls,b as cs,F as us,c as ds}from"./PlayerProvider--aaVRFly.js";import{u as ms}from"./vendor-query-BBT5_sHx.js";import{I as be}from"./vendor-icons-DrybRNxP.js";import{p as Vn,M as bs,z as br,f as Fn,c as hs,C as fs,P as ps,a as vs,b as on,u as gs,i as ys,j as Ss,n as _s,h as Ts,k as Cs,m as ks,l as Es,s as zn,d as Ns,e as Is,g as As,r as xs,o as Le,A as Ls,t as ws,E as Bs,w as Ps,x as Ms,v as le,y as Rs,R as zs,q as $s}from"./useWatchAlongPlayer-Do0c9QsI.js";import{S as Ds,O as $n,a as Os,A as Vs,b as Fs}from"./OptionListMenu-Cwb6MHoZ.js";import{M as qs}from"./MatureConsentModal-DiWSp3Of.js";import{u as Us}from"./useProviders-Bnw0sBAP.js";import{e as Hs,f as Ws,g as Ks,d as Ys,c as js,h as Gs,i as Qs}from"./useTvLibrary-DTWM3iOC.js";import{l as Xs,s as Zs,i as an,h as ur}from"./playbackCompletion-CnxK6_Vz.js";import{u as Js}from"./useIsMobile-Dvx1uJ82.js";import{S as eo}from"./SynopsisText-B3Sa5pRv.js";import{W as to}from"./WatchAlongPanel-DxC7pX1I.js";import"./libraryInvalidation-cJ1WjrJq.js";const no="_fullscreenFlat_10bzs_1",ro="_timeDisplay_10bzs_12",so="_bottomControls_10bzs_16",oo="_leftControls_10bzs_20",ao="_rightControls_10bzs_21",io="_controlBtn_10bzs_25",lo="_controlsOverlay_10bzs_32",co="_hidden_10bzs_52",uo="_topControls_10bzs_58",mo="_backBtn_10bzs_78",bo="_videoTitleInfo_10bzs_98",ho="_animeTitle_10bzs_104",fo="_episodeLabel_10bzs_112",po="_speedBoostBadge_10bzs_119",vo="_progressBarContainer_10bzs_165",go="_progressBar_10bzs_165",yo="_thumb_10bzs_184",So="_bufferedBar_10bzs_202",_o="_watchedBar_10bzs_212",To="_scrubbing_10bzs_237",Co="_timeBubble_10bzs_241",ko="_bottomControlsRow_10bzs_255",Eo="_nextEpisodeBtn_10bzs_278",No="_active_10bzs_340",Io="_settingsPanel_10bzs_352",Ao="_settingsHeader_10bzs_371",xo="_settingsBackBtn_10bzs_379",Lo="_settingsTitle_10bzs_397",wo="_settingsContent_10bzs_408",Bo="_currentValue_10bzs_417",Po="_menuItem_10bzs_423",Mo="_menuNote_10bzs_456",Ro="_loadingOverlay_10bzs_465",zo="_loadingDots_10bzs_476",$o="_dot_10bzs_481",Do="_bufferingOverlay_10bzs_510",Oo="_bufferingSpinner_10bzs_519",o={fullscreenFlat:no,timeDisplay:ro,bottomControls:so,leftControls:oo,rightControls:ao,controlBtn:io,controlsOverlay:lo,hidden:co,topControls:uo,backBtn:mo,videoTitleInfo:bo,animeTitle:ho,episodeLabel:fo,speedBoostBadge:po,progressBarContainer:vo,progressBar:go,thumb:yo,bufferedBar:So,watchedBar:_o,scrubbing:To,timeBubble:Co,bottomControlsRow:ko,nextEpisodeBtn:Eo,active:No,settingsPanel:Io,settingsHeader:Ao,settingsBackBtn:xo,settingsTitle:Lo,settingsContent:wo,currentValue:Bo,menuItem:Po,menuNote:Mo,loadingOverlay:Ro,loadingDots:zo,dot:$o,bufferingOverlay:Do,bufferingSpinner:Oo},Vo=({player:s,visible:h,settingsOpen:z,onOpenSettings:L,onCloseSettings:M,hasSubtitles:I,isSubtitleActive:T,subtitles:c,onSubtitleChange:i,showNextEpisodeButton:C,onNextEpisode:r,isTheaterMode:w,onTheaterModeToggle:he,timeLabelRef:ee})=>{const{state:u,actions:Ce}=s,we=()=>{if(T){i(-1);return}let fe=null;try{fe=O.getItem("tvLastSubtitle")}catch{}i(Vn(c,{lastKey:fe,enabled:!0}))};return t("div",{className:`${o.controlsOverlay} ${h?"":o.hidden}`,"data-speed-boost-ignore":"true",style:{pointerEvents:"none",background:"none",justifyContent:"flex-end"},children:t("div",{className:o.bottomControls,onClick:fe=>fe.stopPropagation(),children:[t(is,{classes:{container:o.progressBarContainer,scrubbing:o.scrubbing,timeBubble:o.timeBubble,bar:o.progressBar,buffered:o.bufferedBar,watched:o.watchedBar,thumb:o.thumb},timeLabelRef:ee}),t("div",{className:o.bottomControlsRow,children:[t("div",{className:o.leftControls,children:[t(ls,{className:o.controlBtn}),t(cs,{buttonClassName:o.controlBtn,onExpandedChange:Ce.setShowVolumeSlider}),t("span",{className:o.timeDisplay,ref:ee,children:[On(0)," / ",On(u.duration)]})]}),t("div",{className:o.rightControls,children:[C&&t("button",{className:o.nextEpisodeBtn,onClick:r,title:"Play next episode",children:"Next EP"}),I&&t("button",{className:`${o.controlBtn} ${T?o.active:""}`,onClick:we,"aria-label":T?"Turn subtitles off":"Turn subtitles on",children:t(be,{name:"closed-captioning"})}),t("button",{className:`${o.controlBtn} ${z?o.active:""}`,onClick:()=>z?M():L(),"aria-label":"Settings",children:t(be,{name:"cog"})}),t("button",{className:`${o.controlBtn} ${w?o.active:""}`,onClick:fe=>{fe.stopPropagation(),he()},title:w?"Exit Theater Mode":"Theater Mode","aria-label":w?"Exit Theater Mode":"Theater Mode",children:t(be,{name:"tv"})}),t(us,{className:o.controlBtn})]})]})]})})},ln=-6e4,Dn=6e4,dr=500,Fo=({classes:s,delayMs:h,onDelayChange:z})=>{const[L,M]=_(null),I=L??h,T=V(z);T.current=z;const c=V(h);c.current=h;const i=V(null);i.current=L,g(()=>{M(null)},[h]),g(()=>()=>{const w=i.current;w!==null&&w!==c.current&&T.current(w)},[]);const C=w=>{c.current=w,i.current=null,T.current(w),M(null)},r=w=>{const he=i.current??c.current,ee=Math.max(ln,Math.min(Dn,he+w));C(ee)};return t(Ge,{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:I===0,"aria-label":"Reset subtitle timing",style:{flex:1,justifyContent:"center"},children:t("span",{children:"Reset"})})]}),t(bs,{label:"Subtitle timing",display:br(I),min:ln,max:Dn,step:100,value:I,percent:(I-ln)/(Dn-ln)*100,onChange:w=>{const he=Math.round(w);i.current=he,M(he)},onCommit:()=>{const w=i.current;w!==null&&C(w)}}),t("div",{className:s.note,children:"Positive delays subtitles (show later). Negative shows them earlier. 0.0s is default."})]})},qo=({view:s,onSelectView:h,onClose:z,player:L,onSubtitleStyleChange:M,streams:I,resolutionIdx:T,onResolutionChange:c,hasSubtitles:i,subtitles:C,selectedSubtitle:r,isSubtitleActive:w,onSubtitleChange:he,audioTracks:ee,selectedAudioTrack:u,onAudioTrackChange:Ce,videoDelayEnabled:we,onVideoDelayToggle:fe,videoDelayMs:pe,onVideoDelayChange:k,onCalibrate:bt,subtitleDelayMs:Qe,onSubtitleDelayChange:A,ambientSettings:$,onAmbientChange:ce})=>{const{state:X}=L,Xe=()=>t(Ge,{children:[I.length>1&&t("button",{className:o.menuItem,onClick:()=>h("resolution"),children:[t("span",{children:"Resolution"}),t("span",{className:o.currentValue,children:I[T]?.quality||"Auto"})]}),i&&t("button",{className:o.menuItem,onClick:()=>h("subtitles"),children:[t("span",{children:"Subtitles"}),t("span",{className:o.currentValue,children:w?C[r]?.label||C[r]?.language:"Off"})]}),i&&t("button",{className:o.menuItem,onClick:()=>h("subtitle-style"),children:[t("span",{children:"Subtitle Style"}),t("span",{className:o.currentValue,children:[X.subtitleFontSize.toFixed(1),"x · ",X.subtitlePosition]})]}),i&&t("button",{className:o.menuItem,onClick:()=>h("subtitle-timing"),children:[t("span",{children:"Subtitle Timing"}),t("span",{className:o.currentValue,children:br(Qe)})]}),ee.length>0&&t("button",{className:o.menuItem,onClick:()=>h("audio"),children:[t("span",{children:"Audio Track"}),t("span",{className:o.currentValue,children:ee[u]?.label||ee[u]?.language})]}),t("button",{className:o.menuItem,onClick:()=>h("av-sync"),children:[t("span",{children:"A/V Sync"}),t("span",{className:o.currentValue,children:we?`${pe}ms`:"Off"})]}),$&&ce&&t("button",{className:o.menuItem,onClick:()=>h("ambient"),children:[t("span",{children:"Ambient Light"}),t("span",{className:o.currentValue,children:$.enabled?"On":"Off"})]})]}),rt=()=>t($n,{classes:{item:o.menuItem,active:o.active},options:I.map((v,K)=>({key:String(K),label:v.quality,selected:K===T})),onSelect:v=>c(Number(v))}),ie=()=>t($n,{classes:{item:o.menuItem,active:o.active},options:[{key:"off",label:"Off",selected:!w},...C.map((v,K)=>({key:String(K),label:v.label||v.language,selected:K===r}))],onSelect:v=>he(v==="off"?-1:Number(v))}),ht=()=>t(Os,{classes:{item:o.menuItem,active:o.active},values:{fontSize:X.subtitleFontSize,position:X.subtitlePosition,bgOpacity:X.subtitleBgOpacity,bgColor:X.subtitleBgColor,textColor:X.subtitleTextColor,edge:X.subtitleEdge,bold:X.subtitleBold},onChange:M}),Ze=()=>t(Fo,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},delayMs:Qe,onDelayChange:v=>A?.(v)}),W=()=>t($n,{classes:{item:o.menuItem,active:o.active},options:ee.map((v,K)=>({key:String(K),label:v.label||v.language,selected:K===u})),onSelect:v=>Ce(Number(v))}),De=()=>t(Vs,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},enabled:we,delayMs:pe,onToggle:v=>fe?.(v),onDelayChange:v=>k?.(v),onCalibrate:bt}),Oe=()=>$&&ce?t(Fs,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},values:$,onChange:ce}):null;return t("div",{"data-speed-boost-ignore":"true",onClick:v=>v.stopPropagation(),children:t(Ds,{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():h("main"),children:[s==="main"&&Xe(),s==="resolution"&&rt(),s==="subtitles"&&ie(),s==="subtitle-style"&&ht(),s==="subtitle-timing"&&Ze(),s==="audio"&&W(),s==="av-sync"&&De(),s==="ambient"&&Oe()]})})},Uo=({player:s,title:h,episodeLabel:z,audioTracks:L,selectedAudioTrack:M,onAudioTrackChange:I,subtitles:T,selectedSubtitle:c,onSubtitleChange:i,streams:C,resolutionIdx:r,onResolutionChange:w,onBack:he,children:ee,videoDelayEnabled:u=!1,onVideoDelayToggle:Ce,videoDelayMs:we=0,onVideoDelayChange:fe,onCalibrateAvSync:pe,subtitleDelayMs:k=0,onSubtitleDelayChange:bt,showNextEpisodeButton:Qe=!1,onNextEpisode:A,isLoading:$=!1,isTheaterMode:ce,onTheaterModeToggle:X,ambientSettings:Xe,onAmbientChange:rt})=>{const{state:ie,refs:ht,actions:Ze}=s,W=ht.videoRef,{subtitleFontSize:De,subtitlePosition:Oe,subtitleBgOpacity:v,subtitleBgColor:K,subtitleTextColor:Be,subtitleEdge:se,subtitleBold:ft}=ie,[Ve,Se]=_(null),pt=V(null),[_e,vt]=_(0);g(()=>{const Ee=W.current;if(!Ee)return;const y=()=>vt(Ee.clientHeight||0);y();const qe=new ResizeObserver(y);return qe.observe(Ee),()=>qe.disconnect()},[W]);const ue=Ze.setSubtitleStyle;g(()=>{const Ee="tv-player-subtitle-style";let y=document.getElementById(Ee);y||(y=document.createElement("style"),y.id=Ee,document.head.appendChild(y));const qe={fontSize:De,position:Oe,bgOpacity:v,bgColor:K,textColor:Be,edge:se,bold:ft},te=W.current,Ne=Fn(De,_e||te?.clientHeight||720);if(y.textContent=hs({...qe,fontSize:Ne}),te){const St=()=>{const B=Number(Oe);return isNaN(B)?0:Math.max(0,Math.min(100,B))},_t=(B,Z)=>{try{const ne=B;ne.snapToLines=!1,ne.line=Z}catch{}},Tt=()=>{const B=Ne*16,Z=te.videoHeight||te.clientHeight||720,ne=te.videoWidth||te.clientWidth||1280;return{step:B*1.3/Z*100,chars:Math.max(20,Math.floor(ne/(B*.55)))}},Ct=B=>{const Z=Math.max(0,Math.min(100,100-St())),ne=Array.from(B.activeCues??[]);if(ne.length<=1){ne.forEach(j=>_t(j,Z));return}const{step:b,chars:d}=Tt();let de=Z;for(let j=ne.length-1;j>=0;j--){const $t=String(ne[j].text??"").replace(/<[^>]*>/g,"").split(`
|
|
1
|
+
import{u as t,d as _,A as V,h as g,S as Ge,g as Jr,q as N,o as es,p as ts,a as ns,T as ye}from"./vendor-core-DfaOB3Rn.js";import{g as On,p as O,t as mt,a6 as rs,a2 as ss,O as Rn,e as os,a9 as as,F as cr,B as sn}from"./index-DYanm9eZ.js";import{P as is,a as ls,b as cs,F as us,c as ds}from"./PlayerProvider-BXBzQc8G.js";import{u as ms}from"./vendor-query-BBT5_sHx.js";import{I as be}from"./vendor-icons-DrybRNxP.js";import{p as Vn,M as bs,z as br,f as Fn,c as hs,C as fs,P as ps,a as vs,b as on,u as gs,i as ys,j as Ss,n as _s,h as Ts,k as Cs,m as ks,l as Es,s as zn,d as Ns,e as Is,g as As,r as xs,o as Le,A as Ls,t as ws,E as Bs,w as Ps,x as Ms,v as le,y as Rs,R as zs,q as $s}from"./useWatchAlongPlayer-3HXJvQR2.js";import{S as Ds,O as $n,a as Os,A as Vs,b as Fs}from"./OptionListMenu-CHJb3qot.js";import{M as qs}from"./MatureConsentModal-LTZSG_Kx.js";import{u as Us}from"./useProviders-D9QoFCnY.js";import{e as Hs,f as Ws,g as Ks,d as Ys,c as js,h as Gs,i as Qs}from"./useTvLibrary-TnVQ2e21.js";import{l as Xs,s as Zs,i as an,h as ur}from"./playbackCompletion-CxGa4g7a.js";import{u as Js}from"./useIsMobile-Dvx1uJ82.js";import{S as eo}from"./SynopsisText-B3Sa5pRv.js";import{W as to}from"./WatchAlongPanel-R7Nd5MXr.js";import"./libraryInvalidation-DlwONLN-.js";const no="_fullscreenFlat_10bzs_1",ro="_timeDisplay_10bzs_12",so="_bottomControls_10bzs_16",oo="_leftControls_10bzs_20",ao="_rightControls_10bzs_21",io="_controlBtn_10bzs_25",lo="_controlsOverlay_10bzs_32",co="_hidden_10bzs_52",uo="_topControls_10bzs_58",mo="_backBtn_10bzs_78",bo="_videoTitleInfo_10bzs_98",ho="_animeTitle_10bzs_104",fo="_episodeLabel_10bzs_112",po="_speedBoostBadge_10bzs_119",vo="_progressBarContainer_10bzs_165",go="_progressBar_10bzs_165",yo="_thumb_10bzs_184",So="_bufferedBar_10bzs_202",_o="_watchedBar_10bzs_212",To="_scrubbing_10bzs_237",Co="_timeBubble_10bzs_241",ko="_bottomControlsRow_10bzs_255",Eo="_nextEpisodeBtn_10bzs_278",No="_active_10bzs_340",Io="_settingsPanel_10bzs_352",Ao="_settingsHeader_10bzs_371",xo="_settingsBackBtn_10bzs_379",Lo="_settingsTitle_10bzs_397",wo="_settingsContent_10bzs_408",Bo="_currentValue_10bzs_417",Po="_menuItem_10bzs_423",Mo="_menuNote_10bzs_456",Ro="_loadingOverlay_10bzs_465",zo="_loadingDots_10bzs_476",$o="_dot_10bzs_481",Do="_bufferingOverlay_10bzs_510",Oo="_bufferingSpinner_10bzs_519",o={fullscreenFlat:no,timeDisplay:ro,bottomControls:so,leftControls:oo,rightControls:ao,controlBtn:io,controlsOverlay:lo,hidden:co,topControls:uo,backBtn:mo,videoTitleInfo:bo,animeTitle:ho,episodeLabel:fo,speedBoostBadge:po,progressBarContainer:vo,progressBar:go,thumb:yo,bufferedBar:So,watchedBar:_o,scrubbing:To,timeBubble:Co,bottomControlsRow:ko,nextEpisodeBtn:Eo,active:No,settingsPanel:Io,settingsHeader:Ao,settingsBackBtn:xo,settingsTitle:Lo,settingsContent:wo,currentValue:Bo,menuItem:Po,menuNote:Mo,loadingOverlay:Ro,loadingDots:zo,dot:$o,bufferingOverlay:Do,bufferingSpinner:Oo},Vo=({player:s,visible:h,settingsOpen:z,onOpenSettings:L,onCloseSettings:M,hasSubtitles:I,isSubtitleActive:T,subtitles:c,onSubtitleChange:i,showNextEpisodeButton:C,onNextEpisode:r,isTheaterMode:w,onTheaterModeToggle:he,timeLabelRef:ee})=>{const{state:u,actions:Ce}=s,we=()=>{if(T){i(-1);return}let fe=null;try{fe=O.getItem("tvLastSubtitle")}catch{}i(Vn(c,{lastKey:fe,enabled:!0}))};return t("div",{className:`${o.controlsOverlay} ${h?"":o.hidden}`,"data-speed-boost-ignore":"true",style:{pointerEvents:"none",background:"none",justifyContent:"flex-end"},children:t("div",{className:o.bottomControls,onClick:fe=>fe.stopPropagation(),children:[t(is,{classes:{container:o.progressBarContainer,scrubbing:o.scrubbing,timeBubble:o.timeBubble,bar:o.progressBar,buffered:o.bufferedBar,watched:o.watchedBar,thumb:o.thumb},timeLabelRef:ee}),t("div",{className:o.bottomControlsRow,children:[t("div",{className:o.leftControls,children:[t(ls,{className:o.controlBtn}),t(cs,{buttonClassName:o.controlBtn,onExpandedChange:Ce.setShowVolumeSlider}),t("span",{className:o.timeDisplay,ref:ee,children:[On(0)," / ",On(u.duration)]})]}),t("div",{className:o.rightControls,children:[C&&t("button",{className:o.nextEpisodeBtn,onClick:r,title:"Play next episode",children:"Next EP"}),I&&t("button",{className:`${o.controlBtn} ${T?o.active:""}`,onClick:we,"aria-label":T?"Turn subtitles off":"Turn subtitles on",children:t(be,{name:"closed-captioning"})}),t("button",{className:`${o.controlBtn} ${z?o.active:""}`,onClick:()=>z?M():L(),"aria-label":"Settings",children:t(be,{name:"cog"})}),t("button",{className:`${o.controlBtn} ${w?o.active:""}`,onClick:fe=>{fe.stopPropagation(),he()},title:w?"Exit Theater Mode":"Theater Mode","aria-label":w?"Exit Theater Mode":"Theater Mode",children:t(be,{name:"tv"})}),t(us,{className:o.controlBtn})]})]})]})})},ln=-6e4,Dn=6e4,dr=500,Fo=({classes:s,delayMs:h,onDelayChange:z})=>{const[L,M]=_(null),I=L??h,T=V(z);T.current=z;const c=V(h);c.current=h;const i=V(null);i.current=L,g(()=>{M(null)},[h]),g(()=>()=>{const w=i.current;w!==null&&w!==c.current&&T.current(w)},[]);const C=w=>{c.current=w,i.current=null,T.current(w),M(null)},r=w=>{const he=i.current??c.current,ee=Math.max(ln,Math.min(Dn,he+w));C(ee)};return t(Ge,{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:I===0,"aria-label":"Reset subtitle timing",style:{flex:1,justifyContent:"center"},children:t("span",{children:"Reset"})})]}),t(bs,{label:"Subtitle timing",display:br(I),min:ln,max:Dn,step:100,value:I,percent:(I-ln)/(Dn-ln)*100,onChange:w=>{const he=Math.round(w);i.current=he,M(he)},onCommit:()=>{const w=i.current;w!==null&&C(w)}}),t("div",{className:s.note,children:"Positive delays subtitles (show later). Negative shows them earlier. 0.0s is default."})]})},qo=({view:s,onSelectView:h,onClose:z,player:L,onSubtitleStyleChange:M,streams:I,resolutionIdx:T,onResolutionChange:c,hasSubtitles:i,subtitles:C,selectedSubtitle:r,isSubtitleActive:w,onSubtitleChange:he,audioTracks:ee,selectedAudioTrack:u,onAudioTrackChange:Ce,videoDelayEnabled:we,onVideoDelayToggle:fe,videoDelayMs:pe,onVideoDelayChange:k,onCalibrate:bt,subtitleDelayMs:Qe,onSubtitleDelayChange:A,ambientSettings:$,onAmbientChange:ce})=>{const{state:X}=L,Xe=()=>t(Ge,{children:[I.length>1&&t("button",{className:o.menuItem,onClick:()=>h("resolution"),children:[t("span",{children:"Resolution"}),t("span",{className:o.currentValue,children:I[T]?.quality||"Auto"})]}),i&&t("button",{className:o.menuItem,onClick:()=>h("subtitles"),children:[t("span",{children:"Subtitles"}),t("span",{className:o.currentValue,children:w?C[r]?.label||C[r]?.language:"Off"})]}),i&&t("button",{className:o.menuItem,onClick:()=>h("subtitle-style"),children:[t("span",{children:"Subtitle Style"}),t("span",{className:o.currentValue,children:[X.subtitleFontSize.toFixed(1),"x · ",X.subtitlePosition]})]}),i&&t("button",{className:o.menuItem,onClick:()=>h("subtitle-timing"),children:[t("span",{children:"Subtitle Timing"}),t("span",{className:o.currentValue,children:br(Qe)})]}),ee.length>0&&t("button",{className:o.menuItem,onClick:()=>h("audio"),children:[t("span",{children:"Audio Track"}),t("span",{className:o.currentValue,children:ee[u]?.label||ee[u]?.language})]}),t("button",{className:o.menuItem,onClick:()=>h("av-sync"),children:[t("span",{children:"A/V Sync"}),t("span",{className:o.currentValue,children:we?`${pe}ms`:"Off"})]}),$&&ce&&t("button",{className:o.menuItem,onClick:()=>h("ambient"),children:[t("span",{children:"Ambient Light"}),t("span",{className:o.currentValue,children:$.enabled?"On":"Off"})]})]}),rt=()=>t($n,{classes:{item:o.menuItem,active:o.active},options:I.map((v,K)=>({key:String(K),label:v.quality,selected:K===T})),onSelect:v=>c(Number(v))}),ie=()=>t($n,{classes:{item:o.menuItem,active:o.active},options:[{key:"off",label:"Off",selected:!w},...C.map((v,K)=>({key:String(K),label:v.label||v.language,selected:K===r}))],onSelect:v=>he(v==="off"?-1:Number(v))}),ht=()=>t(Os,{classes:{item:o.menuItem,active:o.active},values:{fontSize:X.subtitleFontSize,position:X.subtitlePosition,bgOpacity:X.subtitleBgOpacity,bgColor:X.subtitleBgColor,textColor:X.subtitleTextColor,edge:X.subtitleEdge,bold:X.subtitleBold},onChange:M}),Ze=()=>t(Fo,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},delayMs:Qe,onDelayChange:v=>A?.(v)}),W=()=>t($n,{classes:{item:o.menuItem,active:o.active},options:ee.map((v,K)=>({key:String(K),label:v.label||v.language,selected:K===u})),onSelect:v=>Ce(Number(v))}),De=()=>t(Vs,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},enabled:we,delayMs:pe,onToggle:v=>fe?.(v),onDelayChange:v=>k?.(v),onCalibrate:bt}),Oe=()=>$&&ce?t(Fs,{classes:{item:o.menuItem,active:o.active,note:o.menuNote},values:$,onChange:ce}):null;return t("div",{"data-speed-boost-ignore":"true",onClick:v=>v.stopPropagation(),children:t(Ds,{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():h("main"),children:[s==="main"&&Xe(),s==="resolution"&&rt(),s==="subtitles"&&ie(),s==="subtitle-style"&&ht(),s==="subtitle-timing"&&Ze(),s==="audio"&&W(),s==="av-sync"&&De(),s==="ambient"&&Oe()]})})},Uo=({player:s,title:h,episodeLabel:z,audioTracks:L,selectedAudioTrack:M,onAudioTrackChange:I,subtitles:T,selectedSubtitle:c,onSubtitleChange:i,streams:C,resolutionIdx:r,onResolutionChange:w,onBack:he,children:ee,videoDelayEnabled:u=!1,onVideoDelayToggle:Ce,videoDelayMs:we=0,onVideoDelayChange:fe,onCalibrateAvSync:pe,subtitleDelayMs:k=0,onSubtitleDelayChange:bt,showNextEpisodeButton:Qe=!1,onNextEpisode:A,isLoading:$=!1,isTheaterMode:ce,onTheaterModeToggle:X,ambientSettings:Xe,onAmbientChange:rt})=>{const{state:ie,refs:ht,actions:Ze}=s,W=ht.videoRef,{subtitleFontSize:De,subtitlePosition:Oe,subtitleBgOpacity:v,subtitleBgColor:K,subtitleTextColor:Be,subtitleEdge:se,subtitleBold:ft}=ie,[Ve,Se]=_(null),pt=V(null),[_e,vt]=_(0);g(()=>{const Ee=W.current;if(!Ee)return;const y=()=>vt(Ee.clientHeight||0);y();const qe=new ResizeObserver(y);return qe.observe(Ee),()=>qe.disconnect()},[W]);const ue=Ze.setSubtitleStyle;g(()=>{const Ee="tv-player-subtitle-style";let y=document.getElementById(Ee);y||(y=document.createElement("style"),y.id=Ee,document.head.appendChild(y));const qe={fontSize:De,position:Oe,bgOpacity:v,bgColor:K,textColor:Be,edge:se,bold:ft},te=W.current,Ne=Fn(De,_e||te?.clientHeight||720);if(y.textContent=hs({...qe,fontSize:Ne}),te){const St=()=>{const B=Number(Oe);return isNaN(B)?0:Math.max(0,Math.min(100,B))},_t=(B,Z)=>{try{const ne=B;ne.snapToLines=!1,ne.line=Z}catch{}},Tt=()=>{const B=Ne*16,Z=te.videoHeight||te.clientHeight||720,ne=te.videoWidth||te.clientWidth||1280;return{step:B*1.3/Z*100,chars:Math.max(20,Math.floor(ne/(B*.55)))}},Ct=B=>{const Z=Math.max(0,Math.min(100,100-St())),ne=Array.from(B.activeCues??[]);if(ne.length<=1){ne.forEach(j=>_t(j,Z));return}const{step:b,chars:d}=Tt();let de=Z;for(let j=ne.length-1;j>=0;j--){const $t=String(ne[j].text??"").replace(/<[^>]*>/g,"").split(`
|
|
2
2
|
`).reduce((Nt,dn)=>Nt+Math.max(1,Math.ceil(dn.length/d)),0),Et=de-$t*b;_t(ne[j],Math.max(0,Et)),de=Et-b*.4}},et=()=>{const B=Math.max(0,Math.min(100,100-St()));Array.from(te.textTracks).forEach(Z=>{Z.cues&&(Array.from(Z.cues).forEach(ne=>_t(ne,B)),Z.mode==="showing"&&Ct(Z))})};et();const oe=B=>{const Z=B.target;Z.mode==="showing"&&Ct(Z)},zt=()=>{Array.from(te.textTracks).forEach(B=>{B.removeEventListener("cuechange",oe),B.addEventListener("cuechange",oe)}),et()};Array.from(te.textTracks).forEach(B=>{B.addEventListener("cuechange",oe)}),te.textTracks.addEventListener("addtrack",zt);const Me=Array.from(te.querySelectorAll("track")),kt=()=>et();return Me.forEach(B=>B.addEventListener("load",kt)),()=>{Array.from(te.textTracks).forEach(B=>{B.removeEventListener("cuechange",oe)}),te.textTracks.removeEventListener("addtrack",zt),Me.forEach(B=>B.removeEventListener("load",kt))}}},[De,Oe,v,K,Be,se,ft,c,T,W,_e]);const Pe=T.length>0,ke=c>=0,st=()=>{Se("main"),Ze.setShowControls(!0)},Fe=()=>{Se(null)},Rt=ie.showControls||!!Ve,gt=t(vs,{visible:Rt,title:h,episode:z,onBack:he,classes:{overlay:o.controlsOverlay,hidden:o.hidden,top:o.topControls,backBtn:o.backBtn,titleInfo:o.videoTitleInfo,title:o.animeTitle,episode:o.episodeLabel}}),Je=!$&&!ie.isBuffering&&ie.duration>0?t(fs,{}):null,cn=t(Vo,{player:s,visible:Rt,settingsOpen:!!Ve,onOpenSettings:st,onCloseSettings:Fe,hasSubtitles:Pe,isSubtitleActive:ke,subtitles:T,onSubtitleChange:i,showNextEpisodeButton:Qe,onNextEpisode:A,isTheaterMode:ce,onTheaterModeToggle:X,timeLabelRef:pt}),yt=Ve?t(qo,{view:Ve,onSelectView:Se,onClose:Fe,player:s,onSubtitleStyleChange:ue,streams:C,resolutionIdx:r,onResolutionChange:w,hasSubtitles:Pe,subtitles:T,selectedSubtitle:c,isSubtitleActive:ke,onSubtitleChange:i,audioTracks:L,selectedAudioTrack:M,onAudioTrackChange:I,videoDelayEnabled:u,onVideoDelayToggle:Ce,videoDelayMs:we,onVideoDelayChange:fe,onCalibrate:()=>{Se(null),pe?.()},subtitleDelayMs:k,onSubtitleDelayChange:bt,ambientSettings:Xe,onAmbientChange:rt}):null,Y=t(Ge,{children:[$&&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})]})}),ie.isBuffering&&!$&&t("div",{className:o.bufferingOverlay,"aria-hidden":"true",children:t("div",{className:o.bufferingSpinner})}),ie.isSpeedBoostActive&&t("div",{className:o.speedBoostBadge,"aria-hidden":"true",children:[t("span",{children:"2x"}),t(be,{name:"forward",size:12})]})]});return t(ps,{engine:s.engine,topBar:gt,centerControls:Je,bottomBar:!$&&ie.duration>0?cn:null,settingsPanel:yt,overlays:Y,isInteracting:!!Ve||ie.showVolumeSlider,nativeControls:ie.useNativeControls,onStageClick:Fe,className:ie.isFullscreen?o.fullscreenFlat:"",children:ee})},Ho=({servers:s,selectedServer:h,onServerSelect:z})=>s.length===0?null:t("div",{className:on.sourceSelectionContainer,children:[t("h4",{children:"Source"}),t("div",{className:on.sourceButtons,children:s.map(L=>t("button",{className:`${on.sourceButton} ${h===L?on.active:""}`,onClick:()=>z(L),children:L},L))})]}),Wo=Jr.memo(Ho);function Ko({details:s,isMovie:h,season:z,episode:L,videoRef:M,active:I}){const T=V("");T.current||(T.current=`tv-${Date.now()}-${Math.random().toString(36).slice(2)}`);const c=N(()=>{if(!s)return;const i=M.current,C=h?"":`S${String(z).padStart(2,"0")}E${String(L).padStart(2,"0")}`;mt.discord.tvPresence.mutate({title:s.title,episodeLabel:C,isPlaying:i?!i.paused&&!i.ended:!0,thumbnail:s.poster,currentTime:i?i.currentTime:0,duration:i&&i.duration||0,isAdult:s.adult===!0,sessionId:T.current}).catch(()=>{}),mt.discord.heartbeat.mutate({sessionId:T.current}).catch(()=>{})},[s,h,z,L,M]);return g(()=>{if(!s)return;c();const i=window.setInterval(()=>{const C=M.current;(!C||!C.paused)&&c()},15e3);return()=>window.clearInterval(i)},[c,s,M]),g(()=>{if(!s||!I)return;const i=M.current;if(!i)return;const C=()=>c();return i.addEventListener("play",C),i.addEventListener("pause",C),i.addEventListener("seeked",C),()=>{i.removeEventListener("play",C),i.removeEventListener("pause",C),i.removeEventListener("seeked",C)}},[s,I,c,M]),g(()=>{const i=T.current,C=()=>rs(i),r=()=>C();return window.addEventListener("pagehide",r),window.addEventListener("beforeunload",r),()=>{window.removeEventListener("pagehide",r),window.removeEventListener("beforeunload",r),C()}},[]),{sendPresence:c}}function Yo(s,h,z){const L=()=>{const I=Array.isArray(s.audioTracks)?s.audioTracks.length:0,T=z.getWant(),c=I>0?Math.min(Math.max(0,T),I-1):T;s.audioTrack=c,c!==T&&z.onResolve(c)},M=(I,T)=>{const c=z.getWant(),i=Array.isArray(s.audioTracks)?s.audioTracks.length:0;if(T.id!==c&&c>=0&&c<i){s.audioTrack!==c&&(s.audioTrack=c);return}z.onResolve(T.id)};return s.on(h.MANIFEST_PARSED,L),s.on(h.AUDIO_TRACK_SWITCHED,M),()=>{s.off(h.MANIFEST_PARSED,L),s.off(h.AUDIO_TRACK_SWITCHED,M)}}const jo=/\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 Go(){try{if(jo.test(navigator.userAgent||""))return!0;const s=navigator.deviceMemory;if(typeof s=="number"&&s>0&&s<2)return!0}catch{}return!1}const Qo="_statusMsg_zqb8u_1",Xo="_error_zqb8u_7",Zo="_spinner_zqb8u_11",Jo="_spin_zqb8u_11",ea="_sourceLoader_zqb8u_16",ta="_ringSpinner_zqb8u_22",na="_meta_zqb8u_40",ra="_year_zqb8u_48",sa="_rating_zqb8u_53",oa="_typeBadge_zqb8u_62",aa="_tv_zqb8u_70",ia="_movie_zqb8u_75",la="_controlLabel_zqb8u_80",ca="_select_zqb8u_90",ua="_playerSection_zqb8u_102",da="_video_zqb8u_106",ma="_videoHidden_zqb8u_128",ba="_delayCanvas_zqb8u_133",ha="_delayCanvasActive_zqb8u_146",fa="_subtitleOverlay_zqb8u_150",pa="_videoIframe_zqb8u_169",va="_retryButton_zqb8u_177",ga="_sidebarSeason_zqb8u_192",ya="_mobileSeasonRow_zqb8u_208",Sa="_providerSelectWrap_zqb8u_222",_a="_genreRow_zqb8u_230",Ta="_genreChip_zqb8u_237",Ca="_metaRow_zqb8u_247",ka="_detailGrid_zqb8u_256",Ea="_detailItem_zqb8u_264",Na="_imdbLink_zqb8u_286",p={statusMsg:Qo,error:Xo,spinner:Zo,spin:Jo,sourceLoader:ea,ringSpinner:ta,meta:na,year:ra,rating:sa,typeBadge:oa,tv:aa,movie:ia,controlLabel:la,select:ca,playerSection:ua,video:da,videoHidden:ma,delayCanvas:ba,delayCanvasActive:ha,subtitleOverlay:fa,videoIframe:pa,retryButton:va,sidebarSeason:ga,mobileSeasonRow:ya,providerSelectWrap:Sa,genreRow:_a,genreChip:Ta,metaRow:Ca,detailGrid:ka,detailItem:Ea,imdbLink:Na},Ia=[],Aa=[];function mr({error:s,onRetry:h}){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:h,children:"Retry"})]})})}const Ha=()=>{const{id:s}=es(),[h]=ts(),z=V(h);z.current=h;const L=ns(),M=ms(),I=h.get("type"),T=ss(),c=!!T.session,i=c&&!T.session?.host,C=i&&["tv","movie"].includes(T.room?.selection.kind||"")?T.room?.selection:null,[r,w]=_(null),[he,ee]=_(()=>parseInt(h.get("s")||"1",10)||1),u=C?.season??he,[Ce,we]=_([]),[fe,pe]=_(()=>parseInt(h.get("e")||"1",10)||1),k=C?Number(C.episode):fe,[bt,Qe]=_(()=>{try{return O.getItem("tvProvider")||""}catch{return""}}),A=C?.provider??bt,[$,ce]=_([]),[X,Xe]=_(""),{options:rt,isFallback:ie,isLoading:ht}=Us(),Ze=ye(()=>rt.filter(e=>(e.kind??"tv")==="tv").map(e=>({id:e.id,label:e.label,tier:e.tier==="embed"?"embed":"direct",servers:e.servers})),[rt]),W=ie||Ze.length===0?Ia:Ze,De=W.filter(e=>e.tier==="direct"),Oe=W.filter(e=>e.tier==="embed"),[v,K]=_(!1),[Be,se]=_(""),[ft,Ve]=_([]),[Se,pt]=_(0),[_e,vt]=_([]),[ue,Pe]=_(-1),[ke,st]=_(0),[Fe,Rt]=_(""),[gt,Je]=_(""),[cn,yt]=_(()=>{try{return O.getItem("tvServer")||""}catch{return""}}),Y=C?.source??cn,Ee=ye(()=>W.find(e=>e.id===A),[W,A]),y=Ee?.tier==="embed",[qe,te]=_([]),[Ne,St]=_(""),[_t,Tt]=_(""),[Ct,et]=_(!1),oe=ye(()=>qe.length>0?qe:Ee?.servers??[],[qe,Ee]),zt=ye(()=>Ne&&!c?["Embed",...oe]:oe,[oe,Ne,c]),Me=Ct&&!!Ne,kt=Me?_t||Ne:"";g(()=>{if(!Ne){Tt("");return}let e=!1;return Rn(`/api/resolve?url=${encodeURIComponent(Ne)}`).then(n=>{!e&&n.finalUrl&&Tt(n.finalUrl)}).catch(()=>{}),()=>{e=!0}},[Ne]);const B=V([]);g(()=>{B.current=$},[$]);const Z=V(Se);g(()=>{Z.current=Se},[Se]);const ne=V(ue);g(()=>{ne.current=ue},[ue]);const b=gs({skipIntervals:Aa}),d=b.refs.videoRef,de=V(null),j=V([]),un=V(null),$t=V(null),{videoDelayMs:Et,videoDelayEnabled:Nt,setDelayEnabled:dn,handleVideoDelayChange:qn,isCalibrating:hr,testClipActive:Ie,stopCalibration:mn,openAvSyncCalibrator:fr,cancelAvSyncCalibrator:pr,applyAvSyncCalibrator:vr,toggleTestClip:gr,calibReturnRef:Dt,effectiveVideoDelayMs:bn}=ys(d),[ot,yr]=_(()=>{try{const e=Number(O.getItem("tvSubtitleDelayMs"));if(Number.isFinite(e)&&e>=-6e4&&e<=6e4)return Math.round(e)}catch{}return 0}),hn=V(ot);hn.current=ot;const Sr=N(e=>{const n=Math.max(-6e4,Math.min(6e4,Math.round(e)));if(hn.current!==n){hn.current=n,yr(n);try{O.setItem("tvSubtitleDelayMs",String(n))}catch{}}},[]);Ss({videoRef:d,canvasRef:un,delayMs:bn,enabled:Nt});const fn=Nt,ve=fn||ot!==0,{settings:pn,update:_r}=_s(),vn=V(ve);vn.current=ve;const gn=N(()=>{if(!vn.current)return;const e=d.current;e&&Array.from(e.textTracks).forEach(n=>{n.mode!=="hidden"&&(n.mode="hidden")})},[d]),{hasConsent:It,grant:Tr}=os(),f=I==="movie";Ko({details:r,isMovie:f,season:u,episode:k,videoRef:d,active:!y&&!v&&!Be&&$.length>0});const Ot=s?as(I||"tv",s):"",re=Ot,Re=`${re}:${u}:${k}:${A}:${Y}`,Vt=ye(()=>!s||!r||y||Me||v||X!==Re||$[ke]?.type!=="hls"?null:{kind:f?"movie":"tv",...f?{}:{season:u},showId:s,episode:String(f?1:k),provider:A,source:Y,mode:"sub",title:r.title},[s,r,y,Me,v,X,Re,$,ke,f,u,k,A,Y]),Un=Ts(b.engine,Vt,v||!r),Hn=Hs(),Ft=Ws(),qt=Ks(),{toggle:Wn,bookmarkedIds:Cr,pending:kr}=Ys(),{data:Kn}=js(r?Ot:void 0),At=Kn?!!Kn.inLibrary:Ot?Cr.has(Ot):!1,Er=N(()=>{!r||!s||Wn({tmdbId:Number(s),mediaType:I||"tv",title:r.title,poster:r.poster,year:r.year,adult:r.adult})},[r,s,I,Wn]),{data:at,isFetched:Yn,isFetching:yn}=Gs(re||void 0,u,k),Ut=ye(()=>Ce.map(e=>e.episode_number).sort((e,n)=>e-n),[Ce]),xt=Ut.indexOf(k),Sn=xt>0?Ut[xt-1]:null,F=xt>=0&&xt<Ut.length-1?Ut[xt+1]:null,Ht=ye(()=>(r?.seasons??[]).map(e=>e.season_number).filter(e=>Number.isFinite(e)).sort((e,n)=>e-n),[r]),Ue=ye(()=>{if(f||F!=null)return null;const e=Ht.indexOf(u);return e>=0&&e<Ht.length-1?Ht[e+1]:(r?.number_of_seasons??0)>u?u+1:null},[f,F,Ht,u,r?.number_of_seasons]),jn=at?.currentTime??0,Wt=V(null),[He,Kt]=_(!1),[it,Gn]=_(0),[Lt,Qn]=_(!1),[lt,ct]=_(!1),[Nr,_n]=_(!1),[Ir,Ar]=_(""),[Yt,xr]=_(!1),[Lr,Tn]=_(!1),{isTheaterMode:ze,toggleTheaterMode:Cn,handleLayoutClick:wr}=Cs();g(()=>{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"&&Cn()};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[Cn]),ks(b,($.length>0||gt!=="")&&!ze&&!He&&!lt);const Br=Js(),[ut,Pr]=_(Xs),Mr=N(e=>{Pr(e),Zs(e)},[]),We=V(!1),$e=V(null),kn=V(0),J=V(null),jt=V(""),Rr=ur(jn),wt=!c&&!We.current&&(He||lt||Rr),Gt=V(wt);Gt.current=wt;const Qt=V(!1);g(()=>{Qt.current=Lt},[Lt]);const Ke=N((e,n)=>{if(!re||!n||n<30)return;const a=an(e,n);Math.abs(e-kn.current)<10&&!a||(kn.current=e,Hn.mutate({mediaId:re,season:u,episode:k,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:I||"tv",adult:r?.adult?1:0}))},[re,u,k,Hn,r,I]),Ae=N((e,n)=>{mn();const a=new URLSearchParams(h);a.set("type",h.get("type")||"tv"),a.set("s",String(e)),a.set("e",String(n)),L(`${window.location.pathname}?${a.toString()}`)},[h,L,mn]),Bt=N(()=>{const e=d.current;if(!e||f||F==null){_n(!1);return}const n=e.duration||0,a=e.currentTime||0;_n(n>0&&a/n>=.8)},[f,F,d]),Xt=N((e,n)=>["tv-sources",A,f?"movie":"tv",s,e,n,Y],[A,f,s,Y]),Zt=N(async(e,n)=>{if(!r||!s||!A)return{valid:!1,sources:[]};const a=f?"movie":"tv",l=await mt.tv.sources.query({provider:A,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||"",...Y?{server:Y}:{}});return{valid:"valid"in l?l.valid:!1,error:"error"in l?l.error:void 0,sources:l.sources,referer:"referer"in l?l.referer:void 0,audioTracks:l.audioTracks,subtitles:"subtitles"in l?l.subtitles:void 0,servers:"servers"in l?l.servers:void 0,server:"server"in l?l.server:void 0,embedUrl:"embedUrl"in l?l.embedUrl:void 0}},[r,s,A,f,Y]),Xn=N(()=>{if(f||!r||!s||!A||y||F==null)return;const e=Xt(u,F);M.getQueryState(e)?.status!=="success"&&M.prefetchQuery({queryKey:e,queryFn:()=>Zt(u,F),staleTime:300*1e3,gcTime:1800*1e3})},[f,r,s,A,y,F,u,M,Xt,Zt]),zr=N(()=>{if(Ie)return;Bt();const e=d.current;!e||e.paused||e.ended||(e.duration>0&&e.duration-e.currentTime<=60&&Xn(),!$e.current&&($e.current=setTimeout(()=>{$e.current=null,Ke(e.currentTime,e.duration||0)},5e3)))},[Ke,d,Ie,Bt,Xn]),$r=N(()=>{const e=d.current;if(!(!e||!r)&&($e.current&&clearTimeout($e.current),$e.current=null,Ke(e.currentTime,e.duration||0),!i)){if(F!=null){ut&&(pe(F),Ae(u,F));return}Ar(f?r.title:`${r.title} - Season ${u}`),ct(!0),We.current=!0}},[f,r,u,F,ut,Ke,Ae,d,i]),{checkEnd:Jt,logDuration:Zn}=Es({videoRef:d,sourceType:y?"iframe":void 0,resetKey:`${re}:${u}:${k}`,onEnd:$r}),Dr=N(()=>{b.actions.onPlay()},[b.actions]),Or=N(()=>{b.actions.onPause();const e=d.current;e&&!e.ended&&Ke(e.currentTime,e.duration||0)},[b.actions,Ke,d]),Vr=N(()=>{const e=d.current;if(e){try{const n=parseFloat(O.getItem("playerVolume")||"");isNaN(n)||(e.volume=Math.max(0,Math.min(1,n))),e.muted=O.getItem("playerMuted")==="true"}catch{}if(J.current!=null&&J.current>0){try{e.currentTime=J.current}catch{}J.current=null}Bt()}},[d,Bt]),En=N(()=>{const e=d.current;if(e&&J.current!=null&&J.current>0){try{e.currentTime=J.current}catch{}J.current=null}},[d]),Fr=N(()=>{it>0&&(J.current=it);const e=d.current;if(e&&it>0){try{e.currentTime=it,J.current=null}catch{}e.play().catch(()=>{})}Kt(!1),We.current=!0},[it,d]),Jn=N(()=>{J.current=null;const e=d.current;e&&(e.currentTime=0,e.play().catch(()=>{})),Kt(!1),We.current=!0},[d]),qr=N(()=>{F!=null&&(We.current=!0,pe(F),Ae(u,F))},[F,u,Ae]),Ur=N(()=>{Ue!=null&&(ct(!1),We.current=!0,ee(Ue),pe(1),Ae(Ue,1))},[Ue,Ae]),Hr=N(async()=>{if(re)try{At?await Ft.mutateAsync({id:re,status:"Completed"}):r&&s&&(await qt.mutateAsync({tmdbId:Number(s),mediaType:I||"tv",title:r.title,poster:r.poster,backdrop:r.backdrop,year:r.year,overview:r.overview,adult:r.adult,status:"Completed",silent:!0}),cr.success("Moved to Completed")),ct(!1),L("/")}catch{}},[re,At,Ft,qt,r,s,I,L]);g(()=>{We.current=!1,Wt.current=null,Kt(!1),_n(!1),Gn(0),Qn(!1),Qt.current=!1,J.current=null,kn.current=0},[re,u,k]),g(()=>{jt.current=Re},[Re]),g(()=>{Yn&&(Qn(!0),Qt.current=!0)},[Yn,re,u,k]),g(()=>{if(c||yn||!at||We.current)return;const e=`${re}:${u}:${k}`;if(Wt.current===e)return;Wt.current=e;const n=at,a=n.currentTime??0;ur(a)&&n.completed!==1&&!an(a,n.duration??0)&&(Gn(a),Kt(!0))},[at,yn,re,u,k,c]),g(()=>{!c&&He&&d.current&&d.current.pause()},[He,d,c]),g(()=>{const e=d.current;return()=>{$e.current&&clearTimeout($e.current),$e.current=null,!e?.ended&&b.engine.getState().duration>0&&Ke(b.engine.getTimeline().currentTime,b.engine.getState().duration)}},[b.engine,Ke,d]);const Nn=N(e=>{let n=null,a=!0;try{n=O.getItem("tvLastSubtitle"),a=O.getItem("tvSubtitlesEnabled")!=="false"}catch{}return Vn(e,{lastKey:n,enabled:a})},[]),In=N(e=>{if(!(e<0))try{O.setItem("tvSubtitlesEnabled","true"),O.setItem("tvSelectedSubtitle",String(e))}catch{}},[]),er=N(e=>{if(e.length===0)return 0;let n=null;try{n=O.getItem("tvLastAudio")}catch{}if(n){const a=e.findIndex(U=>zn(U)===n);if(a>=0)return a;const l=n.indexOf("|||"),m=l>=0?n.slice(0,l):n,x=l>=0?n.slice(l+3):n,q=e.findIndex(U=>U.language===m||U.label===x);if(q>=0)return q}return Vn(e,{lastKey:null,enabled:!0})},[]),{data:tr}=Qs(re||void 0),nr=ye(()=>(tr?.progress??[]).filter(n=>n.season===u&&(n.completed===1||an(n.currentTime,n.duration))).map(n=>String(n.episode)),[tr,u]),rr=ye(()=>Ce.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})),[Ce]),sr=ye(()=>(r?.genres??[]).map(e=>e.name).slice(0,5),[r]),An=ye(()=>[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]);g(()=>{if(!i&&W.length!==0&&!W.some(e=>e.id===A)){const e=W.find(n=>n.tier==="direct")?.id??W[0].id;Qe(e);try{O.setItem("tvProvider",e)}catch{}}},[W,A,i]),g(()=>{te([]),St(""),Tt(""),et(!1)},[A]),g(()=>{if(!i&&oe.length!==0&&!oe.includes(Y)){yt(oe[0]);try{O.setItem("tvServer",oe[0])}catch{}}},[oe,Y,i]),g(()=>{if(!s){w(null),ce([]),Xe(""),se(""),Je("");return}const e=Number(s),n=I||"tv";w(null),ce([]),Xe(""),se(""),Je("");const a=parseInt(z.current.get("s")||"",10),l=parseInt(z.current.get("e")||"",10);ee(isNaN(a)?1:a),pe(isNaN(l)?1:l),st(0),mt.tv.details.query({type:n,id:String(e)}).then(m=>{const x={id:m.id,title:m.title||"",overview:m.overview||"",vote_average:m.vote_average,year:m.year,poster:m.poster,backdrop:m.backdrop,imdb_id:m.imdb_id||void 0,adult:m.adult,seasons:m.seasons,number_of_seasons:m.number_of_seasons};w(x),x.seasons&&x.seasons.length>0&&isNaN(a)&&ee(x.seasons[0].season_number)}).catch(()=>{})},[s,I]),g(()=>{if(!r||!s)return;if(!(r.seasons!==void 0||r.number_of_seasons!==void 0)){we([]);return}const n=parseInt(h.get("e")||"",10);mt.tv.episodes.query({id:String(s),season:String(u)}).then(a=>{const l=(a.episodes||[]).map(m=>({episode_number:m.episode_number,name:m.name||"",vote_average:m.vote_average,overview:m.overview||"",still_path:m.still_path||""}));we(l),l.length!==0&&pe(m=>!isNaN(n)&&l.some(x=>x.episode_number===n)?n:l.some(x=>x.episode_number===m)?m:l[0].episode_number)}).catch(()=>{})},[r,s,u,h]),g(()=>{if(!y||!r||!s)return;Rn(`/api/tv/embed/${A}/${f?"movie":"tv"}/${s}?season=${u}&episode=${k}`).then(n=>{if(n.url)return Je(n.url),Rn(`/api/resolve?url=${encodeURIComponent(n.url)}`).then(a=>{a.finalUrl&&Je(a.finalUrl)})}).catch(()=>{})},[A,r,s,u,k,f,y]);const en=N(async()=>{if(!r||!s||!A||y||r.adult&&!It)return;const e=Re;K(!0),se(""),B.current.length===0&&(ce([]),st(0),Ve([]),vt([]));try{const n=await M.fetchQuery({queryKey:Xt(u,k),queryFn:()=>Zt(u,k),staleTime:3e5,gcTime:18e5});if(jt.current!==e)return;if(K(!1),!n.valid||!n.sources?.length){se(n.error?`${n.error}`:oe.length>0?`No streams from ${Y}. Try another server.`:"No streams available.");return}if(c&&Y&&n.server&&n.server!==Y){ce([]),se("The host's selected server is unavailable. Automatic source switching is disabled in watch-along rooms.");return}!i&&!Y&&n.server&&yt(n.server);const a=c?n.sources.filter(U=>U.type==="hls"):n.sources;if(c&&a.length===0){ce([]),se("The room requires a direct HLS source. No compatible stream is available here.");return}ce(a),Xe(e),n.servers?.length&&te(n.servers),n.embedUrl&&St(n.embedUrl),st(0),n.referer&&Rt(n.referer);const l=n.audioTracks||[];Ve(l),pt(l.length>0?er(l):0);const m=n.subtitles||[];if(vt(m),m.length>0){const U=Nn(m);Pe(U),In(U)}else Pe(-1);const x=f?"movie":"tv",q=s;mt.tv.subtitles.query({type:x,tmdbId:String(q),season:String(u),episode:String(k)}).then(U=>{if(jt.current!==e)return;const ge=Array.isArray(U.subtitles)?U.subtitles:[];ge.length!==0&&vt(S=>{const G=[...S,...ge.filter(Q=>!S.some(D=>D.url===Q.url))];if(S.length===0){const Q=Nn(G);Pe(Q),In(Q)}return G})}).catch(()=>{}),se("")}catch(n){if(jt.current!==e)return;K(!1),se(n instanceof Error?n.message:"Failed to load streams.")}},[r,s,A,u,k,f,y,It,oe,Y,Nn,In,er,M,Xt,Zt,Re,c,i]),xn=N(()=>{const e=d.current;e&&!isNaN(e.currentTime)&&(J.current=e.currentTime)},[d]),Wr=N(e=>{if(!(i||c&&e==="Embed")){if(e==="Embed"){et(!0);return}xn(),et(!1),yt(e);try{O.setItem("tvServer",e)}catch{}se("")}},[xn,i,c]),Kr=N(e=>{Qe(e);try{O.setItem("tvProvider",e)}catch{}},[]);g(()=>{A&&r&&!y&&en()},[A,r,en,y]),g(()=>{if(!d.current)return;if(de.current=null,y||Me||c&&$[ke]?.type!=="hls"){b.engine.unload();return}if(Ie&&!c)return b.engine.loadSource({url:"/av-sync-test.mp4"},{autoPlay:!Gt.current});if(Dt.current!=null&&(J.current=Dt.current,Dt.current=null),X===Re&&J.current==null&&!Gt.current)try{const S=d.current;S&&!S.ended&&S.currentTime>1&&(J.current=S.currentTime)}catch{}const n=J.current??0,a=!v&&X===Re?Me?"":$[ke]?.url||"":"";if(!a){try{d.current?.pause(),d.current?.removeAttribute("src"),d.current?.load()}catch{}return}const l=d.current;l.pause(),l.removeAttribute("src"),l.load(),b.actions.resetMediaState();const m=`/api/tv/stream-proxy?url=${encodeURIComponent(a)}&referer=${encodeURIComponent(Fe)}&provider=${encodeURIComponent(A)}`,x=Go()||document.body.classList.contains("low-end"),q=x?60:180,U=b.engine.loadSource({url:m,hls:$[ke]?.type==="hls"},{hlsConfig:{enableWorker:!0,lowLatencyMode:!1,startPosition:n>0?n:-1,maxBufferLength:q,maxMaxBufferLength:q+(x?30:60),backBufferLength:x?30:60,maxBufferSize:(x?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:(S,G)=>{de.current=S;const Q=()=>{let R=!1,P=0;try{R=O.getItem("tvSubtitlesEnabled")==="true";const E=parseInt(O.getItem("tvSelectedSubtitle")||"0",10);!isNaN(E)&&E>=0&&(P=E)}catch{}return{enabled:R,index:P}},D=()=>{if(typeof S.subtitleTrack!="number")return;if(j.current.length>0){S.subtitleTrack=-1;return}const R=Array.isArray(S.subtitleTracks)?S.subtitleTracks:[];if(R.length===0){S.subtitleTrack=-1;return}const P=Q();if(P.enabled){const E=P.index<R.length?P.index:0;S.subtitleTrack=E,Pe(E),gn()}else S.subtitleTrack=-1};Yo(S,G.Events,{getWant:()=>Z.current,onResolve:R=>pt(R)}),S.on(G.Events.MANIFEST_PARSED,D),S.on(G.Events.SUBTITLE_TRACKS_UPDATED,()=>{D()}),S.on(G.Events.SUBTITLE_TRACK_SWITCH,(R,P)=>{if(j.current.length>0){if(P.id!==-1)try{S.subtitleTrack=-1}catch{}return}const E=Array.isArray(S.subtitleTracks)?S.subtitleTracks:[];if(E.length!==0){if(P.id===-1){const Te=Q();if(Te.enabled){const ae=Te.index<E.length?Te.index:0;S.subtitleTrack=ae;return}}Pe(P.id),gn()}})},onReady:()=>{(n>0||!Gt.current&&Qt.current)&&b.engine.play()},onError:S=>{se(S.message),K(!1),de.current=null}}),ge=()=>{const Q=l.error?.code===4?"Video source not supported or not found":"Failed to load video stream";se(`${Q}. The source may be invalid or expired. Try switching source or reloading.`),K(!1)};return l.addEventListener("error",ge),()=>{U(),de.current=null,l.removeEventListener("error",ge)}},[$,X,v,ke,A,Fe,y,Me,d,Dt,Ie,re,u,k,En,gn,b.actions,b.engine,Re,c]),g(()=>{if(i||!Lt||He||lt||wt||y||Ie)return;const e=d.current;!e||!e.paused||e.ended||e.readyState<1||(En(),b.engine.play())},[Lt,He,lt,wt,y,Ie,En,d,i,b.engine]),g(()=>{const e=de.current;!e||typeof e.audioTrack!="number"||(e.audioTrack=Se)},[Se]),g(()=>{const e=de.current;!e||typeof e.subtitleTrack!="number"||!Array.isArray(e.subtitleTracks)||e.subtitleTracks.length===0||j.current.length>0||(ue>=0?e.subtitleTrack=ue:e.subtitleTrack=-1)},[ue]),g(()=>{const e=d.current;if(!(!e||y)&&(e.querySelectorAll("track").forEach(n=>n.remove()),j.current=[],_e.length!==0&&(_e.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 l=`/api/subtitle-proxy?url=${encodeURIComponent(n.url)}&referer=${encodeURIComponent(Fe)}`;a.src=l,a.addEventListener("load",()=>{const m=j.current.indexOf(a),x=a.track;if(x&&m>=0){const q=m===ne.current;x.mode=q&&!vn.current?"showing":"hidden"}}),e.appendChild(a),j.current.push(a)}),_e.length>0)))try{const n=de.current;n&&typeof n.subtitleTrack=="number"&&n.subtitleTrack!==-1&&(n.subtitleTrack=-1)}catch{}},[_e,Fe,y,A,d]),g(()=>{const e=d.current;if(!e||y)return;const n=de.current;j.current.length>0&&n&&typeof n.subtitleTrack=="number"&&Array.isArray(n.subtitleTracks)&&n.subtitleTracks.length>0&&(n.subtitleTrack=-1);const a=()=>{const x=Fn(b.state.subtitleFontSize,e.clientHeight||720),q=Math.max(0,Math.min(100,100-b.state.subtitlePosition)),U=()=>{const D=x*16,R=e.videoHeight||e.clientHeight||720,P=e.videoWidth||e.clientWidth||1280;return{step:D*1.3/R*100,chars:Math.max(20,Math.floor(P/(D*.55)))}},ge=(D,R)=>{const P=D;P.snapToLines=!1,P.line=R},S=D=>{if(!D.cues)return;Array.from(D.cues).forEach(ae=>ge(ae,q));const R=Array.from(D.activeCues??[]);if(R.length<=1){R.forEach(ae=>ge(ae,q));return}const{step:P,chars:E}=U();let Te=q;for(let ae=R.length-1;ae>=0;ae--){const Ye=String(R[ae].text??"").replace(/<[^>]*>/g,"").split(`
|
|
3
3
|
`).reduce((nn,Pt)=>nn+Math.max(1,Math.ceil(Pt.length/E)),0);Te=Math.max(0,Te-Ye*P),ge(R[ae],Te),Te-=P*.4}},G=j.current;if(G.length>0){G.forEach((D,R)=>{const P=D.track;if(!P)return;const E=R===ue;P.mode=E&&!ve?"showing":"hidden",E&&!ve&&S(P)});return}const Q=Array.from(e.textTracks);Q.length!==0&&Q.forEach((D,R)=>{const P=R===ue;D.mode=P&&!ve?"showing":"hidden",P&&!ve&&S(D)})};a();const l=()=>a();e.textTracks.addEventListener("addtrack",l),e.addEventListener("loadedmetadata",a,{once:!0});const m=window.setTimeout(a,600);return()=>{e.textTracks.removeEventListener("addtrack",l),e.removeEventListener("loadedmetadata",a),window.clearTimeout(m)}},[ue,_e,y,A,d,ve,b.state.subtitleFontSize,b.state.subtitlePosition]),g(()=>{if(!ve)return;const e=d.current,n=$t.current;if(!e||!n)return;const a=ot/1e3,l=bn/1e3,m=new Set;let x=[],q=-1,U=-1,ge=-1,S=-1,G=0,Q=0,D=!1;const R=()=>{const H=ne.current;if(H<0)return null;const je=j.current;return je.length>0?je[H]?.track??null:Array.from(e.textTracks)[H]??null},P=(H,je)=>{const me=H.cues;if(!me||me.length===0)return Array.from(H.activeCues??[]);let tt=0,nt=me.length;for(;tt<nt;){const xe=tt+nt>>>1;me[xe].endTime+a<je?tt=xe+1:nt=xe}const Mt=[];for(let xe=tt;xe<me.length;xe++){const rn=me[xe];if(rn.startTime+a>je)break;rn.endTime+a>=je&&Mt.push(rn)}return Mt},E=()=>{const H=R(),je=e.currentTime-l,me=H?P(H,je):[],tt=e.clientWidth,nt=e.clientHeight,Mt=e.videoWidth,xe=e.videoHeight;if(me.length===x.length&&me.every((Bn,Pn)=>Bn===x[Pn])&&tt===q&&nt===U&&Mt===ge&&xe===S||(x=me,q=tt,U=nt,ge=Mt,S=xe,n.textContent="",me.length===0))return;const ir={fontSize:Fn(b.state.subtitleFontSize,nt),position:b.state.subtitlePosition,bgOpacity:b.state.subtitleBgOpacity,bgColor:b.state.subtitleBgColor,textColor:b.state.subtitleTextColor,edge:b.state.subtitleEdge,bold:b.state.subtitleBold},Qr=Ns(ir),Xr=Is(e,ir.position);me.forEach((Bn,Pn)=>{const lr=String(Bn.text??"");if(!As(lr).trim())return;const Mn=document.createElement("div"),Zr=(me.length-1-Pn)*1.7;Mn.style.cssText=`${Qr}
|
|
4
4
|
bottom: calc(${Xr}px + ${Zr}em);`,Mn.innerHTML=xs(lr),n.appendChild(Mn)})},Te=()=>{Array.from(e.textTracks).forEach(H=>{m.has(H)||(m.add(H),H.addEventListener("cuechange",E))})},ae=()=>{Te(),E()},wn=()=>{if(D||Q)return;const H=()=>{Q=0,!(D||e.paused||e.ended)&&(E(),wn())};Q=window.requestAnimationFrame(H)},Ye=e,nn=()=>{G=0,E(),!D&&Ye.requestVideoFrameCallback&&(G=Ye.requestVideoFrameCallback(nn))},Pt=()=>{E(),Ye.requestVideoFrameCallback?G||(G=Ye.requestVideoFrameCallback(nn)):wn()};Te(),e.textTracks.addEventListener("addtrack",ae),e.textTracks.addEventListener("removetrack",ae),e.addEventListener("timeupdate",E),e.addEventListener("seeked",E),e.addEventListener("loadedmetadata",E),e.addEventListener("play",Pt);const or=Array.from(e.querySelectorAll("track"));or.forEach(H=>H.addEventListener("load",E));const ar=typeof ResizeObserver>"u"?null:new ResizeObserver(()=>E());return ar?.observe(e),E(),Pt(),()=>{D=!0,m.forEach(H=>H.removeEventListener("cuechange",E)),e.textTracks.removeEventListener("addtrack",ae),e.textTracks.removeEventListener("removetrack",ae),e.removeEventListener("timeupdate",E),e.removeEventListener("seeked",E),e.removeEventListener("loadedmetadata",E),e.removeEventListener("play",Pt),or.forEach(H=>H.removeEventListener("load",E)),ar?.disconnect(),Q&&window.cancelAnimationFrame(Q),G&&Ye.cancelVideoFrameCallback&&Ye.cancelVideoFrameCallback(G),n.textContent=""}},[ve,ot,ue,_e,bn,d,b.state.subtitleFontSize,b.state.subtitlePosition,b.state.subtitleBgOpacity,b.state.subtitleBgColor,b.state.subtitleTextColor,b.state.subtitleEdge,b.state.subtitleBold]);const Ln=()=>{w(null),ce([]),Je(""),L(-1)},Yr=N(e=>{i||(ee(e),pe(1),Ae(e,1))},[Ae,i]),tn=!f&&r?.seasons&&r.seasons.length>1?t("label",{className:p.sidebarSeason,children:[t("span",{children:"Season"}),t("select",{disabled:i,value:u,onChange:e=>Yr(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,dt=N(e=>{if(i)return;const n=parseInt(e,10);if(!isNaN(n)){try{d.current?.pause()}catch{}pe(n),Ae(u,n)}Tn(!1)},[u,Ae,d,i]);g(()=>{if(f)return;const e=n=>{n.target.closest('input, textarea, button, select, a, [role="button"], [contenteditable="true"]')||n.key.toLowerCase()==="n"&&(F!=null?dt(String(F)):cr.error("No next episode available"))};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[f,F,dt]);const jr=e=>{pt(e);try{const a=ft[e];a&&O.setItem("tvLastAudio",zn(a))}catch{}const n=de.current;n&&n.audioTrack!==void 0&&(n.audioTrack=e)},Gr=e=>{Pe(e);try{if(e===-1)O.setItem("tvSubtitlesEnabled","false");else{O.setItem("tvSubtitlesEnabled","true"),O.setItem("tvSelectedSubtitle",String(e));const m=_e[e];m&&O.setItem("tvLastSubtitle",zn(m))}}catch{}const n=d.current,a=de.current;if(a&&typeof a.subtitleTrack=="number"&&Array.isArray(a.subtitleTracks)&&a.subtitleTracks.length>0&&(a.subtitleTrack=j.current.length>0||e<0?-1:e),!n)return;const l=j.current;if(l.length>0){l.forEach((m,x)=>{const q=m.track;if(!q)return;const U=x===e;q.mode=U&&!ve?"showing":"hidden"});return}Array.from(n.textTracks).forEach((m,x)=>{const q=x===e;m.mode=q&&!ve?"showing":"hidden"})};return g(()=>{if(!r){document.title="TV & Movies - dango";return}document.title=f?`${r.title} - dango`:`${r.title} - Season ${u} Episode ${k} - dango`},[r,f,u,k]),g(()=>{if(!r||f)return;const e=new URLSearchParams(h),n=e.get("s"),a=e.get("e"),l=String(u),m=String(k);n===l&&a===m||(e.set("type",h.get("type")||"tv"),e.set("s",l),e.set("e",m),L(`${window.location.pathname}?${e.toString()}`,{replace:!0}))},[r,f,u,k,h,L]),t("div",{className:`${Le.playerPageLayout} ${ze?Le.theaterMode:""} ${f?Le.noSidebar:""}`,onClick:wr,children:[ze&&t(Ls,{videoRef:d,active:pn.enabled&&!y&&$.length>0&&!Be&&!(r?.adult&&!It),settings:pn}),!ze&&!f&&t("aside",{className:Le.episodeSidebar,children:r?t(ws,{episodes:rr,currentEpisode:String(k),watchedEpisodes:nr,onEpisodeClick:dt,header:tn}):t(Bs,{variant:"sidebar"})}),t("div",{className:Le.playerMain,children:[r&&t("div",{className:p.playerSection,onContextMenu:e=>e.preventDefault(),style:r.adult&&!It?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:y&>&&!c?t("iframe",{src:gt,className:p.videoIframe,allow:"autoplay; fullscreen",allowFullScreen:!0}):!y&&kt&&!c?t("iframe",{src:kt,className:p.videoIframe,allow:"autoplay; fullscreen",allowFullScreen:!0}):!y&&($.length>0||v)?t(Ge,{children:[Be&&t(mr,{error:Be,onRetry:en}),t(Uo,{player:b,title:r.title,episodeLabel:f?void 0:`S${u} E${k}`,audioTracks:ft,selectedAudioTrack:Se,onAudioTrackChange:jr,subtitles:_e,selectedSubtitle:ue,onSubtitleChange:Gr,streams:$,resolutionIdx:ke,onResolutionChange:e=>{xn(),st(e)},onBack:Ln,videoDelayEnabled:Nt,onVideoDelayToggle:dn,videoDelayMs:Et,onVideoDelayChange:qn,onCalibrateAvSync:c?void 0:fr,subtitleDelayMs:ot,onSubtitleDelayChange:Sr,showNextEpisodeButton:!i&&Nr&&!He&&!lt,onNextEpisode:qr,isLoading:v,isTheaterMode:ze,onTheaterModeToggle:Cn,ambientSettings:pn,onAmbientChange:_r,children:[t(ds,{autoPlay:!c&&Lt&&!wt,playsInline:!0,disablePictureInPicture:!0,className:`${p.video} ${fn?p.videoHidden:""}`,onTimeUpdate:()=>{Ie||(zr(),Jt())},onEnded:()=>{Ie||Jt(!0)},onPlay:Dr,onPause:Or,onSeeked:()=>{Ie||(Bt(),Jt())},onLoadedMetadata:()=>{Vr(),Zn(),Jt()},onDurationChange:()=>{Zn()},onContextMenu:e=>e.preventDefault(),onError:()=>{se("Video failed to load. Try another server or reload."),K(!1)}}),t("canvas",{ref:un,className:`${p.delayCanvas} ${fn?p.delayCanvasActive:""}`}),ve&&t("div",{ref:$t,className:p.subtitleOverlay}),t(Ps,{isOpen:hr,ms:Et,onChange:qn,onApply:vr,onClose:pr,testClipActive:Ie,onTestClip:gr})]})]}):Be&&!y?t(mr,{error:Be,onRetry:en}):null}),t(to,{playback:Vt?{selection:Vt,position:d.current?.currentTime||0,playing:!1,rate:b.engine.getState().playbackRate}:null,onCreate:()=>{mn(),b.engine.pause()},needsPlayback:Un.needsPlayback,onEnablePlayback:Un.enablePlayback}),c&&!v&&r&&!Vt&&t("p",{role:"alert",children:"The host's direct HLS source is unavailable here. Retry or leave the room to use another source."}),!ze&&r&&t(Ms,{}),!ze&&tn&&t("div",{className:p.mobileSeasonRow,children:tn}),!ze&&r&&t("div",{className:le.streamPanel,children:[t("div",{className:p.providerSelectWrap,children:t("label",{className:p.controlLabel,children:["Provider",t("select",{value:A,onChange:e=>Kr(e.currentTarget.value),className:p.select,disabled:i||W.length===0,children:ht?t("option",{value:"",children:"Loading..."}):W.length===0?t("option",{value:"",children:"No providers available"}):t(Ge,{children:[De.length>0&&t("optgroup",{label:"Direct HLS",children:De.map(e=>t("option",{value:e.id,children:e.label},e.id))}),Oe.length>0&&t("optgroup",{label:"Embeds",children:Oe.map(e=>t("option",{value:e.id,children:e.label},e.id))})]})})]})}),!i&&!y&&(v?t("div",{className:p.sourceLoader,children:t("div",{className:p.ringSpinner})}):t(Wo,{servers:zt,selectedServer:Ct?"Embed":Y,onServerSelect:Wr}))]}),!ze&&r&&t("div",{className:Le.playerInfoContainer,children:[t("div",{className:Le.playerInfoHeader,children:[t("div",{className:Le.playerAnimeCard,children:r.poster&&t("img",{src:`https://image.tmdb.org/t/p/w342${r.poster}`,alt:r.title,loading:"lazy",decoding:"async"})}),t("div",{className:Le.videoTitleSection,children:[t("div",{className:le.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(be,{name:"star",size:12}),Number(r.vote_average).toFixed(1)]}),t("span",{className:`${p.typeBadge} ${p[f?"movie":"tv"]}`,children:f?"Movie":"TV Show"})]}),sr.length>0&&t("div",{className:p.genreRow,children:sr.map(e=>t("span",{className:p.genreChip,children:e},e))}),An.length>0&&t("div",{className:p.metaRow,children:An.map((e,n)=>t("span",{children:[e,n<An.length-1?" · ":""]},`${e}-${n}`))})]}),t("div",{className:le.controls,children:[t("button",{className:`${le.watchlistBtn} ${At?le.inList:""}`,onClick:Er,disabled:kr,type:"button",children:[At?t(be,{name:"check",size:14}):t(be,{name:"plus",size:14}),At?"In Watchlist":"Add to Watchlist"]}),!f&&t(Ge,{children:[t("button",{className:`${le.watchlistBtn}`,onClick:()=>Sn!=null&&dt(String(Sn)),disabled:i||Sn==null,type:"button",children:[t(be,{name:"chevron-left",size:14}),"Prev EP"]}),t("button",{className:`${le.watchlistBtn}`,onClick:()=>F!=null&&dt(String(F)),disabled:i||F==null,type:"button",children:["Next EP",t(be,{name:"chevron-right",size:14})]}),!f&&t("button",{className:`${le.watchlistBtn} ${le.modeToggleBtn} ${ut?le.modeToggleActive:""}`,onClick:()=>Mr(!ut),type:"button","aria-pressed":ut,children:ut?"AUTOPLAY: ON":"AUTOPLAY: OFF"}),Br&&t("button",{className:`${le.watchlistBtn}`,onClick:()=>Tn(!0),type:"button",children:[t(be,{name:"list-ul",size:14}),"Episodes"]})]})]})]})]}),t("div",{className:Le.infoColumns,children:[t("div",{className:`${le.descriptionSection} ${le.synopsisFlat}`,children:[t("h3",{children:"Synopsis"}),t(eo,{text:r.overview,emptyText:"No description available."}),t("button",{className:le.detailsToggleBtn,onClick:()=>xr(!Yt),type:"button",children:[Yt?t(be,{name:"chevron-up"}):t(be,{name:"chevron-down"}),Yt?"Hide Details":"Show Details"]})]}),Yt&&t("div",{className:p.detailGrid,children:[r.first_air_date&&t("div",{className:p.detailItem,children:[t("strong",{children:f?"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"})]})]})]})]}),!f&&t(Rs,{isOpen:Lr,onClose:()=>Tn(!1),episodes:rr,currentEpisode:String(k),watchedEpisodes:nr,onEpisodeClick:dt,header:tn}),r?.adult&&!It&&t(qs,{isOpen:!0,onClose:Ln,onGrant:Tr}),t(zs,{isOpen:!c&&He&&!yn&&Wt.current===`${re}:${u}:${k}`&&at?.completed!==1&&!an(jn,at?.duration??0),onClose:Jn,title:"Resume Watching",message:t(Ge,{children:["You were at ",t("strong",{children:On(it)})]}),restartLabel:"Start from Beginning",onResume:Fr,onRestart:Jn}),t($s,{isOpen:lt,onClose:()=>ct(!1),title:f?"Movie Completed!":Ue!=null?"Season Complete!":"Show Completed!",heading:Ir,message:f?"You finished this movie!":Ue!=null?`You finished Season ${u}.`:"Congratulations! You finished all available episodes.",children:[t(sn,{variant:"secondary",onClick:()=>ct(!1),children:"Close"}),Ue!=null?t(sn,{onClick:Ur,children:["Start Season ",Ue]}):t(Ge,{children:[t(sn,{onClick:()=>{ct(!1),Ln()},children:"Back to Details"}),t(sn,{onClick:Hr,disabled:Ft.isPending||qt.isPending,children:Ft.isPending||qt.isPending?"Saving...":"Move to Completed"})]})]}),!r&&t("div",{className:p.statusMsg,children:[t(be,{name:"spinner",className:p.spinner})," Loading..."]})]})]})};export{Ha as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as R,a as q,p as E,d as l,h as C,T,u as e,g as F}from"./vendor-core-DfaOB3Rn.js";import{I as a}from"./vendor-icons-DrybRNxP.js";import{a8 as j,e as U,a9 as H,t as J,B as w,h as I}from"./index-
|
|
1
|
+
import{o as R,a as q,p as E,d as l,h as C,T,u as e,g as F}from"./vendor-core-DfaOB3Rn.js";import{I as a}from"./vendor-icons-DrybRNxP.js";import{a8 as j,e as U,a9 as H,t as J,B as w,h as I}from"./index-DYanm9eZ.js";import{c as K,d as Q}from"./useTvLibrary-TnVQ2e21.js";import"./vendor-query-BBT5_sHx.js";import"./libraryInvalidation-DlwONLN-.js";const X="_container_198yg_1",Y="_heroSection_198yg_11",Z="_bannerContainer_198yg_17",ee="_banner_198yg_17",ne="_bannerOverlay_198yg_37",te="_heroContent_198yg_49",se="_posterContainer_198yg_62",ae="_poster_198yg_62",oe="_infoGlass_198yg_86",ie="_title_198yg_100",re="_quickMeta_198yg_110",le="_metaItem_198yg_118",ce="_iconStar_198yg_126",de="_iconTv_198yg_130",me="_iconType_198yg_134",_e="_genres_198yg_139",he="_genre_198yg_139",ge="_metaRow_198yg_156",ve="_metaValue_198yg_164",pe="_metaDivider_198yg_168",ue="_synopsisSection_198yg_173",ye="_sectionTitleSmall_198yg_179",ke="_synopsis_198yg_173",be="_actions_198yg_196",Ne="_watchBtn_198yg_202",Se="_watchlistBtn_198yg_226",fe="_active_198yg_250",Ce="_seasonPickerLabel_198yg_256",Te="_seasonSelect_198yg_267",we="_detailsToggleBtn_198yg_286",Ie="_expandedContent_198yg_304",Be="_detailGrid_198yg_309",De="_detailItem_198yg_315",Me="_imdbLink_198yg_333",Le="_heroSkeleton_198yg_343",Pe="_skeletonBanner_198yg_347",$e="_skeletonContent_198yg_354",Ge="_skeletonPoster_198yg_365",xe="_skeletonInfo_198yg_373",Oe="_skeletonTitle_198yg_380",Ae="_skeletonMeta_198yg_388",Ve="_skeletonDesc_198yg_396",We="_skeletonActions_198yg_404",ze="_errorState_198yg_413",Re="_matureOverlay_198yg_434",qe="_matureContent_198yg_444",n={container:X,heroSection:Y,bannerContainer:Z,banner:ee,bannerOverlay:ne,heroContent:te,posterContainer:se,poster:ae,infoGlass:oe,title:ie,quickMeta:re,metaItem:le,iconStar:ce,iconTv:de,iconType:me,genres:_e,genre:he,metaRow:ge,metaValue:ve,metaDivider:pe,synopsisSection:ue,sectionTitleSmall:ye,synopsis:ke,actions:be,watchBtn:Ne,watchlistBtn:Se,active:fe,seasonPickerLabel:Ce,seasonSelect:Te,detailsToggleBtn:we,expandedContent:Ie,detailGrid:Be,detailItem:De,imdbLink:Me,heroSkeleton:Le,skeletonBanner:Pe,skeletonContent:$e,skeletonPoster:Ge,skeletonInfo:xe,skeletonTitle:Oe,skeletonMeta:Ae,skeletonDesc:Ve,skeletonActions:We,errorState:ze,matureOverlay:Re,matureContent:qe};function Ke(){const{id:o}=R(),c=q(),[B]=E(),i=j(B.get("type")),{hasConsent:D}=U(),[t,M]=l(null),[L,_]=l(!0),[u,y]=l(""),[d,P]=l(!1),[h,$]=l(1),G=H(i,o??""),x=Number(o),{data:O}=K(t?G:void 0),g=!!O?.inLibrary,{toggle:A}=Q();C(()=>{o&&(_(!0),y(""),J.tv.details.query({type:i,id:String(o)}).then(s=>{const m={id:s.id,title:s.title||"",overview:s.overview||"",vote_average:s.vote_average,year:s.year,poster:s.poster,backdrop:s.backdrop,imdb_id:s.imdb_id||void 0,adult:s.adult,seasons:s.seasons?.map(z=>({...z,name:""})),number_of_seasons:s.number_of_seasons};M(m),_(!1)}).catch(s=>{y(s.message),_(!1)}))},[o,i]),C(()=>{document.title=t?.title?`${t.title} - dango`:"TV & Movies - dango"},[t?.title]);const V=()=>{!o||!t||c(r?I(i,o):I(i,o,h,1))},W=()=>{t&&A({tmdbId:x,mediaType:i,title:t.title,poster:t.poster,year:t.year,adult:t.adult})},r=i==="movie",v=!r,k=t?.backdrop?`https://image.tmdb.org/t/p/w1280${t.backdrop}`:"",b=t?.poster?`https://image.tmdb.org/t/p/w500${t.poster}`:"",N=T(()=>t?.genres?t.genres.map(s=>s.name).slice(0,5):[],[t?.genres]),S=T(()=>t?.seasons?t.seasons.filter(s=>s.season_number>0):[],[t?.seasons]),p=[t?.year,t?.status,v&&t?.number_of_seasons?`${t.number_of_seasons} Season${t.number_of_seasons>1?"s":""}`:null,v&&t?.number_of_episodes?`${t.number_of_episodes} Episodes`:null].filter(Boolean);if(L)return e("div",{className:n.container,children:e("div",{className:n.heroSkeleton,children:[e("div",{className:n.skeletonBanner}),e("div",{className:n.skeletonContent,children:[e("div",{className:n.skeletonPoster}),e("div",{className:n.skeletonInfo,children:[e("div",{className:n.skeletonTitle}),e("div",{className:n.skeletonMeta}),e("div",{className:n.skeletonDesc}),e("div",{className:n.skeletonActions})]})]})]})});if(u||!t)return e("div",{className:n.container,children:e("div",{className:n.errorState,children:[e(a,{name:"exclamation-triangle",size:48}),e("h2",{children:"Failed to load details"}),e("p",{children:u||"Something went wrong"}),e(w,{onClick:()=>c(-1),children:"Go Back"})]})});const f=t.adult&&!D;return e("div",{className:n.container,style:f?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:[e("div",{className:n.heroSection,children:[e("div",{className:n.bannerContainer,children:[k&&e("div",{className:n.banner,style:{backgroundImage:`url(${k})`}}),e("div",{className:n.bannerOverlay})]}),e("div",{className:n.heroContent,children:[e("div",{className:n.posterContainer,children:b&&e("img",{src:b,alt:t.title,className:n.poster,decoding:"async"})}),e("div",{className:n.infoGlass,children:[e("div",{children:[e("h1",{className:n.title,children:t.title}),e("div",{className:n.quickMeta,children:[t.vote_average!=null&&t.vote_average>0&&e("div",{className:n.metaItem,children:[e(a,{name:"star",className:n.iconStar}),e("span",{children:Number(t.vote_average).toFixed(1)})]}),e("div",{className:n.metaItem,children:[e(a,{name:"tv",className:n.iconTv}),e("span",{children:r?"Movie":"TV Show"})]}),t.vote_count!=null&&e("div",{className:n.metaItem,children:[e(a,{name:"users",className:n.iconType}),e("span",{children:[t.vote_count.toLocaleString()," votes"]})]})]}),N.length>0&&e("div",{className:n.genres,children:N.map(s=>e("span",{className:n.genre,children:s},s))})]}),p.length>0&&e("div",{className:n.metaRow,children:p.map((s,m)=>e(F.Fragment,{children:[e("span",{className:n.metaValue,children:s}),m<p.length-1&&e("span",{className:n.metaDivider,children:"·"})]},m))}),t.overview&&e("div",{className:n.synopsisSection,children:[e("h2",{className:n.sectionTitleSmall,children:"Synopsis"}),e("p",{className:n.synopsis,children:t.overview})]}),e("div",{className:n.actions,children:[e("button",{className:n.watchBtn,onClick:V,children:[e(a,{name:"play",size:14}),r?"Watch Now":`Start S${h}`]}),e("button",{className:`${n.watchlistBtn} ${g?n.active:""}`,onClick:W,children:[g?e(a,{name:"check",size:14}):e(a,{name:"plus",size:14}),g?"In Watchlist":"Add to Watchlist"]})]}),v&&S.length>1&&e("label",{className:n.seasonPickerLabel,children:[e("span",{children:"Season"}),e("select",{value:h,onChange:s=>$(parseInt(s.currentTarget.value,10)||1),className:n.seasonSelect,children:S.map(s=>e("option",{value:s.season_number,children:["Season ",s.season_number," (",s.episode_count," Episodes)"]},s.season_number))})]}),e("button",{className:n.detailsToggleBtn,onClick:()=>P(!d),children:[d?e(a,{name:"chevron-up"}):e(a,{name:"chevron-down"}),d?"Hide Details":"Show Details"]}),d&&e("div",{className:n.expandedContent,children:e("div",{className:n.detailGrid,children:[t.first_air_date&&e("div",{className:n.detailItem,children:[e("strong",{children:r?"Release Date":"First Air Date"}),e("span",{children:t.first_air_date})]}),t.last_air_date&&e("div",{className:n.detailItem,children:[e("strong",{children:"Last Air Date"}),e("span",{children:t.last_air_date})]}),t.networks&&t.networks.length>0&&e("div",{className:n.detailItem,children:[e("strong",{children:"Networks"}),e("span",{children:t.networks.map(s=>s.name).join(", ")})]}),t.created_by&&t.created_by.length>0&&e("div",{className:n.detailItem,children:[e("strong",{children:"Created By"}),e("span",{children:t.created_by.map(s=>s.name).join(", ")})]}),t.episode_run_time&&t.episode_run_time.length>0&&e("div",{className:n.detailItem,children:[e("strong",{children:"Episode Runtime"}),e("span",{children:[t.episode_run_time[0]," min"]})]}),t.imdb_id&&e("div",{className:n.detailItem,children:[e("strong",{children:"IMDb"}),e("a",{href:`https://www.imdb.com/title/${t.imdb_id}`,target:"_blank",rel:"noopener noreferrer",className:n.imdbLink,children:"View on IMDb"})]})]})})]})]})]}),f&&e("div",{className:n.matureOverlay,children:e("div",{className:n.matureContent,children:[e(a,{name:"exclamation-triangle",size:48}),e("h2",{children:"Content Warning"}),e("p",{children:"This content may contain mature themes."}),e(w,{onClick:()=>c("/"),children:"Go Back"})]})})]})}export{Ke as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as n,h as b,T as k,u as T}from"./vendor-core-DfaOB3Rn.js";import{a9 as _,t as m,j as w,h as I,k as P}from"./index-
|
|
1
|
+
import{d as n,h as b,T as k,u as T}from"./vendor-core-DfaOB3Rn.js";import{a9 as _,t as m,j as w,h as I,k as P}from"./index-DYanm9eZ.js";import{d as D}from"./useTvLibrary-TnVQ2e21.js";import{a as W}from"./MediaCard-l2gAJctz.js";const S=({item:e,anchorRect:l,onMouseEnter:i,onMouseLeave:c,onRequestClose:p})=>{const[a,u]=n(null),[d,r]=n(!0),{toggle:v,bookmarkedIds:g}=D(),y=_(e.type,e.id),f=g.has(y);b(()=>{let o=!1;return r(!0),m.tv.details.query({type:e.type,id:String(e.id)}).then(s=>{o||(u({overview:s.overview,vote_average:s.vote_average,number_of_seasons:s.number_of_seasons}),r(!1))}).catch(()=>{o||r(!1)}),()=>{o=!0}},[e.id,e.type]);const h=k(()=>a?.genres?a.genres.slice(0,4).map(o=>o.name):[],[a?.genres]),t=[];return a?.vote_average!=null&&a.vote_average>0&&t.push({icon:"star",label:Number(a.vote_average).toFixed(1),accent:!0}),t.push({icon:"tv",label:e.type==="tv"?"TV Show":"Movie"}),e.year&&t.push({label:e.year}),a?.status&&t.push({label:a.status}),T(W,{anchorRect:l,title:e.title,loading:d,meta:t,genres:h,synopsis:P(a?.overview,200),primaryAction:{to:I(e.type,e.id),label:"Watch now",icon:"play"},secondaryAction:{to:w(e.type,e.id),label:"Details",icon:"info-circle"},bookmarked:f,onToggleBookmark:()=>v({tmdbId:e.id,mediaType:e.type,title:e.title,poster:e.image,year:e.year}),onMouseEnter:i,onMouseLeave:c,onRequestClose:p})};export{S as T};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as I,p as ae,A as re,d as o,T as Y,q as M,u as t}from"./vendor-core-DfaOB3Rn.js";import{I as h}from"./vendor-icons-DrybRNxP.js";import{P as D}from"./MediaCard-
|
|
1
|
+
import{h as I,p as ae,A as re,d as o,T as Y,q as M,u as t}from"./vendor-core-DfaOB3Rn.js";import{I as h}from"./vendor-icons-DrybRNxP.js";import{P as D}from"./MediaCard-l2gAJctz.js";import{a as ne,T as se}from"./useTv-BGXZmuV8.js";import{S as le}from"./SkeletonGrid-nW7P1jQU.js";import{u as ie,T as W,M as Q,a5 as oe,B as x}from"./index-DYanm9eZ.js";import{E as ce}from"./ErrorMessage-DAxegITP.js";import{s as r}from"./Search.module-C_qwCdHS.js";import"./vendor-ui-3qrARCPr.js";import"./useIsMobile-Dvx1uJ82.js";import"./MatureConsentModal-LTZSG_Kx.js";import"./TvPopup-BS4iiQMd.js";import"./useTvLibrary-TnVQ2e21.js";import"./vendor-query-BBT5_sHx.js";import"./libraryInvalidation-DlwONLN-.js";const de=[{value:"multi",label:"All"},{value:"tv",label:"TV Shows"},{value:"movie",label:"Movies"}],ue=[{value:"popularity.desc",label:"Popularity"},{value:"vote_average.desc",label:"Top Rated"},{value:"primary_release_date.desc",label:"Newest"},{value:"primary_release_date.asc",label:"Oldest"},{value:"vote_count.desc",label:"Most Voted"}],O=new Date().getFullYear(),me=[{value:"ALL",label:"All Years"},...Array.from({length:O-1980+1},(l,m)=>({value:String(O-m),label:String(O-m)}))];function _e(){I(()=>{document.title="Search TV & Movies - dango"},[]);const[l,m]=ae(),{lowEndMode:K}=ie(),C=re(null),[g,H]=o(l.get("q")||""),[p,U]=o(l.get("q")||""),[u,v]=o(parseInt(l.get("page")||"1",10)||1),[i,J]=o(l.get("type")||"multi"),[$,k]=o(l.get("genre")||""),[y,B]=o(l.get("year")||"ALL"),[f,E]=o(l.get("sort_by")||"popularity.desc"),[b,X]=o(!1),[c,N]=o(()=>{const e={},a=l.get("genre")||"";return a&&(e[a]="include"),e}),P=Y(()=>{if(i==="tv")return Object.entries(W).map(([a,n])=>({id:a,name:n}));if(i==="movie")return Object.entries(Q).map(([a,n])=>({id:a,name:n}));const e=new Map;for(const[a,n]of Object.entries(W))e.set(a,n);for(const[a,n]of Object.entries(Q))e.set(a,n);return Array.from(e.entries()).map(([a,n])=>({id:a,name:n}))},[i]),S=Y(()=>Object.entries(c).filter(([,a])=>a==="include").map(([a])=>a).join(","),[c]),{data:L,isLoading:w,isError:Z,error:ee}=ne({query:p,type:i,genre:S,year:y,sort_by:f,page:u}),T=L?.results||[],_=L?.total_pages||0,j=L?.total_results||0,R=u<Math.min(_,500),d=M((e={})=>{const a=new URLSearchParams,n=e.q!==void 0?e.q:p,s=e.type!==void 0?e.type:i,G=e.year!==void 0?e.year:y,V=e.sort!==void 0?e.sort:f,F=e.page!==void 0?e.page:String(u),z=e.genre!==void 0?e.genre:S;n.trim()&&a.set("q",n.trim()),s!=="multi"&&a.set("type",s),z&&a.set("genre",z),G!=="ALL"&&a.set("year",G),V!=="popularity.desc"&&a.set("sort_by",V),F!=="1"&&a.set("page",F),m(a,{replace:!0})},[p,i,y,f,u,S,m]),A=M(()=>{oe(),v(1),U(g),d({q:g,page:"1"}),window.scrollTo({top:0,behavior:"smooth"})},[g,d]),q=M(e=>{if(v(e),d({page:String(e)}),C.current){const a=C.current.getBoundingClientRect().top+window.scrollY-100;window.scrollTo({top:a,behavior:"smooth"})}},[d]),te=M(e=>{N(a=>{const n=a[e],s={...a};return n==="include"?s[e]="exclude":n==="exclude"?delete s[e]:s[e]="include",s}),v(1)},[]);return I(()=>{const a=Object.entries(c).filter(([,n])=>n==="include").map(([n])=>n).join(",");a!==$&&(k(a),d({genre:a,page:"1"}))},[c,$,k,d]),t("div",{className:"page-container",children:[t("div",{className:r.header,children:[t("h1",{className:r.pageTitle,children:"Search TV & Movies"}),t("p",{className:r.pageSubtitle,children:"Discover trending shows, movies, and more powered by TMDB"})]}),t("div",{className:r.filterContainer,children:[t("div",{className:r.searchBarWrapper,children:[t("div",{className:r.inputIconWrapper,children:[t(h,{name:"search",className:r.searchIcon}),t("input",{type:"text","data-virtual-keyboard":"true",className:r.searchInput,placeholder:"Search titles...",value:g,onInput:e=>H(e.currentTarget.value),onKeyDown:e=>e.key==="Enter"&&A()})]}),t("div",{className:r.searchActions,children:[t("select",{value:i,onChange:e=>{J(e.currentTarget.value),N({})},className:r.providerSelect,"aria-label":"Media type",children:de.map(e=>t("option",{value:e.value,children:e.label},e.value))}),t(x,{onClick:A,className:r.searchBtn,children:"Search"}),t("button",{className:`${r.filterToggleBtn} ${b?r.active:""}`,onClick:()=>X(!b),children:[t(h,{name:"filter",size:14}),t("span",{children:"Filters"}),b?t(h,{name:"chevron-up",size:12}):t(h,{name:"chevron-down",size:12})]})]})]}),t("div",{className:`${r.advancedFilters} ${b?r.show:""}`,children:[t("div",{className:r.filterDivider}),t("div",{className:r.filterGrid,children:[t("div",{className:r.filterItem,children:[t("label",{children:"Sort By"}),t("select",{value:f,onChange:e=>E(e.currentTarget.value),children:ue.map(e=>t("option",{value:e.value,children:e.label},e.value))})]}),t("div",{className:r.filterItem,children:[t("label",{children:"Year"}),t("select",{value:y,onChange:e=>B(e.currentTarget.value),children:me.map(e=>t("option",{value:e.value,children:e.label},e.value))})]})]}),P.length>0&&t("div",{className:r.genreSection,children:[t("label",{className:r.genreLabel,children:"Genres"}),t("div",{className:r.genreContainer,children:P.map(e=>t("button",{className:`${r.genreButton} ${r[c[e.id]||""]}`,onClick:()=>te(e.id),children:e.name},e.id))})]}),t("div",{className:r.filterActions,children:[t(x,{variant:"secondary",onClick:()=>{N({}),B("ALL"),E("popularity.desc"),v(1),d({genre:"",year:"ALL",sort:"popularity.desc",page:"1"})},children:"Reset All"}),t(x,{onClick:A,className:r.searchBtn,children:"Apply Filters"})]})]})]}),Z&&t(ce,{message:ee?.message||"Search failed"}),Object.keys(c).length>0&&t("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginBottom:"1.5rem"},children:[t("span",{style:{fontSize:"0.8rem",color:"var(--text-muted)",fontWeight:600},children:"Active Filters:"}),Object.entries(c).map(([e,a])=>{const n=P.find(s=>s.id===e)?.name||e;return t("span",{className:`badge ${a==="include"?"badge-primary":"badge-danger"}`,style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[a==="include"?`+ ${n}`:`- ${n}`,t("button",{onClick:()=>{const s={...c};delete s[e],N(s)},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]},e)})]}),t("div",{className:r.resultsHeader,ref:C,children:[t("h2",{className:r.resultsTitle,children:[p?`Results for "${p}"`:S?"Browsing genres":i==="tv"?"Popular TV Shows":i==="movie"?"Popular Movies":"Trending",j>0&&t("span",{style:{fontWeight:400,color:"var(--text-tertiary)",fontSize:"0.85em",marginLeft:"0.5em"},children:["(",j.toLocaleString(),")"]})]}),T.length>0&&t(D,{page:u,totalPages:Math.max(1,Math.min(_,500)),canGoNext:R,onChange:q,isLoading:w})]}),t("div",{className:`${r.resultsGrid} ${K?r.lowEnd:""}`,children:w?t(le,{}):T.map(e=>t(se,{item:{id:e.id,title:e.title,year:e.year,type:e.type,image:e.image,vote_average:e.vote_average,adult:e.adult}},`${e.type}-${e.id}`))}),!w&&T.length===0&&t("div",{className:r.noResults,children:[t(h,{name:"search",size:48,className:r.noResultsIcon}),t("h3",{children:"No results found"}),t("p",{children:"Try adjusting your search or filters to find what you're looking for."})]}),T.length>0&&t("div",{className:r.bottomPagination,children:t(D,{page:u,totalPages:Math.max(1,Math.min(_,500)),canGoNext:R,onChange:q,isLoading:w,variant:"labeled"})})]})}export{_e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as $,d as f,h as L,T as U,u as d}from"./vendor-core-DfaOB3Rn.js";import{M as x}from"./MediaCard-
|
|
1
|
+
import{o as $,d as f,h as L,T as U,u as d}from"./vendor-core-DfaOB3Rn.js";import{M as x}from"./MediaCard-l2gAJctz.js";import{L as F}from"./LibraryListPage-AGyVc7pR.js";import{R as N}from"./ResetProgressModal-DLs9yqI-.js";import{T as _}from"./TvPopup-BS4iiQMd.js";import{h as y,g as u,i as R}from"./index-DYanm9eZ.js";import{j as K,u as O,a as Q,b as Y,f as j,k as q,l as z,m as G,T as I}from"./useTvLibrary-TnVQ2e21.js";import"./vendor-icons-DrybRNxP.js";import"./vendor-ui-3qrARCPr.js";import"./useIsMobile-Dvx1uJ82.js";import"./MatureConsentModal-LTZSG_Kx.js";import"./SkeletonGrid-nW7P1jQU.js";import"./ErrorMessage-DAxegITP.js";import"./LibraryListPage.module-r6k9nyT9.js";import"./vendor-query-BBT5_sHx.js";import"./libraryInvalidation-DlwONLN-.js";const Z=["All","Continue Watching",...I],S=24;function ct(){const{filter:l="All"}=$(),[c,m]=f(1),[s,v]=f(null);L(()=>{document.title="TV Watchlist - dango"},[]),L(()=>{m(1)},[l]);const o=l==="Continue Watching",r=K(o?"All":l,c,S),i=O(100),T=Q(),P=Y(),k=j(),w=q(),C=z(),B=G(),M=U(()=>o?(i.data?.data??[]).map(t=>{const a=t.currentTime??0,e=t.duration??0,g=t.season??1,h=t.episode??1,n=t.mediaType==="movie",p=n?"Movie":`S${g} E${h}`,b=t.completed===1||e>0&&a>=e*.8;return{key:t.id,libId:t.id,tmdbId:t.tmdbId??0,mediaType:t.mediaType,title:t.title||"",poster:t.poster||"",year:t.year,adult:R({adult:t.adult===1}),status:t.watchlistStatus??"",badge:p,progressPercent:b?100:e>0?a/e*100:0,progressLabel:e>0?b?"Watched":n?`${u(a)} / ${u(e)}`:`${p} · ${u(a)} / ${u(e)}`:p,watchTarget:y(t.mediaType,t.tmdbId??0,n?void 0:g,n?void 0:h)}}):(r.data?.data??[]).map(t=>({key:t.id,libId:t.id,tmdbId:t.tmdbId,mediaType:t.mediaType,title:t.title,poster:t.poster||"",year:t.year,adult:R({adult:t.adult===1}),status:t.status,badge:t.lastSeason&&t.lastEpisode?`S${t.lastSeason} E${t.lastEpisode}`:void 0,progressPercent:void 0,progressLabel:void 0,watchTarget:y(t.mediaType,t.tmdbId,t.lastSeason??void 0,t.lastEpisode??void 0)})),[o,i.data,r.data]),W=o?i.data?.total??0:r.data?.total??0,E=o?i.isLoading:r.isLoading,A=o?i.error:r.error,V=t=>{s&&(P.mutate({mediaId:s.libId}),t&&T.mutate(s.libId))};return d(F,{headerTitle:"My TV Watchlist",headerSubtitle:"Track and manage your movies and shows",filters:Z,filterBy:l,filterBasePath:"/tv-watchlist",continueFilter:"Continue Watching",statusOptions:[...I],entries:M,total:W,isLoading:E,error:A,page:c,pageSize:S,onPageChange:m,emptyTitle:"Your TV watchlist is looking a bit empty",emptyFilteredText:"No titles match this filter.",emptyAllText:"Let's find something to watch!",browseLabel:"Browse TV & Movies",browseTarget:"/tv",removeListLabel:"Remove from TV Watchlist",listNoun:"TV watchlist",skipConfirmKey:"tvSkipRemoveConfirmation",onBulkStatus:(t,a)=>w.mutate({ids:t,status:a}),onBulkRemove:t=>{o?B.mutate(t):C.mutate(t)},onStatusChange:(t,a)=>k.mutate({id:t,status:a}),onRemoveItem:t=>T.mutate(t),renderCard:t=>d(x,{item:{id:t.libId,title:t.title,thumbnail:t.poster,typeBadge:t.mediaType==="movie"?"Movie":"TV",chapterBadge:t.badge??null,isAdult:t.adult},linkTo:t.watchTarget,hoverIcon:"play",progress:t.progressPercent!==void 0&&t.progressLabel?{percent:t.progressPercent,label:t.progressLabel}:void 0,showProgress:o,metaRow:t.year?d("span",{style:{opacity:.75},children:t.year}):void 0,onRemove:o?()=>v(t):void 0,renderPopup:(a,e)=>d(_,{item:{id:t.tmdbId??0,title:t.title||"",year:t.year||"",type:t.mediaType||"tv",image:t.poster||""},anchorRect:a,onMouseEnter:e.onMouseEnter,onMouseLeave:e.onMouseLeave,onRequestClose:e.close})}),modals:d(N,{isOpen:!!s,itemName:s?.title,progressKind:"watch",listLabel:"my TV watchlist",onClose:()=>{v(null)},onConfirm:V})})}export{ct as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as _,A as E,h as f,q as N,$ as D,u as o}from"./vendor-core-DfaOB3Rn.js";import{p as x}from"./index-
|
|
1
|
+
import{d as _,A as E,h as f,q as N,$ as D,u as o}from"./vendor-core-DfaOB3Rn.js";import{p as x}from"./index-DYanm9eZ.js";import"./vendor-query-BBT5_sHx.js";import"./vendor-icons-DrybRNxP.js";const O="_keyboard_b2w6l_1",R="_topBar_b2w6l_18",T="_dragHandle_b2w6l_27",q="_grip_b2w6l_38",U="_topButton_b2w6l_46",V="_key_b2w6l_1",W="_closeButton_b2w6l_77",X="_keys_b2w6l_83",Y="_row_b2w6l_90",j="_wideKey_b2w6l_106",A="_spaceKey_b2w6l_110",F="_spaceIcon_b2w6l_118",J="_activeKey_b2w6l_126",t={keyboard:O,topBar:R,dragHandle:T,grip:q,topButton:U,key:V,closeButton:W,keys:X,row:Y,wideKey:j,spaceKey:A,spaceIcon:F,activeKey:J},$="virtual-keyboard-state",b=["small","medium","large"],P=["1","2","3","4","5","6","7","8","9","0"],G=["!","@","#","$","%","^","&","*","(",")"],Q=[["q","w","e","r","t","y","u","i","o","p"],["a","s","d","f","g","h","j","k","l"],["z","x","c","v","b","n","m"]],Z=()=>{const i={position:{x:Math.max(12,window.innerWidth-690),y:Math.max(90,window.innerHeight-330)},size:"medium"};try{const c=x.getItem($);if(!c)return i;const s=JSON.parse(c);return{position:s.position&&Number.isFinite(s.position.x)&&Number.isFinite(s.position.y)?s.position:i.position,size:s.size&&b.includes(s.size)?s.size:i.size}}catch{return i}},K=(i,c)=>{const s=c?.offsetWidth??650,r=c?.offsetHeight??270;return{x:Math.min(Math.max(8,i.x),Math.max(8,window.innerWidth-s-8)),y:Math.min(Math.max(8,i.y),Math.max(8,window.innerHeight-r-8))}};function se({activeInputRef:i,isVisible:c,onClose:s}){const[{position:r,size:l},w]=_(Z),[k,z]=_(!1),[g,S]=_(!1),h=E(null),u=E(null);f(()=>{x.setItem($,JSON.stringify({position:r,size:l}))},[r,l]),f(()=>{const e=()=>{w(n=>({...n,position:K(n.position,h.current)}))};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[]);const v=()=>i.current&&document.contains(i.current)?i.current:document.activeElement instanceof HTMLInputElement?document.activeElement:null,d=e=>{const n=v();if(!n)return;const a=n.selectionStart??n.value.length,y=n.selectionEnd??n.value.length;n.setRangeText(e,a,y,"end"),n.dispatchEvent(new Event("input",{bubbles:!0})),n.focus()},M=()=>{const e=v();if(!e)return;const n=e.selectionStart??e.value.length,a=e.selectionEnd??e.value.length;n===a&&n===0||(e.setRangeText("",n===a?n-1:n,a,"end"),e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus())},B=()=>{const e=v();if(!e){s();return}const n=e.form;n?n.requestSubmit():e.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter",bubbles:!0})),s()},C=e=>{e.preventDefault()},p=N(e=>{if(!u.current)return;const n={x:e.clientX-u.current.x,y:e.clientY-u.current.y};w(a=>({...a,position:K(n,h.current)}))},[]),m=N(()=>{u.current=null,window.removeEventListener("mousemove",p),window.removeEventListener("mouseup",m)},[p]),L=e=>{e.preventDefault(),u.current={x:e.clientX-r.x,y:e.clientY-r.y},window.addEventListener("mousemove",p),window.addEventListener("mouseup",m)};if(f(()=>()=>{window.removeEventListener("mousemove",p),window.removeEventListener("mouseup",m)},[p,m]),!c)return null;const H=g?G:P,I=()=>{w(e=>{const n=b[(b.indexOf(e.size)+1)%b.length];return{...e,size:n}})};return D(o("div",{ref:h,className:`${t.keyboard} ${t[l]}`,style:{left:r.x,top:r.y},onMouseDown:C,"data-virtual-keyboard-root":!0,children:[o("div",{className:t.topBar,children:[o("div",{className:t.dragHandle,onMouseDown:L,"aria-label":"Move virtual keyboard",children:[o("span",{className:t.grip,"aria-hidden":"true"}),o("span",{children:"Virtual Keyboard"})]}),o("button",{type:"button",className:t.topButton,onClick:I,children:["Size: ",l[0].toUpperCase()+l.slice(1)]}),o("button",{type:"button",className:`${t.topButton} ${t.closeButton}`,onClick:s,children:"X"})]}),o("div",{className:t.keys,children:[o("div",{className:t.row,children:[H.map(e=>o("button",{type:"button",className:t.key,onClick:()=>d(e),children:e},e)),o("button",{type:"button",className:`${t.key} ${t.wideKey}`,onClick:M,"aria-label":"Backspace",children:"⟵"})]}),Q.map((e,n)=>o("div",{className:t.row,children:[e.map(a=>{const y=k?a.toUpperCase():a;return o("button",{type:"button",className:t.key,onClick:()=>d(y),children:y},a)}),n===1&&o("button",{type:"button",className:`${t.key} ${t.wideKey}`,onClick:B,children:"Enter"})]},e.join(""))),o("div",{className:t.row,children:[o("button",{type:"button",className:`${t.key} ${t.wideKey} ${g?t.activeKey:""}`,onClick:()=>S(e=>!e),children:"Ctrl"}),o("button",{type:"button",className:`${t.key} ${t.wideKey} ${k?t.activeKey:""}`,onClick:()=>z(e=>!e),children:"Shift"}),o("button",{type:"button",className:`${t.key} ${t.spaceKey}`,onClick:()=>d(" "),"aria-label":"Space",children:o("span",{className:t.spaceIcon})}),o("button",{type:"button",className:t.key,onClick:()=>d("."),children:"."}),o("button",{type:"button",className:t.key,onClick:()=>d("-"),children:"-"})]})]})]}),document.body)}export{se as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as h,d as s,u as e}from"./vendor-core-DfaOB3Rn.js";import{a2 as d,B as m}from"./index-
|
|
1
|
+
import{c as h,d as s,u as e}from"./vendor-core-DfaOB3Rn.js";import{a2 as d,B as m}from"./index-DYanm9eZ.js";import{W as u,s as p,a as g}from"./WatchAlongPanel-R7Nd5MXr.js";import"./vendor-query-BBT5_sHx.js";import"./vendor-icons-DrybRNxP.js";function b(){const o=d(),c=h(),[t,l]=s(c.hash.slice(1)),[n,a]=s("");return e("div",{style:{maxWidth:640,margin:"2rem auto",padding:"0 1rem"},children:[e("h1",{children:"Watch along"}),e("p",{children:"Watch with friends across the internet. The host chooses the episode, provider, and source, and controls playback. Your dango streams your own video."}),o.session&&e(u,{}),!o.session&&e("form",{className:p.panel,onSubmit:r=>{r.preventDefault();try{o.join(t),a("")}catch(i){a(i instanceof Error?i.message:"Could not join room")}},children:[e(g,{}),e("label",{htmlFor:"watch-invite",children:"Invite link or room code"}),e("input",{id:"watch-invite",value:t,onChange:r=>l(r.currentTarget.value),required:!0,autoComplete:"off"}),e("p",{children:"Joining shares your connection and playback readiness with the room service. Start a room from an episode using a direct HLS source."}),e(m,{type:"submit",disabled:!o.workerUrl,style:{marginTop:"1rem"},children:"Join room"}),!o.workerUrl&&e("p",{children:"Watch along is unavailable. The server needs a watch-along service URL."}),n&&e("p",{role:"alert",children:n})]})]})}export{b as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as l,u as s,L as f}from"./vendor-core-DfaOB3Rn.js";import{a2 as m,B as r}from"./index-
|
|
1
|
+
import{d as l,u as s,L as f}from"./vendor-core-DfaOB3Rn.js";import{a2 as m,B as r}from"./index-DYanm9eZ.js";const _="_panel_n8xyd_1",x="_heading_n8xyd_10",C="_actions_n8xyd_11",b="_members_n8xyd_12",k="_name_n8xyd_19",a={panel:_,heading:x,actions:C,members:b,name:k};function N(){const n=m();return s("label",{className:a.name,children:["Display name",s("input",{value:n.displayName,onChange:t=>n.setDisplayName(t.currentTarget.value),maxLength:32,placeholder:"Your name (optional)",autoComplete:"nickname"}),s("small",{children:"Remembered for this profile on this browser."})]})}function W({playback:n,onCreate:t,needsPlayback:u,onEnablePlayback:g}){const e=m(),[p,c]=l(!1),[h,i]=l(""),[y,v]=l(!1),d=e.session?`${e.workerUrl}/join#${e.session.id}.${e.session.guestToken}`:"";return s("section",{className:a.panel,"aria-label":"Watch along",children:[s("div",{className:a.heading,children:[s("strong",{children:["Watch along",e.session?e.session.host?" · You are hosting":" · Following host":""]}),e.session?s("div",{className:a.actions,children:[s(r,{size:"sm",variant:"secondary",onClick:async()=>{v(!0);try{await navigator.clipboard.writeText(d),i("Invite copied")}catch{i("Copy the invite below")}},children:"Copy invite"}),s(r,{size:"sm",variant:"ghost",onClick:e.leave,children:e.session.host?"End room":"Leave room"})]}):s("div",{className:a.actions,children:[t&&s(r,{size:"sm",loading:p,disabled:!n||!e.workerUrl,onClick:async()=>{if(n){c(!0),i("");try{t(),await e.create({...n,playing:!1})}catch(o){i(o instanceof Error?o.message:"Could not create room")}finally{c(!1)}}},children:"Create room"}),s(f,{to:"/watch-along",children:"Join a room"})]})]}),s(N,{}),!e.session&&s("p",{children:"Direct HLS only. Each viewer needs their own dango. Room controls use the shared watch-along service."}),e.session&&s("p",{children:[e.connected?e.room?.hostOnline?"Connected":"Host disconnected. Room closes after 60 seconds unless they reconnect":"Connecting…"," ","· Provider and source follow the host. Volume and subtitles stay yours."]}),e.room&&s("p",{children:[e.session?.host&&"End the room when you are finished watching. ","Rooms automatically close six hours after creation. This room expires at"," ",s("time",{dateTime:new Date(e.room.expiresAt).toISOString(),children:new Date(e.room.expiresAt).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}),", even if playback is still active."]}),e.room&&s("ul",{className:a.members,children:e.room.members.map((o,w)=>s("li",{children:[o.name||(o.host?"Host":`Guest ${w+1}`),o.name&&o.host?" (host)":"",o.id===e.selfId?" (you)":"",": ",o.status]},o.id))}),u&&s(r,{size:"sm",onClick:g,children:"Enable playback"}),y&&e.session&&s("input",{"aria-label":"Room invite",readOnly:!0,value:d,onFocus:o=>o.currentTarget.select()}),(e.error||h)&&s("p",{role:"status",children:e.error||h})]})}export{W,N as a,a as s};
|