Add cloud breadcrumbs and even out cloud cards
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
app,
|
app,
|
||||||
breadcrumbs,
|
breadcrumbs,
|
||||||
browseTo,
|
browseTo,
|
||||||
|
cloudBreadcrumbs,
|
||||||
linkedDocument,
|
linkedDocument,
|
||||||
linkedSpace,
|
linkedSpace,
|
||||||
openCloudFolder,
|
openCloudFolder,
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
let menuAt = $state({ x: 0, y: 0 });
|
let menuAt = $state({ x: 0, y: 0 });
|
||||||
|
|
||||||
const trail = $derived(breadcrumbs());
|
const trail = $derived(breadcrumbs());
|
||||||
|
const cloudTrail = $derived(cloudBreadcrumbs());
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (app.scope === "cloud" && app.account) {
|
if (app.scope === "cloud" && app.account) {
|
||||||
@@ -200,10 +202,10 @@
|
|||||||
<div
|
<div
|
||||||
class="group flex flex-col overflow-hidden rounded-lg border border-[var(--color-line)] bg-[var(--color-surface)] transition hover:border-[var(--color-accent)] hover:shadow-sm"
|
class="group flex flex-col overflow-hidden rounded-lg border border-[var(--color-line)] bg-[var(--color-surface)] transition hover:border-[var(--color-accent)] hover:shadow-sm"
|
||||||
>
|
>
|
||||||
{#if link && cloudThumbs[link.path]}
|
|
||||||
<div
|
<div
|
||||||
class="flex h-24 items-center justify-center overflow-hidden border-b border-[var(--color-line)] bg-[var(--color-surface-muted)]"
|
class="flex h-24 items-center justify-center overflow-hidden border-b border-[var(--color-line)] bg-[var(--color-surface-muted)]"
|
||||||
>
|
>
|
||||||
|
{#if link && cloudThumbs[link.path]}
|
||||||
{#if cloudThumbs[link.path].kind === "svg"}
|
{#if cloudThumbs[link.path].kind === "svg"}
|
||||||
<span
|
<span
|
||||||
class="flex w-full items-start justify-center bg-white p-1 [&_svg]:h-auto [&_svg]:w-full"
|
class="flex w-full items-start justify-center bg-white p-1 [&_svg]:h-auto [&_svg]:w-full"
|
||||||
@@ -217,12 +219,18 @@
|
|||||||
class="h-full w-full object-contain"
|
class="h-full w-full object-contain"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
{:else}
|
||||||
|
<Icon
|
||||||
|
{icon}
|
||||||
|
class="text-3xl {link
|
||||||
|
? 'text-[var(--color-accent)]'
|
||||||
|
: 'text-[var(--color-ink-muted)]'}"
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2.5 p-3">
|
<div class="flex flex-col gap-2.5 p-3">
|
||||||
<div class="flex items-start gap-2">
|
<div class="flex items-start gap-2">
|
||||||
<Icon {icon} class="shrink-0 text-xl text-[var(--color-accent)]" />
|
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="truncate text-xs font-medium" {title}>{title}</p>
|
<p class="truncate text-xs font-medium" {title}>{title}</p>
|
||||||
<p class="truncate text-[10px] text-[var(--color-ink-muted)]">{meta}</p>
|
<p class="truncate text-[10px] text-[var(--color-ink-muted)]">{meta}</p>
|
||||||
@@ -676,6 +684,33 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if cloudTrail.length > 0}
|
||||||
|
<div class="mb-3 flex flex-wrap items-center gap-1 text-xs">
|
||||||
|
<button
|
||||||
|
class="rounded px-2 py-1 text-[var(--color-ink-muted)] transition hover:bg-[var(--color-surface)] hover:text-[var(--color-ink)]"
|
||||||
|
onclick={() => openCloudFolder(null)}
|
||||||
|
>
|
||||||
|
My Drive
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#each cloudTrail as folder, index}
|
||||||
|
<Icon
|
||||||
|
icon="ph:caret-right"
|
||||||
|
class="text-[10px] text-[var(--color-ink-muted)]"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="rounded px-2 py-1 transition hover:bg-[var(--color-surface)]
|
||||||
|
{index === cloudTrail.length - 1
|
||||||
|
? 'font-medium'
|
||||||
|
: 'text-[var(--color-ink-muted)] hover:text-[var(--color-ink)]'}"
|
||||||
|
onclick={() => openCloudFolder(folder.id)}
|
||||||
|
>
|
||||||
|
{folder.name}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if app.cloudFolders.length > 0}
|
{#if app.cloudFolders.length > 0}
|
||||||
<div
|
<div
|
||||||
class="mb-4 grid grid-cols-[repeat(auto-fill,minmax(210px,1fr))] gap-2"
|
class="mb-4 grid grid-cols-[repeat(auto-fill,minmax(210px,1fr))] gap-2"
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ interface AppState {
|
|||||||
spaces: SpaceSummary[];
|
spaces: SpaceSummary[];
|
||||||
cloudFolder: string | null | "shared";
|
cloudFolder: string | null | "shared";
|
||||||
cloudFolders: CloudFolder[];
|
cloudFolders: CloudFolder[];
|
||||||
|
cloudFolderTree: CloudFolder[];
|
||||||
cloudDocuments: CloudDocument[];
|
cloudDocuments: CloudDocument[];
|
||||||
cloudFiles: CloudFile[];
|
cloudFiles: CloudFile[];
|
||||||
cloudLoading: boolean;
|
cloudLoading: boolean;
|
||||||
@@ -65,6 +66,7 @@ export const app = $state<AppState>({
|
|||||||
spaces: [],
|
spaces: [],
|
||||||
cloudFolder: null,
|
cloudFolder: null,
|
||||||
cloudFolders: [],
|
cloudFolders: [],
|
||||||
|
cloudFolderTree: [],
|
||||||
cloudDocuments: [],
|
cloudDocuments: [],
|
||||||
cloudFiles: [],
|
cloudFiles: [],
|
||||||
cloudLoading: false,
|
cloudLoading: false,
|
||||||
@@ -188,6 +190,7 @@ export async function refreshCloud() {
|
|||||||
api.cloudListSpaces(),
|
api.cloudListSpaces(),
|
||||||
api.cloudListFiles(app.cloudFolder),
|
api.cloudListFiles(app.cloudFolder),
|
||||||
]);
|
]);
|
||||||
|
app.cloudFolderTree = folders;
|
||||||
app.cloudFolders = folders.filter(
|
app.cloudFolders = folders.filter(
|
||||||
(folder) => (folder.parent_id ?? null) === app.cloudFolder,
|
(folder) => (folder.parent_id ?? null) === app.cloudFolder,
|
||||||
);
|
);
|
||||||
@@ -202,6 +205,22 @@ export async function refreshCloud() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Trail from the drive root down to the folder being viewed. */
|
||||||
|
export function cloudBreadcrumbs(): CloudFolder[] {
|
||||||
|
if (app.cloudFolder === "shared" || app.cloudFolder === null) return [];
|
||||||
|
|
||||||
|
const byId = new Map(app.cloudFolderTree.map((folder) => [folder.id, folder]));
|
||||||
|
const trail: CloudFolder[] = [];
|
||||||
|
|
||||||
|
let current = byId.get(app.cloudFolder);
|
||||||
|
while (current) {
|
||||||
|
trail.unshift(current);
|
||||||
|
current = current.parent_id ? byId.get(current.parent_id) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trail;
|
||||||
|
}
|
||||||
|
|
||||||
export async function openCloudFolder(id: string | null | "shared") {
|
export async function openCloudFolder(id: string | null | "shared") {
|
||||||
app.cloudFolder = id;
|
app.cloudFolder = id;
|
||||||
await refreshCloud();
|
await refreshCloud();
|
||||||
|
|||||||
Reference in New Issue
Block a user