@serifpersia/dango 3.3.4 → 3.3.6

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.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/client/dist/assets/AnimeCard-OKU7LaSN.js +1 -0
  3. package/client/dist/assets/{AnimeInfo-0huPAq0O.js → AnimeInfo-BCyLw0yz.js} +1 -1
  4. package/client/dist/assets/{AnimeInfoPage-Dqr5QH6R.js → AnimeInfoPage-BZWl-TJY.js} +2 -2
  5. package/client/dist/assets/{Asmr-B6ZiqkmU.js → Asmr-4S6uoevp.js} +1 -1
  6. package/client/dist/assets/{AsmrResetProgressModal-Cqsoo3XC.js → AsmrResetProgressModal-C8i6weqW.js} +1 -1
  7. package/client/dist/assets/{AvSyncCalibrator-C1_iBSyL.css → AvSyncCalibrator-BPa6KaGC.css} +1 -1
  8. package/client/dist/assets/AvSyncCalibrator-oK6LlG61.js +10 -0
  9. package/client/dist/assets/Home-CQ4Ikeja.js +1 -0
  10. package/client/dist/assets/{Insights-ZlgPrzGD.js → Insights-DiAo0UAc.js} +1 -1
  11. package/client/dist/assets/{LibraryListPage-CCiee-Ot.js → LibraryListPage-B0MDTnEc.js} +1 -1
  12. package/client/dist/assets/{ListeningList-ctAz_6Zi.js → ListeningList-Dxkhy6E2.js} +1 -1
  13. package/client/dist/assets/{Manga-BI9WMTx5.js → Manga-pJEpcUpo.js} +1 -1
  14. package/client/dist/assets/{MangaInfoPage-DcrEr7Sk.js → MangaInfoPage-BEQsjTHH.js} +1 -1
  15. package/client/dist/assets/{MangaReadPage-SYg63m48.js → MangaReadPage-C0WAtK-1.js} +1 -1
  16. package/client/dist/assets/{MangaResetProgressModal-DX-1PS4h.js → MangaResetProgressModal-WjKH_G_f.js} +1 -1
  17. package/client/dist/assets/{Mature-Dqh_9SA3.js → Mature-Ckx99wFj.js} +1 -1
  18. package/client/dist/assets/{MediaCard-Be1ST9oj.js → MediaCard-DszKDA4s.js} +1 -1
  19. package/client/dist/assets/{Music-zsPwT8_5.js → Music-CU6TBHF5.js} +1 -1
  20. package/client/dist/assets/{OptionListMenu-Drc_vybW.js → OptionListMenu-CkK2BvEz.js} +1 -1
  21. package/client/dist/assets/Player-C3yWQkXb.js +56 -0
  22. package/client/dist/assets/{PlayerSettings-Cwoji-P7.js → PlayerSettings-CBdTzo0E.js} +1 -1
  23. package/client/dist/assets/{QueueOptionsButton-B6BMq66e.js → QueueOptionsButton-DKWi-9kd.js} +1 -1
  24. package/client/dist/assets/{QueueRail-VxpUDBSm.js → QueueRail-DAcIex5B.js} +1 -1
  25. package/client/dist/assets/{Radio-B2Q_Egj7.js → Radio-BhTsgGGd.js} +1 -1
  26. package/client/dist/assets/{ReadingList-O0QPwXu7.js → ReadingList-BLnkwB--.js} +1 -1
  27. package/client/dist/assets/{ResetProgressModal-CR_ovLAu.js → ResetProgressModal-8mcLXaAb.js} +1 -1
  28. package/client/dist/assets/{Search-C8e2nlDD.js → Search-DxX021dj.js} +1 -1
  29. package/client/dist/assets/{Settings-BgPWBl2V.js → Settings-bSA7BG7h.js} +1 -1
  30. package/client/dist/assets/{SkeletonGrid-CtHKKMLj.js → SkeletonGrid-Du10CNfq.js} +1 -1
  31. package/client/dist/assets/{Trackers-Bfoiyuzy.js → Trackers-BXSONaRD.js} +1 -1
  32. package/client/dist/assets/Tv-C2SWcVzN.css +1 -0
  33. package/client/dist/assets/Tv-DJTbg4VW.js +4 -0
  34. package/client/dist/assets/{TvInfo-D_scgw_h.js → TvInfo-Z0c1Wh3i.js} +1 -1
  35. package/client/dist/assets/{TvPopup-YTI7dEbJ.js → TvPopup-CP41CncZ.js} +1 -1
  36. package/client/dist/assets/{TvSearch-CxU33UOf.js → TvSearch-BlqTQYJa.js} +1 -1
  37. package/client/dist/assets/TvWatchlist-COCWPkgh.js +1 -0
  38. package/client/dist/assets/{Watchlist-P6YMZUdF.js → Watchlist-BHLshSPX.js} +1 -1
  39. package/client/dist/assets/{hls-C4cG9wQw.js → hls-B_yo8-yR.js} +1 -1
  40. package/client/dist/assets/index-lo-bz7f2.js +178 -0
  41. package/client/dist/assets/{useAnimeInfoData-DeuwDSnI.js → useAnimeInfoData-CbNnHRj8.js} +1 -1
  42. package/client/dist/assets/{useAsmr-CbMVRjmV.js → useAsmr-BEcgHwxg.js} +1 -1
  43. package/client/dist/assets/{useAsmrPopup-D91Q3CBg.js → useAsmrPopup-BXD3y2m1.js} +1 -1
  44. package/client/dist/assets/{useMangaLibrary-BPvFb1lU.js → useMangaLibrary-BXhgN-dl.js} +1 -1
  45. package/client/dist/assets/{useMangaPopup-BOL2mQJs.js → useMangaPopup-BvgtZ53s.js} +1 -1
  46. package/client/dist/assets/{useProviders-BsRGONMA.js → useProviders-xlftutIo.js} +1 -1
  47. package/client/dist/assets/{useTv-D37MfTHA.js → useTv-DTqrJEWp.js} +1 -1
  48. package/client/dist/assets/{useTvLibrary-Cwxgy_Bg.js → useTvLibrary-BHeWSd1F.js} +1 -1
  49. package/client/dist/index.html +1 -1
  50. package/package.json +2 -2
  51. package/server/dist/controllers/tv-library.controller.js +9 -5
  52. package/server/dist/repositories/tv.repository.js +10 -8
  53. package/server/dist/sync.js +19 -1
  54. package/server/package.json +1 -1
  55. package/client/dist/assets/AnimeCard-B5A20jAI.js +0 -1
  56. package/client/dist/assets/AvSyncCalibrator-C8ZoIwMY.js +0 -10
  57. package/client/dist/assets/Home-thJhPfs1.js +0 -1
  58. package/client/dist/assets/Player-BEtAYps2.js +0 -56
  59. package/client/dist/assets/Tv-Ca0fCdko.js +0 -3
  60. package/client/dist/assets/Tv-CuEl3Iol.css +0 -1
  61. package/client/dist/assets/TvWatchlist-B4X1fWEH.js +0 -1
  62. package/client/dist/assets/index-IZgh1beL.js +0 -178
