Skip to content

Commit

Permalink
feat: cleanup remove all downloaded files
Browse files Browse the repository at this point in the history
  • Loading branch information
mbret committed Aug 2, 2024
1 parent c03e7b8 commit e7daa69
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 59 deletions.
7 changes: 1 addition & 6 deletions packages/web/src/download/RestoreDownloadState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ import localforage from "localforage"
import { memo, useEffect } from "react"
import { useMutation } from "reactjrx"
import { combineLatest, from, map, of, switchMap } from "rxjs"
import { DOWNLOAD_PREFIX } from "../constants.shared"
import { booksDownloadStateSignal, DownloadState } from "./states"

const getBookKeysFromStorage = async () =>
(await localforage.keys())
.filter((key) => key.startsWith(DOWNLOAD_PREFIX))
.map((key) => ({ key, bookId: key.replace(`${DOWNLOAD_PREFIX}-`, "") }))
import { getBookKeysFromStorage } from "./helpers"

export const useRestoreDownloadState = ({
onSuccess
Expand Down
7 changes: 7 additions & 0 deletions packages/web/src/download/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import localforage from "localforage"
import { DOWNLOAD_PREFIX } from "../constants.shared"

export const getBookKeysFromStorage = async () =>
(await localforage.keys())
.filter((key) => key.startsWith(DOWNLOAD_PREFIX))
.map((key) => ({ key, bookId: key.replace(`${DOWNLOAD_PREFIX}-`, "") }))
82 changes: 54 additions & 28 deletions packages/web/src/download/useRemoveAllDownloadedFiles.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,66 @@
import { useCallback } from "react"
import { useDatabase } from "../rxdb"
import { useRemoveDownloadFile } from "./useRemoveDownloadFile"
import { plugin } from "../plugins/local"
import { plugin as localPlugin } from "../plugins/local"
import { useMutation } from "reactjrx"
import { combineLatest, first, from, map, of, switchMap, tap } from "rxjs"
import { getBookKeysFromStorage } from "./helpers"
import { latestDatabase$ } from "../rxdb/RxDbProvider"

export const useRemoveAllDownloadedFiles = () => {
const { db } = useDatabase()
const { mutateAsync: removeDownloadFile } = useRemoveDownloadFile()

return useCallback(
async (bookIds: string[]) => {
return await Promise.all(
bookIds.map(async (id) => {
const book = await db?.book
.findOne({
selector: {
_id: id
}
})
.exec()
return useMutation({
mutationFn: () => {
return combineLatest([
latestDatabase$,
from(getBookKeysFromStorage())
]).pipe(
first(),
switchMap(([db, keys]) => {
const books$ = from(
db.book
.find({
selector: {
_id: {
$in: keys.map(({ bookId }) => bookId)
}
}
})
.exec()
)

const linkIds = book?.links ?? []
return books$.pipe(
switchMap((books) =>
combineLatest(
books.map((book) => {
// valid to remove
if (book.links.length === 0) return of(book)

if (linkIds.length > 0) {
const links = await db?.link.findByIds(linkIds).exec()
return from(db.link.findByIds(book.links).exec()).pipe(
switchMap((links) => {
const fileLink = Array.from(links?.values() ?? []).find(
({ type }) => type === localPlugin.type
)

const fileLink = Array.from(links?.values() ?? []).find(
({ type }) => type === plugin.type
)

if (fileLink) return
}
// local book, don't remove
if (fileLink) return of(null)

return removeDownloadFile({ bookId: id })
return of(book)
})
)
})
)
),
map((books) => books.filter((book) => !!book)),
switchMap((books) =>
combineLatest(
books.map((book) =>
from(removeDownloadFile({ bookId: book._id }))
)
)
)
)
})
)
},
[db, removeDownloadFile]
)
}
})
}
2 changes: 1 addition & 1 deletion packages/web/src/plugins/dropbox/AddDataSource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { ArrowBackIosRounded, LocalOfferRounded } from "@mui/icons-material"
import { ComponentProps, FC, useState } from "react"
import { DropboxDataSourceData } from "@oboku/shared"
import { useTagIds, useTags } from "../../tags/helpers"
import { useCreateDataSource } from "../../dataSources/helpers"
import { Picker } from "./Picker"
import { DropboxFile } from "./types"
import { TagsSelectionDialog } from "../../tags/TagsSelectionDialog"
import { useCreateDataSource } from "../../dataSources/useCreateDataSource"

export const AddDataSource: FC<{ onClose: () => void }> = ({ onClose }) => {
const [selectedTags, setSelectedTags] = useState<{
Expand Down
6 changes: 3 additions & 3 deletions packages/web/src/plugins/google/GoogleDriveDataSource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import {
import { ArrowBackIosRounded, LocalOfferRounded } from "@mui/icons-material"
import { FC, useState } from "react"
import { useTagIds, useTags } from "../../tags/helpers"
import { useCreateDataSource } from "../../dataSources/helpers"
import { GoogleDriveDataSourceData } from "@oboku/shared"
import { useDrivePicker } from "./lib/useDrivePicker"
import { TagsSelectionDialog } from "../../tags/TagsSelectionDialog"
import { catchError, EMPTY, takeUntil, tap } from "rxjs"
import { catchError, of, takeUntil, tap } from "rxjs"
import { useUnmountObservable } from "reactjrx"
import { useCreateDataSource } from "../../dataSources/useCreateDataSource"

export const GoogleDriveDataSource: FC<{
onClose: () => void
Expand Down Expand Up @@ -105,7 +105,7 @@ export const GoogleDriveDataSource: FC<{
catchError((error) => {
console.error(error)

return EMPTY
return of(null)
})
)
.subscribe()
Expand Down
6 changes: 3 additions & 3 deletions packages/web/src/plugins/google/SelectItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useDataSourceHelpers } from "../../dataSources/helpers"
import { UNIQUE_RESOURCE_IDENTIFIER } from "./lib/constants"
import { useDrivePicker } from "./lib/useDrivePicker"
import { catchError, EMPTY, takeUntil, tap } from "rxjs"
import { catchError, EMPTY, of, takeUntil, tap } from "rxjs"
import { useEffect } from "react"
import { useUnmountObservable } from "reactjrx"
import { ObokuPlugin } from "../plugin-front"
Expand Down Expand Up @@ -44,7 +44,7 @@ export const SelectItem: ObokuPlugin[`SelectItemComponent`] = ({
catchError((error) => {
onClose({ code: `unknown`, originalError: error })

return EMPTY
return of(null)
}),
takeUntil(unMount$.current)
)
Expand All @@ -53,7 +53,7 @@ export const SelectItem: ObokuPlugin[`SelectItemComponent`] = ({
return () => {
stream$.unsubscribe()
}
}, [open, pick, unMount$])
}, [open, pick, unMount$, generateResourceId, onClose])

if (!open) return null

Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/plugins/google/UploadBook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useDrivePicker } from "./lib/useDrivePicker"
import { useAddBook } from "../../books/helpers"
import { useDataSourceHelpers } from "../../dataSources/helpers"
import { UNIQUE_RESOURCE_IDENTIFIER } from "./lib/constants"
import { catchError, EMPTY, from, of, switchMap, takeUntil, timer } from "rxjs"
import { catchError, from, of, switchMap, takeUntil, timer } from "rxjs"
import { useMount } from "react-use"
import { useMutation, useUnmountObservable } from "reactjrx"
import { ObokuPlugin } from "../plugin-front"
Expand All @@ -28,7 +28,7 @@ export const UploadBook: ObokuPlugin["UploadComponent"] = memo(
switchMap((data) => {
onClose()

if (data.action !== "picked") return of(EMPTY)
if (data.action !== "picked") return of(null)

const docs = data?.docs || []

Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/plugins/google/useDownloadBook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isDriveResponseError } from "./lib/types"
import { useAccessToken } from "./lib/useAccessToken"
import { ObokuPlugin } from "../plugin-front"
import { httpClient } from "../../http/httpClient"
import { catchError, filter, from, mergeMap, of } from "rxjs"
import { catchError, from, mergeMap, of } from "rxjs"
import { gapiOrThrow$ } from "./lib/gapi"

export const useDownloadBook: ObokuPlugin[`useDownloadBook`] = ({
Expand Down
20 changes: 5 additions & 15 deletions packages/web/src/settings/ManageStorageScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ import { difference } from "lodash"
import Alert from "@mui/material/Alert"
import { Report } from "../debug/report.shared"
import { useEffect } from "react"
import { useMutation } from "reactjrx"
import { useRemoveAllDownloadedFiles } from "../download/useRemoveAllDownloadedFiles"
import { useRemoveCoversInCache } from "../covers/useRemoveCoversInCache"
import { useDownloadedBooks } from "../download/useDownloadedBooks"
import { useBooks } from "../books/states"
import { useRemoveAllDownloads } from "./useRemoveAllDownloads"

export const ManageStorageScreen = () => {
const books = useDownloadedBooks()
Expand All @@ -45,7 +44,6 @@ export const ManageStorageScreen = () => {
useStorageUse([books])
const { mutate: removeCoversInCache } = useRemoveCoversInCache()
const { mutateAsync: removeDownloadFile } = useRemoveDownloadFile()
const deleteAllDownloadedFiles = useRemoveAllDownloadedFiles()
const { data: downloadedBookIds = [], refetch: refetchDownloadedFilesInfo } =
useDownloadedFilesInfo()
const extraDownloadFilesIds = difference(downloadedBookIds, bookIds)
Expand All @@ -54,17 +52,9 @@ export const ManageStorageScreen = () => {
() => bookIds.filter((id) => visibleBookIds?.includes(id)),
[bookIds, visibleBookIds]
)
const { mutate: onDeleteAllDownloadsClick } = useMutation({
mutationFn: async () => {
const isConfirmed = confirm(
"Are you sure you want to delete all downloads at once?"
)

if (isConfirmed) {
await deleteAllDownloadedFiles(bookIds)

refetchDownloadedFilesInfo()
}
const { mutate: removeAllDownloads } = useRemoveAllDownloads({
onSuccess: () => {
refetchDownloadedFilesInfo()
}
})

Expand Down Expand Up @@ -129,7 +119,7 @@ export const ManageStorageScreen = () => {
/>
</ListItemButton>
{bookIdsToDisplay.length > 0 && (
<ListItemButton onClick={() => onDeleteAllDownloadsClick()}>
<ListItemButton onClick={() => removeAllDownloads()}>
<ListItemIcon>
<DeleteRounded />
</ListItemIcon>
Expand Down
27 changes: 27 additions & 0 deletions packages/web/src/settings/useRemoveAllDownloads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useMutation } from "reactjrx"
import { useRemoveAllDownloadedFiles } from "../download/useRemoveAllDownloadedFiles"
import { from, of } from "rxjs"

export const useRemoveAllDownloads = ({
onSuccess
}: {
onSuccess: () => void
}) => {
const { mutateAsync: deleteAllDownloadedFiles } =
useRemoveAllDownloadedFiles()

return useMutation({
onSuccess,
mutationFn: () => {
const isConfirmed = confirm(
"Are you sure you want to delete all downloads at once?"
)

if (isConfirmed) {
return from(deleteAllDownloadedFiles())
}

return of(null)
}
})
}

0 comments on commit e7daa69

Please sign in to comment.