@serifpersia/dango 3.6.0 → 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 (75) hide show
  1. package/README.md +45 -13
  2. package/client/dist/assets/{AnimeCard-CEDL_2lC.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-a1-1F_la.js → AnimeInfoPage-DSybdvf_.js} +2 -2
  6. package/client/dist/assets/{Asmr-CCMuiaoR.js → Asmr-DFFV-7y4.js} +1 -1
  7. package/client/dist/assets/{AsmrResetProgressModal-CiwgOhH2.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-BmTp0Dx7.js → Home-DjGl-3os.js} +1 -1
  12. package/client/dist/assets/{Insights-C89oz_3z.js → Insights-4O52Z1t2.js} +1 -1
  13. package/client/dist/assets/{LibraryListPage-DOSPLTiR.js → LibraryListPage-Z0w_rmHP.js} +1 -1
  14. package/client/dist/assets/{ListeningList-IHSyufXX.js → ListeningList-DjbzDs1E.js} +1 -1
  15. package/client/dist/assets/{Manga-H4hG-3K8.js → Manga-BRIDluzF.js} +1 -1
  16. package/client/dist/assets/{MangaInfoPage-Bjz2NwLc.js → MangaInfoPage-Q4CjEGJH.js} +1 -1
  17. package/client/dist/assets/{MangaReadPage-DZakUml0.js → MangaReadPage-BbJK5FY6.js} +1 -1
  18. package/client/dist/assets/{MangaResetProgressModal-kbpad7Vl.js → MangaResetProgressModal-BCFPXDF6.js} +1 -1
  19. package/client/dist/assets/{Mature-DfODnRR8.js → Mature-DjQzs66p.js} +1 -1
  20. package/client/dist/assets/{MediaCard-fN3GQyTJ.js → MediaCard-DedwE5DX.js} +1 -1
  21. package/client/dist/assets/{Music-CFVwJyIo.js → Music-z2RkiMDf.js} +1 -1
  22. package/client/dist/assets/{OptionListMenu-BjoortST.js → OptionListMenu-CetjZizt.js} +1 -1
  23. package/client/dist/assets/Player-DCB994_8.css +1 -0
  24. package/client/dist/assets/{Player-DMeWl-5s.js → Player-DD-9SgWU.js} +6 -6
  25. package/client/dist/assets/PlayerSettings-BXGe3F5k.css +1 -0
  26. package/client/dist/assets/{PlayerSettings-DaG98x1K.js → PlayerSettings-ne_DQSTl.js} +1 -1
  27. package/client/dist/assets/{QueueOptionsButton-MpSKva6y.js → QueueOptionsButton-CIKT4YcD.js} +1 -1
  28. package/client/dist/assets/{QueueRail-CtLxXvR_.js → QueueRail-DPclldS0.js} +1 -1
  29. package/client/dist/assets/{Radio-D1zoU38z.js → Radio-aeqPTMht.js} +1 -1
  30. package/client/dist/assets/{ReadingList-C_oRyOHJ.js → ReadingList-p6G7NHtC.js} +1 -1
  31. package/client/dist/assets/{ResetProgressModal-CpbOV9Sk.js → ResetProgressModal-B7UuuL3X.js} +1 -1
  32. package/client/dist/assets/{Search-Cs8U1ZGO.js → Search-BzyHVByR.js} +1 -1
  33. package/client/dist/assets/Settings-DMmtLUsL.js +21 -0
  34. package/client/dist/assets/{SkeletonGrid-gCly-9x7.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-CfYJPE-C.js → TvInfo-DmrBLjgK.js} +1 -1
  39. package/client/dist/assets/{TvPopup-BBIe0fHF.js → TvPopup-D1mSlOZt.js} +1 -1
  40. package/client/dist/assets/{TvSearch-Bfp_r265.js → TvSearch-BGQRUq9E.js} +1 -1
  41. package/client/dist/assets/{TvWatchlist-DNcVUBXZ.js → TvWatchlist-DdLkpeQT.js} +1 -1
  42. package/client/dist/assets/{Watchlist-DnC7uDc4.js → Watchlist-BObmM6QB.js} +1 -1
  43. package/client/dist/assets/{hls-B9wsDt6U.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-Dpkjj68s.js → useAnimeInfoData-CSnwUBuU.js} +1 -1
  47. package/client/dist/assets/{useAsmr-QqLyjBbR.js → useAsmr-BKAaWEXn.js} +1 -1
  48. package/client/dist/assets/{useAsmrPopup-CnYAAhDj.js → useAsmrPopup-DDLRBLzz.js} +1 -1
  49. package/client/dist/assets/{useMangaLibrary-CxRsa2lr.js → useMangaLibrary-C6XEMuSr.js} +1 -1
  50. package/client/dist/assets/{useMangaPopup-CXnu2h4Y.js → useMangaPopup-wfCJubPD.js} +1 -1
  51. package/client/dist/assets/{useProviders-DDPMV3HX.js → useProviders-C7jrBgxf.js} +1 -1
  52. package/client/dist/assets/{useTv-BkZAFGaD.js → useTv-DM5KtzEc.js} +1 -1
  53. package/client/dist/assets/{useTvLibrary-CL3kMD_c.js → useTvLibrary-73NkS_5R.js} +1 -1
  54. package/client/dist/index.html +2 -2
  55. package/client/dist/repo_logo.svg +19 -39
  56. package/orchestrator.js +107 -8
  57. package/package.json +2 -2
  58. package/server/dist/app-hono.js +13 -8
  59. package/server/dist/config.js +3 -2
  60. package/server/dist/hono/auth.js +0 -7
  61. package/server/dist/trpc/routers/auth.js +16 -0
  62. package/server/package.json +1 -1
  63. package/client/dist/assets/AnimeInfo-BFWtHlPC.css +0 -1
  64. package/client/dist/assets/AnimeInfo-mVGUoF9q.js +0 -1
  65. package/client/dist/assets/AvSyncCalibrator-PqA6B5Ey.js +0 -10
  66. package/client/dist/assets/AvSyncCalibrator-ieaRTs3u.css +0 -1
  67. package/client/dist/assets/Home-B_q2l74h.css +0 -1
  68. package/client/dist/assets/Player-DBLl-bj_.css +0 -1
  69. package/client/dist/assets/PlayerSettings-Bj6SsmQ2.css +0 -1
  70. package/client/dist/assets/Settings-BgcOeTlE.js +0 -21
  71. package/client/dist/assets/Trackers-DoHHWI2D.js +0 -2
  72. package/client/dist/assets/Tv-BlVIanQL.css +0 -1
  73. package/client/dist/assets/Tv-DhLdh3WF.js +0 -4
  74. package/client/dist/assets/index-C6HMOCqo.css +0 -1
  75. package/client/dist/assets/index-CfgPGaUO.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-CfgPGaUO.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-CxRsa2lr.js";import{d as I}from"./index-CfgPGaUO.js";import{p as s,a as k}from"./MediaCard-fN3GQyTJ.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-CfgPGaUO.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-fN3GQyTJ.js";import{T as g}from"./TvPopup-BBIe0fHF.js";import{c as m,i as f}from"./useTvLibrary-CL3kMD_c.js";import{b as i}from"./vendor-query-BBT5_sHx.js";import{h as p}from"./index-CfgPGaUO.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-CfgPGaUO.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-CfgPGaUO.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-C6HMOCqo.css">
