web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit f1abc36a0527af45952524b5a20702f41c4a195f
parent ec79e357434cbfc3002a001122882494e78203af
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Sun, 27 Apr 2025 02:26:44 +0000

apps-lib: add nostr relay polling utils, update components, utils, views

Diffstat:
Mapps-lib/src/lib/components/form/form-line-ledger-label-select-label.svelte | 6+++---
Mapps-lib/src/lib/features/farm/farms-products-review-card.svelte | 6+++---
Mapps-lib/src/lib/index.ts | 4+++-
Dapps-lib/src/lib/util/nostr/lib.ts | 51---------------------------------------------------
Aapps-lib/src/lib/util/nostr/nostr-poll-relays.ts | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/util/nostr/nostr-sync.ts | 26++++++++++++++++++++++++++
Mapps-lib/src/lib/view/profile.svelte | 14+++++++-------
Mapps-lib/src/lib/view/settings.svelte | 4++--
8 files changed, 116 insertions(+), 67 deletions(-)

diff --git a/apps-lib/src/lib/components/form/form-line-ledger-label-select-label.svelte b/apps-lib/src/lib/components/form/form-line-ledger-label-select-label.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { ascii } from "@radroots/util"; + import { symbols } from "@radroots/util"; let { basis, @@ -22,12 +22,12 @@ <p class={`absolute font-sansd text-trellis_ti text-layer-0-glyph-label uppercase scale-y-[70%] scale-x-[80%] -translate-y-[1px]`} > - {`${ascii.up}`} + {`${symbols.up}`} </p> <p class={`absolute font-sansd text-trellis_ti text-layer-0-glyph-label uppercase scale-y-[70%] scale-x-[80%] translate-y-[2px]`} > - {`${ascii.down}`} + {`${symbols.down}`} </p> </div> <p class={`font-sansd text-trellis_ti text-layer-0-glyph-label uppercase`}> diff --git a/apps-lib/src/lib/features/farm/farms-products-review-card.svelte b/apps-lib/src/lib/features/farm/farms-products-review-card.svelte @@ -7,7 +7,7 @@ type IViewFarmsProductsAddSubmission, } from "$root"; import { - ascii, + symbols, type I18nTranslateFunction, type I18nTranslateLocale, } from "@radroots/util"; @@ -90,7 +90,7 @@ <p class={`font-sans font-[600] text-xl text-layer-1-glyph`} > - {ascii.bullet} + {symbols.bullet} </p> <p class={`font-sans font-[600] text-lg text-layer-1-glyph`} @@ -114,7 +114,7 @@ {`${basis.data.geolocation_address.primary}, ${basis.data.geolocation_address.admin}`} </p> <p class={`font-sans font-[600] text-th-black`}> - {ascii.bullet} + {symbols.bullet} </p> <p class={`font-sans font-[600] text-th-black`}> {`${basis.data.geolocation_address.country}`} diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -108,7 +108,8 @@ export * from "./util/casl.js" export * from "./util/component.js" export * from "./util/idb.js" export * from "./util/lib.js" -export * from "./util/nostr/lib.js" +export * from "./util/nostr/nostr-poll-relays.js" +export * from "./util/nostr/nostr-sync.js" export * from "./util/service/nostr-event-classified.js" export * from "./util/service/nostr-sync.js" export * from "./util/view.js" @@ -117,3 +118,4 @@ export { default as Notifications } from "./view/notifications.svelte" export { default as ProfileEdit } from "./view/profile-edit.svelte" export { default as Profile } from "./view/profile.svelte" export { default as Settings } from "./view/settings.svelte" + diff --git a/apps-lib/src/lib/util/nostr/lib.ts b/apps-lib/src/lib/util/nostr/lib.ts @@ -1,51 +0,0 @@ -import { get_store, nostr_poll_relays_attempts, nostr_poll_relays_attempts_max, nostr_poll_relays_stop, nostr_sync_attempts, nostr_sync_attempts_max, nostr_sync_stop } from "$root"; - -export const nostr_sync_retry_handler = async (callback: () => Promise<any>) => { - let current_count = 0; - const attempts_max = get_store(nostr_sync_attempts_max); - - nostr_sync_attempts.set(0); - nostr_sync_stop.set(false); - - const exe = async () => { - if (get_store(nostr_sync_stop)) return; - console.log(`nostr_sync_retry_handler ${current_count}`) - try { - await callback(); - } catch (e) { - current_count += 1; - nostr_sync_attempts.set(current_count); - if (current_count < attempts_max) { - await new Promise((res) => setTimeout(res, 500)); - await exe(); - } else nostr_sync_stop.set(true); - } - }; - - await exe(); -}; - -export const nostr_poll_relays_retry_handler = async (callback: () => Promise<any>) => { - let current_count = 0; - const attempts_max = get_store(nostr_poll_relays_attempts_max); - - nostr_poll_relays_attempts.set(0); - nostr_poll_relays_stop.set(false); - - const exe = async () => { - if (get_store(nostr_poll_relays_stop)) return; - console.log(`nostr_poll_relays_retry_handler ${current_count}`) - try { - await callback(); - } catch (e) { - current_count += 1; - nostr_poll_relays_attempts.set(current_count); - if (current_count < attempts_max) { - await new Promise((res) => setTimeout(res, 2000)); - await exe(); - } else nostr_poll_relays_stop.set(true); - } - }; - - await exe(); -}; diff --git a/apps-lib/src/lib/util/nostr/nostr-poll-relays.ts b/apps-lib/src/lib/util/nostr/nostr-poll-relays.ts @@ -0,0 +1,72 @@ +import { get_store, handle_err, ndk_user, nostr_poll_relays_attempts, nostr_poll_relays_attempts_max, nostr_poll_relays_stop, nostr_relays_connected } from "$root"; +import { lib_nostr_relay_build_information_document, type NostrRelayInformationDocumentFields } from "@radroots/nostr-util"; +import { type CallbackPromiseFull, type CallbackPromiseGeneric, type ErrorMessage, type I18nTranslateFunction, type IHttpResponse } from "@radroots/util"; + +export const nostr_poll_relays_retry_handler = async (callback: () => Promise<any>) => { + let current_count = 0; + const attempts_max = get_store(nostr_poll_relays_attempts_max); + + nostr_poll_relays_attempts.set(0); + nostr_poll_relays_stop.set(false); + + const exe = async () => { + if (get_store(nostr_poll_relays_stop)) return; + console.log(`[nostr poll relays] attempt ${current_count}`) + try { + await callback(); + } catch (e) { + current_count += 1; + nostr_poll_relays_attempts.set(current_count); + if (current_count < attempts_max) { + await new Promise((res) => setTimeout(res, 2000)); + await exe(); + } else nostr_poll_relays_stop.set(true); + } + }; + + await exe(); +}; + +export const nostr_poll_relays_handler = async (opts: { + ls: I18nTranslateFunction; + callback_alert: CallbackPromiseGeneric<string>; + callback_relay_urls: CallbackPromiseFull<string, { id: string; url: string; }[]>; + callback_fetch_document: CallbackPromiseFull<string, IHttpResponse | ErrorMessage<string>>; + callback_set_relay_document: CallbackPromiseGeneric<{ url: string; doc: NostrRelayInformationDocumentFields; }>; +}): Promise<void> => { + try { + const { ls, callback_alert, callback_relay_urls, callback_fetch_document, callback_set_relay_document } = opts; + const $ls = get_store(ls); + const $ndk_user = get_store(ndk_user); + const public_key = $ndk_user?.pubkey; + if (!public_key) return void await callback_alert(`${$ls(`error.client.nostr_poll_relays_failure`)}`); + const $nostr_relays_connected = get_store(nostr_relays_connected); + + const relay_urls = await callback_relay_urls(public_key); + const unconnected_relays = relay_urls.filter( + (i) => !$nostr_relays_connected.includes(i.id), + ); + if (unconnected_relays.length === 0) return void nostr_poll_relays_stop.set(true); + + for (const relay of unconnected_relays) { + const res = await callback_fetch_document(relay.url); + if (`err` in res) continue; + else if (res.status === 200 && res.data) { + const doc = lib_nostr_relay_build_information_document(res.data); + if (!doc) continue; + await callback_set_relay_document({ url: relay.url, doc }); + nostr_relays_connected.set( + Array.from( + new Set([ + ...$nostr_relays_connected, + relay.id, + ]), + ), + ); + } + + } + } catch (e) { + await handle_err(e, `nostr_poll_relays_handler`); + } +}; diff --git a/apps-lib/src/lib/util/nostr/nostr-sync.ts b/apps-lib/src/lib/util/nostr/nostr-sync.ts @@ -0,0 +1,26 @@ +import { get_store, nostr_sync_attempts, nostr_sync_attempts_max, nostr_sync_stop } from "$root"; + +export const nostr_sync_retry_handler = async (callback: () => Promise<any>) => { + let current_count = 0; + const attempts_max = get_store(nostr_sync_attempts_max); + + nostr_sync_attempts.set(0); + nostr_sync_stop.set(false); + + const exe = async () => { + if (get_store(nostr_sync_stop)) return; + console.log(`[nostr sync] attempt ${current_count}`) + try { + await callback(); + } catch (e) { + current_count += 1; + nostr_sync_attempts.set(current_count); + if (current_count < attempts_max) { + await new Promise((res) => setTimeout(res, 500)); + await exe(); + } else nostr_sync_stop.set(true); + } + }; + + await exe(); +}; diff --git a/apps-lib/src/lib/view/profile.svelte b/apps-lib/src/lib/view/profile.svelte @@ -1,27 +1,27 @@ <script lang="ts"> import { + ButtonRoundNav, + FloatPage, Glyph, handle_err, idb_init_page, + ImageBlob, ImagePath, ImageUploadAddPhoto, NavigationTabs, SelectMenu, - ImageBlob, - FloatPage, - ButtonRoundNav, type IViewOnDestroy, type IViewProfileData, - type ViewProfileEditFieldKey, type LcPhotoAddCallback, + type ViewProfileEditFieldKey, } from "$root"; import { - ascii, + symbols, type CallbackPromise, type CallbackPromiseFull, type CallbackPromiseGeneric, - type IViewBasis, type I18nTranslateFunction, + type IViewBasis, } from "@radroots/util"; import { onDestroy, onMount } from "svelte"; @@ -209,7 +209,7 @@ <p class={`font-sans font-[400] ${classes_photo_overlay_glyph}`} > - {ascii.bullet} + {symbols.bullet} </p> <button class={`flex flex-row justify-center items-center`} diff --git a/apps-lib/src/lib/view/settings.svelte b/apps-lib/src/lib/view/settings.svelte @@ -11,7 +11,7 @@ type ITrellisKind, } from "$root"; import { - ascii, + symbols, type CallbackPromiseGeneric, type I18nTranslateFunction, type IViewBasis, @@ -78,7 +78,7 @@ { entries: [ { - value: ascii.bullet, + value: symbols.bullet, label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.color_mode`)}`.toLowerCase() })}`, disabled: true, },