@serifpersia/dango 3.5.9 → 3.6.1

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 (74) hide show
  1. package/README.md +44 -4
  2. package/client/dist/assets/{AnimeCard-CDeVbWJO.js → AnimeCard-DbrG4Bo-.js} +1 -1
  3. package/client/dist/assets/AnimeInfo-BivVqWcB.css +1 -0
  4. package/client/dist/assets/AnimeInfo-CgSQGjef.js +1 -0
  5. package/client/dist/assets/{AnimeInfoPage-Cc3OcfHY.js → AnimeInfoPage-DSybdvf_.js} +2 -2
  6. package/client/dist/assets/{Asmr-DZmR_EHb.js → Asmr-DFFV-7y4.js} +1 -1
  7. package/client/dist/assets/{AsmrResetProgressModal-DBCDlfYq.js → AsmrResetProgressModal-Brdfu_22.js} +1 -1
  8. package/client/dist/assets/AvSyncCalibrator-DBBUzoHn.js +10 -0
  9. package/client/dist/assets/AvSyncCalibrator-ZSpMgUid.css +1 -0
  10. package/client/dist/assets/Home-DeY8zvfI.css +1 -0
  11. package/client/dist/assets/{Home-BqhPqzWF.js → Home-DjGl-3os.js} +1 -1
  12. package/client/dist/assets/{Insights-CmbbDZr3.js → Insights-4O52Z1t2.js} +1 -1
  13. package/client/dist/assets/{LibraryListPage-jLA7gnux.js → LibraryListPage-Z0w_rmHP.js} +1 -1
  14. package/client/dist/assets/{ListeningList-Cm9zGlLB.js → ListeningList-DjbzDs1E.js} +1 -1
  15. package/client/dist/assets/{Manga-x4pVT4ZH.js → Manga-BRIDluzF.js} +1 -1
  16. package/client/dist/assets/{MangaInfoPage-BPSW9UER.js → MangaInfoPage-Q4CjEGJH.js} +1 -1
  17. package/client/dist/assets/{MangaReadPage-V1iDbCfL.js → MangaReadPage-BbJK5FY6.js} +1 -1
  18. package/client/dist/assets/{MangaResetProgressModal-Dto3km2X.js → MangaResetProgressModal-BCFPXDF6.js} +1 -1
  19. package/client/dist/assets/{Mature-B0DoN3tQ.js → Mature-DjQzs66p.js} +1 -1
  20. package/client/dist/assets/{MediaCard-D6_9HL2Z.js → MediaCard-DedwE5DX.js} +1 -1
  21. package/client/dist/assets/{Music-1MlUIfdw.js → Music-z2RkiMDf.js} +1 -1
  22. package/client/dist/assets/{OptionListMenu-BWwktIiH.js → OptionListMenu-CetjZizt.js} +1 -1
  23. package/client/dist/assets/Player-DCB994_8.css +1 -0
  24. package/client/dist/assets/{Player-Dgtn--lM.js → Player-DD-9SgWU.js} +6 -6
  25. package/client/dist/assets/PlayerSettings-BXGe3F5k.css +1 -0
  26. package/client/dist/assets/{PlayerSettings-CI5hGpEU.js → PlayerSettings-ne_DQSTl.js} +1 -1
  27. package/client/dist/assets/{QueueOptionsButton-DjcdOJgg.js → QueueOptionsButton-CIKT4YcD.js} +1 -1
  28. package/client/dist/assets/{QueueRail-B5z_xhzj.js → QueueRail-DPclldS0.js} +1 -1
  29. package/client/dist/assets/{Radio-BAE-Q-iN.js → Radio-aeqPTMht.js} +1 -1
  30. package/client/dist/assets/{ReadingList-B97i_hGv.js → ReadingList-p6G7NHtC.js} +1 -1
  31. package/client/dist/assets/{ResetProgressModal-C7-CvTi-.js → ResetProgressModal-B7UuuL3X.js} +1 -1
  32. package/client/dist/assets/{Search-CbPFjKeU.js → Search-BzyHVByR.js} +1 -1
  33. package/client/dist/assets/Settings-DMmtLUsL.js +21 -0
  34. package/client/dist/assets/{SkeletonGrid-BA_x2PRl.js → SkeletonGrid-B5JXhZO4.js} +1 -1
  35. package/client/dist/assets/Trackers-tLL1afjB.js +2 -0
  36. package/client/dist/assets/Tv-Bdruknna.css +1 -0
  37. package/client/dist/assets/Tv-CluLN4KA.js +4 -0
  38. package/client/dist/assets/{TvInfo-CxSmzVSL.js → TvInfo-DmrBLjgK.js} +1 -1
  39. package/client/dist/assets/{TvPopup-S5blnD3l.js → TvPopup-D1mSlOZt.js} +1 -1
  40. package/client/dist/assets/{TvSearch-B-2sRNbN.js → TvSearch-BGQRUq9E.js} +1 -1
  41. package/client/dist/assets/{TvWatchlist-MaA-qhQw.js → TvWatchlist-DdLkpeQT.js} +1 -1
  42. package/client/dist/assets/{Watchlist-yVEi1oVn.js → Watchlist-BObmM6QB.js} +1 -1
  43. package/client/dist/assets/{hls-CnFtaJwf.js → hls-qCuNYJym.js} +1 -1
  44. package/client/dist/assets/index-B4AdKbhW.js +178 -0
  45. package/client/dist/assets/index-D0Haw_Zl.css +1 -0
  46. package/client/dist/assets/{useAnimeInfoData-BqAd5seW.js → useAnimeInfoData-CSnwUBuU.js} +1 -1
  47. package/client/dist/assets/{useAsmr-B1vlDm2S.js → useAsmr-BKAaWEXn.js} +1 -1
  48. package/client/dist/assets/{useAsmrPopup-BNJC4JQo.js → useAsmrPopup-DDLRBLzz.js} +1 -1
  49. package/client/dist/assets/{useMangaLibrary-CU3bFfuD.js → useMangaLibrary-C6XEMuSr.js} +1 -1
  50. package/client/dist/assets/{useMangaPopup-LbRnTFzq.js → useMangaPopup-wfCJubPD.js} +1 -1
  51. package/client/dist/assets/{useProviders-CvKGEjDV.js → useProviders-C7jrBgxf.js} +1 -1
  52. package/client/dist/assets/{useTv-LsgXHZD4.js → useTv-DM5KtzEc.js} +1 -1
  53. package/client/dist/assets/{useTvLibrary-c90knUfT.js → useTvLibrary-73NkS_5R.js} +1 -1
  54. package/client/dist/index.html +2 -2
  55. package/orchestrator.js +107 -8
  56. package/package.json +2 -2
  57. package/server/dist/app-hono.js +13 -8
  58. package/server/dist/config.js +3 -2
  59. package/server/dist/hono/auth.js +0 -7
  60. package/server/dist/trpc/routers/auth.js +16 -0
  61. package/server/package.json +1 -1
  62. package/client/dist/assets/AnimeInfo-BFWtHlPC.css +0 -1
  63. package/client/dist/assets/AnimeInfo-DVpM_cPF.js +0 -1
  64. package/client/dist/assets/AvSyncCalibrator-Cf5L0Dxf.js +0 -10
  65. package/client/dist/assets/AvSyncCalibrator-ieaRTs3u.css +0 -1
  66. package/client/dist/assets/Home-B_q2l74h.css +0 -1
  67. package/client/dist/assets/Player-DBLl-bj_.css +0 -1
  68. package/client/dist/assets/PlayerSettings-Bj6SsmQ2.css +0 -1
  69. package/client/dist/assets/Settings-BbihEcZ2.js +0 -21
  70. package/client/dist/assets/Trackers-Bperfrcz.js +0 -2
  71. package/client/dist/assets/Tv-BSGuUz2F.js +0 -4
  72. package/client/dist/assets/Tv-BlVIanQL.css +0 -1
  73. package/client/dist/assets/index-Ck-R0JKv.css +0 -1
  74. package/client/dist/assets/index-DNxWyfmM.js +0 -178
