From 0d29d599376a02ac74941407c644918b5327f5e8 Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Sat, 21 Jun 2025 16:15:33 +0100 Subject: [PATCH 01/27] change oauth link --- README.md | 9 ++++++--- src/routes/dashboard/index.tsx | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dbab72d..ec869d0 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # stereo.cat frontend -written in typescript with qwik +written in typescript with qwik & bun -## running in dev env -``` +## development +https://bun.sh/docs/installation + +```bash git clone https://git.iwakura.rip/stereo.cat/frontend.git git submodule update --init --recursive bun install @@ -11,4 +13,5 @@ bun dev ``` ## disclaimer + All graphic assets belonging to stereo.cat may not be used in unofficial instances, forks or versions of our software. Please replace them if you are hosting our software yourself, they can be found in the ``public`` folder in this repository. More information (like the full license) can be found [here](https://git.iwakura.rip/stereo.cat/public) diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index 98a3864..c2572c9 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -6,13 +6,14 @@ import File from "~/components/dashboard/File"; import { SolarUploadLinear, SvgSpinnersBarsRotateFade } from "~/components/misc/Icons"; import { useNanostore$ } from "~/hooks/nanostores"; import { api } from "~/lib/api"; +import { OAUTH_LINK } from "~/lib/constants"; import { areFilesLoaded, dashboardFiles } from "~/lib/stores"; import { StereoFile } from "~/lib/types"; export const useAuthCheck = routeLoader$(({ cookie, redirect: r }) => { const jwt = cookie.get("jwt"); if (jwt) return {}; - throw r(302, "/"); + throw r(302, OAUTH_LINK); }); export default component$(() => { From f47a1b22262161de5f72a64c38983d3564add7b2 Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Sat, 21 Jun 2025 17:02:52 +0100 Subject: [PATCH 02/27] templating dashboard & add user route to api client --- src/components/dashboard/Controlbar.tsx | 88 ----------- src/components/dashboard/File.tsx | 199 ------------------------ src/components/dashboard/OSBar.tsx | 9 ++ src/components/dashboard/TitleBar.tsx | 9 ++ src/lib/api.ts | 1 + src/lib/stores.ts | 5 +- src/lib/types.ts | 8 + src/routes/dashboard/index.tsx | 57 +++---- src/routes/layout.tsx | 11 +- 9 files changed, 58 insertions(+), 329 deletions(-) delete mode 100644 src/components/dashboard/Controlbar.tsx delete mode 100644 src/components/dashboard/File.tsx create mode 100644 src/components/dashboard/OSBar.tsx create mode 100644 src/components/dashboard/TitleBar.tsx diff --git a/src/components/dashboard/Controlbar.tsx b/src/components/dashboard/Controlbar.tsx deleted file mode 100644 index 45310c1..0000000 --- a/src/components/dashboard/Controlbar.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { $, component$, noSerialize, NoSerialize, useSignal, useVisibleTask$ } from "@builder.io/qwik"; -import { useNanostore$ } from "~/hooks/nanostores"; -import { api } from "~/lib/api"; -import { areFilesLoaded, dashboardFiles } from "~/lib/stores"; -import { StereoFile } from "~/lib/types"; -import { SolarUploadLinear, SvgSpinnersBarsRotateFade } from "../misc/Icons"; -import StereoLogo from "../misc/StereoLogo"; - -export default component$(() => { - const loaded = useNanostore$(areFilesLoaded); - const files = useNanostore$(dashboardFiles); - const fileInputRef = useSignal(); - const uploadingFiles = useSignal | undefined>(); - const now = useSignal(new Date()); - - useVisibleTask$(() => { - const interval = setInterval(() => { - now.value = new Date(); - }, 500); - return () => clearInterval(interval); - }); - - const uploadFiles = $(async () => { - if (!uploadingFiles.value) { - console.error("No file(s) selected for upload."); - return; - } - - try { - const ufiles = uploadingFiles.value as File[]; - - for (const file of ufiles) { - const name = file.name.replace(/[^a-zA-Z0-9_.-]/g, "_"); - const f = new File([file], name, { type: file.type }); - - await api.upload(f); - } - - files.value = await api.list(); - } catch (error) { - console.error("Error uploading file:", error); - } - }) - return ( -
- { - uploadingFiles.value = noSerialize(Object.values((e.target as HTMLInputElement).files || {})); - await uploadFiles(); - }} - multiple - /> - -
- {/* TODO: replace this button with a modal with options like settings log out etc */} - - -

|

- - -
-

{now.value.toLocaleTimeString()}

