diff --git a/tranga-website/src/App.tsx b/tranga-website/src/App.tsx index 5801ebe..f31aa85 100644 --- a/tranga-website/src/App.tsx +++ b/tranga-website/src/App.tsx @@ -8,6 +8,7 @@ import MangaProvider from './contexts/MangaContext.tsx' import MangaList from './Components/Mangas/MangaList.tsx' import {Search} from './Search.tsx' import MangaConnectorProvider from './contexts/MangaConnectorContext.tsx' +import LibraryProvider from "./contexts/FileLibraryContext.tsx"; export default function App() { const [apiUri, setApiUri] = useState( @@ -27,17 +28,19 @@ export default function App() { return ( - - -
- -
- - setSearchOpen(true)} /> - + + + +
+ +
+ + setSearchOpen(true)} /> + +
-
-
+ +
) diff --git a/tranga-website/src/Components/Inputs/TProps.ts b/tranga-website/src/Components/Inputs/TProps.ts index 2d617aa..16e13d6 100644 --- a/tranga-website/src/Components/Inputs/TProps.ts +++ b/tranga-website/src/Components/Inputs/TProps.ts @@ -35,6 +35,6 @@ export const TColor = (state: TState): ColorPaletteProp => { export default interface TProps { disabled?: boolean completionAction?: ( - value: string | number | readonly string[] | undefined + value?: string | number | readonly string[] ) => Promise } diff --git a/tranga-website/src/MangaDetail.tsx b/tranga-website/src/MangaDetail.tsx index 47aa719..945ea91 100644 --- a/tranga-website/src/MangaDetail.tsx +++ b/tranga-website/src/MangaDetail.tsx @@ -33,7 +33,7 @@ export default function MangaDetail (props: MangaDetailProps) : ReactNode { - + {manga?.tags.map(tag => {tag})} {manga?.authors.map(author => {author.name} )} @@ -41,7 +41,7 @@ export default function MangaDetail (props: MangaDetailProps) : ReactNode { - + {props.actions} diff --git a/tranga-website/src/MangaDownloadDrawer.tsx b/tranga-website/src/MangaDownloadDrawer.tsx new file mode 100644 index 0000000..23f2287 --- /dev/null +++ b/tranga-website/src/MangaDownloadDrawer.tsx @@ -0,0 +1,91 @@ +import {Dispatch, ReactNode, useContext, useEffect, useState} from "react"; +import {Box, Card, Checkbox, Drawer, List, ListItem, Option, Select, Stack, Typography} from "@mui/joy"; +import ModalClose from "@mui/joy/ModalClose"; +import {Manga, MangaConnectorId} from "./api/data-contracts.ts"; +import {ApiContext} from "./contexts/ApiContext.tsx"; +import {MangaContext} from "./contexts/MangaContext.tsx"; +import {FileLibraryContext} from "./contexts/FileLibraryContext.tsx"; +import MangaConnectorIcon from "./Components/Mangas/MangaConnectorIcon.tsx"; +import TButton from "./Components/Inputs/TButton.tsx"; + +export default function MangaDownloadDrawer (props: MangaDownloadDrawerProps) : ReactNode{ + const Api = useContext(ApiContext); + const Manga = useContext(MangaContext); + const Libraries = useContext(FileLibraryContext); + + const [manga, setManga] = useState(props.manga) + const [downloadFromMap, setDownloadFromMap] = useState>(new Map()) + + useEffect(() => { + if (!props.open) return; + if (!props.mangaKey) return; + if (props.manga != undefined) return; + Manga.GetManga(props.mangaKey).then(setManga); + }, [Api, props]); + + useEffect(() => { + const newMap = new Map(); + manga?.mangaConnectorIds.forEach(id => { + newMap.set(id, id.useForDownload); + }) + setDownloadFromMap(newMap); + }, [manga]); + + const setDownload = () : Promise => { + if (!manga) return Promise.reject(); + downloadFromMap.forEach(async (download, id) => { + const result = await Api.mangaSetAsDownloadFromCreate(manga?.key, id.mangaConnectorName, download); + if (!result.ok) + return Promise.reject(); + }); + return Promise.resolve(); + } + + return ( + props.setOpen(false)} + anchor="left" + size="md"> + + + Download + {manga?.name} + + + Select a Library to Download to: + + + + Select which connectors you want to download this Manga from: + + {manga?.mangaConnectorIds.map(id => ( + + downloadFromMap.set(id, c.target.checked)} + label={ +
+ + {id.mangaConnectorName} +
+ } + /> +
+ ))} +
+
+ Download All +
+
+
+ ) +} + +export interface MangaDownloadDrawerProps { + manga?: Manga; + mangaKey?: string; + open: boolean; + setOpen: Dispatch; +} \ No newline at end of file diff --git a/tranga-website/src/Search.tsx b/tranga-website/src/Search.tsx index 34a8eb2..ed0d9ba 100644 --- a/tranga-website/src/Search.tsx +++ b/tranga-website/src/Search.tsx @@ -1,5 +1,6 @@ import {Dispatch, ReactNode, useContext, useEffect, useState} from 'react' import { + Button, List, ListItem, ListItemDecorator, @@ -18,6 +19,7 @@ import { ApiContext } from './contexts/ApiContext.tsx' import { MangaCardList } from './Components/Mangas/MangaList.tsx' import {MangaConnector, MinimalManga} from './api/data-contracts.ts' import MangaDetail from "./MangaDetail.tsx"; +import MangaDownloadDrawer from "./MangaDownloadDrawer.tsx"; export function Search(props: SearchModalProps): ReactNode { const Api = useContext(ApiContext) @@ -64,11 +66,17 @@ export function Search(props: SearchModalProps): ReactNode { const [selectedManga, setSelectedManga] = useState(undefined); const [mangaDetailOpen, setMangaDetailOpen] = useState(false); + const [mangaDownloadDrawerOpen, setMangaDownloadDrawerOpen] = useState(false); function openMangaDetail(manga: MinimalManga) { setSelectedManga(manga); setMangaDetailOpen(true); } + + function openMangaDownloadDrawer() { + setMangaDetailOpen(false); + setMangaDownloadDrawerOpen(true); + } return ( props.setOpen(false)}> @@ -120,7 +128,10 @@ export function Search(props: SearchModalProps): ReactNode { - + Download + ]} /> + ) diff --git a/tranga-website/src/contexts/FileLibraryContext.tsx b/tranga-website/src/contexts/FileLibraryContext.tsx new file mode 100644 index 0000000..8a802ed --- /dev/null +++ b/tranga-website/src/contexts/FileLibraryContext.tsx @@ -0,0 +1,29 @@ +import { + createContext, + ReactNode, + useContext, + useEffect, + useState, +} from 'react' +import {FileLibrary} from '../api/data-contracts.ts' +import { ApiContext } from './ApiContext.tsx' + +export const FileLibraryContext = createContext([]); + +export default function LibraryProvider({ children }: { children: ReactNode }) : ReactNode { + const Api = useContext(ApiContext) + + const [state, setState] = useState([]) + + useEffect(() => { + Api.fileLibraryList().then((result) => { + if (result.ok) { + setState(result.data) + } + }) + }, [Api]) + + return ( + {children} + ); +}