Skip to content

Commit

Permalink
finish settings ui 👀
Browse files Browse the repository at this point in the history
  • Loading branch information
hiaaryan committed Jul 2, 2024
1 parent 42ac9aa commit 3af6d7e
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 97 deletions.
6 changes: 6 additions & 0 deletions main/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
createPlaylist,
getAlbumWithSongs,
getAlbums,
getLibraryStats,
getPlaylistWithSongs,
getPlaylists,
getSettings,
Expand Down Expand Up @@ -191,6 +192,11 @@ ipcMain.handle("createPlaylist", async (_, data: any) => {
return playlist;
});

ipcMain.handle("getLibraryStats", async () => {
const stats = await getLibraryStats();
return stats;
});

ipcMain.handle("updatePlaylist", async (_, data: any) => {
const playlist = await updatePlaylist(data);
return playlist;
Expand Down
16 changes: 15 additions & 1 deletion main/helpers/db/connectDB.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { and, eq, ilike, like } from "drizzle-orm";
import { and, eq, ilike, like, sql } from "drizzle-orm";
import { albums, songs, settings, playlistSongs, playlists } from "./schema";
import fs from "fs";
import { parseFile, selectCover } from "music-metadata";
Expand All @@ -11,6 +11,20 @@ const db: BetterSQLite3Database<typeof schema> = drizzle(sqlite, {
schema,
});

export const getLibraryStats = async () => {
const songCount = await db.select({ count: sql`count(*)` }).from(songs);
const albumCount = await db.select({ count: sql`count(*)` }).from(albums);
const playlistCount = await db
.select({ count: sql`count(*)` })
.from(playlists);

return {
songs: songCount[0].count,
albums: albumCount[0].count,
playlists: playlistCount[0].count,
};
};

export const getSettings = async () => {
const throwSettings = await db.select().from(settings).limit(1);
return throwSettings[0];
Expand Down
2 changes: 1 addition & 1 deletion renderer/components/ui/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function Actions() {
width={16}
height={16}
/>
Wora v0.1.0-alpha
Wora v0.1.0
</div>
</div>
</div>
Expand Down
42 changes: 19 additions & 23 deletions renderer/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,34 @@ import { Toaster } from "@/components/ui/sonner";
export default function App({ Component, pageProps }) {
const router = useRouter();

if (["/setup"].includes(router.pathname)) {
return (
<main className="select-none bg-black font-sans text-xs text-white antialiased">
<Component {...pageProps} />
</main>
);
}

return (
<main className="select-none rounded-lg bg-black font-sans text-xs text-white antialiased">
<Head>
<title>Wora</title>
</Head>
<PlayerProvider>
<div className="h-dvh w-dvw">
<div>
<Actions />
<Toaster position="top-right" />
<div className="flex gap-8">
<div className="sticky top-0 z-50 h-dvh p-8 pr-0 pt-12">
<Navbar />
</div>
<div className="h-screen flex-grow p-8 pl-0 pt-10">
<div className="wora-transition relative flex h-full w-full flex-col">
<Component {...pageProps} />
<Player />
{["/setup"].includes(router.pathname) ? (
<Component {...pageProps} />
) : (
<PlayerProvider>
<div className="h-dvh w-dvw">
<div>
<Actions />
<Toaster position="top-right" />
<div className="flex gap-8">
<div className="sticky top-0 z-50 h-dvh p-8 pr-0 pt-12">
<Navbar />
</div>
<div className="h-screen flex-grow p-8 pl-0 pt-10">
<div className="wora-transition relative flex h-full w-full flex-col">
<Component {...pageProps} />
<Player />
</div>
</div>
</div>
</div>
</div>
</div>
</PlayerProvider>
</PlayerProvider>
)}
</main>
);
}
211 changes: 139 additions & 72 deletions renderer/pages/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Button } from "@/components/ui/button";
import Spinner from "@/components/ui/spinner";
import { Avatar, AvatarImage } from "@/components/ui/avatar";
import { toast } from "sonner";
import { Label } from "@/components/ui/label";

const formSchema = z.object({
name: z.string().min(2, {
Expand All @@ -39,10 +40,25 @@ export default function Settings() {
const [settings, setSettings] = useState<Settings | null>(null);
const [loading, setLoading] = useState(false);
const [musicLoading, setMusicLoading] = useState(false);
const [previewUrl, setPreviewUrl] = useState("");
const [stats, setStats] = useState<{
songs: number;
albums: number;
playlists: number;
} | null>(null);

useEffect(() => {
window.ipc.invoke("getSettings").then((response) => {
setSettings(response);
setPreviewUrl(
response?.profilePicture
? `wora://${response.profilePicture}`
: "/userPicture.png",
);
});

window.ipc.invoke("getLibraryStats").then((response) => {
setStats(response);
});
}, []);

Expand Down Expand Up @@ -129,6 +145,14 @@ export default function Settings() {
.catch(() => setMusicLoading(false));
};

useEffect(() => {
return () => {
if (previewUrl.startsWith("blob:")) {
URL.revokeObjectURL(previewUrl);
}
};
}, [previewUrl]);

return (
<ScrollArea className="mt-2.5 h-full w-[88.15vw] gradient-mask-b-70">
<div className="flex flex-col gap-8">
Expand All @@ -139,66 +163,81 @@ export default function Settings() {
</div>
<div className="relative flex w-full flex-col gap-8">
<div className="flex w-full items-center gap-8">
<div className="wora-border h-48 w-1/2 rounded-xl p-6">
<div className="wora-border h-48 w-2/5 rounded-xl p-6">
<Form {...form}>
<form
onSubmit={form.handleSubmit(updateSettings)}
className="flex h-full gap-4 text-xs"
className="flex h-full flex-col justify-between text-xs"
>
<div className="h-full">
<Avatar className="h-36 w-36">
<AvatarImage
src={`${settings && settings.profilePicture ? "wora://" + settings.profilePicture : "/userPicture.png"}`}
/>
</Avatar>
</div>
<div className="flex h-full w-full flex-col items-end justify-end gap-4">
<div className="flex w-full flex-col gap-2">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex w-full items-center gap-4">
<Label
className="wora-transition w-fit cursor-pointer hover:opacity-50"
htmlFor="profilePicture"
>
<Avatar className="h-20 w-20">
<AvatarImage src={previewUrl} />
</Avatar>
</Label>
<FormField
control={form.control}
name="profilePicture"
render={({ field: { onChange, value, ...rest } }) => {
const fileInputRef = useRef<HTMLInputElement>(null);
return (
<FormItem hidden className="w-full">
<FormControl>
<Input placeholder="Name" {...field} />
<Input
id="profilePicture"
placeholder="Picture"
type="file"
accept="image/*"
onChange={(e) => {
const files = e.target.files;
if (files && files.length > 0) {
const file = files[0];
onChange(files);
const objectUrl =
URL.createObjectURL(file);
setPreviewUrl(objectUrl);
}
}}
ref={fileInputRef}
{...rest}
/>
</FormControl>
<FormMessage className="text-xs" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="profilePicture"
render={({ field: { onChange, value, ...rest } }) => {
const fileInputRef = useRef<HTMLInputElement>(null);
return (
<FormItem className="w-full">
<FormControl>
<Input
placeholder="Picture"
type="file"
accept="image/*"
onChange={(e) => {
const files = e.target.files;
if (files && files.length > 0) {
onChange(files);
}
}}
ref={fileInputRef}
{...rest}
/>
</FormControl>
<FormMessage className="text-xs" />
</FormItem>
);
}}
/>
);
}}
/>
<div className="flex flex-col">
<p className="text-sm font-medium">
{settings && settings.name}
</p>
<p className="opacity-50">A great listner of music.</p>
</div>
</div>
<div className="flex w-full items-center gap-2">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem className="w-full">
<FormControl>
<Input
placeholder="A username would be great."
{...field}
/>
</FormControl>
<FormMessage className="text-xs" />
</FormItem>
)}
/>
<Button
className="w-fit justify-between text-xs"
type="submit"
>
Update Settings
Save
{loading ? (
<Spinner className="h-3.5 w-3.5" />
) : (
Expand All @@ -209,37 +248,51 @@ export default function Settings() {
</form>
</Form>
</div>
<div className="wora-border h-48 w-1/2 rounded-xl p-6">
<div className="flex h-full w-full flex-col items-center justify-center leading-3">
<div className="relative h-14 w-14">
<Image fill src={"/assets/Full [Dark].svg"} alt="Logo" />
<div className="wora-border h-48 w-3/5 rounded-xl p-6">
<div className="flex h-full flex-col justify-between text-xs">
<div className="flex w-full items-center gap-4">
<div className="flex w-full justify-around gap-4">
<div className="flex flex-col items-center gap-4">
Songs
<p className="text-3xl font-medium">
{stats && stats.songs}
</p>
</div>
<div className="flex flex-col items-center gap-4">
Albums
<p className="text-3xl font-medium">
{stats && stats.albums}
</p>
</div>
<div className="flex flex-col items-center gap-4">
Playlists
<p className="text-3xl font-medium">
{stats && stats.playlists}
</p>
</div>
</div>
</div>
<div className="flex items-center">
Made with
<IconHeart
stroke={2}
className="inline-flex h-3.5 fill-red-500 stroke-red-500"
/>
by hiaaryan.
<div className="flex w-full items-center gap-2">
<div className="flex h-9 w-full items-center rounded-lg bg-white/10 px-3 py-1 text-xs transition duration-300 focus:bg-white/20 focus:outline-none">
{settings && settings.musicFolder}
</div>
<Button
className="w-fit justify-between text-nowrap text-xs"
onClick={updateMusicFolder}
>
Update Music Folder
{musicLoading ? (
<Spinner className="h-3.5 w-3.5" />
) : (
<IconArrowRight stroke={2} className="h-3.5 w-3.5" />
)}
</Button>
</div>
</div>
</div>
</div>
<div className="flex w-full items-center gap-8">
<div className="wora-border h-48 w-1/2 rounded-xl p-6">
<Button
className="w-fit justify-between text-xs"
onClick={updateMusicFolder}
>
Update Music Folder
{musicLoading ? (
<Spinner className="h-3.5 w-3.5" />
) : (
<IconArrowRight stroke={2} className="h-3.5 w-3.5" />
)}
</Button>
</div>
<div className="wora-border h-48 w-1/2 rounded-xl p-6">
<div className="wora-border relative h-48 w-full overflow-hidden rounded-xl p-6">
<div className="flex h-full w-full flex-col items-center justify-center leading-3">
<div className="relative h-14 w-14">
<Image fill src={"/assets/Full [Dark].svg"} alt="Logo" />
Expand All @@ -253,6 +306,20 @@ export default function Settings() {
by hiaaryan.
</div>
</div>
<Image
height={512}
width={512}
src={"/assets/Logo.png"}
className="absolute -top-64 right-0 opacity-50"
alt="Logo"
/>
<Image
height={512}
width={512}
src={"/assets/Logo.png"}
className="absolute -bottom-64 left-0 opacity-50"
alt="Logo"
/>
</div>
</div>
</div>
Expand Down
Binary file removed renderer/public/assets/Screenshot 1.png
Binary file not shown.

0 comments on commit 3af6d7e

Please sign in to comment.