commit 4e4637717595700b5845ea3b5e55dc45677e5c13 parent 2a54a0baf4c6db2a9011cf57ac86a614aab65411 Author: triesap <137732411+triesap@users.noreply.github.com> Date: Fri, 27 Sep 2024 08:13:00 +0000 Add `models/nostr-profile/edit` and `models/nostr-profile/view`, edit (conf/app) layout functions, edit routes, edit lib components, conf, utils, styles. Diffstat:
30 files changed, 1113 insertions(+), 329 deletions(-)
diff --git a/src/app.css b/src/app.css @@ -9,3 +9,9 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer components { + .tap-rise-1 { + @apply active:scale-[101%] group-active:scale-[101%] delay-75 duration-700 ease-in-out transition-all; + } +} +\ No newline at end of file diff --git a/src/lib/components/map_control_full.svelte b/src/lib/components/map_control_full.svelte @@ -1,6 +1,5 @@ <script lang="ts"> - import { goto } from "$app/navigation"; - import { Glyph, app_layout } from "@radroots/svelte-lib"; + import { Glyph, app_layout, route } from "@radroots/svelte-lib"; let el_zoom: HTMLElement | null; </script> @@ -12,7 +11,7 @@ <button class={`flex flex-row h-8 w-8 justify-center items-center rounded-2xl bg-layer-1-surface`} on:click={async () => { - await goto(`/`); + await route(`/`); }} > <Glyph diff --git a/src/lib/components/map_full_envelope.svelte b/src/lib/components/map_full_envelope.svelte @@ -1,6 +1,5 @@ <script lang="ts"> - import { goto } from "$app/navigation"; - import { Glyph, app_layout } from "@radroots/svelte-lib"; + import { Glyph, app_layout, route } from "@radroots/svelte-lib"; let el: HTMLElement | null; </script> @@ -12,7 +11,7 @@ <button class={`flex flex-row h-8 w-8 justify-center items-center rounded-2xl bg-layer-1-surface`} on:click={async () => { - await goto(`/`); + await route(`/`); }} > <Glyph diff --git a/src/lib/conf.ts b/src/lib/conf.ts @@ -23,15 +23,18 @@ export const _conf = { title: `Radroots`, description: `Creating networks between farmers, communities and small businesses that give customers greater access to natural foods and grow circular economies where profits are more fairly distributed. Radroots is built on the Nostr protocol and released under a copyleft open source license to provide transparency and give users the option to offer feedback and add or request new features.` }, - const: { - load_delay: 321 + delay: { + load: 321, + notify: 123, + mount_el: 500 }, kv: { nostr_key: (public_key: string) => `nostr:key:${public_key}`, nostr_key_active: `nostr:key:active`, }, cmd: { - root_alert: `*-alert` + //root_alert: `*-alert`, + layout_route: `*-route` }, map: { styles: { diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts @@ -1,22 +1,14 @@ -import { goto } from "$app/navigation"; -import { _conf } from "$lib/conf"; -import { kv } from "@radroots/svelte-lib"; +import { route, type NavigationRoute } from "@radroots/svelte-lib"; import { lc } from "../client"; -export const restart = async (route_to: true | string, alert_message?: string): Promise<void> => { +export const restart = async (route_to: true | NavigationRoute, notify_message?: string): Promise<void> => { try { await lc.window.splash_show(); - if (alert_message) { - await kv.set( - _conf.cmd.root_alert, - alert_message - ); + if (notify_message) { + console.log(`todo! notify_message `, notify_message) + //app_notify.set(notify_message); } - if (route_to) { - if (route_to === true) await goto(`/`); - else await goto(route_to) - } - + await route(typeof route_to === `string` ? route_to : `/`) location.reload(); } catch (e) { console.log(`(error) restart `, e); diff --git a/src/lib/utils/keystore.ts b/src/lib/utils/keystore.ts @@ -3,11 +3,8 @@ import { lc } from "$lib/client"; export const keystore_reset = async (): Promise<void> => { try { const ks_keys = await lc.keystore.keys(); - console.log(JSON.stringify(ks_keys, null, 4), `ks_keys`); if (!ks_keys) return; - for (const ks_key of ks_keys) { - await lc.keystore.remove(ks_key); - } + for (const ks_key of ks_keys) await lc.keystore.remove(ks_key); } catch (e) { console.log(`(error) keystore_reset `, e); } diff --git a/src/lib/utils/trade_product.ts b/src/lib/utils/trade_product.ts @@ -51,50 +51,3 @@ export const trade_product_kv_init = async (kv_pref: string): Promise<void> => { console.log(`(error) trade_product_kv_init `, e); } }; - -/* - const vals = trade_product_form_vals; - console.log(`vals 0!`, vals); - for (const [k, field] of Object.entries( - trade_product_form_fields, - )) { - const field_k = parse_trade_product_form_keys(k); - if (!field_k) continue; - const field_id = fmt_id(field_k); - let field_val = ``; - if (field_k === `price_qty_unit`) { - field_val = await $kv.get(`price_unit`); - } else { - field_val = await $kv.get(field_id); - } - - /* - - if (field_k === `key`) { - field_val = sel_trade_product_key; - } else - - - vals[field_k] = field_val; - } - - console.log(JSON.stringify(vals, null, 4), `vals`); - /* - const db_add = await lc.db.trade_product_add(vals); - if (typeof db_add !== `string` && !Array.isArray(db_add)) { - const { id: trade_product_id } = db_add; - const db_rel = await lc.db.set_trade_product_location({ - trade_product_id, - location_gcs_id: location_gcs_res[0].id, - }); - if (typeof db_rel === `string`) { - // @todo - } - await goto(`/models/trade-product`); - } else { - // @todo - await lc.dialog.alert( - `There was an error: ${db_add.toString()}`, - ); - } -*/ -\ No newline at end of file diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte @@ -1,17 +1,17 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { LayoutWindow, Tabs, app_tab_active, - app_tabs_visible, + route, + tabs_visible, } from "@radroots/svelte-lib"; </script> <LayoutWindow> <slot /> </LayoutWindow> -{#if $app_tabs_visible} +{#if $tabs_visible} <Tabs basis={{ list: [ @@ -19,27 +19,26 @@ icon: `house-line`, callback: async (tab_i) => { app_tab_active.set(tab_i); - await goto("/"); + await route(`/`); }, }, { icon: `compass`, callback: async (tab_i) => { - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); }, }, { icon: `network`, callback: async (tab_i) => { - app_tab_active.set(tab_i); - await goto("/test"); + await route(`/models/nostr-profile`); }, }, { icon: `bell-simple`, callback: async (tab_i) => { app_tab_active.set(tab_i); - await goto("/settings"); + await route(`/settings`); }, }, ], diff --git a/src/routes/(app)/+layout.ts b/src/routes/(app)/+layout.ts @@ -1,18 +1,8 @@ -import { lc } from '$lib/client'; -import { _conf } from '$lib/conf'; -import { kv } from '@radroots/svelte-lib'; import type { LayoutLoad, LayoutLoadEvent } from '../$types'; export const load: LayoutLoad = async ({ url }: LayoutLoadEvent) => { try { console.log(`layout (app) `, url.pathname); - if (url.pathname === `/`) { - const root_alert = await kv.get(_conf.cmd.root_alert); - if (root_alert) { - await kv.delete(_conf.cmd.root_alert); - lc.dialog.alert(root_alert); - } - } } catch (e) { console.log(`layout (app) error: `, e); } finally { diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte @@ -1,14 +1,17 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { app_nostr_key } from "$lib/stores"; import { app_tab_active, - app_tabs_visible, + type CallbackPromise, EnvelopeLower, Glyph, type GlyphKey, type GlyphWeight, LayoutView, + nav_prev, + type NavigationRoute, + route, + tabs_visible, } from "@radroots/svelte-lib"; import { onMount } from "svelte"; @@ -16,18 +19,20 @@ onMount(async () => { try { - app_tabs_visible.set(true); + tabs_visible.set(true); app_tab_active.set(0); + nav_prev.set([]); } catch (e) { } finally { } }); let buttons: { - route: string; + route: NavigationRoute; label: string; key: GlyphKey; weight?: GlyphWeight; + callback?: CallbackPromise; }[] = [ { route: `/models/location-gcs`, @@ -51,6 +56,15 @@ label: `Keys`, key: `key`, weight: `fill`, + callback: async () => { + nav_prev.set([ + ...$nav_prev, + { + route: `/`, + label: `Home`, + }, + ]); + }, }, ]; </script> @@ -91,7 +105,8 @@ <button class={`col-span-6 flex flex-col h-20 py-2 px-3 justify-between rounded-2xl bg-layer-1-surface text-layer-2-glyph font-[500] text-lg font-mono tap-rise active-ring-gray transition-all`} on:click={async () => { - await goto(btn.route); + if (btn.callback) await btn.callback(); + await route(btn.route); }} > <div diff --git a/src/routes/(app)/models/location-gcs/+page.svelte b/src/routes/(app)/models/location-gcs/+page.svelte @@ -3,10 +3,11 @@ import { location_gcs_add } from "$lib/utils/location_gcs"; import { type LocationGcs } from "@radroots/models"; import { - app_tabs_visible, LayoutTrellis, LayoutView, Nav, + t, + tabs_visible, Trellis, } from "@radroots/svelte-lib"; import { onMount } from "svelte"; @@ -16,7 +17,7 @@ onMount(async () => { try { - app_tabs_visible.set(false); + tabs_visible.set(false); await fetch_models(); } catch (e) { } finally { @@ -47,7 +48,7 @@ args: { layer: 1, title: { - value: `Your Locations`, + value: `${$t(`icu.your_*`, { value: `${$t(`common.locations`)}` })}`, }, list: [ { @@ -125,12 +126,14 @@ route: `/`, }, title: { - label: `Locations`, + label: { + value: `${$t(`common.locations`)}`, + }, }, option: models_list.length ? { label: { - value: `Add`, + value: `${$t(`common.add`)}`, classes: `tap-color`, }, callback: async () => { diff --git a/src/routes/(app)/models/nostr-profile/+page.svelte b/src/routes/(app)/models/nostr-profile/+page.svelte @@ -7,7 +7,6 @@ type NostrProfile, } from "@radroots/models"; import { - app_tabs_visible, as_glyph_key, LayoutTrellis, LayoutView, @@ -18,28 +17,28 @@ import { onMount } from "svelte"; let models_list: NostrProfile[] = []; - let loading_models = false; + //let loading_models = false; onMount(async () => { try { - app_tabs_visible.set(false); - await fetch_models(); + await load_models(); } catch (e) { } finally { } }); - const fetch_models = async (): Promise<void> => { + const load_models = async (): Promise<void> => { try { - loading_models = true; + //loading_models = true; const res = await lc.db.nostr_profile_get({ list: [`all`], }); + console.log(JSON.stringify(res, null, 4), `res`); if (typeof res !== `string`) models_list = res; } catch (e) { - console.log(`(error) fetch_models `, e); + console.log(`(error) load_models `, e); } finally { - loading_models = false; + //loading_models = false; } }; </script> @@ -53,7 +52,7 @@ args: { layer: 1, title: { - value: `Your Profiles`, + value: `${$t(`icu.your_*`, { value: `${$t(`common.profiles`)}` })}`, }, list: [ ...Object.keys(nostr_profile_form_vals).map( @@ -91,36 +90,11 @@ }), ), ], - - /*[ - { - hide_active: true, - touch: { - label: { - left: [ - { - value: `Public Key:`, - classes: `capitalize pr-2`, - }, - ], - right: [ - { - classes: `truncate`, - value: li.public_key, - }, - ], - }, - callback: async () => {}, - }, - }, - - ], - */ }, }} /> {/each} - {:else if !loading_models} + {:else} <div class={`flex flex-col w-full justify-center items-center px-4 gap-3`} > @@ -132,7 +106,7 @@ class={`flex flex-row justify-center items-center`} on:click={async () => { const res = await location_gcs_add(); - if (res === true) await fetch_models(); + if (res === true) await load_models(); }} > <p @@ -148,21 +122,23 @@ <Nav basis={{ prev: { - label: `Back`, + label: `${$t(`common.back`)}`, route: `/`, }, title: { - label: `Profiles`, + label: { + value: `${$t(`common.profiles`)}`, + }, }, option: models_list.length ? { label: { - value: `Add`, + value: `${$t(`common.add`)}`, classes: `tap-color`, }, callback: async () => { //const res = await location_gcs_add(); - //if (res === true) await fetch_models(); + //if (res === true) await load_models(); const ks_keys = await lc.keystore.keys(); console.log(JSON.stringify(ks_keys, null, 4), `ks_keys`); for (const ks_key of ks_keys || []) { diff --git a/src/routes/(app)/models/nostr-profile/edit/field/+page.svelte b/src/routes/(app)/models/nostr-profile/edit/field/+page.svelte @@ -0,0 +1,240 @@ +<script lang="ts"> + import { lc } from "$lib/client"; + import { + nostr_profile_form_fields, + parse_nostr_profile_form_keys, + type NostrProfile, + type NostrProfileFields, + type NostrProfileFormFields, + } from "@radroots/models"; + import { + app_notify, + app_submit_route, + Fill, + fmt_id, + kv, + LayoutTrellis, + LayoutView, + Nav, + qp_nostr_pk, + qp_rkey, + route, + sleep, + t, + Trellis, + } from "@radroots/svelte-lib"; + import { onDestroy, onMount } from "svelte"; + + let el_input: HTMLInputElement | null = null; + let el_input_loaded = false; + + type LoadData = { + nostr_profile: NostrProfile; + field_key: keyof NostrProfileFields; + }; + let ld: LoadData | undefined = undefined; + + onMount(async () => { + try { + if (!$qp_rkey || !$qp_nostr_pk) + app_notify.set(`Missing page params`); + + ld = await load_page(); + } catch (e) { + } finally { + } + }); + + onDestroy(async () => { + try { + qp_rkey.set(``); + qp_nostr_pk.set(``); + } catch (e) { + } finally { + } + }); + + let val_field_valid = false; + $: translated_field_key = ld?.field_key + ? `${$t(`model_fields.${ld?.field_key}`, { default: ld?.field_key?.replaceAll(`_`, ` `) })}`.toLowerCase() + : ``; + + const load_page = async (): Promise<LoadData | undefined> => { + try { + const nostr_profiles = await lc.db.nostr_profile_get({ + public_key: $qp_nostr_pk, + }); + if (typeof nostr_profiles === `string`) { + app_notify.set(`Error loading profile`); + return; + } + + const field_key = parse_nostr_profile_form_keys($qp_rkey); + if (!field_key) { + app_notify.set(`Error loading page`); + return; + } + const nostr_profile = nostr_profiles[0]; + + //const existing_field = nostr_profile[field_key]; + //console.log(`existing_field `, existing_field); + //if (existing_field) await kv.set(fmt_id($qp_rkey), existing_field); + + const data: LoadData = { + nostr_profile, + field_key, + }; + return data; + } catch (e) { + console.log(`(error) load_page `, e); + } + }; + + const submit = async (): Promise<void> => { + try { + if (!ld?.field_key || !ld?.nostr_profile) return; + + const val = await kv.get(fmt_id($qp_rkey)); + if (!val) { + await route(`/models/nostr-profile`); + return; + } + const validated = + nostr_profile_form_fields[ld?.field_key].validation.test(val); + if (!validated) { + lc.dialog.alert( + `${$t(`icu.invalid_*_entry`, { value: translated_field_key })}`, + ); + return; + } + + const fields: Partial<NostrProfileFormFields> = {}; + fields[ld?.field_key] = val; + + const update_db = await lc.db.nostr_profile_update({ + on: { + public_key: $qp_nostr_pk, + }, + fields, + }); + if (update_db === true) { + // @todo sync to nostr + if ($app_submit_route) { + await route( + $app_submit_route.route, + $app_submit_route.params, + ); + } else { + await route(`/nostr/keys`); + } + return; + } else { + await lc.dialog.alert(JSON.stringify(update_db)); //@todo + } + } catch (e) { + console.log(`(error) submit `, e); + } + }; + + $: { + if (el_input_loaded && el_input) { + el_input.focus(); + } + } +</script> + +<LayoutView> + <LayoutTrellis> + {#if ld} + <Trellis + basis={{ + args: { + hide_offset: true, + layer: 1, + title: { + value: ld?.nostr_profile[ld?.field_key] + ? `${$t(`icu.edit_*`, { value: translated_field_key })}` + : `${$t(`icu.add_a_*`, { value: translated_field_key.toLowerCase() })}`, + }, + list: [ + { + hide_active: true, + input: { + basis: { + id: fmt_id($qp_rkey), + sync: true, + sync_init: ld?.nostr_profile[ + ld?.field_key + ] + ? ld.nostr_profile[ld.field_key] + : true, + classes: `placeholder:font-[300]`, + placeholder: ld?.nostr_profile[ + ld?.field_key + ] + ? `${$t(`icu.enter_new_*`, { value: translated_field_key.toLowerCase() })}` + : `${$t(`icu.add_a_*`, { value: translated_field_key.toLowerCase() })}`, + field: { + charset: + nostr_profile_form_fields[ + ld?.field_key + ].charset, + validate: + nostr_profile_form_fields[ + ld?.field_key + ].validation, + validate_keypress: false, + }, + callback: async ({ pass }) => { + val_field_valid = pass; + }, + callback_keydown: async ({ key }) => { + if (key === `Enter`) await submit(); + }, + on_mount: async (el) => { + el_input = el; + await sleep(600); + el_input_loaded = true; + }, + }, + }, + }, + ], + }, + }} + > + <div + slot="offset" + class={`flex flex-row w-4 justify-start items-center`} + > + <Fill /> + </div> + </Trellis> + {/if} + </LayoutTrellis> +</LayoutView> +<Nav + basis={{ + prev: { + label: `${$t(`common.back`)}`, + route: `/models/nostr-profile`, + }, + title: { + label: { + classes: `capitalize`, + value: translated_field_key, + }, + }, + option: { + label: { + classes: val_field_valid ? `` : `opacity-60`, + value: ld?.nostr_profile[ld?.field_key] + ? `${$t(`common.update`)}` + : `${$t(`common.add`)}`, + }, + callback: async () => { + if (val_field_valid) await submit(); + }, + }, + }} +/> diff --git a/src/routes/(app)/models/nostr-profile/view/+page.svelte b/src/routes/(app)/models/nostr-profile/view/+page.svelte @@ -0,0 +1,419 @@ +<script lang="ts"> + import { lc } from "$lib/client"; + import { _conf } from "$lib/conf"; + import { app_nostr_key } from "$lib/stores"; + import type { NostrProfile } from "@radroots/models"; + import { + app_notify, + app_submit_route, + as_glyph_key, + clipboard_copy, + LayoutTrellis, + LayoutView, + Nav, + nav_prev, + qp_nostr_pk, + route, + show_toast, + t, + Trellis, + } from "@radroots/svelte-lib"; + import { onMount } from "svelte"; + + type LoadData = { + nostr_profile: NostrProfile; + secret_key: string; + }; + let ld: LoadData | undefined = undefined; + + let el_edit: HTMLLabelElement | null; + let show_public_key_hex = false; + let show_secret_key_hex = false; + let vl_secret_key_unlock = false; + + onMount(async () => { + try { + if (!$qp_nostr_pk) app_notify.set(`Error loading page`); + ld = await load_page(); + } catch (e) { + } finally { + } + }); + + const load_page = async (): Promise<LoadData | undefined> => { + try { + const nostr_profiles = await lc.db.nostr_profile_get({ + public_key: $qp_nostr_pk, + }); + if (typeof nostr_profiles === `string`) { + app_notify.set(`Error loading profile`); + return; + } + + const nostr_profile = nostr_profiles[0]; + const secret_key = await lc.keystore.get( + _conf.kv.nostr_key(nostr_profile.public_key), + ); + + if (!secret_key) { + app_notify.set(`Error loading profile`); + return; + } + + const data: LoadData = { + nostr_profile, + secret_key, + }; + return data; + } catch (e) { + console.log(`(error) load_page `, e); + } + }; + + const toggle_hex_pk = (): void => { + show_public_key_hex = !show_public_key_hex; + }; + + const toggle_hex_sk = (): void => { + show_secret_key_hex = !show_secret_key_hex; + }; +</script> + +<LayoutView> + <LayoutTrellis> + {#if ld} + <Trellis + basis={{ + args: { + layer: 1, + title: { + value: `${$t(`common.public_key`)}`, + link: { + label: { + swap: { + on: { + classes: `pl-1 text-trellisTitleNote uppercase -translate-y-[1px] -translate-x-[2px] text-layer-0-glyph-shade`, + value: `${$t(`common.npub`)}`, + }, + off: { + classes: `pl-1 text-trellisTitleNote uppercase -translate-y-[1px] -translate-x-[6px] text-layer-0-glyph-shade`, + value: `${$t(`common.hex`)}`, + }, + toggle: show_public_key_hex, + }, + }, + callback: async () => { + toggle_hex_pk(); + }, + }, + }, + list: [ + { + offset: { + mod: `sm`, + }, + touch: { + label: { + left: [ + { + value: show_public_key_hex + ? ld.nostr_profile + .public_key + : lc.nostr.lib.npub( + ld.nostr_profile + .public_key, + ), + }, + ], + }, + callback: async () => { + if (!ld) return; + await show_toast({ + args: { + position: `bottom-center`, + label: { + value: `${`${$t( + `icu.*_as`, + { + value: `${$t( + `icu.*_copied`, + { + value: `${$t( + `common.public_key`, + )}`, + }, + )}`, + }, + )}`} ${show_public_key_hex ? `${$t(`common.hex`)}`.toLowerCase() : `${$t(`common.npub`)}`.toLowerCase()}.`, + }, + }, + callback: async () => { + if (!ld) return; + await clipboard_copy( + show_public_key_hex + ? ld?.nostr_profile + .public_key + : lc.nostr.lib.npub( + ld.nostr_profile + .public_key, + ), + ); + }, + }); + }, + }, + }, + ], + }, + }} + /> + <Trellis + basis={{ + args: { + layer: 1, + title: { + value: `${$t(`common.secret_key`)}`, + link: { + label: { + swap: { + on: { + classes: `pl-1 text-trellisTitleNote uppercase -translate-y-[1px] -translate-x-[2px] text-layer-0-glyph-shade`, + value: `${$t(`common.nsec`)}`, + }, + off: { + classes: `pl-1 text-trellisTitleNote uppercase -translate-y-[1px] -translate-x-[6px] text-layer-0-glyph-shade`, + value: `${$t(`common.hex`)}`, + }, + toggle: vl_secret_key_unlock + ? show_secret_key_hex + : false, + }, + }, + callback: async () => { + if (vl_secret_key_unlock) toggle_hex_sk(); + }, + }, + }, + list: [ + { + offset: { + mod: `sm`, + }, + touch: { + label: { + left: [ + { + value: vl_secret_key_unlock + ? show_secret_key_hex + ? ld.secret_key + : lc.nostr.lib.nsec( + ld.secret_key, + ) + : `•`.repeat(40), + }, + ], + }, + callback: async () => { + if (!ld) return; + await show_toast({ + args: { + position: `bottom-center`, + label: { + value: `${`${$t( + `icu.*_as`, + { + value: `${$t( + `icu.*_copied`, + { + value: `${$t( + `common.secret_key`, + )}`, + }, + )}`, + }, + )}`} ${show_secret_key_hex ? `${$t(`common.hex`)}`.toLowerCase() : `${$t(`common.nsec`)}`.toLowerCase()}.`, + }, + }, + callback: async () => { + if (!ld) return; + await clipboard_copy( + show_secret_key_hex + ? ld.secret_key + : lc.nostr.lib.npub( + ld.secret_key, + ), + ); + }, + }); + }, + }, + }, + ], + }, + }} + /> + <Trellis + basis={{ + args: { + layer: 1, + title: { + value: `${$t(`common.status`)}`, + }, + list: [ + { + hide_active: vl_secret_key_unlock, + touch: { + label: { + left: [ + { + classes: + $app_nostr_key === + ld.nostr_profile.public_key + ? `text-success font-[400]` + : undefined, + value: + $app_nostr_key === + ld.nostr_profile.public_key + ? `${$t(`common.active`)}` + : `${$t( + `common.public_key`, + )}`, + }, + ], + }, + }, + }, + ], + }, + }} + /> + <Trellis + basis={{ + args: { + layer: 1, + title: { + value: `${$t(`common.profile`)}`, + }, + list: [ + { + hide_active: vl_secret_key_unlock, + touch: { + label: { + left: [ + { + classes: ld.nostr_profile.name + ? `` + : `text-layer-1-glyph-shade`, + value: + ld.nostr_profile.name || + `${$t(`icu.no_*_published`, { value: `${$t(`common.profile`)}`.toLowerCase() })}`, + }, + ], + }, + end: { + icon: { + key: as_glyph_key(`caret-right`), + }, + }, + callback: async () => { + if (!ld) return; + app_submit_route.set({ + route: `/models/nostr-profile/view`, + params: [ + [ + `nostr_pk`, + ld.nostr_profile.public_key, + ], + ], + }); + $nav_prev.push({ + route: `/models/nostr-profile/view`, + label: `Key`, + params: [ + [ + `nostr_pk`, + ld.nostr_profile.public_key, + ], + ], + }); + await route( + `/models/nostr-profile/edit/field`, + [ + [ + `nostr_pk`, + ld.nostr_profile.public_key, + ], + [`rkey`, `name`], + ], + ); + }, + }, + }, + ], + }, + }} + /> + <Trellis + basis={{ + args: { + layer: 1, + title: { + value: `${$t(`icu.connected_*`, { value: `${$t(`common.relays`)}` })}`, + }, + list: [ + { + hide_active: vl_secret_key_unlock, + touch: { + label: { + left: [ + { + classes: ld.nostr_profile.name + ? `` + : `text-layer-1-glyph-shade`, + value: + ld.nostr_profile.name || + `${$t(`icu.no_*_published`, { value: `${$t(`common.relays`)}`.toLowerCase() })}`, + }, + ], + }, + }, + }, + ], + }, + }} + /> + {/if} + </LayoutTrellis> +</LayoutView> +<Nav + basis={{ + prev: { + label: `${$t(`common.back`)}`, + route: `/models/nostr-profile`, + }, + title: { + label: { + classes: `capitalize`, + value: `${$t(`common.key`)}`, + }, + }, + option: { + label: { + swap: { + on: { + value: `${$t(`common.done`)}`, + }, + off: { + value: `${$t(`common.unlock`)}`, + }, + toggle: vl_secret_key_unlock, + }, + }, + callback: async ([visible, el]) => { + vl_secret_key_unlock = visible; + //show_secret_key_hex = visible; + el_edit = el; + }, + }, + }} +/> diff --git a/src/routes/(app)/models/trade-product/+page.svelte b/src/routes/(app)/models/trade-product/+page.svelte @@ -1,13 +1,14 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { lc } from "$lib/client"; import { type TradeProduct } from "@radroots/models"; import { - app_tabs_visible, LayoutTrellis, LayoutView, locale, Nav, + route, + t, + tabs_visible, time_fmt_iso, Trellis, } from "@radroots/svelte-lib"; @@ -18,7 +19,7 @@ onMount(async () => { try { - app_tabs_visible.set(false); + tabs_visible.set(false); await fetch_models(); } catch (e) { } finally { @@ -166,16 +167,18 @@ route: `/`, }, title: { - label: `Products`, + label: { + value: `${$t(`common.products`)}`, + }, }, option: models_list.length ? { label: { - value: `Add`, + value: `${$t(`common.add`)}`, classes: `tap-color`, }, callback: async () => { - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); }, } : undefined, diff --git a/src/routes/(app)/models/trade-product/add/+page.svelte b/src/routes/(app)/models/trade-product/add/+page.svelte @@ -1,7 +1,6 @@ <!-- svelte-ignore a11y-no-noninteractive-tabindex --> <script lang="ts"> - import { goto } from "$app/navigation"; import { lc } from "$lib/client"; import { location_gcs_add } from "$lib/utils/location_gcs"; import { @@ -24,6 +23,7 @@ LayoutView, Nav, NotifyGlyph, + route, t, } from "@radroots/svelte-lib"; import { @@ -207,7 +207,7 @@ if (!vals.price_qty_amt) await kv.set(fmt_id(`price_qty_amt`), `1`); if (!vals.qty_avail) await kv.set(fmt_id(`qty_avail`), `1`); - await goto(`/models/trade-product/add/preview`); + await route(`/models/trade-product/add/preview`); } catch (e) { console.log(`(error) submit `, e); } finally { @@ -520,14 +520,16 @@ <Nav basis={{ prev: { - label: `Back`, + label: `${$t(`common.back`)}`, route: `/models/trade-product`, callback: async () => { await trade_product_kv_init(fmt_id()); }, }, title: { - label: `Add Product`, + label: { + value: `${$t(`icu.add_*`, { value: `${$t(`common.product`)}` })}`, + }, callback: async () => { const el = el_id(fmt_id(`key_wrap`)); el?.focus(); diff --git a/src/routes/(app)/models/trade-product/add/preview/+page.svelte b/src/routes/(app)/models/trade-product/add/preview/+page.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { lc } from "$lib/client"; import { trade_product_kv_vals } from "$lib/utils/trade_product"; import { @@ -14,6 +13,7 @@ LayoutView, locale, Nav, + route, t, } from "@radroots/svelte-lib"; import { fmt_currency_tuple } from "@radroots/utils"; @@ -53,7 +53,7 @@ }); if (typeof vals === `string`) { await lc.dialog.alert(`Invalid value ${vals}.`); - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); return; } @@ -67,7 +67,7 @@ if (typeof location_gcs_res === `string`) { await lc.dialog.alert(`The product location is missing.`); - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); //@todo add focus return; } @@ -89,19 +89,19 @@ if (typeof vals === `string`) { lc.dialog.alert(`There was a problem adding the product`); - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); return; } const res = await lc.db.trade_product_add(vals); if (typeof res === `string`) { lc.dialog.alert(res); - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); return; } else if (Array.isArray(res)) { lc.dialog.alert(res.join(" ")); - await goto(`/models/trade-product/add`); + await route(`/models/trade-product/add`); return; } @@ -111,7 +111,7 @@ ); for (const key of kv_keys) await kv.delete(key); - await goto(`/models/trade-product`); + await route(`/models/trade-product`); } catch (e) { console.log(`(error) submit `, e); } @@ -169,7 +169,9 @@ `*-el-focus`, `${kv_pref}-key_wrap`, ); - await goto(`/models/trade-product/add`); + await route( + `/models/trade-product/add`, + ); }} > <p @@ -231,7 +233,9 @@ `*-el-focus`, `${kv_pref}-price_wrap`, ); - await goto(`/models/trade-product/add`); + await route( + `/models/trade-product/add`, + ); }} > <p @@ -286,7 +290,9 @@ `*-el-focus`, `${kv_pref}-qty_wrap`, ); - await goto(`/models/trade-product/add`); + await route( + `/models/trade-product/add`, + ); }} > <p @@ -402,7 +408,9 @@ `*-el-focus`, `${kv_pref}-location_gcs_id_wrap`, ); - await goto(`/models/trade-product/add`); + await route( + `/models/trade-product/add`, + ); }} > <p @@ -445,7 +453,9 @@ route: `/models/trade-product/add`, }, title: { - label: `Preview`, + label: { + value: `Preview`, + }, }, option: { label: { diff --git a/src/routes/(app)/nostr/+page.svelte b/src/routes/(app)/nostr/+page.svelte @@ -1,9 +1,9 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { LayoutTrellis, LayoutView, Nav, + route, Trellis, } from "@radroots/svelte-lib"; </script> @@ -29,7 +29,7 @@ ], }, callback: async () => { - await goto(`/nostr/keys`); + await route(`/nostr/keys`); }, end: { icon: { @@ -48,7 +48,7 @@ ], }, callback: async () => { - await goto(`/nostr/profile`); + await route(`/nostr/profile`); }, end: { icon: { @@ -67,7 +67,7 @@ ], }, callback: async () => { - await goto(`/nostr/notes`); + await route(`/nostr/notes`); }, end: { icon: { @@ -89,7 +89,9 @@ route: `/`, }, title: { - label: `Nostr`, + label: { + value: `Nostr`, + }, }, }} /> diff --git a/src/routes/(app)/nostr/keys/+page.svelte b/src/routes/(app)/nostr/keys/+page.svelte @@ -1,133 +1,274 @@ <script lang="ts"> import { lc } from "$lib/client"; import { _conf } from "$lib/conf"; + import { app_nostr_key } from "$lib/stores"; + import type { NostrProfile } from "@radroots/models"; import { + Glyph, LayoutTrellis, LayoutView, Nav, - Trellis, + SelectElement, + TrellisTitle, + app_notify, + nav_prev, + route, + t, + type ISelectOption, } from "@radroots/svelte-lib"; import { onMount } from "svelte"; - let nostr_public_key = ``; - let nostr_secret_key = ``; + type OptionsListKey = + | `view-key` + | `set-key-active` + | `edit-profile-name` + | `add-profile-name` + | `delete-key`; + + const options_list: ISelectOption<OptionsListKey>[] = [ + { + value: `view-key`, + label: `${$t(`icu.view_*`, { value: `${$t(`common.details`)}`.toLowerCase() })}`, + }, + { + value: `edit-profile-name`, + label: `${$t(`icu.edit_*`, { value: `${$t(`common.profile_name`)}`.toLowerCase() })}`, + }, + { + value: `add-profile-name`, + label: `${$t(`icu.add_*`, { value: `${$t(`common.profile_name`)}`.toLowerCase() })}`, + }, + { + value: `set-key-active`, + label: `${$t(`icu.set_as_*`, { value: `${$t(`common.active`)}`.toLowerCase() })}`, + }, + { + value: `delete-key`, + label: `${$t(`icu.delete_*`, { value: `${$t(`common.key`)}`.toLowerCase() })}`, + }, + ]; + + let ls_nostr_keys: { + public_key: string; + nostr_profile?: NostrProfile; + }[] = []; onMount(async () => { try { - const public_key = await lc.preferences.get( - _conf.kv.nostr_key_active, - ); - if (public_key) nostr_public_key = public_key; - const secret_key = await lc.keystore.get(`nostr:key:${public_key}`); - if (secret_key) nostr_secret_key = secret_key; + const ks_keys = ((await lc.keystore.keys()) || []) + .filter((i) => i.startsWith(_conf.kv.nostr_key(``))) + .map((i) => i.slice(_conf.kv.nostr_key(``).length)); + if (!ks_keys) + app_notify.set(`No keys are configured on this device`); + + for (const public_key of ks_keys) { + const nostr_profile = await lc.db.nostr_profile_get({ + public_key, + }); + + ls_nostr_keys = [ + ...ls_nostr_keys, + { + public_key, + nostr_profile: Array.isArray(nostr_profile) + ? nostr_profile[0] + : undefined, + }, + ]; + } } catch (e) { } finally { } }); - async function copyToClipboard(text: string) { - navigator.clipboard.writeText(text).then(async () => { - await lc.dialog.alert( - `Copied nostr key "${text.slice(0, 12)}..." to clipboard.`, - ); - }); - } + const handle_key_options_press = async (opts: { + option: string; + public_key: string; + }): Promise<void> => { + if (opts.option === `view-key`) { + $nav_prev.push({ + route: `/nostr/keys`, + label: `Keys`, + }); + await route(`/models/nostr-profile/view`, [ + [`nostr_pk`, opts.public_key], + ]); + } else if ( + opts.option === `add-profile-name` || + opts.option === `edit-profile-name` + ) { + $nav_prev.push({ + route: `/nostr/keys`, + label: `Keys`, + }); + await route(`/models/nostr-profile/edit/field`, [ + [`nostr_pk`, opts.public_key], + [`rkey`, `name`], + ]); + } else if (opts.option === `set-key-active`) { + /* + app_key.set(public_key); + await load_page(); + */ + } else if (opts.option === `delete-key`) { + /* + if ($app_key === public_key) + return await appc.dialog.alert({ + msg: `cannot delete active key`, + }); + + const confirm = await appc.dialog.confirm({ + msg: `${$t(`common.this_action_cannot_be_reverted`)}. ${$t(`nostr.key.delete.dialog_1`, { value: public_key })}. ${$t(`common.are_you_sure`)}`, + }); + if (confirm === true) { + console.log(`delete pubkey! `, public_key); + const result = await appc.sql.nostr_key_delete({ public_key }); + if (result === true) await load_page(); + } + */ + } + }; </script> <LayoutView basis={{ fade: true }}> <LayoutTrellis> - <Trellis - basis={{ - args: { - layer: 1, - title: { - value: `Public Key`, - }, - list: [ - { - touch: { - label: { - left: [ - { - value: nostr_public_key, - }, - ], - }, - - callback: async () => { - await copyToClipboard(nostr_public_key); - }, - }, - }, - { - touch: { - label: { - left: [ - { - value: lc.nostr.lib.npub( - nostr_public_key, - ), - }, - ], - }, - - callback: async () => { - await copyToClipboard( - lc.nostr.lib.npub(nostr_public_key), - ); - }, - }, - }, - ], - }, - }} - /> - <Trellis - basis={{ - args: { - layer: 1, - title: { - value: `Secret Key`, - }, - list: [ - { - touch: { - label: { - left: [ - { - value: nostr_secret_key, + <div class={`flex flex-col w-full gap-1 justify-start items-center`}> + <TrellisTitle + layer={0} + basis={{ + value: `${$t(`icu.nostr_*`, { value: `${$t(`common.keys`)}` })}`, + }} + /> + {#if ls_nostr_keys.length} + {#each ls_nostr_keys as ks_key (ks_key.public_key)} + <div + class={`relative flex flex-col pt-3 pb-4 px-[9px] bg-layer-1-surface rounded-xl overflow-hidden active:ring-4 active:ring-layer-2-surface/80 transition-all tap-rise-1 active:opacity-60`} + > + <button + class={`flex flex-col h-full w-full pt-[2px] pl-1 gap-1 items-start`} + on:click|preventDefault={async () => { + $nav_prev.push({ + route: `/nostr/keys`, + label: `Keys`, + }); + await route(`/models/nostr-profile/view`, [ + [`nostr_pk`, ks_key.public_key], + ]); + }} + > + <div + class={`flex flex-row w-full pl-1 gap-3 justify-start items-center`} + > + <p + class={`font-mono text-[14px] text-layer-1-glyph-shade text-ellipsis overflow-hidden`} + > + {ks_key.nostr_profile?.name + ? ks_key.nostr_profile?.name + : `(${`${$t(`icu.no_*`, { value: `${$t(`common.profile`)}` })}`})`} + </p> + {#if ks_key.public_key === $app_nostr_key} + <div class={`flex flex-row`}> + <div + class={`flex flex-row h-[16px] justify-center items-center px-[6px] bg-success/70 rounded-md -translate-y-[1px]`} + > + <p + class={`font-mono font-[900] text-[8px] text-white text-ellipsis overflow-hidden`} + > + {`${$t(`common.active`)}`} + </p> + </div> + </div> + {/if} + </div> + <div + class={`grid grid-cols-12 flex flex-row h-6 w-full pt-2 gap-2 items-center`} + > + <div + class={`col-span-2 flex flex-row h-full items-center `} + > + <div + class={`flex flex-row h-[1rem] px-[9px] justify-start items-center bg-zinc-800/90 rounded-[5px] translate-y-[1px]`} + > + <p + class={`font-mono font-[600] text-[0.9rem] text-layer-2-glyph lowercase line-clamp-1`} + > + {`${$t(`common.key`)}`} + </p> + </div> + </div> + <div + class={`col-span-10 flex flex-row h-full items-center overflow-x-hidden`} + > + <p + class={`font-mono text-[0.9rem] text-layer-1-glyph line-clamp-1`} + > + {`${`${lc.nostr.lib.npub(ks_key.public_key) || ""}`.slice( + 0, + 24, + )}...`} + </p> + </div> + </div> + </button> + <div + class={`z-10 absolute top-2 right-3 flex flex-row h-full justify-end pr-1`} + > + <SelectElement + basis={{ + args: { + layer: 0, + mask: true, + callback: async ({ value }) => { + await handle_key_options_press({ + option: value, + public_key: ks_key.public_key, + }); }, - ], - }, - - callback: async () => { - await copyToClipboard(nostr_secret_key); - }, - }, - }, - { - touch: { - label: { - left: [ - { - value: lc.nostr.lib.nsec( - nostr_secret_key, - ), - }, - ], - }, - - callback: async () => { - await copyToClipboard( - lc.nostr.lib.nsec(nostr_secret_key), - ); - }, - }, - }, - ], - }, - }} - /> + options: [ + { + entries: options_list.filter( + (i) => + !( + !ks_key + .nostr_profile + ?.name && + i.value === + `edit-profile-name` + ) && + !( + ks_key.nostr_profile + ?.name && + i.value === + `add-profile-name` + ) && + !( + ks_key.nostr_profile + ?.public_key === + $app_nostr_key && + i.value === + `set-key-active` + ), + ), + }, + ], + }, + }} + > + <svelte:fragment slot="element"> + <Glyph + basis={{ + key: `dots-three`, + dim: `sm`, + classes: `text-layer-1-glyph`, + }} + /> + </svelte:fragment> + </SelectElement> + </div> + </div> + {/each} + {/if} + </div> </LayoutTrellis> </LayoutView> <Nav @@ -137,7 +278,9 @@ route: `/nostr`, }, title: { - label: `Keys`, + label: { + value: `Keys`, + }, }, }} /> diff --git a/src/routes/(app)/nostr/notes/+page.svelte b/src/routes/(app)/nostr/notes/+page.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { app_nostr_key } from "$lib/stores"; import { NDKEvent, NDKKind, type NDKFilter } from "@nostr-dev-kit/ndk"; import type { @@ -12,6 +11,7 @@ locale, Nav, ndk, + route, time_fmt_epoch_s, Trellis, type ITrellisKindTouch, @@ -64,7 +64,7 @@ ], }, callback: async () => { - await goto(`/nostr/notes/post`); + await route(`/nostr/notes/post`); }, }, }); @@ -137,7 +137,7 @@ }, }, callback: async () => { - await goto(`/nostr/notes/post`); + await route(`/nostr/notes/post`); }, }, }, @@ -155,7 +155,9 @@ route: `/nostr`, }, title: { - label: `Notes`, + label: { + value: `Notes`, + }, }, option: $events_store.length ? { @@ -163,7 +165,7 @@ value: `Post`, }, callback: async () => { - await goto(`/nostr/notes/post`); + await route(`/nostr/notes/post`); }, } : undefined, diff --git a/src/routes/(app)/nostr/notes/post/+page.svelte b/src/routes/(app)/nostr/notes/post/+page.svelte @@ -1,5 +1,4 @@ <script lang="ts"> - import { goto } from "$app/navigation"; import { lc } from "$lib/client"; import ButtonSubmit from "$lib/components/button-submit.svelte"; import { NDKKind } from "@nostr-dev-kit/ndk"; @@ -10,6 +9,8 @@ ndk, ndk_event, ndk_user, + route, + t, } from "@radroots/svelte-lib"; let loading = false; @@ -34,7 +35,7 @@ }); if (ev) { await ev.publish(); - await goto(`/nostr/notes`); + await route(`/nostr/notes`); } } catch (e) { console.log(`(error) nostr_note_publish `, e); @@ -72,7 +73,9 @@ route: `/nostr/notes`, }, title: { - label: `Post Note`, + label: { + value: `${$t(`icu.post_*`, { value: `Note` })}`, + }, }, }} /> diff --git a/src/routes/(app)/nostr/profile/+page.svelte b/src/routes/(app)/nostr/profile/+page.svelte @@ -177,7 +177,9 @@ route: `/nostr`, }, title: { - label: `Profile`, + label: { + value: `${$t(`common.profile`)}`, + }, }, option: $events_store.length ? { diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte @@ -4,10 +4,11 @@ import { app_thc } from "$lib/stores"; import { restart } from "$lib/utils"; import { - app_tabs_visible, LayoutTrellis, LayoutView, Nav, + t, + tabs_visible, toggle_color_mode, Trellis, } from "@radroots/svelte-lib"; @@ -15,7 +16,7 @@ onMount(async () => { try { - app_tabs_visible.set(false); + tabs_visible.set(false); } catch (e) { } finally { } @@ -388,7 +389,9 @@ route: `/`, }, title: { - label: `Settings`, + label: { + value: `${$t(`common.settings`)}`, + }, }, }} /> diff --git a/src/routes/(app)/test/+page.svelte b/src/routes/(app)/test/+page.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { Nav,LayoutView } from "@radroots/svelte-lib"; + import { LayoutView, Nav } from "@radroots/svelte-lib"; </script> <LayoutView basis={{ classes: `px-4 gap-8` }}>test</LayoutView> @@ -10,7 +10,9 @@ route: `/`, }, title: { - label: `Test`, + label: { + value: `Test`, + }, }, }} /> diff --git a/src/routes/(conf)/+layout.ts b/src/routes/(conf)/+layout.ts @@ -1,23 +0,0 @@ -import { goto } from '$app/navigation'; -import { lc } from '$lib/client'; -import { _conf } from '$lib/conf'; -import type { LayoutLoad, LayoutLoadEvent } from '../$types'; - -export const load: LayoutLoad = async ({ url }: LayoutLoadEvent) => { - try { - const key_active = await lc.preferences.get(_conf.kv.nostr_key_active); - if (key_active) { - const ks_keys = await lc.keystore.keys(); - const active_nostr_key = ks_keys?.find( - (i) => i === `nostr:key:${key_active}`, - ); - if (active_nostr_key) { - await goto(`/`); - return - } - } - } catch (e) { } finally { - await lc.window.splash_hide(); - return {}; - }; -}; diff --git a/src/routes/(conf)/init/+layout.ts b/src/routes/(conf)/init/+layout.ts @@ -0,0 +1,25 @@ +import { lc } from '$lib/client'; +import { _conf } from '$lib/conf'; +import { route } from '@radroots/svelte-lib'; +import type { LayoutLoad, LayoutLoadEvent } from './$types'; + +export const load: LayoutLoad = async ({ url }: LayoutLoadEvent) => { + try { + console.log(`layout (conf) `, url.pathname); + const key_active = await lc.preferences.get(_conf.kv.nostr_key_active); + console.log(`key_active `, key_active) + if (key_active) { + const ks_keys = await lc.keystore.keys(); + const active_nostr_key = ks_keys?.find( + (i) => i === `nostr:key:${key_active}`, + ); + if (active_nostr_key) { + await route(`/`); + return + } + } + } catch (e) { } finally { + await lc.window.splash_hide(); + return {}; + }; +}; diff --git a/src/routes/(conf)/init/+page.svelte b/src/routes/(conf)/init/+page.svelte @@ -102,7 +102,7 @@ //@todo alert(key_profile_added.join(` `)); } else { - await sleep(_conf.const.load_delay); + await sleep(_conf.delay.load); await restart( true, `Welcome! Your device was configured. To view or change your configuration go to Settings > Configuration.`, @@ -145,11 +145,19 @@ > {`to`} </p> - <p - class={`font-mono font-[400] text-layer-0-glyph text-3xl`} + <button + class={`flex flex-row justify-center items-center`} + on:click={async () => { + //@todo remove + await configure_device(); + }} > - {`radroots`} - </p> + <p + class={`font-mono font-[400] text-layer-0-glyph text-3xl`} + > + {`radroots`} + </p> + </button> </div> <div class={`flex flex-col justify-start items-center`}> <p diff --git a/src/routes/(map)/map/+page.svelte b/src/routes/(map)/map/+page.svelte @@ -17,7 +17,7 @@ if (loc && typeof loc !== `string`) { map_coords = [loc.lng, loc.lat]; } - await sleep(_conf.const.load_delay); + await sleep(_conf.delay.load); } catch (e) { console.log(`e `, e); } finally { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte @@ -1,6 +1,5 @@ <script lang="ts"> import { browser } from "$app/environment"; - import { goto } from "$app/navigation"; import { PUBLIC_DATABASE_NAME, PUBLIC_NOSTR_RELAY_DEFAULTS, @@ -16,13 +15,14 @@ } from "$lib/stores"; import { app_config, + app_notify, app_render, AppConfig, CssStatic, - kv, ndk, ndk_setup_privkey, ndk_user, + route, sleep, theme_set, } from "@radroots/svelte-lib"; @@ -84,7 +84,7 @@ } await lc.preferences.remove(_conf.kv.nostr_key_active); - await goto(`/init`); + await route(`/init`); } catch (e) { console.log(`(app_config) error `, e); } finally { @@ -96,16 +96,17 @@ try { console.log(`app_render `, app_render); if (!app_render) return; + /* let init_route = `/`; //init_route = `/models/trade-product/add`; - const app_init_route = await kv.get(`*-init-route`); + const app_init_route = await kv.get(_conf.cmd.layout_route); if (app_init_route) { init_route = app_init_route; - await kv.delete(`*-init-route`); + await kv.delete(_conf.cmd.layout_route); } console.log(`init_route `, init_route); - await goto(init_route); - await sleep(_conf.const.load_delay); + */ + await sleep(_conf.delay.load); } catch (e) { console.log(`(app_render) error `, e); } finally { @@ -139,6 +140,14 @@ console.log(`(app_nostr_key) error `, e); } }); + + app_notify.subscribe(async (_app_notify) => { + if (!_app_notify) return; + route(`/`); + await sleep(_conf.delay.notify); + lc.dialog.alert(_app_notify); + app_notify.set(``); + }); </script> <svelte:head> diff --git a/tailwind.config.ts b/tailwind.config.ts @@ -19,7 +19,8 @@ const heights = { const widths = { line: `320px`, - trellis_value: `180px` + trellis_value: `180px`, + trellis_display: `290px` }; const dimensions = { @@ -50,6 +51,7 @@ const config: Config = { fontSize: { line: ["1.05rem", { lineHeight: "1.33rem", fontWeight: 300 }], trellisTitle: ["0.8rem", { lineHeight: "1rem", fontWeight: 200 }], + trellisTitleNote: ["0.76rem", { lineHeight: "1rem", fontWeight: 200 }], trellisLine: ["1.05rem", { lineHeight: "1.33rem", fontWeight: 300 }], trellisLabel: ["0.8rem", { lineHeight: "1rem", fontWeight: 200 }], navPrevious: ["1.09rem", { lineHeight: "1.33rem", fontWeight: 400 }],