40
+ <link rel="stylesheet" crossorigin href="/assets/index-D0Haw_Zl.css">
41
41
  </head>
42
42
 
43
43
  <body>
@@ -1,53 +1,33 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="48.6" height="14" viewBox="-2.8 -2 48.6 14">
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="38.4" height="13.3" viewBox="-11.85 -0.8 38.4 13.3">
2
2
  <path
3
- fill="none"
4
- stroke="#d9c6a5"
5
- stroke-width="1.1"
6
- stroke-linecap="round"
7
- d="M -2,5.1 H 45" />
8
- <g transform="translate(0 0.5)">
3
+ fill="#e1afef"
4
+ stroke="#a978a9"
5
+ stroke-width="0.9"
6
+ stroke-linejoin="round"
7
+ paint-order="stroke fill"
8
+ d="M 7.0022839,0 C 3.0649855,0 -0.09802047,2.4883888 0.0022839,6 c 0.13572675,4.751733 5.0802847,4.156395 7,4.156395 1.2538994,0 6.5304511,0.392468 6.5849461,-4.168088 C 13.62431,2.8853946 10.939582,0 7.0022839,0 Z" />
9
+ <path fill="#140f15" d="m 4.9623825,3.416 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
10
+ <path fill="#140f15" d="M 8.588001,3.416 C 8.0021121,3.416 7.9359718,5.7528563 8.563236,5.7528563 9.2237319,5.7528563 9.2337013,3.416 8.588001,3.416 Z" />
11
+ <g transform="translate(12.231148 1.5056648)">
9
12
  <path