-
- ) -}) \ No newline at end of file diff --git a/src/components/dashboard/File.tsx b/src/components/dashboard/File.tsx deleted file mode 100644 index 50c1e02..0000000 --- a/src/components/dashboard/File.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { $, component$, Signal, useSignal, useTask$ } from "@builder.io/qwik"; -import { useNanostore$ } from "~/hooks/nanostores"; -import { api } from "~/lib/api"; -import { dashboardFiles } from "~/lib/stores"; -import { StereoFile } from "~/lib/types"; -import { SolarClipboardAddBold, SolarDownloadMinimalisticBold, SolarTrashBin2Bold } from "../misc/Icons"; - -type FileProps = { - file: StereoFile; -} - -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`; -} - -export default component$(({ file }: FileProps) => { - const files = useNanostore$(dashboardFiles); - - const deleteFile = $(async (id: string) => { - if (!confirm("Are you sure you want to delete this file?")) return; - await api.delete(id); - files.value = await api.list(); - }); - - const addFileToClipboard = $(async () => { - const response = await api.file(file.Name); - const data = await response.blob(); - let mime = data.type || "application/octet-stream"; - let clip; - - if (navigator.clipboard && window.ClipboardItem) { - if (mime === "image/jpeg" || mime === "image/jpg") { - const img = document.createElement("img"); - img.src = URL.createObjectURL(data); - await new Promise((res) => (img.onload = res)); - const canvas = document.createElement("canvas"); - canvas.width = img.width; - canvas.height = img.height; - const ctx = canvas.getContext("2d"); - ctx?.drawImage(img, 0, 0); - const png = await new Promise((resolve) => - canvas.toBlob((b) => resolve(b!), "image/png") - ); - mime = "image/png"; - clip = new ClipboardItem({ [mime]: png }); - } else { - clip = new ClipboardItem({ [mime]: data }); - } - - try { - await navigator.clipboard.write([clip]); - alert("File added to clipboard successfully!"); - } catch (error) { - console.error("Failed to add file to clipboard:", error); - alert("Failed to add file to clipboard. Please try again."); - } - } else { - alert("Clipboard API not supported in this browser."); - } - }); - - return ( -
-
- -
- -
-
- - -
- -
-
-

- { file.Name || "Untitled" } -

-
- { formatSize(file.Size) } - - Uploaded on { new Date(file.CreatedAt).toLocaleDateString() } -
-
-
-
- ) -}) - -const FilePreview = component$(({ file }: FileProps) => { - type FileType = - | "image" - | "video" - | "audio" - | "other"; - - const type: Signal = useSignal("other"); - const extension = file.Name.split('.').pop()?.toLowerCase() || ""; - - useTask$(async () => { - if ( - ["png", "jpg", "jpeg", "gif"] - .includes(extension)) type.value = "image"; - - else if ( - ["mp4", "webm", "ogg", "avi", "mov", "mkv"] - .includes(extension)) type.value = "video"; - else if ( - ["mp3", "wav", "ogg", "flac", "aac"] - .includes(extension)) type.value = "audio"; - - else type.value = "other"; - }); - - switch (type.value) { - case "image": - return ( -
- {file.Name} -
- ); - case "video": - return ( -
- -
- ); - case "audio": - return ( -
- -
- ); - case "other": - default: - return ( -
-

- Preview not available -

-
- ); - } -}); \ No newline at end of file diff --git a/src/components/dashboard/OSBar.tsx b/src/components/dashboard/OSBar.tsx new file mode 100644 index 0000000..4607fcf --- /dev/null +++ b/src/components/dashboard/OSBar.tsx @@ -0,0 +1,9 @@ +import { component$ } from "@builder.io/qwik"; + +export default component$(() => { + return ( +
+ a +
+ ) +}) \ No newline at end of file diff --git a/src/components/dashboard/TitleBar.tsx b/src/components/dashboard/TitleBar.tsx new file mode 100644 index 0000000..8ae4d02 --- /dev/null +++ b/src/components/dashboard/TitleBar.tsx @@ -0,0 +1,9 @@ +import { component$ } from "@builder.io/qwik"; + +export default component$(() => { + return ( +
+

whats on the agenda today, @hexlocation?

+
+ ) +}) \ No newline at end of file diff --git a/src/lib/api.ts b/src/lib/api.ts index c75a9b8..bc5c2e6 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -15,4 +15,5 @@ export const api = { return await client.post('upload', { body: formData }); }, delete: async (uid: string) => await client.delete(uid).json(), + me: async () => (await client.get('auth/me').json() as any).user, } \ No newline at end of file diff --git a/src/lib/stores.ts b/src/lib/stores.ts index 444b668..8fa59e2 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -1,5 +1,6 @@ import { atom } from "nanostores"; -import { StereoFile } from "./types"; +import { StereoFile, StereoUser } from "./types"; export const areFilesLoaded = atom(false); -export const dashboardFiles = atom([]); \ No newline at end of file +export const dashboardFiles = atom([]); +export const userInfo = atom({} as StereoUser); \ No newline at end of file diff --git a/src/lib/types.ts b/src/lib/types.ts index 861bacc..72bec61 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -5,4 +5,12 @@ export type StereoFile = { Size: number; CreatedAt: string; Mime: string; +} + +export type StereoUser = { + id: string; + username: string; + blacklisted: boolean; + email: string; + created_at: string; } \ No newline at end of file diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index c2572c9..c2db24e 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -1,9 +1,8 @@ -import { component$, useVisibleTask$ } from "@builder.io/qwik"; +import { component$, Signal, useVisibleTask$ } from "@builder.io/qwik"; import { routeLoader$, type DocumentHead } from "@builder.io/qwik-city"; -import Controlbar from "~/components/dashboard/Controlbar"; +import OSBar from "~/components/dashboard/OSBar"; +import TitleBar from "~/components/dashboard/TitleBar"; // import Dropzone from "~/components/Dropzone"; -import File from "~/components/dashboard/File"; -import { SolarUploadLinear, SvgSpinnersBarsRotateFade } from "~/components/misc/Icons"; import { useNanostore$ } from "~/hooks/nanostores"; import { api } from "~/lib/api"; import { OAUTH_LINK } from "~/lib/constants"; @@ -23,50 +22,30 @@ export default component$(() => { useVisibleTask$(async () => { loaded.value = false; files.value = await api.list(); - console.log("Files loaded:", files.value); loaded.value = true; }); return ( <> - {/* */} - - {!loaded.value ? ( -
-

-

loading your files...

- please wait... -
- ) : ( - files.value.length === 0 ? ( -
-

{ - [ - "┻━┻︵ \\(°□°)/ ︵ ┻━┻", - "┻━┻︵ヽ(`Д´)ノ︵ ┻━┻", - "ʕノ•ᴥ•ʔノ ︵ ┻━┻", - "(╯°Д°)╯︵ /(.□ . \\)", - "┬─┬ ︵ /(.□. \\)", - "(/ .□.)\\ ︵╰(゜Д゜)╯︵ /(.□. \\)" - ].sort(() => Math.random() - 0.5)[0] - }

