cyreader 0.1.1 → 0.1.2

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 (58) hide show
  1. package/bundle/server/dist/config/paths.js +3 -0
  2. package/bundle/server/dist/library/cache.js +70 -0
  3. package/bundle/server/dist/library/scan.js +54 -8
  4. package/bundle/server/dist/library/scan.test.js +99 -18
  5. package/bundle/server/dist/library/service.js +5 -1
  6. package/bundle/server/dist/library/service.test.js +16 -1
  7. package/bundle/server/dist/reading/progress/merge.js +5 -4
  8. package/bundle/server/dist/reading/progress/schema.js +39 -3
  9. package/bundle/server/dist/reading/progress/schema.test.js +36 -3
  10. package/bundle/server/dist/reading/progress/service.js +2 -3
  11. package/bundle/server/dist/reading/progress/service.test.js +10 -9
  12. package/bundle/server/dist/routes/library.test.js +8 -1
  13. package/bundle/web/dist/assets/_shell-Bm2pxAQP.js +5 -0
  14. package/bundle/web/dist/assets/_shell-Cij8gMSv.js +1 -0
  15. package/bundle/web/dist/assets/comic._id-Djtr8diE.js +1 -0
  16. package/bundle/web/dist/assets/dist-DzLEGVNH.js +1 -0
  17. package/bundle/web/dist/assets/dist-QfKKfHSL.js +1 -0
  18. package/bundle/web/dist/assets/index-BHhqsr5H.js +10 -0
  19. package/bundle/web/dist/assets/index-D9hL3zrL.css +2 -0
  20. package/bundle/web/dist/assets/library-D_1sil_O.js +1 -0
  21. package/bundle/web/dist/assets/library-utils-BRrejTkM.js +1 -0
  22. package/bundle/web/dist/assets/mutation-ChAIwNv3.js +1 -0
  23. package/bundle/web/dist/assets/novel._id-C62VYvcl.js +4 -0
  24. package/bundle/web/dist/assets/query-keys-CbbgiZx4.js +1 -0
  25. package/bundle/web/dist/assets/reading-BozmJNi1.js +1 -0
  26. package/bundle/web/dist/assets/reading-progress-C5bkK-vF.js +1 -0
  27. package/bundle/web/dist/assets/save-reading-progress-D231ROaQ.js +1 -0
  28. package/bundle/web/dist/assets/scroll-area-CyEO8R_G.js +1 -0
  29. package/bundle/web/dist/assets/{settings-2-CCv0KiQI.js → settings-2-8mnAuSax.js} +1 -1
  30. package/bundle/web/dist/assets/settings-BRi0XyRg.js +1 -0
  31. package/bundle/web/dist/assets/shell-context-Buw4m44t.js +41 -0
  32. package/bundle/web/dist/assets/use-library-Bh7Bunn1.js +1 -0
  33. package/bundle/web/dist/assets/{useNavigate-BMyovDLu.js → useNavigate-B29ssGbr.js} +1 -1
  34. package/bundle/web/dist/assets/useRouterState-4dM5FKiy.js +1 -0
  35. package/bundle/web/dist/assets/utils-ChkMmPzE.js +1 -0
  36. package/bundle/web/dist/index.html +5 -5
  37. package/package.json +2 -2
  38. package/bundle/server/dist/app.test.js +0 -9
  39. package/bundle/web/dist/assets/_shell-Co1KI-wo.js +0 -5
  40. package/bundle/web/dist/assets/_shell-bNqNRnHj.js +0 -1
  41. package/bundle/web/dist/assets/comic._id-CC6qdNbU.js +0 -1
  42. package/bundle/web/dist/assets/dist-CqonX7c8.js +0 -1
  43. package/bundle/web/dist/assets/image-BZKAkGUy.js +0 -1
  44. package/bundle/web/dist/assets/index-BQZoypuf.css +0 -2
  45. package/bundle/web/dist/assets/index-Pdit8x1d.js +0 -10
  46. package/bundle/web/dist/assets/input-tgPw9P7N.js +0 -41
  47. package/bundle/web/dist/assets/library-g-QZ29Jj.js +0 -1
  48. package/bundle/web/dist/assets/mutation-CwzbY9ri.js +0 -1
  49. package/bundle/web/dist/assets/novel._id-ByrQLxAT.js +0 -4
  50. package/bundle/web/dist/assets/query-keys-CDsPIOEO.js +0 -1
  51. package/bundle/web/dist/assets/reading-BseNE7P3.js +0 -1
  52. package/bundle/web/dist/assets/reading-progress-BcmbUd_d.js +0 -1
  53. package/bundle/web/dist/assets/save-reading-progress-yvAw7ZNh.js +0 -1
  54. package/bundle/web/dist/assets/scroll-area-awhNOWo3.js +0 -1
  55. package/bundle/web/dist/assets/settings-DmjzIwkt.js +0 -1
  56. package/bundle/web/dist/assets/shell-context-BT0BT8PF.js +0 -1
  57. package/bundle/web/dist/assets/toggle-group-CLpSuWfq.js +0 -1
  58. package/bundle/web/dist/assets/utils-BmM72imW.js +0 -1
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
5
  import { NotFoundError } from '../../library/errors.js';
6
6
  import { LibraryService } from '../../library/service.js';
7
+ import { writeTestImage } from '../../library/test-images.js';
7
8
  import { ProgressService } from './service.js';
8
9
  import { readProgressStoreFromDisk } from './storage.js';
