commit 9a7ec91ced32de23d7db1a9925c63bf6d9820be7
parent 53a7515db0d03d5bdfcea73203a576ac3da0c24d
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Fri, 6 Dec 2024 06:02:22 +0000
Add `/settings/profile`, edit `/settings/nostr`. Add image upload add photo component. Edit home page. Add/edit styles.
Diffstat:
6 files changed, 305 insertions(+), 4 deletions(-)
diff --git a/src/lib/components/image_upload_add_photo.svelte b/src/lib/components/image_upload_add_photo.svelte
@@ -0,0 +1,42 @@
+<script lang="ts">
+ import { dialog } from "$lib/client";
+ import { Glyph, t } from "@radroots/svelte-lib";
+
+ export let photo_path: string;
+
+ const handle_photo_add = async (): Promise<void> => {
+ try {
+ const photo_paths_open = await dialog.open_photos();
+ if (!photo_paths_open) return;
+ photo_path = photo_paths_open.results[0];
+ } catch (e) {
+ console.log(`(error) handle_photo_add `, e);
+ }
+ };
+</script>
+
+<div class={`relative flex flex-row w-full justify-center items-center`}>
+ <button
+ class={`flex flex-row h-[5rem] w-[5rem] justify-center items-center bg-layer-0-surface/80 rounded-full`}
+ on:click={async () => {
+ await handle_photo_add();
+ }}
+ >
+ <Glyph
+ basis={{
+ classes: `text-[40px] text-layer-2-glyph`,
+ dim: `sm`,
+ key: `camera`,
+ }}
+ />
+ <div
+ class={`absolute -bottom-[1.8rem] flex flex-row justify-start items-center`}
+ >
+ <p
+ class={`font-arch font-[600] text-sm text-layer-0-glyph capitalize`}
+ >
+ {`${$t(`icu.add_*`, { value: `${$t(`common.photo`)}` })}`}
+ </p>
+ </div>
+ </button>
+</div>
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
@@ -8,9 +8,12 @@
LayoutView,
nav_prev,
route,
+ t,
} from "@radroots/svelte-lib";
import { onMount } from "svelte";
+ $: device_metadata = device.metadata ? device.metadata.version : ``;
+
onMount(async () => {
try {
nav_prev.set([]);
@@ -34,11 +37,11 @@
<p class={`font-mono font-[600] text-[1.3rem] text-layer-0-glyph`}>
{`radRoots`}
</p>
- {#if device.metadata?.version}
+ {#if device_metadata}
<p
class={`font-mono font-[400] text-[1.3rem] text-layer-0-glyph`}
>
- {`/${device.metadata.version}`}
+ {`/${device_metadata}`}
</p>
{/if}
</div>
@@ -58,6 +61,29 @@
/>
</button>
</div>
+ <div
+ class={`flex flex-col w-full pt-2 px-6 gap-2 justify-center items-center`}
+ >
+ <div class={`flex flex-row w-full justify-start items-center`}>
+ <p class={`font-sans font-[600] text-2xl text-layer-0-glyph`}>
+ {`${$t(`common.general`)}`}
+ </p>
+ </div>
+ <div class={`flex flex-col w-full gap-5 justify-center items-center`}>
+ <button
+ class={`group flex flex-row h-[3.5rem] w-full justify-center items-center rounded-touch bg-layer-1-surface layer-1-active-surface layer-1-active-ring`}
+ on:click={async () => {
+ await route(`/settings/profile`);
+ }}
+ >
+ <p
+ class={`font-sans font-[600] text-xl text-layer-0-glyph capitalize tracking-wider opacity-active`}
+ >
+ {`${$t(`common.profile`)}`}
+ </p>
+ </button>
+ </div>
+ </div>
</LayoutView>
<EnvelopeLower
basis={{
diff --git a/src/routes/(app)/settings/nostr/+page.svelte b/src/routes/(app)/settings/nostr/+page.svelte
@@ -129,7 +129,7 @@
<Nav
basis={{
prev: {
- label: `Settings`,
+ label: `${$t(`common.settings`)}`,
route: `/settings`,
},
title: {
diff --git a/src/routes/(app)/settings/profile/+page.svelte b/src/routes/(app)/settings/profile/+page.svelte
@@ -0,0 +1,232 @@
+<script lang="ts">
+ import { db, fs } from "$lib/client";
+ import ImageUploadAddPhoto from "$lib/components/image_upload_add_photo.svelte";
+ import { ascii } from "$lib/conf";
+ import { kv_init_page } from "$lib/util/kv";
+ import type { NostrProfile } from "@radroots/models";
+ import {
+ app_nostr_key,
+ Glyph,
+ ImageBlob,
+ LayoutView,
+ Nav,
+ t,
+ } from "@radroots/svelte-lib";
+ import { onMount } from "svelte";
+
+ type LoadData = {
+ nostr_profile: NostrProfile;
+ };
+ let ld: LoadData | undefined = undefined;
+
+ let opt_photo_path = ``;
+ let opt_display: `photos` | `following` | `followers` = `photos`;
+
+ onMount(async () => {
+ try {
+ await init_page();
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ $: photo_overlay_visible = ld?.nostr_profile?.picture || opt_photo_path;
+ $: classes_photo_overlay_wrap = photo_overlay_visible
+ ? `bg-white/30 backdrop-blur-sm`
+ : ``;
+ $: classes_photo_overlay_glyph = photo_overlay_visible
+ ? `text-white`
+ : `text-layer-0-glyph`;
+
+ $: classes_photo_overlay_glyph_d = photo_overlay_visible
+ ? `text-white/40`
+ : `text-layer-0-glyph`;
+ const init_page = async (): Promise<void> => {
+ try {
+ await kv_init_page();
+ ld = await load_data();
+ } catch (e) {
+ console.log(`(error) init_page `, e);
+ }
+ };
+
+ const load_data = async (): Promise<LoadData | undefined> => {
+ try {
+ let nostr_profile_get_one = await db.nostr_profile_get_one({
+ public_key: $app_nostr_key,
+ });
+ if (`err` in nostr_profile_get_one) return;
+
+ const load: LoadData = {
+ nostr_profile: nostr_profile_get_one.result,
+ };
+ return load;
+ } catch (e) {
+ console.log(`(error) load_data `, e);
+ }
+ };
+</script>
+
+<LayoutView>
+ <div
+ class={`relative flex flex-col min-h-[525px] h-[525px] w-full justify-center items-center bg-layer-2-surface`}
+ >
+ {#if opt_photo_path}
+ {#await fs.read_bin(opt_photo_path) then file_data}
+ <ImageBlob
+ basis={{
+ data: file_data,
+ }}
+ />
+ {/await}
+ {:else}
+ <div
+ class={`flex flex-row justify-start items-center -translate-y-8`}
+ >
+ <ImageUploadAddPhoto bind:photo_path={opt_photo_path} />
+ </div>
+ {/if}
+ <div
+ class={`absolute bottom-0 left-0 flex flex-col h-[calc(100%-100%/1.618)] w-full px-6 gap-2 justify-end items-center ${classes_photo_overlay_wrap}`}
+ >
+ <div
+ class={`flex flex-col w-full gap-[2px] justify-center items-center`}
+ >
+ <div
+ class={`flex flex-row h-10 w-full justify-start items-center`}
+ >
+ <button
+ class={`group flex flex-row justify-center items-center`}
+ on:click={async () => {}}
+ >
+ <p
+ class={`font-sansd font-[600] text-[1.7rem] ${classes_photo_overlay_glyph} ${ld?.nostr_profile.display_name ? `` : `capitalize opacity-active`} el-re`}
+ >
+ {ld?.nostr_profile.display_name
+ ? ld.nostr_profile.display_name
+ : `+ ${`${$t(`icu.add_*`, { value: `${$t(`common.profile_name`)}` })}`}`}
+ </p>
+ </button>
+ </div>
+ <div
+ class={`flex flex-row w-full gap-[6px] justify-start items-center`}
+ >
+ <button
+ class={`group flex flex-row justify-center items-center`}
+ on:click={async () => {}}
+ >
+ <p
+ class={`font-sans font-[600] text-[1.1rem] ${classes_photo_overlay_glyph} ${ld?.nostr_profile.name ? `` : `capitalize opacity-active`} el-re`}
+ >
+ {ld?.nostr_profile.name
+ ? `@${ld.nostr_profile.name}`
+ : `+ ${`${$t(`icu.add_*`, { value: `${$t(`common.username`)}` })}`}`}
+ </p>
+ </button>
+ <p
+ class={`font-sans font-[400] ${classes_photo_overlay_glyph}`}
+ >
+ {ascii.bullet}
+ </p>
+ <button
+ class={`flex flex-row justify-center items-center`}
+ on:click={async () => {
+ alert(`@todo!`);
+ }}
+ >
+ <Glyph
+ basis={{
+ classes: `${classes_photo_overlay_glyph}`,
+ dim: `xs`,
+ weight: `bold`,
+ key: `link-simple`,
+ }}
+ />
+ </button>
+ </div>
+ <div class={`flex flex-row w-full justify-start items-center`}>
+ <button
+ class={`group flex flex-row justify-center items-center`}
+ on:click={async () => {}}
+ >
+ <p
+ class={`font-sans font-[400] text-[1.1rem] ${classes_photo_overlay_glyph} ${ld?.nostr_profile.about ? `` : `capitalize opacity-active`}`}
+ >
+ {ld?.nostr_profile.about
+ ? `@${ld.nostr_profile.about}`
+ : `+ ${`${$t(`icu.add_*`, { value: `${$t(`common.bio`)}` })}`}`}
+ </p>
+ </button>
+ </div>
+ </div>
+ <div
+ class={`flex flex-row w-full pt-2 pb-6 gap-2 justify-start items-center`}
+ >
+ <button
+ class={`flex flex-row justify-center items-center`}
+ on:click={async () => {
+ opt_display = `photos`;
+ }}
+ >
+ <p
+ class={`font-sans text-[1.1rem] font-[600] ${opt_display === `photos` ? `text-layer-1-glyph_d` : `text-layer-0-glyph`} el-re`}
+ >
+ {`Photos`}
+ </p>
+ </button>
+ <button
+ class={`flex flex-row justify-center items-center`}
+ on:click={async () => {
+ opt_display = `following`;
+ }}
+ >
+ <p
+ class={`font-sans text-[1.1rem] font-[600] ${opt_display === `following` ? `text-layer-1-glyph_d` : `text-layer-0-glyph`} el-re`}
+ >
+ {`Following`}
+ </p>
+ </button>
+ <button
+ class={`flex flex-row justify-center items-center`}
+ on:click={async () => {
+ opt_display = `followers`;
+ }}
+ >
+ <p
+ class={`font-sans text-[1.1rem] font-[600] ${opt_display === `followers` ? `text-layer-1-glyph_d` : `text-layer-0-glyph`} el-re`}
+ >
+ {`Followers`}
+ </p>
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class={`flex flex-col w-full justify-start items-center`}>
+ {#if opt_display === `photos`}
+ <p class={`font-sans font-[400] text-layer-0-glyph`}>
+ {`photos `.repeat(500)}
+ </p>
+ {:else if opt_display === `following`}
+ <p class={`font-sans font-[400] text-layer-0-glyph`}>
+ {`following `.repeat(500)}
+ </p>
+ {:else if opt_display === `followers`}
+ <p class={`font-sans font-[400] text-layer-0-glyph`}>
+ {`followers `.repeat(500)}
+ </p>
+ {/if}
+ </div>
+</LayoutView>
+<Nav
+ basis={{
+ prev: {
+ label: `${$t(`common.home`)}`,
+ route: `/`,
+ },
+ title: {
+ label: {
+ value: `${$t(`common.profile`)}`,
+ },
+ },
+ }}
+/>
diff --git a/src/routes/(cfg)/cfg/init/+page.svelte b/src/routes/(cfg)/cfg/init/+page.svelte
@@ -1132,7 +1132,7 @@
</p>
{#if loading_submit}
<div
- class={`absolute right-0 flex flex-row justify-start items-center`}
+ class={`absolute right-2 flex flex-row justify-start items-center`}
>
<Loading basis={{ dim: `xs` }} />
</div>
diff --git a/tailwind.config.ts b/tailwind.config.ts
@@ -103,6 +103,7 @@ const config: Config = {
},
fontFamily: {
sans: [`SF Pro Rounded`, ...tw_font.sans],
+ sansd: [`SF Pro Display`],
serif: [...tw_font.serif],
mono: [...tw_font.mono],
apercu: [`Apercu Mono Pro`],