-

you haven't uploaded any files yet!

- click the button to get started -
- ) - : ( -
- {files.value.map((file) => ( - - ))} -
- ) - )} - + + + ); }); +const Files = component$<{ + files: Signal; + loaded: Signal; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +}>(({ files, loaded }) => { + return ( +
+ b +
+ ); +}); + export const head: DocumentHead = { title: "Welcome to Qwik", meta: [ diff --git a/src/routes/layout.tsx b/src/routes/layout.tsx index fe816c8..c7a9b0f 100644 --- a/src/routes/layout.tsx +++ b/src/routes/layout.tsx @@ -1,9 +1,18 @@ import { $, component$, Slot, useOnDocument } from '@builder.io/qwik'; import AOS from 'aos'; import 'aos/dist/aos.css'; +import { useNanostore$ } from '~/hooks/nanostores'; +import { api } from '~/lib/api'; +import { userInfo } from '~/lib/stores'; +import { StereoUser } from '~/lib/types'; export default component$(() => { - useOnDocument("DOMContentLoaded", $(() => { + const info = useNanostore$(userInfo); + + useOnDocument("DOMContentLoaded", $(async () => { + info.value = await api.me() + console.log(info.value); + AOS.init({ once: true, duration: 1000, From f16435101111c5dbd8f820c9d2e0d2ebc893ccb1 Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Sat, 21 Jun 2025 17:44:55 +0100 Subject: [PATCH 03/27] top bar --- src/components/dashboard/TitleBar.tsx | 36 +++++++++++++++++++++++++-- src/lib/stores.ts | 8 +++++- src/routes/dashboard/index.tsx | 4 +-- src/routes/layout.tsx | 1 - 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/components/dashboard/TitleBar.tsx b/src/components/dashboard/TitleBar.tsx index 8ae4d02..ba9caa5 100644 --- a/src/components/dashboard/TitleBar.tsx +++ b/src/components/dashboard/TitleBar.tsx @@ -1,9 +1,41 @@ import { component$ } from "@builder.io/qwik"; +import { useNanostore$ } from "~/hooks/nanostores"; +import { userInfo } from "~/lib/stores"; +import { StereoUser } from "~/lib/types"; export default component$(() => { + const greetings = [ + "what's on the agenda today, |?", + "what's on your mind, |?", + "what's the plan, |?", + "ready to rock, |?", + "what's brewing, |?", + "what's the latest, |?", + "how's your day going, |?", + "need some inspiration, |?", + "let's make some noise, |!", + "welcome back, |!", + "good to see you, |!", + "what are we making today, |?", + "time to make some magic, |!", + "let's get creative, |?", + "what's the vibe today, |?", + ] + + const greeting = greetings[Math.floor(Math.random() * greetings.length)]; + const user = useNanostore$(userInfo); + + const splits = greeting.split("|"); + return ( -
-

whats on the agenda today, @hexlocation?

+
+

+ {splits[0]} + + @{user.value?.username || "..."} + + {splits[1]} +

) }) \ No newline at end of file diff --git a/src/lib/stores.ts b/src/lib/stores.ts index 8fa59e2..ab97728 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -3,4 +3,10 @@ import { StereoFile, StereoUser } from "./types"; export const areFilesLoaded = atom(false); export const dashboardFiles = atom([]); -export const userInfo = atom({} as StereoUser); \ No newline at end of file +export const userInfo = atom({ + id: "1", + username: "user", + blacklisted: false, + email: "user@example.com", + created_at: Date.now().toString(), +}); \ No newline at end of file diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index c2db24e..10aa70b 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -26,11 +26,11 @@ export default component$(() => { }); return ( - <> +
- +
); }); diff --git a/src/routes/layout.tsx b/src/routes/layout.tsx index c7a9b0f..9ed7b73 100644 --- a/src/routes/layout.tsx +++ b/src/routes/layout.tsx @@ -11,7 +11,6 @@ export default component$(() => { useOnDocument("DOMContentLoaded", $(async () => { info.value = await api.me() - console.log(info.value); AOS.init({ once: true, From b36d3b76a124caa5a96a25320e47d518819aa15c Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Sat, 21 Jun 2025 20:27:32 +0100 Subject: [PATCH 04/27] Enhance dashboard components with new icons, layout adjustments, and improved file display --- src/components/dashboard/OSBar.tsx | 40 +++++++++++- src/components/dashboard/TitleBar.tsx | 8 ++- src/components/landing/Footer.tsx | 4 +- src/components/landing/Navbar.tsx | 4 +- src/components/landing/Testimonials.tsx | 7 +- src/components/misc/Icons.tsx | 85 ++++++++++++++++++++++++- src/components/misc/StereoLogo.tsx | 9 --- src/routes/dashboard/index.tsx | 21 +++++- src/routes/layout.tsx | 7 +- 9 files changed, 159 insertions(+), 26 deletions(-) delete mode 100644 src/components/misc/StereoLogo.tsx diff --git a/src/components/dashboard/OSBar.tsx b/src/components/dashboard/OSBar.tsx index 4607fcf..44f6698 100644 --- a/src/components/dashboard/OSBar.tsx +++ b/src/components/dashboard/OSBar.tsx @@ -1,9 +1,45 @@ import { component$ } from "@builder.io/qwik"; +import { SolarLibraryLinear, SolarRoundedMagniferLinear, SolarSettingsLinear, SolarUploadMinimalisticLinear, StereoCircularProgress, StereoLogoLinear } from "../misc/Icons"; export default component$(() => { + const used = 3.8; + const total = 15; return ( -
- a +
+
+ +

{used} / {total} GB

+
+ +
+ + + + + +
+ +
+ ? +
) }) \ No newline at end of file diff --git a/src/components/dashboard/TitleBar.tsx b/src/components/dashboard/TitleBar.tsx index ba9caa5..c26af60 100644 --- a/src/components/dashboard/TitleBar.tsx +++ b/src/components/dashboard/TitleBar.tsx @@ -1,4 +1,4 @@ -import { component$ } from "@builder.io/qwik"; +import { component$, useTask$ } from "@builder.io/qwik"; import { useNanostore$ } from "~/hooks/nanostores"; import { userInfo } from "~/lib/stores"; import { StereoUser } from "~/lib/types"; @@ -26,9 +26,13 @@ export default component$(() => { const user = useNanostore$(userInfo); const splits = greeting.split("|"); + + useTask$(({ track }) => { + track(() => user.value); + }) return ( -
+

{splits[0]} diff --git a/src/components/landing/Footer.tsx b/src/components/landing/Footer.tsx index 16fef9d..363619f 100644 --- a/src/components/landing/Footer.tsx +++ b/src/components/landing/Footer.tsx @@ -1,5 +1,5 @@ import { component$ } from "@builder.io/qwik"; -import StereoLogo from "../misc/StereoLogo"; +import { StereoLogoBold } from "../misc/Icons"; export default component$(() => { return ( @@ -7,7 +7,7 @@ export default component$(() => {

- + stereo.cat diff --git a/src/components/landing/Navbar.tsx b/src/components/landing/Navbar.tsx index 85fb716..4e23a25 100644 --- a/src/components/landing/Navbar.tsx +++ b/src/components/landing/Navbar.tsx @@ -1,5 +1,5 @@ import { component$ } from "@builder.io/qwik"; -import StereoLogo from "../misc/StereoLogo"; +import { StereoLogoBold } from "../misc/Icons"; export default component$(() => { const items = [ @@ -17,7 +17,7 @@ export default component$(() => { data-aos-duration="1000" class="fixed flex items-center justify-start top-6 left-1/2 transform -translate-x-1/2 bg-neutral-950 p-8 h-10 rounded-full lg:w-2/3 md:w-4/5 w-4/5 z-[9999999] shadow-lg">
- +

diff --git a/src/components/misc/Icons.tsx b/src/components/misc/Icons.tsx index 5500ae1..73511c1 100644 --- a/src/components/misc/Icons.tsx +++ b/src/components/misc/Icons.tsx @@ -1,5 +1,7 @@ import { QwikIntrinsicElements } from "@builder.io/qwik"; +// Solar - https://icones.js.org/collection/solar + export function SolarUploadLinear(props: QwikIntrinsicElements['svg'], key: string) { return ( @@ -26,7 +28,6 @@ export function SolarLinkRoundBold(props: QwikIntrinsicElements['svg'], key: str ) } - export function SolarDownloadMinimalisticBold(props: QwikIntrinsicElements['svg'], key: string) { return ( @@ -36,4 +37,86 @@ export function SvgSpinnersBarsRotateFade(props: QwikIntrinsicElements['svg'], k return ( ) +} + +export function SolarLibraryLinear(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + +export function SolarUploadMinimalisticLinear(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + + +export function SolarRoundedMagniferLinear(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + + +export function SolarSettingsLinear(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + +// Stereo + +export function StereoLogoBold(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + +export function StereoLogoLinear(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + +export function StereoCircularProgress( + { value, ...svgProps }: QwikIntrinsicElements['svg'] & { value: number }, + key: string +) { + const radius = 10; + const circumference = 2 * Math.PI * radius; + const dashOffset = circumference * (1 - value); + + return ( + + + + + ); } \ No newline at end of file diff --git a/src/components/misc/StereoLogo.tsx b/src/components/misc/StereoLogo.tsx deleted file mode 100644 index 892ea95..0000000 --- a/src/components/misc/StereoLogo.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { component$, QwikIntrinsicElements } from "@builder.io/qwik"; - -export default component$((props: QwikIntrinsicElements['svg']) => { - return ( - - - - ) -}) \ No newline at end of file diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index 10aa70b..5bd769c 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -26,7 +26,7 @@ export default component$(() => { }); return ( -

+
@@ -39,9 +39,24 @@ const Files = component$<{ loaded: Signal; // eslint-disable-next-line @typescript-eslint/no-unused-vars }>(({ files, loaded }) => { + + const File = component$(({ file }: { file: StereoFile }) => { + return ( +
+ {file.Name} +
+ ) + }) + return ( -
- b +
+
+ {files.value.map((file) => ( + Array.from({ length: 15 }).map((_, i) => ( + + )) + ))} +
); }); diff --git a/src/routes/layout.tsx b/src/routes/layout.tsx index 9ed7b73..0d156ac 100644 --- a/src/routes/layout.tsx +++ b/src/routes/layout.tsx @@ -1,4 +1,4 @@ -import { $, component$, Slot, useOnDocument } from '@builder.io/qwik'; +import { $, component$, Slot, useOnDocument, useVisibleTask$ } from '@builder.io/qwik'; import AOS from 'aos'; import 'aos/dist/aos.css'; import { useNanostore$ } from '~/hooks/nanostores'; @@ -9,8 +9,11 @@ import { StereoUser } from '~/lib/types'; export default component$(() => { const info = useNanostore$(userInfo); + useVisibleTask$(async () => { + info.value = await api.me(); + }) + useOnDocument("DOMContentLoaded", $(async () => { - info.value = await api.me() AOS.init({ once: true, From 3217373024ae14edd39f3667eebb0bc702bacc52 Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Sat, 21 Jun 2025 21:58:33 +0100 Subject: [PATCH 05/27] q icon to osbar --- src/components/dashboard/OSBar.tsx | 6 +++--- src/components/misc/Icons.tsx | 7 +++++++ src/routes/dashboard/index.tsx | 6 ++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/dashboard/OSBar.tsx b/src/components/dashboard/OSBar.tsx index 44f6698..47206ac 100644 --- a/src/components/dashboard/OSBar.tsx +++ b/src/components/dashboard/OSBar.tsx @@ -1,5 +1,5 @@ import { component$ } from "@builder.io/qwik"; -import { SolarLibraryLinear, SolarRoundedMagniferLinear, SolarSettingsLinear, SolarUploadMinimalisticLinear, StereoCircularProgress, StereoLogoLinear } from "../misc/Icons"; +import { SolarLibraryLinear, SolarQuestionCircleLinear, SolarRoundedMagniferLinear, SolarSettingsLinear, SolarUploadMinimalisticLinear, StereoCircularProgress, StereoLogoLinear } from "../misc/Icons"; export default component$(() => { const used = 3.8; @@ -37,8 +37,8 @@ export default component$(() => { background: "rgba(255, 38, 78, 0.15)", boxShadow: "0px 4px 20px 0px rgba(255, 38, 78, 0.08), 0px 8px 12px 0px rgba(0, 0, 0, 0.12), 0px 4px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 1px 0px rgba(0, 0, 0, 0.04), 0px 4px 8px 0px rgba(255, 38, 78, 0.12) inset, 0px 1px 3px 0px rgba(255, 38, 78, 0.24) inset", backdropFilter: "blur(12px)", - }} class="flex items-center justify-center px-6 py-4 gap-2 text-white text-xl"> - ? + }} class="flex items-center justify-center px-5 py-5 gap-2 text-white text-3xl h-full"> +
) diff --git a/src/components/misc/Icons.tsx b/src/components/misc/Icons.tsx index 73511c1..6718fbe 100644 --- a/src/components/misc/Icons.tsx +++ b/src/components/misc/Icons.tsx @@ -65,6 +65,13 @@ export function SolarSettingsLinear(props: QwikIntrinsicElements['svg'], key: st ) } + +export function SolarQuestionCircleLinear(props: QwikIntrinsicElements['svg'], key: string) { + return ( + + ) +} + // Stereo export function StereoLogoBold(props: QwikIntrinsicElements['svg'], key: string) { diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index 5bd769c..b6f48e8 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -49,12 +49,10 @@ const Files = component$<{ }) return ( -
+
{files.value.map((file) => ( - Array.from({ length: 15 }).map((_, i) => ( - - )) + ))}
From f843155394aebca6170a395e85841bbadafb9bb7 Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Sat, 21 Jun 2025 22:37:32 +0100 Subject: [PATCH 06/27] Add file preview component and enhance file size formatting in dashboard --- src/routes/dashboard/index.tsx | 93 ++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index b6f48e8..d2a0f3d 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -1,4 +1,4 @@ -import { component$, Signal, 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 OSBar from "~/components/dashboard/OSBar"; import TitleBar from "~/components/dashboard/TitleBar"; @@ -34,6 +34,13 @@ 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`; +} + const Files = component$<{ files: Signal; loaded: Signal; @@ -41,9 +48,89 @@ const Files = component$<{ }>(({ files, loaded }) => { const File = component$(({ file }: { file: StereoFile }) => { + const Preview = component$(() => { + type FileType = + | "image" + | "video" + | "audio" + | "other"; + + const fileType: Signal = useSignal("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 ( +
+ {fileType.value === "image" && ( + {file.Name} + )} + + {fileType.value === "video" && ( +
+ ) + }) + return ( -
- {file.Name} +
+ + +
+

{file.Name}

+

+ {formatSize(file.Size)} + + Uploaded on {new Date(file.CreatedAt).toLocaleDateString()} +

+
) }) From 8e5dff01c058d9035f6b4965a28b0194aa4c5bbc Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Tue, 29 Jul 2025 21:27:49 +0100 Subject: [PATCH 07/27] chore: update dependencies and improve dashboard settings - Updated Qwik and Qwik City to version 1.15.0 - Updated Tailwind CSS and related plugins to latest versions - Added a new Settings component to manage user settings - Integrated settings management into the OSBar component - Improved file display in the dashboard with better responsiveness - Enhanced error handling for user info fetching - Removed unused id from Testimonials component --- bun.lock | 50 +++++++++++++------------ package.json | 18 ++++----- public | 2 +- src/components/dashboard/OSBar.tsx | 15 +++++--- src/components/dashboard/Settings.tsx | 24 ++++++++++++ src/components/landing/Testimonials.tsx | 1 - src/lib/stores.ts | 3 +- src/routes/dashboard/index.tsx | 31 ++++++++------- src/routes/layout.tsx | 6 ++- 9 files changed, 94 insertions(+), 56 deletions(-) create mode 100644 src/components/dashboard/Settings.tsx diff --git a/bun.lock b/bun.lock index fc926af..9ac6a3b 100644 --- a/bun.lock +++ b/bun.lock @@ -33,9 +33,9 @@ "packages": { "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], - "@builder.io/qwik": ["@builder.io/qwik@1.14.1", "", { "dependencies": { "csstype": "^3.1", "rollup": ">= 4.39.0" }, "peerDependencies": { "vite": "^5" }, "bin": { "qwik": "qwik-cli.cjs" } }, "sha512-bq1fkt8RhjkENQOs/bxh8i1IuQ0DIfIZ1RgyoZYmADxcyKjhVRcCx+6kaRUkjovb5sR06pqH96YaHjI7iI/CMw=="], + "@builder.io/qwik": ["@builder.io/qwik@1.15.0", "", { "dependencies": { "csstype": "^3.1", "rollup": ">= 4.39.0" }, "peerDependencies": { "vite": ">=5 <8" }, "bin": { "qwik": "qwik-cli.cjs" } }, "sha512-0PUXGbH+9htHPq0Br+M/QsY7aGJhG7C1A4dZziDGONAB2INcOUkzoOF3Qv2S7JzFyUlgBtN1drmw6P9jLryRyQ=="], - "@builder.io/qwik-city": ["@builder.io/qwik-city@1.14.1", "", { "dependencies": { "@mdx-js/mdx": "^3", "@types/mdx": "^2", "source-map": "^0.7.4", "svgo": "^3.3", "undici": "*", "valibot": ">=0.36.0 <2", "vfile": "6.0.2", "vite": "^5", "vite-imagetools": "^7", "zod": "3.22.4" } }, "sha512-VsAvk7u2HyyTnL9GhpT+h10t2XAIlxtv6LFL3Xt9/1QZ6lMfGWMcMEAMuZB1Ib+D/oTfu7QRqZngRg3FsrIKyg=="], + "@builder.io/qwik-city": ["@builder.io/qwik-city@1.15.0", "", { "dependencies": { "@mdx-js/mdx": "^3", "@types/mdx": "^2", "source-map": "^0.7.4", "svgo": "^3.3", "undici": "*", "valibot": ">=0.36.0 <2", "vfile": "6.0.2", "vite": ">=5 <8", "vite-imagetools": "^7", "zod": "3.22.4" } }, "sha512-fy84pb6fat8YKDBh06tw+vgZ+Iwlhq/qEnFLUpMFLAG+Vll8diH6t0MeK9rtiPG9VsPZYZa32euTy4LnHj2Tiw=="], "@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="], @@ -97,7 +97,7 @@ "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - "@eslint/js": ["@eslint/js@9.28.0", "", {}, "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg=="], + "@eslint/js": ["@eslint/js@9.31.0", "", {}, "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw=="], "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], @@ -215,35 +215,35 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.42.0", "", { "os": "win32", "cpu": "x64" }, "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA=="], - "@tailwindcss/node": ["@tailwindcss/node@4.1.8", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.8" } }, "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q=="], + "@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="], - "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.8", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.8", "@tailwindcss/oxide-darwin-arm64": "4.1.8", "@tailwindcss/oxide-darwin-x64": "4.1.8", "@tailwindcss/oxide-freebsd-x64": "4.1.8", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.8", "@tailwindcss/oxide-linux-arm64-musl": "4.1.8", "@tailwindcss/oxide-linux-x64-gnu": "4.1.8", "@tailwindcss/oxide-linux-x64-musl": "4.1.8", "@tailwindcss/oxide-wasm32-wasi": "4.1.8", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.8", "@tailwindcss/oxide-win32-x64-msvc": "4.1.8" } }, "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A=="], + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="], - "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.8", "", { "os": "android", "cpu": "arm64" }, "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg=="], + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.11", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="], - "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A=="], + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="], - "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw=="], + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="], - "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg=="], + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="], - "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8", "", { "os": "linux", "cpu": "arm" }, "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ=="], + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="], - "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q=="], + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="], - "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ=="], + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="], - "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.8", "", { "os": "linux", "cpu": "x64" }, "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g=="], + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="], - "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.8", "", { "os": "linux", "cpu": "x64" }, "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg=="], + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="], - "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.8", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.10", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg=="], + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="], - "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA=="], + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="], - "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.8", "", { "os": "win32", "cpu": "x64" }, "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ=="], + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.11", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="], - "@tailwindcss/vite": ["@tailwindcss/vite@4.1.8", "", { "dependencies": { "@tailwindcss/node": "4.1.8", "@tailwindcss/oxide": "4.1.8", "tailwindcss": "4.1.8" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A=="], + "@tailwindcss/vite": ["@tailwindcss/vite@4.1.11", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="], "@trysound/sax": ["@trysound/sax@0.2.0", "", {}, "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="], @@ -443,7 +443,7 @@ "eslint": ["eslint@9.25.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.25.1", "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ=="], - "eslint-plugin-qwik": ["eslint-plugin-qwik@1.14.1", "", { "dependencies": { "@typescript-eslint/utils": "^8.31.0", "jsx-ast-utils": "^3.3.5" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-N0C8V/6F4EfRdC6EmE7o0VnUod9T16u94C+AD325xA0U4IQoC191uvkGeeJtJ7RXv6UPWz0Evh1aHTfaEILhkg=="], + "eslint-plugin-qwik": ["eslint-plugin-qwik@1.15.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.31.0", "jsx-ast-utils": "^3.3.5" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-teDkSl0N/2vDCYK1LKfagnbE0A1RCV00tMekitVX6sfrfpM/nJ199Kyco5nrgp6qvhLJgFXsRBXGEEobPgn2jA=="], "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], @@ -635,7 +635,7 @@ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - "ky": ["ky@1.8.1", "", {}, "sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw=="], + "ky": ["ky@1.8.2", "", {}, "sha512-XybQJ3d4Ea1kI27DoelE5ZCT3bSJlibYTtQuMsyzKox3TMyayw1asgQdl54WroAm+fIA3ZCr8zXW2RpR7qWVpA=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], @@ -811,7 +811,7 @@ "prettier": ["prettier@3.3.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew=="], - "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.12", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-OuTQKoqNwV7RnxTPwXWzOFXy6Jc4z8oeRZYGuMpRyG3WbuR3jjXdQFK8qFBMBx8UHWdHrddARz2fgUenild6aw=="], + "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.14", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg=="], "prism-react-renderer": ["prism-react-renderer@2.4.1", "", { "dependencies": { "@types/prismjs": "^1.26.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": ">=16.0.0" } }, "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig=="], @@ -909,7 +909,7 @@ "tailwind-scrollbar": ["tailwind-scrollbar@4.0.2", "", { "dependencies": { "prism-react-renderer": "^2.4.1" }, "peerDependencies": { "tailwindcss": "4.x" } }, "sha512-wAQiIxAPqk0MNTPptVe/xoyWi27y+NRGnTwvn4PQnbvB9kp8QUBiGl/wsfoVBHnQxTmhXJSNt9NHTmcz9EivFA=="], - "tailwindcss": ["tailwindcss@4.1.8", "", {}, "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og=="], + "tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="], "tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="], @@ -943,7 +943,7 @@ "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], - "undici": ["undici@7.10.0", "", {}, "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw=="], + "undici": ["undici@7.12.0", "", {}, "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug=="], "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], @@ -1009,7 +1009,7 @@ "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="], - "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.10", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" }, "bundled": true }, "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ=="], + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="], @@ -1051,6 +1051,8 @@ "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.26.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg=="], + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + "@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], diff --git a/package.json b/package.json index c95d6ca..58a2349 100644 --- a/package.json +++ b/package.json @@ -24,27 +24,27 @@ "qwik": "qwik" }, "devDependencies": { - "@builder.io/qwik": "^1.14.1", - "@builder.io/qwik-city": "^1.14.1", + "@builder.io/qwik": "^1.15.0", + "@builder.io/qwik-city": "^1.15.0", "@eslint/js": "latest", - "@tailwindcss/vite": "^4.0.0", + "@tailwindcss/vite": "^4.1.11", "@types/node": "20.14.11", "eslint": "9.25.1", - "eslint-plugin-qwik": "^1.14.1", + "eslint-plugin-qwik": "^1.15.0", "globals": "16.0.0", "prettier": "3.3.3", - "prettier-plugin-tailwindcss": "^0.6.11", - "tailwindcss": "^4.0.0", + "prettier-plugin-tailwindcss": "^0.6.14", + "tailwindcss": "^4.1.11", "typescript": "5.4.5", "typescript-eslint": "8.26.1", - "undici": "*", + "undici": "^7.12.0", "vite": "5.3.5", - "vite-tsconfig-paths": "^4.2.1" + "vite-tsconfig-paths": "^4.3.2" }, "dependencies": { "@types/aos": "^3.0.7", "aos": "^3.0.0-beta.6", - "ky": "^1.8.1", + "ky": "^1.8.2", "nanostores": "^1.0.1", "tailwind-scrollbar": "^4.0.2" } diff --git a/public b/public index a4f5725..ffdd93a 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit a4f5725fbaf2db1053be198d81d08e1ea0c3e843 +Subproject commit ffdd93af120e3bec48736bfc8a2ae7824c941cfa diff --git a/src/components/dashboard/OSBar.tsx b/src/components/dashboard/OSBar.tsx index 47206ac..26d32f9 100644 --- a/src/components/dashboard/OSBar.tsx +++ b/src/components/dashboard/OSBar.tsx @@ -1,20 +1,25 @@ import { component$ } from "@builder.io/qwik"; +import { useNanostore$ } from "~/hooks/nanostores"; +import { isSettingsOpen } from "~/lib/stores"; import { SolarLibraryLinear, SolarQuestionCircleLinear, SolarRoundedMagniferLinear, SolarSettingsLinear, SolarUploadMinimalisticLinear, StereoCircularProgress, StereoLogoLinear } from "../misc/Icons"; export default component$(() => { const used = 3.8; const total = 15; + + const settingsOpen = useNanostore$(isSettingsOpen); + return ( -
+
+ }} class="flex items-center justify-center px-6 py-4 h-full gap-2 text-white text-xl"> -

{used} / {total} GB

+
{ boxShadow: "0px 4px 20px 0px rgba(255, 38, 78, 0.08), 0px 8px 12px 0px rgba(0, 0, 0, 0.12), 0px 4px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 1px 0px rgba(0, 0, 0, 0.04), 0px 4px 8px 0px rgba(255, 38, 78, 0.12) inset, 0px 1px 3px 0px rgba(255, 38, 78, 0.24) inset", backdropFilter: "blur(12px)", }} class="flex items-center justify-center px-6 py-4 gap-5 text-white text-3xl absolute left-1/2 transform -translate-x-1/2"> - + settingsOpen.value = true}> @@ -37,7 +42,7 @@ export default component$(() => { background: "rgba(255, 38, 78, 0.15)", boxShadow: "0px 4px 20px 0px rgba(255, 38, 78, 0.08), 0px 8px 12px 0px rgba(0, 0, 0, 0.12), 0px 4px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 1px 0px rgba(0, 0, 0, 0.04), 0px 4px 8px 0px rgba(255, 38, 78, 0.12) inset, 0px 1px 3px 0px rgba(255, 38, 78, 0.24) inset", backdropFilter: "blur(12px)", - }} class="flex items-center justify-center px-5 py-5 gap-2 text-white text-3xl h-full"> + }} class="flex items-center justify-center p-4 gap-2 text-white text-3xl h-full">
diff --git a/src/components/dashboard/Settings.tsx b/src/components/dashboard/Settings.tsx new file mode 100644 index 0000000..3b057b9 --- /dev/null +++ b/src/components/dashboard/Settings.tsx @@ -0,0 +1,24 @@ +import { component$ } from "@builder.io/qwik"; +import { useNanostore$ } from "~/hooks/nanostores"; +import { isSettingsOpen, userInfo } from "~/lib/stores"; +import { StereoUser } from "~/lib/types"; + +export default component$(() => { + const info = useNanostore$(userInfo); + const open = useNanostore$(isSettingsOpen); + if (open.value) return ( +
open.value = false} class="z-[50] absolute flex w-full h-screen items-center justify-center backdrop-blur-3xl bg-black/50 text-white text-6xl"> +
e.stopPropagation()} class="flex gap-8 bg-black/50 p-8 rounded-3xl shadow-lg w-4/7 h-4/7"> +
+

settings

+
+ +
+

content

+
+
+
+ ); else return ( + <> + ); +}) \ No newline at end of file diff --git a/src/components/landing/Testimonials.tsx b/src/components/landing/Testimonials.tsx index ad02c30..fb73fe8 100644 --- a/src/components/landing/Testimonials.tsx +++ b/src/components/landing/Testimonials.tsx @@ -95,7 +95,6 @@ export default component$(() => { diff --git a/src/lib/stores.ts b/src/lib/stores.ts index ab97728..d467cee 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -9,4 +9,5 @@ export const userInfo = atom({ blacklisted: false, email: "user@example.com", created_at: Date.now().toString(), -}); \ No newline at end of file +}); +export const isSettingsOpen = atom(false); \ No newline at end of file diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx index d2a0f3d..af8ef4b 100644 --- a/src/routes/dashboard/index.tsx +++ b/src/routes/dashboard/index.tsx @@ -1,6 +1,7 @@ import { component$, Signal, useSignal, useTask$, useVisibleTask$ } from "@builder.io/qwik"; import { routeLoader$, type DocumentHead } from "@builder.io/qwik-city"; import OSBar from "~/components/dashboard/OSBar"; +import Settings from "~/components/dashboard/Settings"; import TitleBar from "~/components/dashboard/TitleBar"; // import Dropzone from "~/components/Dropzone"; import { useNanostore$ } from "~/hooks/nanostores"; @@ -26,11 +27,14 @@ export default component$(() => { }); return ( -
- - - -
+ <> + +
+ + + +
+ ); }); @@ -44,8 +48,7 @@ const formatSize = (bytes: number) => { const Files = component$<{ files: Signal; loaded: Signal; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -}>(({ files, loaded }) => { +}>(({ files }) => { const File = component$(({ file }: { file: StereoFile }) => { const Preview = component$(() => { @@ -78,14 +81,14 @@ const Files = component$<{ }); return ( -
+
{fileType.value === "image" && ( {file.Name} )} @@ -95,7 +98,7 @@ const Files = component$<{ height={300} src={`/api/${file.ID}`} controls - class="w-full h-60 object-cover flex-grow" + class="w-full h-60 object-cover flex-grow hover:scale-105 transition-all duration-300" /> )} @@ -103,7 +106,7 @@ const Files = component$<{