Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/hooks/useLink.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { objStore, selectedObjs, State, me } from "~/store"
import { Obj } from "~/types"
import { Obj, ArchiveObj } from "~/types"
import {
base_path,
api,
Expand Down Expand Up @@ -36,6 +36,12 @@ export const getLinkByDirAndObj = (
if (!api.startsWith(location.origin + base_path))
host = location.origin + base_path
}
const { inner_path, archive } = obj as ArchiveObj
if (archive) {
prefix = "/ae"
path = `${dir}/${archive.name}`
path = encodePath(path, encodeAll)
}
let ans = `${host}${prefix}${path}`
if (type !== "preview" && !isShare && obj.sign) {
ans += `?sign=${obj.sign}`
Expand All @@ -46,6 +52,10 @@ export const getLinkByDirAndObj = (
ans += `?pwd=${pwd}`
}
}
if (archive) {
let inner = `${inner_path}/${obj.name}`
ans += `${ans.includes("?") ? "&" : "?"}inner=${encodePath(inner, encodeAll)}`
}
return ans
}

Expand Down
240 changes: 190 additions & 50 deletions src/pages/home/previews/archive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,35 @@ import {
Match,
Show,
Switch,
Suspense,
onCleanup,
} from "solid-js"
import { getMainColor, local, me, OrderBy, password } from "~/store"
import { Obj, ObjTree, UserMethods, UserPermissions } from "~/types"
import { useFetch, useRouter, useT, useUtil } from "~/hooks"
import { Dynamic } from "solid-js/web"
import {
getMainColor,
local,
me,
OrderBy,
password,
objStore,
ObjStore,
} from "~/store"
import {
Obj,
ObjTree,
UserMethods,
UserPermissions,
ObjType,
ArchiveObj,
} from "~/types"
import { useFetch, useRouter, useT, useUtil, useLink } from "~/hooks"
import { ListTitle } from "~/pages/home/folder/List"
import { cols } from "~/pages/home/folder/ListItem"
import { Error, MaybeLoading } from "~/components"
import { Error, MaybeLoading, FullLoading, SelectWrapper } from "~/components"
import { OpenWith } from "../file/open-with"
import { getPreviews } from "."
import {
bus,
encodePath,
formatDate,
fsArchiveList,
fsArchiveMeta,
Expand Down Expand Up @@ -58,6 +77,7 @@ type ListItemProps = {
innerPath: string
url?: string
pass: string
onFileClick?: () => void
}

const ListItem = (props: ListItemProps) => {
Expand Down Expand Up @@ -88,8 +108,8 @@ const ListItem = (props: ListItemProps) => {
on:click={(_: MouseEvent) => {
if (props.obj.is_dir) {
props.jumpCallback()
} else if (props.url) {
download(props.url)
} else if (!props.obj.is_dir && props.onFileClick) {
props.onFileClick()
}
}}
onContextMenu={(e: MouseEvent) => {
Expand Down Expand Up @@ -219,6 +239,7 @@ type List = {
const Preview = () => {
const t = useT()
const { pathname } = useRouter()
const { rawLink } = useLink()
const [metaLoading, fetchMeta] = useFetch(fsArchiveMeta)
const [listLoading, fetchList] = useFetch(fsArchiveList)
const loading = createMemo(() => {
Expand All @@ -238,6 +259,8 @@ const Preview = () => {
const [extractFolder, setExtractFolder] = createSignal<"" | "front" | "back">(
"",
)
const [selectedFile, setSelectedFile] = createSignal<string>("")
const [selectedPreviewName, setSelectedPreviewName] = createSignal("")
const getObjsMutex = createMutex()
const toList = (tree: ObjTree[] | Obj[]): List => {
let l: List = {}
Expand Down Expand Up @@ -361,6 +384,20 @@ const Preview = () => {
}
return ret
}
// Build inner file url for current path by filename
const buildInnerUrl = (name: string) => {
const innerPath =
(innerPaths().length > 0 ? "/" + innerPaths().join("/") : "") + "/" + name
return innerPath
}
// Build obj with inner property
const buildObjWithInner = (obj: Obj): ArchiveObj => {
const innerPath =
innerPaths().length > 0 ? "/" + innerPaths().join("/") : ""

return { ...obj, sign: sign, inner_path: innerPath, archive: originalObj }
}

const sortObjs = (orderBy: OrderBy, reverse?: boolean) => {
batch(() => {
setExtractFolder("")
Expand All @@ -370,13 +407,79 @@ const Preview = () => {
}
})
}

// Get all files for navigation
const files = createMemo(() =>
sortedObjs()
.filter((obj) => !obj.is_dir)
.map((f) => buildObjWithInner(f)),
)

const previews = createMemo(() => {
const file = files().find((f) => f.name === selectedFile())
if (!file) return []

return getPreviews({ ...file, provider: objStore.provider })
})

const currentPreview = createMemo(() => {
const p = previews()
if (p.length === 0) return null
if (selectedPreviewName()) {
const found = p.find((item) => item.name === selectedPreviewName())
if (found) return found
}
return p[0]
})

// Cast to ArchiveObj to make sure onCleanup can delete archive property correctly
const originalObj: ArchiveObj = {
...objStore.obj,
inner_path: undefined,
archive: undefined,
}
const originalRawUrl = objStore.raw_url

const changeFile = (name: string) => {
batch(() => {
if (name === "") {
// Restore
ObjStore.setObj(originalObj)
ObjStore.setRawUrl(originalRawUrl)
setSelectedFile("")
} else {
// Set new
const file = files().find((f) => f.name === name)
if (file) {
const innerUrl = rawLink(file)
ObjStore.setObj(file)
ObjStore.setRawUrl(innerUrl)
setSelectedFile(name)
}
}
})
}

onCleanup(() => {
// Restore original values
ObjStore.setObj(originalObj)
ObjStore.setRawUrl(originalRawUrl)
})

createEffect(() => {
selectedFile()
setSelectedPreviewName("")
})
return (
<VStack spacing="$2" w="$full">
<Breadcrumb pl="$2" pr="$2" w="$full">
<BreadcrumbItem>
<BreadcrumbLink
currentPage={innerPaths().length === 0}
on:click={() => setInnerPaths([])}
currentPage={innerPaths().length === 0 && !selectedFile()}
on:click={() => {
setInnerPaths([])
changeFile("")
}}
>
.
</BreadcrumbLink>
Expand All @@ -386,14 +489,23 @@ const Preview = () => {
<BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbLink
currentPage={innerPaths().length === i() + 1}
on:click={() => setInnerPaths(innerPaths().slice(0, i() + 1))}
currentPage={innerPaths().length === i() + 1 && !selectedFile()}
on:click={() => {
setInnerPaths(innerPaths().slice(0, i() + 1))
changeFile("")
}}
>
{name}
</BreadcrumbLink>
</BreadcrumbItem>
)}
</For>
<Show when={selectedFile()}>
<BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbLink currentPage={true}>{selectedFile()}</BreadcrumbLink>
</BreadcrumbItem>
</Show>
</Breadcrumb>
<Switch>
<Match when={error() !== ""}>
Expand All @@ -414,47 +526,75 @@ const Preview = () => {
</Password>
</Match>
<Match when={!requiringPassword() && error() === ""}>
<MaybeLoading loading={loading()}>
<VStack class="list" w="$full" spacing="$1">
<ListTitle sortCallback={sortObjs} disableCheckbox />
<For each={sortedObjs()}>
{(obj, i) => {
let url = undefined
let innerPath =
(innerPaths().length > 0
? "/" + innerPaths().join("/")
: "") +
"/" +
obj.name
if (!obj.is_dir) {
const hasQuery = raw_url.includes("?")
url =
raw_url +
`${hasQuery ? "&" : "?"}inner=${encodePath(innerPath, true)}`
if (archive_pass !== "") {
url = url + `&pass=${encodeURIComponent(archive_pass)}`
}
if (sign !== "") {
url = url + `&sign=${sign}`
}
}
return (
<ListItem
obj={obj}
index={i()}
jumpCallback={() =>
setInnerPaths(innerPaths().concat(obj.name))
<Show
when={selectedFile()}
fallback={
<MaybeLoading loading={loading()}>
<VStack class="list" w="$full" spacing="$1">
<ListTitle sortCallback={sortObjs} disableCheckbox />
<For each={sortedObjs()}>
{(obj, i) => {
const objWithInner = buildObjWithInner(obj)
// Use rawLink to construct the URL for the object
let url = !obj.is_dir ? rawLink(objWithInner) : undefined
let innerPath = buildInnerUrl(obj.name)
return (
<ListItem
obj={obj}
index={i()}
jumpCallback={() =>
setInnerPaths(innerPaths().concat(obj.name))
}
innerPath={innerPath}
url={url}
pass={archive_pass}
onFileClick={() => changeFile(obj.name)}
/>
)
}}
</For>
<ContextMenu />
</VStack>
</MaybeLoading>
}
>
<Show when={selectedFile()} fallback={<FullLoading />}>
<VStack w="$full" spacing="$2" alignItems="center">
<Show when={currentPreview()}>
<Suspense fallback={<FullLoading />}>
<Dynamic
component={currentPreview()?.component}
images={files().filter((f) => f.type === ObjType.IMAGE)}
navigate={(name) => {
changeFile(name)
}}
/>
</Suspense>
</Show>
<HStack w="$full" justifyContent="center" spacing="$2" p="$2">
<Show when={previews().length > 1}>
<SelectWrapper
value={currentPreview()?.name || ""}
onChange={(value) =>
setSelectedPreviewName(String(value))
}
innerPath={innerPath}
url={url}
pass={archive_pass}
options={previews().map((p) => ({
value: p.name,
label: p.name,
}))}
/>
)
}}
</For>
<ContextMenu />
</VStack>
</MaybeLoading>
</Show>
<OpenWith
file={{
name: selectedFile(),
raw_url: objStore.raw_url,
d_url: objStore.raw_url,
}}
/>
</HStack>
</VStack>
</Show>
</Show>
</Match>
</Switch>
<Show when={comment() !== ""}>
Expand Down
Loading