@@ -1 +1 @@
1
- import{b as u,c as b,u as g,a as c}from"./vendor-query-BBT5_sHx.js";import{t as p,h as i,z as s}from"./index-DNxWyfmM.js";import{T as Q}from"./vendor-core-DfaOB3Rn.js";const v=300*1e3,M={mangadex:"https://mangadex.org/",mangapill:"https://www.mangapill.com/"},f=(e,a)=>`/api/proxy?url=${encodeURIComponent(a)}&referer=${encodeURIComponent(M[e])}`,T=(e,a)=>a&&(e==="mangapill"?f(e,a):a),k=(e,a=!0)=>{const{provider:r,query:n,page:o,sort:t,status:m,type:d,rating:y,mature:l}=e;return u({queryKey:["mangaBrowse",r,n,o,t,m,d,y,l],queryFn:()=>p.manga.search.query({provider:r,q:n.trim()||void 0,page:o,sort:t||void 0,status:m||void 0,type:d||void 0,rating:y||void 0,mature:l?"1":void 0}),staleTime:v,enabled:a&&!!r})},E=(e,a=14)=>{const{provider:r,query:n,sort:o,status:t,type:m,rating:d,mature:y}=e;return b({queryKey:["mangaBrowseInfinite",r,n,o,t,m,d,y,a],queryFn:({pageParam:l=1})=>p.manga.search.query({provider:r,q:n.trim()||void 0,page:l,limit:a,sort:o||void 0,status:t||void 0,type:m||void 0,rating:d||void 0,mature:y?"1":void 0}),initialPageParam:1,getNextPageParam:(l,q)=>l.hasNext?q.length+1:void 0,staleTime:v,enabled:!!r})},O=(e,a,r="safe",n=!1)=>u({queryKey:["mangaDetail",e,a,r,n],queryFn:()=>p.manga.info.query({provider:e||"",id:a||"",rating:r,mature:n?"1":void 0}),enabled:!!e&&!!a,staleTime:v}),$=(e,a,r)=>u({queryKey:["mangaPages",e,a],queryFn:()=>p.manga.pages.query({provider:e||"",id:a||""}),enabled:!!e&&!!a,staleTime:1800*1e3}),B=()=>{const e=i();return u({...e.manga.trending.queryOptions(),staleTime:600*1e3,retry:1})},I=e=>e.contentRating==="erotica"||e.contentRating==="pornographic"||e.type==="doujinshi";function N(e,a){const r=e.titles??{};return a==="englishName"?r.en||e.title:a==="nativeName"&&(r.native||r.romaji||e.altTitle)||e.title}function A(e){return{englishName:e.titles?.en??e.title,nativeName:e.titles?.native??e.titles?.romaji??e.altTitle??void 0}}const h=/^anilist:ch:(\d+)$/;function w(e){if(!e)return null;const a=h.exec(e.trim());if(!a)return null;const r=Number.parseInt(a[1],10);return Number.isFinite(r)?r:null}function x(e,a){const r=String(a),n=e.find(o=>(o.number??"").trim()===r);return n||(e.find(o=>{const t=Number.parseFloat((o.number??"").trim());return Number.isFinite(t)&&t===a})??null)}const _=["Reading","Completed","On-Hold","Dropped","Planned"],L=(e,a)=>`${e.toLowerCase()}:${a}`,D=(e="All",a=1,r=24)=>{const n=i();return u(n.mangaLibrary.list.queryOptions({status:e,page:a,limit:r}))},P=()=>{const e=i();return u({...e.mangaLibrary.ids.queryOptions(),staleTime:1e3*60})},U=e=>{const a=i();return u({...a.mangaLibrary.check.queryOptions({id:e??""}),enabled:!!e,staleTime:1e3*60})},j=e=>{const a=i();return u({...a.mangaLibrary.entry.queryOptions({id:e??""}),enabled:!!e,staleTime:1e3*60})},H=()=>{const e=i(),a=g();return c(e.mangaLibrary.link.mutationOptions({onSuccess:r=>{s.success(r?.progressMigrated?"Linked — chapter progress carried over":"Linked to AniList entry"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to link: ${r.message}`)}}))},z=(e=24)=>{const a=i();return u(a.mangaProgress.continueReading.queryOptions({limit:e}))},V=e=>{const a=i();return u({...a.mangaProgress.byManga.queryOptions({mangaId:e??""}),enabled:!!e})},S=()=>{const e=i(),a=g();return c(e.mangaLibrary.add.mutationOptions({onSuccess:(r,n)=>{n.silent||s.success("Bookmarked"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]})},onError:r=>{s.error(`Failed to bookmark: ${r.message}`)}}))},F=()=>{const e=i(),a=g();return c(e.mangaLibrary.remove.mutationOptions({onSuccess:()=>{s.success("Bookmark removed"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to remove: ${r.message}`)}}))},Y=()=>{const e=i(),a=g();return c(e.mangaLibrary.setStatus.mutationOptions({onSuccess:()=>{s.success("Status updated"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to update status: ${r.message}`)}}))},G=()=>{const e=i(),a=g();return c(e.mangaProgress.save.mutationOptions({onSuccess:(r,n)=>{a.invalidateQueries({queryKey:["manga-progress",n.mangaId]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())}}))},J=()=>{const e=i(),a=g();return c(e.mangaProgress.remove.mutationOptions({onSuccess:()=>{s.success("Progress reset"),a.invalidateQueries({queryKey:["manga-progress"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())},onError:r=>{s.error(`Failed to reset progress: ${r.message}`)}}))},W=()=>{const e=i(),a=g();return c(e.mangaLibrary.batchStatus.mutationOptions({onSuccess:r=>{s.success(`Status updated for ${r.updated??0} items`),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to update statuses: ${r.message}`)}}))},X=()=>{const e=i(),a=g();return c(e.mangaLibrary.removeMany.mutationOptions({onSuccess:r=>{const n=r.removed??0;s.success(`Removed ${n} ${n===1?"item":"items"} from reading list`),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to remove: ${r.message}`)}}))},Z=()=>{const e=i(),a=g();return c(e.mangaProgress.removeMany.mutationOptions({onSuccess:r=>{const n=r.removed??0;s.success(`Reset progress for ${n} ${n===1?"item":"items"}`),a.invalidateQueries({queryKey:["manga-progress"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())},onError:r=>{s.error(`Failed to reset progress: ${r.message}`)}}))},ee=()=>{const e=S(),a=F(),{data:r}=P(),n=Q(()=>new Set(r?.ids||[]),[r]);return{toggle:t=>{const m=L(t.provider,t.id);n.has(m)?a.mutate(m):e.mutate({provider:t.provider,mangaId:t.id,title:t.title,cover:t.cover,altTitle:t.altTitle,contentRating:t.contentRating})},bookmarkedIds:n,pending:e.isPending||a.isPending}};export{Z as A,J as B,_ as M,E as a,T as b,A as c,z as d,B as e,k as f,j as g,S as h,I as i,H as j,O as k,U as l,L as m,V as n,F as o,Y as p,w as q,N as r,x as s,$ as t,ee as u,f as v,G as w,D as x,W as y,X as z};
1
+ import{b as u,c as b,u as g,a as c}from"./vendor-query-BBT5_sHx.js";import{t as p,h as i,z as s}from"./index-B4AdKbhW.js";import{T as Q}from"./vendor-core-DfaOB3Rn.js";const v=300*1e3,M={mangadex:"https://mangadex.org/",mangapill:"https://www.mangapill.com/"},f=(e,a)=>`/api/proxy?url=${encodeURIComponent(a)}&referer=${encodeURIComponent(M[e])}`,T=(e,a)=>a&&(e==="mangapill"?f(e,a):a),k=(e,a=!0)=>{const{provider:r,query:n,page:o,sort:t,status:m,type:d,rating:y,mature:l}=e;return u({queryKey:["mangaBrowse",r,n,o,t,m,d,y,l],queryFn:()=>p.manga.search.query({provider:r,q:n.trim()||void 0,page:o,sort:t||void 0,status:m||void 0,type:d||void 0,rating:y||void 0,mature:l?"1":void 0}),staleTime:v,enabled:a&&!!r})},E=(e,a=14)=>{const{provider:r,query:n,sort:o,status:t,type:m,rating:d,mature:y}=e;return b({queryKey:["mangaBrowseInfinite",r,n,o,t,m,d,y,a],queryFn:({pageParam:l=1})=>p.manga.search.query({provider:r,q:n.trim()||void 0,page:l,limit:a,sort:o||void 0,status:t||void 0,type:m||void 0,rating:d||void 0,mature:y?"1":void 0}),initialPageParam:1,getNextPageParam:(l,q)=>l.hasNext?q.length+1:void 0,staleTime:v,enabled:!!r})},O=(e,a,r="safe",n=!1)=>u({queryKey:["mangaDetail",e,a,r,n],queryFn:()=>p.manga.info.query({provider:e||"",id:a||"",rating:r,mature:n?"1":void 0}),enabled:!!e&&!!a,staleTime:v}),$=(e,a,r)=>u({queryKey:["mangaPages",e,a],queryFn:()=>p.manga.pages.query({provider:e||"",id:a||""}),enabled:!!e&&!!a,staleTime:1800*1e3}),B=()=>{const e=i();return u({...e.manga.trending.queryOptions(),staleTime:600*1e3,retry:1})},I=e=>e.contentRating==="erotica"||e.contentRating==="pornographic"||e.type==="doujinshi";function N(e,a){const r=e.titles??{};return a==="englishName"?r.en||e.title:a==="nativeName"&&(r.native||r.romaji||e.altTitle)||e.title}function A(e){return{englishName:e.titles?.en??e.title,nativeName:e.titles?.native??e.titles?.romaji??e.altTitle??void 0}}const h=/^anilist:ch:(\d+)$/;function w(e){if(!e)return null;const a=h.exec(e.trim());if(!a)return null;const r=Number.parseInt(a[1],10);return Number.isFinite(r)?r:null}function x(e,a){const r=String(a),n=e.find(o=>(o.number??"").trim()===r);return n||(e.find(o=>{const t=Number.parseFloat((o.number??"").trim());return Number.isFinite(t)&&t===a})??null)}const _=["Reading","Completed","On-Hold","Dropped","Planned"],L=(e,a)=>`${e.toLowerCase()}:${a}`,D=(e="All",a=1,r=24)=>{const n=i();return u(n.mangaLibrary.list.queryOptions({status:e,page:a,limit:r}))},P=()=>{const e=i();return u({...e.mangaLibrary.ids.queryOptions(),staleTime:1e3*60})},U=e=>{const a=i();return u({...a.mangaLibrary.check.queryOptions({id:e??""}),enabled:!!e,staleTime:1e3*60})},j=e=>{const a=i();return u({...a.mangaLibrary.entry.queryOptions({id:e??""}),enabled:!!e,staleTime:1e3*60})},H=()=>{const e=i(),a=g();return c(e.mangaLibrary.link.mutationOptions({onSuccess:r=>{s.success(r?.progressMigrated?"Linked — chapter progress carried over":"Linked to AniList entry"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to link: ${r.message}`)}}))},z=(e=24)=>{const a=i();return u(a.mangaProgress.continueReading.queryOptions({limit:e}))},V=e=>{const a=i();return u({...a.mangaProgress.byManga.queryOptions({mangaId:e??""}),enabled:!!e})},S=()=>{const e=i(),a=g();return c(e.mangaLibrary.add.mutationOptions({onSuccess:(r,n)=>{n.silent||s.success("Bookmarked"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]})},onError:r=>{s.error(`Failed to bookmark: ${r.message}`)}}))},F=()=>{const e=i(),a=g();return c(e.mangaLibrary.remove.mutationOptions({onSuccess:()=>{s.success("Bookmark removed"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to remove: ${r.message}`)}}))},Y=()=>{const e=i(),a=g();return c(e.mangaLibrary.setStatus.mutationOptions({onSuccess:()=>{s.success("Status updated"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to update status: ${r.message}`)}}))},G=()=>{const e=i(),a=g();return c(e.mangaProgress.save.mutationOptions({onSuccess:(r,n)=>{a.invalidateQueries({queryKey:["manga-progress",n.mangaId]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())}}))},J=()=>{const e=i(),a=g();return c(e.mangaProgress.remove.mutationOptions({onSuccess:()=>{s.success("Progress reset"),a.invalidateQueries({queryKey:["manga-progress"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())},onError:r=>{s.error(`Failed to reset progress: ${r.message}`)}}))},W=()=>{const e=i(),a=g();return c(e.mangaLibrary.batchStatus.mutationOptions({onSuccess:r=>{s.success(`Status updated for ${r.updated??0} items`),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to update statuses: ${r.message}`)}}))},X=()=>{const e=i(),a=g();return c(e.mangaLibrary.removeMany.mutationOptions({onSuccess:r=>{const n=r.removed??0;s.success(`Removed ${n} ${n===1?"item":"items"} from reading list`),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to remove: ${r.message}`)}}))},Z=()=>{const e=i(),a=g();return c(e.mangaProgress.removeMany.mutationOptions({onSuccess:r=>{const n=r.removed??0;s.success(`Reset progress for ${n} ${n===1?"item":"items"}`),a.invalidateQueries({queryKey:["manga-progress"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())},onError:r=>{s.error(`Failed to reset progress: ${r.message}`)}}))},ee=()=>{const e=S(),a=F(),{data:r}=P(),n=Q(()=>new Set(r?.ids||[]),[r]);return{toggle:t=>{const m=L(t.provider,t.id);n.has(m)?a.mutate(m):e.mutate({provider:t.provider,mangaId:t.id,title:t.title,cover:t.cover,altTitle:t.altTitle,contentRating:t.contentRating})},bookmarkedIds:n,pending:e.isPending||a.isPending}};export{Z as A,J as B,_ as M,E as a,T as b,A as c,z as d,B as e,k as f,j as g,S as h,I as i,H as j,O as k,U as l,L as m,V as n,F as o,Y as p,w as q,N as r,x as s,$ as t,ee as u,f as v,G as w,D as x,W as y,X as z};
@@ -1 +1 @@
1
- import{u as e,S as f,L as m}from"./vendor-core-DfaOB3Rn.js";import{I as l}from"./vendor-icons-DrybRNxP.js";import{k as y,r as T}from"./useMangaLibrary-CU3bFfuD.js";import{d as I}from"./index-DNxWyfmM.js";import{p as s,a as k}from"./MediaCard-D6_9HL2Z.js";import{u as P}from"./usePopup-DS9jMzp6.js";const R=({data:i,anchorRect:d,bookmarked:r,onToggleBookmark:p,onMouseEnter:h,onMouseLeave:v,onRequestClose:g})=>{const{data:a,isLoading:N}=y(i.provider,i.mangaId,i.rating||"safe",i.mature||!1),{titlePreference:u}=I(),t=a?.chapters.length??0,c=[a?.status,a?.type].filter(Boolean).join(" · "),o=T({title:i.title,altTitle:a?.altTitle??i.altTitle},u);return e(k,{anchorRect:d,onMouseEnter:h,onMouseLeave:v,onRequestClose:g,children:N?e("div",{className:s.loading,children:[e("div",{className:s.spinner}),e("span",{children:"Fetching details..."})]}):e(f,{children:[e("div",{className:s.header,children:[e("div",{className:s.title,children:o}),a?.altTitle&&a.altTitle!==o&&e("div",{className:s.synopsis,children:["Also known as: ",a.altTitle]})]}),e("div",{className:s.body,children:[e("div",{className:s.metaRow,children:[c&&e("div",{className:s.metaItem,children:[e(l,{name:"book",size:14}),e("span",{children:c})]}),t>0&&e("div",{className:s.metaItem,children:e("span",{children:[t," chapter",t===1?"":"s"]})}),i.progressLabel&&e("div",{className:s.metaItem,children:[e(l,{name:"bookmark",size:12}),e("span",{children:i.progressLabel})]})]}),e("div",{className:s.synopsis,children:a?.description?a.description:"No synopsis available."}),Array.isArray(a?.genres)&&(a?.genres?.length??0)>0&&e("div",{className:s.details,children:e("div",{className:s.genres,children:a.genres.filter(Boolean).slice(0,4).map(n=>e("span",{className:s.genre,children:n},n))})})]}),e("div",{className:s.footer,children:[e("div",{className:s.primaryAction,children:e(m,{to:i.readTarget,className:s.watchBtn,children:[e(l,{name:"book",size:14}),"Read now"]})}),e("div",{className:s.secondaryActions,children:[e("button",{className:`${s.watchlistBtn} ${r?s.active:""}`,onClick:n=>{n.preventDefault(),n.stopPropagation(),p()},children:[r?e(l,{name:"check",size:12}):e(l,{name:"plus",size:12}),e("span",{children:r?"Remove":"Bookmark"})]}),e(m,{to:`/manga/${i.provider}/${encodeURIComponent(i.mangaId)}`,className:s.detailsBtn,children:"Read more"})]})]})]})})},$=()=>P();export{R as M,$ as u};
1
+ import{u as e,S as f,L as m}from"./vendor-core-DfaOB3Rn.js";import{I as l}from"./vendor-icons-DrybRNxP.js";import{k as y,r as T}from"./useMangaLibrary-C6XEMuSr.js";import{d as I}from"./index-B4AdKbhW.js";import{p as s,a as k}from"./MediaCard-DedwE5DX.js";import{u as P}from"./usePopup-DS9jMzp6.js";const R=({data:i,anchorRect:d,bookmarked:r,onToggleBookmark:p,onMouseEnter:h,onMouseLeave:v,onRequestClose:g})=>{const{data:a,isLoading:N}=y(i.provider,i.mangaId,i.rating||"safe",i.mature||!1),{titlePreference:u}=I(),t=a?.chapters.length??0,c=[a?.status,a?.type].filter(Boolean).join(" · "),o=T({title:i.title,altTitle:a?.altTitle??i.altTitle},u);return e(k,{anchorRect:d,onMouseEnter:h,onMouseLeave:v,onRequestClose:g,children:N?e("div",{className:s.loading,children:[e("div",{className:s.spinner}),e("span",{children:"Fetching details..."})]}):e(f,{children:[e("div",{className:s.header,children:[e("div",{className:s.title,children:o}),a?.altTitle&&a.altTitle!==o&&e("div",{className:s.synopsis,children:["Also known as: ",a.altTitle]})]}),e("div",{className:s.body,children:[e("div",{className:s.metaRow,children:[c&&e("div",{className:s.metaItem,children:[e(l,{name:"book",size:14}),e("span",{children:c})]}),t>0&&e("div",{className:s.metaItem,children:e("span",{children:[t," chapter",t===1?"":"s"]})}),i.progressLabel&&e("div",{className:s.metaItem,children:[e(l,{name:"bookmark",size:12}),e("span",{children:i.progressLabel})]})]}),e("div",{className:s.synopsis,children:a?.description?a.description:"No synopsis available."}),Array.isArray(a?.genres)&&(a?.genres?.length??0)>0&&e("div",{className:s.details,children:e("div",{className:s.genres,children:a.genres.filter(Boolean).slice(0,4).map(n=>e("span",{className:s.genre,children:n},n))})})]}),e("div",{className:s.footer,children:[e("div",{className:s.primaryAction,children:e(m,{to:i.readTarget,className:s.watchBtn,children:[e(l,{name:"book",size:14}),"Read now"]})}),e("div",{className:s.secondaryActions,children:[e("button",{className:`${s.watchlistBtn} ${r?s.active:""}`,onClick:n=>{n.preventDefault(),n.stopPropagation(),p()},children:[r?e(l,{name:"check",size:12}):e(l,{name:"plus",size:12}),e("span",{children:r?"Remove":"Bookmark"})]}),e(m,{to:`/manga/${i.provider}/${encodeURIComponent(i.mangaId)}`,className:s.detailsBtn,children:"Read more"})]})]})]})})},$=()=>P();export{R as M,$ as u};
@@ -1 +1 @@
1
- import{T as o}from"./vendor-core-DfaOB3Rn.js";import{b as a}from"./vendor-query-BBT5_sHx.js";import{U as i}from"./index-DNxWyfmM.js";const n=300*1e3;function u(r){return{value:r.id,label:r.label,mature:r.mature,kind:r.kind,sub:r.sub,tier:r.tier,browse:r.browse,facets:r.facets,servers:r.servers}}const d=()=>{const r=a({queryKey:["providers"],queryFn:()=>i("/api/providers"),staleTime:n,retry:1}),e=Array.isArray(r.data)?r.data:null,t=o(()=>e&&e.length>0?e.filter(s=>s.loaded).map(u):[],[e]);return{...r,options:t,isFallback:!e||e.length===0}};export{d as u};
1
+ import{T as o}from"./vendor-core-DfaOB3Rn.js";import{b as a}from"./vendor-query-BBT5_sHx.js";import{U as i}from"./index-B4AdKbhW.js";const n=300*1e3;function u(r){return{value:r.id,label:r.label,mature:r.mature,kind:r.kind,sub:r.sub,tier:r.tier,browse:r.browse,facets:r.facets,servers:r.servers}}const d=()=>{const r=a({queryKey:["providers"],queryFn:()=>i("/api/providers"),staleTime:n,retry:1}),e=Array.isArray(r.data)?r.data:null,t=o(()=>e&&e.length>0?e.filter(s=>s.loaded).map(u):[],[e]);return{...r,options:t,isFallback:!e||e.length===0}};export{d as u};
@@ -1 +1 @@
1
- import{N as c,u as r,S as d}from"./vendor-core-DfaOB3Rn.js";import{I as v}from"./vendor-icons-DrybRNxP.js";import{M as T}from"./MediaCard-D6_9HL2Z.js";import{T as g}from"./TvPopup-S5blnD3l.js";import{c as m,i as f}from"./useTvLibrary-c90knUfT.js";import{b as i}from"./vendor-query-BBT5_sHx.js";import{h as p}from"./index-DNxWyfmM.js";const _=c(({item:e})=>{const o=e.type==="tv"||e.type==="tvSeries"||e.type==="tvMiniSeries",s=m(e.type,e.id);return r(T,{item:{id:String(e.id),title:e.title,thumbnail:e.image,typeBadge:o?"TV":"Movie",isAdult:f(e)},linkTo:s,hoverIcon:"info",showInfoButton:!0,metaRow:r(d,{children:[e.year&&r("span",{style:{opacity:.75},children:e.year}),e.vote_average!=null&&r("span",{style:{display:"inline-flex",alignItems:"center",gap:3},children:[r(v,{name:"star",size:10}),Number(e.vote_average).toFixed(1)]})]}),renderPopup:(a,t)=>r(g,{item:e,anchorRect:a,onMouseEnter:t.onMouseEnter,onMouseLeave:t.onMouseLeave,onRequestClose:t.close})})}),u=1e3*60*5,b=e=>{const o=p(),{query:s,type:a,genre:t,year:n,sort_by:l,page:y}=e;return i({...o.tv.search.queryOptions({q:s?.trim()||"",type:a||"multi",genre:t||"",year:n&&n!=="ALL"?n:"",sortBy:l||"popularity.desc",page:y||1}),staleTime:u,retry:1})},A=(e="all",o="week",s=1,a=!0)=>{const t=p();return i({...t.tv.trending.queryOptions({mediaType:e,timeWindow:o,page:s}),enabled:a,staleTime:u,retry:1})};export{_ as T,b as a,A as u};
1
+ import{N as c,u as r,S as d}from"./vendor-core-DfaOB3Rn.js";import{I as v}from"./vendor-icons-DrybRNxP.js";import{M as T}from"./MediaCard-DedwE5DX.js";import{T as g}from"./TvPopup-D1mSlOZt.js";import{c as m,i as f}from"./useTvLibrary-73NkS_5R.js";import{b as i}from"./vendor-query-BBT5_sHx.js";import{h as p}from"./index-B4AdKbhW.js";const _=c(({item:e})=>{const o=e.type==="tv"||e.type==="tvSeries"||e.type==="tvMiniSeries",s=m(e.type,e.id);return r(T,{item:{id:String(e.id),title:e.title,thumbnail:e.image,typeBadge:o?"TV":"Movie",isAdult:f(e)},linkTo:s,hoverIcon:"info",showInfoButton:!0,metaRow:r(d,{children:[e.year&&r("span",{style:{opacity:.75},children:e.year}),e.vote_average!=null&&r("span",{style:{display:"inline-flex",alignItems:"center",gap:3},children:[r(v,{name:"star",size:10}),Number(e.vote_average).toFixed(1)]})]}),renderPopup:(a,t)=>r(g,{item:e,anchorRect:a,onMouseEnter:t.onMouseEnter,onMouseLeave:t.onMouseLeave,onRequestClose:t.close})})}),u=1e3*60*5,b=e=>{const o=p(),{query:s,type:a,genre:t,year:n,sort_by:l,page:y}=e;return i({...o.tv.search.queryOptions({q:s?.trim()||"",type:a||"multi",genre:t||"",year:n&&n!=="ALL"?n:"",sortBy:l||"popularity.desc",page:y||1}),staleTime:u,retry:1})},A=(e="all",o="week",s=1,a=!0)=>{const t=p();return i({...t.tv.trending.queryOptions({mediaType:e,timeWindow:o,page:s}),enabled:a,staleTime:u,retry:1})};export{_ as T,b as a,A as u};
@@ -1 +1 @@
1
- import{T as y}from"./vendor-core-DfaOB3Rn.js";import{b as v,u as o,a as n}from"./vendor-query-BBT5_sHx.js";import{h as a,z as i,t as p}from"./index-DNxWyfmM.js";const d=t=>String(t).toLowerCase()==="movie"?"movie":"tv",m=(t,e)=>`${d(t)}:${e}`,L=(t,e)=>{const r=d(t);return`/tv/${e}?type=${r}`},S=(t,e,r,s)=>{const u=new URLSearchParams;return u.set("type",d(t)),r!==void 0&&u.set("s",String(r)),s!==void 0&&u.set("e",String(s)),`/tv/${e}/watch?${u.toString()}`},F=t=>t.adult===!0||t.adult===1,K=["Watching","Completed","On-Hold","Dropped","Planned"],g=(t,e)=>m(t,e),$=(t="All",e=1,r=24)=>{const s=a();return v(s.tvLibrary.list.queryOptions({status:t,page:e,limit:r}))},h=()=>{const t=a();return v({...t.tvLibrary.ids.queryOptions(),staleTime:1e3*60})},C=t=>{const e=a();return v({...e.tvLibrary.check.queryOptions({id:t||""}),enabled:!!t,staleTime:1e3*60})},w=(t=24)=>{const e=a();return v(e.tvProgress.continueWatching.queryOptions({limit:t}))},O=t=>{const e=a();return v({...e.tvProgress.getByMedia.queryOptions({mediaId:t||""}),enabled:!!t})},f=(t,e,r)=>{const s=a();return v({...s.tvProgress.latest.queryOptions({mediaId:t||"",season:e,episode:r}),enabled:!!t,staleTime:0})},b=()=>{const t=a(),e=o();return n({mutationFn:async r=>{const{silent:s,...u}=r;return p.tvLibrary.add.mutate(u)},onSuccess:(r,s)=>{s.silent||i.success("Added to TV watchlist"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter())},onError:r=>{i.error(`Failed to add: ${r.message}`)}})},Q=()=>{const t=a(),e=o();return n(t.tvLibrary.remove.mutationOptions({onSuccess:()=>{i.success("Removed from TV watchlist"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to remove: ${r.message}`)}}))},k=()=>{const t=a(),e=o();return n(t.tvLibrary.setStatus.mutationOptions({onSuccess:()=>{i.success("Status updated"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to update status: ${r.message}`)}}))},R=()=>{const t=a(),e=o();return n(t.tvProgress.save.mutationOptions({onSuccess:(r,s)=>{e.invalidateQueries({queryKey:["tv-progress",s.mediaId]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())}}))},B=()=>{const t=a(),e=o();return n(t.tvProgress.remove.mutationOptions({onSuccess:()=>{i.success("Progress reset"),e.invalidateQueries({queryKey:["tv-progress"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to reset progress: ${r.message}`)}}))},E=()=>{const t=a(),e=o();return n(t.tvLibrary.batchStatus.mutationOptions({onSuccess:r=>{i.success(`Status updated for ${r.updated??0} items`),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to update statuses: ${r.message}`)}}))},I=()=>{const t=a(),e=o();return n(t.tvLibrary.removeMany.mutationOptions({onSuccess:r=>{const s=r.removed??0;i.success(`Removed ${s} ${s===1?"item":"items"} from TV watchlist`),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to remove: ${r.message}`)}}))},A=()=>{const t=a(),e=o();return n(t.tvProgress.removeMany.mutationOptions({onSuccess:r=>{const s=r.removed??0;i.success(`Reset progress for ${s} ${s===1?"item":"items"}`),e.invalidateQueries({queryKey:["tv-progress"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to reset progress: ${r.message}`)}}))},M=()=>{const t=b(),e=Q(),{data:r}=h(),s=y(()=>new Set(r?.ids||[]),[r]);return{toggle:c=>{const l=g(c.mediaType,c.tmdbId);s.has(l)?e.mutate(l):t.mutate({...c,poster:c.poster||""})},bookmarkedIds:s,pending:t.isPending||e.isPending}};export{K as T,Q as a,B as b,L as c,m as d,C as e,M as f,R as g,k as h,F as i,f as j,O as k,$ as l,E as m,d as n,I as o,A as p,S as t,w as u};
1
+ import{T as y}from"./vendor-core-DfaOB3Rn.js";import{b as v,u as o,a as n}from"./vendor-query-BBT5_sHx.js";import{h as a,z as i,t as p}from"./index-B4AdKbhW.js";const d=t=>String(t).toLowerCase()==="movie"?"movie":"tv",m=(t,e)=>`${d(t)}:${e}`,L=(t,e)=>{const r=d(t);return`/tv/${e}?type=${r}`},S=(t,e,r,s)=>{const u=new URLSearchParams;return u.set("type",d(t)),r!==void 0&&u.set("s",String(r)),s!==void 0&&u.set("e",String(s)),`/tv/${e}/watch?${u.toString()}`},F=t=>t.adult===!0||t.adult===1,K=["Watching","Completed","On-Hold","Dropped","Planned"],g=(t,e)=>m(t,e),$=(t="All",e=1,r=24)=>{const s=a();return v(s.tvLibrary.list.queryOptions({status:t,page:e,limit:r}))},h=()=>{const t=a();return v({...t.tvLibrary.ids.queryOptions(),staleTime:1e3*60})},C=t=>{const e=a();return v({...e.tvLibrary.check.queryOptions({id:t||""}),enabled:!!t,staleTime:1e3*60})},w=(t=24)=>{const e=a();return v(e.tvProgress.continueWatching.queryOptions({limit:t}))},O=t=>{const e=a();return v({...e.tvProgress.getByMedia.queryOptions({mediaId:t||""}),enabled:!!t})},f=(t,e,r)=>{const s=a();return v({...s.tvProgress.latest.queryOptions({mediaId:t||"",season:e,episode:r}),enabled:!!t,staleTime:0})},b=()=>{const t=a(),e=o();return n({mutationFn:async r=>{const{silent:s,...u}=r;return p.tvLibrary.add.mutate(u)},onSuccess:(r,s)=>{s.silent||i.success("Added to TV watchlist"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter())},onError:r=>{i.error(`Failed to add: ${r.message}`)}})},Q=()=>{const t=a(),e=o();return n(t.tvLibrary.remove.mutationOptions({onSuccess:()=>{i.success("Removed from TV watchlist"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to remove: ${r.message}`)}}))},k=()=>{const t=a(),e=o();return n(t.tvLibrary.setStatus.mutationOptions({onSuccess:()=>{i.success("Status updated"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to update status: ${r.message}`)}}))},R=()=>{const t=a(),e=o();return n(t.tvProgress.save.mutationOptions({onSuccess:(r,s)=>{e.invalidateQueries({queryKey:["tv-progress",s.mediaId]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())}}))},B=()=>{const t=a(),e=o();return n(t.tvProgress.remove.mutationOptions({onSuccess:()=>{i.success("Progress reset"),e.invalidateQueries({queryKey:["tv-progress"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to reset progress: ${r.message}`)}}))},E=()=>{const t=a(),e=o();return n(t.tvLibrary.batchStatus.mutationOptions({onSuccess:r=>{i.success(`Status updated for ${r.updated??0} items`),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to update statuses: ${r.message}`)}}))},I=()=>{const t=a(),e=o();return n(t.tvLibrary.removeMany.mutationOptions({onSuccess:r=>{const s=r.removed??0;i.success(`Removed ${s} ${s===1?"item":"items"} from TV watchlist`),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to remove: ${r.message}`)}}))},A=()=>{const t=a(),e=o();return n(t.tvProgress.removeMany.mutationOptions({onSuccess:r=>{const s=r.removed??0;i.success(`Reset progress for ${s} ${s===1?"item":"items"}`),e.invalidateQueries({queryKey:["tv-progress"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to reset progress: ${r.message}`)}}))},M=()=>{const t=b(),e=Q(),{data:r}=h(),s=y(()=>new Set(r?.ids||[]),[r]);return{toggle:c=>{const l=g(c.mediaType,c.tmdbId);s.has(l)?e.mutate(l):t.mutate({...c,poster:c.poster||""})},bookmarkedIds:s,pending:t.isPending||e.isPending}};export{K as T,Q as a,B as b,L as c,m as d,C as e,M as f,R as g,k as h,F as i,f as j,O as k,$ as l,E as m,d as n,I as o,A as p,S as t,w as u};
@@ -33,11 +33,11 @@
33
33
  background-color: #0c0d12;
34
34
  }
35
35
  </style>
36
- <script type="module" crossorigin src="/assets/index-DNxWyfmM.js"></script>
36
+ <script type="module" crossorigin src="/assets/index-B4AdKbhW.js"></script>
37
37
  <link rel="modulepreload" crossorigin href="/assets/vendor-core-DfaOB3Rn.js">
38
38
  <link rel="modulepreload" crossorigin href="/assets/vendor-query-BBT5_sHx.js">
39
39
  <link rel="modulepreload" crossorigin href="/assets/vendor-icons-DrybRNxP.js">
40
- <link rel="stylesheet" crossorigin href="/assets/index-Ck-R0JKv.css">
40
+ <link rel="stylesheet" crossorigin href="/assets/index-D0Haw_Zl.css">
41
41
  </head>
42
42
 
43
43
  <body>
package/orchestrator.js CHANGED
@@ -5,6 +5,7 @@ const http = require('http')
5
5
  const os = require('os')
6
6
  const path = require('path')
7
7
  const crypto = require('crypto')
8
+ const { parseArgs } = require('util')
8
9
 
9
10
  async function fetchJson(url, timeoutMs) {
10
11
  const controller = new AbortController()
@@ -36,7 +37,38 @@ function detectGlobalInstall() {
36
37
  }
37
38
 
38
39
  const shutdownToken = crypto.randomBytes(32).toString('hex')
39
- const mode = process.argv[2] || 'prod'
40
+ let options, mode
41
+ try {
42
+ const { values, positionals } = parseArgs({
43
+ allowPositionals: true,
44
+ options: {
45
+ port: { type: 'string' },
46
+ 'dev-port': { type: 'string' },
47
+ 'no-update': { type: 'boolean' },
48
+ version: { type: 'boolean', short: 'v' },
49
+ help: { type: 'boolean', short: 'h' },
50
+ },
51
+ })
52
+ options = values
53
+ mode = positionals[0] || 'prod'
54
+ if (positionals.length > 1 || !['dev', 'prod'].includes(mode)) {
55
+ throw new Error('Expected at most one mode: dev or prod')
56
+ }
57
+ for (const [flag, variable] of [
58
+ ['port', 'PORT'],
59
+ ['dev-port', 'DEV_PORT'],
60
+ ]) {
61
+ const value = options[flag]
62
+ if (value === undefined) continue
63
+ if (!/^\d+$/.test(value) || Number(value) < 1 || Number(value) > 65535) {
64
+ throw new Error(`--${flag} must be an integer between 1 and 65535`)
65
+ }
66
+ process.env[variable] = String(Number(value))
67
+ }
68
+ } catch (err) {
69
+ console.error(`dango: ${err.message}`)
70
+ process.exit(1)
71
+ }
40
72
  const isWin = os.platform() === 'win32'
41
73
  const npmCmd = isWin ? 'npm.cmd' : 'npm'
42
74
 
@@ -47,16 +79,20 @@ const colors = {
47
79
  system: '\x1b[33m',
48
80
  }
49
81
 
50
- if (mode === '--version' || mode === '-v') {
82
+ if (options.version) {
51
83
  const pkg = require('./package.json')
52
84
  console.log(`dango version ${pkg.version}`)
53
85
  process.exit(0)
54
86
  }
55
87
 
56
- if (mode === '--help' || mode === '-h') {
57
- console.log('Usage: dango [dev|prod] [--no-update] [--version] [--help]')
88
+ if (options.help) {
89
+ console.log(
90
+ 'Usage: dango [dev|prod] [--port PORT] [--dev-port PORT] [--no-update] [--version] [--help]'
91
+ )
58
92
  console.log(' dev Run with hot-reload (server + client)')
59
93
  console.log(' prod Run pre-built version (default)')
94
+ console.log(' --port PORT Backend port (overrides PORT; default: 3000)')
95
+ console.log(' --dev-port PORT Development frontend port (overrides DEV_PORT; default: 5173)')
60
96
  console.log(' --no-update Skip update checks')
61
97
  console.log(' --version, -v Print version and exit')
62
98
  console.log(' --help, -h Show this help and exit')
@@ -104,7 +140,7 @@ const isNewerVersion = (remote, current) => {
104
140
  }
105
141
 
106
142
  async function checkForUpdates() {
107
- if (process.argv.includes('--no-update') || mode === 'dev') return
143
+ if (options['no-update'] || mode === 'dev') return
108
144
 
109
145
  try {
110
146
  const isGlobalInstall = detectGlobalInstall()
@@ -224,6 +260,37 @@ const CLIENT_DIR = path.join(__dirname, 'client')
224
260
  let syncSpinner = null
225
261
  let syncMessage = ''
226
262
  let syncDots = 0
263
+ let providerLineActive = false
264
+ let providerPhase = false
265
+ let providerFields = {}
266
+ let pendingProviderSummary = false
267
+
268
+ const ansiPattern = /\x1b\[[0-9;]*m/g
269
+ const readPrettyField = (line) => {
270
+ const match = /^\s+([\w-]+):\s*(.*)$/.exec(line.replace(ansiPattern, ''))
271
+ return match ? [match[1], match[2].trim().replace(/^"|"$/g, '')] : null
272
+ }
273
+
274
+ const showProvider = (color, prefix, fields) => {
275
+ process.stdout.write(
276
+ `\r\x1b[K${color}[${prefix}]${colors.reset} ${colors.system}Loading providers${colors.reset} ` +
277
+ `${colors.client}${fields.provider || ''}${fields.version ? ` v${fields.version}` : ''}${colors.reset}`
278
+ )
279
+ providerLineActive = true
280
+ }
281
+
282
+ const flushProviderSummary = (color, prefix) => {
283
+ if (providerLineActive) {
284
+ process.stdout.write('\n')
285
+ providerLineActive = false
286
+ }
287
+ if (!pendingProviderSummary) return
288
+ pendingProviderSummary = false
289
+ console.log(
290
+ `${color}[${prefix}]${colors.reset} ${colors.system}Providers ready${colors.reset} ` +
291
+ `${colors.client}${providerFields.count} anime, ${providerFields.mangaCount} manga, ${providerFields.tvCount} tv${colors.reset}`
292
+ )
293
+ }
227
294
 
228
295
  const startSpinner = (msg) => {
229
296
  stopSpinner()
@@ -281,7 +348,7 @@ const formatChildLine = (line) => {
281
348
  const text =
282
349
  `${time ? `[${time}] ` : ''}${levelColor}${levelName}${colors.reset} ${messageColor}${obj.msg}${colors.reset}` +
283
350
  (extras.length ? ` (${propertyColor}${extras.join(' ')}${colors.reset})` : '')
284
- return { text, msg: obj.msg }
351
+ return { text, msg: obj.msg, obj }
285
352
  }
286
353
 
287
354
  const log = (prefix, color, data) => {
@@ -293,9 +360,23 @@ const log = (prefix, color, data) => {
293
360
 
294
361
  const display = []
295
362
  for (const line of lines) {
296
- const { text, msg } = formatChildLine(line)
363
+ if (providerPhase) {
364
+ const field = readPrettyField(line)
365
+ if (field) {
366
+ providerFields[field[0]] = field[1]
367
+ if (providerLineActive && field[0] !== 'module') {
368
+ showProvider(color, prefix, providerFields)
369
+ }
370
+ continue
371
+ }
372
+ }
373
+
374
+ const { text, msg, obj } = formatChildLine(line)
297
375
  const content = msg !== undefined ? msg : text
298
376
 
377
+ const boundMatch = content.match(/Server running on http:\/\/localhost:(\d+)/)
378
+ if (boundMatch) boundServerPort = Number(boundMatch[1])
379
+
299
380
  if (content.includes('[SERVER_EXIT]')) {
300
381
  isShuttingDown = true
301
382
  stopSpinner()
@@ -308,6 +389,23 @@ const log = (prefix, color, data) => {
308
389
  return
309
390
  }
310
391
 
392
+ if (content.includes('remote provider loaded')) {
393
+ if (pendingProviderSummary) flushProviderSummary(color, prefix)
394
+ providerPhase = true
395
+ providerFields = { ...(obj || {}) }
396
+ showProvider(color, prefix, providerFields)
397
+ continue
398
+ }
399
+ if (content.includes('remote providers refreshed')) {
400
+ providerPhase = true
401
+ Object.assign(providerFields, obj)
402
+ pendingProviderSummary = true
403
+ continue
404
+ }
405
+ flushProviderSummary(color, prefix)
406
+ providerPhase = false
407
+ providerFields = {}
408
+
311
409
  if (content.includes('[SYNC_START]')) {
312
410
  startSpinner(content.split('[SYNC_START]')[1].trim())
313
411
  continue
@@ -392,6 +490,7 @@ const terminateProcess = (proc, signal = 'SIGTERM') => {
392
490
  }
393
491
  let serverProcess, clientProcess
394
492
  let isShuttingDown = false
493
+ let boundServerPort = Number(process.env.PORT) || 3000
395
494
 
396
495
  async function main() {
397
496
  console.log(
@@ -465,7 +564,7 @@ const shutdown = () => {
465
564
  }, 5000)
466
565
  }
467
566
 
468
- const serverPort = Number(process.env.PORT) || 3000
567
+ const serverPort = boundServerPort
469
568
  const req = http.request(
470
569
  {
471
570
  hostname: '127.0.0.1',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serifpersia/dango",
3
- "version": "3.5.9",
3
+ "version": "3.6.1",
4
4
  "description": "A web application for watching anime.",
5
5
  "main": "orchestrator.js",
6
6
  "repository": {
@@ -83,5 +83,5 @@
83
83
  "allowScripts": {
84
84
  "esbuild@0.28.2": true
85
85
  },
86
- "versionDate": "2026-10-13T22:50:45.916Z"
86
+ "versionDate": "2026-10-16T10:34:21.293Z"
87
87
  }
@@ -53,6 +53,11 @@ export function getHonoClientIp(c) {
53
53
  return c.req.header('x-dango-client-ip') ?? undefined;
54
54
  }
55
55
  }
56
+ const NOT_READY_HEADER = 'x-dango-not-ready';
57
+ function notReady(c, body) {
58
+ c.header(NOT_READY_HEADER, '1');
59
+ return typeof body === 'string' ? c.text(body, 503) : c.json(body, 503);
60
+ }
56
61
  export async function honoRequestLogger(c, next) {
57
62
  const start = process.hrtime.bigint();
58
63
  const url = new URL(c.req.url);
@@ -61,7 +66,7 @@ export async function honoRequestLogger(c, next) {
61
66
  const ms = Math.round((Number(process.hrtime.bigint() - start) / 1_000_000) * 10) / 10;
62
67
  const status = c.res.status;
63
68
  const payload = { method: c.req.method, url: loggedUrl, status, ms };
64
- if (status >= 500) {
69
+ if (status >= 500 && !c.res.headers.get(NOT_READY_HEADER)) {
65
70
  logger.warn(payload, 'request failed');
66
71
  }
67
72
  else if (!loggedUrl.startsWith('/api/proxy')) {
@@ -208,26 +213,26 @@ export function createHonoApp(getState, getGuardState, getDbs, dbAdmin, provider
208
213
  app.get('/api/health', (c) => {
209
214
  const state = getState();
210
215
  if (state.shuttingDown) {
211
- return c.json({ status: 'shutting-down', ready: false }, 503);
216
+ return notReady(c, { status: 'shutting-down', ready: false });
212
217
  }
213
218
  if (!state.dbReady) {
214
- return c.json({ status: 'starting', ready: false }, 503);
219
+ return notReady(c, { status: 'starting', ready: false });
215
220
  }
216
221
  return c.json({ status: 'ok', ready: true });
217
222
  });
218
223
  app.use(async (c, next) => {
219
224
  const guard = getGuardState();
220
225
  if (guard.shuttingDown) {
221
- return c.text('Server is shutting down...', 503);
226
+ return notReady(c, 'Server is shutting down...');
222
227
  }
223
228
  if (!guard.dbsReady) {
224
- return c.text('Database initializing...', 503);
229
+ return notReady(c, 'Database initializing...');
225
230
  }
226
231
  if (guard.bootSyncing &&
227
232
  c.req.method !== 'GET' &&
228
233
  c.req.method !== 'HEAD' &&
229
234
  c.req.method !== 'OPTIONS') {
230
- return c.text('Sync in progress...', 503);
235
+ return notReady(c, 'Sync in progress...');
231
236
  }
232
237
  await next();
233
238
  });
@@ -288,7 +293,7 @@ export function createHonoApp(getState, getGuardState, getDbs, dbAdmin, provider
288
293
  app.get('/api/auth/app-status', (c) => {
289
294
  const authed = !hasAppPassword() ||
290
295
  validateLanSession(getTokenFromHeaders(c.req.header('authorization'), c.req.header('cookie')));
291
- return c.json({ hasPassword: hasAppPassword(), isAuthenticated: authed });
296
+ return c.json({ hasPassword: hasAppPassword(), isAuthenticated: authed, port: CONFIG.PORT });
292
297
  });
293
298
  app.post('/api/auth/app-login', async (c) => {
294
299
  const body = (await c.req.json().catch(() => undefined));
@@ -470,7 +475,7 @@ export function createHonoApp(getState, getGuardState, getDbs, dbAdmin, provider
470
475
  try {
471
476
  const dbs = getDbs();
472
477
  if (!dbs.mangaDb || dbs.mangaDb.isClosedCheck()) {
473
- return c.json({ error: 'Manga database is not ready' }, 503);
478
+ return notReady(c, { error: 'Manga database is not ready' });
474
479
  }
475
480
  let result;
476
481
  try {
@@ -117,10 +117,11 @@ migrateFromAniWeb(DATA_ROOT);
117
117
  dotenv.config({ path: path.join(SERVER_ROOT, '.env') });
118
118
  dotenv.config({ path: ENV_PATH, override: true });
119
119
  const IS_DEV = process.argv.includes('--dev');
120
- const PORT = 3000;
120
+ const PORT = Number(process.env.PORT) || 3000;
121
+ const DEV_PORT = Number(process.env.DEV_PORT) || 5173;
121
122
  const HOST = process.env.HOST || '0.0.0.0';
122
123
  const GOOGLE_REDIRECT_URI = IS_DEV
123
- ? 'http://localhost:5173/api/auth/google/callback'
124
+ ? `http://localhost:${DEV_PORT}/api/auth/google/callback`
124
125
  : `http://localhost:${PORT}/api/auth/google/callback`;
125
126
  export const CONFIG = {
126
127
  ROOT: DATA_ROOT,
@@ -1,6 +1,5 @@
1
1
  import logger from '../logger.js';
2
2
  import { googleDriveService } from '../google.js';
3
- import { CONFIG } from '../config.js';
4
3
  import { updateEnvFile } from '../utils/env.utils.js';
5
4
  export function registerAuth(app, getDbs, runSync) {
6
5
  app.get('/api/auth/google/callback', async (c) => {
@@ -32,12 +31,6 @@ export function registerAuth(app, getDbs, runSync) {
32
31
  try {
33
32
  if (window.opener && !window.opener.closed) {
34
33
  window.opener.postMessage(payload, window.location.origin);
35
- try {
36
- window.opener.postMessage(payload, 'http://localhost:${CONFIG.PORT}');
37
- } catch (e) {}
38
- try {
39
- window.opener.postMessage(payload, 'http://127.0.0.1:${CONFIG.PORT}');
40
- } catch (e) {}
41
34
  setTimeout(function () { window.close(); }, 300);
42
35
  setTimeout(function () { window.location.href = '/?google_auth=success'; }, 1500);
43
36
  } else {
@@ -1,4 +1,5 @@
1
1
  import logger from '../../logger.js';
2
+ import { TRPCError } from '@trpc/server';
2
3
  import { googleDriveService } from '../../google.js';
3
4
  import { githubSyncService } from '../../github-sync.js';
4
5
  import { initSyncProvider, getActiveProvider, runFullSyncSequence } from '../../sync.js';
@@ -27,6 +28,9 @@ const syncProviderInput = () => defineSchema((value) => ({
27
28
  const rcloneSaveInput = () => defineSchema((value) => ({
28
29
  remote: reqObj(value).remote,
29
30
  }));
31
+ const serverPortInput = () => defineSchema((value) => ({
32
+ port: reqObj(value).port,
33
+ }));
30
34
  export const authRouter = router({
31
35
  configStatus: protectedProcedure.query(async () => {
32
36
  const useWorker = !!CONFIG.GOOGLE_AUTH_WORKER_URL;
@@ -145,6 +149,18 @@ export const authRouter = router({
145
149
  await runSyncFromCtx(ctx, ctx.db, 'rclone');
146
150
  return { success: true };
147
151
  }),
152
+ setServerPort: protectedProcedure.input(serverPortInput()).mutation(async ({ input }) => {
153
+ const port = Number(input.port);
154
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
155
+ throw new TRPCError({
156
+ code: 'BAD_REQUEST',
157
+ message: 'Port must be an integer between 1 and 65535',
158
+ });
159
+ }
160
+ await updateEnvFile({ PORT: String(port) });
161
+ logger.info({ port }, 'Server port saved. Restart required to apply.');
162
+ return { success: true, port };
163
+ }),
148
164
  googleAuthUrl: protectedProcedure.query(async () => {
149
165
  const url = await googleDriveService.getAuthUrl();
150
166
  return { url };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dango-server",
3
3
  "private": true,
4
- "version": "3.5.9",
4
+ "version": "3.6.1",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=22.12.0"
@@ -1 +0,0 @@
1
- ._container_1287q_1{max-width:var(--max-width);margin:0 auto;padding:0;min-height:100vh;background:var(--bg-main);overflow-x:hidden}._heroSection_1287q_11{position:relative;width:100%;padding-bottom:var(--space-12)}._bannerContainer_1287q_17{position:absolute;top:0;left:0;right:0;height:500px;overflow:hidden;z-index:0}._banner_1287q_17{width:100%;height:100%;background-size:cover;background-position:center 20%;filter:brightness(.3) saturate(1.1);transform:scale(1.05);transition:transform var(--transition-slow)}._bannerOverlay_1287q_37{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(5,5,5,.4) 0%,rgba(5,5,5,.7) 40%,var(--bg-main) 100%);box-shadow:inset 0 -100px 100px -20px var(--bg-main)}._heroContent_1287q_49{position:relative;z-index:1;display:grid;grid-template-columns:320px 1fr;gap:var(--space-10);max-width:1200px;margin:0 auto;padding:var(--space-16) var(--space-6) 0;align-items:flex-start}._posterContainer_1287q_62{position:sticky;top:120px;border-radius:var(--radius-lg);overflow:hidden;box-shadow:0 20px 50px #00000080;transform:translateY(0);animation:_floatIn_1287q_1 .8s var(--ease-spring);border:1px solid var(--border-secondary)}._poster_1287q_62{width:100%;display:block;object-fit:cover;aspect-ratio:2 / 3;transition:transform var(--transition-base)}._posterContainer_1287q_62:hover ._poster_1287q_62{transform:scale(1.05)}._infoGlass_1287q_86{background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius-xl);padding:var(--space-8);box-shadow:var(--glass-shadow);animation:_slideUpIn_1287q_1 .8s var(--ease-smooth);display:flex;flex-direction:column;gap:var(--space-8)}._title_1287q_100{font-size:clamp(1.5rem,4vw,2.5rem);font-weight:800;color:var(--text-primary);line-height:1.1;margin:0 0 var(--space-4);letter-spacing:-.02em}._quickMeta_1287q_109{display:flex;flex-wrap:wrap;gap:var(--space-6);align-items:center;margin-bottom:var(--space-2)}._metaItem_1287q_117{display:flex;align-items:center;gap:var(--space-2);color:var(--text-secondary);font-size:var(--font-size-sm);font-weight:500}._iconStar_1287q_126{color:var(--accent-lighter)}._iconTv_1287q_129{color:var(--accent)}._iconType_1287q_132{color:var(--color-success)}._iconClock_1287q_135{color:#60a5fa}._genres_1287q_139{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-4)}._genre_1287q_139{background:#ffffff0d;padding:.4rem 1rem;border-radius:var(--radius-full);font-size:var(--font-size-sm);color:var(--text-secondary);border:1px solid var(--border-primary);transition:all var(--transition-fast);font-weight:500}._genre_1287q_139:hover{background:var(--accent);border-color:var(--accent);color:var(--accent-text);transform:translateY(-2px)}._synopsisSection_1287q_165{border-top:1px solid var(--border-primary);padding-top:var(--space-6)}._sectionTitleSmall_1287q_170{font-size:var(--font-size-sm);text-transform:uppercase;letter-spacing:.1em;color:var(--text-tertiary);margin-bottom:var(--space-3)}._description_1287q_178{font-size:var(--font-size-base);color:var(--text-secondary);line-height:1.7;max-width:800px}._actions_1287q_186{display:flex;gap:var(--space-4);margin-top:auto}._watchBtn_1287q_192{display:inline-flex;align-items:center;gap:var(--space-3);background:linear-gradient(135deg,var(--accent) 0%,var(--accent-dark) 100%);color:var(--accent-text);padding:.8rem 1.8rem;border-radius:var(--radius-md);font-weight:600;font-size:var(--font-size-sm);border:none;cursor:pointer;transition:all var(--transition-base);box-shadow:0 4px 15px var(--accent-glow)}._watchBtn_1287q_192:hover{transform:translateY(-2px);box-shadow:0 8px 25px var(--accent-glow);opacity:.95}._watchlistBtn_1287q_214{display:inline-flex;align-items:center;gap:var(--space-3);background:#ffffff0d;color:var(--text-primary);border:1px solid var(--border-secondary);padding:.8rem 1.8rem;border-radius:var(--radius-md);font-weight:600;font-size:var(--font-size-sm);cursor:pointer;transition:all var(--transition-base)}._watchlistBtn_1287q_214:hover{background:#ffffff1a;border-color:var(--text-secondary)}._watchlistBtn_1287q_214._active_1287q_234{background:color-mix(in srgb,var(--color-success) 10%,transparent);border-color:var(--color-success);color:var(--color-success)}._detailsSection_1287q_241{max-width:1200px;margin:0 auto var(--space-16);padding:0 var(--space-6)}._detailsToggleBtn_1287q_247{display:flex;align-items:center;justify-content:center;gap:var(--space-3);width:100%;padding:var(--space-4);background:var(--bg-secondary);color:var(--text-secondary);border:1px solid var(--border-primary);border-radius:var(--radius-lg);font-weight:600;cursor:pointer;transition:all var(--transition-base);margin-bottom:var(--space-6)}._detailsToggleBtn_1287q_247:hover{background:var(--bg-tertiary);color:var(--text-primary);border-color:var(--border-secondary)}._expandedContent_1287q_270{animation:_fadeIn_1287q_1 .5s var(--ease-smooth)}._detailsGridContainer_1287q_274{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:var(--space-6);padding:var(--space-8);background:var(--bg-secondary);border-radius:var(--radius-xl);border:1px solid var(--border-primary)}._detailItem_1287q_284{display:flex;flex-direction:column;gap:var(--space-1)}._detailItem_1287q_284 strong{font-size:.7rem;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.1em}._detailItem_1287q_284 span{font-size:var(--font-size-sm);color:var(--text-primary);font-weight:500}._airingValue_1287q_303{color:var(--accent-light)!important}._loadingDetails_1287q_308{display:flex;flex-direction:column;align-items:center;gap:var(--space-4);padding:var(--space-12);color:var(--text-tertiary)}._spinner_1287q_317{width:30px;height:30px;border:3px solid rgba(255,255,255,.1);border-top-color:var(--accent);border-radius:50%;animation:_spin_1287q_317 .8s linear infinite}@keyframes _spin_1287q_317{to{transform:rotate(360deg)}}._heroSkeleton_1287q_332{width:100%}._skeletonBanner_1287q_336,._skeletonPoster_1287q_337,._skeletonTitle_1287q_338,._skeletonMeta_1287q_339,._skeletonDesc_1287q_340,._skeletonActions_1287q_341{position:relative;overflow:hidden;background:var(--bg-tertiary)}._skeletonBanner_1287q_336:after,._skeletonPoster_1287q_337:after,._skeletonTitle_1287q_338:after,._skeletonMeta_1287q_339:after,._skeletonDesc_1287q_340:after,._skeletonActions_1287q_341:after{content:"";position:absolute;inset:0;transform:translate(-100%);background-image:linear-gradient(90deg,#fff0 0,#ffffff0d 20%,#ffffff1f 60%,#fff0);animation:_skeleton-wave_1287q_1 1.8s infinite ease-in-out}._skeletonBanner_1287q_336{height:400px}._skeletonContent_1287q_374{max-width:1200px;margin:-100px auto 0;padding:0 var(--space-6);display:grid;grid-template-columns:320px 1fr;gap:var(--space-10)}._skeletonPoster_1287q_337{height:480px;border-radius:var(--radius-lg)}._skeletonInfo_1287q_388{background:var(--bg-secondary);border-radius:var(--radius-xl);padding:var(--space-8);display:flex;flex-direction:column;gap:var(--space-6)}._skeletonTitle_1287q_338{height:40px;width:60%;border-radius:var(--radius-sm)}._skeletonMeta_1287q_339{height:24px;width:40%;border-radius:var(--radius-sm)}._skeletonDesc_1287q_340{height:160px;width:100%;border-radius:var(--radius-sm)}._skeletonActions_1287q_341{height:50px;width:50%;border-radius:var(--radius-sm)}@keyframes _floatIn_1287q_1{0%{opacity:0;transform:translateY(30px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes _slideUpIn_1287q_1{0%{opacity:0;transform:translateY(50px)}to{opacity:1;transform:translateY(0)}}@keyframes _fadeIn_1287q_1{0%{opacity:0}to{opacity:1}}@media(max-width:1024px){._heroContent_1287q_49{grid-template-columns:1fr;padding-top:var(--space-12)}._posterContainer_1287q_62{width:220px;margin:0 auto;position:relative;top:0}._infoGlass_1287q_86{margin-top:-40px;padding-top:var(--space-12);text-align:center}._quickMeta_1287q_109,._genres_1287q_139{justify-content:center}._actions_1287q_186{flex-direction:column}._watchBtn_1287q_192,._watchlistBtn_1287q_214{width:100%;justify-content:center}._skeletonContent_1287q_374{grid-template-columns:1fr}._skeletonPoster_1287q_337{width:220px;height:330px;margin:0 auto}}@media(max-width:768px){._heroSection_1287q_11{padding-bottom:var(--space-8)}._heroContent_1287q_49{grid-template-columns:1fr;gap:var(--space-6);padding:var(--space-12) var(--space-4) 0}._posterContainer_1287q_62{position:relative;top:0;max-width:240px;margin:0 auto;margin-bottom:var(--space-4);animation:none}._infoGlass_1287q_86{padding:var(--space-6);animation:none}}@media(max-width:480px){._infoGlass_1287q_86{padding:var(--space-6);animation:none}._title_1287q_100{font-size:1.5rem}._quickMeta_1287q_109{gap:var(--space-3)}._metaItem_1287q_117 span{font-size:.75rem}}
@@ -1 +0,0 @@
1
- import{o as C,a as I,d as S,h as p,T,u as e}from"./vendor-core-DfaOB3Rn.js";import{I as s}from"./vendor-icons-DrybRNxP.js";import{u as b}from"./useAnimeInfoData-BqAd5seW.js";import{d as B,e as w,f as d,s as M,M as x,B as u}from"./index-DNxWyfmM.js";import{A}from"./AnimeMetaDetails-BogOi_bM.js";import{S as D}from"./SynopsisText-B3Sa5pRv.js";import{Q as G}from"./QueueOptionsButton-DjcdOJgg.js";import"./vendor-query-BBT5_sHx.js";import"./useIsMobile-Dvx1uJ82.js";import"./vendor-ui-3qrARCPr.js";const P="_container_1287q_1",W="_heroSection_1287q_11",O="_bannerContainer_1287q_17",$="_banner_1287q_17",U="_bannerOverlay_1287q_37",j="_heroContent_1287q_49",z="_posterContainer_1287q_62",V="_floatIn_1287q_1",Q="_poster_1287q_62",E="_infoGlass_1287q_86",H="_slideUpIn_1287q_1",F="_title_1287q_100",J="_quickMeta_1287q_109",K="_metaItem_1287q_117",L="_iconStar_1287q_126",R="_iconTv_1287q_129",X="_iconType_1287q_132",Y="_iconClock_1287q_135",Z="_genres_1287q_139",ee="_genre_1287q_139",ne="_synopsisSection_1287q_165",te="_sectionTitleSmall_1287q_170",se="_description_1287q_178",ae="_actions_1287q_186",ie="_watchBtn_1287q_192",oe="_watchlistBtn_1287q_214",le="_active_1287q_234",ce="_detailsSection_1287q_241",re="_detailsToggleBtn_1287q_247",de="_expandedContent_1287q_270",_e="_fadeIn_1287q_1",me="_detailsGridContainer_1287q_274",he="_detailItem_1287q_284",pe="_airingValue_1287q_303",ue="_loadingDetails_1287q_308",ve="_spinner_1287q_317",ge="_spin_1287q_317",ke="_heroSkeleton_1287q_332",qe="_skeletonBanner_1287q_336",fe="_skeletonPoster_1287q_337",Ne="_skeletonTitle_1287q_338",ye="_skeletonMeta_1287q_339",Ce="_skeletonDesc_1287q_340",Ie="_skeletonActions_1287q_341",Se="_skeletonContent_1287q_374",Te="_skeletonInfo_1287q_388",n={container:P,heroSection:W,bannerContainer:O,banner:$,bannerOverlay:U,heroContent:j,posterContainer:z,floatIn:V,poster:Q,infoGlass:E,slideUpIn:H,title:F,quickMeta:J,metaItem:K,iconStar:L,iconTv:R,iconType:X,iconClock:Y,genres:Z,genre:ee,synopsisSection:ne,sectionTitleSmall:te,description:se,actions:ae,watchBtn:ie,watchlistBtn:oe,active:le,detailsSection:ce,detailsToggleBtn:re,expandedContent:de,fadeIn:_e,detailsGridContainer:me,detailItem:he,airingValue:pe,loadingDetails:ue,spinner:ve,spin:ge,heroSkeleton:ke,skeletonBanner:qe,skeletonPoster:fe,skeletonTitle:Ne,skeletonMeta:ye,skeletonDesc:Ce,skeletonActions:Ie,"skeleton-wave":"_skeleton-wave_1287q_1",skeletonContent:Se,skeletonInfo:Te};function Oe(){const{id:a}=C(),i=I(),{titlePreference:l}=B(),[o,v]=S(!1),{showMeta:t,loadingMeta:g,toggleWatchlist:k,inWatchlist:c}=b(a),{hasConsent:q,grant:f}=w();p(()=>{a&&t?.id&&t.id!==a&&i(`/anime/${t.id}`,{replace:!0})},[a,t,i]),p(()=>{document.title=t?.name?`${t.name} - dango`:"Anime - dango"},[t?.name]);const N=()=>t?.name?l==="name"?t.name:l==="nativeName"?t.names?.native||t.name:l==="englishName"&&t.names?.english||t.name:"",y=()=>{a&&i(`/watch/${a}`)},_=T(()=>t?.bannerImage?d(t.bannerImage):t?.thumbnail?d(t.thumbnail,1200,450):"",[t?.bannerImage,t?.thumbnail]);if(g||!t?.name)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})]})]})]})});const m=t.isAdult===!0&&!q;return e("div",{className:n.container,style:m?{filter:"blur(14px)",pointerEvents:"none",userSelect:"none"}:void 0,children:[e("div",{className:n.heroSection,children:[e("div",{className:n.bannerContainer,children:[e("div",{className:n.banner,style:_?{backgroundImage:`url(${_})`}:void 0}),e("div",{className:n.bannerOverlay})]}),e("div",{className:n.heroContent,children:[e("div",{className:n.posterContainer,children:e("img",{src:d(t.thumbnail||"",320,480),alt:t.name,className:n.poster,decoding:"async"})}),e("div",{className:n.infoGlass,children:[e("div",{className:n.topInfo,children:[e("h1",{className:n.title,children:N()}),e("div",{className:n.quickMeta,children:[t.score&&e("div",{className:n.metaItem,children:[e(s,{name:"star",className:n.iconStar}),e("span",{children:t.score})]}),t.status&&e("div",{className:n.metaItem,children:[e(s,{name:"tv",className:n.iconTv}),e("span",{children:t.status})]}),t.type&&e("div",{className:n.metaItem,children:[e(s,{name:"layer-group",className:n.iconType}),e("span",{children:t.type})]})]}),Array.isArray(t.genres)&&t.genres.length>0&&e("div",{className:n.genres,children:t.genres.filter(Boolean).slice(0,5).map(r=>{const h=typeof r=="string"?r:r?.name;return e("span",{className:n.genre,children:h},h)})})]}),e("div",{className:n.synopsisSection,children:[e("h2",{className:n.sectionTitleSmall,children:"Synopsis"}),e(D,{text:M(t.description),emptyText:"No description available."})]}),e("div",{className:n.actions,children:[e("button",{className:n.watchBtn,onClick:y,children:[e(s,{name:"play",size:14}),"Start Watching"]}),e("button",{className:`${n.watchlistBtn} ${c?n.active:""}`,onClick:k,children:[c?e(s,{name:"check",size:14}):e(s,{name:"plus",size:14}),c?"In Watchlist":"Add to Watchlist"]}),e(G,{showId:a,showName:t.name||t.names?.romaji,showThumbnail:t.thumbnail,nativeName:t.names?.native,englishName:t.names?.english,showType:t.type,className:n.watchlistBtn,activeClassName:n.active})]})]})]})]}),e("div",{className:n.detailsSection,children:[e("button",{className:n.detailsToggleBtn,onClick:()=>{v(!o)},children:[o?e(s,{name:"chevron-up"}):e(s,{name:"chevron-down"}),o?"Hide Details":"Show Details"]}),o&&e("div",{className:n.expandedContent,children:e(A,{showMeta:t,styles:n})})]}),m&&e(x,{isOpen:!0,title:"Content Warning",onClose:()=>i("/"),children:e("div",{style:{padding:"1rem",textAlign:"center"},children:[e("p",{children:"This title contains mature content intended for adult audiences."}),e("p",{children:["By proceeding, you confirm that you are ",e("strong",{children:"18 years of age or older"})," (or the age of majority in your jurisdiction) and wish to view this content."]}),e("div",{style:{marginTop:"1rem",display:"flex",gap:"10px",justifyContent:"center"},children:[e(u,{variant:"secondary",onClick:()=>i("/"),children:"Go Back"}),e(u,{onClick:f,children:"I'm 18+, Continue"})]})]})})]})}export{Oe as default};