um
This commit is contained in:
parent
9240263490
commit
5e5fc372cc
3 changed files with 94 additions and 73 deletions
|
@ -8,7 +8,13 @@ export const client = ky.create({
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
file: async (uid: string) => await client.get<Blob>(uid),
|
file: async (uid: string) => await client.get<Blob>(uid),
|
||||||
list: async () => await client.get('list').json<StereoFile[]>(),
|
list: async (page?: number, size?: number) => {
|
||||||
|
const searchParams = new URLSearchParams();
|
||||||
|
if (page !== undefined) searchParams.append('page', String(page));
|
||||||
|
if (size !== undefined) searchParams.append('size', String(size));
|
||||||
|
|
||||||
|
return await client.get('list', { searchParams }).json<StereoFile[]>();
|
||||||
|
},
|
||||||
upload: async (file: File) => {
|
upload: async (file: File) => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { RequestEvent, RequestHandler } from '@builder.io/qwik-city';
|
import type { RequestEvent, RequestHandler } from '@builder.io/qwik-city';
|
||||||
|
|
||||||
const proxy = async ({ send, url, pathname, request }: RequestEvent) => {
|
const proxy = async ({ send, url, pathname, request }: RequestEvent) => {
|
||||||
const targetUrl = new URL(`http://localhost:8081${pathname}`, url);
|
const targetUrl = new URL(`http://localhost:8081${pathname}${url.search}`, url);
|
||||||
const headers = new Headers(request.headers);
|
const headers = new Headers(request.headers);
|
||||||
|
|
||||||
const fetchOptions: RequestInit = {
|
const fetchOptions: RequestInit = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { component$, Signal, useSignal, useTask$, useVisibleTask$ } from "@builder.io/qwik";
|
import { $, component$, Signal, useSignal, useTask$, useVisibleTask$ } from "@builder.io/qwik";
|
||||||
import { routeLoader$, type DocumentHead } from "@builder.io/qwik-city";
|
import { routeLoader$, type DocumentHead } from "@builder.io/qwik-city";
|
||||||
import Actionbar from "~/components/dashboard/Actionbar";
|
import Actionbar from "~/components/dashboard/Actionbar";
|
||||||
import Settings from "~/components/dashboard/Settings";
|
import Settings from "~/components/dashboard/Settings";
|
||||||
|
@ -35,7 +35,7 @@ export default component$(() => {
|
||||||
<Actionbar />
|
<Actionbar />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const formatSize = (bytes: number) => {
|
const formatSize = (bytes: number) => {
|
||||||
|
@ -50,81 +50,96 @@ const Files = component$<{
|
||||||
files: Signal<StereoFile[]>;
|
files: Signal<StereoFile[]>;
|
||||||
loaded: Signal<boolean>;
|
loaded: Signal<boolean>;
|
||||||
}>(({ files }) => {
|
}>(({ files }) => {
|
||||||
const File = component$(({ file }: { file: StereoFile }) => {
|
const File = component$(({ file }: { file: StereoFile }) => {
|
||||||
const Preview = component$(() => {
|
const Preview = component$(() => {
|
||||||
type FileType = "image" | "video" | "audio" | "other";
|
type FileType = "image" | "video" | "audio" | "other";
|
||||||
const fileType: Signal<FileType> = useSignal<FileType>("other");
|
const fileType: Signal<FileType> = useSignal<FileType>("other");
|
||||||
const type = file.Mime.split("/")[1];
|
const type = file.Mime.split("/")[1];
|
||||||
useTask$(() => {
|
|
||||||
if (["jpeg", "jpg", "png", "gif", "webp"].includes(type)) fileType.value = "image";
|
useTask$(() => {
|
||||||
else if (["mp4", "webm", "ogg", "avi", "mov"].includes(type)) fileType.value = "video";
|
if (["jpeg", "jpg", "png", "gif", "webp"].includes(type)) fileType.value = "image";
|
||||||
else if (["mp3", "wav", "flac", "aac"].includes(type)) fileType.value = "audio";
|
else if (["mp4", "webm", "ogg", "avi", "mov"].includes(type)) fileType.value = "video";
|
||||||
else fileType.value = "other";
|
else if (["mp3", "wav", "flac", "aac"].includes(type)) fileType.value = "audio";
|
||||||
});
|
else fileType.value = "other";
|
||||||
return (
|
});
|
||||||
<div class="w-full h-max object-cover flex-grow relative overflow-clip">
|
|
||||||
{fileType.value === "image" && (
|
return (
|
||||||
// eslint-disable-next-line qwik/jsx-img
|
<div class="w-full h-max object-cover flex-grow relative overflow-clip">
|
||||||
<img
|
{fileType.value === "image" && (
|
||||||
width={400}
|
// eslint-disable-next-line qwik/jsx-img
|
||||||
src={`/api/${file.ID}`}
|
<img
|
||||||
alt={file.Name}
|
width={400}
|
||||||
class="w-full min-h-30 object-cover flex-grow hover:scale-[102.5%] transition-all duration-500"
|
src={`/api/${file.ID}`}
|
||||||
/>
|
alt={file.Name}
|
||||||
)}
|
class="w-full min-h-30 object-cover flex-grow hover:scale-[102.5%] transition-all duration-500"
|
||||||
{fileType.value === "video" && (
|
/>
|
||||||
<video
|
)}
|
||||||
width={400}
|
{fileType.value === "video" && (
|
||||||
src={`/api/${file.ID}`}
|
<video
|
||||||
controls
|
width={400}
|
||||||
class="w-full min-h-30 object-cover flex-grow hover:scale-[102.5%] transition-all duration-500"
|
src={`/api/${file.ID}`}
|
||||||
/>
|
controls
|
||||||
)}
|
class="w-full min-h-30 object-cover flex-grow hover:scale-[102.5%] transition-all duration-500"
|
||||||
{fileType.value === "audio" && (
|
/>
|
||||||
<audio
|
)}
|
||||||
src={`/api/${file.ID}`}
|
{fileType.value === "audio" && (
|
||||||
controls
|
<audio
|
||||||
class="w-full min-h-30 object-cover flex-grow hover:scale-[102.5%] transition-all duration-500"
|
src={`/api/${file.ID}`}
|
||||||
/>
|
controls
|
||||||
)}
|
class="w-full min-h-30 object-cover flex-grow hover:scale-[102.5%] transition-all duration-500"
|
||||||
{fileType.value === "other" && (
|
/>
|
||||||
<div class="w-full min-h-30 flex items-center justify-center bg-gray-200 text-gray-500">
|
)}
|
||||||
<p>Unsupported file type</p>
|
{fileType.value === "other" && (
|
||||||
|
<div class="w-full min-h-30 flex items-center justify-center bg-gray-200 text-gray-500">
|
||||||
|
<p>Unsupported file type</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"linear-gradient(180deg, rgba(255, 38, 78, 0.00) 57.21%, rgba(255, 38, 78, 0.17) 100%); ",
|
||||||
|
boxShadow: "0px 4px 21.2px 2px rgba(255, 38, 78, 0.05)",
|
||||||
|
}}
|
||||||
|
class="transition-all rounded-3xl flex flex-col overflow-clip items-center justify-center mb-4 break-inside-avoid"
|
||||||
|
>
|
||||||
|
<Preview />
|
||||||
|
<div class="flex flex-col items-center justify-center text-center w-full h-full p-5">
|
||||||
|
<p class="text-xl truncate w-full">{file.Name}</p>
|
||||||
|
<p class="text-stereo/50 text-lg">
|
||||||
|
{formatSize(file.Size)}
|
||||||
|
<span class="text-stereo/40"> • </span>
|
||||||
|
Uploaded on {new Date(file.CreatedAt).toLocaleDateString()}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loadingMore = useSignal(false);
|
||||||
|
|
||||||
|
const onScroll = $(async (e: Event) => {
|
||||||
|
const element = e.target as HTMLElement;
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
const isAtBottom = element.scrollHeight - element.scrollTop - element.clientHeight < threshold;
|
||||||
|
if (isAtBottom) {
|
||||||
|
console.log("Loading more files...");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class="px-2 mb-6 flex-grow overflow-y-auto mask-clip-content rounded-3xl" onScroll$={onScroll}>
|
||||||
style={{
|
<div class="w-full columns-1 md:columns-2 lg:columns-4 gap-2 space-y-2">
|
||||||
background:
|
{files.value.map((file) => (
|
||||||
"linear-gradient(180deg, rgba(255, 38, 78, 0.00) 57.21%, rgba(255, 38, 78, 0.17) 100%); ",
|
<File key={file.ID} file={file} />
|
||||||
boxShadow: "0px 4px 21.2px 2px rgba(255, 38, 78, 0.05)",
|
))}
|
||||||
}}
|
</div>
|
||||||
class="transition-all rounded-3xl flex flex-col overflow-clip items-center justify-center mb-4 break-inside-avoid"
|
|
||||||
>
|
|
||||||
<Preview />
|
|
||||||
<div class="flex flex-col items-center justify-center text-center w-full h-full p-5">
|
|
||||||
<p class="text-xl truncate w-full">{file.Name}</p>
|
|
||||||
<p class="text-stereo/50 text-lg">
|
|
||||||
{formatSize(file.Size)}
|
|
||||||
<span class="text-stereo/40"> • </span>
|
|
||||||
Uploaded on {new Date(file.CreatedAt).toLocaleDateString()}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div class="px-2 mb-6 flex-grow overflow-y-auto mask-clip-content rounded-3xl">
|
|
||||||
<div class="w-full columns-1 md:columns-2 lg:columns-4 gap-2 space-y-2">
|
|
||||||
{files.value.map((file) => (
|
|
||||||
<File key={file.ID} file={file} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const head: DocumentHead = {
|
export const head: DocumentHead = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue