diff --git a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTable.tsx b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTable.tsx index 2aa755867..b01c23d19 100644 --- a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTable.tsx +++ b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTable.tsx @@ -18,6 +18,7 @@ import { import { ChapterTablePagination } from './ChapterTablePagination'; import { chapterDownloadStatusesState, + chapterFilterGroupNamesState, chapterListState, seriesState, sortedFilteredChapterListState, @@ -34,13 +35,20 @@ import { Chapter, Languages, Series } from '@tiyo/common'; import routes from '@/common/constants/routes.json'; import { DropdownMenu, + DropdownMenuGroup, + DropdownMenuSub, + DropdownMenuPortal, + DropdownMenuSubTrigger, + DropdownMenuSubContent, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, + DropdownMenuItem } from '@houdoku/ui/components/DropdownMenu'; import { Button } from '@houdoku/ui/components/Button'; +import { ScrollArea } from '@houdoku/ui/components/ScrollArea'; import { ArrowDown, ArrowUp, @@ -48,21 +56,27 @@ import { Download, Eye, EyeOff, + EllipsisVertical, + Filter, FileCheck, LanguagesIcon, Play, Settings2, + X, } from 'lucide-react'; import { ChapterTableLanguageFilter } from './ChapterTableLanguageFilter'; import { ChapterTableGroupFilter } from './ChapterTableGroupFilter'; import { markChapters } from '@/renderer/features/library/utils'; import { downloaderClient } from '@/renderer/services/downloader'; import ipcChannels from '@/common/constants/ipcChannels.json'; +import { Badge } from '@houdoku/ui/components/Badge'; import { Checkbox } from '@houdoku/ui/components/Checkbox'; +import { Separator } from '@houdoku/ui/components/Separator'; import { TableColumnSortOrder } from '@/common/models/types'; import { FS_METADATA } from '@/common/temp_fs_metadata'; import { ContextMenu, ContextMenuTrigger } from '@houdoku/ui/components/ContextMenu'; import { ChapterTableContextMenu } from './ChapterTableContextMenu'; +import { ChapterTableReadFilter } from './ChapterTableReadFilter'; import { useEffect } from 'react'; import { currentTaskState } from '@/renderer/state/downloaderStates'; @@ -83,7 +97,8 @@ export function ChapterTable(props: ChapterTableProps) { const setSeries = useSetRecoilState(seriesState); const [chapterList, setChapterList] = useRecoilState(chapterListState); const sortedFilteredChapterList = useRecoilValue(sortedFilteredChapterListState); - const chapterLanguages = useRecoilValue(chapterLanguagesState); + const [filterGroupNames, setFilterGroupNames] = useRecoilState(chapterFilterGroupNamesState); + const [chapterLanguages, setChapterLanguages] = useRecoilState(chapterLanguagesState); const [chapterListVolOrder, setChapterListVolOrder] = useRecoilState(chapterListVolOrderState); const [chapterListChOrder, setChapterListChOrder] = useRecoilState(chapterListChOrderState); const [chapterDownloadStatuses, setChapterDownloadStatuses] = useRecoilState( @@ -99,11 +114,8 @@ export function ChapterTable(props: ChapterTableProps) {
table.toggleAllRowsSelected(!!value)} + checked={table.getIsAllPageRowsSelected()} + onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} />
@@ -269,6 +281,10 @@ export function ChapterTable(props: ChapterTableProps) { return table.getSelectedRowModel().rows.map((row) => row.original) as Chapter[]; }; + const getAllChapters = (): Chapter[] => { + return table.getCoreRowModel().rows.map((row) => row.original) as Chapter[]; + }; + const getNextUnreadChapter = () => { return sortedFilteredChapterList .slice() @@ -300,6 +316,17 @@ export function ChapterTable(props: ChapterTableProps) { ); }; + const setAllRead = (read: boolean) => { + markChapters( + getAllChapters(), + props.series, + read, + setChapterList, + setSeries, + chapterLanguages, + ); + }; + const downloadSelected = () => { downloaderClient.add( getSelectedChapters().map((chapter) => ({ @@ -311,79 +338,218 @@ export function ChapterTable(props: ChapterTableProps) { downloaderClient.start(); }; + const downloadAll = () => { + downloaderClient.add( + getAllChapters().map((chapter) => ({ + chapter, + series: props.series, + downloadsDir: customDownloadsDir || defaultDownloadsDir, + })), + ); + downloaderClient.start(); + }; + return (
- {table.getIsSomeRowsSelected() || table.getIsAllRowsSelected() ? ( -
- - - {/* TODO add confirmation prompt */} - -
- ) : ( - <> -
- - chapter.groupName)), +
+ + - - - Columns - - {table - .getAllColumns() - .filter((column) => column.getCanHide()) - .map((column) => { - return ( - column.toggleVisibility(!!value)} - onSelect={(event) => event.preventDefault()} +
+ + + + + + + + chapter.groupName)), + )} + /> + + + + + + + + + + + + + + Download Chapters + + +
+ + Download +
+
+ + + +
downloadAll()} + className="flex items-center w-full" > - {column.id} - - ); - })} - - - {getNextUnreadChapter() && ( - - - - )} -
- - )} + All Chapters +
+ + +
downloadSelected()} + className="flex items-center w-full" + > + Selected Chapters +
+
+ + + + + + + Mark Chapters + + All Chapters + + + +
setAllRead(true)} + className="flex items-center w-full" + > + + Read +
+
+ +
setAllRead(false)} + className="flex items-center w-full" + > + + Unread +
+
+
+
+
+ + + Selected Chapters + + + +
setSelectedRead(true)} + className="flex items-center w-full" + > + + Read +
+
+ +
setSelectedRead(false)} + className="flex items-center w-full" + > + + Unread +
+
+
+
+
+
+ + +
+ +
+ + + + + + Columns + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + column.toggleVisibility(!!value)} + onSelect={(event) => event.preventDefault()} + > + {column.id} + + ); + })} + + + {getNextUnreadChapter() && ( + + + + )} +
-
+
- + {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { diff --git a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableGroupFilter.tsx b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableGroupFilter.tsx index 78a931013..c635b7c04 100644 --- a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableGroupFilter.tsx +++ b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableGroupFilter.tsx @@ -1,8 +1,6 @@ -import { Check, Filter } from 'lucide-react'; - +import { Check, ChevronRight } from 'lucide-react'; import { cn } from '@houdoku/ui/util'; import { Badge } from '@houdoku/ui/components/Badge'; -import { Button } from '@houdoku/ui/components/Button'; import { Command, CommandEmpty, @@ -35,9 +33,14 @@ export function ChapterTableGroupFilter(props: Props) { return ( - + - + diff --git a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableLanguageFilter.tsx b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableLanguageFilter.tsx index 9f30fde66..0e3d62eb1 100644 --- a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableLanguageFilter.tsx +++ b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableLanguageFilter.tsx @@ -1,7 +1,6 @@ -import { Check, Filter } from 'lucide-react'; +import { Check, ChevronRight } from 'lucide-react'; import { cn } from '@houdoku/ui/util'; import { Badge } from '@houdoku/ui/components/Badge'; -import { Button } from '@houdoku/ui/components/Button'; import { Command, CommandEmpty, @@ -35,9 +34,13 @@ export function ChapterTableLanguageFilter() { return ( - + - + diff --git a/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableReadFilter.tsx b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableReadFilter.tsx new file mode 100644 index 000000000..f0c16fc24 --- /dev/null +++ b/apps/desktop/src/renderer/components/library/series/chapter-table/ChapterTableReadFilter.tsx @@ -0,0 +1,28 @@ +import { useRecoilState } from 'recoil'; +import { hideUnreadChaptersState } from '@/renderer/state/libraryStates'; +import { Checkbox } from '@houdoku/ui/components/Checkbox'; +import { Label } from '@houdoku/ui/components/Label'; +export function ChapterTableReadFilter() { + const [hideReadChapters, setHideReadChapters] = useRecoilState(hideUnreadChaptersState); + + const toggleReadChapters = () => { + setHideReadChapters(!hideReadChapters); + }; + + return ( +
e.stopPropagation()}> + + +
+ + ); +}; diff --git a/apps/desktop/src/renderer/state/libraryStates.ts b/apps/desktop/src/renderer/state/libraryStates.ts index f7525e361..354d20210 100644 --- a/apps/desktop/src/renderer/state/libraryStates.ts +++ b/apps/desktop/src/renderer/state/libraryStates.ts @@ -95,6 +95,11 @@ export const activeSeriesListState = selector({ }, }); +export const hideUnreadChaptersState = atom({ + key: 'hideUnreadChaptersState', + default: false, +}); + export const sortedFilteredChapterListState = selector({ key: 'sortedFilteredChapterListState', get: ({ get }) => { @@ -103,8 +108,8 @@ export const sortedFilteredChapterListState = selector({ const chapterFilterGroupNames = get(chapterFilterGroupNamesState); const chapterListVolOrder = get(chapterListVolOrderState); const chapterListChOrder = get(chapterListChOrderState); - const uniqueChapters = new Map(); + const toggleReadChapters = get(hideUnreadChaptersState); if (chapterLanguages.length > 0) { chapterLanguages.forEach((lang) => { @@ -129,8 +134,9 @@ export const sortedFilteredChapterListState = selector({ (uniqueChapters.has(chapter.chapterNumber) && uniqueChapters.get(chapter.chapterNumber) === chapter) || chapterLanguages.length === 0; + const readChapters = !toggleReadChapters || !chapter.read; - return matchesLanguage && matchesGroup && unique; + return matchesLanguage && matchesGroup && unique && readChapters; }) .sort((a, b) => { const volumeComp = { diff --git a/packages/ui/src/components/Table.tsx b/packages/ui/src/components/Table.tsx index 30908eb82..79e1f53d3 100644 --- a/packages/ui/src/components/Table.tsx +++ b/packages/ui/src/components/Table.tsx @@ -4,7 +4,7 @@ import { cn } from '@houdoku/ui/util'; const Table = React.forwardRef>( ({ className, ...props }, ref) => ( -
+
),