@@ -1 +1 @@
1
- import{h as k,o as pe,a as ge,d as o,A as me,g as ve,u as a}from"./vendor-core-8R2fFbyN.js";import{I as d}from"./vendor-icons-CDMuNDeL.js";import{A as fe}from"./AnimeCard-B5A20jAI.js";import{S as be}from"./SkeletonGrid-CtHKKMLj.js";import{u as Le,r as Ae,P as ee,B as w,Q as ye}from"./index-IZgh1beL.js";import{E as Se}from"./ErrorMessage-z4f4WGgP.js";import{s as t}from"./Search.module-CMEai-B-.js";import"./useAnimeInfoData-DeuwDSnI.js";import"./vendor-query-BXRECSI6.js";import"./QueueOptionsButton-B6BMq66e.js";import"./vendor-ui-CUDCvRS_.js";import"./MediaCard-Be1ST9oj.js";import"./useIsMobile-Dm_b6Ob3.js";const Ne=[{value:"ALL",label:"All Types"},{value:"TV",label:"TV Series"},{value:"Movie",label:"Movie"},{value:"OVA",label:"OVA"},{value:"ONA",label:"ONA"},{value:"TV_SHORT",label:"TV Short"},{value:"SPECIAL",label:"Special"},{value:"ADULT",label:"Mature"}],Ce=[{value:"ALL",label:"All Seasons"},{value:"Winter",label:"Winter"},{value:"Spring",label:"Spring"},{value:"Summer",label:"Summer"},{value:"Fall",label:"Fall"}],Te=[{value:"ALL",label:"All Countries"},{value:"JP",label:"Japan"},{value:"CN",label:"China"}],Ee=[{value:"POPULARITY_DESC",label:"Popularity"},{value:"TRENDING_DESC",label:"Trending"},{value:"SCORE_DESC",label:"Score"},{value:"START_DATE_DESC",label:"Newest"},{value:"START_DATE_ASC",label:"Oldest"},{value:"EPISODES_DESC",label:"Most Episodes"},{value:"FAVOURITES_DESC",label:"Favourites"}],Ie=[{value:"RELEASING",label:"Currently Airing"},{value:"FINISHED",label:"Finished"},{value:"NOT_YET_RELEASED",label:"Not Yet Released"},{value:"CANCELLED",label:"Cancelled"},{value:"HIATUS",label:"Hiatus"}];function Me(){k(()=>{document.title="Search - dango"},[]);const[r,ae]=pe(),te=ge(),[m,B]=o(r.get("query")||""),[c,_]=o(parseInt(r.get("page")||"1")),[h,A]=o(r.get("type")||"ALL"),[v,y]=o(r.get("season")||"ALL"),[f,S]=o(r.get("year")||"ALL"),[G,I]=o(r.get("country")||"ALL"),[Y,le]=o(r.get("provider")||"anilist"),[U,P]=o(r.get("sortBy")||"POPULARITY_DESC"),[F,x]=o(r.get("status")||""),[N,ne]=o(!1),[re,M]=o(null);k(()=>{let e=!1;return fetch("/api/anilist-status").then(n=>n.json()).then(n=>{e||M(n.available)}).catch(()=>{e||M(!0)}),()=>{e=!0}},[]);const{lowEndMode:se}=Le(),D=me(null),{data:ie}=Ae(),$=ie?.genres||[],[b,C]=o(()=>{const e={},n=r.get("genres")?.split(",").map(l=>l.trim()).filter(Boolean)||[],s=r.get("excludeGenres")?.split(",").map(l=>l.trim()).filter(Boolean)||[];return n.forEach(l=>l&&(e[l]="include")),s.forEach(l=>l&&(e[l]="exclude")),e}),z=new URLSearchParams(r);z.delete("page");const j=z.toString(),{data:L=[],isLoading:g,isError:oe,error:ce}=ee(j,c,14),{data:V}=ee(j,c+1,14),[O,ue]=o(!1),T=ve.useMemo(()=>Y==="anilist"&&h==="ADULT"||O?L:L.filter(e=>!(e.isAdult||e.rating==="R+"||e.rating==="Rx"||e.rating?.includes("17+"))),[L,O,Y,h]);k(()=>{B(r.get("query")||""),A(r.get("type")||"ALL"),y(r.get("season")||"ALL"),S(r.get("year")||"ALL"),I(r.get("country")||"ALL"),le(r.get("provider")||"anilist"),P(r.get("sortBy")||"POPULARITY_DESC"),x(r.get("status")||""),_(parseInt(r.get("page")||"1"));const e={},n=r.get("genres")?.split(",").map(l=>l.trim()).filter(Boolean)||[],s=r.get("excludeGenres")?.split(",").map(l=>l.trim()).filter(Boolean)||[];n.forEach(l=>l&&(e[l]="include")),s.forEach(l=>l&&(e[l]="exclude")),C(e)},[r]);const u=(e=1,n={})=>{ye();const s=n.type??h,l=n.status??F,H=n.season??v,q=n.year??f,J=n.country??G,K=n.sort??U,Q=n.genreState??b,he=n.showMature??O,i=new URLSearchParams;m.trim()&&i.set("query",m.trim()),s!=="ALL"&&i.set("type",s),l&&i.set("status",l),H!=="ALL"&&i.set("season",H),q!=="ALL"&&i.set("year",q),J!=="ALL"&&i.set("country",J),K!=="POPULARITY_DESC"&&i.set("sortBy",K);const X=Object.entries(Q).filter(([,p])=>p==="include").map(([p])=>p),Z=Object.entries(Q).filter(([,p])=>p==="exclude").map(([p])=>p);X.length>0&&i.set("genres",X.join(",")),Z.length>0&&i.set("excludeGenres",Z.join(",")),s!=="ADULT"&&!he&&i.set("adult","false"),i.set("provider","anilist"),e>1&&i.set("page",e.toString()),ae(i),e!==c&&_(e)},E=e=>{if(u(e),D.current){const n=D.current.getBoundingClientRect().top+window.scrollY-100;window.scrollTo({top:n,behavior:"smooth"})}},R=new Date().getFullYear(),de=[{value:"ALL",label:"All Years"},...Array.from({length:R-1980+1},(e,n)=>({value:String(R-n),label:String(R-n)}))],W=L.length>=14&&V&&V.length>0;return a("div",{className:"page-container",children:[a("div",{className:t.header,children:[a("h1",{className:t.pageTitle,children:"Search Anime"}),a("p",{className:t.pageSubtitle,children:"Search through thousands of titles and discover your next favorite"})]}),a("div",{className:t.filterContainer,children:[a("div",{className:t.searchBarWrapper,children:[a("div",{className:t.inputIconWrapper,children:[a(d,{name:"search",className:t.searchIcon}),a("input",{type:"text","data-virtual-keyboard":"true",className:t.searchInput,placeholder:"Search by title, character, or studio...",value:m,onInput:e=>B(e.currentTarget.value),onKeyDown:e=>e.key==="Enter"&&u()})]}),a("div",{className:t.searchActions,children:[a(w,{onClick:()=>u(),className:t.searchBtn,children:"Search"}),a("button",{className:`${t.filterToggleBtn} ${N?t.active:""}`,onClick:()=>ne(!N),children:[a(d,{name:"filter",size:14}),a("span",{children:"Filters"}),N?a(d,{name:"chevron-up",size:12}):a(d,{name:"chevron-down",size:12})]})]})]}),a("div",{className:`${t.advancedFilters} ${N?t.show:""}`,children:[a("div",{className:t.filterDivider}),a("div",{className:t.filterGrid,children:[a("div",{className:t.filterItem,children:[a("label",{children:"Type"}),a("select",{value:h,onChange:e=>{if(e.currentTarget.value==="ADULT"){te("/mature?provider=mal");return}A(e.currentTarget.value)},children:Ne.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Status"}),a("select",{value:F,onChange:e=>x(e.currentTarget.value),children:[a("option",{value:"",children:"All Status"}),Ie.map(e=>a("option",{value:e.value,children:e.label},e.value))]})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Season"}),a("select",{value:v,onChange:e=>y(e.currentTarget.value),children:Ce.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Year"}),a("select",{value:f,onChange:e=>S(e.currentTarget.value),children:de.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:["Country",re===!1&&a("span",{style:{display:"block",fontSize:"0.75rem",color:"var(--text-muted)",fontWeight:400},children:"AniList only — ignored by fallback providers"})]}),a("select",{value:G,onChange:e=>I(e.currentTarget.value),children:Te.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Sort By"}),a("select",{value:U,onChange:e=>P(e.currentTarget.value),children:Ee.map(e=>a("option",{value:e.value,children:e.label},e.value))})]})]}),$.length>0&&a("div",{className:t.genreSection,children:[a("label",{className:t.genreLabel,children:"Genres"}),a("div",{className:t.genreContainer,children:$.map(e=>a("button",{className:`${t.genreButton} ${t[b[e]||""]}`,onClick:()=>{C(n=>{const s=n[e],l={...n};return s==="include"?l[e]="exclude":s==="exclude"?delete l[e]:l[e]="include",l})},children:e},e))})]}),a("div",{className:t.filterActions,children:[a(w,{variant:"secondary",onClick:()=>{C({}),A("ALL"),y("ALL"),S("ALL"),I("ALL"),P("POPULARITY_DESC"),x(""),ue(!1),u(1,{type:"ALL",status:"",season:"ALL",year:"ALL",country:"ALL",sort:"POPULARITY_DESC",genreState:{},showMature:!1})},children:"Reset All"}),a(w,{onClick:()=>u(),className:t.applyBtn,children:"Apply Filters"})]})]})]}),oe&&a(Se,{message:ce?.message||"Error"}),(h!=="ALL"||v!=="ALL"||f!=="ALL"||Object.keys(b).length>0)&&a("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",alignItems:"center",marginBottom:"1.5rem"},children:[a("span",{style:{fontSize:"0.8rem",color:"var(--text-muted)",fontWeight:600},children:"Active Filters:"}),h!=="ALL"&&a("span",{className:"badge badge-secondary",style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:["Type: ",h,a("button",{onClick:e=>{e.stopPropagation(),e.preventDefault(),A("ALL"),u(1,{type:"ALL"})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]}),v!=="ALL"&&a("span",{className:"badge badge-secondary",style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:["Season: ",v,a("button",{onClick:e=>{e.stopPropagation(),e.preventDefault(),y("ALL"),u(1,{season:"ALL"})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]}),f!=="ALL"&&a("span",{className:"badge badge-secondary",style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:["Year: ",f,a("button",{onClick:e=>{e.stopPropagation(),e.preventDefault(),S("ALL"),u(1,{year:"ALL"})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]}),Object.entries(b).map(([e,n])=>a("span",{className:`badge ${n==="include"?"badge-primary":"badge-danger"}`,style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[n==="include"?`+ ${e}`:`- ${e}`,a("button",{onClick:s=>{s.stopPropagation(),s.preventDefault();const l={...b};delete l[e],C(l),u(1,{genreState:l})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]},e))]}),a("div",{className:t.resultsHeader,ref:D,children:[a("h2",{className:t.resultsTitle,children:m?`Search Results for "${m}"`:"Discover Anime"}),T.length>0&&a("div",{className:t.pagination,children:[a("button",{className:t.pageBtn,onClick:()=>E(c-1),disabled:c===1||g,"aria-label":"Previous page",children:a(d,{name:"chevron-left",size:14})}),a("span",{className:t.pageInfo,children:["Page ",a("strong",{children:c})]}),a("button",{className:t.pageBtn,onClick:()=>E(c+1),disabled:!W||g,"aria-label":"Next page",children:a(d,{name:"chevron-right",size:14})})]})]}),a("div",{className:`${t.resultsGrid} ${se?t.lowEnd:""}`,children:g?a(be,{}):T.map(e=>a(fe,{anime:e},e._id))}),!g&&T.length===0&&a("div",{className:t.noResults,children:[a(d,{name:"search",size:48,className:t.noResultsIcon}),a("h3",{children:"No results found"}),a("p",{children:"Try adjusting your search or filters to find what you're looking for."})]}),T.length>0&&a("div",{className:t.bottomPagination,children:a("div",{className:t.pagination,children:[a("button",{className:t.pageBtn,onClick:()=>E(c-1),disabled:c===1||g,children:[a(d,{name:"chevron-left",size:14}),a("span",{children:"Previous"})]}),a("span",{className:t.pageInfo,children:["Page ",a("strong",{children:c})]}),a("button",{className:t.pageBtn,onClick:()=>E(c+1),disabled:!W||g,children:[a("span",{children:"Next"}),a(d,{name:"chevron-right",size:14})]})]})})]})}export{Me as default};
1
+ import{h as k,o as pe,a as ge,d as o,A as me,g as ve,u as a}from"./vendor-core-8R2fFbyN.js";import{I as d}from"./vendor-icons-CDMuNDeL.js";import{A as fe}from"./AnimeCard-OKU7LaSN.js";import{S as be}from"./SkeletonGrid-Du10CNfq.js";import{u as Le,r as Ae,P as ee,B as w,Q as ye}from"./index-lo-bz7f2.js";import{E as Se}from"./ErrorMessage-z4f4WGgP.js";import{s as t}from"./Search.module-CMEai-B-.js";import"./useAnimeInfoData-CbNnHRj8.js";import"./vendor-query-BXRECSI6.js";import"./QueueOptionsButton-DKWi-9kd.js";import"./vendor-ui-CUDCvRS_.js";import"./MediaCard-DszKDA4s.js";import"./useIsMobile-Dm_b6Ob3.js";const Ne=[{value:"ALL",label:"All Types"},{value:"TV",label:"TV Series"},{value:"Movie",label:"Movie"},{value:"OVA",label:"OVA"},{value:"ONA",label:"ONA"},{value:"TV_SHORT",label:"TV Short"},{value:"SPECIAL",label:"Special"},{value:"ADULT",label:"Mature"}],Ce=[{value:"ALL",label:"All Seasons"},{value:"Winter",label:"Winter"},{value:"Spring",label:"Spring"},{value:"Summer",label:"Summer"},{value:"Fall",label:"Fall"}],Te=[{value:"ALL",label:"All Countries"},{value:"JP",label:"Japan"},{value:"CN",label:"China"}],Ee=[{value:"POPULARITY_DESC",label:"Popularity"},{value:"TRENDING_DESC",label:"Trending"},{value:"SCORE_DESC",label:"Score"},{value:"START_DATE_DESC",label:"Newest"},{value:"START_DATE_ASC",label:"Oldest"},{value:"EPISODES_DESC",label:"Most Episodes"},{value:"FAVOURITES_DESC",label:"Favourites"}],Ie=[{value:"RELEASING",label:"Currently Airing"},{value:"FINISHED",label:"Finished"},{value:"NOT_YET_RELEASED",label:"Not Yet Released"},{value:"CANCELLED",label:"Cancelled"},{value:"HIATUS",label:"Hiatus"}];function Me(){k(()=>{document.title="Search - dango"},[]);const[r,ae]=pe(),te=ge(),[m,B]=o(r.get("query")||""),[c,_]=o(parseInt(r.get("page")||"1")),[h,A]=o(r.get("type")||"ALL"),[v,y]=o(r.get("season")||"ALL"),[f,S]=o(r.get("year")||"ALL"),[G,I]=o(r.get("country")||"ALL"),[Y,le]=o(r.get("provider")||"anilist"),[U,P]=o(r.get("sortBy")||"POPULARITY_DESC"),[F,x]=o(r.get("status")||""),[N,ne]=o(!1),[re,M]=o(null);k(()=>{let e=!1;return fetch("/api/anilist-status").then(n=>n.json()).then(n=>{e||M(n.available)}).catch(()=>{e||M(!0)}),()=>{e=!0}},[]);const{lowEndMode:se}=Le(),D=me(null),{data:ie}=Ae(),$=ie?.genres||[],[b,C]=o(()=>{const e={},n=r.get("genres")?.split(",").map(l=>l.trim()).filter(Boolean)||[],s=r.get("excludeGenres")?.split(",").map(l=>l.trim()).filter(Boolean)||[];return n.forEach(l=>l&&(e[l]="include")),s.forEach(l=>l&&(e[l]="exclude")),e}),z=new URLSearchParams(r);z.delete("page");const j=z.toString(),{data:L=[],isLoading:g,isError:oe,error:ce}=ee(j,c,14),{data:V}=ee(j,c+1,14),[O,ue]=o(!1),T=ve.useMemo(()=>Y==="anilist"&&h==="ADULT"||O?L:L.filter(e=>!(e.isAdult||e.rating==="R+"||e.rating==="Rx"||e.rating?.includes("17+"))),[L,O,Y,h]);k(()=>{B(r.get("query")||""),A(r.get("type")||"ALL"),y(r.get("season")||"ALL"),S(r.get("year")||"ALL"),I(r.get("country")||"ALL"),le(r.get("provider")||"anilist"),P(r.get("sortBy")||"POPULARITY_DESC"),x(r.get("status")||""),_(parseInt(r.get("page")||"1"));const e={},n=r.get("genres")?.split(",").map(l=>l.trim()).filter(Boolean)||[],s=r.get("excludeGenres")?.split(",").map(l=>l.trim()).filter(Boolean)||[];n.forEach(l=>l&&(e[l]="include")),s.forEach(l=>l&&(e[l]="exclude")),C(e)},[r]);const u=(e=1,n={})=>{ye();const s=n.type??h,l=n.status??F,H=n.season??v,q=n.year??f,J=n.country??G,K=n.sort??U,Q=n.genreState??b,he=n.showMature??O,i=new URLSearchParams;m.trim()&&i.set("query",m.trim()),s!=="ALL"&&i.set("type",s),l&&i.set("status",l),H!=="ALL"&&i.set("season",H),q!=="ALL"&&i.set("year",q),J!=="ALL"&&i.set("country",J),K!=="POPULARITY_DESC"&&i.set("sortBy",K);const X=Object.entries(Q).filter(([,p])=>p==="include").map(([p])=>p),Z=Object.entries(Q).filter(([,p])=>p==="exclude").map(([p])=>p);X.length>0&&i.set("genres",X.join(",")),Z.length>0&&i.set("excludeGenres",Z.join(",")),s!=="ADULT"&&!he&&i.set("adult","false"),i.set("provider","anilist"),e>1&&i.set("page",e.toString()),ae(i),e!==c&&_(e)},E=e=>{if(u(e),D.current){const n=D.current.getBoundingClientRect().top+window.scrollY-100;window.scrollTo({top:n,behavior:"smooth"})}},R=new Date().getFullYear(),de=[{value:"ALL",label:"All Years"},...Array.from({length:R-1980+1},(e,n)=>({value:String(R-n),label:String(R-n)}))],W=L.length>=14&&V&&V.length>0;return a("div",{className:"page-container",children:[a("div",{className:t.header,children:[a("h1",{className:t.pageTitle,children:"Search Anime"}),a("p",{className:t.pageSubtitle,children:"Search through thousands of titles and discover your next favorite"})]}),a("div",{className:t.filterContainer,children:[a("div",{className:t.searchBarWrapper,children:[a("div",{className:t.inputIconWrapper,children:[a(d,{name:"search",className:t.searchIcon}),a("input",{type:"text","data-virtual-keyboard":"true",className:t.searchInput,placeholder:"Search by title, character, or studio...",value:m,onInput:e=>B(e.currentTarget.value),onKeyDown:e=>e.key==="Enter"&&u()})]}),a("div",{className:t.searchActions,children:[a(w,{onClick:()=>u(),className:t.searchBtn,children:"Search"}),a("button",{className:`${t.filterToggleBtn} ${N?t.active:""}`,onClick:()=>ne(!N),children:[a(d,{name:"filter",size:14}),a("span",{children:"Filters"}),N?a(d,{name:"chevron-up",size:12}):a(d,{name:"chevron-down",size:12})]})]})]}),a("div",{className:`${t.advancedFilters} ${N?t.show:""}`,children:[a("div",{className:t.filterDivider}),a("div",{className:t.filterGrid,children:[a("div",{className:t.filterItem,children:[a("label",{children:"Type"}),a("select",{value:h,onChange:e=>{if(e.currentTarget.value==="ADULT"){te("/mature?provider=mal");return}A(e.currentTarget.value)},children:Ne.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Status"}),a("select",{value:F,onChange:e=>x(e.currentTarget.value),children:[a("option",{value:"",children:"All Status"}),Ie.map(e=>a("option",{value:e.value,children:e.label},e.value))]})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Season"}),a("select",{value:v,onChange:e=>y(e.currentTarget.value),children:Ce.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Year"}),a("select",{value:f,onChange:e=>S(e.currentTarget.value),children:de.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:["Country",re===!1&&a("span",{style:{display:"block",fontSize:"0.75rem",color:"var(--text-muted)",fontWeight:400},children:"AniList only — ignored by fallback providers"})]}),a("select",{value:G,onChange:e=>I(e.currentTarget.value),children:Te.map(e=>a("option",{value:e.value,children:e.label},e.value))})]}),a("div",{className:t.filterItem,children:[a("label",{children:"Sort By"}),a("select",{value:U,onChange:e=>P(e.currentTarget.value),children:Ee.map(e=>a("option",{value:e.value,children:e.label},e.value))})]})]}),$.length>0&&a("div",{className:t.genreSection,children:[a("label",{className:t.genreLabel,children:"Genres"}),a("div",{className:t.genreContainer,children:$.map(e=>a("button",{className:`${t.genreButton} ${t[b[e]||""]}`,onClick:()=>{C(n=>{const s=n[e],l={...n};return s==="include"?l[e]="exclude":s==="exclude"?delete l[e]:l[e]="include",l})},children:e},e))})]}),a("div",{className:t.filterActions,children:[a(w,{variant:"secondary",onClick:()=>{C({}),A("ALL"),y("ALL"),S("ALL"),I("ALL"),P("POPULARITY_DESC"),x(""),ue(!1),u(1,{type:"ALL",status:"",season:"ALL",year:"ALL",country:"ALL",sort:"POPULARITY_DESC",genreState:{},showMature:!1})},children:"Reset All"}),a(w,{onClick:()=>u(),className:t.applyBtn,children:"Apply Filters"})]})]})]}),oe&&a(Se,{message:ce?.message||"Error"}),(h!=="ALL"||v!=="ALL"||f!=="ALL"||Object.keys(b).length>0)&&a("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",alignItems:"center",marginBottom:"1.5rem"},children:[a("span",{style:{fontSize:"0.8rem",color:"var(--text-muted)",fontWeight:600},children:"Active Filters:"}),h!=="ALL"&&a("span",{className:"badge badge-secondary",style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:["Type: ",h,a("button",{onClick:e=>{e.stopPropagation(),e.preventDefault(),A("ALL"),u(1,{type:"ALL"})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]}),v!=="ALL"&&a("span",{className:"badge badge-secondary",style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:["Season: ",v,a("button",{onClick:e=>{e.stopPropagation(),e.preventDefault(),y("ALL"),u(1,{season:"ALL"})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]}),f!=="ALL"&&a("span",{className:"badge badge-secondary",style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:["Year: ",f,a("button",{onClick:e=>{e.stopPropagation(),e.preventDefault(),S("ALL"),u(1,{year:"ALL"})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]}),Object.entries(b).map(([e,n])=>a("span",{className:`badge ${n==="include"?"badge-primary":"badge-danger"}`,style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[n==="include"?`+ ${e}`:`- ${e}`,a("button",{onClick:s=>{s.stopPropagation(),s.preventDefault();const l={...b};delete l[e],C(l),u(1,{genreState:l})},style:{background:"none",border:"none",color:"inherit",cursor:"pointer"},children:"✕"})]},e))]}),a("div",{className:t.resultsHeader,ref:D,children:[a("h2",{className:t.resultsTitle,children:m?`Search Results for "${m}"`:"Discover Anime"}),T.length>0&&a("div",{className:t.pagination,children:[a("button",{className:t.pageBtn,onClick:()=>E(c-1),disabled:c===1||g,"aria-label":"Previous page",children:a(d,{name:"chevron-left",size:14})}),a("span",{className:t.pageInfo,children:["Page ",a("strong",{children:c})]}),a("button",{className:t.pageBtn,onClick:()=>E(c+1),disabled:!W||g,"aria-label":"Next page",children:a(d,{name:"chevron-right",size:14})})]})]}),a("div",{className:`${t.resultsGrid} ${se?t.lowEnd:""}`,children:g?a(be,{}):T.map(e=>a(fe,{anime:e},e._id))}),!g&&T.length===0&&a("div",{className:t.noResults,children:[a(d,{name:"search",size:48,className:t.noResultsIcon}),a("h3",{children:"No results found"}),a("p",{children:"Try adjusting your search or filters to find what you're looking for."})]}),T.length>0&&a("div",{className:t.bottomPagination,children:a("div",{className:t.pagination,children:[a("button",{className:t.pageBtn,onClick:()=>E(c-1),disabled:c===1||g,children:[a(d,{name:"chevron-left",size:14}),a("span",{children:"Previous"})]}),a("span",{className:t.pageInfo,children:["Page ",a("strong",{children:c})]}),a("button",{className:t.pageBtn,onClick:()=>E(c+1),disabled:!W||g,children:[a("span",{children:"Next"}),a(d,{name:"chevron-right",size:14})]})]})})]})}export{Me as default};
@@ -1,4 +1,4 @@
1
- import{d as r,A as V,h as U,u as e,q as te,S as ee,T as Te,o as Re,a as De,g as ge,_ as Ie}from"./vendor-core-8R2fFbyN.js";import{d as Pe,B as D,M as G,h as xe,T as F,z as me,D as ie,E as Le,F as Oe,q as de,u as Ae,G as Ue,w as pe,x as Me,H as Ee,I as $e,V as je,J as Ge,K as Ke,L as He}from"./index-IZgh1beL.js";import{u as ue}from"./vendor-query-BXRECSI6.js";import{I as q}from"./vendor-icons-CDMuNDeL.js";const oe={"title-preference-container":"_title-preference-container_sdqgs_1","toggle-button":"_toggle-button_sdqgs_21","toggle-label":"_toggle-label_sdqgs_51"},ce=["name","nativeName","englishName"],le={name:"Default (Romaji)",nativeName:"Native",englishName:"English"},Fe=()=>{const{titlePreference:t,setTitlePreference:n,loading:o}=Pe(),[i,l]=r(le[t]),[w,b]=r(!1),d=V(null);U(()=>{o||l(le[t])},[t,o]);const s=async()=>{if(w)return;b(!0);const g=(ce.indexOf(t)+1)%ce.length,p=ce[g],h=le[p];d.current&&(d.current.style.transform="translateX(-100%)",d.current.style.opacity="0"),setTimeout(async()=>{l(h),n(p),d.current&&(d.current.style.transition="none",d.current.style.transform="translateX(100%)",d.current.style.opacity="0",d.current.offsetWidth,d.current.style.transition="transform 0.3s ease-out, opacity 0.3s ease-out",d.current.style.transform="translateX(0)",d.current.style.opacity="1");try{await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:"titlePreference",value:p})})}catch(C){console.error("Error saving title preference:",C)}finally{b(!1)}},300)};return o?e("p",{children:"Loading title preference..."}):e("div",{className:oe["title-preference-container"],children:[e("h4",{children:"Anime Title Display Preference"}),e("button",{onClick:s,className:oe["toggle-button"],disabled:w,children:e("span",{ref:d,className:oe["toggle-label"],children:i})})]})},ze="_settingsHeader_14a5d_1",Be="_pageTitle_14a5d_6",We="_pageSubtitle_14a5d_14",qe="_settingsLayout_14a5d_20",Ve="_sidebar_14a5d_27",Je="_sidebarIndicator_14a5d_35",Ye="_sidebarItem_14a5d_50",Qe="_active_14a5d_72",Xe="_mainContent_14a5d_80",Ze="_tabContent_14a5d_85",et="_sectionCard_14a5d_103",tt="_settingItem_14a5d_127",at="_settingRow_14a5d_132",nt="_controls_14a5d_145",st="_status_14a5d_151",m={settingsHeader:ze,pageTitle:Be,pageSubtitle:We,settingsLayout:qe,sidebar:Ve,sidebarIndicator:Je,sidebarItem:Ye,active:Qe,mainContent:Xe,tabContent:Ze,sectionCard:et,settingItem:tt,settingRow:at,controls:nt,status:st},rt="_sectionCard_wt900_12",it="_title_wt900_22",ot="_signIn_wt900_29",ct="_userInfo_wt900_36",lt="_warning_wt900_58",dt="_formGroup_wt900_65",ut="_label_wt900_69",ht="_inputWrapper_wt900_79",gt="_input_wt900_79",mt="_select_wt900_103",pt="_actions_wt900_140",yt="_hr_wt900_148",y={sectionCard:rt,title:it,signIn:ot,userInfo:ct,warning:lt,formGroup:dt,label:ut,inputWrapper:ht,input:gt,select:mt,actions:pt,hr:yt},ft=()=>{const[t,n]=r(!0),[o,i]=r(!1),[l,w]=r(!1),[b,d]=r(null),[s,u]=r({status:"idle"}),[g,p]=r(!1),[h,C]=r(""),[k,f]=r(!1),I=V(null),[T,P]=r({show:!1,message:"",type:"info"}),N=()=>{I.current&&(window.clearInterval(I.current),I.current=null)},L=te(S=>{w(S.authenticated),d(S.user||S.device.user||null),u(S.device),p(!!S.hasCustomClientId)},[]),O=te(async()=>{const M=await(await fetch("/api/auth/github/status")).json();L(M)},[L]),E=async()=>{try{const M=await(await fetch("/api/auth/github/poll")).json();u(M),M.status==="success"?(N(),await O(),P({show:!0,message:"GitHub authentication complete. Sync has been initialized.",type:"success"})):M.status==="error"&&(N(),P({show:!0,message:M.error||"GitHub authentication failed.",type:"error"}))}catch{N(),P({show:!0,message:"Failed to poll GitHub authentication status.",type:"error"})}},_=(S=5)=>{N(),I.current=window.setInterval(E,Math.max(S,5)*1e3)};U(()=>(O().catch(()=>{P({show:!0,message:"Failed to load GitHub sync status.",type:"error"})}).finally(()=>n(!1)),N),[O]);const v=async()=>{i(!0);try{const S=await fetch("/api/auth/github/start",{method:"POST"}),M=await S.json();if(!S.ok)throw new Error("Failed to start GitHub authentication.");u(M),_(M.verification?.interval)}catch(S){P({show:!0,message:S instanceof Error?S.message:"Failed to start GitHub authentication.",type:"error"})}finally{i(!1)}},R=async()=>{try{await fetch("/api/auth/github/logout",{method:"POST"}),w(!1),d(null),u({status:"idle"}),P({show:!0,message:"Signed out of GitHub sync.",type:"success"})}catch{P({show:!0,message:"Failed to sign out of GitHub.",type:"error"})}},$=async()=>{f(!0);try{if(!(await fetch("/api/auth/github/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:h})})).ok)throw new Error("save failed");C(""),await O(),P({show:!0,message:"Custom GitHub auth saved.",type:"success"})}catch{P({show:!0,message:"Failed to save override.",type:"error"})}finally{f(!1)}},K=async()=>{f(!0);try{await fetch("/api/auth/github/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:""})}),C(""),await O(),P({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{P({show:!0,message:"Failed to clear override.",type:"error"})}finally{f(!1)}};return t?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:y.sectionCard,children:[e("h3",{className:y.title,children:"GitHub Cloud Sync"}),e("p",{className:y.signIn,children:"Sync local data through a private GitHub repository named dango-sync-data."}),l&&b?e("div",{className:y.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:b.name||b.login})]}),e(D,{variant:"danger",onClick:R,children:"Sign Out"})]}):e("div",{className:y.signIn,children:e(D,{onClick:v,disabled:o||s.status==="pending",children:o||s.status==="pending"?"Waiting for GitHub...":"Sign in with GitHub"})}),s.status==="pending"&&s.verification&&e(ee,{children:[e("hr",{className:y.hr}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Verification URL"}),e("div",{className:y.inputWrapper,children:[e("input",{className:y.input,value:s.verification.verification_uri,readOnly:!0}),e(D,{onClick:()=>{const S=s.verification?.verification_uri;S&&/^https?:\/\//i.test(S)&&window.open(S,"_blank","noopener,noreferrer")},children:"Open"})]})]}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Device Code"}),e("input",{className:y.input,value:s.verification.user_code,readOnly:!0})]})]}),s.status==="error"&&e("p",{className:y.warning,children:s.error}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",g?"(override active)":""]}),e("div",{className:y.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:y.label,children:"Client ID (optional)"}),e("input",{className:y.input,value:h,onChange:S=>C(S.currentTarget.value),placeholder:"Your GitHub OAuth app ID"})]}),e("div",{className:y.actions,children:[e(D,{onClick:$,disabled:k,children:"Save override"}),e(D,{variant:"secondary",onClick:K,disabled:k,children:"Use dango defaults"})]})]}),e(G,{isOpen:T.show,onClose:()=>P(S=>({...S,show:!1})),width:"sm",children:[e(G.Body,{children:e("p",{children:T.message})}),e(G.Actions,{children:e(D,{onClick:()=>P(S=>({...S,show:!1})),children:"OK"})})]})]})},wt=()=>{const[t,n]=r(!0),[o,i]=r(null),[l,w]=r(!1),[b,d]=r(!1),[s,u]=r(""),[g,p]=r(""),[h,C]=r(""),[k,f]=r(!1),[I,T]=r({show:!1,message:"",type:"info"}),P=async()=>{try{const R=await(await fetch("/api/auth/user")).json();i(R?.email?R:null)}catch{i(null)}},N=async()=>{try{const[v,R]=await Promise.all([fetch("/api/auth/config-status"),fetch("/api/auth/google-auth")]),$=await v.json(),K=await R.json();w(!!$.hasConfig),d(!!(K.hasCustomWorkerUrl||K.hasCustomClientId||K.hasClientSecret))}catch(v){console.error("Failed to fetch config status",v)}};U(()=>{(async()=>{n(!0),await Promise.all([P(),N()]);try{new URLSearchParams(window.location.search).get("google_auth")==="success"&&(await P(),window.history.replaceState(null,"",window.location.pathname))}catch{}n(!1)})();const R=$=>{$.origin===window.location.origin&&typeof $.data=="object"&&$.data!==null&&$.data.type==="GOOGLE_AUTH_SUCCESS"&&(i($.data.user),window.location.reload())};return window.addEventListener("message",R),()=>window.removeEventListener("message",R)},[]);const L=async()=>{try{const R=await(await fetch("/api/auth/google/login",{method:"POST"})).json();if(R.authenticated){window.location.reload();return}if(R.url){if(typeof window.DangoBridge<"u"){window.location.href=R.url;return}const K=600,S=700,M=window.innerWidth/2-K/2,ae=window.innerHeight/2-S/2;window.open(R.url,"GoogleAuth",`width=${K},height=${S},top=${ae},left=${M}`)}else throw new Error("Auth URL not available")}catch{T({show:!0,message:"Authentication failed. Ensure server is configured correctly.",type:"error"})}},O=async()=>{try{await fetch("/api/auth/logout",{method:"POST"}),i(null),T({show:!0,message:"Successfully signed out.",type:"success"}),window.location.reload()}catch(v){console.error("Sign out failed",v),T({show:!0,message:"Failed to sign out.",type:"error"})}},E=async()=>{f(!0);try{if(!(await fetch("/api/auth/google-auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workerUrl:s,clientId:g,clientSecret:h})})).ok)throw new Error("save failed");u(""),p(""),C(""),await N(),T({show:!0,message:"Custom auth saved. Restart may be required.",type:"success"})}catch{T({show:!0,message:"Failed to save override.",type:"error"})}finally{f(!1)}},_=async()=>{f(!0);try{await fetch("/api/auth/google-auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workerUrl:"",clientId:"",clientSecret:""})}),u(""),p(""),C(""),await N(),T({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{T({show:!0,message:"Failed to clear override.",type:"error"})}finally{f(!1)}};return t?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:y.sectionCard,children:[e("h3",{className:y.title,children:"Google Drive Sync"}),o?e("div",{className:y.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:o.name})," (",o.email,")"]}),e(D,{variant:"danger",onClick:O,children:"Sign Out"})]}):e("div",{className:y.signIn,children:[e("p",{children:"Sign in with your Google account to enable synchronization features."}),e(D,{onClick:L,disabled:!l,children:"Sign in with Google"}),!l&&e("p",{className:y.warning,children:"Google sync is not configured on the server."})]}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",b?"(override active)":""]}),e("div",{className:y.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:y.label,children:"Worker URL (optional)"}),e("input",{className:y.input,value:s,onChange:v=>u(v.currentTarget.value),placeholder:"https://your-worker.workers.dev"})]}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Client ID (optional)"}),e("input",{className:y.input,value:g,onChange:v=>p(v.currentTarget.value),placeholder:"Your Google OAuth client ID"})]}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Client Secret (optional)"}),e("input",{type:"password",className:y.input,value:h,onChange:v=>C(v.currentTarget.value),placeholder:"Your Google OAuth secret"})]}),e("div",{className:y.actions,children:[e(D,{onClick:E,disabled:k,children:"Save override"}),e(D,{variant:"secondary",onClick:_,disabled:k,children:"Use dango defaults"})]})]}),e(G,{isOpen:I.show,onClose:()=>T(v=>({...v,show:!1})),width:"sm",children:[e(G.Body,{children:e("p",{children:I.message})}),e(G.Actions,{children:e(D,{onClick:()=>T(v=>({...v,show:!1})),children:"OK"})})]})]})},vt="_sectionCard_1pqo4_1",bt="_settingItem_1pqo4_26",_t="_settingRow_1pqo4_31",kt="_modalOverlay_1pqo4_38",St="_modal_1pqo4_38",Ct="_modalActions_1pqo4_73",Nt="_modalSecondary_1pqo4_79",Tt="_modalPrimary_1pqo4_89",j={sectionCard:vt,settingItem:bt,settingRow:_t,modalOverlay:kt,modal:St,modalActions:Ct,modalSecondary:Nt,modalPrimary:Tt},Rt={anime:{heading:"Watchlist Preferences",blurb:"Customize your experience when managing your watchlist and series entries.",skipKey:"skipRemoveConfirmation",ignoreKey:"ignoreAdultContent",listOnlyKey:"cwWatchlistOnly",skipLabel:"Skip confirmation when removing from watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in watchlist",listNoun:"watchlist",continueNoun:"continue watching",adultCountUrl:"/api/continue-watching/adult-count",purgeUrl:"/api/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["allContinueWatching"]]},manga:{heading:"Reading List Preferences",blurb:"Customize your experience when managing your reading list and manga entries.",skipKey:"mangaSkipRemoveConfirmation",ignoreKey:"mangaIgnoreAdultContent",listOnlyKey:"mangaCwWatchlistOnly",skipLabel:"Skip confirmation when removing from reading list",ignoreLabel:"Hide adult content from continue reading",listOnlyLabel:"Only show continue reading for manga in reading list",listNoun:"reading list",continueNoun:"continue reading",adultCountUrl:"/api/manga/continue-reading/adult-count",purgeUrl:"/api/manga/continue-reading/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue reading`,invalidateKeys:[["manga-continue-reading"]]},tv:{heading:"TV Watchlist Preferences",blurb:"Customize your experience when managing your TV watchlist and series entries.",skipKey:"tvSkipRemoveConfirmation",ignoreKey:"tvIgnoreAdultContent",listOnlyKey:"tvCwWatchlistOnly",skipLabel:"Skip confirmation when removing from TV watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in TV watchlist",listNoun:"TV watchlist",continueNoun:"continue watching",adultCountUrl:"/api/tv/continue-watching/adult-count",purgeUrl:"/api/tv/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["tv-continue-watching"]]},asmr:{heading:"Listening List Preferences",blurb:"Customize your experience when managing your listening list and work entries.",skipKey:"asmrSkipRemoveConfirmation",ignoreKey:"asmrIgnoreAdultContent",listOnlyKey:"asmrCwWatchlistOnly",skipLabel:"Skip confirmation when removing from listening list",ignoreLabel:"Hide adult content from continue listening",listOnlyLabel:"Only show continue listening for works in listening list",listNoun:"listening list",continueNoun:"continue listening",adultCountUrl:"/api/asmr/continue-listening/adult-count",purgeUrl:"/api/asmr/continue-listening/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue listening`,invalidateKeys:[["asmr-continue-listening"]]}},Dt=(t,n)=>{if(t==null)return n;const o=String(t);return o==="true"||o==="1"?!0:o==="false"||o==="0"?!1:n},ye=(t,n,o)=>{const[i,l]=r(n),[w,b]=r(!1),d=ue();return U(()=>{(async()=>{try{const p=await(await fetch(`/api/settings?key=${t}`)).json();l(Dt(p.value,n))}catch(g){console.error("Failed to fetch setting",g)}})()},[t,n]),{value:i,setValue:l,isUpdating:w,toggle:async()=>{if(w)return;b(!0);const u=!i;l(u);try{await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:t,value:u})});for(const g of o)d.invalidateQueries({queryKey:g})}catch(g){console.error("Error saving setting:",g),l(!u)}finally{b(!1)}}}},It=()=>{const{contentType:t}=xe(),n=Rt[t],[o,i]=r(!1),[l,w]=r(!0),[b,d]=r(!1),s=ye(n.ignoreKey,!0,n.invalidateKeys),u=ye(n.listOnlyKey,!1,n.invalidateKeys),[g,p]=r(null),[h,C]=r(!1),k=ue();U(()=>{w(!0),(async()=>{try{const O=await(await fetch(`/api/settings?key=${n.skipKey}`)).json();String(O.value)==="true"||String(O.value)==="1"?i(!0):i(!1)}catch(L){console.error("Failed to fetch setting",L)}finally{w(!1)}})()},[n.skipKey]);const f=async()=>{if(b)return;d(!0);const N=!o;i(N);try{await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n.skipKey,value:N})})}catch(L){console.error("Error saving setting:",L),i(!N)}finally{d(!1)}},I=async()=>{if(!s.isUpdating){if(s.value)try{const L=await(await fetch(n.adultCountUrl)).json();if(typeof L.count=="number"&&L.count>0){p(L.count);return}}catch(N){console.error("Failed to fetch adult count",N)}s.toggle()}},T=()=>{p(null),s.toggle()},P=async()=>{if(!h){C(!0);try{const L=await(await fetch(n.purgeUrl,{method:"POST"})).json();me.success(n.purgeDoneText(L.removed));for(const O of n.invalidateKeys)k.invalidateQueries({queryKey:O})}catch(N){console.error("Failed to purge adult entries",N),me.error("Failed to remove adult entries")}finally{C(!1),p(null)}s.toggle()}};return l?e("div",{children:"Loading settings..."}):e("div",{className:j.sectionCard,children:[e("h3",{children:n.heading}),e("p",{children:n.blurb}),e("div",{className:j.settingItem,children:e("div",{className:j.settingRow,children:[e("label",{htmlFor:"skip-confirmation-toggle",children:n.skipLabel}),e(F,{isChecked:o,onChange:f,id:"skip-confirmation-toggle",disabled:b})]})}),e("div",{className:j.settingItem,children:e("div",{className:j.settingRow,children:[e("label",{htmlFor:"ignore-adult-toggle",children:n.ignoreLabel}),e(F,{isChecked:s.value,onChange:I,id:"ignore-adult-toggle",disabled:s.isUpdating})]})}),e("div",{className:j.settingItem,children:e("div",{className:j.settingRow,children:[e("label",{htmlFor:"cw-watchlist-only-toggle",children:n.listOnlyLabel}),e(F,{isChecked:u.value,onChange:u.toggle,id:"cw-watchlist-only-toggle",disabled:u.isUpdating})]})}),g!==null&&e("div",{className:j.modalOverlay,onClick:()=>p(null),children:e("div",{className:j.modal,onClick:N=>N.stopPropagation(),children:[e("h4",{children:"Show adult entries?"}),e("p",{children:[g," adult ",g===1?"entry":"entries"," not in your"," ",n.listNoun," ",g===1?"is":"are"," currently hidden from"," ",n.continueNoun,". You can purge ",g===1?"it":"them"," from the database instead of showing ",g===1?"it":"them","."]}),e("div",{className:j.modalActions,children:[e("button",{type:"button",className:j.modalSecondary,onClick:T,disabled:h,children:"Show them"}),e("button",{type:"button",className:j.modalPrimary,onClick:P,disabled:h,children:h?"Purging...":`Purge ${g}`})]})]})})]})},Pt="_sectionCard_jkggs_1",xt="_statsGrid_jkggs_26",Lt="_statCard_jkggs_33",Ot="_statLabel_jkggs_43",At="_statValue_jkggs_51",Ut="_statMeta_jkggs_57",Mt="_statusBanner_jkggs_63",Et="_statusSuccess_jkggs_74",$t="_statusUpdating_jkggs_80",jt="_statusError_jkggs_86",Gt="_sha_jkggs_92",Kt="_settingItem_jkggs_99",Ht="_settingRow_jkggs_104",Ft="_settingTitle_jkggs_111",zt="_settingSubtitle_jkggs_117",Bt="_actionsRow_jkggs_124",x={sectionCard:Pt,statsGrid:xt,statCard:Lt,statLabel:Ot,statValue:At,statMeta:Ut,statusBanner:Mt,statusSuccess:Et,statusUpdating:$t,statusError:jt,sha:Gt,settingItem:Kt,settingRow:Ht,settingTitle:Ft,settingSubtitle:zt,actionsRow:Bt},Wt=()=>{const[t,n]=r(null),[o,i]=r(!0),[l,w]=r(!1),[b,d]=r(!1),s=V(null),u=async()=>{try{const k=await fetch("/api/settings/offline-db");if(k.ok){const f=await k.json();return n(f),f}}catch(k){console.error("Failed to fetch offline DB info:",k)}finally{i(!1)}return null};U(()=>(u(),()=>{s.current&&window.clearInterval(s.current)}),[]),U(()=>{t?.isRefreshing?s.current||(s.current=window.setInterval(async()=>{const k=await u();k&&!k.isRefreshing&&s.current&&(window.clearInterval(s.current),s.current=null)},2e3)):s.current&&(window.clearInterval(s.current),s.current=null)},[t?.isRefreshing]);const g=async()=>{if(!t||l)return;const k=!t.autoUpdateEnabled;w(!0),n({...t,autoUpdateEnabled:k});try{(await fetch("/api/settings/offline-db/auto-update",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({enabled:k})})).ok||n({...t,autoUpdateEnabled:!k})}catch(f){console.error("Failed to update auto update setting:",f),n({...t,autoUpdateEnabled:!k})}finally{w(!1)}},p=async()=>{if(!(t?.isRefreshing||b)){d(!0);try{(await fetch("/api/settings/offline-db/update",{method:"POST"})).ok&&n(f=>f?{...f,isRefreshing:!0,lastStatus:"updating",lastMessage:"Downloading database..."}:null)}catch(k){console.error("Failed to trigger offline DB update:",k)}finally{d(!1)}}},h=k=>{if(!k)return"Never";try{return new Date(k).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"})}catch{return k}},C=t?.isRefreshing||b;return e("div",{className:x.sectionCard,children:[e("h3",{children:"Offline Metadata Database"}),e("p",{children:"Local MAL to AniList ID map used for instant imports and metadata enrichment without hitting rate-limited APIs. Updates automatically every Saturday in the background."}),e("div",{className:x.statsGrid,children:[e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"MAL Mapped"}),e("span",{className:x.statValue,children:o?"—":(t?.totalMalMapped??0).toLocaleString()})]}),e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"Release"}),e("span",{className:x.statMeta,children:o?"—":t?.releaseTag??"Never"})]}),e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"Last Checked"}),e("span",{className:x.statMeta,children:o?"—":h(t?.lastCheckedAt??null)})]}),e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"Last Updated"}),e("span",{className:x.statMeta,children:o?"—":h(t?.lastUpdatedAt??null)})]})]}),t?.lastMessage&&e("div",{className:`${x.statusBanner} ${t.lastStatus==="failed"?x.statusError:t.lastStatus==="updating"?x.statusUpdating:x.statusSuccess}`,children:[e("span",{children:t.lastMessage}),t.contentSha256&&e("span",{className:x.sha,children:["sha:",t.contentSha256.slice(0,12)]})]}),e("div",{className:x.settingItem,children:e("div",{className:x.settingRow,children:[e("div",{children:[e("span",{className:x.settingTitle,children:"Weekly Automatic Updates (Saturdays)"}),e("div",{className:x.settingSubtitle,children:"Download and index new database releases in the background. Catches up on startup if the server was offline."})]}),e(F,{id:"offline-db-auto-update-toggle",isChecked:t?t.autoUpdateEnabled:!0,onChange:g,disabled:o||l})]})}),e("div",{className:x.actionsRow,children:e(D,{onClick:p,disabled:o||C,children:C?"Updating Database...":"Update Offline Database Now"})})]})},qt="_sectionCard_1g4qx_1",Vt="_dangerCard_1g4qx_26",Jt="_status_1g4qx_34",Yt="_warningText_1g4qx_40",Qt="_ackLabel_1g4qx_44",Z={sectionCard:qt,dangerCard:Vt,status:Jt,warningText:Yt,ackLabel:Qt},Xt=()=>{const t=ue(),[n,o]=r(!1),[i,l]=r(!1),[w,b]=r(!1),[d,s]=r(""),u=()=>{l(!1),s(""),o(!0)},g=()=>{w||(o(!1),l(!1))},p=async()=>{if(!(!i||w)){b(!0),s("");try{const h=await fetch("/api/database/clear",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({confirm:!0})}),C=await h.json();if(!h.ok)throw new Error(C.error||"Failed to clear database");const k=C.deleted,f=C.deletedManga,I=C.deletedTv,T=C.deletedAsmr,P=Object.values(k).reduce((E,_)=>E+(_||0),0)+Object.values(f??{}).reduce((E,_)=>E+(_||0),0)+Object.values(I??{}).reduce((E,_)=>E+(_||0),0)+Object.values(T??{}).reduce((E,_)=>E+(_||0),0),N=(f?.manga_library??0)+(f?.manga_progress??0),L=(I?.tv_library??0)+(I?.tv_progress??0),O=(T?.asmr_library??0)+(T?.asmr_progress??0);s(`Library cleared — ${k.watchlist??0} watchlist entries, ${N} manga rows, ${L} TV rows, ${O} ASMR rows and ${P} total rows removed.`),t.invalidateQueries({queryKey:["watchlist"]}),t.invalidateQueries({queryKey:["allContinueWatching"]}),t.invalidateQueries({queryKey:["manga-library"]}),t.invalidateQueries({queryKey:["manga-library-ids"]}),t.invalidateQueries({queryKey:["manga-continue-reading"]}),t.invalidateQueries({queryKey:["tv-library"]}),t.invalidateQueries({queryKey:["tv-library-ids"]}),t.invalidateQueries({queryKey:["tv-continue-watching"]}),t.invalidateQueries({queryKey:["asmr-library"]}),t.invalidateQueries({queryKey:["asmr-library-ids"]}),t.invalidateQueries({queryKey:["asmr-continue-listening"]}),o(!1)}catch(h){s(h.message)}finally{b(!1),l(!1)}}};return e("div",{className:`${Z.sectionCard} ${Z.dangerCard}`,children:[e("h3",{children:"Danger Zone"}),e("p",{children:"Permanently delete your library (watchlist, watched episodes, queue, cached show metadata, manga reading list and reading progress, TV watchlist and watch progress, ASMR listening list and listening progress) to start fresh. Your settings, sync state and the offline metadata cache are preserved."}),e(D,{variant:"danger",onClick:u,children:"Clear Library Data"}),d&&e("p",{className:Z.status,children:d}),e(G,{isOpen:n,onClose:g,title:"Clear library data?",width:"sm",children:[e(G.Body,{children:[e("p",{className:Z.warningText,children:"This permanently deletes everything in your library. It acts on the active database (dev or prod, per server config) and cannot be undone. Settings, sync state and the offline metadata cache are kept."}),e("label",{className:Z.ackLabel,children:[e("input",{type:"checkbox",checked:i,onChange:h=>l(h.target.checked),disabled:w}),e("span",{children:"I understand this permanently deletes my library"})]})]}),e(G.Actions,{children:[e(D,{variant:"secondary",onClick:g,disabled:w,children:"Cancel"}),e(D,{variant:"danger",onClick:p,disabled:!i||w,children:w?"Clearing...":"Yes, delete everything"})]})]})]})},Zt=()=>{const[t,n]=r(""),[o,i]=r([]),[l,w]=r(null),[b,d]=r(!0),[s,u]=r({show:!1,message:"",type:"info"}),g=async()=>{try{d(!0);const C=await(await fetch("/api/auth/settings/rclone")).json();n(C.remote||""),i(C.availableRemotes||[]),w(C.activeRemote||null)}catch(h){console.error("Failed to fetch Rclone settings",h)}finally{d(!1)}};U(()=>{g()},[]);const p=async()=>{try{if((await fetch("/api/auth/settings/rclone",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({remote:t})})).ok)u({show:!0,message:"Rclone configuration saved successfully. You must restart the server for these changes to take effect.",type:"success"}),g();else throw new Error("Failed to save")}catch{u({show:!0,message:"Failed to save Rclone configuration.",type:"error"})}};return b?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:y.sectionCard,children:[e("h3",{className:y.title,children:"Rclone Cloud Sync"}),e("p",{className:y.signIn,children:"Configure which Rclone remote to use for database synchronization."}),l?e("div",{className:y.userInfo,children:e("p",{children:["Current Active Remote: ",e("strong",{children:l})]})}):e("p",{className:y.warning,style:{marginBottom:"1.5rem"},children:"Rclone sync is not currently active. Ensure rclone is installed and a remote is configured."}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Remote Name"}),e("div",{className:y.inputWrapper,children:e("select",{className:y.select,value:t,onChange:h=>n(h.target.value),children:[e("option",{value:"",children:"(Disabled / None)"}),o.map(h=>e("option",{value:h,children:h},h)),t&&!o.includes(t)&&e("option",{value:t,children:[t," (Manual)"]})]})}),e("p",{className:y.warning,style:{marginTop:"12px"},children:[e("strong",{children:"Note:"})," You can choose which provider is active using the selector at the top of the page."]})]}),e("div",{className:y.actions,children:e(D,{onClick:p,children:"Save Rclone Settings"})}),e(G,{isOpen:s.show,onClose:()=>u(h=>({...h,show:!1})),width:"sm",children:[e(G.Body,{children:e("p",{children:s.message})}),e(G.Actions,{children:e(D,{onClick:()=>u(h=>({...h,show:!1})),children:"OK"})})]})]})},ea=()=>{const[t,n]=r(null),[o,i]=r(!0),l=async()=>{try{const u=await(await fetch("/api/auth/settings/sync")).json();n(u)}catch(s){console.error("Failed to fetch sync settings",s)}finally{i(!1)}};U(()=>{l()},[]);const w=async s=>{const u=s.target.value;try{const g=await fetch("/api/auth/settings/sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:u})});if(g.ok){const p=await g.json();n(h=>h?{...h,activeProvider:p.activeProvider}:null),await l(),ie.success(`Sync provider updated to ${u==="default"?"Default Order":u}`)}else ie.error("Failed to update sync provider")}catch{ie.error("Error updating sync provider")}};if(o||!t)return null;const b=[{value:"default",label:"Default (Priority Based)"}];t.authenticatedProviders.github&&b.push({value:"github",label:"GitHub"}),t.authenticatedProviders.google&&b.push({value:"google",label:"Google Drive"}),t.authenticatedProviders.rclone&&b.push({value:"rclone",label:"Rclone"}),b.push({value:"none",label:"None (Local Only)"});const d=s=>s==="none"?"Local Only (No Sync)":s==="google"?"Google Drive":s==="github"?"GitHub":s==="rclone"?"Rclone":s;return e("div",{className:m.sectionCard,children:[e("h3",{children:"Active Sync Provider"}),e("p",{children:'Choose which provider to use for synchronization. "Default" uses the first available provider you are logged into.'}),e("div",{style:{marginBottom:"1.5rem",padding:"0.75rem",background:"rgba(255, 255, 255, 0.03)",borderRadius:"var(--radius-md)",borderLeft:"4px solid var(--accent)",fontSize:"var(--font-size-sm)"},children:["Current Status:"," ",e("strong",{style:{color:"var(--accent-light)",textTransform:"capitalize"},children:d(t.actualActiveProvider)})]}),e("div",{className:m.settingRow,children:[e("label",{htmlFor:"sync-provider-select",children:"Selected Preference"}),e("select",{id:"sync-provider-select",value:t.activeProvider,onChange:w,style:{padding:"0.5rem",borderRadius:"var(--radius-md)",background:"rgba(255, 255, 255, 0.05)",color:"var(--text-primary)",border:"1px solid var(--glass-border)",fontSize:"var(--font-size-sm)",minWidth:"220px",outline:"none",cursor:"pointer"},children:b.map(s=>e("option",{value:s.value,children:s.label},s.value))})]})]})};function ta(){return"javascript:"+encodeURIComponent(`(function(){
1
+ import{d as r,A as V,h as U,u as e,q as te,S as ee,T as Te,o as Re,a as De,g as ge,_ as Ie}from"./vendor-core-8R2fFbyN.js";import{d as Pe,B as D,M as G,h as xe,T as F,z as me,D as ie,E as Le,F as Oe,q as de,u as Ae,G as Ue,w as pe,x as Me,H as Ee,I as $e,V as je,J as Ge,K as Ke,L as He}from"./index-lo-bz7f2.js";import{u as ue}from"./vendor-query-BXRECSI6.js";import{I as q}from"./vendor-icons-CDMuNDeL.js";const oe={"title-preference-container":"_title-preference-container_sdqgs_1","toggle-button":"_toggle-button_sdqgs_21","toggle-label":"_toggle-label_sdqgs_51"},ce=["name","nativeName","englishName"],le={name:"Default (Romaji)",nativeName:"Native",englishName:"English"},Fe=()=>{const{titlePreference:t,setTitlePreference:n,loading:o}=Pe(),[i,l]=r(le[t]),[w,b]=r(!1),d=V(null);U(()=>{o||l(le[t])},[t,o]);const s=async()=>{if(w)return;b(!0);const g=(ce.indexOf(t)+1)%ce.length,p=ce[g],h=le[p];d.current&&(d.current.style.transform="translateX(-100%)",d.current.style.opacity="0"),setTimeout(async()=>{l(h),n(p),d.current&&(d.current.style.transition="none",d.current.style.transform="translateX(100%)",d.current.style.opacity="0",d.current.offsetWidth,d.current.style.transition="transform 0.3s ease-out, opacity 0.3s ease-out",d.current.style.transform="translateX(0)",d.current.style.opacity="1");try{await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:"titlePreference",value:p})})}catch(C){console.error("Error saving title preference:",C)}finally{b(!1)}},300)};return o?e("p",{children:"Loading title preference..."}):e("div",{className:oe["title-preference-container"],children:[e("h4",{children:"Anime Title Display Preference"}),e("button",{onClick:s,className:oe["toggle-button"],disabled:w,children:e("span",{ref:d,className:oe["toggle-label"],children:i})})]})},ze="_settingsHeader_14a5d_1",Be="_pageTitle_14a5d_6",We="_pageSubtitle_14a5d_14",qe="_settingsLayout_14a5d_20",Ve="_sidebar_14a5d_27",Je="_sidebarIndicator_14a5d_35",Ye="_sidebarItem_14a5d_50",Qe="_active_14a5d_72",Xe="_mainContent_14a5d_80",Ze="_tabContent_14a5d_85",et="_sectionCard_14a5d_103",tt="_settingItem_14a5d_127",at="_settingRow_14a5d_132",nt="_controls_14a5d_145",st="_status_14a5d_151",m={settingsHeader:ze,pageTitle:Be,pageSubtitle:We,settingsLayout:qe,sidebar:Ve,sidebarIndicator:Je,sidebarItem:Ye,active:Qe,mainContent:Xe,tabContent:Ze,sectionCard:et,settingItem:tt,settingRow:at,controls:nt,status:st},rt="_sectionCard_wt900_12",it="_title_wt900_22",ot="_signIn_wt900_29",ct="_userInfo_wt900_36",lt="_warning_wt900_58",dt="_formGroup_wt900_65",ut="_label_wt900_69",ht="_inputWrapper_wt900_79",gt="_input_wt900_79",mt="_select_wt900_103",pt="_actions_wt900_140",yt="_hr_wt900_148",y={sectionCard:rt,title:it,signIn:ot,userInfo:ct,warning:lt,formGroup:dt,label:ut,inputWrapper:ht,input:gt,select:mt,actions:pt,hr:yt},ft=()=>{const[t,n]=r(!0),[o,i]=r(!1),[l,w]=r(!1),[b,d]=r(null),[s,u]=r({status:"idle"}),[g,p]=r(!1),[h,C]=r(""),[k,f]=r(!1),I=V(null),[T,P]=r({show:!1,message:"",type:"info"}),N=()=>{I.current&&(window.clearInterval(I.current),I.current=null)},L=te(S=>{w(S.authenticated),d(S.user||S.device.user||null),u(S.device),p(!!S.hasCustomClientId)},[]),O=te(async()=>{const M=await(await fetch("/api/auth/github/status")).json();L(M)},[L]),E=async()=>{try{const M=await(await fetch("/api/auth/github/poll")).json();u(M),M.status==="success"?(N(),await O(),P({show:!0,message:"GitHub authentication complete. Sync has been initialized.",type:"success"})):M.status==="error"&&(N(),P({show:!0,message:M.error||"GitHub authentication failed.",type:"error"}))}catch{N(),P({show:!0,message:"Failed to poll GitHub authentication status.",type:"error"})}},_=(S=5)=>{N(),I.current=window.setInterval(E,Math.max(S,5)*1e3)};U(()=>(O().catch(()=>{P({show:!0,message:"Failed to load GitHub sync status.",type:"error"})}).finally(()=>n(!1)),N),[O]);const v=async()=>{i(!0);try{const S=await fetch("/api/auth/github/start",{method:"POST"}),M=await S.json();if(!S.ok)throw new Error("Failed to start GitHub authentication.");u(M),_(M.verification?.interval)}catch(S){P({show:!0,message:S instanceof Error?S.message:"Failed to start GitHub authentication.",type:"error"})}finally{i(!1)}},R=async()=>{try{await fetch("/api/auth/github/logout",{method:"POST"}),w(!1),d(null),u({status:"idle"}),P({show:!0,message:"Signed out of GitHub sync.",type:"success"})}catch{P({show:!0,message:"Failed to sign out of GitHub.",type:"error"})}},$=async()=>{f(!0);try{if(!(await fetch("/api/auth/github/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:h})})).ok)throw new Error("save failed");C(""),await O(),P({show:!0,message:"Custom GitHub auth saved.",type:"success"})}catch{P({show:!0,message:"Failed to save override.",type:"error"})}finally{f(!1)}},K=async()=>{f(!0);try{await fetch("/api/auth/github/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:""})}),C(""),await O(),P({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{P({show:!0,message:"Failed to clear override.",type:"error"})}finally{f(!1)}};return t?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:y.sectionCard,children:[e("h3",{className:y.title,children:"GitHub Cloud Sync"}),e("p",{className:y.signIn,children:"Sync local data through a private GitHub repository named dango-sync-data."}),l&&b?e("div",{className:y.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:b.name||b.login})]}),e(D,{variant:"danger",onClick:R,children:"Sign Out"})]}):e("div",{className:y.signIn,children:e(D,{onClick:v,disabled:o||s.status==="pending",children:o||s.status==="pending"?"Waiting for GitHub...":"Sign in with GitHub"})}),s.status==="pending"&&s.verification&&e(ee,{children:[e("hr",{className:y.hr}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Verification URL"}),e("div",{className:y.inputWrapper,children:[e("input",{className:y.input,value:s.verification.verification_uri,readOnly:!0}),e(D,{onClick:()=>{const S=s.verification?.verification_uri;S&&/^https?:\/\//i.test(S)&&window.open(S,"_blank","noopener,noreferrer")},children:"Open"})]})]}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Device Code"}),e("input",{className:y.input,value:s.verification.user_code,readOnly:!0})]})]}),s.status==="error"&&e("p",{className:y.warning,children:s.error}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",g?"(override active)":""]}),e("div",{className:y.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:y.label,children:"Client ID (optional)"}),e("input",{className:y.input,value:h,onChange:S=>C(S.currentTarget.value),placeholder:"Your GitHub OAuth app ID"})]}),e("div",{className:y.actions,children:[e(D,{onClick:$,disabled:k,children:"Save override"}),e(D,{variant:"secondary",onClick:K,disabled:k,children:"Use dango defaults"})]})]}),e(G,{isOpen:T.show,onClose:()=>P(S=>({...S,show:!1})),width:"sm",children:[e(G.Body,{children:e("p",{children:T.message})}),e(G.Actions,{children:e(D,{onClick:()=>P(S=>({...S,show:!1})),children:"OK"})})]})]})},wt=()=>{const[t,n]=r(!0),[o,i]=r(null),[l,w]=r(!1),[b,d]=r(!1),[s,u]=r(""),[g,p]=r(""),[h,C]=r(""),[k,f]=r(!1),[I,T]=r({show:!1,message:"",type:"info"}),P=async()=>{try{const R=await(await fetch("/api/auth/user")).json();i(R?.email?R:null)}catch{i(null)}},N=async()=>{try{const[v,R]=await Promise.all([fetch("/api/auth/config-status"),fetch("/api/auth/google-auth")]),$=await v.json(),K=await R.json();w(!!$.hasConfig),d(!!(K.hasCustomWorkerUrl||K.hasCustomClientId||K.hasClientSecret))}catch(v){console.error("Failed to fetch config status",v)}};U(()=>{(async()=>{n(!0),await Promise.all([P(),N()]);try{new URLSearchParams(window.location.search).get("google_auth")==="success"&&(await P(),window.history.replaceState(null,"",window.location.pathname))}catch{}n(!1)})();const R=$=>{$.origin===window.location.origin&&typeof $.data=="object"&&$.data!==null&&$.data.type==="GOOGLE_AUTH_SUCCESS"&&(i($.data.user),window.location.reload())};return window.addEventListener("message",R),()=>window.removeEventListener("message",R)},[]);const L=async()=>{try{const R=await(await fetch("/api/auth/google/login",{method:"POST"})).json();if(R.authenticated){window.location.reload();return}if(R.url){if(typeof window.DangoBridge<"u"){window.location.href=R.url;return}const K=600,S=700,M=window.innerWidth/2-K/2,ae=window.innerHeight/2-S/2;window.open(R.url,"GoogleAuth",`width=${K},height=${S},top=${ae},left=${M}`)}else throw new Error("Auth URL not available")}catch{T({show:!0,message:"Authentication failed. Ensure server is configured correctly.",type:"error"})}},O=async()=>{try{await fetch("/api/auth/logout",{method:"POST"}),i(null),T({show:!0,message:"Successfully signed out.",type:"success"}),window.location.reload()}catch(v){console.error("Sign out failed",v),T({show:!0,message:"Failed to sign out.",type:"error"})}},E=async()=>{f(!0);try{if(!(await fetch("/api/auth/google-auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workerUrl:s,clientId:g,clientSecret:h})})).ok)throw new Error("save failed");u(""),p(""),C(""),await N(),T({show:!0,message:"Custom auth saved. Restart may be required.",type:"success"})}catch{T({show:!0,message:"Failed to save override.",type:"error"})}finally{f(!1)}},_=async()=>{f(!0);try{await fetch("/api/auth/google-auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workerUrl:"",clientId:"",clientSecret:""})}),u(""),p(""),C(""),await N(),T({show:!0,message:"Custom auth cleared. Using dango defaults.",type:"success"})}catch{T({show:!0,message:"Failed to clear override.",type:"error"})}finally{f(!1)}};return t?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:y.sectionCard,children:[e("h3",{className:y.title,children:"Google Drive Sync"}),o?e("div",{className:y.userInfo,children:[e("p",{children:["Signed in as: ",e("strong",{children:o.name})," (",o.email,")"]}),e(D,{variant:"danger",onClick:O,children:"Sign Out"})]}):e("div",{className:y.signIn,children:[e("p",{children:"Sign in with your Google account to enable synchronization features."}),e(D,{onClick:L,disabled:!l,children:"Sign in with Google"}),!l&&e("p",{className:y.warning,children:"Google sync is not configured on the server."})]}),e("details",{style:{marginTop:"1rem",fontSize:"var(--font-size-sm)"},children:[e("summary",{style:{cursor:"pointer",color:"var(--text-secondary)"},children:["Advanced: use your own auth ",b?"(override active)":""]}),e("div",{className:y.formGroup,style:{marginTop:"0.75rem"},children:[e("label",{className:y.label,children:"Worker URL (optional)"}),e("input",{className:y.input,value:s,onChange:v=>u(v.currentTarget.value),placeholder:"https://your-worker.workers.dev"})]}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Client ID (optional)"}),e("input",{className:y.input,value:g,onChange:v=>p(v.currentTarget.value),placeholder:"Your Google OAuth client ID"})]}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Client Secret (optional)"}),e("input",{type:"password",className:y.input,value:h,onChange:v=>C(v.currentTarget.value),placeholder:"Your Google OAuth secret"})]}),e("div",{className:y.actions,children:[e(D,{onClick:E,disabled:k,children:"Save override"}),e(D,{variant:"secondary",onClick:_,disabled:k,children:"Use dango defaults"})]})]}),e(G,{isOpen:I.show,onClose:()=>T(v=>({...v,show:!1})),width:"sm",children:[e(G.Body,{children:e("p",{children:I.message})}),e(G.Actions,{children:e(D,{onClick:()=>T(v=>({...v,show:!1})),children:"OK"})})]})]})},vt="_sectionCard_1pqo4_1",bt="_settingItem_1pqo4_26",_t="_settingRow_1pqo4_31",kt="_modalOverlay_1pqo4_38",St="_modal_1pqo4_38",Ct="_modalActions_1pqo4_73",Nt="_modalSecondary_1pqo4_79",Tt="_modalPrimary_1pqo4_89",j={sectionCard:vt,settingItem:bt,settingRow:_t,modalOverlay:kt,modal:St,modalActions:Ct,modalSecondary:Nt,modalPrimary:Tt},Rt={anime:{heading:"Watchlist Preferences",blurb:"Customize your experience when managing your watchlist and series entries.",skipKey:"skipRemoveConfirmation",ignoreKey:"ignoreAdultContent",listOnlyKey:"cwWatchlistOnly",skipLabel:"Skip confirmation when removing from watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in watchlist",listNoun:"watchlist",continueNoun:"continue watching",adultCountUrl:"/api/continue-watching/adult-count",purgeUrl:"/api/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["allContinueWatching"]]},manga:{heading:"Reading List Preferences",blurb:"Customize your experience when managing your reading list and manga entries.",skipKey:"mangaSkipRemoveConfirmation",ignoreKey:"mangaIgnoreAdultContent",listOnlyKey:"mangaCwWatchlistOnly",skipLabel:"Skip confirmation when removing from reading list",ignoreLabel:"Hide adult content from continue reading",listOnlyLabel:"Only show continue reading for manga in reading list",listNoun:"reading list",continueNoun:"continue reading",adultCountUrl:"/api/manga/continue-reading/adult-count",purgeUrl:"/api/manga/continue-reading/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue reading`,invalidateKeys:[["manga-continue-reading"]]},tv:{heading:"TV Watchlist Preferences",blurb:"Customize your experience when managing your TV watchlist and series entries.",skipKey:"tvSkipRemoveConfirmation",ignoreKey:"tvIgnoreAdultContent",listOnlyKey:"tvCwWatchlistOnly",skipLabel:"Skip confirmation when removing from TV watchlist",ignoreLabel:"Hide adult content from continue watching",listOnlyLabel:"Only show continue watching for shows in TV watchlist",listNoun:"TV watchlist",continueNoun:"continue watching",adultCountUrl:"/api/tv/continue-watching/adult-count",purgeUrl:"/api/tv/continue-watching/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue watching`,invalidateKeys:[["tv-continue-watching"]]},asmr:{heading:"Listening List Preferences",blurb:"Customize your experience when managing your listening list and work entries.",skipKey:"asmrSkipRemoveConfirmation",ignoreKey:"asmrIgnoreAdultContent",listOnlyKey:"asmrCwWatchlistOnly",skipLabel:"Skip confirmation when removing from listening list",ignoreLabel:"Hide adult content from continue listening",listOnlyLabel:"Only show continue listening for works in listening list",listNoun:"listening list",continueNoun:"continue listening",adultCountUrl:"/api/asmr/continue-listening/adult-count",purgeUrl:"/api/asmr/continue-listening/purge-adult",purgeDoneText:t=>`Removed ${t??0} entries from continue listening`,invalidateKeys:[["asmr-continue-listening"]]}},Dt=(t,n)=>{if(t==null)return n;const o=String(t);return o==="true"||o==="1"?!0:o==="false"||o==="0"?!1:n},ye=(t,n,o)=>{const[i,l]=r(n),[w,b]=r(!1),d=ue();return U(()=>{(async()=>{try{const p=await(await fetch(`/api/settings?key=${t}`)).json();l(Dt(p.value,n))}catch(g){console.error("Failed to fetch setting",g)}})()},[t,n]),{value:i,setValue:l,isUpdating:w,toggle:async()=>{if(w)return;b(!0);const u=!i;l(u);try{await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:t,value:u})});for(const g of o)d.invalidateQueries({queryKey:g})}catch(g){console.error("Error saving setting:",g),l(!u)}finally{b(!1)}}}},It=()=>{const{contentType:t}=xe(),n=Rt[t],[o,i]=r(!1),[l,w]=r(!0),[b,d]=r(!1),s=ye(n.ignoreKey,!0,n.invalidateKeys),u=ye(n.listOnlyKey,!1,n.invalidateKeys),[g,p]=r(null),[h,C]=r(!1),k=ue();U(()=>{w(!0),(async()=>{try{const O=await(await fetch(`/api/settings?key=${n.skipKey}`)).json();String(O.value)==="true"||String(O.value)==="1"?i(!0):i(!1)}catch(L){console.error("Failed to fetch setting",L)}finally{w(!1)}})()},[n.skipKey]);const f=async()=>{if(b)return;d(!0);const N=!o;i(N);try{await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n.skipKey,value:N})})}catch(L){console.error("Error saving setting:",L),i(!N)}finally{d(!1)}},I=async()=>{if(!s.isUpdating){if(s.value)try{const L=await(await fetch(n.adultCountUrl)).json();if(typeof L.count=="number"&&L.count>0){p(L.count);return}}catch(N){console.error("Failed to fetch adult count",N)}s.toggle()}},T=()=>{p(null),s.toggle()},P=async()=>{if(!h){C(!0);try{const L=await(await fetch(n.purgeUrl,{method:"POST"})).json();me.success(n.purgeDoneText(L.removed));for(const O of n.invalidateKeys)k.invalidateQueries({queryKey:O})}catch(N){console.error("Failed to purge adult entries",N),me.error("Failed to remove adult entries")}finally{C(!1),p(null)}s.toggle()}};return l?e("div",{children:"Loading settings..."}):e("div",{className:j.sectionCard,children:[e("h3",{children:n.heading}),e("p",{children:n.blurb}),e("div",{className:j.settingItem,children:e("div",{className:j.settingRow,children:[e("label",{htmlFor:"skip-confirmation-toggle",children:n.skipLabel}),e(F,{isChecked:o,onChange:f,id:"skip-confirmation-toggle",disabled:b})]})}),e("div",{className:j.settingItem,children:e("div",{className:j.settingRow,children:[e("label",{htmlFor:"ignore-adult-toggle",children:n.ignoreLabel}),e(F,{isChecked:s.value,onChange:I,id:"ignore-adult-toggle",disabled:s.isUpdating})]})}),e("div",{className:j.settingItem,children:e("div",{className:j.settingRow,children:[e("label",{htmlFor:"cw-watchlist-only-toggle",children:n.listOnlyLabel}),e(F,{isChecked:u.value,onChange:u.toggle,id:"cw-watchlist-only-toggle",disabled:u.isUpdating})]})}),g!==null&&e("div",{className:j.modalOverlay,onClick:()=>p(null),children:e("div",{className:j.modal,onClick:N=>N.stopPropagation(),children:[e("h4",{children:"Show adult entries?"}),e("p",{children:[g," adult ",g===1?"entry":"entries"," not in your"," ",n.listNoun," ",g===1?"is":"are"," currently hidden from"," ",n.continueNoun,". You can purge ",g===1?"it":"them"," from the database instead of showing ",g===1?"it":"them","."]}),e("div",{className:j.modalActions,children:[e("button",{type:"button",className:j.modalSecondary,onClick:T,disabled:h,children:"Show them"}),e("button",{type:"button",className:j.modalPrimary,onClick:P,disabled:h,children:h?"Purging...":`Purge ${g}`})]})]})})]})},Pt="_sectionCard_jkggs_1",xt="_statsGrid_jkggs_26",Lt="_statCard_jkggs_33",Ot="_statLabel_jkggs_43",At="_statValue_jkggs_51",Ut="_statMeta_jkggs_57",Mt="_statusBanner_jkggs_63",Et="_statusSuccess_jkggs_74",$t="_statusUpdating_jkggs_80",jt="_statusError_jkggs_86",Gt="_sha_jkggs_92",Kt="_settingItem_jkggs_99",Ht="_settingRow_jkggs_104",Ft="_settingTitle_jkggs_111",zt="_settingSubtitle_jkggs_117",Bt="_actionsRow_jkggs_124",x={sectionCard:Pt,statsGrid:xt,statCard:Lt,statLabel:Ot,statValue:At,statMeta:Ut,statusBanner:Mt,statusSuccess:Et,statusUpdating:$t,statusError:jt,sha:Gt,settingItem:Kt,settingRow:Ht,settingTitle:Ft,settingSubtitle:zt,actionsRow:Bt},Wt=()=>{const[t,n]=r(null),[o,i]=r(!0),[l,w]=r(!1),[b,d]=r(!1),s=V(null),u=async()=>{try{const k=await fetch("/api/settings/offline-db");if(k.ok){const f=await k.json();return n(f),f}}catch(k){console.error("Failed to fetch offline DB info:",k)}finally{i(!1)}return null};U(()=>(u(),()=>{s.current&&window.clearInterval(s.current)}),[]),U(()=>{t?.isRefreshing?s.current||(s.current=window.setInterval(async()=>{const k=await u();k&&!k.isRefreshing&&s.current&&(window.clearInterval(s.current),s.current=null)},2e3)):s.current&&(window.clearInterval(s.current),s.current=null)},[t?.isRefreshing]);const g=async()=>{if(!t||l)return;const k=!t.autoUpdateEnabled;w(!0),n({...t,autoUpdateEnabled:k});try{(await fetch("/api/settings/offline-db/auto-update",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({enabled:k})})).ok||n({...t,autoUpdateEnabled:!k})}catch(f){console.error("Failed to update auto update setting:",f),n({...t,autoUpdateEnabled:!k})}finally{w(!1)}},p=async()=>{if(!(t?.isRefreshing||b)){d(!0);try{(await fetch("/api/settings/offline-db/update",{method:"POST"})).ok&&n(f=>f?{...f,isRefreshing:!0,lastStatus:"updating",lastMessage:"Downloading database..."}:null)}catch(k){console.error("Failed to trigger offline DB update:",k)}finally{d(!1)}}},h=k=>{if(!k)return"Never";try{return new Date(k).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"})}catch{return k}},C=t?.isRefreshing||b;return e("div",{className:x.sectionCard,children:[e("h3",{children:"Offline Metadata Database"}),e("p",{children:"Local MAL to AniList ID map used for instant imports and metadata enrichment without hitting rate-limited APIs. Updates automatically every Saturday in the background."}),e("div",{className:x.statsGrid,children:[e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"MAL Mapped"}),e("span",{className:x.statValue,children:o?"—":(t?.totalMalMapped??0).toLocaleString()})]}),e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"Release"}),e("span",{className:x.statMeta,children:o?"—":t?.releaseTag??"Never"})]}),e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"Last Checked"}),e("span",{className:x.statMeta,children:o?"—":h(t?.lastCheckedAt??null)})]}),e("div",{className:x.statCard,children:[e("span",{className:x.statLabel,children:"Last Updated"}),e("span",{className:x.statMeta,children:o?"—":h(t?.lastUpdatedAt??null)})]})]}),t?.lastMessage&&e("div",{className:`${x.statusBanner} ${t.lastStatus==="failed"?x.statusError:t.lastStatus==="updating"?x.statusUpdating:x.statusSuccess}`,children:[e("span",{children:t.lastMessage}),t.contentSha256&&e("span",{className:x.sha,children:["sha:",t.contentSha256.slice(0,12)]})]}),e("div",{className:x.settingItem,children:e("div",{className:x.settingRow,children:[e("div",{children:[e("span",{className:x.settingTitle,children:"Weekly Automatic Updates (Saturdays)"}),e("div",{className:x.settingSubtitle,children:"Download and index new database releases in the background. Catches up on startup if the server was offline."})]}),e(F,{id:"offline-db-auto-update-toggle",isChecked:t?t.autoUpdateEnabled:!0,onChange:g,disabled:o||l})]})}),e("div",{className:x.actionsRow,children:e(D,{onClick:p,disabled:o||C,children:C?"Updating Database...":"Update Offline Database Now"})})]})},qt="_sectionCard_1g4qx_1",Vt="_dangerCard_1g4qx_26",Jt="_status_1g4qx_34",Yt="_warningText_1g4qx_40",Qt="_ackLabel_1g4qx_44",Z={sectionCard:qt,dangerCard:Vt,status:Jt,warningText:Yt,ackLabel:Qt},Xt=()=>{const t=ue(),[n,o]=r(!1),[i,l]=r(!1),[w,b]=r(!1),[d,s]=r(""),u=()=>{l(!1),s(""),o(!0)},g=()=>{w||(o(!1),l(!1))},p=async()=>{if(!(!i||w)){b(!0),s("");try{const h=await fetch("/api/database/clear",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({confirm:!0})}),C=await h.json();if(!h.ok)throw new Error(C.error||"Failed to clear database");const k=C.deleted,f=C.deletedManga,I=C.deletedTv,T=C.deletedAsmr,P=Object.values(k).reduce((E,_)=>E+(_||0),0)+Object.values(f??{}).reduce((E,_)=>E+(_||0),0)+Object.values(I??{}).reduce((E,_)=>E+(_||0),0)+Object.values(T??{}).reduce((E,_)=>E+(_||0),0),N=(f?.manga_library??0)+(f?.manga_progress??0),L=(I?.tv_library??0)+(I?.tv_progress??0),O=(T?.asmr_library??0)+(T?.asmr_progress??0);s(`Library cleared — ${k.watchlist??0} watchlist entries, ${N} manga rows, ${L} TV rows, ${O} ASMR rows and ${P} total rows removed.`),t.invalidateQueries({queryKey:["watchlist"]}),t.invalidateQueries({queryKey:["allContinueWatching"]}),t.invalidateQueries({queryKey:["manga-library"]}),t.invalidateQueries({queryKey:["manga-library-ids"]}),t.invalidateQueries({queryKey:["manga-continue-reading"]}),t.invalidateQueries({queryKey:["tv-library"]}),t.invalidateQueries({queryKey:["tv-library-ids"]}),t.invalidateQueries({queryKey:["tv-continue-watching"]}),t.invalidateQueries({queryKey:["asmr-library"]}),t.invalidateQueries({queryKey:["asmr-library-ids"]}),t.invalidateQueries({queryKey:["asmr-continue-listening"]}),o(!1)}catch(h){s(h.message)}finally{b(!1),l(!1)}}};return e("div",{className:`${Z.sectionCard} ${Z.dangerCard}`,children:[e("h3",{children:"Danger Zone"}),e("p",{children:"Permanently delete your library (watchlist, watched episodes, queue, cached show metadata, manga reading list and reading progress, TV watchlist and watch progress, ASMR listening list and listening progress) to start fresh. Your settings, sync state and the offline metadata cache are preserved."}),e(D,{variant:"danger",onClick:u,children:"Clear Library Data"}),d&&e("p",{className:Z.status,children:d}),e(G,{isOpen:n,onClose:g,title:"Clear library data?",width:"sm",children:[e(G.Body,{children:[e("p",{className:Z.warningText,children:"This permanently deletes everything in your library. It acts on the active database (dev or prod, per server config) and cannot be undone. Settings, sync state and the offline metadata cache are kept."}),e("label",{className:Z.ackLabel,children:[e("input",{type:"checkbox",checked:i,onChange:h=>l(h.target.checked),disabled:w}),e("span",{children:"I understand this permanently deletes my library"})]})]}),e(G.Actions,{children:[e(D,{variant:"secondary",onClick:g,disabled:w,children:"Cancel"}),e(D,{variant:"danger",onClick:p,disabled:!i||w,children:w?"Clearing...":"Yes, delete everything"})]})]})]})},Zt=()=>{const[t,n]=r(""),[o,i]=r([]),[l,w]=r(null),[b,d]=r(!0),[s,u]=r({show:!1,message:"",type:"info"}),g=async()=>{try{d(!0);const C=await(await fetch("/api/auth/settings/rclone")).json();n(C.remote||""),i(C.availableRemotes||[]),w(C.activeRemote||null)}catch(h){console.error("Failed to fetch Rclone settings",h)}finally{d(!1)}};U(()=>{g()},[]);const p=async()=>{try{if((await fetch("/api/auth/settings/rclone",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({remote:t})})).ok)u({show:!0,message:"Rclone configuration saved successfully. You must restart the server for these changes to take effect.",type:"success"}),g();else throw new Error("Failed to save")}catch{u({show:!0,message:"Failed to save Rclone configuration.",type:"error"})}};return b?e("div",{style:{color:"var(--text-secondary)",padding:"1.5rem"},children:"Loading..."}):e("div",{className:y.sectionCard,children:[e("h3",{className:y.title,children:"Rclone Cloud Sync"}),e("p",{className:y.signIn,children:"Configure which Rclone remote to use for database synchronization."}),l?e("div",{className:y.userInfo,children:e("p",{children:["Current Active Remote: ",e("strong",{children:l})]})}):e("p",{className:y.warning,style:{marginBottom:"1.5rem"},children:"Rclone sync is not currently active. Ensure rclone is installed and a remote is configured."}),e("div",{className:y.formGroup,children:[e("label",{className:y.label,children:"Remote Name"}),e("div",{className:y.inputWrapper,children:e("select",{className:y.select,value:t,onChange:h=>n(h.target.value),children:[e("option",{value:"",children:"(Disabled / None)"}),o.map(h=>e("option",{value:h,children:h},h)),t&&!o.includes(t)&&e("option",{value:t,children:[t," (Manual)"]})]})}),e("p",{className:y.warning,style:{marginTop:"12px"},children:[e("strong",{children:"Note:"})," You can choose which provider is active using the selector at the top of the page."]})]}),e("div",{className:y.actions,children:e(D,{onClick:p,children:"Save Rclone Settings"})}),e(G,{isOpen:s.show,onClose:()=>u(h=>({...h,show:!1})),width:"sm",children:[e(G.Body,{children:e("p",{children:s.message})}),e(G.Actions,{children:e(D,{onClick:()=>u(h=>({...h,show:!1})),children:"OK"})})]})]})},ea=()=>{const[t,n]=r(null),[o,i]=r(!0),l=async()=>{try{const u=await(await fetch("/api/auth/settings/sync")).json();n(u)}catch(s){console.error("Failed to fetch sync settings",s)}finally{i(!1)}};U(()=>{l()},[]);const w=async s=>{const u=s.target.value;try{const g=await fetch("/api/auth/settings/sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:u})});if(g.ok){const p=await g.json();n(h=>h?{...h,activeProvider:p.activeProvider}:null),await l(),ie.success(`Sync provider updated to ${u==="default"?"Default Order":u}`)}else ie.error("Failed to update sync provider")}catch{ie.error("Error updating sync provider")}};if(o||!t)return null;const b=[{value:"default",label:"Default (Priority Based)"}];t.authenticatedProviders.github&&b.push({value:"github",label:"GitHub"}),t.authenticatedProviders.google&&b.push({value:"google",label:"Google Drive"}),t.authenticatedProviders.rclone&&b.push({value:"rclone",label:"Rclone"}),b.push({value:"none",label:"None (Local Only)"});const d=s=>s==="none"?"Local Only (No Sync)":s==="google"?"Google Drive":s==="github"?"GitHub":s==="rclone"?"Rclone":s;return e("div",{className:m.sectionCard,children:[e("h3",{children:"Active Sync Provider"}),e("p",{children:'Choose which provider to use for synchronization. "Default" uses the first available provider you are logged into.'}),e("div",{style:{marginBottom:"1.5rem",padding:"0.75rem",background:"rgba(255, 255, 255, 0.03)",borderRadius:"var(--radius-md)",borderLeft:"4px solid var(--accent)",fontSize:"var(--font-size-sm)"},children:["Current Status:"," ",e("strong",{style:{color:"var(--accent-light)",textTransform:"capitalize"},children:d(t.actualActiveProvider)})]}),e("div",{className:m.settingRow,children:[e("label",{htmlFor:"sync-provider-select",children:"Selected Preference"}),e("select",{id:"sync-provider-select",value:t.activeProvider,onChange:w,style:{padding:"0.5rem",borderRadius:"var(--radius-md)",background:"rgba(255, 255, 255, 0.05)",color:"var(--text-primary)",border:"1px solid var(--glass-border)",fontSize:"var(--font-size-sm)",minWidth:"220px",outline:"none",cursor:"pointer"},children:b.map(s=>e("option",{value:s.value,children:s.label},s.value))})]})]})};function ta(){return"javascript:"+encodeURIComponent(`(function(){
2
2
  if(!/(^|\\.)discord\\.com$/.test(location.hostname)){alert('Dango: use this bookmarklet while on discord.com');return}
3
3
  var t=null;
4
4
  try{
@@ -1 +1 @@
1
- import{u as e,g as t}from"./vendor-core-8R2fFbyN.js";import{u as l}from"./index-IZgh1beL.js";const a="_skeletonCard_1b0hr_1",i="_poster_1b0hr_11",c="_line_1b0hr_20",_="_info_1b0hr_38",d="_short_1b0hr_54",h="_horizontal_1b0hr_60",m="_vertical_1b0hr_78",v="_lowEnd_1b0hr_97",o={skeletonCard:a,poster:i,line:c,"skeleton-wave":"_skeleton-wave_1b0hr_1",info:_,short:d,horizontal:h,vertical:m,lowEnd:v},b=({layout:n="vertical"})=>{const{lowEndMode:r}=l();return e("div",{className:`${o.skeletonCard} ${o[n]} ${r?o.lowEnd:""}`,children:[e("div",{className:o.poster}),e("div",{className:o.info,children:[e("div",{className:o.line}),e("div",{className:`${o.line} ${o.short}`})]})]})},k=({count:n=14,layout:r="vertical"})=>e("div",{className:"grid-container",children:Array.from({length:n}).map((p,s)=>e(b,{layout:r},s))}),E=t.memo(k);export{b as A,E as S};
1
+ import{u as e,g as t}from"./vendor-core-8R2fFbyN.js";import{u as l}from"./index-lo-bz7f2.js";const a="_skeletonCard_1b0hr_1",i="_poster_1b0hr_11",c="_line_1b0hr_20",_="_info_1b0hr_38",d="_short_1b0hr_54",h="_horizontal_1b0hr_60",m="_vertical_1b0hr_78",v="_lowEnd_1b0hr_97",o={skeletonCard:a,poster:i,line:c,"skeleton-wave":"_skeleton-wave_1b0hr_1",info:_,short:d,horizontal:h,vertical:m,lowEnd:v},b=({layout:n="vertical"})=>{const{lowEndMode:r}=l();return e("div",{className:`${o.skeletonCard} ${o[n]} ${r?o.lowEnd:""}`,children:[e("div",{className:o.poster}),e("div",{className:o.info,children:[e("div",{className:o.line}),e("div",{className:`${o.line} ${o.short}`})]})]})},k=({count:n=14,layout:r="vertical"})=>e("div",{className:"grid-container",children:Array.from({length:n}).map((p,s)=>e(b,{layout:r},s))}),E=t.memo(k);export{b as A,E as S};
@@ -1,2 +1,2 @@
1
- import{d as a,h as me,g as ce,A as le,q as je,u as e,S as I}from"./vendor-core-8R2fFbyN.js";import{u as ue,b as de,a as R}from"./vendor-query-BXRECSI6.js";import{z as s,W as Se,B as pe}from"./index-IZgh1beL.js";import{I as h}from"./vendor-icons-CDMuNDeL.js";function Ce(){const B=ue(),[r,m]=a(!1);return me(()=>{const g=new URLSearchParams(window.location.search),u=g.get("anilist");if(u){const i=g.get("user"),b=g.get("reason");window.history.replaceState(null,"",window.location.pathname),u==="success"?(s.success(i?`Connected to AniList as ${decodeURIComponent(i)}`:"Connected to AniList"),B.invalidateQueries({queryKey:["trackerStatus"]})):s.error(b?decodeURIComponent(b):"AniList authentication failed");return}const w=new URLSearchParams(window.location.hash.substring(1)),c=w.get("access_token"),D=g.get("code");if(!c&&!D){const i=w.get("error");i&&(s.error(`AniList error: ${i}`),window.history.replaceState(null,"",window.location.pathname));return}const j=window.location.origin+window.location.pathname;window.history.replaceState(null,"",window.location.pathname),m(!0),s("Connecting to AniList..."),fetch("/api/tracker/anilist/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c?{token:c}:{code:D,redirectUri:j})}).then(async i=>{const b=await i.json().catch(()=>({}));if(!i.ok)throw new Error(b.error||"Authentication failed");s.success(`Connected to AniList as ${b.user?.name??"AniList user"}`),B.invalidateQueries({queryKey:["trackerStatus"]})}).catch(i=>{s.error(i instanceof Error?i.message:"Failed to authenticate with AniList")}).finally(()=>{m(!1)})},[B]),r}const Te="_header_j1lbh_1",xe="_fadeIn_j1lbh_1",Le="_pageTitle_j1lbh_6",Ae="_pageSubtitle_j1lbh_14",Pe="_importCard_j1lbh_20",Ee="_slideUpIn_j1lbh_1",Be="_cardHeader_j1lbh_37",De="_uploadArea_j1lbh_55",Me="_fileInputWrapper_j1lbh_59",Oe="_fileInput_j1lbh_59",Fe="_fileDisplay_j1lbh_87",$e="_fileIcon_j1lbh_95",Ue="_fileName_j1lbh_100",Re="_browseButton_j1lbh_109",qe="_optionsArea_j1lbh_120",Ke="_checkboxLabel_j1lbh_128",He="_checkbox_j1lbh_128",Qe="_checkboxCustom_j1lbh_141",Ge="_optionText_j1lbh_169",We="_optionTitle_j1lbh_175",ze="_optionDesc_j1lbh_181",Je="_actions_j1lbh_187",Xe="_importBtn_j1lbh_195",Ve="_cancelBtn_j1lbh_201",Ye="_statusMessage_j1lbh_215",Ze="_success_j1lbh_225",en="_error_j1lbh_231",nn="_progressSection_j1lbh_237",tn="_progressBar_j1lbh_242",sn="_progressFill_j1lbh_250",an="_progressInfo_j1lbh_257",on="_progressCount_j1lbh_264",rn="_progressTitle_j1lbh_271",cn="_sourceBadge_j1lbh_289",ln="_anilist_j1lbh_301",dn="_kitsu_j1lbh_307",pn="_offline_j1lbh_313",hn="_skipped_j1lbh_319",mn="_cardTitleRow_j1lbh_324",un="_anilistIcon_j1lbh_334",_n="_malIcon_j1lbh_340",gn="_badgeOnline_j1lbh_346",bn="_badgeOffline_j1lbh_358",fn="_connectedProfile_j1lbh_370",yn="_avatar_j1lbh_379",wn="_connectedInfo_j1lbh_386",Nn="_connectedName_j1lbh_394",kn="_connectedHint_j1lbh_400",vn="_loginPrompt_j1lbh_405",In="_loginSection_j1lbh_413",jn="_fieldLabel_j1lbh_419",Sn="_helpText_j1lbh_438",Cn="_loginText_j1lbh_455",Tn="_primaryBtn_j1lbh_464",xn="_secondaryBtn_j1lbh_465",Ln="_syncBtn_j1lbh_466",An="_divider_j1lbh_518",Pn="_actionSection_j1lbh_524",En="_inputGroup_j1lbh_538",Bn="_input_j1lbh_538",Dn="_syncSummary_j1lbh_559",Mn="_syncErrors_j1lbh_565",On="_spin_j1lbh_569",Fn="_radioGroup_j1lbh_598",$n="_radioLabel_j1lbh_604",Un="_syncHint_j1lbh_642",Rn="_importLoading_j1lbh_649",n={header:Te,fadeIn:xe,pageTitle:Le,pageSubtitle:Ae,importCard:Pe,slideUpIn:Ee,cardHeader:Be,uploadArea:De,fileInputWrapper:Me,fileInput:Oe,fileDisplay:Fe,fileIcon:$e,fileName:Ue,browseButton:Re,optionsArea:qe,checkboxLabel:Ke,checkbox:He,checkboxCustom:Qe,optionText:Ge,optionTitle:We,optionDesc:ze,actions:Je,importBtn:Xe,cancelBtn:Ve,statusMessage:Ye,success:Ze,error:en,progressSection:nn,progressBar:tn,progressFill:sn,progressInfo:an,progressCount:on,progressTitle:rn,sourceBadge:cn,anilist:ln,kitsu:dn,offline:pn,skipped:hn,cardTitleRow:mn,anilistIcon:un,malIcon:_n,badgeOnline:gn,badgeOffline:bn,connectedProfile:fn,avatar:yn,connectedInfo:wn,connectedName:Nn,connectedHint:kn,loginPrompt:vn,loginSection:In,fieldLabel:jn,helpText:Sn,loginText:Cn,primaryBtn:Tn,secondaryBtn:xn,syncBtn:Ln,divider:An,actionSection:Pn,inputGroup:En,input:Bn,syncSummary:Dn,syncErrors:Mn,spin:On,radioGroup:Fn,radioLabel:$n,syncHint:Un,importLoading:Rn},W="tracker_anilist_client_id",he="49887".trim(),Gn=()=>{const{setIsOpen:B}=Se(),r=ue();ce.useEffect(()=>{document.title="Trackers - dango"},[]);const[m,g]=a(""),[u,w]=a("username"),[c,D]=a(null),[j,i]=a(""),b=Ce(),{data:z,isLoading:_e}=de({queryKey:["trackerStatus"],queryFn:async()=>{const t=await fetch("/api/tracker/status");if(!t.ok)throw new Error("Failed to load tracker status");return t.json()}}),{data:N}=de({queryKey:["anilistClientId"],queryFn:async()=>(await(await fetch(`/api/settings?key=${W}`)).json()).value||""}),J=le(!1);ce.useEffect(()=>{J.current||N!==void 0&&(N&&i(N),J.current=!0)},[N]);const S=z?.anilist?.connected??!1;me(()=>{S&&w("sync")},[S]);const M=z?.anilist?.user??null,q=!!he,ge=(N||"").trim(),be=async()=>{const t=j.trim(),o=t||he;if(!o){s.error("Enter your AniList client ID first");return}const _=async(y,Q)=>{if(!(await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:y,value:Q})})).ok)throw new Error(`Failed to save ${y}`)};try{t?t!==N&&await _(W,t):q&&ge&&await _(W,""),r.invalidateQueries({queryKey:["anilistClientId"]})}catch(y){s.error(y.message);return}const p=window.location.origin+window.location.pathname,A=encodeURIComponent(p);window.location.href=`https://anilist.co/api/v2/oauth/authorize?client_id=${encodeURIComponent(o)}&response_type=token&state=${A}`},X=R({mutationFn:async()=>{const t=await fetch("/api/tracker/anilist/disconnect",{method:"POST"});if(!t.ok)throw new Error("Failed to disconnect");return t.json()},onSuccess:()=>{r.invalidateQueries({queryKey:["trackerStatus"]}),s.success("Disconnected from AniList")},onError:t=>s.error(t.message)}),O=R({mutationFn:async()=>{const t=await fetch("/api/tracker/sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:"anilist"})}),o=await t.json();if(!t.ok)throw new Error(o.error||"Sync failed");return o.summary},onSuccess:t=>{r.invalidateQueries({queryKey:["watchlist"]}),r.invalidateQueries({queryKey:["allContinueWatching"]}),D(t),s.success(`Sync complete — pushed ${t.pushed}, pulled ${t.pulled}, merged ${t.merged}, unchanged ${t.unchanged}`,{duration:6e3})},onError:t=>s.error(t.message)}),k=R({mutationFn:async()=>{if(!m.trim())throw new Error("Please enter a username");const t=await fetch("/api/tracker/anilist/import",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:m.trim(),erase:f})}),o=await t.json();if(!t.ok)throw new Error(o.error||"Import failed");return o.count},onSuccess:t=>{r.invalidateQueries({queryKey:["watchlist"]}),r.invalidateQueries({queryKey:["allContinueWatching"]}),s.success(`Imported ${t} anime entries from AniList`),g("")},onError:t=>s.error(t.message)}),[C,V]=a(""),d=R({mutationFn:async t=>{if(!C.trim())throw new Error("Please enter a MAL username");const o=await fetch("/api/tracker/mal/import",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:C.trim(),erase:t.erase,useOfflineDb:t.useOfflineDb,skipFallback:t.skipFallback})}),_=await o.json();if(!o.ok)throw new Error(_.error||"Import failed");return _.count},onSuccess:t=>{r.invalidateQueries({queryKey:["watchlist"]}),r.invalidateQueries({queryKey:["allContinueWatching"]}),s.success(`Imported ${t} anime entries from MAL`),V("")},onError:t=>s.error(t.message)}),[f,Y]=a(!1),[T,fe]=a(!0),[x,ye]=a(!1),[Z,ee]=a(""),[v,ne]=a(!1),[l,te]=a(null),[K,se]=a(null),[ae,F]=a(""),H=le(null),we=t=>{t.target.files&&t.target.files.length>0?ee(t.target.files[0].name):ee("")},Ne=je(async()=>{const t=document.getElementById("malFile");if(!t.files||t.files.length===0){F("Please select a file first.");return}const o=t.files[0];ne(!0),te(null),se(null),F("");const _=new AbortController;H.current=_;try{const p=new FormData;p.append("xmlfile",o),p.append("erase",String(f)),p.append("useOfflineDb",String(T)),p.append("skipFallback",String(x));const A=await fetch("/api/import/mal-xml",{method:"POST",body:p,signal:_.signal});if(!A.ok){const G=await A.text();let P="Failed to import";try{P=JSON.parse(G).error||P}catch{}throw new Error(P)}const y=A.body?.getReader();if(!y)throw new Error("No response stream");const Q=new TextDecoder;let $="",U="";for(;;){const{done:G,value:P}=await y.read();if(G)break;$+=Q.decode(P,{stream:!0});const oe=$.split(`
1
+ import{d as a,h as me,g as ce,A as le,q as je,u as e,S as I}from"./vendor-core-8R2fFbyN.js";import{u as ue,b as de,a as R}from"./vendor-query-BXRECSI6.js";import{z as s,W as Se,B as pe}from"./index-lo-bz7f2.js";import{I as h}from"./vendor-icons-CDMuNDeL.js";function Ce(){const B=ue(),[r,m]=a(!1);return me(()=>{const g=new URLSearchParams(window.location.search),u=g.get("anilist");if(u){const i=g.get("user"),b=g.get("reason");window.history.replaceState(null,"",window.location.pathname),u==="success"?(s.success(i?`Connected to AniList as ${decodeURIComponent(i)}`:"Connected to AniList"),B.invalidateQueries({queryKey:["trackerStatus"]})):s.error(b?decodeURIComponent(b):"AniList authentication failed");return}const w=new URLSearchParams(window.location.hash.substring(1)),c=w.get("access_token"),D=g.get("code");if(!c&&!D){const i=w.get("error");i&&(s.error(`AniList error: ${i}`),window.history.replaceState(null,"",window.location.pathname));return}const j=window.location.origin+window.location.pathname;window.history.replaceState(null,"",window.location.pathname),m(!0),s("Connecting to AniList..."),fetch("/api/tracker/anilist/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c?{token:c}:{code:D,redirectUri:j})}).then(async i=>{const b=await i.json().catch(()=>({}));if(!i.ok)throw new Error(b.error||"Authentication failed");s.success(`Connected to AniList as ${b.user?.name??"AniList user"}`),B.invalidateQueries({queryKey:["trackerStatus"]})}).catch(i=>{s.error(i instanceof Error?i.message:"Failed to authenticate with AniList")}).finally(()=>{m(!1)})},[B]),r}const Te="_header_j1lbh_1",xe="_fadeIn_j1lbh_1",Le="_pageTitle_j1lbh_6",Ae="_pageSubtitle_j1lbh_14",Pe="_importCard_j1lbh_20",Ee="_slideUpIn_j1lbh_1",Be="_cardHeader_j1lbh_37",De="_uploadArea_j1lbh_55",Me="_fileInputWrapper_j1lbh_59",Oe="_fileInput_j1lbh_59",Fe="_fileDisplay_j1lbh_87",$e="_fileIcon_j1lbh_95",Ue="_fileName_j1lbh_100",Re="_browseButton_j1lbh_109",qe="_optionsArea_j1lbh_120",Ke="_checkboxLabel_j1lbh_128",He="_checkbox_j1lbh_128",Qe="_checkboxCustom_j1lbh_141",Ge="_optionText_j1lbh_169",We="_optionTitle_j1lbh_175",ze="_optionDesc_j1lbh_181",Je="_actions_j1lbh_187",Xe="_importBtn_j1lbh_195",Ve="_cancelBtn_j1lbh_201",Ye="_statusMessage_j1lbh_215",Ze="_success_j1lbh_225",en="_error_j1lbh_231",nn="_progressSection_j1lbh_237",tn="_progressBar_j1lbh_242",sn="_progressFill_j1lbh_250",an="_progressInfo_j1lbh_257",on="_progressCount_j1lbh_264",rn="_progressTitle_j1lbh_271",cn="_sourceBadge_j1lbh_289",ln="_anilist_j1lbh_301",dn="_kitsu_j1lbh_307",pn="_offline_j1lbh_313",hn="_skipped_j1lbh_319",mn="_cardTitleRow_j1lbh_324",un="_anilistIcon_j1lbh_334",_n="_malIcon_j1lbh_340",gn="_badgeOnline_j1lbh_346",bn="_badgeOffline_j1lbh_358",fn="_connectedProfile_j1lbh_370",yn="_avatar_j1lbh_379",wn="_connectedInfo_j1lbh_386",Nn="_connectedName_j1lbh_394",kn="_connectedHint_j1lbh_400",vn="_loginPrompt_j1lbh_405",In="_loginSection_j1lbh_413",jn="_fieldLabel_j1lbh_419",Sn="_helpText_j1lbh_438",Cn="_loginText_j1lbh_455",Tn="_primaryBtn_j1lbh_464",xn="_secondaryBtn_j1lbh_465",Ln="_syncBtn_j1lbh_466",An="_divider_j1lbh_518",Pn="_actionSection_j1lbh_524",En="_inputGroup_j1lbh_538",Bn="_input_j1lbh_538",Dn="_syncSummary_j1lbh_559",Mn="_syncErrors_j1lbh_565",On="_spin_j1lbh_569",Fn="_radioGroup_j1lbh_598",$n="_radioLabel_j1lbh_604",Un="_syncHint_j1lbh_642",Rn="_importLoading_j1lbh_649",n={header:Te,fadeIn:xe,pageTitle:Le,pageSubtitle:Ae,importCard:Pe,slideUpIn:Ee,cardHeader:Be,uploadArea:De,fileInputWrapper:Me,fileInput:Oe,fileDisplay:Fe,fileIcon:$e,fileName:Ue,browseButton:Re,optionsArea:qe,checkboxLabel:Ke,checkbox:He,checkboxCustom:Qe,optionText:Ge,optionTitle:We,optionDesc:ze,actions:Je,importBtn:Xe,cancelBtn:Ve,statusMessage:Ye,success:Ze,error:en,progressSection:nn,progressBar:tn,progressFill:sn,progressInfo:an,progressCount:on,progressTitle:rn,sourceBadge:cn,anilist:ln,kitsu:dn,offline:pn,skipped:hn,cardTitleRow:mn,anilistIcon:un,malIcon:_n,badgeOnline:gn,badgeOffline:bn,connectedProfile:fn,avatar:yn,connectedInfo:wn,connectedName:Nn,connectedHint:kn,loginPrompt:vn,loginSection:In,fieldLabel:jn,helpText:Sn,loginText:Cn,primaryBtn:Tn,secondaryBtn:xn,syncBtn:Ln,divider:An,actionSection:Pn,inputGroup:En,input:Bn,syncSummary:Dn,syncErrors:Mn,spin:On,radioGroup:Fn,radioLabel:$n,syncHint:Un,importLoading:Rn},W="tracker_anilist_client_id",he="49887".trim(),Gn=()=>{const{setIsOpen:B}=Se(),r=ue();ce.useEffect(()=>{document.title="Trackers - dango"},[]);const[m,g]=a(""),[u,w]=a("username"),[c,D]=a(null),[j,i]=a(""),b=Ce(),{data:z,isLoading:_e}=de({queryKey:["trackerStatus"],queryFn:async()=>{const t=await fetch("/api/tracker/status");if(!t.ok)throw new Error("Failed to load tracker status");return t.json()}}),{data:N}=de({queryKey:["anilistClientId"],queryFn:async()=>(await(await fetch(`/api/settings?key=${W}`)).json()).value||""}),J=le(!1);ce.useEffect(()=>{J.current||N!==void 0&&(N&&i(N),J.current=!0)},[N]);const S=z?.anilist?.connected??!1;me(()=>{S&&w("sync")},[S]);const M=z?.anilist?.user??null,q=!!he,ge=(N||"").trim(),be=async()=>{const t=j.trim(),o=t||he;if(!o){s.error("Enter your AniList client ID first");return}const _=async(y,Q)=>{if(!(await fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:y,value:Q})})).ok)throw new Error(`Failed to save ${y}`)};try{t?t!==N&&await _(W,t):q&&ge&&await _(W,""),r.invalidateQueries({queryKey:["anilistClientId"]})}catch(y){s.error(y.message);return}const p=window.location.origin+window.location.pathname,A=encodeURIComponent(p);window.location.href=`https://anilist.co/api/v2/oauth/authorize?client_id=${encodeURIComponent(o)}&response_type=token&state=${A}`},X=R({mutationFn:async()=>{const t=await fetch("/api/tracker/anilist/disconnect",{method:"POST"});if(!t.ok)throw new Error("Failed to disconnect");return t.json()},onSuccess:()=>{r.invalidateQueries({queryKey:["trackerStatus"]}),s.success("Disconnected from AniList")},onError:t=>s.error(t.message)}),O=R({mutationFn:async()=>{const t=await fetch("/api/tracker/sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:"anilist"})}),o=await t.json();if(!t.ok)throw new Error(o.error||"Sync failed");return o.summary},onSuccess:t=>{r.invalidateQueries({queryKey:["watchlist"]}),r.invalidateQueries({queryKey:["allContinueWatching"]}),D(t),s.success(`Sync complete — pushed ${t.pushed}, pulled ${t.pulled}, merged ${t.merged}, unchanged ${t.unchanged}`,{duration:6e3})},onError:t=>s.error(t.message)}),k=R({mutationFn:async()=>{if(!m.trim())throw new Error("Please enter a username");const t=await fetch("/api/tracker/anilist/import",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:m.trim(),erase:f})}),o=await t.json();if(!t.ok)throw new Error(o.error||"Import failed");return o.count},onSuccess:t=>{r.invalidateQueries({queryKey:["watchlist"]}),r.invalidateQueries({queryKey:["allContinueWatching"]}),s.success(`Imported ${t} anime entries from AniList`),g("")},onError:t=>s.error(t.message)}),[C,V]=a(""),d=R({mutationFn:async t=>{if(!C.trim())throw new Error("Please enter a MAL username");const o=await fetch("/api/tracker/mal/import",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:C.trim(),erase:t.erase,useOfflineDb:t.useOfflineDb,skipFallback:t.skipFallback})}),_=await o.json();if(!o.ok)throw new Error(_.error||"Import failed");return _.count},onSuccess:t=>{r.invalidateQueries({queryKey:["watchlist"]}),r.invalidateQueries({queryKey:["allContinueWatching"]}),s.success(`Imported ${t} anime entries from MAL`),V("")},onError:t=>s.error(t.message)}),[f,Y]=a(!1),[T,fe]=a(!0),[x,ye]=a(!1),[Z,ee]=a(""),[v,ne]=a(!1),[l,te]=a(null),[K,se]=a(null),[ae,F]=a(""),H=le(null),we=t=>{t.target.files&&t.target.files.length>0?ee(t.target.files[0].name):ee("")},Ne=je(async()=>{const t=document.getElementById("malFile");if(!t.files||t.files.length===0){F("Please select a file first.");return}const o=t.files[0];ne(!0),te(null),se(null),F("");const _=new AbortController;H.current=_;try{const p=new FormData;p.append("xmlfile",o),p.append("erase",String(f)),p.append("useOfflineDb",String(T)),p.append("skipFallback",String(x));const A=await fetch("/api/import/mal-xml",{method:"POST",body:p,signal:_.signal});if(!A.ok){const G=await A.text();let P="Failed to import";try{P=JSON.parse(G).error||P}catch{}throw new Error(P)}const y=A.body?.getReader();if(!y)throw new Error("No response stream");const Q=new TextDecoder;let $="",U="";for(;;){const{done:G,value:P}=await y.read();if(G)break;$+=Q.decode(P,{stream:!0});const oe=$.split(`
2
2
  `);$=oe.pop()||"";for(const E of oe)if(E.startsWith("event: "))U=E.slice(7).trim();else if(E.startsWith("data: ")){const Ie=E.slice(6);try{const re=JSON.parse(Ie);U==="progress"?te(re):U==="complete"&&se(re)}catch{}}else E===""&&(U="")}r.invalidateQueries({queryKey:["watchlist"]})}catch(p){p instanceof DOMException&&p.name==="AbortError"?F("Import cancelled."):F(p.message)}finally{ne(!1),H.current=null}},[f,T,x,r]),ke=()=>{H.current?.abort(),fetch("/api/import/mal-xml/cancel",{method:"POST"}).catch(()=>{})},ve=l?Math.round(l.current/l.total*100):0,[L,ie]=a("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 with tracking services"})]}),e("div",{className:n.importCard,children:[e("div",{className:n.cardHeader,children:e("div",{className:n.cardTitleRow,children:[e(h,{name:"anilist",className:n.anilistIcon}),e("h3",{children:"AniList"}),_e?null:S?e("span",{className:n.badgeOnline,children:"Connected"}):e("span",{className:n.badgeOffline,children:"Not connected"})]})}),S&&M?e("div",{className:n.connectedProfile,children:[M.avatar&&e("img",{src:M.avatar,alt:"Avatar",className:n.avatar,loading:"lazy",decoding:"async"}),e("div",{className:n.connectedInfo,children:[e("span",{className:n.connectedName,children:M.name}),e("span",{className:n.connectedHint,children:"2-way sync is ready"})]}),e("button",{className:n.secondaryBtn,onClick:()=>X.mutate(),disabled:X.isPending,children:[e(h,{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.",b&&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(h,{name:"external-link-alt",size:9})]})]}),e("div",{className:n.inputGroup,children:[e("input",{type:"text",placeholder:"Client ID",value:j,onChange:t=>i(t.target.value),className:n.input}),e("button",{className:n.primaryBtn,onClick:be,disabled:!(j.trim()||q),children:[e(h,{name:"external-link-alt"})," Connect"]})]}),e("p",{className:n.helpText,children:q?e(I,{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.port==="5173"?`${window.location.protocol}//${window.location.hostname}:3000/api/tracker/anilist/callback`:`${window.location.origin}/api/tracker/anilist/callback`}),", then paste only the ",e("strong",{children:"Client ID"})," above (leave empty to use Dango's)."]}):e(I,{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.port==="5173"?`${window.location.protocol}//${window.location.hostname}:3000/api/tracker/anilist/callback`:`${window.location.origin}/api/tracker/anilist/callback`}),", then paste the ",e("strong",{children:"Client ID"})," above."]})})]}),S&&e(I,{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:u==="username",onChange:()=>w("username")}),e("span",{children:"Quick Import"})]}),e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"anilistMode",value:"sync",checked:u==="sync",onChange:()=>w("sync")}),e("span",{children:"Two-way Sync"})]})]}),u==="username"?e("div",{className:n.inputGroup,children:e("input",{type:"text",placeholder:"Enter AniList username",value:m,onChange:t=>g(t.target.value),className:n.input,disabled:k.isPending,onKeyDown:t=>{t.key==="Enter"&&m.trim()&&k.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."}),u==="username"&&e("div",{className:n.optionsArea,children:e("label",{className:n.checkboxLabel,children:[e("input",{type:"checkbox",checked:f,onChange:t=>Y(t.target.checked),className:n.checkbox,disabled:k.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."})]})]})}),u==="username"?e("button",{className:n.syncBtn,onClick:()=>k.mutate(),disabled:!m.trim()||k.isPending,children:[e(h,{name:"download"}),k.isPending?"Importing...":"Start Import"]}):e(I,{children:[e("button",{className:n.syncBtn,onClick:()=>O.mutate(),disabled:O.isPending,children:[e(h,{name:"sync-alt",className:O.isPending?n.spin:""}),O.isPending?"Syncing...":"Start Sync"]}),c&&e("div",{className:n.syncSummary,children:["Pushed: ",c.pushed," · Pulled: ",c.pulled," · Merged:"," ",c.merged," · Unchanged: ",c.unchanged,c.errors.length>0&&e("span",{className:n.syncErrors,children:[" ","· ",c.errors.length," error",c.errors.length>1?"s":""]})]})]}),e("p",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginTop:"8px"},children:["AniList ",e("code",{children:"Rewatching (REPEATING)"})," is not tracked — entries with this status are ignored."]})]})]}),e("div",{className:n.importCard,children:[e("div",{className:n.cardHeader,children:e("div",{className:n.cardTitleRow,children:[e(h,{name:"myanimelist",className:n.malIcon}),e("h3",{children:"MyAnimeList"})]})}),e("div",{className:n.radioGroup,children:[e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"malMode",value:"username",checked:L==="username",onChange:()=>ie("username")}),e("span",{children:"Username"})]}),e("label",{className:n.radioLabel,children:[e("input",{type:"radio",name:"malMode",value:"xml",checked:L==="xml",onChange:()=>ie("xml")}),e("span",{children:"XML File"})]})]}),L==="username"?e(I,{children:[e("div",{className:n.inputGroup,children:e("input",{type:"text",placeholder:"Enter MAL username",value:C,onChange:t=>V(t.target.value),className:n.input,disabled:d.isPending,onKeyDown:t=>{t.key==="Enter"&&C.trim()&&d.mutate({erase:f,useOfflineDb:T,skipFallback:x})}})}),d.isPending&&e("div",{className:n.importLoading,children:[e(h,{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:we,disabled:v}),e("div",{className:n.fileDisplay,children:[e(h,{name:"file-alt",className:n.fileIcon}),e("span",{className:n.fileName,children:Z||"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:f,onChange:t=>Y(t.target.checked),className:n.checkbox,disabled:v||d.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:T,onChange:t=>fe(t.target.checked),className:n.checkbox,disabled:v||d.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:x,onChange:t=>ye(t.target.checked),className:n.checkbox,disabled:v||d.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."})]})]})]}),L==="username"?e("button",{className:n.syncBtn,onClick:()=>d.mutate({erase:f,useOfflineDb:T,skipFallback:x}),disabled:!C.trim()||d.isPending,children:[e(h,{name:"download"}),d.isPending?"Importing...":"Start Import"]}):e("div",{className:n.actions,children:v?e(pe,{onClick:ke,className:n.cancelBtn,children:"Cancel Import"}):e(pe,{onClick:Ne,className:n.importBtn,disabled:!Z,children:[e(h,{name:"upload"})," Start Import"]})}),L==="username"&&d.isError&&e("div",{className:`${n.statusMessage} ${n.error}`,children:d.error.message}),v&&l&&e("div",{className:n.progressSection,children:[e("div",{className:n.progressBar,children:e("div",{className:n.progressFill,style:{width:`${ve}%`}})}),e("div",{className:n.progressInfo,children:[e("span",{className:n.progressCount,children:[l.current," / ",l.total]}),e("span",{className:n.progressTitle,children:l.found?e(I,{children:[l.matchedTitle,e("span",{className:`${n.sourceBadge} ${n[l.source||"anilist"]}`,children:l.source==="kitsu"?"Kitsu":l.source==="offline"?"Offline DB":"AniList"})]}):e("span",{className:n.skipped,children:["Skipped: ",l.title]})})]})]}),K&&e("div",{className:`${n.statusMessage} ${n.success}`,children:["Import complete! Imported: ",K.imported,", Skipped: ",K.skipped,"."]}),ae&&e("div",{className:`${n.statusMessage} ${n.error}`,children:ae})]})]})};export{Gn as default};
@@ -0,0 +1 @@
1
+ ._fullscreenFlat_1deq4_1,._fullscreenFlat_1deq4_1 ._video_1deq4_2,._fullscreenFlat_1deq4_1 ._delayCanvas_1deq4_3,._fullscreenFlat_1deq4_1 ._subtitleOverlay_1deq4_4{border-radius:0}@media(max-width:900px)and (orientation:landscape){._fullscreenFlat_1deq4_1{border-radius:0}}@container (max-width: 26rem){._timeDisplay_1deq4_15{display:none}._bottomControls_1deq4_19{padding:.75rem}._leftControls_1deq4_23,._rightControls_1deq4_24{gap:.2rem}._controlBtn_1deq4_28{padding:5px;min-width:2.125rem;min-height:2.125rem}}._video_1deq4_2{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;display:block;background:#000;border:none}._controlsOverlay_1deq4_47{position:absolute;inset:0;opacity:1;transition:opacity .4s cubic-bezier(.4,0,.2,1);z-index:50;pointer-events:none;display:flex;flex-direction:column;justify-content:space-between;background:radial-gradient(circle,transparent 20%,rgba(0,0,0,.4) 100%)}._controlsOverlay_1deq4_47>*{pointer-events:auto}._controlsOverlay_1deq4_47._hidden_1deq4_67{opacity:0;pointer-events:none;cursor:none}._topControls_1deq4_73{position:absolute;top:0;left:0;right:0;display:flex;align-items:center;gap:var(--space-6);background:linear-gradient(to bottom,rgba(0,0,0,.85) 0%,rgba(0,0,0,.45) 60%,transparent 100%);padding:var(--space-8) var(--space-10);transition:transform .4s cubic-bezier(.2,.8,.2,1);z-index:10;pointer-events:auto}._backBtn_1deq4_93{background:transparent;border:none;color:#ffffffd9;font-size:1.6rem;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--transition-fast);padding:8px;border-radius:50%}._backBtn_1deq4_93:hover{background:#0f0f1199;color:#fff;transform:scale(1.1)}._videoTitleInfo_1deq4_113{display:flex;flex-direction:column;gap:.25rem}._animeTitle_1deq4_119{font-size:1.4rem;font-weight:800;color:#fff;letter-spacing:-.01em;text-shadow:0 2px 4px rgba(0,0,0,.5)}._episodeLabel_1deq4_127{font-size:.85rem;font-weight:600;color:#ffffffbf;text-shadow:0 2px 4px rgba(0,0,0,.5)}._speedBoostBadge_1deq4_134{position:absolute;top:1.5rem;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:.7rem;padding:.65rem 1rem;border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);border-radius:var(--radius-md);background:#121216eb;color:#f5f3ff;font-size:.85rem;font-weight:800;letter-spacing:.06em;z-index:11;pointer-events:none}._speedBoostBadge_1deq4_134 span{line-height:1}._speedBoostBadge_1deq4_134 svg{display:block;flex-shrink:0}._bottomControls_1deq4_19{position:absolute;bottom:0;left:0;right:0;background:linear-gradient(to top,rgba(0,0,0,.85) 0%,rgba(0,0,0,.45) 60%,transparent 100%);padding:clamp(1rem,4cqw,2.5rem) clamp(1rem,4cqw,2.5rem) clamp(.75rem,2.5cqw,1.5rem);z-index:10;pointer-events:auto;transition:transform .4s cubic-bezier(.2,.8,.2,1)}._progressBarContainer_1deq4_180{width:100%;height:20px;display:flex;align-items:center;cursor:pointer;position:relative;touch-action:pan-y}@media(pointer:coarse){._progressBarContainer_1deq4_180{height:28px}._progressBarContainer_1deq4_180 ._progressBar_1deq4_180{height:6px}._progressBarContainer_1deq4_180 ._thumb_1deq4_199{opacity:1}}._progressBar_1deq4_180{width:100%;height:4px;background:#fff3;border-radius:2px;position:relative;transition:height .15s ease}._progressBarContainer_1deq4_180:hover ._progressBar_1deq4_180{height:6px}._bufferedBar_1deq4_217{position:absolute;top:0;left:0;height:100%;background:#ffffff4d;border-radius:2px;pointer-events:none}._watchedBar_1deq4_227{position:absolute;top:0;left:0;height:100%;background:var(--accent);border-radius:2px;pointer-events:none}._thumb_1deq4_199{position:absolute;top:50%;width:12px;height:12px;background:#fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 4px #0006;pointer-events:none;opacity:0;transition:opacity .15s ease}._progressBarContainer_1deq4_180:hover ._thumb_1deq4_199,._progressBarContainer_1deq4_180._scrubbing_1deq4_252 ._thumb_1deq4_199{opacity:1}._timeBubble_1deq4_256{position:absolute;bottom:24px;background:#000000d9;color:#fff;padding:4px 8px;border-radius:4px;font-size:.8rem;font-weight:500;transform:translate(-50%);pointer-events:none;white-space:nowrap}._bottomControlsRow_1deq4_270{display:flex;align-items:center;justify-content:space-between;gap:.75rem;margin-top:8px}._leftControls_1deq4_23{display:flex;align-items:center;gap:1rem;gap:clamp(.5rem,2.5cqw,1rem);min-width:0}._rightControls_1deq4_24{display:flex;align-items:center;gap:.75rem;gap:clamp(.5rem,2cqw,.75rem)}._nextEpisodeBtn_1deq4_293{background:#ffffff0f;border:1px solid rgba(255,255,255,.12);border-radius:var(--radius-md);padding:.45rem .8rem;color:#fffc;font-weight:600;font-size:.9rem;display:inline-flex;align-items:center;gap:.5rem;cursor:pointer;transition:all var(--transition-fast);white-space:nowrap}._nextEpisodeBtn_1deq4_293:hover{background:#ffffff1a;color:#fff;transform:translateY(-1px);border-color:#fff3}._controlBtn_1deq4_28{background:transparent;border:none;color:#ffffffd9;font-size:1.1rem;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:8px;border-radius:4px;transition:all var(--transition-fast);min-width:2.125rem;min-height:2.125rem;flex:0 0 auto}@media(pointer:coarse){._controlBtn_1deq4_28{padding:10px;min-width:2.75rem;min-height:2.75rem}}._controlBtn_1deq4_28:hover{color:#fff;background:#ffffff1a}._controlBtn_1deq4_28._active_1deq4_346{color:var(--accent)}._volumeContainer_1deq4_350{display:flex;align-items:center;position:relative}._volumeSlider_1deq4_356{width:0;opacity:0;transform:scaleX(0);transform-origin:left;transition:all .3s cubic-bezier(.4,0,.2,1);cursor:pointer;margin-left:8px;-webkit-appearance:none;appearance:none;background:transparent;height:20px}._volumeContainer_1deq4_350:hover ._volumeSlider_1deq4_356,._volumeSlider_1deq4_356:focus{width:80px;opacity:1;transform:scaleX(1)}._volumeSlider_1deq4_356::-webkit-slider-runnable-track{width:100%;height:4px;background:linear-gradient(to right,var(--accent) 0%,var(--accent) var(--volume-percent, 0%),rgba(255,255,255,.2) var(--volume-percent, 0%),rgba(255,255,255,.2) 100%);border-radius:4px}._volumeSlider_1deq4_356::-moz-range-track{width:100%;height:4px;background:#fff3;border-radius:4px}._volumeSlider_1deq4_356::-moz-range-progress{height:4px;background:var(--accent);border-radius:4px}._volumeSlider_1deq4_356::-webkit-slider-thumb{-webkit-appearance:none;height:12px;width:12px;border-radius:50%;background:#fff;margin-top:-4px;box-shadow:0 0 5px #00000080}._timeDisplay_1deq4_15{color:#fffc;font-size:.85rem;font-weight:500;font-variant-numeric:tabular-nums;min-width:100px}._settingsPanel_1deq4_421{position:absolute;bottom:clamp(6rem,15vh,8rem);right:clamp(1rem,3vw,2rem);background:#141418f2;border:1px solid var(--border-secondary);border-radius:var(--radius-md);width:max-content;min-width:12rem;max-width:min(19rem,calc(100vw - 1.5rem));font-size:.85rem;z-index:60;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 8px 32px #00000080;display:flex;flex-direction:column;overflow:hidden}._settingsHeader_1deq4_440{display:flex;align-items:center;padding:.55rem .75rem;border-bottom:1px solid var(--border-secondary);gap:.625rem}._settingsBackBtn_1deq4_448{background:transparent;border:none;color:#ffffffd9;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:4px;border-radius:4px;transition:all var(--transition-fast)}._settingsBackBtn_1deq4_448:hover{background:#ffffff1a;color:#fff}._settingsTitle_1deq4_466{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._settingsContent_1deq4_477{overflow-y:auto;padding:.375rem;display:flex;flex-direction:column;gap:.125rem;max-height:min(56vh,22rem)}._currentValue_1deq4_486{color:var(--text-tertiary);font-size:.8rem;font-weight:500}._settingsLabel_1deq4_492{padding:var(--space-2) var(--space-4);font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-secondary)}._menuItem_1deq4_501{display:flex;align-items:center;justify-content:space-between;gap:.75rem;width:100%;min-height:2rem;padding:.5rem .75rem;background:transparent;border:none;color:var(--text-primary);font-size:.85rem;cursor:pointer;border-radius:var(--radius-sm);transition:background-color var(--transition-fast);text-align:left;white-space:nowrap}._menuItem_1deq4_501:hover{background:var(--bg-tertiary)}._menuItem_1deq4_501._active_1deq4_346{background:var(--bg-tertiary);color:var(--accent)}._currentValue_1deq4_486{color:var(--text-secondary);font-size:.85rem}._menuNote_1deq4_534{padding:.5rem .75rem;font-size:.7rem;line-height:1.5;color:var(--text-tertiary);white-space:normal;overflow-wrap:break-word}._spin_1deq4_543{animation:_spin_1deq4_543 1s linear infinite}@keyframes _spin_1deq4_543{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media(pointer:coarse){._settingsPanel_1deq4_421{font-size:.9rem;bottom:calc(env(safe-area-inset-bottom,0px) + 7rem);right:max(.75rem,env(safe-area-inset-right,0px))}._menuItem_1deq4_501{min-height:2.75rem}._settingsContent_1deq4_477{max-height:52vh}}@media(max-width:480px){._settingsPanel_1deq4_421{min-width:9rem;max-width:calc(100vw - 2rem);font-size:.75rem;bottom:calc(env(safe-area-inset-bottom,0px) + 6rem)}._settingsHeader_1deq4_440{padding:.4rem .625rem}._settingsTitle_1deq4_466{font-size:.64rem}._menuItem_1deq4_501{min-height:2.25rem;padding:.45rem .625rem;font-size:.75rem;gap:.5rem}._settingsContent_1deq4_477{max-height:min(40vh,15rem)}}@media(max-height:500px)and (orientation:landscape){._settingsPanel_1deq4_421{bottom:7.25rem;right:2rem;min-width:10rem;max-width:min(15rem,calc(100vw - 1.5rem));font-size:.8rem}._menuItem_1deq4_501{min-height:2.5rem;font-size:.8rem}._settingsContent_1deq4_477{max-height:50vh;overflow-y:auto}}._page_263ma_1{max-width:1200px;margin:0 auto;padding:1.5rem}._header_263ma_7{margin-bottom:1.5rem}._pageTitle_263ma_11{font-size:1.75rem;font-weight:700;margin:0 0 1rem;display:flex;align-items:center;gap:.5rem;color:var(--text-primary)}._searchForm_263ma_21{display:flex;gap:.5rem;max-width:600px}._searchInput_263ma_27{flex:1;padding:.6rem 1rem;border-radius:8px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);font-size:.95rem;outline:none}._searchInput_263ma_27:focus{border-color:var(--accent)}._searchBtn_263ma_42{padding:.6rem 1rem;border-radius:8px;border:none;background:var(--accent);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center}._searchBtn_263ma_42:hover{opacity:.9}._suggestions_263ma_58{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:1.5rem}._suggestionPill_263ma_65{padding:.4rem .8rem;border-radius:20px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-secondary);cursor:pointer;font-size:.85rem;transition:all .15s ease}._suggestionPill_263ma_65:hover{border-color:var(--accent);color:var(--text-primary)}._statusMsg_263ma_81{padding:1rem;text-align:center;color:var(--text-secondary)}._statusMsg_263ma_81._error_263ma_87{color:#f87171}._statusMsg_263ma_81._textOnly_263ma_91{background:none;padding:.5rem}._spinner_263ma_96{animation:_spin_263ma_96 1s linear infinite;margin-right:.5rem}@keyframes _spin_263ma_96{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._grid_263ma_110{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:1rem}._skeletonCard_263ma_116{border-radius:8px;overflow:hidden}._skeletonThumb_263ma_121{aspect-ratio:2 / 3;background:var(--bg-secondary);border-radius:8px}._skeletonLine_263ma_127{height:12px;background:var(--bg-secondary);border-radius:4px;margin-top:.5rem}._shimmer_263ma_134{background:linear-gradient(90deg,var(--bg-secondary) 25%,var(--bg-elevated) 50%,var(--bg-secondary) 75%);background-size:200% 100%;animation:_shimmer_263ma_134 1.5s infinite}@keyframes _shimmer_263ma_134{0%{background-position:200% 0}to{background-position:-200% 0}}._backBtn_263ma_154{display:inline-flex;align-items:center;gap:.4rem;padding:.4rem .8rem;border-radius:6px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);cursor:pointer;font-size:.85rem;margin-bottom:1rem}._backBtn_263ma_154:hover{border-color:var(--accent)}._meta_263ma_172{display:flex;align-items:center;gap:.75rem;margin:.5rem 0;flex-wrap:wrap}._headerActions_263ma_180{display:flex;gap:.5rem;margin:.75rem 0 0;flex-wrap:wrap}._watchlistBtn_263ma_187{display:inline-flex;align-items:center;gap:.4rem;padding:.5rem 1rem;border-radius:6px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);cursor:pointer;font-size:.85rem;font-weight:600}._watchlistBtn_263ma_187:hover:not(:disabled){border-color:var(--accent)}._watchlistBtn_263ma_187._active_263ma_205{border-color:var(--color-success);color:var(--color-success)}._watchlistBtn_263ma_187:disabled{opacity:.6;cursor:default}._year_263ma_215{color:var(--text-secondary);font-size:.9rem}._rating_263ma_220{display:inline-flex;align-items:center;gap:4px;color:var(--accent-lighter);font-weight:600;font-size:.9rem}._typeBadge_263ma_229{padding:2px 10px;border-radius:4px;font-size:.75rem;font-weight:600;text-transform:uppercase}._typeBadge_263ma_229._tv_263ma_237{background:color-mix(in srgb,var(--accent) 20%,transparent);color:var(--accent)}._typeBadge_263ma_229._movie_263ma_242{background:color-mix(in srgb,var(--accent-lighter) 20%,transparent);color:var(--accent-lighter)}._typeBadge_263ma_229._tvSeries_263ma_247,._typeBadge_263ma_229._tvMiniSeries_263ma_252{background:color-mix(in srgb,var(--accent) 20%,transparent);color:var(--accent)}._overview_263ma_257{color:var(--text-secondary);line-height:1.6;margin:.5rem 0 0;max-width:800px}._controls_263ma_264{display:flex;flex-wrap:wrap;gap:1rem;margin:1rem 0;align-items:flex-end}._controlLabel_263ma_272{display:flex;flex-direction:column;gap:.3rem;font-size:.8rem;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em}._select_263ma_282{padding:.5rem .75rem;border-radius:6px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);font-size:.9rem;cursor:pointer;min-width:160px}._playerSection_263ma_293{margin:1.5rem 0;border-radius:0;overflow:hidden;overflow:clip;isolation:isolate;background:#000;position:relative}._video_263ma_297{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;display:block;background:#000;border:none;border-radius:inherit}._videoHidden_263ma_319{opacity:0;pointer-events:none}._delayCanvas_263ma_324{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;opacity:0;pointer-events:none;z-index:2;border-radius:inherit}._delayCanvasActive_263ma_337{opacity:1}._subtitleOverlay_263ma_341{position:absolute;top:0;left:0;width:100%;height:100%;z-index:3;pointer-events:none;overflow:hidden;border-radius:inherit}@media(max-width:900px)and (orientation:landscape){._playerSection_263ma_293{margin:0;border-radius:0}}._videoIframe_263ma_360{width:100%;aspect-ratio:16 / 9;min-height:400px;border:none;background:#000}._retryButton_263ma_368{margin-left:8px;padding:4px 10px;border-radius:4px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-primary);cursor:pointer;font-size:.8rem}._retryButton_263ma_368:hover{border-color:var(--accent)}._sidebarSeason_263ma_383{display:flex;flex-direction:column;gap:.4rem;font-size:.75rem;font-weight:700;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.1em;margin-bottom:var(--space-4)}._sidebarSeason_263ma_383 ._select_263ma_282{width:100%}._mobileSeasonRow_263ma_399{display:none}@media(max-width:768px){._mobileSeasonRow_263ma_399{display:block}._mobileSeasonRow_263ma_399 ._sidebarSeason_263ma_383{margin-bottom:0}}._sidebarPosterCard_263ma_413{padding:1rem;display:flex;flex-direction:column;gap:.75rem}._sidebarPosterCard_263ma_413 img{width:100%;border-radius:var(--radius-md);aspect-ratio:2 / 3;object-fit:cover;background:#ffffff0f}._sidebarPosterMeta_263ma_428{display:flex;flex-direction:column;gap:.25rem}._sidebarPosterMeta_263ma_428 strong{color:var(--text-primary);font-size:.95rem;line-height:1.3}._sidebarPosterMeta_263ma_428 span{color:var(--text-secondary);font-size:.85rem}._providerSelectWrap_263ma_445{display:flex;align-items:flex-end;gap:1rem;flex-wrap:wrap;min-width:0}._providerSelectWrap_263ma_445 ._backBtn_263ma_154{margin-bottom:0}._genreRow_263ma_457{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.6rem}._genreChip_263ma_464{padding:.2rem .7rem;border-radius:20px;border:1px solid var(--glass-border);background:#ffffff0d;color:var(--text-secondary);font-size:.78rem;font-weight:600}._metaRow_263ma_474{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.6rem;color:var(--text-secondary);font-size:.9rem}._detailGrid_263ma_483{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:.75rem;margin-top:1rem}._detailItem_263ma_490{display:flex;flex-direction:column;gap:.2rem;padding:.75rem 1rem;border-radius:var(--radius-md);border:1px solid var(--glass-border);background:#ffffff08}._detailItem_263ma_490 strong{font-size:.75rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-tertiary)}._detailItem_263ma_490 span{color:var(--text-primary);font-size:.9rem}._imdbLink_263ma_512{color:var(--accent-light);font-size:.9rem;text-decoration:none}._imdbLink_263ma_512:hover{text-decoration:underline}
@@ -0,0 +1,4 @@
1
+ import{d as v,A as T,h as y,u as t,S as Ve,n as Fr,o as qr,a as zr,T as Se,q as S}from"./vendor-core-8R2fFbyN.js";import{u as Wr}from"./vendor-query-BXRECSI6.js";import{e as An,z as Ur,M as cn,B as _e}from"./index-lo-bz7f2.js";import{I as $}from"./vendor-icons-CDMuNDeL.js";import{M as Hr,t as ur,f as Rn,d as jr,C as Kr,S as Yr,U as Qr,a as Gr,p as Dn,u as Jr,b as Xr,c as Zr,l as es,q as ts,i as Pn,v as ns,w as rs,x as cr,s as Ln,e as ss,g as as,h as os,r as is,j as nt,k as ls,E as cs,A as ds,P as us,m as be,o as ms}from"./AvSyncCalibrator-oK6LlG61.js";import{O as un,S as hs,a as ps,A as fs}from"./OptionListMenu-CkK2BvEz.js";import{u as gs}from"./useMatureConsent-CT7-KfzG.js";import{u as vs}from"./useProviders-xlftutIo.js";import{d as bs,g as ys,h as Ss,f as _s,e as Cs,j as Ts,k as ks}from"./useTvLibrary-BHeWSd1F.js";import{l as Es,c as Ns}from"./hls-B_yo8-yR.js";import{u as ws}from"./useIsMobile-Dm_b6Ob3.js";import{S as xs}from"./SynopsisText-BcpwT5iw.js";const Is="_fullscreenFlat_1deq4_1",Bs="_timeDisplay_1deq4_15",Ms="_bottomControls_1deq4_19",As="_leftControls_1deq4_23",Ps="_rightControls_1deq4_24",Ls="_controlBtn_1deq4_28",$s="_controlsOverlay_1deq4_47",Rs="_hidden_1deq4_67",Ds="_topControls_1deq4_73",Os="_backBtn_1deq4_93",Vs="_videoTitleInfo_1deq4_113",Fs="_animeTitle_1deq4_119",qs="_episodeLabel_1deq4_127",zs="_speedBoostBadge_1deq4_134",Ws="_progressBarContainer_1deq4_180",Us="_progressBar_1deq4_180",Hs="_thumb_1deq4_199",js="_bufferedBar_1deq4_217",Ks="_watchedBar_1deq4_227",Ys="_scrubbing_1deq4_252",Qs="_timeBubble_1deq4_256",Gs="_bottomControlsRow_1deq4_270",Js="_nextEpisodeBtn_1deq4_293",Xs="_active_1deq4_346",Zs="_settingsPanel_1deq4_421",ea="_settingsHeader_1deq4_440",ta="_settingsBackBtn_1deq4_448",na="_settingsTitle_1deq4_466",ra="_settingsContent_1deq4_477",sa="_currentValue_1deq4_486",aa="_menuItem_1deq4_501",oa="_menuNote_1deq4_534",a={fullscreenFlat:Is,timeDisplay:Bs,bottomControls:Ms,leftControls:As,rightControls:Ps,controlBtn:Ls,controlsOverlay:$s,hidden:Rs,topControls:Ds,backBtn:Os,videoTitleInfo:Vs,animeTitle:Fs,episodeLabel:qs,speedBoostBadge:zs,progressBarContainer:Ws,progressBar:Us,thumb:Hs,bufferedBar:js,watchedBar:Ks,scrubbing:Ys,timeBubble:Qs,bottomControlsRow:Gs,nextEpisodeBtn:Js,active:Xs,settingsPanel:Zs,settingsHeader:ea,settingsBackBtn:ta,settingsTitle:na,settingsContent:ra,currentValue:sa,menuItem:aa,menuNote:oa},dn=-1e4,$n=1e4,dr=500,ia=({classes:u,delayMs:w,onDelayChange:Z})=>{const[U,q]=v(null),V=U??w,r=T(Z);r.current=Z;const B=T(w);B.current=w;const se=T(null);se.current=U,y(()=>{q(null)},[w]),y(()=>()=>{const H=se.current;H!==null&&H!==B.current&&r.current(H)},[]);const me=H=>{B.current=H,se.current=null,r.current(H),q(null)},l=H=>{const ne=se.current??B.current,Fe=Math.max(dn,Math.min($n,ne+H));me(Fe)};return t(Ve,{children:[t("div",{style:{display:"flex",gap:6,padding:"0.5rem 0.75rem 0.25rem"},children:[t("button",{type:"button",className:u.item,onClick:()=>l(-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:u.item,onClick:()=>l(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:u.item,onClick:()=>me(0),disabled:V===0,"aria-label":"Reset subtitle timing",style:{flex:1,justifyContent:"center"},children:t("span",{children:"Reset"})})]}),t(Hr,{label:"Subtitle timing",display:ur(V),min:dn,max:$n,step:100,value:V,percent:(V-dn)/($n-dn)*100,onChange:H=>{const ne=Math.round(H);se.current=ne,q(ne)},onCommit:()=>{const H=se.current;H!==null&&me(H)}}),t("div",{className:u.note,children:"Positive delays subtitles (show later). Negative shows them earlier. 0.0s is default."})]})},la=({classes:u,tracks:w,selected:Z,onChange:U})=>t(un,{classes:u,options:w.map((q,V)=>({key:String(V),label:q.label||q.language,selected:V===Z})),onSelect:q=>U(Number(q))}),ca=({player:u,title:w,episodeLabel:Z,audioTracks:U,selectedAudioTrack:q,onAudioTrackChange:V,subtitles:r,selectedSubtitle:B,onSubtitleChange:se,streams:me,qualityIdx:l,onQualityChange:H,onBack:ne,children:Fe,movyServers:g=[],selectedMovyServer:ye="atlanta",onMovyServerSelect:R,isMovySource:$t=!1,videoDelayEnabled:ae=!1,onVideoDelayToggle:qe,videoDelayMs:yt=0,onVideoDelayChange:St,onCalibrateAvSync:Rt,subtitleDelayMs:Dt=0,onSubtitleDelayChange:mn,showNextEpisodeButton:Ot=!1,onNextEpisode:oe})=>{const{state:M,refs:Vt,actions:P}=u,j=Vt.videoRef,{subtitleFontSize:he,subtitlePosition:K,subtitleBgOpacity:rt,subtitleBgColor:st,subtitleTextColor:Ce,subtitleEdge:ze,subtitleBold:pe}=M,[x,D]=v(null),Ie=T(null),[Ae,hn]=v(0);y(()=>{const o=j.current;if(!o)return;const c=()=>hn(o.clientHeight||0);c();const Be=new ResizeObserver(c);return Be.observe(o),()=>Be.disconnect()},[j,me]);const fe=(o,c)=>{try{localStorage.setItem(o,String(c))}catch{}},at=(o,c)=>{switch(o){case"fontSize":typeof c=="number"&&(P.setSubtitleFontSize(c),fe("subtitleFontSize",c));break;case"position":typeof c=="number"&&(P.setSubtitlePosition(c),fe("subtitlePosition",c));break;case"bgOpacity":typeof c=="number"&&(P.setSubtitleBgOpacity(c),fe("subtitleBgOpacity",c));break;case"bgColor":typeof c=="string"&&(P.setSubtitleBgColor(c),fe("subtitleBgColor",c));break;case"textColor":typeof c=="string"&&(P.setSubtitleTextColor(c),fe("subtitleTextColor",c));break;case"edge":(c==="shadow"||c==="outline"||c==="none")&&(P.setSubtitleEdge(c),fe("subtitleEdge",c));break;case"bold":typeof c=="boolean"&&(P.setSubtitleBold(c),fe("subtitleBold",c));break}};y(()=>{const o="tv-player-subtitle-style";let c=document.getElementById(o);c||(c=document.createElement("style"),c.id=o,document.head.appendChild(c));const Be={fontSize:he,position:K,bgOpacity:rt,bgColor:st,textColor:Ce,edge:ze,bold:pe},L=j.current,kt=Rn(he,Ae||L?.clientHeight||720);if(c.textContent=jr({...Be,fontSize:kt}),L){const Et=()=>{const E=Number(K);return isNaN(E)?0:Math.max(0,Math.min(100,E))},Te=(E,Q)=>{try{const A=E;A.snapToLines=!1,A.line=Q}catch{}},vn=()=>{const E=kt*16,Q=L.videoHeight||L.clientHeight||720,A=L.videoWidth||L.clientWidth||1280;return{step:E*1.3/Q*100,chars:Math.max(20,Math.floor(A/(E*.55)))}},ct=E=>{const Q=Math.max(0,Math.min(100,100-Et())),A=Array.from(E.activeCues??[]);if(A.length<=1){A.forEach(Le=>Te(Le,Q));return}const{step:ut,chars:wt}=vn();let je=Q;for(let Le=A.length-1;Le>=0;Le--){const m=String(A[Le].text??"").replace(/<[^>]*>/g,"").split(`
2
+ `).reduce((O,Yt)=>O+Math.max(1,Math.ceil(Yt.length/wt)),0),Ke=je-m*ut;Te(A[Le],Math.max(0,Ke)),je=Ke-ut*.4}},Nt=()=>{const E=Math.max(0,Math.min(100,100-Et()));Array.from(L.textTracks).forEach(Q=>{Q.cues&&(Array.from(Q.cues).forEach(A=>Te(A,E)),Q.mode==="showing"&&ct(Q))})};Nt();const dt=E=>{const Q=E.target;Q.mode==="showing"&&ct(Q)},Ht=()=>{Array.from(L.textTracks).forEach(E=>{E.removeEventListener("cuechange",dt),E.addEventListener("cuechange",dt)}),Nt()};Array.from(L.textTracks).forEach(E=>{E.addEventListener("cuechange",dt)}),L.textTracks.addEventListener("addtrack",Ht);const jt=Array.from(L.querySelectorAll("track")),Kt=()=>Nt();return jt.forEach(E=>E.addEventListener("load",Kt)),()=>{Array.from(L.textTracks).forEach(E=>{E.removeEventListener("cuechange",dt)}),L.textTracks.removeEventListener("addtrack",Ht),jt.forEach(E=>E.removeEventListener("load",Kt))}}},[he,K,rt,st,Ce,ze,pe,B,r,j,Ae]);const ot=o=>{const c=j.current;!c||isNaN(M.duration)||M.duration===0||(c.currentTime=o*M.duration)},pn=()=>{j.current&&(P.setIsScrubbing(!0),P.wasPlayingBeforeScrub.current=!j.current.paused,j.current.pause())},_t=o=>{const c=j.current;c&&M.duration&&(c.currentTime=o*M.duration)},We=()=>{P.setIsScrubbing(!1),P.wasPlayingBeforeScrub.current&&j.current?.play().catch(()=>{})},ee=o=>{const c=j.current;c&&(c.volume=o,c.muted=o===0,localStorage.setItem("playerVolume",o.toString()))},Ft=()=>{P.toggleMute()},Pe=r.length>0,k=B>=0,X=()=>{D("main"),P.setShowControls(!0)},qt=()=>{if(k){se(-1);return}let o=null;try{o=localStorage.getItem("tvLastSubtitle")}catch{}se(Dn(r,{lastKey:o,enabled:!0}))},Ct=()=>{D(null)},Tt=()=>t(Ve,{children:[me.length>1&&t("button",{className:a.menuItem,onClick:()=>D("quality"),children:[t("span",{children:"Quality"}),t("span",{className:a.currentValue,children:me[l]?.quality||"Auto"})]}),$t&&g.length>0&&t("button",{className:a.menuItem,onClick:()=>D("server"),children:[t("span",{style:{display:"flex",alignItems:"center",gap:6},children:[t($,{name:"server",size:12})," Movy Server"]}),t("span",{className:a.currentValue,style:{textTransform:"capitalize"},children:ye})]}),Pe&&t("button",{className:a.menuItem,onClick:()=>D("subtitles"),children:[t("span",{children:"Subtitles"}),t("span",{className:a.currentValue,children:k?r[B]?.label||r[B]?.language:"Off"})]}),Pe&&t("button",{className:a.menuItem,onClick:()=>D("subtitle-style"),children:[t("span",{children:"Subtitle Style"}),t("span",{className:a.currentValue,children:[he.toFixed(1),"x · ",K]})]}),Pe&&t("button",{className:a.menuItem,onClick:()=>D("subtitle-timing"),children:[t("span",{children:"Subtitle Timing"}),t("span",{className:a.currentValue,children:ur(Dt)})]}),U.length>0&&t("button",{className:a.menuItem,onClick:()=>D("audio"),children:[t("span",{children:"Audio Track"}),t("span",{className:a.currentValue,children:U[q]?.label||U[q]?.language})]}),t("button",{className:a.menuItem,onClick:()=>D("av-sync"),children:[t("span",{children:"A/V Sync"}),t("span",{className:a.currentValue,children:ae?`${yt}ms`:"Off"})]})]}),fn=()=>t(un,{classes:{item:a.menuItem,active:a.active},options:me.map((o,c)=>({key:String(c),label:o.quality,selected:c===l})),onSelect:o=>H(Number(o))}),_=()=>t(un,{classes:{item:a.menuItem,active:a.active},options:[{key:"off",label:"Off",selected:!k},...r.map((o,c)=>({key:String(c),label:o.label||o.language,selected:c===B}))],onSelect:o=>se(o==="off"?-1:Number(o))}),d=()=>t(ps,{classes:{item:a.menuItem,active:a.active},values:{fontSize:he,position:K,bgOpacity:rt,bgColor:st,textColor:Ce,edge:ze,bold:pe},onChange:at}),ie=()=>t(ia,{classes:{item:a.menuItem,active:a.active,note:a.menuNote},delayMs:Dt,onDelayChange:o=>mn?.(o)}),le=()=>t(la,{classes:{item:a.menuItem,active:a.active},tracks:U,selected:q,onChange:V}),zt=()=>t(un,{classes:{item:a.menuItem,active:a.active},options:g.map(o=>({key:o,label:t("span",{style:{textTransform:"capitalize"},children:o}),selected:ye===o})),onSelect:o=>R?.(o)}),Wt=()=>t(fs,{classes:{item:a.menuItem,active:a.active,note:a.menuNote},enabled:ae,delayMs:yt,onToggle:o=>qe?.(o),onDelayChange:o=>St?.(o),onCalibrate:()=>{D(null),Rt?.()}}),Ue=M.isMuted?t($,{name:"volume-mute"}):M.volume<.5?t($,{name:"volume-down"}):t($,{name:"volume-up"}),Ut=t("div",{className:`${a.controlsOverlay} ${!M.showControls&&!x?a.hidden:""}`,"data-speed-boost-ignore":"true",style:{pointerEvents:"none",background:"none"},children:t("div",{className:a.topControls,onClick:o=>o.stopPropagation(),children:[t("button",{className:a.backBtn,onClick:ne,title:"Back","aria-label":"Back",children:t($,{name:"chevron-left"})}),t("div",{className:a.videoTitleInfo,children:[t("span",{className:a.animeTitle,children:w}),Z&&t("span",{className:a.episodeLabel,children:Z})]})]})}),He=t(Kr,{isPlaying:M.isPlaying,onTogglePlay:P.togglePlay,onSkipBack:()=>P.seek(-10),onSkipForward:()=>P.seek(10)}),it=t("div",{className:`${a.controlsOverlay} ${!M.showControls&&!x?a.hidden:""}`,"data-speed-boost-ignore":"true",style:{pointerEvents:"none",background:"none",justifyContent:"flex-end"},children:t("div",{className:a.bottomControls,onClick:o=>o.stopPropagation(),children:[t(Yr,{classes:{container:a.progressBarContainer,scrubbing:a.scrubbing,timeBubble:a.timeBubble,bar:a.progressBar,buffered:a.bufferedBar,watched:a.watchedBar,thumb:a.thumb},videoRef:j,duration:M.duration,formatTime:An,isScrubbing:M.isScrubbing,buffered:"full",onSeek:ot,onScrubStart:pn,onScrubMove:_t,onScrubEnd:We,timeLabelRef:Ie}),t("div",{className:a.bottomControlsRow,children:[t("div",{className:a.leftControls,children:[t("button",{className:a.controlBtn,onClick:P.togglePlay,"aria-label":M.isPlaying?"Pause":"Play",children:M.isPlaying?t($,{name:"pause"}):t($,{name:"play"})}),t(Qr,{muted:M.isMuted,volume:M.volume,volumeIcon:Ue,buttonClassName:a.controlBtn,onToggleMute:Ft,onVolumeChange:ee,onExpandedChange:o=>P.setShowVolumeSlider(o)}),t("span",{className:a.timeDisplay,ref:Ie,children:[An(0)," / ",An(M.duration)]})]}),t("div",{className:a.rightControls,children:[Ot&&t("button",{className:a.nextEpisodeBtn,onClick:oe,title:"Play next episode",children:"Next EP"}),Pe&&t("button",{className:`${a.controlBtn} ${k?a.active:""}`,onClick:qt,"aria-label":k?"Turn subtitles off":"Turn subtitles on",children:t($,{name:"closed-captioning"})}),t("button",{className:`${a.controlBtn} ${x?a.active:""}`,onClick:()=>x?Ct():X(),"aria-label":"Settings",children:t($,{name:"cog"})}),t("button",{className:a.controlBtn,onClick:P.toggleFullscreen,"aria-label":M.isFullscreen?"Exit Fullscreen":"Fullscreen",children:M.isFullscreen?t($,{name:"compress"}):t($,{name:"expand"})})]})]})]})}),gn=x?t("div",{"data-speed-boost-ignore":"true",onClick:o=>o.stopPropagation(),children:t(hs,{classes:{panel:a.settingsPanel,header:a.settingsHeader,backBtn:a.settingsBackBtn,title:a.settingsTitle,content:a.settingsContent},title:x==="main"?"Settings":x==="subtitle-style"?"Subtitle Style":x==="subtitle-timing"?"Subtitle Timing":x==="audio"?"Audio Track":x==="server"?"Movy Server":x==="av-sync"?"A/V Sync":x.charAt(0).toUpperCase()+x.slice(1),onBack:()=>x==="main"?Ct():D("main"),children:[x==="main"&&Tt(),x==="quality"&&fn(),x==="subtitles"&&_(),x==="subtitle-style"&&d(),x==="subtitle-timing"&&ie(),x==="audio"&&le(),x==="server"&&zt(),x==="av-sync"&&Wt()]})}):null,lt=M.isSpeedBoostActive?t("div",{className:a.speedBoostBadge,"aria-hidden":"true",children:[t("span",{children:"2x"}),t($,{name:"forward",size:12})]}):null;return t(Gr,{player:u,topBar:Ut,centerControls:He,bottomBar:it,settingsPanel:gn,overlays:lt,isInteracting:!!x,className:M.isFullscreen?a.fullscreenFlat:"",children:Fe})};function da(u,w,Z){const U=()=>{const V=Array.isArray(u.audioTracks)?u.audioTracks.length:0,r=Z.getWant(),B=V>0?Math.min(Math.max(0,r),V-1):r;u.audioTrack=B,B!==r&&Z.onResolve(B)},q=(V,r)=>{const B=Z.getWant(),se=Array.isArray(u.audioTracks)?u.audioTracks.length:0;if(r.id!==B&&B>=0&&B<se){u.audioTrack!==B&&(u.audioTrack=B);return}Z.onResolve(r.id)};return u.on(w.MANIFEST_PARSED,U),u.on(w.AUDIO_TRACK_SWITCHED,q),()=>{u.off(w.MANIFEST_PARSED,U),u.off(w.AUDIO_TRACK_SWITCHED,q)}}const ua="_page_263ma_1",ma="_header_263ma_7",ha="_pageTitle_263ma_11",pa="_searchForm_263ma_21",fa="_searchInput_263ma_27",ga="_searchBtn_263ma_42",va="_suggestions_263ma_58",ba="_suggestionPill_263ma_65",ya="_statusMsg_263ma_81",Sa="_error_263ma_87",_a="_textOnly_263ma_91",Ca="_spinner_263ma_96",Ta="_spin_263ma_96",ka="_grid_263ma_110",Ea="_skeletonCard_263ma_116",Na="_skeletonThumb_263ma_121",wa="_skeletonLine_263ma_127",xa="_shimmer_263ma_134",Ia="_backBtn_263ma_154",Ba="_meta_263ma_172",Ma="_headerActions_263ma_180",Aa="_watchlistBtn_263ma_187",Pa="_active_263ma_205",La="_year_263ma_215",$a="_rating_263ma_220",Ra="_typeBadge_263ma_229",Da="_tv_263ma_237",Oa="_movie_263ma_242",Va="_tvSeries_263ma_247",Fa="_tvMiniSeries_263ma_252",qa="_overview_263ma_257",za="_controls_263ma_264",Wa="_controlLabel_263ma_272",Ua="_select_263ma_282",Ha="_playerSection_263ma_293",ja="_video_263ma_297",Ka="_videoHidden_263ma_319",Ya="_delayCanvas_263ma_324",Qa="_delayCanvasActive_263ma_337",Ga="_subtitleOverlay_263ma_341",Ja="_videoIframe_263ma_360",Xa="_retryButton_263ma_368",Za="_sidebarSeason_263ma_383",eo="_mobileSeasonRow_263ma_399",to="_sidebarPosterCard_263ma_413",no="_sidebarPosterMeta_263ma_428",ro="_providerSelectWrap_263ma_445",so="_genreRow_263ma_457",ao="_genreChip_263ma_464",oo="_metaRow_263ma_474",io="_detailGrid_263ma_483",lo="_detailItem_263ma_490",co="_imdbLink_263ma_512",h={page:ua,header:ma,pageTitle:ha,searchForm:pa,searchInput:fa,searchBtn:ga,suggestions:va,suggestionPill:ba,statusMsg:ya,error:Sa,textOnly:_a,spinner:Ca,spin:Ta,grid:ka,skeletonCard:Ea,skeletonThumb:Na,skeletonLine:wa,shimmer:xa,backBtn:Ia,meta:Ba,headerActions:Ma,watchlistBtn:Aa,active:Pa,year:La,rating:$a,typeBadge:Ra,tv:Da,movie:Oa,tvSeries:Va,tvMiniSeries:Fa,overview:qa,controls:za,controlLabel:Wa,select:Ua,playerSection:Ha,video:ja,videoHidden:Ka,delayCanvas:Ya,delayCanvasActive:Qa,subtitleOverlay:Ga,videoIframe:Ja,retryButton:Xa,sidebarSeason:Za,mobileSeasonRow:eo,sidebarPosterCard:to,sidebarPosterMeta:no,providerSelectWrap:ro,genreRow:so,genreChip:ao,metaRow:oo,detailGrid:io,detailItem:lo,imdbLink:co},uo=[],Eo=()=>{const{id:u}=Fr(),[w]=qr(),Z=T(w);Z.current=w;const U=zr(),q=Wr(),V=w.get("type"),[r,B]=v(null),[se,me]=v(!1),[l,H]=v(()=>parseInt(w.get("s")||"1",10)||1),[ne,Fe]=v([]),[g,ye]=v(()=>parseInt(w.get("e")||"1",10)||1),[R,$t]=v(()=>{try{return localStorage.getItem("tvProvider")||""}catch{return""}}),[ae,qe]=v([]),[yt,St]=v(""),{options:Rt,isFallback:Dt,isLoading:mn}=vs(),Ot=Se(()=>Rt.filter(e=>(e.kind??"tv")==="tv").map(e=>({id:e.value,label:e.label,tier:e.tier==="embed"?"embed":"direct",servers:e.servers})),[Rt]),oe=Dt||Ot.length===0?uo:Ot,M=oe.filter(e=>e.tier==="direct"),Vt=oe.filter(e=>e.tier==="embed"),[P,j]=v(!1),[he,K]=v(""),[rt,st]=v([]),[Ce,ze]=v(0),[pe,x]=v([]),[D,Ie]=v(-1),[Ae,hn]=v("all"),[fe,at]=v(0),[ot,pn]=v(""),[_t,We]=v(""),[ee,Ft]=v(()=>{try{return localStorage.getItem("movyServer")||""}catch{return""}}),Pe=Se(()=>oe.find(e=>e.id===R),[oe,R]),k=Pe?.tier==="embed",X=Se(()=>Pe?.servers??[],[Pe]),qt=T([]);y(()=>{qt.current=ae},[ae]);const Ct=T(Ce);y(()=>{Ct.current=Ce},[Ce]);const Tt=T(D);y(()=>{Tt.current=D},[D]);const fn=Se(()=>[],[]),_=Jr({skipIntervals:fn}),d=_.refs.videoRef,ie=T(null),le=T([]),zt=T(null),Wt=T(null),[Ue,Ut]=v(()=>{try{const e=Number(localStorage.getItem("playerVideoDelayMs"));if(Number.isFinite(e)&&e>=0&&e<=500)return Math.round(e)}catch{}return 180}),[He,it]=v(()=>{try{return localStorage.getItem("playerVideoDelayEnabled")==="true"}catch{return!1}}),[gn,lt]=v(!1),[o,c]=v(!1),Be=T(null),L=T(null),kt=(e,n)=>{try{localStorage.setItem("playerVideoDelayMs",String(e)),localStorage.setItem("playerVideoDelayEnabled",String(n))}catch{}},Et=e=>{const n=Math.max(0,Math.min(500,Math.round(e)));Ut(n);try{localStorage.setItem("playerVideoDelayMs",String(n))}catch{}},[Te,vn]=v(()=>{try{const e=Number(localStorage.getItem("tvSubtitleDelayMs"));if(Number.isFinite(e)&&e>=-1e4&&e<=1e4)return Math.round(e)}catch{}return 0}),ct=T(Te);ct.current=Te;const Nt=S(e=>{const n=Math.max(-1e4,Math.min(1e4,Math.round(e)));if(ct.current!==n){ct.current=n,vn(n);try{localStorage.setItem("tvSubtitleDelayMs",String(n))}catch{}}},[]),dt=()=>{Be.current={enabled:He,ms:Ue},it(!0);try{localStorage.setItem("playerVideoDelayEnabled","true")}catch{}lt(!0)},Ht=()=>{const e=Be.current;Be.current=null,e&&(Ut(e.ms),it(e.enabled),kt(e.ms,e.enabled)),c(!1),lt(!1)},jt=()=>{Be.current=null,it(!0),kt(Ue,!0),c(!1),lt(!1)},Kt=()=>{if(o){c(!1);return}const e=d.current;e&&!isNaN(e.currentTime)&&(L.current=e.currentTime),c(!0)},E=He?Ue:0;Xr({videoRef:d,canvasRef:zt,delayMs:E,enabled:He});const Q=He,A=Q||Te!==0,ut=T(A);ut.current=A;const wt=S(()=>{if(!ut.current)return;const e=d.current;e&&Array.from(e.textTracks).forEach(n=>{n.mode!=="hidden"&&(n.mode="hidden")})},[d]),{hasConsent:je,grant:Le}=gs(),mt=T("");mt.current||(mt.current=`tv-${Date.now()}-${Math.random().toString(36).slice(2)}`);const m=V==="movie",Ke=u?bs(V||"tv",u):"",O=Ke,Yt=ys(),Qt=Ss(),{toggle:On,bookmarkedIds:mr,pending:hr}=_s(),{data:Vn}=Cs(r?Ke:void 0),Gt=Vn?!!Vn.inLibrary:Ke?mr.has(Ke):!1,pr=S(()=>{!r||!u||On({tmdbId:Number(u),mediaType:V||"tv",title:r.title,poster:r.poster,year:r.year,adult:r.adult})},[r,u,V,On]),{data:Ye,isFetched:Fn,isPending:qn}=Ts(O||void 0,l,g),Jt=Se(()=>ne.map(e=>e.episode_number).sort((e,n)=>e-n),[ne]),Qe=Jt.indexOf(g),bn=Qe>0?Jt[Qe-1]:null,N=Qe>=0&&Qe<Jt.length-1?Jt[Qe+1]:null,Xt=Se(()=>(r?.seasons??[]).map(e=>e.season_number).filter(e=>Number.isFinite(e)).sort((e,n)=>e-n),[r]),ge=Se(()=>{if(m||N!=null)return null;const e=Xt.indexOf(l);return e>=0&&e<Xt.length-1?Xt[e+1]:(r?.number_of_seasons??0)>l?l+1:null},[m,N,Xt,l,r?.number_of_seasons]),zn=Ye?.currentTime??0,Wn=Ye?.duration??0,yn=Ye?.completed===!0||Ye?.completed===1||Pn(zn,Wn),[ke,Me]=v(!1),Ee=T(!1),Sn=T(null),xt=T(null);y(()=>{Ee.current=!1,xt.current=null,Me(!1)},[O,l,g]);const[Ne,Zt]=v(!1),[ht,Un]=v(0),[Ge,Hn]=v(!1),[$e,Je]=v(!1),[fr,_n]=v(!1),[gr,jn]=v(""),[en,vr]=v(!1),[br,Cn]=v(!1);Zr(_,(ae.length>0||_t!=="")&&!Ne&&!ke&&!$e);const yr=ws(),[pt,Sr]=v(es),_r=S(e=>{Sr(e),ts(e)},[]),ce=T(!1),Xe=T(null),Tn=T(0),Kn=T(!1),Yn=T(0),te=T(null),It=T(""),Cr=cr(zn,Wn),Bt=!ce.current&&!Ee.current&&(Ne||ke||$e||yn||Cr),ft=T(Bt);ft.current=Bt;const gt=T(!1);y(()=>{gt.current=Ge},[Ge]);const Tr=e=>{const n=Math.floor(e/3600),s=Math.floor(e%3600/60),i=Math.floor(e%60);return n>0?`${n}:${String(s).padStart(2,"0")}:${String(i).padStart(2,"0")}`:`${s}:${String(i).padStart(2,"0")}`},Re=S((e,n)=>{if(!O||!n||n<30)return;const s=Pn(e,n),i=s?n:e;Math.abs(i-Tn.current)<10&&!s||(Tn.current=i,Yt.mutate({mediaId:O,season:l,episode:g,currentTime:Math.floor(i),duration:Math.floor(n),completed:s,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:V||"tv",adult:r?.adult?1:0}))},[O,l,g,Yt,r,V]),we=S((e,n)=>{c(!1),lt(!1);const s=new URLSearchParams(w);s.set("type",w.get("type")||"tv"),s.set("s",String(e)),s.set("e",String(n)),U(`${window.location.pathname}?${s.toString()}`)},[w,U]),Mt=S(()=>{const e=d.current;if(!e||m||N==null){_n(!1);return}const n=e.duration||0,s=e.currentTime||0;_n(n>0&&s/n>=.8)},[m,N,d]),tn=S((e,n)=>["tv-sources",R,m?"movie":"tv",u,e,n,ee],[R,m,u,ee]),nn=S(async(e,n)=>{if(!r||!u||!R)return{valid:!1,sources:[]};const s=m?"movie":"tv",i=new URLSearchParams({title:r.title||"",year:r.year||"",season:String(e),episode:String(n),totalSeasons:String(r.number_of_seasons||1),imdbId:r.imdb_id||""});return X.length>0&&ee&&i.set("server",ee),await(await fetch(`/api/tv/sources/${R}/${s}/${u}?${i.toString()}`)).json()},[r,u,R,m,X,ee]),Qn=S(()=>{if(m||!r||!u||!R||k||N==null)return;const e=tn(l,N);q.getQueryState(e)?.status!=="success"&&q.prefetchQuery({queryKey:e,queryFn:()=>nn(l,N),staleTime:300*1e3,gcTime:1800*1e3})},[m,r,u,R,k,N,l,q,tn,nn]),kr=S(()=>{if(o)return;Mt();const e=d.current;!e||e.paused||e.ended||(e.duration>0&&e.duration-e.currentTime<=60&&Qn(),Xe.current&&clearTimeout(Xe.current),Xe.current=setTimeout(()=>{Re(e.currentTime,e.duration||0)},5e3))},[Re,d,o,Mt,Qn]),Er=S(()=>{const e=d.current;if(!e||!r)return;Xe.current&&clearTimeout(Xe.current),Re(e.currentTime,e.duration||0),Kn.current=!0;const n=ns({seekInduced:Date.now()-Yn.current<rs,autoplayEnabled:pt,hasNext:!m&&N!=null,isFinal:m||N==null});n==="advance"&&N!=null?(ye(N),we(l,N)):n==="prompt-next"?(Ee.current=!1,ce.current=!0,Me(!0)):n==="prompt-complete"&&(jn(m?r.title:`${r.title} — Season ${l}`),Je(!0),Ee.current=!0,ce.current=!0)},[m,r,l,N,pt,Re,we,d]),Nr=S(()=>{Kn.current=!1,_.actions.onPlay()},[_.actions]),wr=S(()=>{_.actions.onPause();const e=d.current;e&&!e.ended&&Re(e.currentTime,e.duration||0)},[_.actions,Re,d]),xr=S(()=>{_.actions.onLoadedMetadata();const e=d.current;if(e){try{const n=parseFloat(localStorage.getItem("playerVolume")||"");isNaN(n)||(e.volume=Math.max(0,Math.min(1,n))),e.muted=localStorage.getItem("playerMuted")==="true"}catch{}if(te.current!=null&&te.current>0){try{e.currentTime=te.current}catch{}te.current=null}Mt()}},[_.actions,d,Mt]),vt=S(()=>{const e=d.current;if(e&&te.current!=null&&te.current>0){try{e.currentTime=te.current}catch{}te.current=null}},[d]),Ir=S(()=>{ht>0&&(te.current=ht);const e=d.current;if(e&&ht>0){try{e.currentTime=ht,te.current=null}catch{}e.play().catch(()=>{})}Zt(!1),ce.current=!0},[ht,d]),Gn=S(()=>{te.current=null;const e=d.current;e&&(e.currentTime=0,e.play().catch(()=>{})),Zt(!1),ce.current=!0},[d]),Br=S(()=>{Ee.current=!0,Me(!1),ce.current=!0},[]),Mr=S(()=>{Ee.current=!0,Me(!1),ce.current=!0,te.current=null;const e=d.current;if(e){try{e.currentTime=0}catch{}e.play().catch(()=>{})}},[d]),Jn=S(()=>{N!=null&&(Ee.current=!0,Me(!1),ce.current=!0,ye(N),we(l,N))},[N,l,we]),Xn=S(()=>{ge!=null&&(Ee.current=!0,Me(!1),Je(!1),ce.current=!0,H(ge),ye(1),we(ge,1))},[ge,we]),Ar=S(async()=>{if(O)try{await Qt.mutateAsync({id:O,status:"Completed"}),Je(!1),Me(!1),U("/")}catch{}},[O,Qt,U]);y(()=>{ce.current=!1,Sn.current=null,Zt(!1),_n(!1),Un(0),Hn(!1),gt.current=!1,te.current=null,It.current=`${O}:${l}:${g}`,Tn.current=0},[O,l,g]),y(()=>{Fn&&(Hn(!0),gt.current=!0)},[Fn,O,l,g]),y(()=>{if(!Ye||ce.current)return;const e=`${O}:${l}:${g}`;if(Sn.current===e)return;Sn.current=e;const n=Ye,s=n.currentTime??0,i=n.duration??0;cr(s,i)&&(Un(s),Zt(!0))},[Ye,O,l,g]),y(()=>{if(!Ge||ce.current||Ee.current||Ne||$e||ke)return;const e=`${O}:${l}:${g}`;if(xt.current!==e){if(!yn){qn||(xt.current=e);return}if(m){xt.current=e,Me(!0);return}if(!(!r||Qe<0||ne.length===0)){if(xt.current=e,N==null&&ge==null){r&&ne.length>0&&(jn(`${r.title} — Season ${l}`),Je(!0),Ee.current=!0,ce.current=!0);return}Me(!0)}}},[Ge,yn,qn,Ne,$e,ke,m,N,ge,r,Qe,ne.length,O,l,g]),y(()=>{(Ne||ke)&&d.current&&d.current.pause()},[Ne,ke,d]),y(()=>{const e=d.current;return()=>{Xe.current&&clearTimeout(Xe.current),e&&!e.ended&&Re(e.currentTime,e.duration||0)}},[Re,d]);const kn=S(e=>{let n=null,s=!0;try{n=localStorage.getItem("tvLastSubtitle"),s=localStorage.getItem("tvSubtitlesEnabled")!=="false"}catch{}return Dn(e,{lastKey:n,enabled:s})},[]),En=S(e=>{if(!(e<0))try{localStorage.setItem("tvSubtitlesEnabled","true"),localStorage.setItem("tvSelectedSubtitle",String(e))}catch{}},[]),Zn=S(e=>{if(e.length===0)return 0;let n=null;try{n=localStorage.getItem("tvLastAudio")}catch{}if(n){const s=e.findIndex(p=>Ln(p)===n);if(s>=0)return s;const i=n.indexOf("|||"),f=i>=0?n.slice(0,i):n,G=i>=0?n.slice(i+3):n,b=e.findIndex(p=>p.language===f||p.label===G);if(b>=0)return b}return Dn(e,{lastKey:null,enabled:!0})},[]),{data:er}=ks(O||void 0),tr=Se(()=>(er?.progress??[]).filter(n=>n.season===l&&(n.completed===!0||n.completed===1||Pn(n.currentTime,n.duration))).map(n=>String(n.episode)),[er,l]),nr=Se(()=>ne.map(e=>({id:String(e.episode_number),label:`Episode ${e.episode_number}`,sublabel:e.name||void 0,thumbnail:e.still_path?`https://image.tmdb.org/t/p/w185${e.still_path}`:void 0})),[ne]),rr=Se(()=>(r?.genres??[]).map(e=>e.name).slice(0,5),[r]),Nn=Se(()=>[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]);y(()=>{if(oe.length!==0&&!oe.some(e=>e.id===R)){const e=oe.find(n=>n.tier==="direct")?.id??oe[0].id;$t(e);try{localStorage.setItem("tvProvider",e)}catch{}}},[oe,R]),y(()=>{if(X.length!==0&&!X.includes(ee)){Ft(X[0]);try{localStorage.setItem("movyServer",X[0])}catch{}}},[X,ee]),y(()=>{if(!u){B(null),qe([]),St(""),K(""),We("");return}const e=Number(u),n=V||"tv";me(!0),B(null),qe([]),St(""),K(""),We("");const s=parseInt(Z.current.get("s")||"",10),i=parseInt(Z.current.get("e")||"",10);H(isNaN(s)?1:s),ye(isNaN(i)?1:i),at(0),fetch(`/api/tv/details/${n}/${e}`).then(f=>f.json()).then(f=>{B(f),me(!1),f.seasons&&f.seasons.length>0&&isNaN(s)&&H(f.seasons[0].season_number)}).catch(()=>{me(!1)})},[u,V]),y(()=>{if(!r||!u)return;if(!(r.seasons!==void 0||r.number_of_seasons!==void 0)){Fe([]);return}const n=parseInt(w.get("e")||"",10);fetch(`/api/tv/episodes/${u}/${l}`).then(s=>s.json()).then(s=>{if(Fe(s.episodes||[]),s.episodes?.length>0){const i=!isNaN(n)&&s.episodes.find(f=>f.episode_number===n)?n:s.episodes[0].episode_number;ye(i)}}).catch(()=>{})},[r,u,l,w]),y(()=>{!r||!u||m||fetch(`/api/tv/episodes/${u}/${l}`).then(e=>e.json()).then(e=>{const n=e.episodes||[];Fe(n),n.length>0&&!n.find(s=>s.episode_number===g)&&ye(n[0].episode_number)}).catch(()=>{})},[l,r,u,m,g]),y(()=>{if(!k||!r||!u)return;fetch(`/api/tv/embed/${R}/${m?"movie":"tv"}/${u}?season=${l}&episode=${g}`).then(n=>n.json()).then(n=>{if(n.url)return We(n.url),fetch(`/api/resolve?url=${encodeURIComponent(n.url)}`).then(s=>s.json()).then(s=>{s.finalUrl&&We(s.finalUrl)})}).catch(()=>{})},[R,r,u,l,g,m,k]);const rn=S(async()=>{if(!r||!u||!R||k||r.adult&&!je)return;const e=`${O}:${l}:${g}`;qt.current.length>0?K(""):(j(!0),K(""),qe([]),at(0),st([]),x([]));try{const s=await q.fetchQuery({queryKey:tn(l,g),queryFn:()=>nn(l,g),staleTime:3e5,gcTime:18e5});if(It.current!==e)return;if(j(!1),!s.valid||!s.sources?.length){K(s.error?`${s.error}`:X.length>0?`No streams from ${ee}. Try another server.`:"No streams available.");return}qe(s.sources),St(e),hn("all"),at(0),s.referer&&pn(s.referer);const i=s.audioTracks||[];st(i),ze(i.length>0?Zn(i):0);const f=s.subtitles||[];if(x(f),f.length>0){const p=kn(f);Ie(p),En(p)}else Ie(-1);fetch(`/api/tv/subtitles/${m?"movie":"tv"}/${u}?season=${l}&episode=${g}`).then(p=>p.json()).then(p=>{if(It.current!==e)return;const re=Array.isArray(p.subtitles)?p.subtitles:[];re.length!==0&&x(ve=>{const F=[...ve,...re.filter(I=>!ve.some(C=>C.url===I.url))];if(ve.length===0){const I=kn(F);Ie(I),En(I)}return F})}).catch(()=>{}),K("")}catch{if(It.current!==e)return;j(!1),K("Failed to load streams.")}},[r,u,R,l,g,m,k,je,X,ee,kn,En,Zn,O,q,tn,nn]),wn=S(e=>{const n=e.toLowerCase();Ft(n);try{localStorage.setItem("movyServer",n)}catch{}K("")},[]),Pr=S(e=>{$t(e);try{localStorage.setItem("tvProvider",e)}catch{}},[]);y(()=>{R&&r&&!k&&rn()},[R,r,rn,k]),y(()=>{if(!d.current||(ie.current&&(ie.current.destroy(),ie.current=null),k))return;let e=!1;if(o){const b=d.current;return b&&(b.pause(),b.removeAttribute("src"),b.load(),b.src="/av-sync-test.mp4",ft.current||b.play().catch(()=>{})),()=>{e=!0}}const n=Ae==="all"?ae:ae.filter(b=>b.type===Ae),s=yt===`${O}:${l}:${g}`&&n[fe]?.url||"";if(!s){try{d.current?.pause()}catch{}return}const i=d.current;if(It.current===`${O}:${l}:${g}`&&te.current==null&&!ft.current)try{!i.ended&&i.currentTime>1&&(te.current=i.currentTime)}catch{}i.pause(),i.removeAttribute("src"),i.load();const f=`/api/tv/stream-proxy?url=${encodeURIComponent(s)}&referer=${encodeURIComponent(ot)}`;n[fe]?.type==="hls"?(async()=>{const b=await Es();if(!e)if(b&&b.isSupported()){const p=new b({enableWorker:!0});ie.current=p,p.on(b.Events.ERROR,(F,I)=>{I.fatal&&(K(`Stream failed (${I.details}). Try another source or reload.`),j(!1),p.destroy(),ie.current=null)}),p.loadSource(f),p.attachMedia(i);const re=()=>{let F=!1,I=0;try{F=localStorage.getItem("tvSubtitlesEnabled")==="true";const C=parseInt(localStorage.getItem("tvSelectedSubtitle")||"0",10);!isNaN(C)&&C>=0&&(I=C)}catch{}return{enabled:F,index:I}},ve=()=>{if(typeof p.subtitleTrack!="number")return;if(le.current.length>0){p.subtitleTrack=-1;return}const F=Array.isArray(p.subtitleTracks)?p.subtitleTracks:[];if(F.length===0){p.subtitleTrack=-1;return}const I=re();if(I.enabled){const C=I.index<F.length?I.index:0;p.subtitleTrack=C,Ie(C),wt()}else p.subtitleTrack=-1};da(p,b.Events,{getWant:()=>Ct.current,onResolve:F=>ze(F)}),p.on(b.Events.MANIFEST_PARSED,()=>{ve(),L.current!=null&&(i.currentTime=L.current,L.current=null),vt(),!ft.current&&gt.current&&i.play().catch(()=>{})}),p.on(b.Events.SUBTITLE_TRACKS_UPDATED,()=>{ve()}),p.on(b.Events.SUBTITLE_TRACK_SWITCH,(F,I)=>{if(le.current.length>0){if(I.id!==-1)try{p.subtitleTrack=-1}catch{}return}const C=Array.isArray(p.subtitleTracks)?p.subtitleTracks:[];if(C.length!==0){if(I.id===-1){const Y=re();if(Y.enabled){const J=Y.index<C.length?Y.index:0;p.subtitleTrack=J;return}}Ie(I.id),wt()}})}else Ns(i)&&(i.src=f,L.current!=null&&(i.currentTime=L.current,L.current=null),vt(),!ft.current&&gt.current&&i.play().catch(()=>{K("Failed to play stream. Try another source.")}))})():(i.src=f,L.current!=null&&(i.currentTime=L.current,L.current=null),vt(),!ft.current&&gt.current&&i.play().catch(()=>{K("Failed to play stream. Try another source.")}));const G=()=>{const re=i.error?.code===4?"Video source not supported or not found":"Failed to load video stream";K(`${re}. The source may be invalid or expired. Try switching source or reloading.`),j(!1)};return i.addEventListener("error",G),()=>{e=!0,i.removeEventListener("error",G)}},[ae,yt,fe,Ae,R,ot,k,d,o,O,l,g,vt,wt]),y(()=>{if(!Ge||Ne||ke||$e||Bt||k||o)return;const e=d.current;!e||!e.paused||e.ended||e.readyState<1||(vt(),e.play().catch(()=>{}))},[Ge,Ne,ke,$e,Bt,k,o,vt,d]),y(()=>{const e=ie.current;!e||typeof e.audioTrack!="number"||(e.audioTrack=Ce)},[Ce]),y(()=>{const e=ie.current;!e||typeof e.subtitleTrack!="number"||!Array.isArray(e.subtitleTracks)||e.subtitleTracks.length===0||le.current.length>0||(D>=0?e.subtitleTrack=D:e.subtitleTrack=-1)},[D]),y(()=>{const e=d.current;if(!(!e||k)&&(e.querySelectorAll("track").forEach(n=>n.remove()),le.current=[],pe.length!==0&&(pe.forEach(n=>{const s=document.createElement("track");s.kind="subtitles",s.label=n.label||n.language||"Unknown",s.srclang=n.language||n.label||"en";const i=`/api/subtitle-proxy?url=${encodeURIComponent(n.url)}&referer=${encodeURIComponent(ot)}`;s.src=i,s.addEventListener("load",()=>{const f=le.current.indexOf(s),G=s.track;if(G&&f>=0){const b=f===Tt.current;G.mode=b&&!ut.current?"showing":"hidden"}}),e.appendChild(s),le.current.push(s)}),pe.length>0)))try{const n=ie.current;n&&typeof n.subtitleTrack=="number"&&n.subtitleTrack!==-1&&(n.subtitleTrack=-1)}catch{}},[pe,ot,k,R,d]),y(()=>{const e=d.current;if(!e||k)return;const n=ie.current;le.current.length>0&&n&&typeof n.subtitleTrack=="number"&&Array.isArray(n.subtitleTracks)&&n.subtitleTracks.length>0&&(n.subtitleTrack=-1);const s=()=>{const G=Rn(_.state.subtitleFontSize,e.clientHeight||720),b=Math.max(0,Math.min(100,100-_.state.subtitlePosition)),p=()=>{const C=G*16,Y=e.videoHeight||e.clientHeight||720,J=e.videoWidth||e.clientWidth||1280;return{step:C*1.3/Y*100,chars:Math.max(20,Math.floor(J/(C*.55)))}},re=(C,Y)=>{const J=C;J.snapToLines=!1,J.line=Y},ve=C=>{if(!C.cues)return;Array.from(C.cues).forEach(de=>re(de,b));const Y=Array.from(C.activeCues??[]);if(Y.length<=1){Y.forEach(de=>re(de,b));return}const{step:J,chars:z}=p();let Ze=b;for(let de=Y.length-1;de>=0;de--){const De=String(Y[de].text??"").replace(/<[^>]*>/g,"").split(`
3
+ `).reduce((on,Pt)=>on+Math.max(1,Math.ceil(Pt.length/z)),0);Ze=Math.max(0,Ze-De*J),re(Y[de],Ze),Ze-=J*.4}},F=le.current;if(F.length>0){F.forEach((C,Y)=>{const J=C.track;if(!J)return;const z=Y===D;J.mode=z&&!A?"showing":"hidden",z&&!A&&ve(J)});return}const I=Array.from(e.textTracks);I.length!==0&&I.forEach((C,Y)=>{const J=Y===D;C.mode=J&&!A?"showing":"hidden",J&&!A&&ve(C)})};s();const i=()=>s();e.textTracks.addEventListener("addtrack",i),e.addEventListener("loadedmetadata",s,{once:!0});const f=window.setTimeout(s,600);return()=>{e.textTracks.removeEventListener("addtrack",i),e.removeEventListener("loadedmetadata",s),window.clearTimeout(f)}},[D,pe,k,R,d,A,_.state.subtitleFontSize,_.state.subtitlePosition]),y(()=>{if(!A)return;const e=d.current,n=Wt.current;if(!e||!n)return;const s=Te/1e3,i=E/1e3,f=new Set;let G=[],b=-1,p=-1,re=-1,ve=-1,F=0,I=0,C=!1;const Y=()=>{const W=Tt.current;if(W<0)return null;const Oe=le.current;return Oe.length>0?Oe[W]?.track??null:Array.from(e.textTracks)[W]??null},J=(W,Oe)=>{const ue=W.cues;if(!ue||ue.length===0)return Array.from(W.activeCues??[]);let et=0,tt=ue.length;for(;et<tt;){const xe=et+tt>>>1;ue[xe].endTime+s<Oe?et=xe+1:tt=xe}const Lt=[];for(let xe=et;xe<ue.length;xe++){const ln=ue[xe];if(ln.startTime+s>Oe)break;ln.endTime+s>=Oe&&Lt.push(ln)}return Lt},z=()=>{const W=Y(),Oe=e.currentTime-i,ue=W?J(W,Oe):[],et=e.clientWidth,tt=e.clientHeight,Lt=e.videoWidth,xe=e.videoHeight;if(ue.length===G.length&&ue.every((In,Bn)=>In===G[Bn])&&et===b&&tt===p&&Lt===re&&xe===ve||(G=ue,b=et,p=tt,re=Lt,ve=xe,n.textContent="",ue.length===0))return;const ir={fontSize:Rn(_.state.subtitleFontSize,tt),position:_.state.subtitlePosition,bgOpacity:_.state.subtitleBgOpacity,bgColor:_.state.subtitleBgColor,textColor:_.state.subtitleTextColor,edge:_.state.subtitleEdge,bold:_.state.subtitleBold},Dr=ss(ir),Or=as(e,ir.position);ue.forEach((In,Bn)=>{const lr=String(In.text??"");if(!os(lr).trim())return;const Mn=document.createElement("div"),Vr=(ue.length-1-Bn)*1.7;Mn.style.cssText=`${Dr}
4
+ bottom: calc(${Or}px + ${Vr}em);`,Mn.innerHTML=is(lr),n.appendChild(Mn)})},Ze=()=>{Array.from(e.textTracks).forEach(W=>{f.has(W)||(f.add(W),W.addEventListener("cuechange",z))})},de=()=>{Ze(),z()},xn=()=>{if(C||I)return;const W=()=>{I=0,!(C||e.paused||e.ended)&&(z(),xn())};I=window.requestAnimationFrame(W)},De=e,on=()=>{F=0,z(),!C&&De.requestVideoFrameCallback&&(F=De.requestVideoFrameCallback(on))},Pt=()=>{z(),De.requestVideoFrameCallback?F||(F=De.requestVideoFrameCallback(on)):xn()};Ze(),e.textTracks.addEventListener("addtrack",de),e.textTracks.addEventListener("removetrack",de),e.addEventListener("timeupdate",z),e.addEventListener("seeked",z),e.addEventListener("loadedmetadata",z),e.addEventListener("play",Pt);const ar=Array.from(e.querySelectorAll("track"));ar.forEach(W=>W.addEventListener("load",z));const or=typeof ResizeObserver>"u"?null:new ResizeObserver(()=>z());return or?.observe(e),z(),Pt(),()=>{C=!0,f.forEach(W=>W.removeEventListener("cuechange",z)),e.textTracks.removeEventListener("addtrack",de),e.textTracks.removeEventListener("removetrack",de),e.removeEventListener("timeupdate",z),e.removeEventListener("seeked",z),e.removeEventListener("loadedmetadata",z),e.removeEventListener("play",Pt),ar.forEach(W=>W.removeEventListener("load",z)),or?.disconnect(),I&&window.cancelAnimationFrame(I),F&&De.cancelVideoFrameCallback&&De.cancelVideoFrameCallback(F),n.textContent=""}},[A,Te,D,pe,E,d,_.state.subtitleFontSize,_.state.subtitlePosition,_.state.subtitleBgOpacity,_.state.subtitleBgColor,_.state.subtitleTextColor,_.state.subtitleEdge,_.state.subtitleBold]);const sn=()=>{B(null),qe([]),We(""),U(-1)},Lr=S(e=>{H(e),ye(1),we(e,1)},[we]),an=!m&&r?.seasons&&r.seasons.length>1?t("label",{className:h.sidebarSeason,children:[t("span",{children:"Season"}),t("select",{value:l,onChange:e=>Lr(parseInt(e.target.value,10)||1),className:h.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,bt=S(e=>{const n=parseInt(e,10);if(!isNaN(n)){try{d.current?.pause()}catch{}ye(n),we(l,n)}Cn(!1)},[l,we,d]);y(()=>{if(m)return;const e=n=>{n.target.closest('input, textarea, button, select, a, [role="button"], [contenteditable="true"]')||n.key.toLowerCase()==="n"&&(N!=null?bt(String(N)):Ur.error("No next episode available"))};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}},[m,N,bt]);const $r=e=>{ze(e);try{const s=rt[e];s&&localStorage.setItem("tvLastAudio",Ln(s))}catch{}const n=ie.current;n&&n.audioTrack!==void 0&&(n.audioTrack=e)},Rr=e=>{Ie(e);try{if(e===-1)localStorage.setItem("tvSubtitlesEnabled","false");else{localStorage.setItem("tvSubtitlesEnabled","true"),localStorage.setItem("tvSelectedSubtitle",String(e));const f=pe[e];f&&localStorage.setItem("tvLastSubtitle",Ln(f))}}catch{}const n=d.current,s=ie.current;if(s&&typeof s.subtitleTrack=="number"&&Array.isArray(s.subtitleTracks)&&s.subtitleTracks.length>0&&(s.subtitleTrack=le.current.length>0||e<0?-1:e),!n)return;const i=le.current;if(i.length>0){i.forEach((f,G)=>{const b=f.track;if(!b)return;const p=G===e;b.mode=p&&!A?"showing":"hidden"});return}Array.from(n.textTracks).forEach((f,G)=>{const b=G===e;f.mode=b&&!A?"showing":"hidden"})},At=S(()=>{if(!r)return;const e=d.current,n=m?"":`S${String(l).padStart(2,"0")}E${String(g).padStart(2,"0")}`;fetch("/api/discord/tv",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:r.title,episodeLabel:n,isPlaying:e?!e.paused&&!e.ended:!0,thumbnail:r.poster,currentTime:e?e.currentTime:0,duration:e&&e.duration||0,isAdult:r.adult===!0,sessionId:mt.current})}).catch(()=>{}),fetch("/api/discord/heartbeat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:mt.current})}).catch(()=>{})},[r,m,l,g,d]);y(()=>{if(!r)return;At();const e=window.setInterval(()=>{const n=d.current;(!n||!n.paused)&&At()},15e3);return()=>window.clearInterval(e)},[At,r,d]),y(()=>{if(!r||k||P||he||ae.length===0)return;const e=d.current;if(!e)return;const n=()=>At();return e.addEventListener("play",n),e.addEventListener("pause",n),e.addEventListener("seeked",n),()=>{e.removeEventListener("play",n),e.removeEventListener("pause",n),e.removeEventListener("seeked",n)}},[r,k,P,he,ae,At,d]),y(()=>{const e=mt.current,n=()=>{const i=JSON.stringify({sessionId:e});navigator.sendBeacon?(navigator.sendBeacon("/api/discord/clear",new Blob([i],{type:"application/json"})),navigator.sendBeacon("/api/discord/heartbeat",new Blob([JSON.stringify({sessionId:e,bye:!0})],{type:"application/json"}))):fetch("/api/discord/clear",{method:"POST",headers:{"Content-Type":"application/json"},body:i,keepalive:!0}).catch(()=>{})},s=()=>n();return window.addEventListener("pagehide",s),window.addEventListener("beforeunload",s),()=>{window.removeEventListener("pagehide",s),window.removeEventListener("beforeunload",s),n()}},[]);const sr=Ae==="all"?ae:ae.filter(e=>e.type===Ae);return y(()=>{if(!r){document.title="TV & Movies - dango";return}document.title=m?`${r.title} - dango`:`${r.title} - Season ${l} Episode ${g} - dango`},[r,m,l,g]),y(()=>{if(!r||m)return;const e=new URLSearchParams(w),n=e.get("s"),s=e.get("e"),i=String(l),f=String(g);n===i&&s===f||(e.set("type",w.get("type")||"tv"),e.set("s",i),e.set("e",f),U(`${window.location.pathname}?${e.toString()}`,{replace:!0}))},[r,m,l,g,w,U]),t("div",{className:nt.playerPageLayout,children:[t("aside",{className:nt.episodeSidebar,children:r?m?t("div",{className:h.sidebarPosterCard,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:h.sidebarPosterMeta,children:[t("strong",{children:r.title}),t("span",{children:r.year})]})]}):t(ls,{episodes:nr,currentEpisode:String(g),watchedEpisodes:tr,onEpisodeClick:bt,header:an}):m?t("div",{className:h.statusMsg,children:[t($,{name:"spinner",className:h.spinner})," Loading..."]}):t(cs,{variant:"sidebar"})}),t("div",{className:nt.playerMain,children:[r&&t("div",{className:h.playerSection,onContextMenu:e=>e.preventDefault(),style:r.adult&&!je?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:[P&&!k&&t("div",{className:h.statusMsg,children:[t($,{name:"spinner",className:h.spinner})," Loading stream..."]}),k&&_t?t("iframe",{src:_t,className:h.videoIframe,allow:"autoplay; fullscreen",allowFullScreen:!0}):!k&&(sr.length>0||P)?t(Ve,{children:[he&&t("div",{className:`${h.statusMsg} ${h.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:he}),t("button",{className:h.retryButton,onClick:rn,children:"Retry"})]}),X.length>0&&t("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center",marginTop:4},children:[t("span",{style:{fontSize:"0.8rem",opacity:.9,fontWeight:600},children:"Servers:"}),X.map(e=>t("button",{onClick:()=>wn(e),className:h.retryButton,style:{padding:"4px 8px",fontSize:"0.75rem",textTransform:"capitalize",background:ee===e?"var(--accent)":void 0,color:ee===e?"white":void 0},children:e},e))]})]}),t(ca,{player:_,title:r.title,episodeLabel:m?void 0:`S${l} E${g}`,audioTracks:rt,selectedAudioTrack:Ce,onAudioTrackChange:$r,subtitles:pe,selectedSubtitle:D,onSubtitleChange:Rr,streams:sr,qualityIdx:fe,onQualityChange:at,onBack:sn,movyServers:X,selectedMovyServer:ee,onMovyServerSelect:wn,isMovySource:X.length>0,videoDelayEnabled:He,onVideoDelayToggle:e=>{it(e);try{localStorage.setItem("playerVideoDelayEnabled",String(e))}catch{}},videoDelayMs:Ue,onVideoDelayChange:Et,onCalibrateAvSync:dt,subtitleDelayMs:Te,onSubtitleDelayChange:Nt,showNextEpisodeButton:fr&&!Ne&&!ke&&!$e,onNextEpisode:Jn,children:[t("video",{ref:d,autoPlay:Ge&&!Bt,playsInline:!0,disablePictureInPicture:!0,className:`${h.video} ${Q?h.videoHidden:""}`,onTimeUpdate:kr,onEnded:()=>{o||Er()},onPlay:Nr,onPause:wr,onSeeked:()=>{Yn.current=Date.now(),Mt()},onLoadedMetadata:xr,onVolumeChange:_.actions.onVolumeChange,onContextMenu:e=>e.preventDefault(),onError:()=>{K("Video failed to load. Try another server or reload."),j(!1)}}),t("canvas",{ref:zt,className:`${h.delayCanvas} ${Q?h.delayCanvasActive:""}`}),A&&t("div",{ref:Wt,className:h.subtitleOverlay}),t(ds,{isOpen:gn,ms:Ue,onChange:Et,onApply:jt,onClose:Ht,testClipActive:o,onTestClip:Kt})]})]}):he&&!k?t("div",{className:`${h.statusMsg} ${h.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:he}),t("button",{className:h.retryButton,onClick:rn,children:"Retry"})]}),X.length>0&&t("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center",marginTop:4},children:[t("span",{style:{fontSize:"0.8rem",opacity:.9,fontWeight:600},children:"Servers:"}),X.map(e=>t("button",{onClick:()=>wn(e),className:h.retryButton,style:{padding:"4px 8px",fontSize:"0.75rem",textTransform:"capitalize",background:ee===e?"var(--accent)":void 0,color:ee===e?"white":void 0},children:e},e))]})]}):null]}),r&&t(us,{showTheater:!1}),an&&t("div",{className:h.mobileSeasonRow,children:an}),r&&t("div",{className:h.providerSelectWrap,children:t("label",{className:h.controlLabel,children:["Source",t("select",{value:R,onChange:e=>Pr(e.target.value),className:h.select,disabled:oe.length===0,children:mn?t("option",{value:"",children:"Loading…"}):oe.length===0?t("option",{value:"",children:"No providers available"}):t(Ve,{children:[M.length>0&&t("optgroup",{label:"Direct HLS",children:M.map(e=>t("option",{value:e.id,children:e.label},e.id))}),Vt.length>0&&t("optgroup",{label:"Embeds",children:Vt.map(e=>t("option",{value:e.id,children:e.label},e.id))})]})})]})}),r&&t("div",{className:nt.playerInfoContainer,children:[t("div",{className:nt.playerInfoHeader,children:[t("div",{className:nt.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:nt.videoTitleSection,children:[t("div",{className:be.titleContainer,children:[t("h1",{children:r.title}),t("div",{className:h.meta,children:[t("span",{className:h.year,children:r.year}),r.vote_average!=null&&r.vote_average>0&&t("span",{className:h.rating,children:[t($,{name:"star",size:12}),Number(r.vote_average).toFixed(1)]}),t("span",{className:`${h.typeBadge} ${h[m?"movie":"tv"]}`,children:m?"Movie":"TV Show"})]}),rr.length>0&&t("div",{className:h.genreRow,children:rr.map(e=>t("span",{className:h.genreChip,children:e},e))}),Nn.length>0&&t("div",{className:h.metaRow,children:Nn.map((e,n)=>t("span",{children:[e,n<Nn.length-1?" · ":""]},`${e}-${n}`))})]}),t("div",{className:be.controls,children:[t("button",{className:`${be.watchlistBtn} ${Gt?be.inList:""}`,onClick:pr,disabled:hr,type:"button",children:[Gt?t($,{name:"check",size:14}):t($,{name:"plus",size:14}),Gt?"In Watchlist":"Add to Watchlist"]}),!m&&t(Ve,{children:[t("button",{className:`${be.watchlistBtn}`,onClick:()=>bn!=null&&bt(String(bn)),disabled:bn==null,type:"button",children:[t($,{name:"chevron-left",size:14}),"Prev EP"]}),t("button",{className:`${be.watchlistBtn}`,onClick:()=>N!=null&&bt(String(N)),disabled:N==null,type:"button",children:["Next EP",t($,{name:"chevron-right",size:14})]}),!m&&t("button",{className:`${be.watchlistBtn} ${be.modeToggleBtn} ${pt?be.modeToggleActive:""}`,onClick:()=>_r(!pt),type:"button","aria-pressed":pt,children:pt?"AUTOPLAY: ON":"AUTOPLAY: OFF"}),yr&&t("button",{className:`${be.watchlistBtn}`,onClick:()=>Cn(!0),type:"button",children:[t($,{name:"list-ul",size:14}),"Episodes"]})]})]})]})]}),t("div",{className:be.descriptionSection,children:[t("h3",{children:"Synopsis"}),t(xs,{text:r.overview,emptyText:"No description available."})]}),t("button",{className:be.detailsToggleBtn,onClick:()=>vr(!en),type:"button",children:[en?t($,{name:"chevron-up"}):t($,{name:"chevron-down"}),en?"Hide Details":"Show Details"]}),en&&t("div",{className:h.detailGrid,children:[r.first_air_date&&t("div",{className:h.detailItem,children:[t("strong",{children:m?"Release Date":"First Air Date"}),t("span",{children:r.first_air_date})]}),r.last_air_date&&t("div",{className:h.detailItem,children:[t("strong",{children:"Last Air Date"}),t("span",{children:r.last_air_date})]}),r.networks&&r.networks.length>0&&t("div",{className:h.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:h.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:h.detailItem,children:[t("strong",{children:"Episode Runtime"}),t("span",{children:[r.episode_run_time[0]," min"]})]}),r.imdb_id&&t("div",{className:h.detailItem,children:[t("strong",{children:"IMDb"}),t("a",{href:`https://www.imdb.com/title/${r.imdb_id}`,target:"_blank",rel:"noopener noreferrer",className:h.imdbLink,children:"View on IMDb"})]})]})]}),!m&&t(ms,{isOpen:br,onClose:()=>Cn(!1),episodes:nr,currentEpisode:String(g),watchedEpisodes:tr,onEpisodeClick:bt,header:an}),r?.adult&&!je&&t(cn,{isOpen:!0,title:"Content Warning",onClose:sn,children:t("div",{style:{padding:"1rem",textAlign:"center"},children:[t("p",{children:"This title contains mature content intended for adult audiences."}),t("p",{children:["By proceeding, you confirm that you are ",t("strong",{children:"18 years of age or older"})," ","(or the age of majority in your jurisdiction) and wish to view this content."]}),t("div",{style:{marginTop:"1rem",display:"flex",gap:"10px",justifyContent:"center"},children:[t(_e,{variant:"secondary",onClick:sn,children:"Go Back"}),t(_e,{onClick:Le,children:"I'm 18+, Continue"})]})]})}),t(cn,{isOpen:Ne,onClose:Gn,title:"Resume Watching",children:t("div",{style:{padding:"1rem",textAlign:"center"},children:[t("p",{children:["You were at ",t("strong",{children:Tr(ht)})]}),t("div",{style:{marginTop:"1rem",display:"flex",gap:"10px",justifyContent:"center"},children:[t(_e,{variant:"secondary",onClick:Gn,children:"Start from Beginning"}),t(_e,{onClick:Ir,children:"Resume"})]})]})}),t(cn,{isOpen:ke,onClose:Br,title:m?"Movie Completed":"Episode Completed",children:t("div",{style:{padding:"1rem",textAlign:"center"},children:[t("p",{children:m?t(Ve,{children:"You've already watched this movie."}):t(Ve,{children:["You've already watched"," ",t("strong",{children:["Season ",l," Episode ",g]}),". Would you like to continue?"]})}),t("div",{style:{marginTop:"1rem",display:"flex",gap:"10px",justifyContent:"center",flexWrap:"wrap"},children:[t(_e,{variant:"secondary",onClick:Mr,children:"Replay"}),N!=null?t(_e,{onClick:Jn,children:["Watch EP ",N]}):ge!=null?t(_e,{onClick:Xn,children:["Start Season ",ge]}):null]})]})}),t(cn,{isOpen:$e,onClose:()=>Je(!1),title:m?"Movie Completed!":ge!=null?"Season Complete!":"Show Completed!",children:t("div",{style:{padding:"1rem",textAlign:"center"},children:[t($,{name:"check-circle",size:48,style:{color:"var(--accent-lighter)",marginBottom:"0.5rem"}}),t("p",{style:{fontSize:"1.1rem",fontWeight:600},children:gr}),t("p",{style:{color:"var(--text-secondary)"},children:m?"You finished this movie!":ge!=null?`You finished Season ${l}.`:"Congratulations! You finished all available episodes."}),t("div",{style:{marginTop:"1rem",display:"flex",gap:"10px",justifyContent:"center",flexWrap:"wrap"},children:[t(_e,{variant:"secondary",onClick:()=>Je(!1),children:"Close"}),ge!=null?t(_e,{onClick:Xn,children:["Start Season ",ge]}):t(Ve,{children:[t(_e,{onClick:()=>{Je(!1),sn()},children:"Back to Details"}),Gt&&t(_e,{onClick:Ar,disabled:Qt.isPending,children:Qt.isPending?"Saving...":"Move to Completed"})]})]})]})}),!r&&t("div",{className:h.statusMsg,children:[t($,{name:"spinner",className:h.spinner})," Loading..."]})]})]})};export{Eo as default};
@@ -1 +1 @@
1
- import{n as z,a as E,o as R,d as l,h as C,T,u as e,g as F}from"./vendor-core-8R2fFbyN.js";import{I as a}from"./vendor-icons-CDMuNDeL.js";import{B as w}from"./index-IZgh1beL.js";import{u as q}from"./useMatureConsent-CT7-KfzG.js";import{n as j,d as U,e as H,f as J,t as I}from"./useTvLibrary-Cwxgy_Bg.js";import"./vendor-query-BXRECSI6.js";const K="_container_198yg_1",Q="_heroSection_198yg_11",X="_bannerContainer_198yg_17",Y="_banner_198yg_17",Z="_bannerOverlay_198yg_37",ee="_heroContent_198yg_49",ne="_posterContainer_198yg_62",te="_poster_198yg_62",se="_infoGlass_198yg_86",ae="_title_198yg_100",oe="_quickMeta_198yg_110",ie="_metaItem_198yg_118",re="_iconStar_198yg_126",le="_iconTv_198yg_130",ce="_iconType_198yg_134",de="_genres_198yg_139",me="_genre_198yg_139",_e="_metaRow_198yg_156",he="_metaValue_198yg_164",ge="_metaDivider_198yg_168",ve="_synopsisSection_198yg_173",pe="_sectionTitleSmall_198yg_179",ye="_synopsis_198yg_173",ue="_actions_198yg_196",ke="_watchBtn_198yg_202",Ne="_watchlistBtn_198yg_226",be="_active_198yg_250",Se="_seasonPickerLabel_198yg_256",fe="_seasonSelect_198yg_267",Ce="_detailsToggleBtn_198yg_286",Te="_expandedContent_198yg_304",we="_detailGrid_198yg_309",Ie="_detailItem_198yg_315",Be="_imdbLink_198yg_333",De="_heroSkeleton_198yg_343",Me="_skeletonBanner_198yg_347",Le="_skeletonContent_198yg_354",$e="_skeletonPoster_198yg_365",Pe="_skeletonInfo_198yg_373",Ge="_skeletonTitle_198yg_380",xe="_skeletonMeta_198yg_388",Oe="_skeletonDesc_198yg_396",Ae="_skeletonActions_198yg_404",Ve="_errorState_198yg_413",We="_matureOverlay_198yg_434",ze="_matureContent_198yg_444",n={container:K,heroSection:Q,bannerContainer:X,banner:Y,bannerOverlay:Z,heroContent:ee,posterContainer:ne,poster:te,infoGlass:se,title:ae,quickMeta:oe,metaItem:ie,iconStar:re,iconTv:le,iconType:ce,genres:de,genre:me,metaRow:_e,metaValue:he,metaDivider:ge,synopsisSection:ve,sectionTitleSmall:pe,synopsis:ye,actions:ue,watchBtn:ke,watchlistBtn:Ne,active:be,seasonPickerLabel:Se,seasonSelect:fe,detailsToggleBtn:Ce,expandedContent:Te,detailGrid:we,detailItem:Ie,imdbLink:Be,heroSkeleton:De,skeletonBanner:Me,skeletonContent:Le,skeletonPoster:$e,skeletonInfo:Pe,skeletonTitle:Ge,skeletonMeta:xe,skeletonDesc:Oe,skeletonActions:Ae,errorState:Ve,matureOverlay:We,matureContent:ze};function He(){const{id:o}=z(),c=E(),[B]=R(),i=j(B.get("type")),{hasConsent:D}=q(),[t,M]=l(null),[L,m]=l(!0),[p,y]=l(""),[d,$]=l(!1),[_,P]=l(1),G=U(i,o),x=Number(o),{data:O}=H(t?G:void 0),h=!!O?.inLibrary,{toggle:A}=J();C(()=>{o&&(m(!0),y(""),fetch(`/api/tv/details/${i}/${o}`).then(s=>{if(!s.ok)throw new Error("Failed to load details");return s.json()}).then(s=>{M(s),m(!1)}).catch(s=>{y(s.message),m(!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,_,1))},W=()=>{t&&A({tmdbId:x,mediaType:i,title:t.title,poster:t.poster,year:t.year,adult:t.adult})},r=i==="movie",g=!r,u=t?.backdrop?`https://image.tmdb.org/t/p/w1280${t.backdrop}`:"",k=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]),b=T(()=>t?.seasons?t.seasons.filter(s=>s.season_number>0):[],[t?.seasons]),v=[t?.year,t?.status,g&&t?.number_of_seasons?`${t.number_of_seasons} Season${t.number_of_seasons>1?"s":""}`:null,g&&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(p||!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:p||"Something went wrong"}),e(w,{onClick:()=>c(-1),children:"Go Back"})]})});const S=t.adult&&!D;return e("div",{className:n.container,style:S?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:[e("div",{className:n.heroSection,children:[e("div",{className:n.bannerContainer,children:[u&&e("div",{className:n.banner,style:{backgroundImage:`url(${u})`}}),e("div",{className:n.bannerOverlay})]}),e("div",{className:n.heroContent,children:[e("div",{className:n.posterContainer,children:k&&e("img",{src:k,alt:t.title,className:n.poster,decoding:"async"})}),e("div",{className:n.infoGlass,children:[e("div",{className:n.topInfo,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))})]}),v.length>0&&e("div",{className:n.metaRow,children:v.map((s,f)=>e(F.Fragment,{children:[e("span",{className:n.metaValue,children:s}),f<v.length-1&&e("span",{className:n.metaDivider,children:"·"})]},f))}),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${_}`]}),e("button",{className:`${n.watchlistBtn} ${h?n.active:""}`,onClick:W,children:[h?e(a,{name:"check",size:14}):e(a,{name:"plus",size:14}),h?"In Watchlist":"Add to Watchlist"]})]}),g&&b.length>1&&e("label",{className:n.seasonPickerLabel,children:[e("span",{children:"Season"}),e("select",{value:_,onChange:s=>P(parseInt(s.target.value,10)||1),className:n.seasonSelect,children:b.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:()=>$(!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"})]})]})})]})]})]}),S&&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{He as default};
1
+ import{n as z,a as E,o as R,d as l,h as C,T,u as e,g as F}from"./vendor-core-8R2fFbyN.js";import{I as a}from"./vendor-icons-CDMuNDeL.js";import{B as w}from"./index-lo-bz7f2.js";import{u as q}from"./useMatureConsent-CT7-KfzG.js";import{n as j,d as U,e as H,f as J,t as I}from"./useTvLibrary-BHeWSd1F.js";import"./vendor-query-BXRECSI6.js";const K="_container_198yg_1",Q="_heroSection_198yg_11",X="_bannerContainer_198yg_17",Y="_banner_198yg_17",Z="_bannerOverlay_198yg_37",ee="_heroContent_198yg_49",ne="_posterContainer_198yg_62",te="_poster_198yg_62",se="_infoGlass_198yg_86",ae="_title_198yg_100",oe="_quickMeta_198yg_110",ie="_metaItem_198yg_118",re="_iconStar_198yg_126",le="_iconTv_198yg_130",ce="_iconType_198yg_134",de="_genres_198yg_139",me="_genre_198yg_139",_e="_metaRow_198yg_156",he="_metaValue_198yg_164",ge="_metaDivider_198yg_168",ve="_synopsisSection_198yg_173",pe="_sectionTitleSmall_198yg_179",ye="_synopsis_198yg_173",ue="_actions_198yg_196",ke="_watchBtn_198yg_202",Ne="_watchlistBtn_198yg_226",be="_active_198yg_250",Se="_seasonPickerLabel_198yg_256",fe="_seasonSelect_198yg_267",Ce="_detailsToggleBtn_198yg_286",Te="_expandedContent_198yg_304",we="_detailGrid_198yg_309",Ie="_detailItem_198yg_315",Be="_imdbLink_198yg_333",De="_heroSkeleton_198yg_343",Me="_skeletonBanner_198yg_347",Le="_skeletonContent_198yg_354",$e="_skeletonPoster_198yg_365",Pe="_skeletonInfo_198yg_373",Ge="_skeletonTitle_198yg_380",xe="_skeletonMeta_198yg_388",Oe="_skeletonDesc_198yg_396",Ae="_skeletonActions_198yg_404",Ve="_errorState_198yg_413",We="_matureOverlay_198yg_434",ze="_matureContent_198yg_444",n={container:K,heroSection:Q,bannerContainer:X,banner:Y,bannerOverlay:Z,heroContent:ee,posterContainer:ne,poster:te,infoGlass:se,title:ae,quickMeta:oe,metaItem:ie,iconStar:re,iconTv:le,iconType:ce,genres:de,genre:me,metaRow:_e,metaValue:he,metaDivider:ge,synopsisSection:ve,sectionTitleSmall:pe,synopsis:ye,actions:ue,watchBtn:ke,watchlistBtn:Ne,active:be,seasonPickerLabel:Se,seasonSelect:fe,detailsToggleBtn:Ce,expandedContent:Te,detailGrid:we,detailItem:Ie,imdbLink:Be,heroSkeleton:De,skeletonBanner:Me,skeletonContent:Le,skeletonPoster:$e,skeletonInfo:Pe,skeletonTitle:Ge,skeletonMeta:xe,skeletonDesc:Oe,skeletonActions:Ae,errorState:Ve,matureOverlay:We,matureContent:ze};function He(){const{id:o}=z(),c=E(),[B]=R(),i=j(B.get("type")),{hasConsent:D}=q(),[t,M]=l(null),[L,m]=l(!0),[p,y]=l(""),[d,$]=l(!1),[_,P]=l(1),G=U(i,o),x=Number(o),{data:O}=H(t?G:void 0),h=!!O?.inLibrary,{toggle:A}=J();C(()=>{o&&(m(!0),y(""),fetch(`/api/tv/details/${i}/${o}`).then(s=>{if(!s.ok)throw new Error("Failed to load details");return s.json()}).then(s=>{M(s),m(!1)}).catch(s=>{y(s.message),m(!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,_,1))},W=()=>{t&&A({tmdbId:x,mediaType:i,title:t.title,poster:t.poster,year:t.year,adult:t.adult})},r=i==="movie",g=!r,u=t?.backdrop?`https://image.tmdb.org/t/p/w1280${t.backdrop}`:"",k=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]),b=T(()=>t?.seasons?t.seasons.filter(s=>s.season_number>0):[],[t?.seasons]),v=[t?.year,t?.status,g&&t?.number_of_seasons?`${t.number_of_seasons} Season${t.number_of_seasons>1?"s":""}`:null,g&&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(p||!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:p||"Something went wrong"}),e(w,{onClick:()=>c(-1),children:"Go Back"})]})});const S=t.adult&&!D;return e("div",{className:n.container,style:S?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:[e("div",{className:n.heroSection,children:[e("div",{className:n.bannerContainer,children:[u&&e("div",{className:n.banner,style:{backgroundImage:`url(${u})`}}),e("div",{className:n.bannerOverlay})]}),e("div",{className:n.heroContent,children:[e("div",{className:n.posterContainer,children:k&&e("img",{src:k,alt:t.title,className:n.poster,decoding:"async"})}),e("div",{className:n.infoGlass,children:[e("div",{className:n.topInfo,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))})]}),v.length>0&&e("div",{className:n.metaRow,children:v.map((s,f)=>e(F.Fragment,{children:[e("span",{className:n.metaValue,children:s}),f<v.length-1&&e("span",{className:n.metaDivider,children:"·"})]},f))}),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${_}`]}),e("button",{className:`${n.watchlistBtn} ${h?n.active:""}`,onClick:W,children:[h?e(a,{name:"check",size:14}):e(a,{name:"plus",size:14}),h?"In Watchlist":"Add to Watchlist"]})]}),g&&b.length>1&&e("label",{className:n.seasonPickerLabel,children:[e("span",{children:"Season"}),e("select",{value:_,onChange:s=>P(parseInt(s.target.value,10)||1),className:n.seasonSelect,children:b.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:()=>$(!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"})]})]})})]})]})]}),S&&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{He as default};