Skip to content

Commit

Permalink
feat(archive): archive management (#234)
Browse files Browse the repository at this point in the history
* feat(archive): archive management

* feat(archive): preview

* fix(archive): hide extract when not permitted

* fix
  • Loading branch information
KirCute authored Jan 18, 2025
1 parent c6ffe3b commit 17eda9a
Show file tree
Hide file tree
Showing 27 changed files with 950 additions and 66 deletions.
19 changes: 15 additions & 4 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import "./index.css"
import { useI18n } from "@solid-primitives/i18n"
import { initialLang, langMap, loadedLangs } from "./i18n"
import { Resp } from "~/types"
import { setArchiveExtensions } from "~/store/archive"

const Home = lazy(() => import("~/pages/home/Layout"))
const Manage = lazy(() => import("~/pages/manage"))
Expand All @@ -44,7 +45,7 @@ const App: Component = () => {
bus.emit("pathname", pathname())
})

const [err, setErr] = createSignal<string>()
const [err, setErr] = createSignal<string[]>([])
const [loading, data] = useLoading(() =>
Promise.all([
(async () => {
Expand All @@ -55,7 +56,14 @@ const App: Component = () => {
handleRespWithoutAuthAndNotify(
(await r.get("/public/settings")) as Resp<Record<string, string>>,
setSettings,
setErr,
(e) => setErr(err().concat(e)),
)
})(),
(async () => {
handleRespWithoutAuthAndNotify(
(await r.get("/public/archive_extensions")) as Resp<string[]>,
setArchiveExtensions,
(e) => setErr(err().concat(e)),
)
})(),
]),
Expand Down Expand Up @@ -101,11 +109,14 @@ const App: Component = () => {
</Routes>
}
>
<Match when={err() !== undefined}>
<Match when={err().length > 0}>
<Error
h="100vh"
msg={
t("home.fetching_settings_failed") + t("home." + (err() || ""))
t("home.fetching_settings_failed") +
err()
.map((e) => t("home." + e))
.join(", ")
}
/>
</Match>
Expand Down
8 changes: 7 additions & 1 deletion src/components/FolderTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
Setter,
createEffect,
on,
JSXElement,
} from "solid-js"
import { useFetch, useT, useUtil } from "~/hooks"
import { getMainColor, password } from "~/store"
Expand Down Expand Up @@ -192,6 +193,8 @@ export type ModalFolderChooseProps = {
type?: string
defaultValue?: string
loading?: boolean
children?: JSXElement
header: string
}
export const ModalFolderChoose = (props: ModalFolderChooseProps) => {
const t = useT()
Expand All @@ -211,8 +214,11 @@ export const ModalFolderChoose = (props: ModalFolderChooseProps) => {
<ModalOverlay />
<ModalContent>
{/* <ModalCloseButton /> */}
<ModalHeader>{t("home.toolbar.choose_dst_folder")}</ModalHeader>
<ModalHeader w="$full" css={{ overflowWrap: "break-word" }}>
{props.header}
</ModalHeader>
<ModalBody>
{props.children}
<FolderTree
onChange={setValue}
handle={(h) => setHandler(h)}
Expand Down
10 changes: 10 additions & 0 deletions src/lang/en/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@
"choose_dst_folder": "Select destination folder",
"delete": "Delete",
"delete-tips": "Are you sure to delete the selected object?",
"decompress": "Decompress",
"decompress-pass": "Extraction password: ",
"decompress-cache-full": "Cache full into a temp-file",
"decompress-put-into-new": "Decompress into a new sub-folder",
"extract": "Extract to",
"archive": {
"input_password": "Please input extraction password",
"incorrect_password": "Incorrect password",
"extract_header": "Extract {{path}} to..."
},
"copy_link": "Copy link",
"preview_page": "Preview page",
"down_link": "Download link",
Expand Down
1 change: 1 addition & 0 deletions src/lang/en/manage.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"tasks": "Tasks",
"upload": "Upload",
"copy": "Copy",
"decompress": "Decompress",
"backup-restore": "Backup & Restore",
"home": "Home",
"indexes": "Indexes",
Expand Down
8 changes: 8 additions & 0 deletions src/lang/en/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"offline_download_transfer": "Transfer downloaded file to corresponding storage",
"upload": "Upload file to corresponding storage",
"copy": "Copy file from a storage to another storage",
"decompress": "Download and decompress an archive file",
"decompress_upload": "Upload extracted file into target storage",
"done": "Completed",
"undone": "Running",
"clear_succeeded": "Clear Succeeded",
Expand Down Expand Up @@ -48,6 +50,12 @@
"transfer_src": "Source Path",
"transfer_dst": "Destination Path"
},
"decompress": {
"src": "Source Path",
"dst": "Destination Path",
"inner": "Inner Path",
"password": "Extraction Password"
},
"time_elapsed": "Time Elapsed",
"status": "Status",
"err": "Error"
Expand Down
4 changes: 3 additions & 1 deletion src/lang/en/users.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"webdav_read": "Webdav read",
"webdav_manage": "Webdav manage",
"ftp_read": "FTP read",
"ftp_manage": "FTP manage"
"ftp_manage": "FTP manage",
"read_archives": "Read archives",
"decompress": "Decompress"
},
"username": "Username",
"password": "Password",
Expand Down
35 changes: 29 additions & 6 deletions src/pages/home/Obj.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useColorModeValue, VStack } from "@hope-ui/solid"
import { Text, useColorModeValue, VStack } from "@hope-ui/solid"
import {
Suspense,
Switch,
Expand All @@ -8,9 +8,15 @@ import {
on,
createSignal,
} from "solid-js"
import { FullLoading, Error } from "~/components"
import { resetGlobalPage, useObjTitle, usePath, useRouter } from "~/hooks"
import { objStore, recordScroll, /*layout,*/ State } from "~/store"
import { FullLoading, Error, LinkWithBase } from "~/components"
import { resetGlobalPage, useObjTitle, usePath, useRouter, useT } from "~/hooks"
import {
objStore,
recordScroll,
/*layout,*/ State,
password,
setPassword,
} from "~/store"

const Folder = lazy(() => import("./folder/Folder"))
const File = lazy(() => import("./file/File"))
Expand All @@ -23,9 +29,10 @@ export { objBoxRef }

let first = true
export const Obj = () => {
const t = useT()
const cardBg = useColorModeValue("white", "$neutral3")
const { pathname } = useRouter()
const { handlePathChange } = usePath()
const { handlePathChange, refresh } = usePath()
let lastPathname = pathname()
createEffect(
on(pathname, (pathname) => {
Expand Down Expand Up @@ -66,7 +73,23 @@ export const Obj = () => {
</Show> */}
</Match>
<Match when={objStore.state === State.NeedPassword}>
<Password />
<Password
title={t("home.input_password")}
password={password}
setPassword={setPassword}
enterCallback={() => refresh(true)}
>
<Text>{t("global.have_account")}</Text>
<Text
color="$info9"
as={LinkWithBase}
href={`/@login?redirect=${encodeURIComponent(
location.pathname,
)}`}
>
{t("global.go_login")}
</Text>
</Password>
</Match>
<Match
when={[State.Folder, State.FetchingMore].includes(objStore.state)}
Expand Down
37 changes: 19 additions & 18 deletions src/pages/home/Password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ import {
useColorModeValue,
VStack,
} from "@hope-ui/solid"
import { LinkWithBase } from "~/components"
import { usePath, useRouter, useT } from "~/hooks"
import { password, setPassword } from "~/store"
import { useRouter, useT } from "~/hooks"
import { JSXElement } from "solid-js"

const Password = () => {
type PasswordProps = {
title: string
password: () => string
setPassword: (s: string) => void
enterCallback: () => void
children?: JSXElement
}

const Password = (props: PasswordProps) => {
const t = useT()
const { refresh } = usePath()
const { back } = useRouter()
return (
<VStack
Expand All @@ -26,17 +32,17 @@ const Password = () => {
spacing="$3"
alignItems="start"
>
<Heading>{t("home.input_password")}</Heading>
<Heading>{props.title}</Heading>
<Input
type="password"
value={password()}
value={props.password()}
background={useColorModeValue("$neutral3", "$neutral2")()}
onKeyDown={(e) => {
if (e.key === "Enter") {
refresh(true)
props.enterCallback()
}
}}
onInput={(e) => setPassword(e.currentTarget.value)}
onInput={(e) => props.setPassword(e.currentTarget.value)}
/>
<HStack w="$full" justifyContent="space-between">
<Flex
Expand All @@ -45,20 +51,15 @@ const Password = () => {
direction={{ "@initial": "column", "@sm": "row" }}
columnGap="$1"
>
<Text>{t("global.have_account")}</Text>
<Text
color="$info9"
as={LinkWithBase}
href={`/@login?redirect=${encodeURIComponent(location.pathname)}`}
>
{t("global.go_login")}
</Text>
{props.children}
</Flex>
<HStack spacing="$2">
<Button colorScheme="neutral" onClick={back}>
{t("global.back")}
</Button>
<Button onClick={() => refresh(true)}>{t("global.ok")}</Button>
<Button onClick={() => props.enterCallback()}>
{t("global.ok")}
</Button>
</HStack>
</HStack>
</VStack>
Expand Down
61 changes: 35 additions & 26 deletions src/pages/home/folder/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ import { Col, cols, ListItem } from "./ListItem"
import { ItemCheckbox, useSelectWithMouse } from "./helper"
import { bus } from "~/utils"

const ListLayout = () => {
export const ListTitle = (props: {
sortCallback: (orderBy: OrderBy, reverse?: boolean) => void
disableCheckbox?: boolean
}) => {
const t = useT()
const [orderBy, setOrderBy] = createSignal<OrderBy>()
const [reverse, setReverse] = createSignal(false)
createEffect(() => {
if (orderBy()) {
sortObjs(orderBy()!, reverse())
props.sortCallback(orderBy()!, reverse())
}
})
const itemProps = (col: Col) => {
Expand All @@ -42,6 +45,35 @@ const ListLayout = () => {
},
}
}
return (
<HStack class="title" w="$full" p="$2">
<HStack w={cols[0].w} spacing="$1">
<Show when={!props.disableCheckbox && checkboxOpen()}>
<ItemCheckbox
checked={allChecked()}
indeterminate={isIndeterminate()}
onChange={(e: any) => {
selectAll(e.target.checked as boolean)
}}
/>
</Show>
<Text {...itemProps(cols[0])}>{t(`home.obj.${cols[0].name}`)}</Text>
</HStack>
<Text w={cols[1].w} {...itemProps(cols[1])}>
{t(`home.obj.${cols[1].name}`)}
</Text>
<Text
w={cols[2].w}
{...itemProps(cols[2])}
display={{ "@initial": "none", "@md": "inline" }}
>
{t(`home.obj.${cols[2].name}`)}
</Text>
</HStack>
)
}

const ListLayout = () => {
const onDragOver = (e: DragEvent) => {
const items = Array.from(e.dataTransfer?.items ?? [])
for (let i = 0; i < items.length; i++) {
Expand All @@ -65,30 +97,7 @@ const ListLayout = () => {
w="$full"
spacing="$1"
>
<HStack class="title" w="$full" p="$2">
<HStack w={cols[0].w} spacing="$1">
<Show when={checkboxOpen()}>
<ItemCheckbox
checked={allChecked()}
indeterminate={isIndeterminate()}
onChange={(e: any) => {
selectAll(e.target.checked as boolean)
}}
/>
</Show>
<Text {...itemProps(cols[0])}>{t(`home.obj.${cols[0].name}`)}</Text>
</HStack>
<Text w={cols[1].w} {...itemProps(cols[1])}>
{t(`home.obj.${cols[1].name}`)}
</Text>
<Text
w={cols[2].w}
{...itemProps(cols[2])}
display={{ "@initial": "none", "@md": "inline" }}
>
{t(`home.obj.${cols[2].name}`)}
</Text>
</HStack>
<ListTitle sortCallback={sortObjs} />
<For each={objStore.objs}>
{(obj, i) => {
return <ListItem obj={obj} index={i()} />
Expand Down
Loading

0 comments on commit 17eda9a

Please sign in to comment.