commit 349a9c5602166edcaf1b2617e573342026ab59b7
parent a9fe266fd7771bc532f8d7e8ab0f313349bf1d9b
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Fri, 7 Mar 2025 16:48:01 +0000
apps-lib: edit profile view, profile edit view. split float page button into separate components. add/edit types
Diffstat:
8 files changed, 117 insertions(+), 83 deletions(-)
diff --git a/apps-lib/src/lib/components/button/button-round-nav.svelte b/apps-lib/src/lib/components/button/button-round-nav.svelte
@@ -0,0 +1,24 @@
+<script lang="ts">
+ import { Glyph, LoadSymbol, type IButtonNavRound } from "$root";
+
+ let { basis }: { basis: IButtonNavRound } = $props();
+</script>
+
+<button
+ class={`flex flex-row h-12 w-12 justify-center items-center bg-layer-1-surface rounded-full el-re`}
+ disabled={!!basis.disabled}
+ onclick={basis.callback}
+>
+ {#if basis.loading}
+ <LoadSymbol />
+ {:else}
+ <Glyph
+ basis={{
+ classes: `text-layer-0-glyph`,
+ dim: `sm+`,
+
+ key: basis.glyph,
+ }}
+ />
+ {/if}
+</button>
diff --git a/apps-lib/src/lib/components/button/float-page-button.svelte b/apps-lib/src/lib/components/button/float-page-button.svelte
@@ -1,43 +0,0 @@
-<script lang="ts">
- import { Glyph, LoadSymbol } from "$root";
- import {
- type GeometryScreenPositionHorizontal,
- type ICb,
- type IDisabledOpt,
- type IGlyphKey,
- type ILoadingOpt,
- } from "@radroots/util";
-
- let {
- basis,
- }: {
- basis: ICb &
- IDisabledOpt &
- ILoadingOpt &
- IGlyphKey & {
- posx: Omit<GeometryScreenPositionHorizontal, "center">;
- };
- } = $props();
-</script>
-
-<div class={`absolute top-10 ${basis.posx}-6 flex flex-row`}>
- <button
- class={`flex flex-row h-12 w-12 justify-center items-center bg-layer-1-surface rounded-full el-re`}
- disabled={!!basis.disabled}
- onclick={basis.callback}
- >
- {#if basis.loading}
- <LoadSymbol />
- {:else}
- <Glyph
- basis={{
- classes: `text-layer-0-glyph`,
- dim: `sm+`,
-
- key: basis.glyph,
- }}
- />
- {/if}
- </button>
-</div>
-<div class="hidden left-6 right-6"></div>
diff --git a/apps-lib/src/lib/components/float/float-page.svelte b/apps-lib/src/lib/components/float/float-page.svelte
@@ -0,0 +1,12 @@
+<script lang="ts">
+ import type { IFloatPage } from "$lib/types/component";
+ import type { Snippet } from "svelte";
+
+ let { basis, children }: { basis: IFloatPage; children: Snippet } =
+ $props();
+</script>
+
+<div class={`absolute top-10 ${basis.posx}-6 flex flex-row`}>
+ {@render children()}
+</div>
+<div class="hidden left-6 right-6"></div>
diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts
@@ -3,10 +3,10 @@ export { default as ButtonLabelDashed } from "./components/button/button-label-d
export { default as ButtonLabelGlyph } from "./components/button/button-label-glyph.svelte"
export { default as ButtonLayoutPair } from "./components/button/button-layout-pair.svelte"
export { default as ButtonLayout } from "./components/button/button-layout.svelte"
+export { default as ButtonRoundNav } from "./components/button/button-round-nav.svelte"
export { default as ButtonRound } from "./components/button/button-round.svelte"
export { default as ButtonSimpleGlyph } from "./components/button/button-simple-glyph.svelte"
export { default as ButtonSimple } from "./components/button/button-simple.svelte"
-export { default as FloatPageButton } from "./components/button/float-page-button.svelte"
export { default as GlyphButtonSimple } from "./components/button/glyph-button-simple.svelte"
export { default as GlyphButton } from "./components/button/glyph-button.svelte"
export { default as CarouselFlowItem } from "./components/carousel/carousel-flow-item.svelte"
@@ -15,6 +15,7 @@ export { default as CarouselItem } from "./components/carousel/carousel-item.sve
export { default as Carousel } from "./components/carousel/carousel.svelte"
export { default as EnvelopeLowerFull } from "./components/envelope/envelope-lower-full.svelte"
export { default as MapLocationSelectEnvelope } from "./components/envelope/map-location-select-envelope.svelte"
+export { default as FloatPage } from "./components/float/float-page.svelte"
export { default as EntryLineIdb } from "./components/form/entry-line-idb.svelte"
export { default as EntryLine } from "./components/form/entry-line.svelte"
export { default as EntryMultiline } from "./components/form/entry-multiline.svelte"
@@ -95,6 +96,7 @@ export * from "./store/client.js"
export * from "./store/component.js"
export * from "./store/layout.js"
export * from "./store/ndk.js"
+export * from "./types/component.js"
export * from "./types/view.js"
export * from "./util/carousel.js"
export * from "./util/casl.js"
diff --git a/apps-lib/src/lib/types/component.ts b/apps-lib/src/lib/types/component.ts
@@ -0,0 +1,7 @@
+import { type GeometryScreenPositionHorizontal, type ICb, type IDisabledOpt, type IGlyphKey, type ILoadingOpt } from "@radroots/util";
+
+export type IButtonNavRound = ICb & IDisabledOpt & ILoadingOpt & IGlyphKey;
+
+export type IFloatPage = {
+ posx: Omit<GeometryScreenPositionHorizontal, "center">;
+}
+\ No newline at end of file
diff --git a/apps-lib/src/lib/types/view.ts b/apps-lib/src/lib/types/view.ts
@@ -3,10 +3,7 @@ export type IViewProfileData = {
name?: string;
display_name?: string;
about?: string;
- photos?: {
- src: string;
- primary: boolean;
- }[];
+ picture?: string;
};
export type ViewProfileEditFieldKey = `name` | `display_name` | `about`;
diff --git a/apps-lib/src/lib/view/profile-edit.svelte b/apps-lib/src/lib/view/profile-edit.svelte
@@ -1,7 +1,8 @@
<script lang="ts">
+ import ButtonRoundNav from "$lib/components/button/button-round-nav.svelte";
+ import FloatPage from "$lib/components/float/float-page.svelte";
import Empty from "$lib/components/lib/empty.svelte";
import {
- FloatPageButton,
fmt_id,
handle_err,
idb_init_page,
@@ -81,16 +82,21 @@
{/if}
</LayoutPage>
</LayoutView>
-<FloatPageButton
+<FloatPage
basis={{
posx: `left`,
- glyph: `arrow-left`,
- callback: async () => {
- await basis.lc_handle_back({
- field: basis.data.field,
- public_key: basis.data.public_key,
- });
- },
}}
-/>
+>
+ <ButtonRoundNav
+ basis={{
+ glyph: `arrow-left`,
+ callback: async () => {
+ await basis.lc_handle_back({
+ field: basis.data.field,
+ public_key: basis.data.public_key,
+ });
+ },
+ }}
+ />
+</FloatPage>
<NavigationTabs />
diff --git a/apps-lib/src/lib/view/profile.svelte b/apps-lib/src/lib/view/profile.svelte
@@ -1,7 +1,9 @@
<script lang="ts">
+ import ButtonRoundNav from "$lib/components/button/button-round-nav.svelte";
+ import FloatPage from "$lib/components/float/float-page.svelte";
import ImageBlob from "$lib/components/lib/image-blob.svelte";
+ import SelectMenu from "$lib/components/lib/select-menu.svelte";
import {
- FloatPageButton,
Glyph,
handle_err,
idb_init_page,
@@ -26,11 +28,12 @@
let {
basis,
ls,
- photo_path_opt = $bindable(``),
+ photo_path = $bindable(``),
}: {
basis: IViewBasis<{
data: IViewProfileData;
loading_photo_upload: boolean;
+ loading_photo_upload_open: boolean;
lc_handle_back: CallbackPromise;
lc_handle_photo_add: LcPhotoAddCallback;
lc_handle_photo_options: CallbackPromise;
@@ -41,12 +44,14 @@
}> &
IViewOnDestroy<{ public_key: string }>;
ls: I18nTranslateFunction;
- photo_path_opt: string;
+ photo_path: string;
} = $props();
type ViewDisplay = `photos` | `following` | `followers`;
let view_display: ViewDisplay = $state(`photos`);
+ let val_sel_options_button = $state(``);
+
onMount(async () => {
try {
if (!basis.kv_init_prevent) await idb_init_page();
@@ -63,9 +68,9 @@
}
});
- const profile_photo = $derived(basis.data?.photos?.find((i) => i.primary));
-
- const photo_overlay_visible = $derived(!!(profile_photo || photo_path_opt));
+ const photo_overlay_visible = $derived(
+ !!(basis.data.picture || photo_path),
+ );
const classes_photo_overlay_glyph = $derived(
photo_overlay_visible ? `text-white` : `text-layer-0-glyph`,
@@ -83,41 +88,64 @@
<div
class={`relative flex flex-col min-h-[525px] h-[525px] w-full justify-center items-center bg-layer-2-surface fade-in`}
>
- <FloatPageButton
+ <FloatPage
basis={{
posx: `left`,
- glyph: `arrow-left`,
- callback: basis.lc_handle_back,
}}
- />
- <FloatPageButton
+ >
+ <ButtonRoundNav
+ basis={{
+ glyph: `arrow-left`,
+ loading: basis.loading_photo_upload,
+ callback: basis.lc_handle_back,
+ }}
+ />
+ </FloatPage>
+ <FloatPage
basis={{
posx: `right`,
- glyph: `images-square`,
- callback: basis.lc_handle_photo_options,
}}
- />
- {#if profile_photo}
- <ImagePath
+ >
+ <SelectMenu
+ bind:value={val_sel_options_button}
basis={{
- path: profile_photo.src,
+ layer: 0,
+ options: [
+ {
+ entries: [
+ {
+ value: `*add-new`,
+ label: `Add new photo`,
+ },
+ ],
+ },
+ ],
}}
- />
- {:else if photo_path_opt}
- {#if photo_path_opt.startsWith(`file://`)}
- {#await basis.lc_fs_read_bin(photo_path_opt) then data}
+ >
+ <ButtonRoundNav
+ basis={{
+ glyph: `images-square`,
+ callback: basis.lc_handle_photo_options,
+ }}
+ />
+ </SelectMenu>
+ </FloatPage>
+ {#if basis.data.picture || photo_path}
+ {@const img_path = photo_path || basis.data.picture || ``}
+ {#if img_path.startsWith(`file://`)}
+ {#await basis.lc_fs_read_bin(img_path) then data}
<ImageBlob basis={{ data }} />
{/await}
- {:else if photo_path_opt.startsWith(`https://`)}
- <ImagePath basis={{ path: photo_path_opt }} />
+ {:else if img_path.startsWith(`http://`) || img_path.startsWith(`https://`)}
+ <ImagePath basis={{ path: img_path }} />
{/if}
{:else}
<div class={`flex flex-row justify-start items-center -translate-y-8`}>
<ImageUploadAddPhoto
- bind:photo_path={photo_path_opt}
+ bind:photo_path
{ls}
basis={{
- loading: basis.loading_photo_upload,
+ loading: basis.loading_photo_upload_open,
lc_handle_photo_add: basis.lc_handle_photo_add,
}}
/>