9
10
  describe('ProgressService', () => {
@@ -26,9 +27,9 @@ describe('ProgressService', () => {
26
27
  await mkdir(novelRoot);
27
28
  await mkdir(mangaDir, { recursive: true });
28
29
  await writeFile(path.join(novelRoot, 'book.txt'), 'line one\n\nline two');
29
- await writeFile(path.join(mangaDir, '1.jpg'), '');
30
- await writeFile(path.join(mangaDir, '2.jpg'), '');
31
- await writeFile(path.join(mangaDir, '3.jpg'), '');
30
+ await writeTestImage(path.join(mangaDir, '1.jpg'), 300, 400);
31
+ await writeTestImage(path.join(mangaDir, '2.jpg'), 300, 400);
32
+ await writeTestImage(path.join(mangaDir, '3.jpg'), 300, 400);
32
33
  libraryService = new LibraryService(() => ({
33
34
  novelDirectories: [{ id: 'novel-root', path: novelRoot }],
34
35
  comicDirectories: [{ id: 'comic-root', path: comicRoot }],
@@ -49,21 +50,21 @@ describe('ProgressService', () => {
49
50
  }
50
51
  await rm(tempDir, { recursive: true, force: true });
51
52
  });
52
- it('saves and reads comic progress with clamped page index', async () => {
53
+ it('saves and reads comic progress with clamped scroll ratio', async () => {
53
54
  const entry = await progressService.saveProgress(comicId, {
54
55
  type: 'comic',
55
- pageIndex: 99,
56
+ scrollRatio: 1.5,
56
57
  });
57
58
  expect(entry).toEqual({
58
59
  type: 'comic',
59
- pageIndex: 2,
60
+ scrollRatio: 1,
60
61
  updatedAt: expect.any(String),
61
62
  });
62
63
  const map = await progressService.getProgressMap();
63
64
  const comicProgress = map[comicId];
64
65
  expect(comicProgress?.type).toBe('comic');
65
- if (comicProgress?.type === 'comic') {
66
- expect(comicProgress.pageIndex).toBe(2);
66
+ if (comicProgress?.type === 'comic' && 'scrollRatio' in comicProgress) {
67
+ expect(comicProgress.scrollRatio).toBe(1);
67
68
  }
68
69
  });
69
70
  it('saves novel progress', async () => {
@@ -83,7 +84,7 @@ describe('ProgressService', () => {
83
84
  await expect(progressService.saveProgress('missing', { type: 'novel', paragraphIndex: 0 })).rejects.toBeInstanceOf(NotFoundError);
84
85
  });
85
86
  it('throws when progress type mismatches item type', async () => {
86
- await expect(progressService.saveProgress(novelId, { type: 'comic', pageIndex: 0 })).rejects.toBeInstanceOf(TypeError);
87
+ await expect(progressService.saveProgress(novelId, { type: 'comic', scrollRatio: 0 })).rejects.toBeInstanceOf(TypeError);
87
88
  });
88
89
  it('prunes stale progress entries', async () => {
89
90
  await progressService.saveProgress(novelId, { type: 'novel', paragraphIndex: 1 });
@@ -59,12 +59,14 @@ describe('library routes', () => {
59
59
  id: expect.any(String),
60
60
  type: 'novel',
61
61
  title: 'book',
62
+ addedAt: expect.any(String),
62
63
  progress: null,
63
64
  },
64
65
  {
65
66
  id: expect.any(String),
66
67
  type: 'comic',
67
68
  title: 'manga',
69
+ addedAt: expect.any(String),
68
70
  cover: expect.stringMatching(/^\/static\/comic-root\/manga\/cover\.jpg$/),
69
71
  pageCount: 2,
70
72
  progress: null,
@@ -80,6 +82,7 @@ describe('library routes', () => {
80
82
  id: novel.id,
81
83
  type: 'novel',
82
84
  title: 'book',
85
+ addedAt: expect.any(String),
83
86
  directoryId: 'novel-root',
84
87
  filename: 'book.txt',
85
88
  progress: null,
@@ -102,8 +105,12 @@ describe('library routes', () => {
102
105
  id: comic.id,
103
106
  type: 'comic',
104
107
  title: 'manga',
108
+ addedAt: expect.any(String),
105
109
  directoryId: 'comic-root',
106
- pages: ['1.jpg', '2.jpg'],
110
+ pages: [
111
+ { filename: '1.jpg', width: 300, height: 400 },
112
+ { filename: '2.jpg', width: 300, height: 400 },
113
+ ],
107
114
  progress: null,
108
115
  });
109
116
  });
@@ -0,0 +1,5 @@
1
+ import{Y as e,a as t,b as n,c as r,f as i,g as a,h as o,i as s,l as c,p as l,s as u,t as d,u as f,x as p}from"./utils-ChkMmPzE.js";import{a as m,i as h,r as g}from"./query-keys-CbbgiZx4.js";import{i as _,r as ee,t as te}from"./use-library-Bh7Bunn1.js";import{t as ne}from"./useNavigate-B29ssGbr.js";import{t as v}from"./useRouterState-4dM5FKiy.js";import{a as re,t as ie}from"./library-utils-BRrejTkM.js";import{a as ae,i as oe,o as se,s as ce,t as le}from"./shell-context-Buw4m44t.js";import{a as ue,f as de,i as fe,m as y,p as pe,r as me,v as he,y as ge}from"./index-BHhqsr5H.js";var _e=a(`bookmark`,[[`path`,{d:`M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z`,key:`oz39mx`}]]),ve=a(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]),ye=a(`circle-plus`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M8 12h8`,key:`1wcyev`}],[`path`,{d:`M12 8v8`,key:`napkw2`}]]),be=a(`layers`,[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]]),xe=a(`library`,[[`path`,{d:`m16 6 4 14`,key:`ji33uf`}],[`path`,{d:`M12 6v14`,key:`1n7gus`}],[`path`,{d:`M8 8v12`,key:`1gg7y9`}],[`path`,{d:`M4 4v16`,key:`6qkkli`}]]),Se=a(`settings`,[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),b=e(p(),1),x=n(),S=`Dialog`,[C,Ce]=c(S),[we,w]=C(S),T=e=>{let{__scopeDialog:n,children:r,open:i,defaultOpen:a,onOpenChange:o,modal:c=!0}=e,l=b.useRef(null),u=b.useRef(null),[d,f]=t({prop:i,defaultProp:a??!1,onChange:o,caller:S});return(0,x.jsx)(we,{scope:n,triggerRef:l,contentRef:u,contentId:s(),titleId:s(),descriptionId:s(),open:d,onOpenChange:f,onOpenToggle:b.useCallback(()=>f(e=>!e),[f]),modal:c,children:r})};T.displayName=S;var E=`DialogTrigger`,Te=b.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=w(E,n),a=o(t,i.triggerRef);return(0,x.jsx)(f.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.open?i.contentId:void 0,"data-state":V(i.open),...r,ref:a,onClick:u(e.onClick,i.onOpenToggle)})});Te.displayName=E;var D=`DialogPortal`,[Ee,O]=C(D,{forceMount:void 0}),k=e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=w(D,t);return(0,x.jsx)(Ee,{scope:t,forceMount:n,children:b.Children.map(r,e=>(0,x.jsx)(y,{present:n||a.open,children:(0,x.jsx)(de,{asChild:!0,container:i,children:e})}))})};k.displayName=D;var A=`DialogOverlay`,j=b.forwardRef((e,t)=>{let n=O(A,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=w(A,e.__scopeDialog);return a.modal?(0,x.jsx)(y,{present:r||a.open,children:(0,x.jsx)(Oe,{...i,ref:t})}):null});j.displayName=A;var De=l(`DialogOverlay.RemoveScroll`),Oe=b.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=w(A,n);return(0,x.jsx)(ae,{as:De,allowPinchZoom:!0,shards:[i.contentRef],children:(0,x.jsx)(f.div,{"data-state":V(i.open),...r,ref:t,style:{pointerEvents:`auto`,...r.style}})})}),M=`DialogContent`,N=b.forwardRef((e,t)=>{let n=O(M,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=w(M,e.__scopeDialog);return(0,x.jsx)(y,{present:r||a.open,children:a.modal?(0,x.jsx)(ke,{...i,ref:t}):(0,x.jsx)(Ae,{...i,ref:t})})});N.displayName=M;var ke=b.forwardRef((e,t)=>{let n=w(M,e.__scopeDialog),r=b.useRef(null),i=o(t,n.contentRef,r);return b.useEffect(()=>{let e=r.current;if(e)return oe(e)},[]),(0,x.jsx)(P,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:n.open,onCloseAutoFocus:u(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:u(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:u(e.onFocusOutside,e=>e.preventDefault())})}),Ae=b.forwardRef((e,t)=>{let n=w(M,e.__scopeDialog),r=b.useRef(!1),i=b.useRef(!1);return(0,x.jsx)(P,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),P=b.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,...s}=e,c=w(M,n),l=b.useRef(null),u=o(t,l);return se(),(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(ce,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,x.jsx)(pe,{role:`dialog`,id:c.contentId,"aria-describedby":c.descriptionId,"aria-labelledby":c.titleId,"data-state":V(c.open),...s,ref:u,onDismiss:()=>c.onOpenChange(!1)})}),(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Me,{titleId:c.titleId}),(0,x.jsx)(Pe,{contentRef:l,descriptionId:c.descriptionId})]})]})}),F=`DialogTitle`,I=b.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=w(F,n);return(0,x.jsx)(f.h2,{id:i.titleId,...r,ref:t})});I.displayName=F;var L=`DialogDescription`,R=b.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=w(L,n);return(0,x.jsx)(f.p,{id:i.descriptionId,...r,ref:t})});R.displayName=L;var z=`DialogClose`,B=b.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=w(z,n);return(0,x.jsx)(f.button,{type:`button`,...r,ref:t,onClick:u(e.onClick,()=>i.onOpenChange(!1))})});B.displayName=z;function V(e){return e?`open`:`closed`}var H=`DialogTitleWarning`,[je,U]=r(H,{contentName:M,titleName:F,docsSlug:`dialog`}),Me=({titleId:e})=>{let t=U(H),n=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
2
+
3
+ If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
4
+
5
+ For more information, see https://radix-ui.com/primitives/docs/components/${t.docsSlug}`;return b.useEffect(()=>{e&&(document.getElementById(e)||console.error(n))},[n,e]),null},Ne=`DialogDescriptionWarning`,Pe=({contentRef:e,descriptionId:t})=>{let n=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${U(Ne).contentName}}.`;return b.useEffect(()=>{let r=e.current?.getAttribute(`aria-describedby`);t&&r&&(document.getElementById(t)||console.warn(n))},[n,e,t]),null},Fe=T,Ie=k,Le=j,Re=N,ze=I,Be=R,Ve=B,W=768;function He(){let[e,t]=b.useState(void 0);return b.useEffect(()=>{let e=window.matchMedia(`(max-width: ${W-1}px)`),n=()=>{t(window.innerWidth<W)};return e.addEventListener(`change`,n),t(window.innerWidth<W),()=>e.removeEventListener(`change`,n)},[]),!!e}function Ue({...e}){return(0,x.jsx)(Fe,{"data-slot":`sheet`,...e})}function We({...e}){return(0,x.jsx)(Ie,{"data-slot":`sheet-portal`,...e})}function Ge({className:e,...t}){return(0,x.jsx)(Le,{"data-slot":`sheet-overlay`,className:d(`fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0`,e),...t})}function Ke({className:e,children:t,side:n=`right`,showCloseButton:r=!0,...i}){return(0,x.jsxs)(We,{children:[(0,x.jsx)(Ge,{}),(0,x.jsxs)(Re,{"data-slot":`sheet-content`,"data-side":n,className:d(`fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10`,e),...i,children:[t,r&&(0,x.jsx)(Ve,{"data-slot":`sheet-close`,asChild:!0,children:(0,x.jsxs)(h,{variant:`ghost`,className:`absolute top-3 right-3`,size:`icon-sm`,children:[(0,x.jsx)(re,{}),(0,x.jsx)(`span`,{className:`sr-only`,children:`Close`})]})})]})]})}function qe({className:e,...t}){return(0,x.jsx)(`div`,{"data-slot":`sheet-header`,className:d(`flex flex-col gap-0.5 p-4`,e),...t})}function Je({className:e,...t}){return(0,x.jsx)(ze,{"data-slot":`sheet-title`,className:d(`font-heading text-base font-medium text-foreground`,e),...t})}function Ye({className:e,...t}){return(0,x.jsx)(Be,{"data-slot":`sheet-description`,className:d(`text-sm text-muted-foreground`,e),...t})}var Xe=`sidebar_state`,Ze=3600*24*7,Qe=`16rem`,$e=`18rem`,et=`3rem`,tt=`b`,G=b.createContext(null);function K(){let e=b.useContext(G);if(!e)throw Error(`useSidebar must be used within a SidebarProvider.`);return e}function nt({defaultOpen:e=!0,open:t,onOpenChange:n,className:r,style:i,children:a,...o}){let s=He(),[c,l]=b.useState(!1),[u,f]=b.useState(e),p=t??u,m=b.useCallback(e=>{let t=typeof e==`function`?e(p):e;n?n(t):f(t),document.cookie=`${Xe}=${t}; path=/; max-age=${Ze}`},[n,p]),h=b.useCallback(()=>s?l(e=>!e):m(e=>!e),[s,m,l]);b.useEffect(()=>{let e=e=>{e.key===tt&&(e.metaKey||e.ctrlKey)&&(e.preventDefault(),h())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[h]);let g=p?`expanded`:`collapsed`,_=b.useMemo(()=>({state:g,open:p,setOpen:m,isMobile:s,openMobile:c,setOpenMobile:l,toggleSidebar:h}),[g,p,m,s,c,l,h]);return(0,x.jsx)(G.Provider,{value:_,children:(0,x.jsx)(`div`,{"data-slot":`sidebar-wrapper`,style:{"--sidebar-width":Qe,"--sidebar-width-icon":et,...i},className:d(`group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar`,r),...o,children:a})})}function rt({side:e=`left`,variant:t=`sidebar`,collapsible:n=`offcanvas`,className:r,children:i,dir:a,...o}){let{isMobile:s,state:c,openMobile:l,setOpenMobile:u}=K();return n===`none`?(0,x.jsx)(`div`,{"data-slot":`sidebar`,className:d(`flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground`,r),...o,children:i}):s?(0,x.jsx)(Ue,{open:l,onOpenChange:u,...o,children:(0,x.jsxs)(Ke,{dir:a,"data-sidebar":`sidebar`,"data-slot":`sidebar`,"data-mobile":`true`,className:`w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden`,style:{"--sidebar-width":$e},side:e,children:[(0,x.jsxs)(qe,{className:`sr-only`,children:[(0,x.jsx)(Je,{children:`Sidebar`}),(0,x.jsx)(Ye,{children:`Displays the mobile sidebar.`})]}),(0,x.jsx)(`div`,{className:`flex h-full w-full flex-col`,children:i})]})}):(0,x.jsxs)(`div`,{className:`group peer hidden text-sidebar-foreground md:block`,"data-state":c,"data-collapsible":c===`collapsed`?n:``,"data-variant":t,"data-side":e,"data-slot":`sidebar`,children:[(0,x.jsx)(`div`,{"data-slot":`sidebar-gap`,className:d(`relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear`,`group-data-[collapsible=offcanvas]:w-0`,`group-data-[side=right]:rotate-180`,t===`floating`||t===`inset`?`group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]`:`group-data-[collapsible=icon]:w-(--sidebar-width-icon)`)}),(0,x.jsx)(`div`,{"data-slot":`sidebar-container`,"data-side":e,className:d(`fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex`,t===`floating`||t===`inset`?`p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]`:`group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l`,r),...o,children:(0,x.jsx)(`div`,{"data-sidebar":`sidebar`,"data-slot":`sidebar-inner`,className:`flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border`,children:i})})]})}function it({className:e,...t}){return(0,x.jsx)(`main`,{"data-slot":`sidebar-inset`,className:d(`relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2`,e),...t})}function at({className:e,...t}){return(0,x.jsx)(`div`,{"data-slot":`sidebar-header`,"data-sidebar":`header`,className:d(`flex flex-col gap-2 p-2`,e),...t})}function ot({className:e,...t}){return(0,x.jsx)(`div`,{"data-slot":`sidebar-footer`,"data-sidebar":`footer`,className:d(`flex flex-col gap-2 p-2`,e),...t})}function st({className:e,...t}){return(0,x.jsx)(`div`,{"data-slot":`sidebar-content`,"data-sidebar":`content`,className:d(`no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden`,e),...t})}function q({className:e,...t}){return(0,x.jsx)(`div`,{"data-slot":`sidebar-group`,"data-sidebar":`group`,className:d(`relative flex w-full min-w-0 flex-col p-2`,e),...t})}function J({className:e,asChild:t=!1,...n}){return(0,x.jsx)(t?i:`div`,{"data-slot":`sidebar-group-label`,"data-sidebar":`group-label`,className:d(`flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0`,e),...n})}function Y({className:e,...t}){return(0,x.jsx)(`div`,{"data-slot":`sidebar-group-content`,"data-sidebar":`group-content`,className:d(`w-full text-sm`,e),...t})}function X({className:e,...t}){return(0,x.jsx)(`ul`,{"data-slot":`sidebar-menu`,"data-sidebar":`menu`,className:d(`flex w-full min-w-0 flex-col gap-0`,e),...t})}function Z({className:e,...t}){return(0,x.jsx)(`li`,{"data-slot":`sidebar-menu-item`,"data-sidebar":`menu-item`,className:d(`group/menu-item relative`,e),...t})}var ct=m(`peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate`,{variants:{variant:{default:`hover:bg-sidebar-accent hover:text-sidebar-accent-foreground`,outline:`bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]`},size:{default:`h-8 text-sm`,sm:`h-7 text-xs`,lg:`h-12 text-sm group-data-[collapsible=icon]:p-0!`}},defaultVariants:{variant:`default`,size:`default`}});function Q({asChild:e=!1,isActive:t=!1,variant:n=`default`,size:r=`default`,tooltip:a,className:o,...s}){let c=e?i:`button`,{isMobile:l,state:u}=K(),f=(0,x.jsx)(c,{"data-slot":`sidebar-menu-button`,"data-sidebar":`menu-button`,"data-size":r,"data-active":t,className:d(ct({variant:n,size:r}),o),...s});return a?(typeof a==`string`&&(a={children:a}),(0,x.jsxs)(me,{children:[(0,x.jsx)(ue,{asChild:!0,children:f}),(0,x.jsx)(fe,{side:`right`,align:`center`,hidden:u!==`collapsed`||l,...a})]})):f}function $(e,t){return e.filter(e=>e.type===t).length}function lt({items:e,activeFilter:t,onFilterChange:n}){let r=v({select:e=>e.location.pathname})===`/settings`,i=ie(e),a=[{id:`all`,label:`全部`,icon:be,count:e.length},{id:`novel`,label:`小说`,icon:_,count:$(e,`novel`)},{id:`comic`,label:`漫画`,icon:ee,count:$(e,`comic`)}],o=[{id:`reading`,label:`阅读中`,icon:_e,count:i.reading},{id:`unread`,label:`未开始`,icon:ye,count:i.unread},{id:`completed`,label:`已完成`,icon:ve,count:i.completed}],s=`h-9 text-[13px] text-[#9f9fad] hover:bg-[#1e1e24] hover:text-[#d5d5dd] data-[active=true]:bg-[#1e1e24] data-[active=true]:font-normal data-[active=true]:text-[#e2e2e8]`;return(0,x.jsxs)(rt,{collapsible:`none`,className:`w-[220px] shrink-0 border-r border-sidebar-border bg-sidebar`,children:[(0,x.jsx)(at,{className:`border-b border-sidebar-border px-[18px] py-3.5`,children:(0,x.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[(0,x.jsx)(`div`,{className:`flex size-7 items-center justify-center rounded-md bg-indigo-500`,children:(0,x.jsx)(xe,{className:`size-4 text-white`})}),(0,x.jsx)(`span`,{className:`text-[15px] font-bold tracking-wide text-[#f3f3f7]`,children:`CYReader`})]})}),(0,x.jsxs)(st,{className:`px-3 py-2`,children:[(0,x.jsxs)(q,{children:[(0,x.jsx)(J,{className:`px-2 text-[11px] font-semibold tracking-[0.8px] text-[#6b6b78] uppercase`,children:`书库`}),(0,x.jsx)(Y,{children:(0,x.jsx)(X,{className:`gap-1`,children:a.map(e=>(0,x.jsx)(Z,{children:(0,x.jsxs)(Q,{isActive:!r&&t===e.id,onClick:()=>n(e.id),className:s,children:[(0,x.jsx)(e.icon,{}),(0,x.jsx)(`span`,{children:e.label}),(0,x.jsx)(`span`,{className:`ml-auto text-[11px] font-medium text-[#6b6b78]`,children:e.count})]})},e.id))})})]}),(0,x.jsxs)(q,{children:[(0,x.jsx)(J,{className:`px-2 text-[11px] font-semibold tracking-[0.8px] text-[#6b6b78] uppercase`,children:`阅读状态`}),(0,x.jsx)(Y,{children:(0,x.jsx)(X,{className:`gap-1`,children:o.map(e=>(0,x.jsx)(Z,{children:(0,x.jsxs)(Q,{isActive:!r&&t===e.id,onClick:()=>n(e.id),className:s,children:[(0,x.jsx)(e.icon,{}),(0,x.jsx)(`span`,{children:e.label}),(0,x.jsx)(`span`,{className:`ml-auto text-[11px] font-medium text-[#6b6b78]`,children:e.count})]})},e.id))})})]})]}),(0,x.jsx)(ot,{className:`border-t border-sidebar-border px-3 py-2`,children:(0,x.jsx)(X,{children:(0,x.jsx)(Z,{children:(0,x.jsx)(Q,{asChild:!0,isActive:r,className:d(s,!r&&`text-[#6b6b78]`,r&&`bg-[#1e1e24] text-[#e2e2e8]`),children:(0,x.jsxs)(ge,{to:`/settings`,children:[(0,x.jsx)(Se,{}),(0,x.jsx)(`span`,{children:`设置`})]})})})})})]})}function ut(){let e=ne(),t=v({select:e=>e.location.pathname}),{state:n,loading:r,refresh:i}=te(),[a,o]=(0,b.useState)(`all`),s=n?.items??[];return(0,x.jsxs)(nt,{defaultOpen:!0,className:`h-screen overflow-hidden`,children:[(0,x.jsx)(lt,{items:s,activeFilter:a,onFilterChange:n=>{o(n),t!==`/`&&e({to:`/`})}}),(0,x.jsx)(it,{className:`min-w-0 overflow-hidden`,children:r&&t===`/`?(0,x.jsxs)(`div`,{className:`flex flex-col gap-3 p-5`,children:[(0,x.jsx)(g,{className:`h-10 w-full max-w-lg`}),(0,x.jsx)(g,{className:`h-40 w-full`})]}):(0,x.jsx)(le,{value:{filter:a,items:s,scanning:n?.scanning??!1,refreshLibrary:i},children:(0,x.jsx)(he,{})})})]})}export{ut as component};
@@ -0,0 +1 @@
1
+ import{Y as e,b as t,f as n,g as r,t as i,x as a}from"./utils-ChkMmPzE.js";import{a as o,i as s,o as c,r as l,t as u}from"./query-keys-CbbgiZx4.js";import{t as ee}from"./useNavigate-B29ssGbr.js";import{a as d,i as f,n as p,o as m,r as h,s as g,t as _}from"./scroll-area-CyEO8R_G.js";import{a as v,i as y,n as te,r as ne}from"./library-utils-BRrejTkM.js";import{n as b,r as x}from"./shell-context-Buw4m44t.js";import{a as S,i as C,t as w}from"./reading-BozmJNi1.js";import{a as T,i as E}from"./reading-progress-C5bkK-vF.js";var D=r(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]),O=r(`layout-grid`,[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]),k=r(`list`,[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]),A=r(`search-x`,[[`path`,{d:`m13.5 8.5-5 5`,key:`1cs55j`}],[`path`,{d:`m8.5 8.5 5 5`,key:`a8mexj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}],[`path`,{d:`m21 21-4.3-4.3`,key:`1qie3q`}]]),j=r(`search`,[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]),M=e(a(),1),N=t();function P({className:e,...t}){return(0,N.jsx)(`div`,{"data-slot":`empty`,className:i(`flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance`,e),...t})}function F({className:e,...t}){return(0,N.jsx)(`div`,{"data-slot":`empty-header`,className:i(`flex max-w-sm flex-col items-center gap-2`,e),...t})}var I=o(`mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0`,{variants:{variant:{default:`bg-transparent`,icon:`flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-4`}},defaultVariants:{variant:`default`}});function L({className:e,variant:t=`default`,...n}){return(0,N.jsx)(`div`,{"data-slot":`empty-icon`,"data-variant":t,className:i(I({variant:t,className:e})),...n})}function R({className:e,...t}){return(0,N.jsx)(`div`,{"data-slot":`empty-title`,className:i(`font-heading text-sm font-medium tracking-tight`,e),...t})}function z({className:e,...t}){return(0,N.jsx)(`div`,{"data-slot":`empty-description`,className:i(`text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary`,e),...t})}var B=o(`group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!`,{variants:{variant:{default:`bg-primary text-primary-foreground [a]:hover:bg-primary/80`,secondary:`bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80`,destructive:`bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20`,outline:`border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground`,ghost:`hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50`,link:`text-primary underline-offset-4 hover:underline`}},defaultVariants:{variant:`default`}});function re({className:e,variant:t=`default`,asChild:r=!1,...a}){return(0,N.jsx)(r?n:`span`,{"data-slot":`badge`,"data-variant":t,className:i(B({variant:t}),e),...a})}var V=`/novel-default-cover.png`;function H(e){return e.type===`comic`?e.cover:V}function U(e,t){if(t.type===`novel`){e({to:`/read/novel/$id`,params:{id:t.id},state:{readerTitle:t.title}});return}e({to:`/read/comic/$id`,params:{id:t.id},state:{readerTitle:t.title}})}var W=`h-[180px]`,G=`h-16`,K=`h-[244px]`,q={reading:`bg-indigo-500 shadow-[0_0_6px_rgba(99,102,241,0.4)]`,unread:`bg-green-500 shadow-[0_0_6px_rgba(34,197,94,0.4)]`,completed:`bg-muted-foreground`};function J({item:e,view:t}){let n=ee(),r=()=>{U(n,e)},a=E(e.progress),o=T(e);return t===`list`?(0,N.jsxs)(`button`,{type:`button`,onClick:r,className:`flex h-14 w-full items-stretch overflow-hidden rounded-md border border-[#25252a] bg-[#1a1a20] text-left transition-colors hover:border-[#3a3a44]`,children:[(0,N.jsx)(`div`,{className:`relative h-full w-10 shrink-0 overflow-hidden bg-muted`,children:(0,N.jsx)(`img`,{src:H(e),alt:``,className:`absolute inset-0 block size-full object-cover`,loading:`lazy`})}),(0,N.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-4 px-3.5`,children:[(0,N.jsx)(`div`,{className:`min-w-0 flex-1 truncate text-xs font-semibold text-[#e2e2e8]`,children:e.title}),(0,N.jsx)(`div`,{className:`min-w-[100px]`,children:(0,N.jsx)(`div`,{className:`h-[3px] w-full overflow-hidden rounded-full bg-[#2a2a32]`,children:(0,N.jsx)(`div`,{className:i(`h-full rounded-full`,a===`unread`?`bg-muted-foreground`:`bg-indigo-500`),style:{width:`${o}%`}})})})]})]}):(0,N.jsxs)(`button`,{type:`button`,onClick:r,className:i(`group flex w-full flex-col overflow-hidden rounded-lg border border-[#25252a] bg-[#1a1a20] text-left transition-all hover:-translate-y-px hover:border-[#3a3a44]`,K),children:[(0,N.jsxs)(`div`,{className:i(`relative w-full shrink-0 overflow-hidden bg-muted`,W),children:[(0,N.jsx)(`img`,{src:H(e),alt:``,className:`absolute inset-0 block size-full object-cover`,loading:`lazy`}),(0,N.jsx)(re,{variant:`secondary`,className:`absolute top-1.5 left-1.5 border-0 bg-black/60 px-1.5 py-0 text-[10px] text-[#c2c2ca] backdrop-blur-sm`,children:e.type===`novel`?`小说`:`漫画`}),(0,N.jsx)(`span`,{className:i(`absolute top-1.5 right-1.5 size-2 rounded-full`,q[a])})]}),(0,N.jsxs)(`div`,{className:i(`flex shrink-0 flex-col justify-between p-2.5`,G),children:[(0,N.jsx)(`div`,{className:`truncate text-xs leading-4 font-semibold text-[#e2e2e8]`,children:e.title}),(0,N.jsx)(`div`,{className:`h-[3px] w-full overflow-hidden rounded-full bg-[#2a2a32]`,children:(0,N.jsx)(`div`,{className:i(`h-full rounded-full`,a===`unread`?`bg-muted-foreground`:`bg-indigo-500`),style:{width:`${o}%`}})})]})]})}function Y({items:e,view:t,filterLabel:n}){return e.length===0?(0,N.jsx)(P,{className:`border py-16`,children:(0,N.jsxs)(F,{children:[(0,N.jsx)(L,{variant:`icon`,children:(0,N.jsx)(A,{})}),(0,N.jsx)(R,{children:`未找到匹配的作品`}),(0,N.jsx)(z,{children:`尝试调整搜索词或筛选条件`})]})}):(0,N.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,N.jsx)(`div`,{className:`flex items-center justify-between py-2`,children:(0,N.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[n,` · `,e.length,` 部作品`]})}),t===`list`?(0,N.jsxs)(`div`,{className:`mb-1.5 hidden grid-cols-[40px_1fr_1fr_80px_100px] gap-4 border-b px-3.5 py-1.5 text-[11px] font-semibold tracking-wide text-muted-foreground uppercase md:grid`,children:[(0,N.jsx)(`div`,{}),(0,N.jsx)(`div`,{children:`作品`}),(0,N.jsx)(`div`,{children:`作者`}),(0,N.jsx)(`div`,{className:`text-right`,children:`进度`}),(0,N.jsx)(`div`,{className:`text-right`,children:`状态`})]}):null,(0,N.jsx)(`div`,{className:i(t===`grid`?`grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-3.5`:`flex flex-col gap-1.5`),children:e.map(e=>(0,N.jsx)(J,{item:e,view:t},e.id))})]})}var X=`h-8 border-[#2a2a32] bg-[#1a1a20] text-xs text-[#9f9fad] hover:bg-[#23232a] hover:text-[#d5d5dd]`;function ie({query:e,onQueryChange:t,sort:n,onSortChange:r,view:a,onViewChange:o}){return(0,N.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b px-5`,children:[(0,N.jsxs)(`div`,{className:`relative max-w-[520px] flex-1`,children:[(0,N.jsx)(j,{className:`pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground`}),(0,N.jsx)(x,{value:e,onChange:e=>t(e.target.value),placeholder:`搜索作品、作者...`,className:`h-[34px] border-[#2a2a32] bg-[#1a1a20] pl-8 text-[13px] text-[#e2e2e8] placeholder:text-[#6b6b78] focus-visible:border-indigo-500`}),e?(0,N.jsx)(s,{type:`button`,variant:`ghost`,size:`icon-xs`,className:`absolute top-1/2 right-1.5 -translate-y-1/2`,onClick:()=>t(``),children:(0,N.jsx)(v,{})}):null]}),(0,N.jsxs)(`div`,{className:`ml-auto flex items-center gap-3`,children:[(0,N.jsxs)(p,{value:n,onValueChange:e=>r(e),children:[(0,N.jsx)(m,{size:`sm`,className:i(X,`h-8 min-w-[108px] px-2.5`),children:(0,N.jsx)(g,{})}),(0,N.jsx)(h,{children:(0,N.jsxs)(f,{children:[(0,N.jsx)(d,{value:`addedAt`,children:`最近添加`}),(0,N.jsx)(d,{value:`name`,children:`名称`})]})})]}),(0,N.jsxs)(C,{type:`single`,value:a,onValueChange:e=>{e&&o(e)},variant:`outline`,size:`sm`,className:`gap-0.5`,children:[(0,N.jsx)(S,{value:`grid`,"aria-label":`网格视图`,className:i(X,`px-2 data-[state=on]:border-[#3e3e52] data-[state=on]:bg-[#2a2a3a] data-[state=on]:text-[#e2e2e8]`),children:(0,N.jsx)(O,{})}),(0,N.jsx)(S,{value:`list`,"aria-label":`列表视图`,className:i(X,`px-2 data-[state=on]:border-[#3e3e52] data-[state=on]:bg-[#2a2a3a] data-[state=on]:text-[#e2e2e8]`),children:(0,N.jsx)(k,{})})]})]})]})}function ae(){let e=c({queryKey:u.recent,queryFn:w});return{items:e.data?.items??[],loading:e.isPending,error:e.error?e.error instanceof Error?e.error.message:`Failed to load recent reading`:null}}function oe(){let{filter:e}=b(),{items:t,loading:n}=ae(),r=(0,M.useMemo)(()=>e===`novel`||e===`comic`?t.filter(t=>t.type===e):t,[e,t]);return(0,N.jsxs)(`section`,{className:`mb-2`,children:[(0,N.jsxs)(`div`,{className:`flex items-center gap-2 py-4 text-[13px] font-semibold text-foreground/80`,children:[(0,N.jsx)(D,{className:`size-3.5 text-indigo-500`}),`最近阅读`]}),n?(0,N.jsx)(`div`,{className:`grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-3.5 pb-2`,children:Array.from({length:4},(e,t)=>(0,N.jsxs)(`div`,{className:i(`flex flex-col overflow-hidden rounded-lg border border-[#25252a] bg-[#1a1a20]`,K),children:[(0,N.jsx)(l,{className:i(`w-full shrink-0 rounded-none`,W)}),(0,N.jsxs)(`div`,{className:i(`flex flex-col justify-between p-2.5`,G),children:[(0,N.jsx)(l,{className:`h-3 w-4/5`}),(0,N.jsx)(l,{className:`h-[3px] w-full`})]})]},t))}):null,!n&&r.length===0?(0,N.jsx)(`div`,{className:`pb-2 text-xs text-muted-foreground`,children:`暂无阅读记录`}):null,!n&&r.length>0?(0,N.jsx)(`div`,{className:`grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-3.5 pb-2`,children:r.map(e=>(0,N.jsx)(J,{item:e,view:`grid`},e.id))}):null]})}var Z=`cyreader:library-sort`,Q=`addedAt`,$=new Set([`name`,`addedAt`]);function se(e){return typeof e==`string`&&$.has(e)?e:Q}function ce(){if(typeof window>`u`)return Q;try{let e=window.localStorage.getItem(Z);return e?se(JSON.parse(e)):Q}catch{return Q}}function le(e){if(!(typeof window>`u`))try{window.localStorage.setItem(Z,JSON.stringify(e))}catch{}}function ue(){let{filter:e,items:t,scanning:n}=b(),[r,i]=(0,M.useState)(``),[a,o]=(0,M.useState)(`grid`),[s,c]=(0,M.useState)(()=>ce()),l=(0,M.useMemo)(()=>y(te(t,e,r),s),[t,e,r,s]);return(0,N.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,N.jsx)(ie,{query:r,onQueryChange:i,sort:s,onSortChange:e=>{c(e),le(e)},view:a,onViewChange:o}),(0,N.jsx)(_,{className:`min-h-0 flex-1`,children:(0,N.jsxs)(`div`,{className:`px-5 pb-5`,children:[n?(0,N.jsx)(`div`,{className:`py-2 text-xs text-muted-foreground`,children:`正在扫描书库...`}):null,(0,N.jsx)(oe,{}),(0,N.jsx)(Y,{items:l,view:a,filterLabel:ne(e)})]})})]})}export{ue as component};
@@ -0,0 +1 @@
1
+ import{Y as e,b as t,t as n,x as r}from"./utils-ChkMmPzE.js";import{i,r as a}from"./query-keys-CbbgiZx4.js";import{t as o}from"./useRouterState-4dM5FKiy.js";import{a as s,d as c,i as l,l as u,n as d,r as f,t as p,u as m}from"./save-reading-progress-D231ROaQ.js";import{t as h}from"./settings-2-8mnAuSax.js";import{a as g,i as _}from"./reading-BozmJNi1.js";import{t as v,y}from"./index-BHhqsr5H.js";import{n as b}from"./reading-progress-C5bkK-vF.js";var x=e(r(),1),S=t();function C({open:e,direction:t,onDirectionChange:n}){return e?(0,S.jsx)(`div`,{className:`absolute top-14 right-0 z-20 flex w-80 flex-col gap-4 border-b border-l border-[#25252a] bg-[#0a0a0f] p-4`,children:(0,S.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,S.jsx)(`span`,{className:`text-sm text-[#d4c5a9]`,children:`阅读方向`}),(0,S.jsxs)(_,{type:`single`,value:t,onValueChange:e=>{(e===`ltr`||e===`rtl`)&&n(e)},children:[(0,S.jsx)(g,{value:`ltr`,"aria-label":`从左往右`,children:`左→右`}),(0,S.jsx)(g,{value:`rtl`,"aria-label":`从右往左`,children:`右→左`})]})]})}):null}function w(e){(0,x.useEffect)(()=>{let t=e.current;if(!t)return;let n=!1,r=0,i=0,a=null,o=null,s=0,c=()=>{s=0,o!==null&&(t.scrollLeft=o,o=null)},l=e=>{n&&(n=!1,a=null,s&&=(cancelAnimationFrame(s),0),o=null,t.hasPointerCapture(e)&&t.releasePointerCapture(e),t.style.cursor=`grab`)},u=e=>{e.button===0&&(n=!0,a=e.pointerId,r=e.clientX,i=t.scrollLeft,t.setPointerCapture(e.pointerId),t.style.cursor=`grabbing`)},d=e=>{!n||a!==e.pointerId||(o=i-(e.clientX-r),s||=requestAnimationFrame(c))},f=e=>{l(e.pointerId)};return t.style.cursor=`grab`,t.style.userSelect=`none`,t.addEventListener(`pointerdown`,u),t.addEventListener(`pointermove`,d),t.addEventListener(`pointerup`,f),t.addEventListener(`pointercancel`,f),()=>{s&&cancelAnimationFrame(s),t.removeEventListener(`pointerdown`,u),t.removeEventListener(`pointermove`,d),t.removeEventListener(`pointerup`,f),t.removeEventListener(`pointercancel`,f),t.style.cursor=``,t.style.userSelect=``}},[e])}function T(e,t,n){return`/static/${e}/${encodeURIComponent(t)}/${encodeURIComponent(n)}`}var E=2/3,D=.995;function O(e){return Number.isFinite(e)?Math.min(Math.max(e,0),1):0}function k(e,t){return Math.max(0,e-t)}function A(e,t,n,r=`ltr`){let i=k(t,n);if(i===0)return 0;let a=O(e/i);return r===`rtl`?1-a:a}function j(e,t,n,r=`ltr`){let i=k(t,n),a=O(e);return(r===`rtl`?1-a:a)*i}function M(e,t,n=`ltr`){e.scrollLeft=j(t,e.scrollWidth,e.clientWidth,n)}function N(e,t){return t<=1?0:Math.min(Math.max(e,0),t-1)/(t-1)}function P(e){return O(e)>=D}function F(e,t,n){if(t<=0)return 0;let r=Math.min(Math.max(e,0),t-1);return n===`rtl`?t-1-r:r}function I(e){return e<=0?200:Math.round(e*E)+8}function L(e,t,n){return e<=0||t<=0||n<=0?I(n):Math.round(e/t*n)+8}function R(e,t){return e.reduce((e,n)=>e+L(n.width,n.height,t),0)}function z({directoryId:e,title:t,pages:r,direction:i,initialScrollRatio:a,onScrollProgress:o}){let s=(0,x.useRef)(null),c=(0,x.useRef)(o),l=(0,x.useRef)(a),u=(0,x.useRef)(!0),d=(0,x.useRef)(!1),[f,p]=(0,x.useState)(0);c.current=o;let h=f>0,g=r.length,_=(0,x.useMemo)(()=>I(f),[f]);w(s);let v=(0,x.useCallback)(e=>F(e,g,i),[i,g]),y=m({horizontal:!0,count:g,enabled:h,getScrollElement:()=>s.current,estimateSize:(0,x.useCallback)(e=>{let t=r[v(e)];return t?L(t.width,t.height,f):_},[f,_,v,r]),overscan:4,initialOffset:(0,x.useCallback)(()=>{let e=s.current;if(!e||!h)return 0;let t=R(r,f);return j(l.current,t,e.clientWidth,i)},[f,i,h,r]),getItemKey:e=>r[v(e)]?.filename??e}),b=(0,x.useRef)(y.measure);b.current=y.measure;let C=(0,x.useCallback)(()=>{let e=s.current;e&&(d.current=!0,M(e,l.current,i),window.setTimeout(()=>{d.current=!1},0))},[i]);return(0,x.useLayoutEffect)(()=>{let e=s.current;if(!e)return;let t=()=>{p(e.clientHeight)};t();let n=new ResizeObserver(t);return n.observe(e),()=>{n.disconnect()}},[]),(0,x.useLayoutEffect)(()=>{l.current=a,u.current=!0},[i,a,r,t]),(0,x.useLayoutEffect)(()=>{g===0||!h||(b.current(),u.current&&C())},[C,f,i,h,g]),(0,x.useEffect)(()=>{if(g===0||!h||!u.current)return;let e=window.setTimeout(()=>{C(),u.current=!1},120);return()=>{window.clearTimeout(e)}},[C,a,h,g]),(0,x.useEffect)(()=>{let e=s.current;if(!e||!h)return;let t,n=()=>{t&&clearTimeout(t),t=setTimeout(()=>{if(d.current||u.current)return;let t=A(e.scrollLeft,e.scrollWidth,e.clientWidth,i);c.current(t)},100)};return e.addEventListener(`scroll`,n,{passive:!0}),()=>{e.removeEventListener(`scroll`,n),t&&clearTimeout(t)}},[i,h]),(0,S.jsx)(`div`,{ref:s,className:n(`reader-scrollbar-none h-full overflow-x-auto overflow-y-hidden`),children:(0,S.jsx)(`div`,{style:{width:y.getTotalSize(),height:`100%`,position:`relative`},children:y.getVirtualItems().map(n=>{let i=v(n.index),a=r[i];return a?(0,S.jsx)(`div`,{"data-index":n.index,className:`flex h-full items-center`,style:{position:`absolute`,top:0,left:0,height:`100%`,width:n.size,paddingRight:8,transform:`translateX(${n.start}px)`},children:(0,S.jsx)(`img`,{src:T(e,t,a.filename),alt:`第 ${i+1} 页`,draggable:!1,decoding:`async`,className:`h-full w-auto max-w-none select-none`})},n.key):null})})})}function B(e,t){return e?typeof e.scrollRatio==`number`?O(e.scrollRatio):typeof e.pageIndex==`number`?N(e.pageIndex,t):0:0}function V({id:e}){let t=o({select:e=>e.location.state?.readerTitle}),{data:r,isPending:m,error:g}=u(e),{settings:_,patchSettings:v}=s(`comic`),[w,T]=(0,x.useState)(0),[E,D]=(0,x.useState)(null),[k,A]=(0,x.useState)(!1),j=r&&r.type===`comic`?r:null,M=j?.pages.length??0,N=t??r?.title??`加载中...`,F=g?g instanceof Error?g.message:`加载失败`:null,I=(0,x.useMemo)(()=>b(w),[w]),L=(0,x.useCallback)((t,n)=>{j&&d(e,{type:`comic`,scrollRatio:t,completedAt:n})},[j,e]),R=(0,x.useCallback)(e=>{let t=O(e);T(t),L(t,P(t)?new Date().toISOString():null)},[L]),V=(0,x.useCallback)(e=>{D(w),v({direction:e})},[v,w]);return(0,x.useEffect)(()=>{D(null),T(0)},[e]),(0,x.useEffect)(()=>{if(!j||E!==null)return;let e=B(j.progress,M);D(e),T(e)},[j,M,E]),(0,x.useEffect)(()=>(l(e),()=>{f(e),p(e)}),[e]),(0,S.jsxs)(`div`,{className:`relative flex h-screen flex-col overflow-hidden bg-[#0a0a0f] text-[#d4c5a9]`,children:[(0,S.jsxs)(`header`,{className:`relative z-10 flex h-14 shrink-0 items-center gap-3 border-b border-[#25252a] px-4`,children:[(0,S.jsx)(i,{type:`button`,variant:`ghost`,size:`sm`,asChild:!0,children:(0,S.jsxs)(y,{to:`/`,children:[(0,S.jsx)(c,{"data-icon":`inline-start`}),`返回`]})}),(0,S.jsx)(`div`,{className:`flex-1 truncate text-center text-sm font-medium`,children:N}),(0,S.jsx)(i,{type:`button`,variant:`ghost`,size:`icon-sm`,onClick:()=>A(e=>!e),className:n(k&&`bg-[#25252a]`),children:(0,S.jsx)(h,{})})]}),(0,S.jsx)(C,{open:k,direction:_.direction,onDirectionChange:V}),(0,S.jsxs)(`div`,{className:`relative min-h-0 flex-1`,children:[m&&!j?(0,S.jsx)(`div`,{className:`flex size-full items-center justify-center`,children:(0,S.jsx)(a,{className:`h-[70vh] w-full max-w-3xl`})}):null,F?(0,S.jsx)(`div`,{className:`p-8 text-sm text-red-400`,children:F}):null,!m&&!F&&r&&r.type!==`comic`?(0,S.jsx)(`div`,{className:`p-8 text-sm text-red-400`,children:`作品类型不匹配`}):null,j&&M>0&&E!==null?(0,S.jsx)(z,{directoryId:j.directoryId,title:j.title,pages:j.pages,direction:_.direction,initialScrollRatio:E,onScrollProgress:R},`${e}-${_.direction}`):null,j&&M===0?(0,S.jsx)(`div`,{className:`flex size-full items-center justify-center text-sm text-muted-foreground`,children:`暂无页面`}):null]}),(0,S.jsxs)(`footer`,{className:`flex h-11 shrink-0 items-center justify-center border-t border-[#25252a] text-xs opacity-80`,children:[`已读 `,I,`%`]})]})}function H(){let{id:e}=v.useParams();return(0,S.jsx)(V,{id:e})}export{H as component};
@@ -0,0 +1 @@
1
+ import{Y as e,x as t}from"./utils-ChkMmPzE.js";var n=e(t(),1);function r(e){let t=n.useRef({value:e,previous:e});return n.useMemo(()=>(t.current.value!==e&&(t.current.previous=t.current.value,t.current.value=e),t.current.previous),[e])}function i(e,[t,n]){return Math.min(n,Math.max(t,e))}export{r as n,i as t};
@@ -0,0 +1 @@
1
+ import{Y as e,b as t,h as n,l as r,p as i,x as a}from"./utils-ChkMmPzE.js";var o=e(a(),1),s=t();function c(e){let t=e+`CollectionProvider`,[a,c]=r(t),[l,u]=a(t,{collectionRef:{current:null},itemMap:new Map}),d=e=>{let{scope:t,children:n}=e,r=o.useRef(null),i=o.useRef(new Map).current;return(0,s.jsx)(l,{scope:t,itemMap:i,collectionRef:r,children:n})};d.displayName=t;let f=e+`CollectionSlot`,p=i(f),m=o.forwardRef((e,t)=>{let{scope:r,children:i}=e;return(0,s.jsx)(p,{ref:n(t,u(f,r).collectionRef),children:i})});m.displayName=f;let h=e+`CollectionItemSlot`,g=`data-radix-collection-item`,_=i(h),v=o.forwardRef((e,t)=>{let{scope:r,children:i,...a}=e,c=o.useRef(null),l=n(t,c),d=u(h,r);return o.useEffect(()=>(d.itemMap.set(c,{ref:c,...a}),()=>void d.itemMap.delete(c))),(0,s.jsx)(_,{[g]:``,ref:l,children:i})});v.displayName=h;function y(t){let n=u(e+`CollectionConsumer`,t);return o.useCallback(()=>{let e=n.collectionRef.current;if(!e)return[];let t=Array.from(e.querySelectorAll(`[${g}]`));return Array.from(n.itemMap.values()).sort((e,n)=>t.indexOf(e.ref.current)-t.indexOf(n.ref.current))},[n.collectionRef,n.itemMap])}return[{Provider:d,Slot:m,ItemSlot:v},y,c]}var l=o.createContext(void 0);function u(e){let t=o.useContext(l);return e||t||`ltr`}export{c as n,u as t};