commit fccd5dff5dbef0166a9ac5b87582575b9f15119a
parent c86c3f39da6b7e19a8a884ddd80181f5b0162b23
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Sat, 31 Aug 2024 13:50:31 +0000
Use svelte version 4, add `/nostr/keys`, add css, update nostr routes, update dependencies
Diffstat:
30 files changed, 1036 insertions(+), 271 deletions(-)
diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle
@@ -11,6 +11,7 @@ apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-browser')
implementation project(':capacitor-dialog')
+ implementation project(':capacitor-device')
implementation project(':capacitor-geolocation')
implementation project(':capacitor-haptics')
implementation project(':capacitor-preferences')
diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle
@@ -8,6 +8,9 @@ project(':capacitor-browser').projectDir = new File('../../../node_modules/.pnpm
include ':capacitor-dialog'
project(':capacitor-dialog').projectDir = new File('../../../node_modules/.pnpm/@capacitor+dialog@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/dialog/android')
+include ':capacitor-device'
+project(':capacitor-device').projectDir = new File('../../../node_modules/.pnpm/@capacitor+device@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/device/android')
+
include ':capacitor-geolocation'
project(':capacitor-geolocation').projectDir = new File('../../../node_modules/.pnpm/@capacitor+geolocation@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/geolocation/android')
diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj
@@ -15,6 +15,7 @@
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
+ C11106072C8353B800B825E4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = C11106062C8353B800B825E4 /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -29,6 +30,7 @@
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
+ C11106062C8353B800B825E4 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -55,6 +57,7 @@
504EC2FB1FED79650016851F = {
isa = PBXGroup;
children = (
+ C11106062C8353B800B825E4 /* PrivacyInfo.xcprivacy */,
504EC3061FED79650016851F /* App */,
504EC3051FED79650016851F /* Products */,
7F8756D8B27F46E3366F6CEA /* Pods */,
@@ -158,6 +161,7 @@
buildActionMask = 2147483647;
files = (
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
+ C11106072C8353B800B825E4 /* PrivacyInfo.xcprivacy in Resources */,
50B271D11FEDC1A000F3C39B /* public in Resources */,
504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
diff --git a/ios/App/Podfile b/ios/App/Podfile
@@ -13,6 +13,7 @@ def capacitor_pods
pod 'CapacitorCordova', :path => '../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios'
pod 'CapacitorBrowser', :path => '../../../../node_modules/.pnpm/@capacitor+browser@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/browser'
pod 'CapacitorDialog', :path => '../../../../node_modules/.pnpm/@capacitor+dialog@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/dialog'
+ pod 'CapacitorDevice', :path => '../../../../node_modules/.pnpm/@capacitor+device@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/device'
pod 'CapacitorGeolocation', :path => '../../../../node_modules/.pnpm/@capacitor+geolocation@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/geolocation'
pod 'CapacitorHaptics', :path => '../../../../node_modules/.pnpm/@capacitor+haptics@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/haptics'
pod 'CapacitorPreferences', :path => '../../../../node_modules/.pnpm/@capacitor+preferences@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/preferences'
diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock
@@ -4,6 +4,8 @@ PODS:
- CapacitorBrowser (6.0.2):
- Capacitor
- CapacitorCordova (6.1.2)
+ - CapacitorDevice (6.0.1):
+ - Capacitor
- CapacitorDialog (6.0.1):
- Capacitor
- CapacitorGeolocation (6.0.1):
@@ -41,6 +43,7 @@ DEPENDENCIES:
- "Capacitor (from `../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios`)"
- "CapacitorBrowser (from `../../../../node_modules/.pnpm/@capacitor+browser@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/browser`)"
- "CapacitorCordova (from `../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios`)"
+ - "CapacitorDevice (from `../../../../node_modules/.pnpm/@capacitor+device@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/device`)"
- "CapacitorDialog (from `../../../../node_modules/.pnpm/@capacitor+dialog@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/dialog`)"
- "CapacitorGeolocation (from `../../../../node_modules/.pnpm/@capacitor+geolocation@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/geolocation`)"
- "CapacitorHaptics (from `../../../../node_modules/.pnpm/@capacitor+haptics@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/haptics`)"
@@ -66,6 +69,8 @@ EXTERNAL SOURCES:
:path: "../../../../node_modules/.pnpm/@capacitor+browser@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/browser"
CapacitorCordova:
:path: "../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios"
+ CapacitorDevice:
+ :path: "../../../../node_modules/.pnpm/@capacitor+device@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/device"
CapacitorDialog:
:path: "../../../../node_modules/.pnpm/@capacitor+dialog@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/dialog"
CapacitorGeolocation:
@@ -93,6 +98,7 @@ SPEC CHECKSUMS:
Capacitor: 679f9673fdf30597493a6362a5d5bf233d46abc2
CapacitorBrowser: 83ec661a9ccd56c28a6851e4dd1ac33b181227ec
CapacitorCordova: f48c89f96c319101cd2f0ce8a2b7449b5fb8b3dd
+ CapacitorDevice: 7097a1deb4224b77fd13a6e60a355d0062a5d772
CapacitorDialog: ad752191fdb22a8d0ac199b0754b8a021d86dbf9
CapacitorGeolocation: 39dca51d755f08ed1d43e51be55291a402cdc64f
CapacitorHaptics: fe689ade56ef20ec9b041a753c6da70c5d8ec9a9
@@ -108,6 +114,6 @@ SPEC CHECKSUMS:
SQLCipher: 77fbe633cd84db04b07876dd50766b4924b57d61
ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c
-PODFILE CHECKSUM: c6c1e7d552d32beb42585f968d80f8b142e3fef4
+PODFILE CHECKSUM: 37b4ea0a5a13844ab526c251f4635f95ea68eb09
COCOAPODS: 1.15.2
diff --git a/ios/App/PrivacyInfo.xcprivacy b/ios/App/PrivacyInfo.xcprivacy
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>NSPrivacyAccessedAPITypes</key>
+ <array>
+ <dict>
+ <key>NSPrivacyAccessedAPIType</key>
+ <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
+ <key>NSPrivacyAccessedAPITypeReasons</key>
+ <array>
+ <string>85F4.1</string>
+ </array>
+ </dict>
+ </array>
+ </dict>
+</plist>
+\ No newline at end of file
diff --git a/package.json b/package.json
@@ -17,7 +17,7 @@
"sql:wasm:rm": "rm -rf static/assets/sql-wasm.wasm"
},
"devDependencies": {
- "@capacitor/cli": "^6.0.0",
+ "@capacitor/cli": "^6.1.2",
"@sveltejs/adapter-static": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
@@ -25,8 +25,8 @@
"autoprefixer": "^10.4.19",
"daisyui": "^4.10.0",
"postcss": "^8.4.38",
- "svelte": "^5.0.0-next.1",
- "svelte-check": "^3.6.0",
+ "svelte": "^4.2.19",
+ "svelte-check": "^3.8.6",
"tailwindcss": "^3.4.3",
"tslib": "^2.4.1",
"typescript": "^5.3.3",
@@ -34,19 +34,21 @@
},
"type": "module",
"dependencies": {
- "@capacitor/android": "^6.0.0",
+ "@capacitor/android": "^6.1.2",
"@capacitor/browser": "^6.0.0",
"@capacitor/core": "^6.1.2",
"@capacitor/dialog": "^6.0.0",
+ "@capacitor/device": "^6.0.0",
"@capacitor/geolocation": "^6.0.0",
"@capacitor/haptics": "^6.0.0",
- "@capacitor/ios": "^6.0.0",
+ "@capacitor/ios": "^6.1.2",
"@capacitor/preferences": "^6.0.0",
"@capacitor/share": "^6.0.0",
"@capacitor/splash-screen": "^6.0.0",
"@capacitor/status-bar": "^6.0.0",
"@ionic/pwa-elements": "^3.3.0",
"@nostr-dev-kit/ndk": "^2.7.1",
+ "@nostr-dev-kit/ndk-svelte": "^2.2.18",
"@nostr-dev-kit/ndk-cache-dexie": "^2.3.1",
"@radroots/capacitor-native-settings": "workspace:*",
"@radroots/capacitor-secure-storage": "workspace:*",
diff --git a/src/app.css b/src/app.css
@@ -1,10 +1,27 @@
+@import "./lib/css/spinner.css";
+@import "./lib/css/spinner-6.css";
+@import "./lib/css/spinner-12.css";
+
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
+ .input-simple {
+ @apply input flex flex-row w-full h-fit p-0 border-0 focus:border-0 outline-0 focus:outline-0 placeholder:font-[300] bg-layer-1-surface font-mono text-sm text-layer-2-glyph;
+ }
+
+ .button-submit {
+ @apply h-[32px] min-w-[82px] w-fit rounded-xl active:bg-layer-1-surface_a;
+ }
+
.button-simple {
- @apply flex flex-row h-line w-line justify-center items-center bg-layer-1-surface font-mono text-sm lowercase text-layer-2-glyph;
+ @apply h-line w-line;
+ }
+
+ .button-simple,
+ .button-submit {
+ @apply flex flex-row justify-center items-center bg-layer-1-surface font-mono text-sm lowercase text-layer-2-glyph transition-all select-none cursor-none;
}
.flex-fill {
diff --git a/src/lib/components/button-submit.svelte b/src/lib/components/button-submit.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+ import type { CallbackPromise } from "@radroots/svelte-lib";
+ import { loading as Loading, t } from "@radroots/svelte-lib";
+
+ export let basis: {
+ callback: CallbackPromise;
+ loading?: boolean;
+ };
+ $: basis = basis;
+</script>
+
+<button
+ class={`button-submit`}
+ on:click={async () => {
+ await basis.callback();
+ }}
+>
+ {#if basis.loading}
+ <Loading basis={{ dim: `xs` }} />
+ {:else}
+ {`${$t(`common.submit`, { default: `submit` })}`}
+ {/if}
+</button>
diff --git a/src/lib/components/layout-trellis.svelte b/src/lib/components/layout-trellis.svelte
@@ -1,10 +1,3 @@
-<script lang="ts">
- import type { PropChildren } from "@radroots/svelte-lib";
-
- let { children }: PropChildren = $props();
-</script>
-
-
<div class={`flex flex-col w-full pt-4 px-4 pb-12 gap-4`}>
- {@render children()}
+ <slot />
</div>
diff --git a/src/lib/components/layout-view.svelte b/src/lib/components/layout-view.svelte
@@ -1,21 +1,46 @@
<script lang="ts">
- import { app_layout, app_nav_blur, app_nav_visible, app_tabs_blur, app_tabs_visible } from "$lib/stores";
- import { type AppLayoutKey, type PropChildren } from "@radroots/svelte-lib";
+ import {
+ app_layout,
+ app_nav_blur,
+ app_nav_visible,
+ app_tabs_blur,
+ app_tabs_visible,
+ } from "$lib/stores";
+ import { type AppLayoutKey } from "@radroots/svelte-lib";
+ import { onDestroy, onMount } from "svelte";
const styles: Record<AppLayoutKey, string> = {
- base: 'pt-2',
- lg:'pt-16'
+ base: "pt-2",
+ lg: "pt-16",
};
- let { children, basis }: PropChildren & { basis?: { fade?: boolean; }} = $props();
+ export let basis: { fade?: boolean } | undefined = undefined;
+ $: basis = basis;
let el: HTMLElement | null;
- let classes_nav = $derived($app_nav_visible ? `pt-h_nav_${$app_layout}` : `${styles[$app_layout]}`)
- let classes_tabs = $derived($app_tabs_visible ? `pb-h_tabs_${$app_layout}` : ``)
- let classes_fade = $derived(basis?.fade ? `fade-in` : ``)
+ onMount(async () => {
+ try {
+ el?.addEventListener("scroll", scrollChange);
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ onDestroy(async () => {
+ try {
+ el?.removeEventListener("scroll", scrollChange);
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ $: classes_nav = $app_nav_visible
+ ? `pt-h_nav_${$app_layout}`
+ : `${styles[$app_layout]}`;
+ $: classes_tabs = $app_tabs_visible ? `pb-h_tabs_${$app_layout}` : ``;
+ $: classes_fade = basis?.fade ? `fade-in` : ``;
-
const scrollChange = (): void => {
if (Math.max(el?.scrollTop || 0, 0) > 10) app_nav_blur.set(true);
else app_nav_blur.set(false);
@@ -23,17 +48,11 @@
if (Math.max(el?.scrollTop || 0, 0) > 10) app_tabs_blur.set(true);
else app_tabs_blur.set(false);
};
-
- $effect(() => {
- el?.addEventListener("scroll", scrollChange);
-
- return () => el?.removeEventListener("scroll", scrollChange);
- });
</script>
<div
bind:this={el}
class={`absolute top-0 left-0 flex flex-col h-[100vh] w-full overflow-y-scroll scroll-hide ${classes_nav} ${classes_tabs} ${classes_fade}`}
>
- {@render children()}
+ <slot />
</div>
diff --git a/src/lib/components/layout-window.svelte b/src/lib/components/layout-window.svelte
@@ -1,13 +1,7 @@
-<script lang="ts">
- import type { PropChildren } from "@radroots/svelte-lib";
-
- let { children }: PropChildren = $props();
-</script>
-
<div
class={`relative flex flex-col h-[100vh] w-full overflow-x-hidden overflow-y-hidden bg-layer-0-surface`}
>
<div class={`flex flex-col h-full w-full`}>
- {@render children()}
+ <slot />
</div>
</div>
diff --git a/src/lib/components/nav.svelte b/src/lib/components/nav.svelte
@@ -4,21 +4,28 @@
import type { INavBasis } from "$lib/types";
import { restart } from "$lib/utils";
import { fill as Fill, glyph as Glyph } from "@radroots/svelte-lib";
+ import { onDestroy, onMount } from "svelte";
- let {
- basis,
- }: {
- basis: INavBasis;
- } = $props();
+ export let basis: INavBasis;
+ $: basis = basis;
let el: HTMLElement | null;
let el_inner: HTMLElement | null;
- $effect(() => {
- app_nav_visible.set(true);
- return () => {
+ onMount(async () => {
+ try {
+ app_nav_visible.set(true);
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ onDestroy(async () => {
+ try {
app_nav_visible.set(false);
- };
+ } catch (e) {
+ } finally {
+ }
});
</script>
@@ -35,7 +42,7 @@
>
<button
class={`col-span-4 flex flex-row h-full pl-2 justify-start items-center`}
- onclick={async () => {
+ on:click={async () => {
await goto(basis.prev.route);
}}
>
@@ -63,7 +70,7 @@
{#if basis.title}
<button
class={`flex flex-row justify-center items-center`}
- onclick={async () => {
+ on:click={async () => {
await restart();
}}
>
@@ -83,7 +90,7 @@
{#if basis.option}
<button
class={`col-span-4 flex flex-row h-full pr-6 justify-end items-center`}
- onclick={async () => {
+ on:click={async () => {
await basis.option?.callback();
}}
>
diff --git a/src/lib/components/tabs.svelte b/src/lib/components/tabs.svelte
@@ -2,13 +2,10 @@
import { app_layout, app_tab_active, app_tabs_blur } from "$lib/stores";
import { glyph as Glyph, type ITabsBasis } from "@radroots/svelte-lib";
- let {
- basis,
- }: {
- basis: ITabsBasis;
- } = $props();
+ export let basis: ITabsBasis;
+ $: basis = basis;
- let classes_blur = $derived($app_tabs_blur ? `bg-layer-1-surface/30` : ``);
+ $: classes_blur = $app_tabs_blur ? `bg-layer-1-surface/30` : ``;
let el: HTMLElement | null;
let el_inner: HTMLElement | null;
@@ -28,7 +25,7 @@
{#each basis.list as tab, tab_i}
<button
class={`col-span-3 flex flex-col h-full justify-start items-center transition-all`}
- onclick={async () => {
+ on:click={async () => {
app_tab_active.set(tab_i);
await tab.callback(tab_i);
}}
diff --git a/src/lib/css/spinner-12.css b/src/lib/css/spinner-12.css
@@ -0,0 +1,89 @@
+@layer base {
+ .spinner12 {
+ position: relative;
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ }
+
+ .spinner12.center {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ }
+
+ .spinner12 .spinner12-blade {
+ position: absolute;
+ left: 0.4629em;
+ bottom: 0;
+ width: 0.074em;
+ height: 0.2777em;
+ border-radius: 0.0555em;
+ background-color: transparent;
+ transform-origin: center -0.2222em;
+ animation: spinner-fade-base 1s infinite linear;
+ }
+
+ .spinner12 .spinner12-blade:nth-child(1) {
+ animation-delay: 0s;
+ transform: rotate(0deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(2) {
+ animation-delay: 0.083s;
+ transform: rotate(30deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(3) {
+ animation-delay: 0.166s;
+ transform: rotate(60deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(4) {
+ animation-delay: 0.249s;
+ transform: rotate(90deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(5) {
+ animation-delay: 0.332s;
+ transform: rotate(120deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(6) {
+ animation-delay: 0.415s;
+ transform: rotate(150deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(7) {
+ animation-delay: 0.498s;
+ transform: rotate(180deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(8) {
+ animation-delay: 0.581s;
+ transform: rotate(210deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(9) {
+ animation-delay: 0.664s;
+ transform: rotate(240deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(10) {
+ animation-delay: 0.747s;
+ transform: rotate(270deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(11) {
+ animation-delay: 0.83s;
+ transform: rotate(300deg);
+ }
+
+ .spinner12 .spinner12-blade:nth-child(12) {
+ animation-delay: 0.913s;
+ transform: rotate(330deg);
+ }
+}
+\ No newline at end of file
diff --git a/src/lib/css/spinner-6.css b/src/lib/css/spinner-6.css
@@ -0,0 +1,59 @@
+@layer base {
+ .spinner6 {
+ position: relative;
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ }
+
+ .spinner6.center {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ }
+
+ .spinner6 .spinner6-blade {
+ position: absolute;
+ left: 0.4629em;
+ bottom: 0;
+ width: 0.074em;
+ height: 0.2777em;
+ border-radius: 0.0555em;
+ background-color: transparent;
+ transform-origin: center -0.2222em;
+ animation: spinner-fade-base 1s infinite linear;
+ }
+
+ .spinner6 .spinner6-blade:nth-child(1) {
+ animation-delay: 0s;
+ transform: rotate(0deg);
+ }
+
+ .spinner6 .spinner6-blade:nth-child(2) {
+ animation-delay: 0.1s;
+ transform: rotate(60deg);
+ }
+
+ .spinner6 .spinner6-blade:nth-child(3) {
+ animation-delay: 0.2s;
+ transform: rotate(120deg);
+ }
+
+ .spinner6 .spinner6-blade:nth-child(4) {
+ animation-delay: 0.3s;
+ transform: rotate(180deg);
+ }
+
+ .spinner6 .spinner6-blade:nth-child(5) {
+ animation-delay: 0.4s;
+ transform: rotate(240deg);
+ }
+
+ .spinner6 .spinner6-blade:nth-child(6) {
+ animation-delay: 0.5s;
+ transform: rotate(300deg);
+ }
+}
+\ No newline at end of file
diff --git a/src/lib/css/spinner.css b/src/lib/css/spinner.css
@@ -0,0 +1,19 @@
+@layer base {
+ @keyframes spinner-fade-white {
+ 0% {
+ background-color: white;
+ }
+ 100% {
+ background-color: transparent;
+ }
+ }
+
+ @keyframes spinner-fade-base {
+ 0% {
+ background-color: hsl(var(--layer-2-glyph));
+ }
+ 100% {
+ background-color: transparent;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/src/lib/stores.ts b/src/lib/stores.ts
@@ -23,3 +23,5 @@ export const app_sqlite = writable<boolean>(false);
export const app_nav_visible = writable<boolean>(false);
//export const app_nav_prev = writable<NavParamPrev>([]);
//export const app_nav_title = writable<NavParamTitle | false>(false);
+
+export const app_init_route = writable<string>(``);
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte
@@ -2,14 +2,11 @@
import { goto } from "$app/navigation";
import Tabs from "$lib/components/tabs.svelte";
import { app_layout, app_tab_active, app_tabs_visible } from "$lib/stores";
- import { type PropChildren } from "@radroots/svelte-lib";
- let { children }: PropChildren = $props();
-
</script>
-{@render children()}
+<slot />
{#if $app_tabs_visible}
- <Tabs
+ <Tabs
basis={{
tab_active: $app_tab_active,
app_layout: $app_layout,
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
@@ -4,11 +4,15 @@
import { app_tab_active, app_tabs_visible } from "$lib/stores";
import { NDKKind } from "@nostr-dev-kit/ndk";
import { ndk, ndk_event, ndk_user, t } from "@radroots/svelte-lib";
+ import { onMount } from "svelte";
- $effect(() => {
- //app_nav_visible.set(false);
- app_tabs_visible.set(true);
- app_tab_active.set(0);
+ onMount(async () => {
+ try {
+ app_tabs_visible.set(true);
+ app_tab_active.set(0);
+ } catch (e) {
+ } finally {
+ }
});
const nostr_note_pub = async (): Promise<void> => {
@@ -34,7 +38,7 @@
<div class={`flex flex-col w-full pt-16 gap-8 justify-center items-center`}>
<button
class={`button-simple`}
- onclick={async () => {
+ on:click={async () => {
await cl.dialog.alert(`Hi! You're platform is ${cl.platform}`);
}}
>
@@ -42,18 +46,10 @@
</button>
<button
class={`button-simple`}
- onclick={async () => {
+ on:click={async () => {
await goto(`/models/location-gcs`);
}}
>
- {"models location_gcs"}
- </button>
- <button
- class={`button-simple`}
- onclick={async () => {
- await nostr_note_pub();
- }}
- >
- {"publish test note"}
+ {"models geolocation"}
</button>
</div>
diff --git a/src/routes/(app)/models/location-gcs/+page.svelte b/src/routes/(app)/models/location-gcs/+page.svelte
@@ -2,30 +2,39 @@
import { cl } from "$lib/client";
import LayoutTrellis from "$lib/components/layout-trellis.svelte";
import LayoutView from "$lib/components/layout-view.svelte";
+ import Nav from "$lib/components/nav.svelte";
import { app_tabs_visible } from "$lib/stores";
- import { type LocationGcs, type LocationGcsFormFields } from "@radroots/client";
+ import { type LocationGcs } from "@radroots/client";
import { trellis as Trellis } from "@radroots/svelte-lib";
import { location_geohash } from "@radroots/utils";
+ import { onMount } from "svelte";
- let locations_all = $state<LocationGcs[]>([]);
+ let locations_all: LocationGcs[] = [];
- $effect(() => {
- app_tabs_visible.set(false);
- (async () => {
- try {
+ onMount(async () => {
+ try {
+ app_tabs_visible.set(false);
+ await fetch_models();
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ const fetch_models = async (): Promise<void> => {
+ try {
const res = await cl.db.location_gcs_get({
list: [`all`],
});
- if(typeof res !== `string`) locations_all = res;
- } catch (e) { }
- })();
- });
+ if (typeof res !== `string`) locations_all = res;
+ } catch (e) {
+ console.log(`(error) fetch_models `, e);
+ }
+ };
</script>
-
<LayoutView>
<LayoutTrellis>
- <Trellis
+ <Trellis
basis={{
args: {
layer: 1,
@@ -45,36 +54,67 @@
},
callback: async () => {
const loc_gcs = await cl.geo.current();
- if (loc_gcs && typeof loc_gcs !== `string`) {
- const loc_gcs_label = await cl.dialog.prompt({
- title: `Geolocation Label`,
- message: `What is the name of the location.`,
- input_placeholder: `Enter location name`,
- });
- if(loc_gcs_label === false) return;
-
+ if (
+ loc_gcs &&
+ typeof loc_gcs !== `string`
+ ) {
+ const loc_gcs_label =
+ await cl.dialog.prompt({
+ title: `Geolocation Label`,
+ message: `What is the name of the location.`,
+ input_placeholder: `Enter location name`,
+ });
+ if (loc_gcs_label === false) return;
const { lat, lng } = loc_gcs;
- const geohash = location_geohash(lat, lng);
- const fields: LocationGcsFormFields = {
+ const geohash = location_geohash(
+ lat,
+ lng,
+ );
+ const fields = {
lat: lat.toString(),
lng: lng.toString(),
geohash,
- label: loc_gcs_label
+ label: loc_gcs_label,
};
- const exe_res = await cl.db.location_gcs_add(fields);
- if(typeof exe_res !== `string` && `id` in exe_res) {
- await cl.dialog.alert(`Added new location (${exe_res.id})`);
- } else if(typeof exe_res === `string` && exe_res === `*-location-gcs-geohash-unique`) {
- await cl.dialog.alert(`This location has already been added.`);
+ const exe_res =
+ await cl.db.location_gcs_add(
+ fields,
+ );
+ if (
+ typeof exe_res !== `string` &&
+ `id` in exe_res
+ ) {
+ await fetch_models();
+ } else if (
+ typeof exe_res === `string` &&
+ exe_res ===
+ `*-location-gcs-geohash-unique`
+ ) {
+ await cl.dialog.alert(
+ `This location has already been added.`,
+ );
}
- } else if (loc_gcs && typeof loc_gcs === `string`) {
- const dcf_res = await cl.dialog.confirm(`Enable location permission is required.`);
+ } else if (
+ loc_gcs &&
+ typeof loc_gcs === `string`
+ ) {
+ const dcf_res = await cl.dialog.confirm(
+ `Enable location permission is required.`,
+ );
if (dcf_res) {
await cl.settings.open(
cl.platform === `ios`
- ? { ios: { setting: `LocationServices` } }
- : { android: { setting: `Location` } },
+ ? {
+ ios: {
+ setting: `LocationServices`,
+ },
+ }
+ : {
+ android: {
+ setting: `Location`,
+ },
+ },
);
}
}
@@ -95,8 +135,8 @@
const res = await cl.db.location_gcs_get({
list: [`all`],
});
- if(typeof res !== `string`) locations_all = res;
-
+ if (typeof res !== `string`)
+ locations_all = res;
},
},
},
@@ -111,7 +151,8 @@
</p>
{#each locations_all as location}
<div class={`flex flex-col justify-center items-center`}>
- <pre class={`font-sans font-[400] text-layer-0-glyph text-xs`}>{JSON.stringify(
+ <pre
+ class={`font-sans font-[400] text-layer-0-glyph text-xs`}>{JSON.stringify(
location,
null,
4,
@@ -127,3 +168,14 @@
</div>
</LayoutTrellis>
</LayoutView>
+<Nav
+ basis={{
+ prev: {
+ label: `Home`,
+ route: `/`,
+ },
+ title: {
+ label: `Locations`,
+ },
+ }}
+/>
diff --git a/src/routes/(app)/nostr/+page.svelte b/src/routes/(app)/nostr/+page.svelte
@@ -22,13 +22,38 @@
label: {
left: [
{
- value: `View Profile`,
+ value: `View Your Keys`,
+ },
+ ],
+ },
+ callback: async () => {
+ await goto(`/nostr/keys`);
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
+ },
+ },
+ },
+ },
+ {
+ hide_active: true,
+ touch: {
+ label: {
+ left: [
+ {
+ value: `View Your Profile`,
},
],
},
callback: async () => {
await goto(`/nostr/profile`);
},
+ end: {
+ icon: {
+ key: `caret-right`,
+ },
+ },
},
},
{
@@ -37,13 +62,18 @@
label: {
left: [
{
- value: `View Notes`,
+ value: `View Your Notes`,
},
],
},
callback: async () => {
await goto(`/nostr/notes`);
},
+ end: {
+ icon: {
+ key: `caret-right`,
+ },
+ },
},
},
],
@@ -58,5 +88,8 @@
label: `Home`,
route: `/`,
},
+ title: {
+ label: `Nostr`,
+ },
}}
/>
diff --git a/src/routes/(app)/nostr/keys/+page.svelte b/src/routes/(app)/nostr/keys/+page.svelte
@@ -0,0 +1,139 @@
+<script lang="ts">
+ import { cl } from "$lib/client";
+ import LayoutTrellis from "$lib/components/layout-trellis.svelte";
+ import LayoutView from "$lib/components/layout-view.svelte";
+ import Nav from "$lib/components/nav.svelte";
+ import { _cf } from "$lib/conf";
+ import { trellis as Trellis } from "@radroots/svelte-lib";
+ import { onMount } from "svelte";
+
+ let nostr_public_key = ``;
+ let nostr_secret_key = ``;
+
+ onMount(async () => {
+ try {
+ const public_key = await cl.preferences.get(_cf.pref_key_active);
+ if (public_key) nostr_public_key = public_key;
+ const secret_key = await cl.keystore.get(`nostr:key:${public_key}`);
+ if (secret_key) nostr_secret_key = secret_key;
+ } catch (e) {
+ } finally {
+ }
+ });
+
+ async function copyToClipboard(text: string) {
+ navigator.clipboard.writeText(text).then(async () => {
+ await cl.dialog.alert(
+ `Copied nostr key "${text.slice(0, 12)}..." to clipboard.`,
+ );
+ });
+ }
+</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: cl.nostr.lib.npub(
+ nostr_public_key,
+ ),
+ },
+ ],
+ },
+
+ callback: async () => {
+ await copyToClipboard(
+ cl.nostr.lib.npub(nostr_public_key),
+ );
+ },
+ },
+ },
+ ],
+ },
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Secret Key`,
+ },
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: nostr_secret_key,
+ },
+ ],
+ },
+
+ callback: async () => {
+ await copyToClipboard(nostr_secret_key);
+ },
+ },
+ },
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: cl.nostr.lib.nsec(
+ nostr_secret_key,
+ ),
+ },
+ ],
+ },
+
+ callback: async () => {
+ await copyToClipboard(
+ cl.nostr.lib.nsec(nostr_secret_key),
+ );
+ },
+ },
+ },
+ ],
+ },
+ }}
+ />
+ </LayoutTrellis>
+</LayoutView>
+<Nav
+ basis={{
+ prev: {
+ label: `Nostr`,
+ route: `/nostr`,
+ },
+ title: {
+ label: `Keys`,
+ },
+ }}
+/>
diff --git a/src/routes/(app)/nostr/notes/+page.svelte b/src/routes/(app)/nostr/notes/+page.svelte
@@ -1,83 +1,151 @@
<script lang="ts">
- import { cl } from "$lib/client";
+ import { goto } from "$app/navigation";
import LayoutTrellis from "$lib/components/layout-trellis.svelte";
import LayoutView from "$lib/components/layout-view.svelte";
import Nav from "$lib/components/nav.svelte";
import { app_nostr_key } from "$lib/stores";
- import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
- import { ndk, trellis as Trellis } from "@radroots/svelte-lib";
- import { writable } from "svelte/store";
+ import { NDKEvent, NDKKind, type NDKFilter } from "@nostr-dev-kit/ndk";
+ import type {
+ ExtendedBaseType,
+ NDKEventStore,
+ } from "@nostr-dev-kit/ndk-svelte";
+ import {
+ locale,
+ ndk,
+ time_fmt_nostr_event,
+ trellis as Trellis,
+ type ITrellisKindTouch,
+ } from "@radroots/svelte-lib";
+ import { onDestroy } from "svelte";
- let ndk_sub = $ndk.subscribe(
- {
+ let events_store: NDKEventStore<ExtendedBaseType<NDKEvent>>;
+
+ $: {
+ let authors = [$app_nostr_key];
+ let ndk_filter: NDKFilter = {
kinds: [NDKKind.Text],
- authors: [$app_nostr_key],
- },
- {
- closeOnEose: false,
- },
- );
- const events_list = writable<NDKEvent[]>([]);
+ ...{ authors },
+ };
- events_list.subscribe((events_list) => {
- console.log(
- `events_list `,
- JSON.stringify(events_list.map((i) => i.content)),
- );
- });
+ fetch_events(ndk_filter).then(() => {
+ events_store?.startSubscription();
+ });
+ }
- ndk_sub.on("event", (event) => {
- events_list.set([...$events_list, event]);
+ async function fetch_events(filter: NDKFilter) {
+ try {
+ events_store = $ndk.storeSubscribe(filter, {
+ closeOnEose: true,
+ groupable: false,
+ autoStart: false,
+ });
+ if (events_store) {
+ events_store.onEose(() => {});
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ }
+
+ onDestroy(() => {
+ events_store?.unsubscribe();
});
+
+ const parse_nostr_text_note = (ev: NDKEvent): ITrellisKindTouch[] => {
+ const trellis_list: ITrellisKindTouch[] = [];
+
+ trellis_list.push({
+ touch: {
+ label: {
+ left: [
+ {
+ value: ev.content,
+ },
+ ],
+ },
+ callback: async () => {
+ await goto(`/nostr/notes/post`);
+ },
+ },
+ });
+
+ trellis_list.push({
+ hide_active: true,
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Published At:`,
+ },
+ ],
+ right: [
+ {
+ value: time_fmt_nostr_event($locale, ev.created_at),
+ },
+ ],
+ },
+ },
+ });
+
+ for (const tags of Object.entries(ev.tags)) {
+ console.log(`tags `, tags);
+ }
+ return trellis_list;
+ };
</script>
<LayoutView basis={{ fade: true }}>
<LayoutTrellis>
- <Trellis
- basis={{
- args: {
- layer: 1,
- title: {
- value: `Nostr Profile`,
+ {#if $events_store.length}
+ {#each $events_store as ev, ev_i (ev.id)}
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title:
+ ev_i === 0
+ ? {
+ value: `Your Notes`,
+ }
+ : undefined,
+ list: parse_nostr_text_note(ev),
+ },
+ }}
+ />
+ {/each}
+ {:else}
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Your Notes`,
+ },
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Add Note`,
+ },
+ ],
+ },
+ end: {
+ icon: {
+ key: `caret-right`,
+ },
+ },
+ callback: async () => {
+ await goto(`/nostr/notes/post`);
+ },
+ },
+ },
+ ],
},
- list: $events_list.length
- ? $events_list.map((ev) => ({
- hide_active: true,
- touch: {
- label: {
- left: [
- {
- value: ev.content,
- },
- ],
- },
- callback: async () => {},
- },
- }))
- : [
- {
- touch: {
- label: {
- left: [
- {
- value: `Add Note`,
- },
- ],
- },
- end: {
- icon: {
- key: `caret-right`,
- },
- },
- callback: async () => {
- await cl.dialog.alert(`Todo!`);
- },
- },
- },
- ],
- },
- }}
- />
+ }}
+ />
+ {/if}
</LayoutTrellis>
</LayoutView>
<Nav
@@ -89,11 +157,11 @@
title: {
label: `Notes`,
},
- option: $events_list.length
+ option: $events_store.length
? {
- label: `Edit`,
+ label: `Post`,
callback: async () => {
- await cl.dialog.alert(`Todo!`);
+ await goto(`/nostr/notes/post`);
},
}
: undefined,
diff --git a/src/routes/(app)/nostr/notes/post/+page.svelte b/src/routes/(app)/nostr/notes/post/+page.svelte
@@ -0,0 +1,74 @@
+<script lang="ts">
+ import { goto } from "$app/navigation";
+ import { cl } from "$lib/client";
+ import ButtonSubmit from "$lib/components/button-submit.svelte";
+ import LayoutTrellis from "$lib/components/layout-trellis.svelte";
+ import LayoutView from "$lib/components/layout-view.svelte";
+ import Nav from "$lib/components/nav.svelte";
+ import { NDKKind } from "@nostr-dev-kit/ndk";
+ import { ndk, ndk_event, ndk_user } from "@radroots/svelte-lib";
+
+ let loading = false;
+ let value_note_content = ``;
+
+ const nostr_note_publish = async (): Promise<void> => {
+ try {
+ if (!value_note_content) {
+ await cl.dialog.alert(`You must write something to post.`);
+ return;
+ }
+
+ loading = true;
+
+ const ev = await ndk_event({
+ $ndk,
+ $ndk_user,
+ basis: {
+ kind: NDKKind.Text,
+ content: value_note_content,
+ },
+ });
+ if (ev) {
+ await ev.publish();
+ await goto(`/nostr/notes`);
+ }
+ } catch (e) {
+ console.log(`(error) nostr_note_publish `, e);
+ } finally {
+ loading = false;
+ }
+ };
+</script>
+
+<LayoutView basis={{ fade: true }}>
+ <LayoutTrellis>
+ <div class={`flex flex-col w-full gap-3 justify-center items-center`}>
+ <textarea
+ class="input-simple p-4 h-44 rounded-xl"
+ placeholder="Write your note here"
+ bind:value={value_note_content}
+ />
+ <div class={`flex flex-row w-full justify-end items-center`}>
+ <ButtonSubmit
+ basis={{
+ callback: async () => {
+ await nostr_note_publish();
+ },
+ loading,
+ }}
+ />
+ </div>
+ </div>
+ </LayoutTrellis>
+</LayoutView>
+<Nav
+ basis={{
+ prev: {
+ label: `Notes`,
+ route: `/nostr/notes`,
+ },
+ title: {
+ label: `Post New`,
+ },
+ }}
+/>
diff --git a/src/routes/(app)/nostr/profile/+page.svelte b/src/routes/(app)/nostr/profile/+page.svelte
@@ -4,13 +4,11 @@
import LayoutView from "$lib/components/layout-view.svelte";
import Nav from "$lib/components/nav.svelte";
import { app_nostr_key } from "$lib/stores";
- import { restart } from "$lib/utils";
- import {
- NDKEvent,
- NDKKind,
- type NDKFilter,
- type NDKSubscriptionOptions,
- } from "@nostr-dev-kit/ndk";
+ import { NDKEvent, NDKKind, type NDKFilter } from "@nostr-dev-kit/ndk";
+ import type {
+ ExtendedBaseType,
+ NDKEventStore,
+ } from "@nostr-dev-kit/ndk-svelte";
import {
ndk,
ndk_event,
@@ -18,56 +16,84 @@
t,
trellis as Trellis,
} from "@radroots/svelte-lib";
- import { writable } from "svelte/store";
+ import { onDestroy } from "svelte";
- const ndk_filter: NDKFilter = {
- kinds: [NDKKind.Metadata],
- authors: [$app_nostr_key],
- };
- const ndk_opts: NDKSubscriptionOptions = {
- closeOnEose: false,
- };
- const ndk_sub = $ndk.subscribe(ndk_filter, ndk_opts);
+ let events_store: NDKEventStore<ExtendedBaseType<NDKEvent>>;
- const events_list = writable<NDKEvent[]>([]);
+ $: {
+ let authors = [$app_nostr_key];
+ let ndk_filter: NDKFilter = {
+ kinds: [NDKKind.Metadata],
+ ...{ authors },
+ };
- events_list.subscribe((events_list) => {
- console.log(
- `events_list `,
- JSON.stringify(events_list.map((i) => i.content)),
- );
- });
+ fetch_events(ndk_filter).then(() => {
+ events_store?.startSubscription();
+ });
+ }
+
+ async function fetch_events(filter: NDKFilter) {
+ try {
+ events_store = $ndk.storeSubscribe(filter, {
+ closeOnEose: true,
+ groupable: false,
+ autoStart: false,
+ });
+ if (events_store) {
+ events_store.onEose(() => {});
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ }
- ndk_sub.on("event", (event) => {
- events_list.set(
- [...$events_list, event].sort(
- (a, b) =>
- parseInt(cl.nostr.ev.first_tag_value(b, "published_at")) -
- parseInt(cl.nostr.ev.first_tag_value(a, "published_at")),
- ),
- );
+ onDestroy(() => {
+ events_store?.unsubscribe();
});
const nostr_metadata_publish = async (): Promise<void> => {
try {
- const profile_name = await cl.dialog.prompt({
+ const kind0_name = await cl.dialog.prompt({
+ title: `Name`,
+ message: `What is your personal name.`,
+ input_placeholder: `Enter your name`,
+ });
+ if (kind0_name === false) return;
+
+ const kind0_display_name = await cl.dialog.prompt({
title: `Profile Name`,
message: `What is your profile name.`,
input_placeholder: `Enter profile name`,
});
- if (profile_name === false) return;
+ if (kind0_display_name === false) return;
+
+ const kind0_about = await cl.dialog.prompt({
+ title: `About`,
+ message: `What is your about me blurb.`,
+ input_placeholder: `Enter about me`,
+ });
+ if (kind0_about === false) return;
- const display_name = await cl.dialog.prompt({
- title: `Display Name`,
- message: `What is your display name.`,
- input_placeholder: `Enter display name`,
+ const kind0_website = await cl.dialog.prompt({
+ title: `About`,
+ message: `What is your website.`,
+ input_placeholder: `Enter website`,
});
- if (display_name === false) return;
+ if (kind0_website === false) return;
+
+ const content: Record<string, string> = {};
+
+ if (kind0_name) content.name = kind0_name;
+ if (kind0_display_name) content.display_name = kind0_display_name;
+ if (kind0_about) content.about = kind0_about;
+ if (kind0_website) content.website = kind0_website;
- const content = {
- name: profile_name,
- display_name,
- };
+ if (Object.keys(content).length === 0) {
+ await cl.dialog.alert(
+ `You must specify at least one profile field.`,
+ );
+ return;
+ }
const ev = await ndk_event({
$ndk,
$ndk_user,
@@ -78,7 +104,8 @@
});
if (ev) {
await ev.publish();
- await restart();
+ events_store?.unsubscribe();
+ events_store?.startSubscription();
}
} catch (e) {
console.log(`(error) nostr_metadata_pub `, e);
@@ -93,21 +120,26 @@
args: {
layer: 1,
title: {
- value: `Nostr Profile`,
+ value: `Profile Metadata`,
},
- list: $events_list.length
+ list: $events_store.length
? Object.entries(
- JSON.parse($events_list[0].content),
+ JSON.parse($events_store[0].content),
).map(([entry_key, entry_val]) => ({
hide_active: true,
touch: {
label: {
left: [
{
- value: `${$t(`common.${entry_key}`, { default: `${entry_key.replace(`_`, ` `)}` })}: ${entry_val}`,
+ value: `${$t(`common.${entry_key}`, { default: `${entry_key.replace(`_`, ` `)}` })}:`,
classes: `capitalize`,
},
],
+ right: [
+ {
+ value: `${entry_val}`,
+ },
+ ],
},
callback: async () => {},
},
@@ -147,7 +179,7 @@
title: {
label: `Profile`,
},
- option: $events_list.length
+ option: $events_store.length
? {
label: `Edit`,
callback: async () => {
diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte
@@ -10,10 +10,14 @@
toggle_color_mode,
trellis as Trellis,
} from "@radroots/svelte-lib";
+ import { onMount } from "svelte";
- $effect(() => {
- //app_nav_visible.set(true);
- app_tabs_visible.set(false);
+ onMount(async () => {
+ try {
+ app_tabs_visible.set(false);
+ } catch (e) {
+ } finally {
+ }
});
</script>
@@ -200,7 +204,7 @@
args: {
layer: 1,
title: {
- value: `Tests`,
+ value: `Web`,
},
list: [
{
@@ -208,7 +212,7 @@
label: {
left: [
{
- value: `Radroots Homepage (Open)`,
+ value: `Radroots.Org (Open Homepage)`,
},
],
},
@@ -223,7 +227,7 @@
label: {
left: [
{
- value: `Radroots Homepage (Share)`,
+ value: `Radroots.Org (Share Homepage)`,
},
],
},
@@ -242,6 +246,79 @@
label: {
left: [
{
+ value: `Primal.Net (Open Profile)`,
+ },
+ ],
+ },
+ callback: async () => {
+ const public_key = await cl.preferences.get(
+ _cf.pref_key_active,
+ );
+ const npub = cl.nostr.lib.npub(public_key);
+ const url = `https://primal.net/p/${npub}`;
+ await cl.browser.open(url);
+ },
+ },
+ },
+ ],
+ },
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Device`,
+ },
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Device (Info)`,
+ },
+ ],
+ },
+ callback: async () => {
+ const data = await cl.device.info();
+ await cl.dialog.alert(JSON.stringify(data));
+ },
+ },
+ },
+ {
+ touch: {
+ label: {
+ left: [
+ {
+ value: `Device (Battery)`,
+ },
+ ],
+ },
+ callback: async () => {
+ const data = await cl.device.battery();
+ await cl.dialog.alert(JSON.stringify(data));
+ },
+ },
+ },
+ ],
+ },
+ }}
+ />
+ <Trellis
+ basis={{
+ args: {
+ layer: 1,
+ title: {
+ value: `Tests`,
+ },
+ list: [
+ {
+ touch: {
+ label: {
+ left: [
+ {
value: `Haptics Touch (less)`,
classes: `capitalize`,
},
@@ -309,5 +386,8 @@
label: `Home`,
route: `/`,
},
+ title: {
+ label: `Settings`,
+ },
}}
/>
diff --git a/src/routes/(conf)/conf/nostr/+page.svelte b/src/routes/(conf)/conf/nostr/+page.svelte
@@ -7,7 +7,7 @@
<div class={`flex flex-col w-full pt-16 justify-center items-center`}>
<button
class={`flex flex-row justify-center items-center text-white`}
- onclick={async () => {
+ on:click={async () => {
const sk_hex = cl.nostr.lib.generate_key();
const pk_hex = cl.nostr.lib.public_key(sk_hex);
const new_key_added = await cl.keystore.set(
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
@@ -1,11 +1,25 @@
<script lang="ts">
import { browser } from "$app/environment";
import { goto } from "$app/navigation";
- import { PUBLIC_DATABASE_NAME, PUBLIC_NOSTR_RELAY_DEFAULTS } from "$env/static/public";
+ import {
+ PUBLIC_DATABASE_NAME,
+ PUBLIC_NOSTR_RELAY_DEFAULTS,
+ } from "$env/static/public";
import { cl } from "$lib/client";
import LayoutWindow from "$lib/components/layout-window.svelte";
import { _cf } from "$lib/conf";
- import { app_config, app_layout, app_nostr_key, app_pwa_polyfills, app_render, app_sqlite, app_thc, app_thm, app_win } from "$lib/stores";
+ import {
+ app_config,
+ app_init_route,
+ app_layout,
+ app_nostr_key,
+ app_pwa_polyfills,
+ app_render,
+ app_sqlite,
+ app_thc,
+ app_thm,
+ app_win,
+ } from "$lib/stores";
import {
css_static as CssStatic,
ndk,
@@ -13,13 +27,14 @@
ndk_user,
sleep,
theme_set,
- type PropChildren
} from "@radroots/svelte-lib";
- import { parse_color_mode, parse_theme_key } from "@radroots/theme/src/utils";
+ import {
+ parse_color_mode,
+ parse_theme_key,
+ } from "@radroots/theme/src/utils";
+ import { onMount } from "svelte";
import "../app.css";
- let { children }: PropChildren = $props();
-
let render_pwa = browser && cl.platform === `web`;
if (render_pwa) {
const el = document.createElement(`jeep-sqlite`);
@@ -35,15 +50,20 @@
});
}
- $effect(() => {
- app_win.set([window.innerHeight, window.innerWidth]);
+ onMount(async () => {
+ try {
+ app_win.set([window.innerHeight, window.innerWidth]);
- const prefers_dark = window.matchMedia(
- `(prefers-color-scheme: dark)`,
- ).matches;
+ const prefers_dark = window.matchMedia(
+ `(prefers-color-scheme: dark)`,
+ ).matches;
- if (prefers_dark) app_thc.set(`dark`);
- app_config.set(true);
+ if (prefers_dark) app_thc.set(`dark`);
+ app_config.set(true);
+ } catch (e) {
+ console.log(`(layout mount) `, e);
+ } finally {
+ }
});
app_win.subscribe(([win_h, win_w]) => {
@@ -63,16 +83,19 @@
});
app_sqlite.subscribe((app_sqlite) => {
- if(!app_sqlite) return;
+ if (!app_sqlite) return;
console.log(`(app_sqlite) connected`);
});
app_nostr_key.subscribe(async (app_nostr_key) => {
try {
- if(!app_nostr_key) return;
- const private_key = await cl.keystore.get(`nostr:key:${app_nostr_key}`);
+ if (!app_nostr_key) return;
+ const private_key = await cl.keystore.get(
+ `nostr:key:${app_nostr_key}`,
+ );
if (private_key) {
- for (const url of PUBLIC_NOSTR_RELAY_DEFAULTS.split(',')) $ndk.addExplicitRelay(url);
+ for (const url of PUBLIC_NOSTR_RELAY_DEFAULTS.split(","))
+ $ndk.addExplicitRelay(url);
await $ndk.connect().then(() => {
console.log(`(ndk) connected`);
});
@@ -86,20 +109,29 @@
console.log(`(ndk_user) connected`);
}
}
- } catch(e) {
+ } catch (e) {
console.log(`(app_nostr_key) error `, e);
- };
- })
+ }
+ });
app_config.subscribe(async (app_config) => {
try {
if (!app_config) return;
app_sqlite.set(!!(await cl.db.connect(PUBLIC_DATABASE_NAME)));
- const active_nostr_pk = await cl.preferences.get(_cf.pref_key_active);
- console.log(`active_nostr_pk `, active_nostr_pk)
- const active_nostr_sk = await cl.keystore.get(`nostr:key:${active_nostr_pk}`);
- console.log(`active_nostr_sk `, active_nostr_sk)
- if(typeof active_nostr_sk === `string` && active_nostr_sk && active_nostr_pk) app_nostr_key.set(active_nostr_pk);
+ const active_nostr_pk = await cl.preferences.get(
+ _cf.pref_key_active,
+ );
+ console.log(`active_nostr_pk `, active_nostr_pk);
+ const active_nostr_sk = await cl.keystore.get(
+ `nostr:key:${active_nostr_pk}`,
+ );
+ console.log(`active_nostr_sk `, active_nostr_sk);
+ if (
+ typeof active_nostr_sk === `string` &&
+ active_nostr_sk &&
+ active_nostr_pk
+ )
+ app_nostr_key.set(active_nostr_pk);
else {
await cl.preferences.remove(_cf.pref_key_active);
await goto(`/conf/nostr`);
@@ -113,20 +145,30 @@
app_render.subscribe(async (app_render) => {
try {
+ console.log(`app_render `, app_render);
if (!app_render) return;
- await goto(`/`);
+ let init_route = `/`;
+ if ($app_init_route) {
+ init_route = $app_init_route;
+ app_init_route.set(`/`);
+ }
+ console.log(`init_route `, init_route);
+ await goto(init_route);
await sleep(321);
+ await cl.window.splash_hide();
} catch (e) {
console.log(`(app_render) error `, e);
} finally {
- await cl.window.splash_hide();
}
});
</script>
+
{#if $app_render}
<LayoutWindow>
- {@render children()}
+ <slot />
</LayoutWindow>
{/if}
<CssStatic />
-<div class="hidden h-nav_base pt-h_nav_base pb-h_nav_base h-nav_lg pt-h_nav_lg pb-h_nav_lg h-tabs_base pt-h_tabs_base pb-h_tabs_base h-tabs_lg pt-h_tabs_lg pb-h_tabs_lg"></div>
+<div
+ class="hidden h-nav_base pt-h_nav_base pb-h_nav_base h-nav_lg pt-h_nav_lg pb-h_nav_lg h-tabs_base pt-h_tabs_base pb-h_tabs_base h-tabs_lg pt-h_tabs_lg pb-h_tabs_lg"
+></div>
diff --git a/svelte.config.js b/svelte.config.js
@@ -7,11 +7,6 @@ const config = {
kit: {
adapter: adapter(),
},
- compilerOptions: {
- compatibility: {
- componentApi: 5
- }
- }
};
export default config;
\ No newline at end of file