10
- fill="#897cff"
11
- stroke="#5646db"
12
- stroke-width="0.9"
13
- stroke-linejoin="round"
14
- paint-order="stroke fill"
15
- d="m 7,0 c -3.9372984,0 -7.10030437,2.4883888 -7,6 0.13572675,4.751733 5.0802847,4.156395 7,4.156395 1.2538994,0 6.530451,0.392468 6.584946,-4.168088 C 13.622023,2.8853946 10.937298,0 7,0 Z" />
16
- <path
17
- fill="#140f15"
18
- d="m 4.9623825,3.416 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
19
- <path
20
- fill="#140f15"
21
- d="M 8.588001,3.416 C 8.0021121,3.416 7.9359718,5.7528563 8.563236,5.7528563 9.2237319,5.7528563 9.2337013,3.416 8.588001,3.416 Z" />
22
- </g>
23
- <g transform="translate(15 -0.9)">
24
- <path
25
- fill="#e1afef"
26
- stroke="#a978a9"
13
+ fill="#e3e1ee"
14
+ stroke="#b3b1c6"
27
15
  stroke-width="0.9"
28
16
  stroke-linejoin="round"
29
17
  paint-order="stroke fill"
30
18
  d="m 7,0 c -3.9372984,0 -7.10030437,2.4883888 -7,6 0.13572675,4.751733 5.0802847,4.156395 7,4.156395 1.2538994,0 6.530451,0.392468 6.584946,-4.168088 C 13.622023,2.8853946 10.937298,0 7,0 Z" />
31
- <path
32
- fill="#140f15"
33
- d="m 4.9623825,3.416 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
34
- <path
35
- fill="#140f15"
36
- d="M 8.588001,3.416 C 8.0021121,3.416 7.9359718,5.7528563 8.563236,5.7528563 9.2237319,5.7528563 9.2337013,3.416 8.588001,3.416 Z" />
19
+ <path fill="#140f15" d="m 3.3556746,2.945744 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
20
+ <path fill="#140f15" d="m 6.9812931,2.945744 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
37
21
  </g>
38
- <g transform="translate(30 0.3)">
22
+ <g transform="translate(-11.063909 1.423053)">
39
23
  <path
40
- fill="#e3e1ee"
41
- stroke="#b3b1c6"
24
+ fill="#897cff"
25
+ stroke="#5646db"
42
26
  stroke-width="0.9"
43
27
  stroke-linejoin="round"
44
28
  paint-order="stroke fill"
45
29
  d="m 7,0 c -3.9372984,0 -7.10030437,2.4883888 -7,6 0.13572675,4.751733 5.0802847,4.156395 7,4.156395 1.2538994,0 6.530451,0.392468 6.584946,-4.168088 C 13.622023,2.8853946 10.937298,0 7,0 Z" />
46
- <path
47
- fill="#140f15"
48
- d="m 4.9623825,3.416 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
49
- <path
50
- fill="#140f15"
51
- d="M 8.588001,3.416 C 8.0021121,3.416 7.9359718,5.7528563 8.563236,5.7528563 9.2237319,5.7528563 9.2337013,3.416 8.588001,3.416 Z" />
30
+ <path fill="#140f15" d="m 7.3136624,3.376812 c -0.5858889,0 -0.6520292,2.3368563 -0.024765,2.3368563 0.6604959,0 0.6704653,-2.3368563 0.024765,-2.3368563 z" />
31
+ <path fill="#140f15" d="m 10.939281,3.376812 c -0.585889,0 -0.652029,2.3368563 -0.02476,2.3368563 0.660496,0 0.670465,-2.3368563 0.02476,-2.3368563 z" />
52
32
  </g>
53
33
  </svg>
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.6.0",
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-14T16:07:34.273Z"
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.6.0",
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-Dpkjj68s.js";import{d as B,e as w,f as d,s as M,M as x,B as u}from"./index-CfgPGaUO.js";import{A}from"./AnimeMetaDetails-BogOi_bM.js";import{S as D}from"./SynopsisText-B3Sa5pRv.js";import{Q as G}from"./QueueOptionsButton-MpSKva6y.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};