new settings layout

This commit is contained in:
grngxd 2025-07-29 22:19:56 +01:00
parent 8e5dff01c0
commit 361c4e0b62
2 changed files with 180 additions and 116 deletions

View file

@ -39,114 +39,91 @@ export default component$(() => {
});
const formatSize = (bytes: number) => {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}
const Files = component$<{
files: Signal<StereoFile[]>;
loaded: Signal<boolean>;
files: Signal<StereoFile[]>;
loaded: Signal<boolean>;
}>(({ files }) => {
const File = component$(({ file }: { file: StereoFile }) => {
const Preview = component$(() => {
type FileType =
| "image"
| "video"
| "audio"
| "other";
const fileType: Signal<FileType> = useSignal<FileType>("other");
const type = file.Mime.split("/")[1];
useTask$(async () => {
if (
["jpeg", "jpg", "png", "gif", "webp"]
.includes(type)
) fileType.value = "image";
else if (
["mp4", "webm", "ogg", "avi", "mov"]
.includes(type)
) fileType.value = "video";
else if (
["mp3", "wav", "flac", "aac"]
.includes(type)
) fileType.value = "audio";
else fileType.value = "other";
});
return (
<div class="w-full h-60 object-cover flex-grow relative overflow-clip">
{fileType.value === "image" && (
<img
width={400}
height={300}
src={`/api/${file.ID}`}
alt={file.Name}
class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300"
/>
)}
{fileType.value === "video" && (
<video
width={400}
height={300}
src={`/api/${file.ID}`}
controls
class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300"
/>
)}
{fileType.value === "audio" && (
<audio
src={`/api/${file.ID}`}
controls
class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300"
/>
)}
{fileType.value === "other" && (
<div class="w-full h-60 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">
<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>
)
})
return (
<div class="px-2 mb-6 flex flex-col w-full max-h-full overflow-y-auto overflow-x-hidden mask-clip-content rounded-3xl">
<div class="w-full h-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2">
{files.value.map((file) => (
<File key={file.ID} file={file} />
))}
const File = component$(({ file }: { file: StereoFile }) => {
const Preview = component$(() => {
type FileType = "image" | "video" | "audio" | "other";
const fileType: Signal<FileType> = useSignal<FileType>("other");
const type = file.Mime.split("/")[1];
useTask$(() => {
if (["jpeg", "jpg", "png", "gif", "webp"].includes(type)) fileType.value = "image";
else if (["mp4", "webm", "ogg", "avi", "mov"].includes(type)) fileType.value = "video";
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" && (
<img
width={400}
src={`/api/${file.ID}`}
alt={file.Name}
class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300"
/>
)}
{fileType.value === "video" && (
<video
width={400}
src={`/api/${file.ID}`}
controls
class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300"
/>
)}
{fileType.value === "audio" && (
<audio
src={`/api/${file.ID}`}
controls
class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300"
/>
)}
{fileType.value === "other" && (
<div class="w-full h-60 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>
);
});
return (
<div class="px-2 mb-6 flex flex-col w-full max-h-full overflow-y-auto overflow-x-hidden mask-clip-content rounded-3xl">
<div class="w-full h-full columns-1 md:columns-2 lg:columns-4 gap-2">
{files.value.map((file) => (
<File key={file.ID} file={file} />
))}
</div>
</div>
);
});
export const head: DocumentHead = {