app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 0ac84a8f2ec30433ba5abda106920f7af7ff4a80
parent ff4f555dd2ef91f55e10586b7ab66433402e8ce1
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Wed, 16 Oct 2024 22:24:46 +0000

Add `core` and `tauri` crates, refactor application adding tauri framework to compile native binaries. Edit `/conf/init` adding mutli-view options for device configuration and EULA. Edit `/models/` routes improving client logic, error handling, and adding localized text. Edit layouts for root, (conf), (app) scopes. Edit lib client, components, config, stores, types, utils. Add styles.

Diffstat:
M.gitignore | 5++++-
D.npmrc | 1-
ACargo.lock | 6651+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ACargo.toml | 6++++++
Dandroid/.gitignore | 101-------------------------------------------------------------------------------
Dandroid/app/.gitignore | 2--
Dandroid/app/build.gradle | 54------------------------------------------------------
Dandroid/app/capacitor.build.gradle | 31-------------------------------
Dandroid/app/proguard-rules.pro | 21---------------------
Dandroid/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java | 26--------------------------
Dandroid/app/src/main/AndroidManifest.xml | 44--------------------------------------------
Dandroid/app/src/main/java/chroma/radroots/ios/MainActivity.java | 5-----
Dandroid/app/src/main/res/drawable-land-hdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-land-mdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-land-xhdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-land-xxhdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-land-xxxhdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-port-hdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-port-mdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-port-xhdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-port-xxhdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-port-xxxhdpi/splash.png | 0
Dandroid/app/src/main/res/drawable-v24/ic_launcher_foreground.xml | 34----------------------------------
Dandroid/app/src/main/res/drawable/ic_launcher_background.xml | 170-------------------------------------------------------------------------------
Dandroid/app/src/main/res/drawable/splash.png | 0
Dandroid/app/src/main/res/layout/activity_main.xml | 12------------
Dandroid/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml | 6------
Dandroid/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml | 6------
Dandroid/app/src/main/res/mipmap-hdpi/ic_launcher.png | 0
Dandroid/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png | 0
Dandroid/app/src/main/res/mipmap-hdpi/ic_launcher_round.png | 0
Dandroid/app/src/main/res/mipmap-mdpi/ic_launcher.png | 0
Dandroid/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png | 0
Dandroid/app/src/main/res/mipmap-mdpi/ic_launcher_round.png | 0
Dandroid/app/src/main/res/mipmap-xhdpi/ic_launcher.png | 0
Dandroid/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png | 0
Dandroid/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png | 0
Dandroid/app/src/main/res/mipmap-xxhdpi/ic_launcher.png | 0
Dandroid/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png | 0
Dandroid/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png | 0
Dandroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png | 0
Dandroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png | 0
Dandroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png | 0
Dandroid/app/src/main/res/values/ic_launcher_background.xml | 5-----
Dandroid/app/src/main/res/values/strings.xml | 7-------
Dandroid/app/src/main/res/values/styles.xml | 23-----------------------
Dandroid/app/src/main/res/xml/file_paths.xml | 6------
Dandroid/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java | 18------------------
Dandroid/build.gradle | 29-----------------------------
Dandroid/capacitor.settings.gradle | 42------------------------------------------
Dandroid/gradle.properties | 22----------------------
Dandroid/gradle/wrapper/gradle-wrapper.jar | 0
Dandroid/gradle/wrapper/gradle-wrapper.properties | 7-------
Dandroid/gradlew | 248-------------------------------------------------------------------------------
Dandroid/gradlew.bat | 92-------------------------------------------------------------------------------
Dandroid/settings.gradle | 6------
Dandroid/variables.gradle | 17-----------------
Dcapacitor.config.ts | 33---------------------------------
Acrates/core/Cargo.toml | 16++++++++++++++++
Acrates/core/src/error.rs | 39+++++++++++++++++++++++++++++++++++++++
Acrates/core/src/lib.rs | 4++++
Acrates/core/src/models/location_gcs.rs | 288+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/core/src/models/mod.rs | 4++++
Acrates/core/src/models/nostr_profile.rs | 288+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/core/src/models/nostr_relay.rs | 288+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/core/src/models/trade_product.rs | 304+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/core/src/types.rs | 12++++++++++++
Acrates/core/src/utils.rs | 11+++++++++++
Acrates/tauri/.gitignore | 4++++
Acrates/tauri/Cargo.toml | 35+++++++++++++++++++++++++++++++++++
Acrates/tauri/Info.ios.plist | 18++++++++++++++++++
Acrates/tauri/build.rs | 3+++
Acrates/tauri/capabilities/default.json | 38++++++++++++++++++++++++++++++++++++++
Acrates/tauri/icons/128x128.png | 0
Acrates/tauri/icons/128x128@2x.png | 0
Acrates/tauri/icons/32x32.png | 0
Acrates/tauri/icons/Square107x107Logo.png | 0
Acrates/tauri/icons/Square142x142Logo.png | 0
Acrates/tauri/icons/Square150x150Logo.png | 0
Acrates/tauri/icons/Square284x284Logo.png | 0
Acrates/tauri/icons/Square30x30Logo.png | 0
Acrates/tauri/icons/Square310x310Logo.png | 0
Acrates/tauri/icons/Square44x44Logo.png | 0
Acrates/tauri/icons/Square71x71Logo.png | 0
Acrates/tauri/icons/Square89x89Logo.png | 0
Acrates/tauri/icons/StoreLogo.png | 0
Acrates/tauri/icons/icon.icns | 0
Acrates/tauri/icons/icon.ico | 0
Acrates/tauri/icons/icon.png | 0
Acrates/tauri/migrations/0001_location_gcs.sql | 16++++++++++++++++
Acrates/tauri/migrations/0002_trade_product.sql | 22++++++++++++++++++++++
Acrates/tauri/migrations/0003_nostr_profile.sql | 16++++++++++++++++
Acrates/tauri/migrations/0004_nostr_relay.sql | 16++++++++++++++++
Acrates/tauri/src/database.rs | 30++++++++++++++++++++++++++++++
Acrates/tauri/src/lib.rs | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/tauri/src/main.rs | 6++++++
Acrates/tauri/src/models/location_gcs.rs | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/tauri/src/models/mod.rs | 4++++
Acrates/tauri/src/models/nostr_profile.rs | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/tauri/src/models/nostr_relay.rs | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/tauri/src/models/trade_product.rs | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/tauri/src/radroots.rs | 3+++
Acrates/tauri/tauri.conf.json | 47+++++++++++++++++++++++++++++++++++++++++++++++
Dios/.gitignore | 13-------------
Dios/App/App.xcodeproj/project.pbxproj | 416-------------------------------------------------------------------------------
Dios/App/App.xcworkspace/contents.xcworkspacedata | 10----------
Dios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist | 8--------
Dios/App/App/AppDelegate.swift | 49-------------------------------------------------
Dios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png | 0
Dios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json | 14--------------
Dios/App/App/Assets.xcassets/Contents.json | 7-------
Dios/App/App/Assets.xcassets/Splash.imageset/Contents.json | 24------------------------
Dios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png | 0
Dios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png | 0
Dios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png | 0
Dios/App/App/Base.lproj/LaunchScreen.storyboard | 32--------------------------------
Dios/App/App/Base.lproj/Main.storyboard | 19-------------------
Dios/App/App/Info.plist | 51---------------------------------------------------
Dios/App/Podfile | 36------------------------------------
Dios/App/Podfile.lock | 119-------------------------------------------------------------------------------
Dios/App/PrivacyInfo.xcprivacy | 18------------------
Mpackage.json | 34++++++----------------------------
Msrc/app.css | 20++++++++++++++------
Msrc/app.d.ts | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/client.ts | 35+++++++++++++----------------------
Dsrc/lib/components/button-submit.svelte | 24------------------------
Asrc/lib/components/button_appearing_pair.svelte | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/components/map_choose_location.svelte | 6+++---
Dsrc/lib/components/map_control_full.svelte | 34----------------------------------
Dsrc/lib/components/map_full_envelope.svelte | 26--------------------------
Msrc/lib/components/map_marker_dot.svelte | 0
Msrc/lib/components/map_popup_location_info.svelte | 0
Msrc/lib/conf.ts | 31+++++++++----------------------
Dsrc/lib/stores.ts | 7-------
Dsrc/lib/types.ts | 6------
Asrc/lib/utils/client.ts | 25+++++++++++++++++++++++++
Dsrc/lib/utils/index.ts | 15---------------
Dsrc/lib/utils/keystore.ts | 12------------
Asrc/lib/utils/kv.ts | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/lib/utils/location_gcs.ts | 108-------------------------------------------------------------------------------
Asrc/lib/utils/models.ts | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/lib/utils/nostr.ts | 44--------------------------------------------
Dsrc/lib/utils/trade_product.ts | 55-------------------------------------------------------
Msrc/routes/(app)/+layout.svelte | 175++++---------------------------------------------------------------------------
Dsrc/routes/(app)/+layout.ts | 11-----------
Msrc/routes/(app)/+page.svelte | 13++++++++-----
Dsrc/routes/(app)/map/+page.svelte | 61-------------------------------------------------------------
Dsrc/routes/(app)/map/choose-location/+page.svelte | 89-------------------------------------------------------------------------------
Msrc/routes/(app)/models/location-gcs/+page.svelte | 25++++++++++++++++---------
Dsrc/routes/(app)/models/location-gcs/view-map/+page.svelte | 4----
Msrc/routes/(app)/models/nostr-profile/+page.svelte | 39++++++++++++++++++++++++++-------------
Msrc/routes/(app)/models/nostr-profile/edit/field/+page.svelte | 54++++++++++++++++++++++++++++++------------------------
Msrc/routes/(app)/models/nostr-profile/view/+page.svelte | 34+++++++++++++++++-----------------
Msrc/routes/(app)/models/nostr-relay/+page.svelte | 12++++++------
Msrc/routes/(app)/models/nostr-relay/view/+page.svelte | 36++++++++++++++++++------------------
Msrc/routes/(app)/models/trade-product/+page.svelte | 56++++++++++++++++++++++++++++++++++----------------------
Msrc/routes/(app)/models/trade-product/add/+page.svelte | 1655+++++++++++++++++++++++++++++++++++++++----------------------------------------
Dsrc/routes/(app)/nostr/+page.svelte | 97-------------------------------------------------------------------------------
Dsrc/routes/(app)/nostr/keys/+page.svelte | 286-------------------------------------------------------------------------------
Dsrc/routes/(app)/nostr/notes/+page.svelte | 169-------------------------------------------------------------------------------
Dsrc/routes/(app)/nostr/notes/post/+page.svelte | 81-------------------------------------------------------------------------------
Dsrc/routes/(app)/nostr/profile/+page.svelte | 195-------------------------------------------------------------------------------
Msrc/routes/(app)/settings/+page.svelte | 113+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/routes/(app)/test/+page.svelte | 64+++-------------------------------------------------------------
Dsrc/routes/(conf)/+layout.svelte | 7-------
Asrc/routes/(conf)/conf/error/+page.svelte | 22++++++++++++++++++++++
Msrc/routes/(conf)/conf/init/+layout.ts | 40+++++++++++++++++-----------------------
Msrc/routes/(conf)/conf/init/+page.svelte | 1154+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/routes/+error.svelte | 47++++++++++++++++++++++++-----------------------
Msrc/routes/+layout.svelte | 151+++++++++++++++++++++++++++++++------------------------------------------------
Msrc/routes/+layout.ts | 2+-
Astatic/splashscreen.html | 27+++++++++++++++++++++++++++
Mtailwind.config.ts | 232++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mvite.config.ts | 16+++++++++++++++-
174 files changed, 10896 insertions(+), 5239 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -47,5 +47,7 @@ _tmp notes*.txt justfile dist -static/assets/sql-wasm.wasm git-diff.txt +target +tauri.conf.build* +/crates/tauri/gen +\ No newline at end of file diff --git a/.npmrc b/.npmrc @@ -1 +0,0 @@ -engine-strict=true diff --git a/Cargo.lock b/Cargo.lock @@ -0,0 +1,6651 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_log-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" + +[[package]] +name = "android_logger" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ashpd" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "raw-window-handle", + "serde", + "serde_repr", + "tokio", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "atk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "borsh" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d4d6dafc1a3bb54687538972158f07b2c948bc57d5890df22c0739098b3028" +dependencies = [ + "borsh-derive", + "cfg_aliases 0.1.1", +] + +[[package]] +name = "borsh-derive" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0" +dependencies = [ + "once_cell", + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 2.0.79", + "syn_derive", +] + +[[package]] +name = "brotli" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-unit" +version = "5.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ac19bdf0b2665407c39d82dbc937e951e7e2001609f0fb32edd0af45a2d63e" +dependencies = [ + "rust_decimal", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.6.0", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cargo_toml" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719" +dependencies = [ + "serde", + "toml 0.8.2", +] + +[[package]] +name = "cc" +version = "1.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +dependencies = [ + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "cocoa" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" +dependencies = [ + "bitflags 2.6.0", + "block", + "cocoa-foundation", + "core-foundation 0.10.0", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-foundation 0.10.0", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" +dependencies = [ + "cookie", + "idna 0.5.0", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.79", +] + +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote", + "syn 2.0.79", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.79", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.79", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "dlopen2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +dependencies = [ + "serde", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] + +[[package]] +name = "embed-resource" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 0.8.2", + "vswhom", + "winreg", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fdeflate" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fern" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +dependencies = [ + "log", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90fbf5c033c65d93792192a49a8efb5bb1e640c419682a58bb96f5ae77f3d4a" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2ea8a4909d530f79921290389cbd7c34cb9d623bfe970eaae65ca5f9cd9cce" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee8f00f4ee46cad2939b8990f5c70c94ff882c3028f3cc5abf950fa4ab53043" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.6.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.11", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.11", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa 1.0.11", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae" +dependencies = [ + "byteorder", + "png", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", + "serde", +] + +[[package]] +name = "infer" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847" +dependencies = [ + "cfb", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonptr" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" +dependencies = [ + "fluent-uri", + "serde", + "serde_json", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.6.0", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "keyring" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd3d701d3de5b9c4b0d9d077f8c2c66f0388d75e96932ebbb7cdff8713d7f7c6" +dependencies = [ + "byteorder", + "linux-keyutils", + "security-framework", + "windows-sys 0.59.0", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 1.9.3", + "matches", + "selectors", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-keyutils" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "value-bag", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "mac-notification-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce8f34f3717aa37177e723df6c1fc5fb02b2a1087374ea3fe0ea42316dc8f91" +dependencies = [ + "cc", + "dirs-next", + "objc-foundation", + "objc_id", + "time", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "muda" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8123dfd4996055ac9b15a60ad263b44b01e539007523ad7a4a533a3d93b0591" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "png", + "serde", + "thiserror", + "windows-sys 0.59.0", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.6.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "notify-rust" +version = "4.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5134a72dc570b178bff81b01e81ab14a6fcc015391ed4b3b14853090658cd3a3" +dependencies = [ + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "open" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "os_pipe" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "plist" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" +dependencies = [ + "base64 0.22.1", + "indexmap 2.6.0", + "quick-xml 0.32.0", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "publicsuffix" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" +dependencies = [ + "idna 0.3.0", + "psl-types", +] + +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "radroots" +version = "0.0.1" +dependencies = [ + "env_logger", + "keyring", + "log", + "radroots_core", + "serde", + "serde_json", + "sqlx", + "tauri", + "tauri-build", + "tauri-plugin-dialog", + "tauri-plugin-geolocation", + "tauri-plugin-http", + "tauri-plugin-log", + "tauri-plugin-map-display", + "tauri-plugin-notification", + "tauri-plugin-shell", + "tauri-plugin-store", +] + +[[package]] +name = "radroots_core" +version = "0.0.1" +dependencies = [ + "chrono", + "futures", + "regex", + "serde", + "serde_json", + "sqlx", + "thiserror", + "uuid", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64 0.22.1", + "bytes", + "cookie", + "cookie_store", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", + "windows-registry", +] + +[[package]] +name = "rfd" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" +dependencies = [ + "ashpd", + "block2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rust_decimal" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", + "url", + "uuid", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.79", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d0283c0a4a22a0f1b0e4edca251aa20b92fc96eaa09b84bec052f9415e9d71" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6" +dependencies = [ + "erased-serde", + "serde", + "typeid", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa 1.0.11", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.11", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.6.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shared_child" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "softbuffer" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +dependencies = [ + "bytemuck", + "cfg_aliases 0.2.1", + "core-graphics", + "foreign-types", + "js-sys", + "log", + "objc2", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle", + "redox_syscall", + "wasm-bindgen", + "web-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "specta" +version = "2.0.0-rc.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ccbb212565d2dc177bc15ecb7b039d66c4490da892436a4eee5b394d620c9bc" +dependencies = [ + "paste", + "specta-macros", + "thiserror", +] + +[[package]] +name = "specta-macros" +version = "2.0.0-rc.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68999d29816965eb9e5201f60aec02a76512139811661a7e8e653abc810b8f72" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" +dependencies = [ + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.14.5", + "hashlink", + "hex", + "indexmap 2.6.0", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.79", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" +dependencies = [ + "dotenvy", + "either", + "heck 0.5.0", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.79", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.6.0", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa 1.0.11", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.6.0", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa 1.0.11", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "tracing", + "url", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "swift-rs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.2", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dbbebe82d02044dfa481adca1550d6dd7bd16e086bc34fa0fbecceb5a63751" +dependencies = [ + "bitflags 2.6.0", + "cocoa", + "core-foundation 0.10.0", + "core-graphics", + "crossbeam-channel", + "dispatch", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "instant", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "raw-window-handle", + "scopeguard", + "tao-macros", + "unicode-segmentation", + "url", + "windows 0.58.0", + "windows-core 0.58.0", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tauri" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd96d46534b10765ce0c6208f9451d98ea38636364a41b272d3610c70dd0e4c3" +dependencies = [ + "anyhow", + "bytes", + "dirs", + "dunce", + "embed_plist", + "futures-util", + "getrandom 0.2.15", + "glob", + "gtk", + "heck 0.5.0", + "http", + "http-range", + "jni", + "libc", + "log", + "mime", + "muda", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "percent-encoding", + "plist", + "raw-window-handle", + "reqwest", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "specta", + "swift-rs", + "tauri-build", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils", + "thiserror", + "tokio", + "tray-icon", + "url", + "urlpattern", + "webkit2gtk", + "webview2-com", + "window-vibrancy", + "windows 0.58.0", +] + +[[package]] +name = "tauri-build" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "935f9b3c49b22b3e2e485a57f46d61cd1ae07b1cbb2ba87387a387caf2d8c4e7" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs", + "glob", + "heck 0.5.0", + "json-patch", + "schemars", + "semver", + "serde", + "serde_json", + "tauri-utils", + "tauri-winres", + "toml 0.8.2", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95d7443dd4f0b597704b6a14b964ee2ed16e99928d8e6292ae9825f09fbcd30e" +dependencies = [ + "base64 0.22.1", + "brotli", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "syn 2.0.79", + "tauri-utils", + "thiserror", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2c0963ccfc3f5194415f2cce7acc975942a8797fbabfb0aa1ed6f59326ae7f" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.79", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-plugin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e6660a409963e4d57b9bfab4addd141eeff41bd3a7fb14e13004a832cf7ef6" +dependencies = [ + "anyhow", + "glob", + "plist", + "schemars", + "serde", + "serde_json", + "tauri-utils", + "toml 0.8.2", + "walkdir", +] + +[[package]] +name = "tauri-plugin-dialog" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddb2fe88b602461c118722c574e2775ab26a4e68886680583874b2f6520608b7" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror", + "url", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab300488ebec3487ca5f56289692e7e45feb07eea8d5e1dba497f7dc9dd9c407" +dependencies = [ + "anyhow", + "dunce", + "glob", + "percent-encoding", + "schemars", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "thiserror", + "url", + "uuid", +] + +[[package]] +name = "tauri-plugin-geolocation" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14553ada3bcb836d710e8cb9013bcc98508b48ba9b0dc166e7510552bd05cf9" +dependencies = [ + "log", + "serde", + "serde_json", + "specta", + "tauri", + "tauri-plugin", + "thiserror", +] + +[[package]] +name = "tauri-plugin-http" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784333f1632d96c94346e8145bfe52970923a38a0e6eacd3dccaa12289275acf" +dependencies = [ + "data-url", + "http", + "regex", + "reqwest", + "schemars", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror", + "tokio", + "url", + "urlpattern", +] + +[[package]] +name = "tauri-plugin-log" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49f2c05d15e6375ab7f7e528b3049150ba4dfafdf61f85e5178d0aef18e3f5" +dependencies = [ + "android_logger", + "byte-unit", + "cocoa", + "fern", + "log", + "objc", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror", + "time", +] + +[[package]] +name = "tauri-plugin-map-display" +version = "0.1.0" +source = "git+https://github.com/inkibra/tauri-plugins?tag=@inkibra/tauri-plugin-map-display@0.2.0#31aa60a18d19f35828649e84c36597d18661b7e9" +dependencies = [ + "serde", + "tauri", + "tauri-plugin", + "thiserror", +] + +[[package]] +name = "tauri-plugin-notification" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef492a2d19b6376bb4c9e0c4fab3f3bf8a220ea112d24f35027b737ff55de20c" +dependencies = [ + "log", + "notify-rust", + "rand 0.8.5", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "thiserror", + "time", + "url", +] + +[[package]] +name = "tauri-plugin-shell" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "371fb9aca2823990a2d0db7970573be5fdf07881fcaa2b835b29631feb84aec1" +dependencies = [ + "encoding_rs", + "log", + "open", + "os_pipe", + "regex", + "schemars", + "serde", + "serde_json", + "shared_child", + "tauri", + "tauri-plugin", + "thiserror", + "tokio", +] + +[[package]] +name = "tauri-plugin-store" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5058f179f7215390fc5a68eeffcb805b7e2681d6e817a5d08094fae7ab649e68" +dependencies = [ + "dunce", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror", + "tokio", +] + +[[package]] +name = "tauri-runtime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8f437293d6f5e5dce829250f4dbdce4e0b52905e297a6689cc2963eb53ac728" +dependencies = [ + "dpi", + "gtk", + "http", + "jni", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror", + "url", + "windows 0.58.0", +] + +[[package]] +name = "tauri-runtime-wry" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaac63b65df8e85570993eaf93ae1dd73a6fb66d8bd99674ce65f41dc3c63e7d" +dependencies = [ + "gtk", + "http", + "jni", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "percent-encoding", + "raw-window-handle", + "softbuffer", + "tao", + "tauri-runtime", + "tauri-utils", + "url", + "webkit2gtk", + "webview2-com", + "windows 0.58.0", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38b0230d6880cf6dd07b6d7dd7789a0869f98ac12146e0d18d1c1049215a045" +dependencies = [ + "brotli", + "cargo_metadata", + "ctor", + "dunce", + "glob", + "html5ever", + "infer", + "json-patch", + "kuchikiki", + "log", + "memchr", + "phf 0.11.2", + "proc-macro2", + "quote", + "regex", + "schemars", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror", + "toml 0.8.2", + "url", + "urlpattern", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-winres" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb" +dependencies = [ + "embed-resource", + "toml 0.7.8", +] + +[[package]] +name = "tauri-winrt-notification" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89f5fb70d6f62381f5d9b2ba9008196150b40b75f3068eb24faeddf1c686871" +dependencies = [ + "quick-xml 0.31.0", + "windows 0.56.0", + "windows-version", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa 1.0.11", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tray-icon" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533fc2d4105e0e3d96ce1c71f2d308c9fbbe2ef9c587cab63dd627ab5bde218f" +dependencies = [ + "core-graphics", + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "png", + "serde", + "thiserror", + "windows-sys 0.59.0", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-ucd-ident" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlpattern" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +dependencies = [ + "regex", + "serde", + "unic-ucd-ident", + "url", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom 0.2.15", + "serde", +] + +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "wasm-streams" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" +dependencies = [ + "bitflags 2.6.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml 0.36.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webview2-com" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows 0.58.0", + "windows-core 0.58.0", + "windows-implement 0.58.0", + "windows-interface 0.58.0", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "webview2-com-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" +dependencies = [ + "thiserror", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea403deff7b51fff19e261330f71608ff2cdef5721d72b64180bb95be7c4150" +dependencies = [ + "objc2", + "objc2-app-kit", + "objc2-foundation", + "raw-window-handle", + "windows-sys 0.59.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-version" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998aa457c9ba8ff2fb9f13e9d2a930dabcea28f1d0ab94d687d8b3654844515" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wry" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469a3765ecc3e8aa9ccdf3c5a52c82697ec03037cd60494488763880d31a1b3a" +dependencies = [ + "base64 0.22.1", + "block2", + "crossbeam-channel", + "dpi", + "dunce", + "gdkx11", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "sha2", + "soup3", + "tao-macros", + "thiserror", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows 0.58.0", + "windows-core 0.58.0", + "windows-version", + "x11-dl", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "zbus" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zvariant" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] diff --git a/Cargo.toml b/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +resolver = "2" +members = [ + "crates/core", + "crates/tauri", +] diff --git a/android/.gitignore b/android/.gitignore @@ -1,101 +0,0 @@ -# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore - -# Built application files -*.apk -*.aar -*.ap_ -*.aab - -# Files for the ART/Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -bin/ -gen/ -out/ -# Uncomment the following line in case you need and you don't have the release build type files in your app -# release/ - -# Gradle files -.gradle/ -build/ - -# Local configuration file (sdk path, etc) -local.properties - -# Proguard folder generated by Eclipse -proguard/ - -# Log Files -*.log - -# Android Studio Navigation editor temp files -.navigation/ - -# Android Studio captures folder -captures/ - -# IntelliJ -*.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/assetWizardSettings.xml -.idea/dictionaries -.idea/libraries -# Android Studio 3 in .gitignore file. -.idea/caches -.idea/modules.xml -# Comment next line if keeping position of elements in Navigation Editor is relevant for you -.idea/navEditor.xml - -# Keystore files -# Uncomment the following lines if you do not want to check your keystore files in. -#*.jks -#*.keystore - -# External native build folder generated in Android Studio 2.2 and later -.externalNativeBuild -.cxx/ - -# Google Services (e.g. APIs or Firebase) -# google-services.json - -# Freeline -freeline.py -freeline/ -freeline_project_description.json - -# fastlane -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots -fastlane/test_output -fastlane/readme.md - -# Version control -vcs.xml - -# lint -lint/intermediates/ -lint/generated/ -lint/outputs/ -lint/tmp/ -# lint/reports/ - -# Android Profiling -*.hprof - -# Cordova plugins for Capacitor -capacitor-cordova-android-plugins - -# Copied web assets -app/src/main/assets/public - -# Generated Config files -app/src/main/assets/capacitor.config.json -app/src/main/assets/capacitor.plugins.json -app/src/main/res/xml/config.xml diff --git a/android/app/.gitignore b/android/app/.gitignore @@ -1,2 +0,0 @@ -/build/* -!/build/.npmkeep diff --git a/android/app/build.gradle b/android/app/build.gradle @@ -1,54 +0,0 @@ -apply plugin: 'com.android.application' - -android { - namespace "chroma.radroots.ios" - compileSdk rootProject.ext.compileSdkVersion - defaultConfig { - applicationId "chroma.radroots.ios" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - aaptOptions { - // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. - // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 - ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' - } - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -repositories { - flatDir{ - dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' - } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" - implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" - implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" - implementation project(':capacitor-android') - testImplementation "junit:junit:$junitVersion" - androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" - androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" - implementation project(':capacitor-cordova-android-plugins') -} - -apply from: 'capacitor.build.gradle' - -try { - def servicesJSON = file('google-services.json') - if (servicesJSON.text) { - apply plugin: 'com.google.gms.google-services' - } -} catch(Exception e) { - logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") -} diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle @@ -1,31 +0,0 @@ -// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN - -android { - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } -} - -apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" -dependencies { - implementation project(':capacitor-browser') - implementation project(':capacitor-device') - implementation project(':capacitor-dialog') - implementation project(':capacitor-geolocation') - implementation project(':capacitor-haptics') - implementation project(':capacitor-preferences') - implementation project(':capacitor-share') - implementation project(':capacitor-splash-screen') - implementation project(':capacitor-status-bar') - implementation project(':radroots-capacitor-native-settings') - implementation project(':radroots-capacitor-secure-storage') - implementation project(':radroots-capacitor-sqlite') - implementation project(':radroots-capacitor-wifi') - -} - - -if (hasProperty('postBuildExtras')) { - postBuildExtras() -} diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -1,26 +0,0 @@ -package com.getcapacitor.myapp; - -import static org.junit.Assert.*; - -import android.content.Context; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.platform.app.InstrumentationRegistry; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - - assertEquals("com.getcapacitor.app", appContext.getPackageName()); - } -} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android"> - - <application - android:allowBackup="true" - android:icon="@mipmap/ic_launcher" - android:label="@string/app_name" - android:roundIcon="@mipmap/ic_launcher_round" - android:supportsRtl="true" - android:theme="@style/AppTheme"> - - <activity - android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" - android:name=".MainActivity" - android:label="@string/title_activity_main" - android:theme="@style/AppTheme.NoActionBarLaunch" - android:launchMode="singleTask" - android:exported="true"> - - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - </activity> - - <provider - android:name="androidx.core.content.FileProvider" - android:authorities="${applicationId}.fileprovider" - android:exported="false" - android:grantUriPermissions="true"> - <meta-data - android:name="android.support.FILE_PROVIDER_PATHS" - android:resource="@xml/file_paths"></meta-data> - </provider> - </application> - - <!-- Permissions --> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> - <uses-feature android:name="android.hardware.location.gps" /> -</manifest> diff --git a/android/app/src/main/java/chroma/radroots/ios/MainActivity.java b/android/app/src/main/java/chroma/radroots/ios/MainActivity.java @@ -1,5 +0,0 @@ -package chroma.radroots.ios; - -import com.getcapacitor.BridgeActivity; - -public class MainActivity extends BridgeActivity {} diff --git a/android/app/src/main/res/drawable-land-hdpi/splash.png b/android/app/src/main/res/drawable-land-hdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-land-mdpi/splash.png b/android/app/src/main/res/drawable-land-mdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-land-xhdpi/splash.png b/android/app/src/main/res/drawable-land-xhdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/android/app/src/main/res/drawable-land-xxhdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/android/app/src/main/res/drawable-land-xxxhdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-port-hdpi/splash.png b/android/app/src/main/res/drawable-port-hdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-port-mdpi/splash.png b/android/app/src/main/res/drawable-port-mdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-port-xhdpi/splash.png b/android/app/src/main/res/drawable-port-xhdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/android/app/src/main/res/drawable-port-xxhdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/android/app/src/main/res/drawable-port-xxxhdpi/splash.png Binary files differ. diff --git a/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -1,34 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="108dp" - android:height="108dp" - android:viewportHeight="108" - android:viewportWidth="108"> - <path - android:fillType="evenOdd" - android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" - android:strokeColor="#00000000" - android:strokeWidth="1"> - <aapt:attr name="android:fillColor"> - <gradient - android:endX="78.5885" - android:endY="90.9159" - android:startX="48.7653" - android:startY="61.0927" - android:type="linear"> - <item - android:color="#44000000" - android:offset="0.0" /> - <item - android:color="#00000000" - android:offset="1.0" /> - </gradient> - </aapt:attr> - </path> - <path - android:fillColor="#FFFFFF" - android:fillType="nonZero" - android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" - android:strokeColor="#00000000" - android:strokeWidth="1" /> -</vector> diff --git a/android/app/src/main/res/drawable/ic_launcher_background.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,170 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="108dp" - android:height="108dp" - android:viewportHeight="108" - android:viewportWidth="108"> - <path - android:fillColor="#26A69A" - android:pathData="M0,0h108v108h-108z" /> - <path - android:fillColor="#00000000" - android:pathData="M9,0L9,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,0L19,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M29,0L29,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M39,0L39,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M49,0L49,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M59,0L59,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M69,0L69,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M79,0L79,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M89,0L89,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M99,0L99,108" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,9L108,9" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,19L108,19" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,29L108,29" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,39L108,39" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,49L108,49" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,59L108,59" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,69L108,69" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,79L108,79" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,89L108,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M0,99L108,99" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,29L89,29" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,39L89,39" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,49L89,49" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,59L89,59" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,69L89,69" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M19,79L89,79" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M29,19L29,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M39,19L39,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M49,19L49,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M59,19L59,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M69,19L69,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> - <path - android:fillColor="#00000000" - android:pathData="M79,19L79,89" - android:strokeColor="#33FFFFFF" - android:strokeWidth="0.8" /> -</vector> diff --git a/android/app/src/main/res/drawable/splash.png b/android/app/src/main/res/drawable/splash.png Binary files differ. diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent" - tools:context=".MainActivity"> - - <WebView - android:layout_width="match_parent" - android:layout_height="match_parent" /> -</androidx.coordinatorlayout.widget.CoordinatorLayout> diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@color/ic_launcher_background"/> - <foreground android:drawable="@mipmap/ic_launcher_foreground"/> -</adaptive-icon> -\ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@color/ic_launcher_background"/> - <foreground android:drawable="@mipmap/ic_launcher_foreground"/> -</adaptive-icon> -\ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png Binary files differ. diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png Binary files differ. diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - <color name="ic_launcher_background">#FFFFFF</color> -</resources> -\ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml @@ -1,7 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_name">Radroots</string> - <string name="title_activity_main">Radroots</string> - <string name="package_name">chroma.radroots.ios</string> - <string name="custom_url_scheme">chroma.radroots.ios</string> -</resources> diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - - <!-- Base application theme. --> - <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> - <!-- Customize your theme here. --> - <item name="colorPrimary">@color/colorPrimary</item> - <item name="colorPrimaryDark">@color/colorPrimaryDark</item> - <item name="colorAccent">@color/colorAccent</item> - </style> - - <style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar"> - <item name="windowActionBar">false</item> - <item name="windowNoTitle">true</item> - <item name="android:background">@null</item> - </style> - - - <style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen"> - <item name="android:background">@drawable/splash</item> - </style> -</resources> -\ No newline at end of file diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<paths xmlns:android="http://schemas.android.com/apk/res/android"> - <external-path name="my_images" path="." /> - <cache-path name="my_cache_images" path="." /> -</paths> -\ No newline at end of file diff --git a/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java @@ -1,18 +0,0 @@ -package com.getcapacitor.myapp; - -import static org.junit.Assert.*; - -import org.junit.Test; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> - */ -public class ExampleUnitTest { - - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} diff --git a/android/build.gradle b/android/build.gradle @@ -1,29 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:8.2.1' - classpath 'com.google.gms:google-services:4.4.0' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -apply from: "variables.gradle" - -allprojects { - repositories { - google() - mavenCentral() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle @@ -1,42 +0,0 @@ -// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN -include ':capacitor-android' -project(':capacitor-android').projectDir = new File('../../../node_modules/.pnpm/@capacitor+android@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/android/capacitor') - -include ':capacitor-browser' -project(':capacitor-browser').projectDir = new File('../../../node_modules/.pnpm/@capacitor+browser@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/browser/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-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-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') - -include ':capacitor-haptics' -project(':capacitor-haptics').projectDir = new File('../../../node_modules/.pnpm/@capacitor+haptics@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/haptics/android') - -include ':capacitor-preferences' -project(':capacitor-preferences').projectDir = new File('../../../node_modules/.pnpm/@capacitor+preferences@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/preferences/android') - -include ':capacitor-share' -project(':capacitor-share').projectDir = new File('../../../node_modules/.pnpm/@capacitor+share@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/share/android') - -include ':capacitor-splash-screen' -project(':capacitor-splash-screen').projectDir = new File('../../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen/android') - -include ':capacitor-status-bar' -project(':capacitor-status-bar').projectDir = new File('../../../node_modules/.pnpm/@capacitor+status-bar@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/status-bar/android') - -include ':radroots-capacitor-native-settings' -project(':radroots-capacitor-native-settings').projectDir = new File('../../../packages/capacitor-native-settings/android') - -include ':radroots-capacitor-secure-storage' -project(':radroots-capacitor-secure-storage').projectDir = new File('../../../packages/capacitor-secure-storage/android') - -include ':radroots-capacitor-sqlite' -project(':radroots-capacitor-sqlite').projectDir = new File('../../../packages/capacitor-sqlite/android') - -include ':radroots-capacitor-wifi' -project(':radroots-capacitor-wifi').projectDir = new File('../../../packages/capacitor-wifi/android') diff --git a/android/gradle.properties b/android/gradle.properties @@ -1,22 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar Binary files differ. diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew @@ -1,248 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/android/settings.gradle b/android/settings.gradle @@ -1,5 +0,0 @@ -include ':app' -include ':capacitor-cordova-android-plugins' -project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') - -apply from: 'capacitor.settings.gradle' -\ No newline at end of file diff --git a/android/variables.gradle b/android/variables.gradle @@ -1,16 +0,0 @@ -ext { - minSdkVersion = 22 - compileSdkVersion = 34 - targetSdkVersion = 34 - androidxActivityVersion = '1.8.0' - androidxAppCompatVersion = '1.6.1' - androidxCoordinatorLayoutVersion = '1.2.0' - androidxCoreVersion = '1.12.0' - androidxFragmentVersion = '1.6.2' - coreSplashScreenVersion = '1.0.1' - androidxWebkitVersion = '1.9.0' - junitVersion = '4.13.2' - androidxJunitVersion = '1.1.5' - androidxEspressoCoreVersion = '3.5.1' - cordovaAndroidVersion = '10.1.1' -} -\ No newline at end of file diff --git a/capacitor.config.ts b/capacitor.config.ts @@ -1,33 +0,0 @@ -import type { CapacitorConfig } from '@capacitor/cli'; - -const dev = process.env.NODE_ENV === `dev`; -const port = process.env.RADROOTS_APP_PORT ? Number(process.env.RADROOTS_APP_PORT) : 3000; -const iosKeychainPrefix = process.env.RADROOTS_APP_SQLITE_KEYCHAIN_PREFIX; -if (!iosKeychainPrefix) throw new Error('Error: iosKeychainPrefix is required'); -const iosDatabaseLocation = process.env.RADROOTS_APP_SQLITE_DATABASE_LOCATION; -if (!iosDatabaseLocation) throw new Error('Error: iosDatabaseLocation is required'); - -const config: CapacitorConfig = { - appId: process.env.RADROOTS_APP_ID, - appName: 'Radroots', - webDir: 'build', - server: { - url: dev ? `http://localhost:${port}` : undefined, - cleartext: dev ? true : false, - iosScheme: `radroots`, - androidScheme: `radroots`, - }, - plugins: { - SplashScreen: { - launchAutoHide: false, - }, - CapacitorSQLite: { - iosDatabaseLocation, - iosIsEncryption: true, - iosKeychainPrefix, - androidIsEncryption: true, - } - } -}; - -export default config; diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "radroots_core" +version = "0.0.1" +license = "GPLv3" +edition = "2021" + +[dependencies] +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio"] } +thiserror = "1.0.64" +uuid = { version = "1", features = ["v4"] } +chrono = "0.4" +regex = "1.11.0" +futures = "0.3.31" +\ No newline at end of file diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs @@ -0,0 +1,39 @@ +use thiserror::Error; + +#[derive(Error, Debug, Clone)] +pub enum ModelError { + #[error("Invalid argument: {0}")] + InvalidArgument(String), + #[error("{0} not found")] + NotFound(String), + #[error("Serialization error: {0}")] + SerializationError(String), + #[error("Invalid query: {0}")] + InvalidQuery(String), + #[error("Internal error")] + Internal, +} + +impl From<ModelError> for String { + fn from(err: ModelError) -> Self { + err.to_string() + } +} + +#[derive(Error, Debug, Clone)] +pub enum KeyringError { + #[error("Internal error")] + Internal, + #[error("Keyring error: {0}")] + KeyringError(String), + #[error("Parsing error: {0}")] + ParsingError(String), + #[error("Missing secret key")] + MissingSecretKey, +} + +impl From<KeyringError> for String { + fn from(err: KeyringError) -> Self { + err.to_string() + } +} diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs @@ -0,0 +1,4 @@ +pub mod error; +pub mod models; +pub mod types; +pub mod utils; diff --git a/crates/core/src/models/location_gcs.rs b/crates/core/src/models/location_gcs.rs @@ -0,0 +1,288 @@ +use crate::{ + error::ModelError, + types::{IModelsId, IModelsQueryBindValue, IModelsQueryBindValueTuple, IModelsResults}, + utils::{time_created_on, uuidv4}, +}; +use futures::TryStreamExt; + +#[derive(Debug, serde::Serialize, serde::Deserialize, sqlx::FromRow)] +pub struct LocationGcs { + id: String, + created_at: String, + updated_at: String, + lat: f64, + lng: f64, + geohash: String, + label: Option<String>, + gc_id: Option<String>, + gc_name: Option<String>, + gc_admin1_id: Option<String>, + gc_admin1_name: Option<String>, + gc_country_id: Option<String>, + gc_country_name: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ILocationGcsFields { + pub lat: String, + pub lng: String, + pub geohash: String, + pub label: Option<String>, + pub gc_id: Option<String>, + pub gc_name: Option<String>, + pub gc_admin1_id: Option<String>, + pub gc_admin1_name: Option<String>, + pub gc_country_id: Option<String>, + pub gc_country_name: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ILocationGcsFieldsUpdate { + pub lat: Option<String>, + pub lng: Option<String>, + pub geohash: Option<String>, + pub label: Option<String>, + pub gc_id: Option<String>, + pub gc_name: Option<String>, + pub gc_admin1_id: Option<String>, + pub gc_admin1_name: Option<String>, + pub gc_country_id: Option<String>, + pub gc_country_name: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum LocationGcsSort { + Newest, + Oldest, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum LocationGcsQueryBindValues { + Id(IModelsQueryBindValue), + Geohash(IModelsQueryBindValue), +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ILocationGcsQueryGetList { + pub of: Vec<String>, + pub sort: Option<LocationGcsSort>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ILocationGcsQueryGet { + pub on: Option<LocationGcsQueryBindValues>, + pub list: Option<ILocationGcsQueryGetList>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ILocationGcsQueryUpdate { + pub on: LocationGcsQueryBindValues, + pub fields: ILocationGcsFieldsUpdate, +} + +impl ILocationGcsQueryGet { + pub fn new_on(values: LocationGcsQueryBindValues) -> Self { + ILocationGcsQueryGet { + on: Some(values), + list: None, + } + } + pub fn new_list(list: ILocationGcsQueryGetList) -> Self { + ILocationGcsQueryGet { + on: None, + list: Some(list), + } + } +} + +pub type ILocationGcsAdd = ILocationGcsFields; +pub type ILocationGcsAddResolve = IModelsId; +pub type ILocationGcsGet = ILocationGcsQueryGet; +pub type ILocationGcsGetResolve = IModelsResults<LocationGcs>; +pub type ILocationGcsDelete = LocationGcsQueryBindValues; +pub type ILocationGcsDeleteResolve = (); +pub type ILocationGcsUpdate = ILocationGcsQueryUpdate; +pub type ILocationGcsUpdateResolve = (); + +fn location_gcs_query_bind_values(opts: LocationGcsQueryBindValues) -> IModelsQueryBindValueTuple { + match opts { + LocationGcsQueryBindValues::Id(id) => ("id".to_string(), id), + LocationGcsQueryBindValues::Geohash(geohash) => ("geohash".to_string(), geohash), + } +} + +fn location_gcs_fields_bind_values( + opts: ILocationGcsFields, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +fn location_gcs_fields_update_bind_values( + opts: ILocationGcsFieldsUpdate, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +pub async fn lib_model_location_gcs_add( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ILocationGcsAdd, +) -> Result<ILocationGcsAddResolve, ModelError> { + let id = uuidv4(); + let created_at = time_created_on(); + let updated_at = created_at.clone(); + let bind_values = location_gcs_fields_bind_values(opts) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let mut query_col = vec![ + "id".to_string(), + "created_at".to_string(), + "updated_at".to_string(), + ]; + let mut query_pl = vec!["?1".to_string(), "?2".to_string(), "?3".to_string()]; + let mut query_vals: Vec<String> = vec![id.to_string(), created_at.clone(), updated_at.clone()]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len())); + query_vals.push(v.clone()); + } + let query = format!( + "INSERT INTO location_gcs ({}) VALUES ({});", + query_col.join(", "), + query_pl.join(", ") + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsId { id }) +} + +fn location_gcs_query_get( + opts: ILocationGcsGet, +) -> Result<(String, Vec<IModelsQueryBindValue>), ModelError> { + match opts { + ILocationGcsQueryGet { + list: Some(opts_list), + .. + } => { + let sort = match opts_list.sort { + Some(LocationGcsSort::Newest) => "created_at DESC", + Some(LocationGcsSort::Oldest) => "created_at ASC", + None => "created_at DESC", + }; + let query = format!("SELECT * FROM location_gcs ORDER BY {};", sort); + Ok((query, vec![])) + } + ILocationGcsQueryGet { + on: Some(opts_on), .. + } => { + let (bv_k, bv) = location_gcs_query_bind_values(opts_on); + let query = format!("SELECT * FROM location_gcs WHERE {} = ?1;", bv_k); + Ok((query, vec![bv])) + } + _ => Err(ModelError::InvalidQuery( + "model.location_gcs.error.query_invalid".to_string(), + )), + } +} + +pub async fn lib_model_location_gcs_get( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ILocationGcsQueryGet, +) -> Result<ILocationGcsGetResolve, ModelError> { + let (query, bind_values) = location_gcs_query_get(opts)?; + let mut query_builder = sqlx::query_as::<_, LocationGcs>(&query); + for value in bind_values.iter() { + query_builder = query_builder.bind(value); + } + let results = query_builder + .fetch(db) + .try_collect() + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsResults { results }) +} + +pub async fn lib_model_location_gcs_delete( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ILocationGcsDelete, +) -> Result<ILocationGcsDeleteResolve, ModelError> { + let (bv_k, bv) = location_gcs_query_bind_values(opts); + let query = format!("DELETE FROM location_gcs WHERE {} = ?1;", bv_k); + let result = sqlx::query(&query) + .bind(bv) + .execute(db) + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} + +pub async fn lib_model_location_gcs_update( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ILocationGcsUpdate, +) -> Result<ILocationGcsUpdateResolve, ModelError> { + let (bv_k, bv) = location_gcs_query_bind_values(opts.on); + let bind_values = location_gcs_fields_update_bind_values(opts.fields) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let updated_at = time_created_on(); + let mut query_col = vec!["updated_at".to_string()]; + let mut query_pl = vec!["?2".to_string()]; + let mut query_vals = vec![bv, updated_at]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len() + 1)); + query_vals.push(v.clone()); + } + let query = format!( + "UPDATE location_gcs SET {} WHERE {} = ?1;", + query_col + .iter() + .enumerate() + .map(|(i, col)| format!("{} = {}", col, query_pl[i])) + .collect::<Vec<_>>() + .join(", "), + bv_k + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + let result = query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} diff --git a/crates/core/src/models/mod.rs b/crates/core/src/models/mod.rs @@ -0,0 +1,4 @@ +pub mod location_gcs; +pub mod trade_product; +pub mod nostr_profile; +pub mod nostr_relay; diff --git a/crates/core/src/models/nostr_profile.rs b/crates/core/src/models/nostr_profile.rs @@ -0,0 +1,288 @@ +use crate::{ + error::ModelError, + types::{IModelsId, IModelsQueryBindValue, IModelsQueryBindValueTuple, IModelsResults}, + utils::{time_created_on, uuidv4}, +}; +use futures::TryStreamExt; + +#[derive(Debug, serde::Serialize, serde::Deserialize, sqlx::FromRow)] +pub struct NostrProfile { + id: String, + created_at: String, + updated_at: String, + public_key: String, + name: Option<String>, + display_name: Option<String>, + about: Option<String>, + website: Option<String>, + picture: Option<String>, + banner: Option<String>, + nip05: Option<String>, + lud06: Option<String>, + lud16: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrProfileFields { + pub public_key: String, + pub name: Option<String>, + pub display_name: Option<String>, + pub about: Option<String>, + pub website: Option<String>, + pub picture: Option<String>, + pub banner: Option<String>, + pub nip05: Option<String>, + pub lud06: Option<String>, + pub lud16: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrProfileFieldsUpdate { + pub public_key: Option<String>, + pub name: Option<String>, + pub display_name: Option<String>, + pub about: Option<String>, + pub website: Option<String>, + pub picture: Option<String>, + pub banner: Option<String>, + pub nip05: Option<String>, + pub lud06: Option<String>, + pub lud16: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum NostrProfileSort { + Newest, + Oldest, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum NostrProfileQueryBindValues { + Id(IModelsQueryBindValue), + PublicKey(IModelsQueryBindValue), +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrProfileQueryGetList { + pub of: Vec<String>, + pub sort: Option<NostrProfileSort>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrProfileQueryGet { + pub on: Option<NostrProfileQueryBindValues>, + pub list: Option<INostrProfileQueryGetList>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrProfileQueryUpdate { + pub on: NostrProfileQueryBindValues, + pub fields: INostrProfileFieldsUpdate, +} + +impl INostrProfileQueryGet { + pub fn new_on(values: NostrProfileQueryBindValues) -> Self { + INostrProfileQueryGet { + on: Some(values), + list: None, + } + } + pub fn new_list(list: INostrProfileQueryGetList) -> Self { + INostrProfileQueryGet { + on: None, + list: Some(list), + } + } +} + +pub type INostrProfileAdd = INostrProfileFields; +pub type INostrProfileAddResolve = IModelsId; +pub type INostrProfileGet = INostrProfileQueryGet; +pub type INostrProfileGetResolve = IModelsResults<NostrProfile>; +pub type INostrProfileDelete = NostrProfileQueryBindValues; +pub type INostrProfileDeleteResolve = (); +pub type INostrProfileUpdate = INostrProfileQueryUpdate; +pub type INostrProfileUpdateResolve = (); + +fn nostr_profile_query_bind_values(opts: NostrProfileQueryBindValues) -> IModelsQueryBindValueTuple { + match opts { + NostrProfileQueryBindValues::Id(id) => ("id".to_string(), id), + NostrProfileQueryBindValues::PublicKey(public_key) => ("public_key".to_string(), public_key), + } +} + +fn nostr_profile_fields_bind_values( + opts: INostrProfileFields, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +fn nostr_profile_fields_update_bind_values( + opts: INostrProfileFieldsUpdate, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +pub async fn lib_model_nostr_profile_add( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrProfileAdd, +) -> Result<INostrProfileAddResolve, ModelError> { + let id = uuidv4(); + let created_at = time_created_on(); + let updated_at = created_at.clone(); + let bind_values = nostr_profile_fields_bind_values(opts) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let mut query_col = vec![ + "id".to_string(), + "created_at".to_string(), + "updated_at".to_string(), + ]; + let mut query_pl = vec!["?1".to_string(), "?2".to_string(), "?3".to_string()]; + let mut query_vals: Vec<String> = vec![id.to_string(), created_at.clone(), updated_at.clone()]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len())); + query_vals.push(v.clone()); + } + let query = format!( + "INSERT INTO nostr_profile ({}) VALUES ({});", + query_col.join(", "), + query_pl.join(", ") + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsId { id }) +} + +fn nostr_profile_query_get( + opts: INostrProfileGet, +) -> Result<(String, Vec<IModelsQueryBindValue>), ModelError> { + match opts { + INostrProfileQueryGet { + list: Some(opts_list), + .. + } => { + let sort = match opts_list.sort { + Some(NostrProfileSort::Newest) => "created_at DESC", + Some(NostrProfileSort::Oldest) => "created_at ASC", + None => "created_at DESC", + }; + let query = format!("SELECT * FROM nostr_profile ORDER BY {};", sort); + Ok((query, vec![])) + } + INostrProfileQueryGet { + on: Some(opts_on), .. + } => { + let (bv_k, bv) = nostr_profile_query_bind_values(opts_on); + let query = format!("SELECT * FROM nostr_profile WHERE {} = ?1;", bv_k); + Ok((query, vec![bv])) + } + _ => Err(ModelError::InvalidQuery( + "model.nostr_profile.error.query_invalid".to_string(), + )), + } +} + +pub async fn lib_model_nostr_profile_get( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrProfileQueryGet, +) -> Result<INostrProfileGetResolve, ModelError> { + let (query, bind_values) = nostr_profile_query_get(opts)?; + let mut query_builder = sqlx::query_as::<_, NostrProfile>(&query); + for value in bind_values.iter() { + query_builder = query_builder.bind(value); + } + let results = query_builder + .fetch(db) + .try_collect() + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsResults { results }) +} + +pub async fn lib_model_nostr_profile_delete( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrProfileDelete, +) -> Result<INostrProfileDeleteResolve, ModelError> { + let (bv_k, bv) = nostr_profile_query_bind_values(opts); + let query = format!("DELETE FROM nostr_profile WHERE {} = ?1;", bv_k); + let result = sqlx::query(&query) + .bind(bv) + .execute(db) + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} + +pub async fn lib_model_nostr_profile_update( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrProfileUpdate, +) -> Result<INostrProfileUpdateResolve, ModelError> { + let (bv_k, bv) = nostr_profile_query_bind_values(opts.on); + let bind_values = nostr_profile_fields_update_bind_values(opts.fields) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let updated_at = time_created_on(); + let mut query_col = vec!["updated_at".to_string()]; + let mut query_pl = vec!["?2".to_string()]; + let mut query_vals = vec![bv, updated_at]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len() + 1)); + query_vals.push(v.clone()); + } + let query = format!( + "UPDATE nostr_profile SET {} WHERE {} = ?1;", + query_col + .iter() + .enumerate() + .map(|(i, col)| format!("{} = {}", col, query_pl[i])) + .collect::<Vec<_>>() + .join(", "), + bv_k + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + let result = query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} diff --git a/crates/core/src/models/nostr_relay.rs b/crates/core/src/models/nostr_relay.rs @@ -0,0 +1,288 @@ +use crate::{ + error::ModelError, + types::{IModelsId, IModelsQueryBindValue, IModelsQueryBindValueTuple, IModelsResults}, + utils::{time_created_on, uuidv4}, +}; +use futures::TryStreamExt; + +#[derive(Debug, serde::Serialize, serde::Deserialize, sqlx::FromRow)] +pub struct NostrRelay { + id: String, + created_at: String, + updated_at: String, + url: String, + relay_id: Option<String>, + name: Option<String>, + description: Option<String>, + pubkey: Option<String>, + contact: Option<String>, + supported_nips: Option<String>, + software: Option<String>, + version: Option<String>, + data: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrRelayFields { + pub url: String, + pub relay_id: Option<String>, + pub name: Option<String>, + pub description: Option<String>, + pub pubkey: Option<String>, + pub contact: Option<String>, + pub supported_nips: Option<String>, + pub software: Option<String>, + pub version: Option<String>, + pub data: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrRelayFieldsUpdate { + pub url: Option<String>, + pub relay_id: Option<String>, + pub name: Option<String>, + pub description: Option<String>, + pub pubkey: Option<String>, + pub contact: Option<String>, + pub supported_nips: Option<String>, + pub software: Option<String>, + pub version: Option<String>, + pub data: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum NostrRelaySort { + Newest, + Oldest, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum NostrRelayQueryBindValues { + Id(IModelsQueryBindValue), + Url(IModelsQueryBindValue), +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrRelayQueryGetList { + pub of: Vec<String>, + pub sort: Option<NostrRelaySort>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrRelayQueryGet { + pub on: Option<NostrRelayQueryBindValues>, + pub list: Option<INostrRelayQueryGetList>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct INostrRelayQueryUpdate { + pub on: NostrRelayQueryBindValues, + pub fields: INostrRelayFieldsUpdate, +} + +impl INostrRelayQueryGet { + pub fn new_on(values: NostrRelayQueryBindValues) -> Self { + INostrRelayQueryGet { + on: Some(values), + list: None, + } + } + pub fn new_list(list: INostrRelayQueryGetList) -> Self { + INostrRelayQueryGet { + on: None, + list: Some(list), + } + } +} + +pub type INostrRelayAdd = INostrRelayFields; +pub type INostrRelayAddResolve = IModelsId; +pub type INostrRelayGet = INostrRelayQueryGet; +pub type INostrRelayGetResolve = IModelsResults<NostrRelay>; +pub type INostrRelayDelete = NostrRelayQueryBindValues; +pub type INostrRelayDeleteResolve = (); +pub type INostrRelayUpdate = INostrRelayQueryUpdate; +pub type INostrRelayUpdateResolve = (); + +fn nostr_relay_query_bind_values(opts: NostrRelayQueryBindValues) -> IModelsQueryBindValueTuple { + match opts { + NostrRelayQueryBindValues::Id(id) => ("id".to_string(), id), + NostrRelayQueryBindValues::Url(url) => ("url".to_string(), url), + } +} + +fn nostr_relay_fields_bind_values( + opts: INostrRelayFields, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +fn nostr_relay_fields_update_bind_values( + opts: INostrRelayFieldsUpdate, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +pub async fn lib_model_nostr_relay_add( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrRelayAdd, +) -> Result<INostrRelayAddResolve, ModelError> { + let id = uuidv4(); + let created_at = time_created_on(); + let updated_at = created_at.clone(); + let bind_values = nostr_relay_fields_bind_values(opts) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let mut query_col = vec![ + "id".to_string(), + "created_at".to_string(), + "updated_at".to_string(), + ]; + let mut query_pl = vec!["?1".to_string(), "?2".to_string(), "?3".to_string()]; + let mut query_vals: Vec<String> = vec![id.to_string(), created_at.clone(), updated_at.clone()]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len())); + query_vals.push(v.clone()); + } + let query = format!( + "INSERT INTO nostr_relay ({}) VALUES ({});", + query_col.join(", "), + query_pl.join(", ") + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsId { id }) +} + +fn nostr_relay_query_get( + opts: INostrRelayGet, +) -> Result<(String, Vec<IModelsQueryBindValue>), ModelError> { + match opts { + INostrRelayQueryGet { + list: Some(opts_list), + .. + } => { + let sort = match opts_list.sort { + Some(NostrRelaySort::Newest) => "created_at DESC", + Some(NostrRelaySort::Oldest) => "created_at ASC", + None => "created_at DESC", + }; + let query = format!("SELECT * FROM nostr_relay ORDER BY {};", sort); + Ok((query, vec![])) + } + INostrRelayQueryGet { + on: Some(opts_on), .. + } => { + let (bv_k, bv) = nostr_relay_query_bind_values(opts_on); + let query = format!("SELECT * FROM nostr_relay WHERE {} = ?1;", bv_k); + Ok((query, vec![bv])) + } + _ => Err(ModelError::InvalidQuery( + "model.nostr_relay.error.query_invalid".to_string(), + )), + } +} + +pub async fn lib_model_nostr_relay_get( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrRelayQueryGet, +) -> Result<INostrRelayGetResolve, ModelError> { + let (query, bind_values) = nostr_relay_query_get(opts)?; + let mut query_builder = sqlx::query_as::<_, NostrRelay>(&query); + for value in bind_values.iter() { + query_builder = query_builder.bind(value); + } + let results = query_builder + .fetch(db) + .try_collect() + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsResults { results }) +} + +pub async fn lib_model_nostr_relay_delete( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrRelayDelete, +) -> Result<INostrRelayDeleteResolve, ModelError> { + let (bv_k, bv) = nostr_relay_query_bind_values(opts); + let query = format!("DELETE FROM nostr_relay WHERE {} = ?1;", bv_k); + let result = sqlx::query(&query) + .bind(bv) + .execute(db) + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} + +pub async fn lib_model_nostr_relay_update( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: INostrRelayUpdate, +) -> Result<INostrRelayUpdateResolve, ModelError> { + let (bv_k, bv) = nostr_relay_query_bind_values(opts.on); + let bind_values = nostr_relay_fields_update_bind_values(opts.fields) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let updated_at = time_created_on(); + let mut query_col = vec!["updated_at".to_string()]; + let mut query_pl = vec!["?2".to_string()]; + let mut query_vals = vec![bv, updated_at]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len() + 1)); + query_vals.push(v.clone()); + } + let query = format!( + "UPDATE nostr_relay SET {} WHERE {} = ?1;", + query_col + .iter() + .enumerate() + .map(|(i, col)| format!("{} = {}", col, query_pl[i])) + .collect::<Vec<_>>() + .join(", "), + bv_k + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + let result = query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} diff --git a/crates/core/src/models/trade_product.rs b/crates/core/src/models/trade_product.rs @@ -0,0 +1,304 @@ +use crate::{ + error::ModelError, + types::{IModelsId, IModelsQueryBindValue, IModelsQueryBindValueTuple, IModelsResults}, + utils::{time_created_on, uuidv4}, +}; +use futures::TryStreamExt; + +#[derive(Debug, serde::Serialize, serde::Deserialize, sqlx::FromRow)] +pub struct TradeProduct { + id: String, + created_at: String, + updated_at: String, + key: String, + title: String, + summary: String, + process: Option<String>, + lot: Option<String>, + profile: Option<String>, + year: i32, + qty_amt: i32, + qty_unit: String, + qty_label: String, + qty_avail: i32, + price_amt: f64, + price_currency: String, + price_qty_amt: i32, + price_qty_unit: String, + notes: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ITradeProductFields { + pub key: String, + pub title: String, + pub summary: String, + pub process: Option<String>, + pub lot: Option<String>, + pub profile: Option<String>, + pub year: String, + pub qty_amt: String, + pub qty_unit: String, + pub qty_label: String, + pub qty_avail: String, + pub price_amt: String, + pub price_currency: String, + pub price_qty_amt: String, + pub price_qty_unit: String, + pub notes: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ITradeProductFieldsUpdate { + pub key: Option<String>, + pub title: Option<String>, + pub summary: Option<String>, + pub process: Option<String>, + pub lot: Option<String>, + pub profile: Option<String>, + pub year: Option<String>, + pub qty_amt: Option<String>, + pub qty_unit: Option<String>, + pub qty_label: Option<String>, + pub qty_avail: Option<String>, + pub price_amt: Option<String>, + pub price_currency: Option<String>, + pub price_qty_amt: Option<String>, + pub price_qty_unit: Option<String>, + pub notes: Option<String>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum TradeProductSort { + Newest, + Oldest, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub enum TradeProductQueryBindValues { + Id(IModelsQueryBindValue), +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ITradeProductQueryGetList { + pub of: Vec<String>, + pub sort: Option<TradeProductSort>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ITradeProductQueryGet { + pub on: Option<TradeProductQueryBindValues>, + pub list: Option<ITradeProductQueryGetList>, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ITradeProductQueryUpdate { + pub on: TradeProductQueryBindValues, + pub fields: ITradeProductFieldsUpdate, +} + +impl ITradeProductQueryGet { + pub fn new_on(values: TradeProductQueryBindValues) -> Self { + ITradeProductQueryGet { + on: Some(values), + list: None, + } + } + pub fn new_list(list: ITradeProductQueryGetList) -> Self { + ITradeProductQueryGet { + on: None, + list: Some(list), + } + } +} + +pub type ITradeProductAdd = ITradeProductFields; +pub type ITradeProductAddResolve = IModelsId; +pub type ITradeProductGet = ITradeProductQueryGet; +pub type ITradeProductGetResolve = IModelsResults<TradeProduct>; +pub type ITradeProductDelete = TradeProductQueryBindValues; +pub type ITradeProductDeleteResolve = (); +pub type ITradeProductUpdate = ITradeProductQueryUpdate; +pub type ITradeProductUpdateResolve = (); + +fn trade_product_query_bind_values(opts: TradeProductQueryBindValues) -> IModelsQueryBindValueTuple { + match opts { + TradeProductQueryBindValues::Id(id) => ("id".to_string(), id), + } +} + +fn trade_product_fields_bind_values( + opts: ITradeProductFields, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +fn trade_product_fields_update_bind_values( + opts: ITradeProductFieldsUpdate, +) -> Result<Vec<IModelsQueryBindValueTuple>, ModelError> { + let bind_values = serde_json::to_value(&opts) + .map_err(|err| ModelError::SerializationError(err.to_string()))? + .as_object() + .ok_or_else(|| ModelError::InvalidArgument("model.error.object_invalid".to_string()))? + .iter() + .filter_map(|(key, value)| value.as_str().map(|v| (key.clone(), v.to_string()))) + .collect::<Vec<_>>(); + Ok(bind_values) +} + +pub async fn lib_model_trade_product_add( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ITradeProductAdd, +) -> Result<ITradeProductAddResolve, ModelError> { + let id = uuidv4(); + let created_at = time_created_on(); + let updated_at = created_at.clone(); + let bind_values = trade_product_fields_bind_values(opts) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let mut query_col = vec![ + "id".to_string(), + "created_at".to_string(), + "updated_at".to_string(), + ]; + let mut query_pl = vec!["?1".to_string(), "?2".to_string(), "?3".to_string()]; + let mut query_vals: Vec<String> = vec![id.to_string(), created_at.clone(), updated_at.clone()]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len())); + query_vals.push(v.clone()); + } + let query = format!( + "INSERT INTO trade_product ({}) VALUES ({});", + query_col.join(", "), + query_pl.join(", ") + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsId { id }) +} + +fn trade_product_query_get( + opts: ITradeProductGet, +) -> Result<(String, Vec<IModelsQueryBindValue>), ModelError> { + match opts { + ITradeProductQueryGet { + list: Some(opts_list), + .. + } => { + let sort = match opts_list.sort { + Some(TradeProductSort::Newest) => "created_at DESC", + Some(TradeProductSort::Oldest) => "created_at ASC", + None => "created_at DESC", + }; + let query = format!("SELECT * FROM trade_product ORDER BY {};", sort); + Ok((query, vec![])) + } + ITradeProductQueryGet { + on: Some(opts_on), .. + } => { + let (bv_k, bv) = trade_product_query_bind_values(opts_on); + let query = format!("SELECT * FROM trade_product WHERE {} = ?1;", bv_k); + Ok((query, vec![bv])) + } + _ => Err(ModelError::InvalidQuery( + "model.trade_product.error.query_invalid".to_string(), + )), + } +} + +pub async fn lib_model_trade_product_get( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ITradeProductQueryGet, +) -> Result<ITradeProductGetResolve, ModelError> { + let (query, bind_values) = trade_product_query_get(opts)?; + let mut query_builder = sqlx::query_as::<_, TradeProduct>(&query); + for value in bind_values.iter() { + query_builder = query_builder.bind(value); + } + let results = query_builder + .fetch(db) + .try_collect() + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + Ok(IModelsResults { results }) +} + +pub async fn lib_model_trade_product_delete( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ITradeProductDelete, +) -> Result<ITradeProductDeleteResolve, ModelError> { + let (bv_k, bv) = trade_product_query_bind_values(opts); + let query = format!("DELETE FROM trade_product WHERE {} = ?1;", bv_k); + let result = sqlx::query(&query) + .bind(bv) + .execute(db) + .await + .map_err(|e: sqlx::Error| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} + +pub async fn lib_model_trade_product_update( + db: &sqlx::Pool<sqlx::Sqlite>, + opts: ITradeProductUpdate, +) -> Result<ITradeProductUpdateResolve, ModelError> { + let (bv_k, bv) = trade_product_query_bind_values(opts.on); + let bind_values = trade_product_fields_update_bind_values(opts.fields) + .map_err(|e| ModelError::InvalidArgument(e.to_string()))?; + let updated_at = time_created_on(); + let mut query_col = vec!["updated_at".to_string()]; + let mut query_pl = vec!["?2".to_string()]; + let mut query_vals = vec![bv, updated_at]; + for (k, v) in bind_values.iter() { + query_col.push(k.clone()); + query_pl.push(format!("?{}", query_col.len() + 1)); + query_vals.push(v.clone()); + } + let query = format!( + "UPDATE trade_product SET {} WHERE {} = ?1;", + query_col + .iter() + .enumerate() + .map(|(i, col)| format!("{} = {}", col, query_pl[i])) + .collect::<Vec<_>>() + .join(", "), + bv_k + ); + let mut query_builder = sqlx::query(&query); + for value in query_vals.iter() { + query_builder = query_builder.bind(value); + } + let result = query_builder + .execute(db) + .await + .map_err(|e| ModelError::InvalidQuery(e.to_string()))?; + println!("{:?}", result); + if result.rows_affected() > 0 { + Ok(()) + } else { + Err(ModelError::InvalidQuery( + "models.error.model_not_found".to_string(), + )) + } +} diff --git a/crates/core/src/types.rs b/crates/core/src/types.rs @@ -0,0 +1,12 @@ +pub type IModelsQueryBindValue = String; +pub type IModelsQueryBindValueTuple = (String, IModelsQueryBindValue); + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct IModelsId { + pub id: String, +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct IModelsResults<T> { + pub results: Vec<T>, +} diff --git a/crates/core/src/utils.rs b/crates/core/src/utils.rs @@ -0,0 +1,11 @@ +use chrono::Utc; +use uuid::Uuid; + +pub fn time_created_on() -> String { + let now: chrono::DateTime<Utc> = Utc::now(); + now.to_rfc3339_opts(chrono::SecondsFormat::Millis, true) +} + +pub fn uuidv4() -> String { + Uuid::new_v4().to_string() +} diff --git a/crates/tauri/.gitignore b/crates/tauri/.gitignore @@ -0,0 +1,4 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +/gen/schemas diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "radroots" +version = "0.0.1" +authors = ["Radroots Authors"] +license = "GPLv3" +edition = "2021" +rust-version = "1.77.2" + +[lib] +name = "radroots_lib" +crate-type = ["staticlib", "cdylib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2.0.0-rc", features = [] } + +[dependencies] +env_logger = "0.11.5" +keyring = { version = "3.2.0", features = ["apple-native", "linux-native", "windows-native"] } +log = "0.4" +radroots_core = { path = "../core" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio"] } +tauri = { version = "2.0.0-rc", features = ["protocol-asset"] } +tauri-plugin-dialog = "2.0.0-rc" +tauri-plugin-geolocation = "2.0.0" +tauri-plugin-http = "2.0.0-rc" +tauri-plugin-log = "2.0.0-rc" +tauri-plugin-map-display = { git = "https://github.com/inkibra/tauri-plugins", tag = "@inkibra/tauri-plugin-map-display@0.2.0", package="tauri-plugin-map-display" } +tauri-plugin-notification = "2.0.0-rc" +tauri-plugin-store = "2.0.0-rc" +tauri-plugin-shell = "2.0.0-rc" + +[profile.dev] +incremental = true diff --git a/crates/tauri/Info.ios.plist b/crates/tauri/Info.ios.plist @@ -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>NSLocationWhenInUseUsageDescription</key> + <string>Uses device GPS to read current location.</string> + <key>NFCReaderUsageDescription</key> + <string>Uses device NFC to enable wireless communication.</string> + <key>NSLocationWhenInUseUsageDescription</key> + <string>Uses device mapping features to display and explore locations.</string> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSAllowsArbitraryLoads</key> + <true/> + </dict> + </dict> +</plist> +\ No newline at end of file diff --git a/crates/tauri/build.rs b/crates/tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/crates/tauri/capabilities/default.json b/crates/tauri/capabilities/default.json @@ -0,0 +1,37 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "enables the default permissions", + "windows": [ + "main" + ], + "permissions": [ + "core:default", + "dialog:default", + "geolocation:allow-check-permissions", + "geolocation:allow-get-current-position", + "geolocation:allow-request-permissions", + "geolocation:allow-watch-position", + "geolocation:allow-clear-permissions", + "geolocation:allow-clear-watch", + { + "identifier": "http:default", + "allow": [ + { + "url": "http://localhost" + }, + { + "url": "https://radroots.org" + }, + { + "url": "https://*.radroots.org" + } + ], + "deny": [] + }, + "notification:default", + "store:default", + "shell:allow-open", + "map-display:default" + ] +} +\ No newline at end of file diff --git a/crates/tauri/icons/128x128.png b/crates/tauri/icons/128x128.png Binary files differ. diff --git a/crates/tauri/icons/128x128@2x.png b/crates/tauri/icons/128x128@2x.png Binary files differ. diff --git a/crates/tauri/icons/32x32.png b/crates/tauri/icons/32x32.png Binary files differ. diff --git a/crates/tauri/icons/Square107x107Logo.png b/crates/tauri/icons/Square107x107Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square142x142Logo.png b/crates/tauri/icons/Square142x142Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square150x150Logo.png b/crates/tauri/icons/Square150x150Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square284x284Logo.png b/crates/tauri/icons/Square284x284Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square30x30Logo.png b/crates/tauri/icons/Square30x30Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square310x310Logo.png b/crates/tauri/icons/Square310x310Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square44x44Logo.png b/crates/tauri/icons/Square44x44Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square71x71Logo.png b/crates/tauri/icons/Square71x71Logo.png Binary files differ. diff --git a/crates/tauri/icons/Square89x89Logo.png b/crates/tauri/icons/Square89x89Logo.png Binary files differ. diff --git a/crates/tauri/icons/StoreLogo.png b/crates/tauri/icons/StoreLogo.png Binary files differ. diff --git a/crates/tauri/icons/icon.icns b/crates/tauri/icons/icon.icns Binary files differ. diff --git a/crates/tauri/icons/icon.ico b/crates/tauri/icons/icon.ico Binary files differ. diff --git a/crates/tauri/icons/icon.png b/crates/tauri/icons/icon.png Binary files differ. diff --git a/crates/tauri/migrations/0001_location_gcs.sql b/crates/tauri/migrations/0001_location_gcs.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS location_gcs ( + id CHAR(36) PRIMARY KEY NOT NULL UNIQUE CHECK(length(id) = 36), + created_at DATETIME NOT NULL CHECK(length(created_at) = 24), + updated_at DATETIME NOT NULL CHECK(length(created_at) = 24), + lat FLOAT NOT NULL, + lng FLOAT NOT NULL, + geohash CHAR(12) NOT NULL UNIQUE, + label TEXT, + gc_id TEXT, + gc_name TEXT, + gc_admin1_id TEXT, + gc_admin1_name TEXT, + gc_country_id TEXT, + gc_country_name TEXT +); +\ No newline at end of file diff --git a/crates/tauri/migrations/0002_trade_product.sql b/crates/tauri/migrations/0002_trade_product.sql @@ -0,0 +1,21 @@ +CREATE TABLE IF NOT EXISTS trade_product ( + id CHAR(36) PRIMARY KEY NOT NULL UNIQUE CHECK(length(id) = 36), + created_at DATETIME NOT NULL CHECK(length(created_at) = 24), + updated_at DATETIME NOT NULL CHECK(length(created_at) = 24), + key TEXT, + title TEXT, + summary TEXT, + process TEXT, + lot TEXT, + profile TEXT, + year INTEGER NOT NULL, + qty_amt REAL, + qty_unit CHAR(4) NOT NULL, + qty_label TEXT, + qty_avail INTEGER, + price_amt REAL NOT NULL, + price_currency CHAR(3) NOT NULL, + price_qty_amt REAL, + price_qty_unit CHAR(4) NOT NULL, + notes TEXT +); +\ No newline at end of file diff --git a/crates/tauri/migrations/0003_nostr_profile.sql b/crates/tauri/migrations/0003_nostr_profile.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS nostr_profile ( + id CHAR(36) PRIMARY KEY NOT NULL UNIQUE CHECK(length(id) = 36), + created_at DATETIME NOT NULL CHECK(length(created_at) = 24), + updated_at DATETIME NOT NULL CHECK(length(created_at) = 24), + public_key CHAR(64) NOT NULL CHECK(length(public_key) = 64), + name TEXT, + display_name TEXT, + about TEXT, + website TEXT, + picture TEXT, + banner TEXT, + nip05 TEXT, + lud06 TEXT, + lud16 TEXT +); +\ No newline at end of file diff --git a/crates/tauri/migrations/0004_nostr_relay.sql b/crates/tauri/migrations/0004_nostr_relay.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS nostr_relay ( + id CHAR(36) PRIMARY KEY NOT NULL UNIQUE CHECK(length(id) = 36), + created_at DATETIME NOT NULL CHECK(length(created_at) = 24), + updated_at DATETIME NOT NULL CHECK(length(created_at) = 24), + url TEXT NOT NULL UNIQUE, + relay_id TEXT, + name TEXT, + description TEXT, + pubkey TEXT, + contact TEXT, + supported_nips TEXT, + software TEXT, + version TEXT, + data TEXT +); +\ No newline at end of file diff --git a/crates/tauri/src/database.rs b/crates/tauri/src/database.rs @@ -0,0 +1,30 @@ +use sqlx::sqlite::SqlitePoolOptions; +use std::fs::OpenOptions; +use std::path::PathBuf; + +pub async fn setup_db(data_dir: &PathBuf) -> sqlx::Pool<sqlx::Sqlite> { + let mut path = data_dir.clone(); + match std::fs::create_dir_all(path.clone()) { + Ok(_) => {} + Err(err) => { + panic!("Error resolving databse directory {}", err); + } + }; + path.push("radroots.sqlite"); + let result = OpenOptions::new().create_new(true).write(true).open(&path); + match result { + Ok(_) => println!("Database file created"), + Err(err) => match err.kind() { + std::io::ErrorKind::AlreadyExists => println!("Database file exists"), + _ => { + panic!("Error creating databse file {}", err); + } + }, + } + let db = SqlitePoolOptions::new() + .connect(path.to_str().unwrap()) + .await + .unwrap(); + sqlx::migrate!("./migrations").run(&db).await.unwrap(); + db +} diff --git a/crates/tauri/src/lib.rs b/crates/tauri/src/lib.rs @@ -0,0 +1,73 @@ +mod database; +pub mod models; +mod radroots; + +use database::setup_db; +use models::{ + location_gcs::{ + model_location_gcs_add, model_location_gcs_delete, model_location_gcs_get, + model_location_gcs_update, + }, + nostr_profile::{ + model_nostr_profile_add, model_nostr_profile_delete, model_nostr_profile_get, + model_nostr_profile_update, + }, + nostr_relay::{ + model_nostr_relay_add, model_nostr_relay_delete, model_nostr_relay_get, + model_nostr_relay_update, + }, + trade_product::{ + model_trade_product_add, model_trade_product_delete, model_trade_product_get, + model_trade_product_update, + }, +}; +use radroots::Radroots; +use tauri::Manager; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + env_logger::init(); + + tauri::Builder::default() + .setup(|app| { + tauri::async_runtime::block_on(async move { + let data_dir = app + .handle() + .path() + .app_data_dir() + .expect("Failed to resolve app data dir"); + + let db = setup_db(&data_dir).await; + app.manage(Radroots { db }); + + Ok(()) + }) + }) + .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_geolocation::init()) + .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_notification::init()) + .plugin(tauri_plugin_store::Builder::new().build()) + .plugin(tauri_plugin_map_display::init()) + .invoke_handler(tauri::generate_handler![ + model_location_gcs_add, + model_location_gcs_get, + model_location_gcs_delete, + model_location_gcs_update, + model_trade_product_add, + model_trade_product_get, + model_trade_product_delete, + model_trade_product_update, + model_nostr_profile_add, + model_nostr_profile_get, + model_nostr_profile_delete, + model_nostr_profile_update, + model_nostr_relay_add, + model_nostr_relay_get, + model_nostr_relay_delete, + model_nostr_relay_update, + ]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} diff --git a/crates/tauri/src/main.rs b/crates/tauri/src/main.rs @@ -0,0 +1,6 @@ +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + radroots_lib::run(); +} diff --git a/crates/tauri/src/models/location_gcs.rs b/crates/tauri/src/models/location_gcs.rs @@ -0,0 +1,60 @@ +use crate::radroots::Radroots; +use radroots_core::{ + models::location_gcs::{lib_model_location_gcs_add, ILocationGcsAdd, ILocationGcsAddResolve, lib_model_location_gcs_get, ILocationGcsGet, ILocationGcsGetResolve, lib_model_location_gcs_delete, ILocationGcsDelete, ILocationGcsDeleteResolve, lib_model_location_gcs_update, ILocationGcsUpdate, ILocationGcsUpdateResolve}, +}; + +#[tauri::command] +pub async fn model_location_gcs_add( + state: tauri::State<'_, Radroots>, + opts: ILocationGcsAdd, +) -> Result<ILocationGcsAddResolve, String> { + match lib_model_location_gcs_add(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_location_gcs_get( + state: tauri::State<'_, Radroots>, + opts: ILocationGcsGet, +) -> Result<ILocationGcsGetResolve, String> { + match lib_model_location_gcs_get(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_location_gcs_delete( + state: tauri::State<'_, Radroots>, + opts: ILocationGcsDelete, +) -> Result<ILocationGcsDeleteResolve, String> { + match lib_model_location_gcs_delete(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_location_gcs_update( + state: tauri::State<'_, Radroots>, + opts: ILocationGcsUpdate, +) -> Result<ILocationGcsUpdateResolve, String> { + match lib_model_location_gcs_update(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} diff --git a/crates/tauri/src/models/mod.rs b/crates/tauri/src/models/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod location_gcs; +pub(crate) mod nostr_profile; +pub(crate) mod nostr_relay; +pub(crate) mod trade_product; diff --git a/crates/tauri/src/models/nostr_profile.rs b/crates/tauri/src/models/nostr_profile.rs @@ -0,0 +1,60 @@ +use crate::radroots::Radroots; +use radroots_core::{ + models::nostr_profile::{lib_model_nostr_profile_add, INostrProfileAdd, INostrProfileAddResolve, lib_model_nostr_profile_get, INostrProfileGet, INostrProfileGetResolve, lib_model_nostr_profile_delete, INostrProfileDelete, INostrProfileDeleteResolve, lib_model_nostr_profile_update, INostrProfileUpdate, INostrProfileUpdateResolve}, +}; + +#[tauri::command] +pub async fn model_nostr_profile_add( + state: tauri::State<'_, Radroots>, + opts: INostrProfileAdd, +) -> Result<INostrProfileAddResolve, String> { + match lib_model_nostr_profile_add(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_nostr_profile_get( + state: tauri::State<'_, Radroots>, + opts: INostrProfileGet, +) -> Result<INostrProfileGetResolve, String> { + match lib_model_nostr_profile_get(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_nostr_profile_delete( + state: tauri::State<'_, Radroots>, + opts: INostrProfileDelete, +) -> Result<INostrProfileDeleteResolve, String> { + match lib_model_nostr_profile_delete(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_nostr_profile_update( + state: tauri::State<'_, Radroots>, + opts: INostrProfileUpdate, +) -> Result<INostrProfileUpdateResolve, String> { + match lib_model_nostr_profile_update(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} diff --git a/crates/tauri/src/models/nostr_relay.rs b/crates/tauri/src/models/nostr_relay.rs @@ -0,0 +1,60 @@ +use crate::radroots::Radroots; +use radroots_core::{ + models::nostr_relay::{lib_model_nostr_relay_add, INostrRelayAdd, INostrRelayAddResolve, lib_model_nostr_relay_get, INostrRelayGet, INostrRelayGetResolve, lib_model_nostr_relay_delete, INostrRelayDelete, INostrRelayDeleteResolve, lib_model_nostr_relay_update, INostrRelayUpdate, INostrRelayUpdateResolve}, +}; + +#[tauri::command] +pub async fn model_nostr_relay_add( + state: tauri::State<'_, Radroots>, + opts: INostrRelayAdd, +) -> Result<INostrRelayAddResolve, String> { + match lib_model_nostr_relay_add(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_nostr_relay_get( + state: tauri::State<'_, Radroots>, + opts: INostrRelayGet, +) -> Result<INostrRelayGetResolve, String> { + match lib_model_nostr_relay_get(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_nostr_relay_delete( + state: tauri::State<'_, Radroots>, + opts: INostrRelayDelete, +) -> Result<INostrRelayDeleteResolve, String> { + match lib_model_nostr_relay_delete(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_nostr_relay_update( + state: tauri::State<'_, Radroots>, + opts: INostrRelayUpdate, +) -> Result<INostrRelayUpdateResolve, String> { + match lib_model_nostr_relay_update(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} diff --git a/crates/tauri/src/models/trade_product.rs b/crates/tauri/src/models/trade_product.rs @@ -0,0 +1,60 @@ +use crate::radroots::Radroots; +use radroots_core::{ + models::trade_product::{lib_model_trade_product_add, ITradeProductAdd, ITradeProductAddResolve, lib_model_trade_product_get, ITradeProductGet, ITradeProductGetResolve, lib_model_trade_product_delete, ITradeProductDelete, ITradeProductDeleteResolve, lib_model_trade_product_update, ITradeProductUpdate, ITradeProductUpdateResolve}, +}; + +#[tauri::command] +pub async fn model_trade_product_add( + state: tauri::State<'_, Radroots>, + opts: ITradeProductAdd, +) -> Result<ITradeProductAddResolve, String> { + match lib_model_trade_product_add(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_trade_product_get( + state: tauri::State<'_, Radroots>, + opts: ITradeProductGet, +) -> Result<ITradeProductGetResolve, String> { + match lib_model_trade_product_get(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_trade_product_delete( + state: tauri::State<'_, Radroots>, + opts: ITradeProductDelete, +) -> Result<ITradeProductDeleteResolve, String> { + match lib_model_trade_product_delete(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} + +#[tauri::command] +pub async fn model_trade_product_update( + state: tauri::State<'_, Radroots>, + opts: ITradeProductUpdate, +) -> Result<ITradeProductUpdateResolve, String> { + match lib_model_trade_product_update(&state.db, opts).await { + Ok(result) => Ok(result), + Err(e) => { + println!("ERROR {}", e); + Err(e.to_string()) + } + } +} diff --git a/crates/tauri/src/radroots.rs b/crates/tauri/src/radroots.rs @@ -0,0 +1,3 @@ +pub struct Radroots { + pub db: sqlx::Pool<sqlx::Sqlite>, +} diff --git a/crates/tauri/tauri.conf.json b/crates/tauri/tauri.conf.json @@ -0,0 +1,46 @@ +{ + "$schema": "../../node_modules/@tauri-apps/cli/config.schema.json", + "productName": "Radroots", + "version": "0.0.1", + "identifier": "mobile.radroots.app", + "build": { + "frontendDist": "../../build", + "devUrl": "http://localhost:21640", + "beforeDevCommand": "pnpm run dev:serve", + "beforeBuildCommand": "pnpm run build" + }, + "app": { + "windows": [ + { + "title": "Radroots", + "width": 800, + "height": 600, + "resizable": true, + "fullscreen": false, + "visible": true + } + ], + "security": { + "csp": null, + "assetProtocol": { + "enable": true, + "scope": { + "allow": [ + "**" + ] + } + } + } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] + } +} +\ No newline at end of file diff --git a/ios/.gitignore b/ios/.gitignore @@ -1,13 +0,0 @@ -App/build -App/Pods -App/output -App/App/public -DerivedData -xcuserdata - -# Cordova plugins for Capacitor -capacitor-cordova-ios-plugins - -# Generated Config files -App/App/capacitor.config.json -App/App/config.xml diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj @@ -1,416 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; - 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; - 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; - 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; - 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; - 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 */ - 2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; }; - 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; }; - 504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; - 504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; - 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; - 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; - 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; - 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 */ - -/* Begin PBXFrameworksBuildPhase section */ - 504EC3011FED79650016851F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 27E2DDA53C4D2A4D1A88CE4A /* Frameworks */ = { - isa = PBXGroup; - children = ( - AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; - 504EC2FB1FED79650016851F = { - isa = PBXGroup; - children = ( - C11106062C8353B800B825E4 /* PrivacyInfo.xcprivacy */, - 504EC3061FED79650016851F /* App */, - 504EC3051FED79650016851F /* Products */, - 7F8756D8B27F46E3366F6CEA /* Pods */, - 27E2DDA53C4D2A4D1A88CE4A /* Frameworks */, - ); - sourceTree = "<group>"; - }; - 504EC3051FED79650016851F /* Products */ = { - isa = PBXGroup; - children = ( - 504EC3041FED79650016851F /* App.app */, - ); - name = Products; - sourceTree = "<group>"; - }; - 504EC3061FED79650016851F /* App */ = { - isa = PBXGroup; - children = ( - 50379B222058CBB4000EE86E /* capacitor.config.json */, - 504EC3071FED79650016851F /* AppDelegate.swift */, - 504EC30B1FED79650016851F /* Main.storyboard */, - 504EC30E1FED79650016851F /* Assets.xcassets */, - 504EC3101FED79650016851F /* LaunchScreen.storyboard */, - 504EC3131FED79650016851F /* Info.plist */, - 2FAD9762203C412B000D30F8 /* config.xml */, - 50B271D01FEDC1A000F3C39B /* public */, - ); - path = App; - sourceTree = "<group>"; - }; - 7F8756D8B27F46E3366F6CEA /* Pods */ = { - isa = PBXGroup; - children = ( - FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */, - AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */, - ); - name = Pods; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 504EC3031FED79650016851F /* App */ = { - isa = PBXNativeTarget; - buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */; - buildPhases = ( - 6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */, - 504EC3001FED79650016851F /* Sources */, - 504EC3011FED79650016851F /* Frameworks */, - 504EC3021FED79650016851F /* Resources */, - 9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = App; - productName = App; - productReference = 504EC3041FED79650016851F /* App.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 504EC2FC1FED79650016851F /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0920; - TargetAttributes = { - 504EC3031FED79650016851F = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 504EC2FB1FED79650016851F; - packageReferences = ( - ); - productRefGroup = 504EC3051FED79650016851F /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 504EC3031FED79650016851F /* App */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 504EC3021FED79650016851F /* Resources */ = { - isa = PBXResourcesBuildPhase; - 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 */, - 504EC30D1FED79650016851F /* Main.storyboard in Resources */, - 2FAD9763203C412B000D30F8 /* config.xml in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 504EC3001FED79650016851F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 504EC30B1FED79650016851F /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 504EC30C1FED79650016851F /* Base */, - ); - name = Main.storyboard; - sourceTree = "<group>"; - }; - 504EC3101FED79650016851F /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 504EC3111FED79650016851F /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = "<group>"; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 504EC3141FED79650016851F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 504EC3151FED79650016851F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 504EC3171FED79650016851F /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 29; - DEVELOPMENT_TEAM = AR84X5Z9HU; - INFOPLIST_FILE = App/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = Radroots; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 0.1.5; - OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; - PRODUCT_BUNDLE_IDENTIFIER = chroma.radroots.ios; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 504EC3181FED79650016851F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 29; - DEVELOPMENT_TEAM = AR84X5Z9HU; - INFOPLIST_FILE = App/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = Radroots; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 0.1.5; - PRODUCT_BUNDLE_IDENTIFIER = chroma.radroots.ios; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 504EC3141FED79650016851F /* Debug */, - 504EC3151FED79650016851F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 504EC3171FED79650016851F /* Debug */, - 504EC3181FED79650016851F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 504EC2FC1FED79650016851F /* Project object */; -} diff --git a/ios/App/App.xcworkspace/contents.xcworkspacedata b/ios/App/App.xcworkspace/contents.xcworkspacedata @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Workspace - version = "1.0"> - <FileRef - location = "group:App.xcodeproj"> - </FileRef> - <FileRef - location = "group:Pods/Pods.xcodeproj"> - </FileRef> -</Workspace> diff --git a/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -1,8 +0,0 @@ -<?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>IDEDidComputeMac32BitWarning</key> - <true/> -</dict> -</plist> diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift @@ -1,49 +0,0 @@ -import UIKit -import Capacitor - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { - // Called when the app was launched with a url. Feel free to add additional processing here, - // but if you want the App API to support tracking app url opens, make sure to keep this call - return ApplicationDelegateProxy.shared.application(app, open: url, options: options) - } - - func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - // Called when the app was launched with an activity, including Universal Links. - // Feel free to add additional processing here, but if you want the App API to support - // tracking app url opens, make sure to keep this call - return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) - } - -} diff --git a/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png Binary files differ. diff --git a/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,14 +0,0 @@ -{ - "images" : [ - { - "filename" : "AppIcon-512@2x.png", - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/ios/App/App/Assets.xcassets/Contents.json b/ios/App/App/Assets.xcassets/Contents.json @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} -\ No newline at end of file diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json b/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "splash-2732x2732-2.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "splash-2732x2732-1.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "splash-2732x2732.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} -\ No newline at end of file diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png Binary files differ. diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png Binary files differ. diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png b/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png Binary files differ. diff --git a/ios/App/App/Base.lproj/LaunchScreen.storyboard b/ios/App/App/Base.lproj/LaunchScreen.storyboard @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17132" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> - <device id="retina4_7" orientation="portrait" appearance="light"/> - <dependencies> - <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17105"/> - <capability name="System colors in document resources" minToolsVersion="11.0"/> - <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <scenes> - <!--View Controller--> - <scene sceneID="EHf-IW-A2E"> - <objects> - <viewController id="01J-lp-oVM" sceneMemberID="viewController"> - <imageView key="view" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Splash" id="snD-IY-ifK"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask"/> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> - </imageView> - </viewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="53" y="375"/> - </scene> - </scenes> - <resources> - <image name="Splash" width="1366" height="1366"/> - <systemColor name="systemBackgroundColor"> - <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - </systemColor> - </resources> -</document> diff --git a/ios/App/App/Base.lproj/Main.storyboard b/ios/App/App/Base.lproj/Main.storyboard @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14111" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> - <device id="retina4_7" orientation="portrait"> - <adaptation id="fullscreen"/> - </device> - <dependencies> - <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> - </dependencies> - <scenes> - <!--Bridge View Controller--> - <scene sceneID="tne-QT-ifu"> - <objects> - <viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/> - <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> - </objects> - </scene> - </scenes> -</document> diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist @@ -1,51 +0,0 @@ -<?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>NSLocationWhenInUseUsageDescription</key> - <string>Uses device GPS to read current location.</string> - <key>CFBundleDevelopmentRegion</key> - <string>en</string> - <key>CFBundleDisplayName</key> - <string>Radroots</string> - <key>CFBundleExecutable</key> - <string>$(EXECUTABLE_NAME)</string> - <key>CFBundleIdentifier</key> - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>$(PRODUCT_NAME)</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleShortVersionString</key> - <string>$(MARKETING_VERSION)</string> - <key>CFBundleVersion</key> - <string>$(CURRENT_PROJECT_VERSION)</string> - <key>LSRequiresIPhoneOS</key> - <true/> - <key>UILaunchStoryboardName</key> - <string>LaunchScreen</string> - <key>UIMainStoryboardFile</key> - <string>Main</string> - <key>UIRequiredDeviceCapabilities</key> - <array> - <string>armv7</string> - </array> - <key>UISupportedInterfaceOrientations</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> - <key>UISupportedInterfaceOrientations~ipad</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> - <key>UIViewControllerBasedStatusBarAppearance</key> - <true/> -</dict> -</plist> diff --git a/ios/App/Podfile b/ios/App/Podfile @@ -1,36 +0,0 @@ -require_relative '../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios/scripts/pods_helpers' - -platform :ios, '13.0' -use_frameworks! - -# workaround to avoid Xcode caching of Pods that requires -# Product -> Clean Build Folder after new Cordova plugins installed -# Requires CocoaPods 1.6 or newer -install! 'cocoapods', :disable_input_output_paths => true - -def capacitor_pods - pod 'Capacitor', :path => '../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios' - 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 'CapacitorDevice', :path => '../../../../node_modules/.pnpm/@capacitor+device@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/device' - pod 'CapacitorDialog', :path => '../../../../node_modules/.pnpm/@capacitor+dialog@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/dialog' - 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' - pod 'CapacitorShare', :path => '../../../../node_modules/.pnpm/@capacitor+share@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/share' - pod 'CapacitorSplashScreen', :path => '../../../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen' - pod 'CapacitorStatusBar', :path => '../../../../node_modules/.pnpm/@capacitor+status-bar@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/status-bar' - pod 'RadrootsCapacitorNativeSettings', :path => '../../../../packages/capacitor-native-settings' - pod 'RadrootsCapacitorSecureStorage', :path => '../../../../packages/capacitor-secure-storage' - pod 'RadrootsCapacitorSqlite', :path => '../../../../packages/capacitor-sqlite' - pod 'RadrootsCapacitorWifi', :path => '../../../../packages/capacitor-wifi' -end - -target 'App' do - capacitor_pods - # Add your Pods here -end - -post_install do |installer| - assertDeploymentTarget(installer) -end diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock @@ -1,119 +0,0 @@ -PODS: - - Capacitor (6.1.2): - - CapacitorCordova - - CapacitorBrowser (6.0.2): - - Capacitor - - CapacitorCordova (6.1.2) - - CapacitorDevice (6.0.1): - - Capacitor - - CapacitorDialog (6.0.1): - - Capacitor - - CapacitorGeolocation (6.0.1): - - Capacitor - - CapacitorHaptics (6.0.1): - - Capacitor - - CapacitorPreferences (6.0.2): - - Capacitor - - CapacitorShare (6.0.2): - - Capacitor - - CapacitorSplashScreen (6.0.2): - - Capacitor - - CapacitorStatusBar (6.0.1): - - Capacitor - - KeychainSwift (21.0.0) - - RadrootsCapacitorNativeSettings (6.0.1): - - Capacitor - - RadrootsCapacitorSecureStorage (6.0.1): - - Capacitor - - KeychainSwift (~> 21.0) - - RadrootsCapacitorSqlite (6.0.1): - - Capacitor - - SQLCipher - - ZIPFoundation - - RadrootsCapacitorWifi (0.2.20): - - Capacitor - - SQLCipher (4.6.1): - - SQLCipher/standard (= 4.6.1) - - SQLCipher/common (4.6.1) - - SQLCipher/standard (4.6.1): - - SQLCipher/common - - ZIPFoundation (0.9.19) - -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`)" - - "CapacitorPreferences (from `../../../../node_modules/.pnpm/@capacitor+preferences@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/preferences`)" - - "CapacitorShare (from `../../../../node_modules/.pnpm/@capacitor+share@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/share`)" - - "CapacitorSplashScreen (from `../../../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen`)" - - "CapacitorStatusBar (from `../../../../node_modules/.pnpm/@capacitor+status-bar@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/status-bar`)" - - RadrootsCapacitorNativeSettings (from `../../../../packages/capacitor-native-settings`) - - RadrootsCapacitorSecureStorage (from `../../../../packages/capacitor-secure-storage`) - - RadrootsCapacitorSqlite (from `../../../../packages/capacitor-sqlite`) - - RadrootsCapacitorWifi (from `../../../../packages/capacitor-wifi`) - -SPEC REPOS: - trunk: - - KeychainSwift - - SQLCipher - - ZIPFoundation - -EXTERNAL SOURCES: - Capacitor: - :path: "../../../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios" - CapacitorBrowser: - :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: - :path: "../../../../node_modules/.pnpm/@capacitor+geolocation@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/geolocation" - CapacitorHaptics: - :path: "../../../../node_modules/.pnpm/@capacitor+haptics@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/haptics" - CapacitorPreferences: - :path: "../../../../node_modules/.pnpm/@capacitor+preferences@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/preferences" - CapacitorShare: - :path: "../../../../node_modules/.pnpm/@capacitor+share@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/share" - CapacitorSplashScreen: - :path: "../../../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen" - CapacitorStatusBar: - :path: "../../../../node_modules/.pnpm/@capacitor+status-bar@6.0.1_@capacitor+core@6.1.2/node_modules/@capacitor/status-bar" - RadrootsCapacitorNativeSettings: - :path: "../../../../packages/capacitor-native-settings" - RadrootsCapacitorSecureStorage: - :path: "../../../../packages/capacitor-secure-storage" - RadrootsCapacitorSqlite: - :path: "../../../../packages/capacitor-sqlite" - RadrootsCapacitorWifi: - :path: "../../../../packages/capacitor-wifi" - -SPEC CHECKSUMS: - Capacitor: 679f9673fdf30597493a6362a5d5bf233d46abc2 - CapacitorBrowser: 83ec661a9ccd56c28a6851e4dd1ac33b181227ec - CapacitorCordova: f48c89f96c319101cd2f0ce8a2b7449b5fb8b3dd - CapacitorDevice: 7097a1deb4224b77fd13a6e60a355d0062a5d772 - CapacitorDialog: ad752191fdb22a8d0ac199b0754b8a021d86dbf9 - CapacitorGeolocation: 39dca51d755f08ed1d43e51be55291a402cdc64f - CapacitorHaptics: fe689ade56ef20ec9b041a753c6da70c5d8ec9a9 - CapacitorPreferences: e8284bf740cf8c6d3f25409af3c01df87dfeb5a1 - CapacitorShare: 591ae4693d85686ceb590db8e8b44aa014ec6490 - CapacitorSplashScreen: 250df9ef8014fac5c7c1fd231f0f8b1d8f0b5624 - CapacitorStatusBar: b81d4fb5d4e0064c712018071b3ab4b810b39a63 - KeychainSwift: 4a71a45c802fd9e73906457c2dcbdbdc06c9419d - RadrootsCapacitorNativeSettings: 0c099fd9e4b3ff04cde651e94c4057295066dbeb - RadrootsCapacitorSecureStorage: d95a1648c105ddf18a1b0612528e0ce1f77b789e - RadrootsCapacitorSqlite: 11b1be8786af151612ee8e058d16f4979c2e3b1c - RadrootsCapacitorWifi: b655736c72ac2ed083635544e6ceddb875c01518 - SQLCipher: 77fbe633cd84db04b07876dd50766b4924b57d61 - ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c - -PODFILE CHECKSUM: d735d5f1c8ed8c7099f2bf2d93f8347cd9b2eb64 - -COCOAPODS: 1.15.2 diff --git a/ios/App/PrivacyInfo.xcprivacy b/ios/App/PrivacyInfo.xcprivacy @@ -1,17 +0,0 @@ -<?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 @@ -8,21 +8,22 @@ "build": "vite build --mode production", "prepare:native": "npm run gen", "prepare:web": "npm run gen", - "serve:dev": "vite dev --mode development --debug hmr", - "serve:prod": "vite dev --mode production", + "dev:serve": "vite dev --mode development --debug hmr", + "prod:serve": "vite dev --mode production", "dev": "", "gen": "", - "sql:cp": "rsync -u node_modules/sql.js/dist/sql-wasm.wasm static", - "sql:rm": "rm -rf static/sql-wasm.wasm", + "sql:wasm": "rsync -u node_modules/sql.js/dist/sql-wasm.wasm static", "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "tauri": "tauri" }, "devDependencies": { "@capacitor/cli": "^6.1.2", "@sveltejs/adapter-static": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@tauri-apps/cli": "2.0.0-rc.16", "@types/node": "^20.12.7", "@types/sql.js": "^1.4.9", "autoprefixer": "^10.4.19", @@ -38,26 +39,8 @@ }, "type": "module", "dependencies": { - "@capacitor/android": "^6.1.2", - "@capacitor/browser": "^6.0.0", - "@capacitor/core": "^6.1.2", - "@capacitor/device": "^6.0.0", - "@capacitor/dialog": "^6.0.0", - "@capacitor/geolocation": "^6.0.0", - "@capacitor/haptics": "^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.2.2", "@nostr-dev-kit/ndk": "^2.10.0", - "@nostr-dev-kit/ndk-cache-dexie": "^2.5.1", "@nostr-dev-kit/ndk-svelte": "^2.2.18", - "@radroots/capacitor-native-settings": "workspace:*", - "@radroots/capacitor-secure-storage": "workspace:*", - "@radroots/capacitor-sqlite": "workspace:*", - "@radroots/capacitor-wifi": "workspace:*", "@radroots/client": "workspace:*", "@radroots/geocoder": "workspace:*", "@radroots/models": "workspace:*", @@ -65,11 +48,6 @@ "@radroots/svelte-maplibre": "workspace:*", "@radroots/theme": "workspace:*", "@radroots/utils": "workspace:*", - "jeep-sqlite": "2.7.1", - "loader": "link:@ionic/pwa-elements/loader", - "maplibre-gl": "^4.0.0", - "pmtiles": "^3.0.3", - "protomaps-themes-base": "^3.1.0", "sql.js": "^1.11.0" } } \ No newline at end of file diff --git a/src/app.css b/src/app.css @@ -14,6 +14,11 @@ @tailwind utilities; @layer components { + .map-trellis-1 { + height: 400px; + width: 100%; + } + .tap-rise-1 { @apply active:scale-[101%] group-active:scale-[101%] delay-75 duration-700 ease-in-out transition-all; } @@ -23,13 +28,8 @@ @apply active:scale-[97%] group-active:scale-[97%] delay-75 duration-700 ease-in-out transition-all; } - .map-trellis-1 { - height: 400px; - width: 100%; - } - .touch-layer-1 { - @apply active:bg-layer-1-surface_a/20 group-active:bg-layer-1-surface_a/20; + @apply active:bg-layer-1-surface_a/20 group-active:bg-layer-1-surface_a/20 transition-all; } .touch-layer-1-raise, @@ -44,4 +44,12 @@ .touch-layer-1-raise-less { @apply ring-layer-2-surface/60 active:ring-[0.25rem] group-active:ring-[0.25rem] delay-[50ms] duration-[350ms]; } + + .layer-1-ring { + @apply ring-layer-2-surface/60 ring-[0.3rem] + } + + .layer-1-ring-less { + @apply ring-layer-2-surface/60 ring-[0.25rem] + } } \ No newline at end of file diff --git a/src/app.d.ts b/src/app.d.ts @@ -1,5 +1,137 @@ declare global { namespace App { } + declare class Keyva { + /** + * An IDBKeyRange that has no upper or lower bounding. + */ + static readonly unbound: IDBKeyRange; + /** + * Returns an IDBKeyRange that matches all keys that start + * with the specified string prefix. + */ + static prefix(prefix: string): IDBKeyRange; + /** + * @returns An array of strings that contain the names of all + * Keyva-created IndexedDB databases. + */ + static each(): Promise<string[]>; + /** + * Deletes Keyva-created IndexedDB databases with the + * specified names. + * + * @param names The names of the databases to delete. + * If no names are provided, all Keyva IndexedDB databases + * are deleted. + */ + static delete(...names: string[]): Promise<void>; + /** Stores the prefix that is added to every IndexedDB database created by Keyva. */ + private static readonly kvPrefix; + /** + * Creates a new IndexedDB-backed database + */ + constructor(options?: Keyva.IConstructorOptions); + private readonly indexes; + private readonly name; + /** + * Get a value by its key. + * @param key The key of the value to get. + */ + get<T = any>(key: Keyva.Key): Promise<T>; + /** + * Get a series of values from the keys specified. + * @param keys The key of the value to get. + */ + get<T = any>(keys: Keyva.Key[]): Promise<T[]>; + /** + * Gets all keys and values from the Keyva database. + * @param key The key of the value to get. + */ + each<T = any>(): Promise<[Keyva.Key, T][]>; + /** + * Gets a series of keys and values that match the specified + * set of options. + */ + each<T = any>(options: Keyva.IQuery): Promise<[Keyva.Key, T][]>; + /** + * Gets a series of keys only that match the specified set of options. + */ + each(options: Keyva.IQuery, only: "keys"): Promise<Keyva.Key[]>; + /** + * Gets a series of values only that match the specified set of options. + */ + each<T = any>(options: Keyva.IQuery, only: "values"): Promise<T[]>; + /** + * Set a value with a key. + */ + set(key: Keyva.Key, value: any): Promise<void>; + /** + * Set multiple values at once. This is faster than calling set() multiple times. + * It's also atomic – if one of the pairs can't be added, none will be added. + * @param entries Array of entries, where each entry is an array of `[key, value]`. + */ + set(entries: [Keyva.Key, any][]): Promise<void>; + /** + * Deletes all objects from this Keyva database + * (but keeps the Keyva database itself is kept). + */ + delete(): Promise<void>; + /** + * Delete a single object from the store with the specified key. + */ + delete(range: IDBKeyRange): Promise<void>; + /** + * Delete a single object from the store with the specified key. + */ + delete(key: Keyva.Key): Promise<void>; + /** + * Delete a series of objects from the store at once, with the specified keys. + */ + delete(keys: Keyva.Key[]): Promise<void>; + /** */ + private getStore; + /** */ + private getDatabase; + private database; + /** + * Works around a Safari 14 bug. + * + * Safari has a bug where IDB requests can hang while the browser is + * starting up. https://bugs.webkit.org/show_bug.cgi?id=226547 + * The only solution is to keep nudging it until it's awake. + */ + private maybeFixSafari; + /** */ + private static asPromise; + } + declare namespace Keyva { + /** */ + interface IConstructorOptions { + /** + * Defines the name of the IndexedDB database as it is stored in the browser. + * Note that the name is prefixed with the Keyva database prefix constant. + */ + name?: string | number; + /** + * Defines the name or names of the index or indexes to define on the database. + */ + indexes?: string | string[]; + } + /** */ + interface IQuery { + /** + * A standard IDBKeyRange to use for the query. Worth noting that the methods + * in the static Keyva.* namespace contain utility functions to ease the creation + * of IDBKeyRange objects. + */ + range?: IDBKeyRange; + /** The name of the index to use for the query. */ + index?: string; + /** A number which indicates the maximum number of objects to return from a query. */ + limit?: number; + } + /** */ + type Key = string | number | Date | BufferSource; + } } export { }; diff --git a/src/lib/client.ts b/src/lib/client.ts @@ -1,25 +1,15 @@ -import { PUBLIC_DATABASE_NAME } from "$env/static/public"; -import { ClientCapacitor } from "@radroots/client"; +import { ClientNostr, TauriClientDb, TauriClientDialog, TauriClientGeolocation, TauriClientHaptics, TauriClientHttp, TauriClientKeying, TauriClientKeystore, TauriClientMap, TauriClientNotification, TauriClientWindow } from "@radroots/client"; import { Geocoder } from "@radroots/geocoder"; -import { location_gcs_table, nostr_profile_relay_table, nostr_profile_table, nostr_relay_table, trade_product_table } from "@radroots/models"; - -export const lc = new ClientCapacitor({ - sqlite: { - database: PUBLIC_DATABASE_NAME, - upgrade: [ - { - toVersion: 1, - statements: [ - `PRAGMA foreign_keys = ON;`, - location_gcs_table, - trade_product_table, - nostr_profile_table, - nostr_relay_table, - nostr_profile_relay_table - ] - } - ] - } -}); export const geoc = new Geocoder(`/geonames/geonames.db`); +export const db = new TauriClientDb(); +export const dialog = new TauriClientDialog(); +export const geol = new TauriClientGeolocation(); +export const haptics = new TauriClientHaptics(); +export const http = new TauriClientHttp(); +export const map = new TauriClientMap(); +export const keystore = new TauriClientKeystore(); +export const keyring = new TauriClientKeying(); +export const nostr = new ClientNostr(); +export const notification = new TauriClientNotification(); +export const win = new TauriClientWindow(); +\ No newline at end of file diff --git a/src/lib/components/button-submit.svelte b/src/lib/components/button-submit.svelte @@ -1,24 +0,0 @@ -<script lang="ts"> - import type { CallbackPromise } from "@radroots/svelte-lib"; - import { Loading, t } from "@radroots/svelte-lib"; - - export let basis: { - callback: CallbackPromise; - loading?: boolean; - label?: string; - }; - $: basis = basis; -</script> - -<button - class={`button-submit`} - on:click={async () => { - await basis.callback(); - }} -> - {#if basis.loading} - <Loading basis={{ dim: `xs` }} /> - {:else} - {basis.label || `${$t(`common.submit`, { default: `submit` })}`} - {/if} -</button> diff --git a/src/lib/components/button_appearing_pair.svelte b/src/lib/components/button_appearing_pair.svelte @@ -0,0 +1,61 @@ +<script lang="ts"> + import { + app_layout, + Fill, + t, + type CallbackPromise, + } from "@radroots/svelte-lib"; + + export let basis: { + continue: { + disabled?: boolean; + label?: string; + callback: CallbackPromise; + }; + back?: { + visible: boolean; + disabled?: boolean; + label?: string; + callback: CallbackPromise; + }; + }; +</script> + +<div class={`flex flex-col justify-center items-center`}> + <button + class={`group flex flex-row h-touch_guide w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-touch ${basis.continue.disabled ? `opacity-60` : `touch-layer-1`} transition-all`} + on:click|stopPropagation={async () => { + if (!basis.continue.disabled) await basis.continue.callback(); + }} + > + <p + class={`font-sans font-[600] tracking-wide text-layer-1-glyph/80 ${basis.continue.disabled ? `` : `group-active:text-layer-1-glyph/40 `}transition-all`} + > + {basis.continue.label || `${$t(`common.continue`)}`} + </p> + </button> + {#if basis.back} + <div class={`flex flex-col justify-center items-center transition-all`}> + {#if basis.back?.visible} + <button + class={`group flex flex-row h-12 w-${$app_layout} justify-center items-center fade-in`} + on:click|stopPropagation={async () => { + if (!basis.back?.disabled) await basis.back?.callback(); + }} + > + <p + class={`font-sans font-[600] tracking-wide text-layer-1-glyph-shade ${basis.back?.disabled ? `` : `group-active:text-layer-1-glyph/40`} transition-all`} + > + {basis.back?.label || `${$t(`common.back`)}`} + </p> + </button> + {:else} + <div + class={`flex flex-row h-4 w-full justify-start items-center`} + > + <Fill /> + </div> + {/if} + </div> + {/if} +</div> diff --git a/src/lib/components/map_choose_location.svelte b/src/lib/components/map_choose_location.svelte @@ -1,6 +1,6 @@ <script lang="ts"> import { geoc } from "$lib/client"; - import { _conf } from "$lib/conf"; + import { cfg } from "$lib/conf"; import type { GeocoderReverseResult } from "@radroots/geocoder"; import { app_thc, @@ -51,7 +51,7 @@ center={map_point_center} zoom={10} class={`${basis.classes_map} ${basis.loading ? `hidden` : ``}`} - style={_conf.map.styles.base[$app_thc]} + style={cfg.map.styles.base[$app_thc]} attributionControl={false} > <Marker @@ -69,7 +69,7 @@ > <MapMarkerDot /> <Popup - offset={_conf.map.popup.dot.offset} + offset={cfg.map.popup.dot.offset} open={true} closeOnClickOutside={false} closeButton={false} diff --git a/src/lib/components/map_control_full.svelte b/src/lib/components/map_control_full.svelte @@ -1,34 +0,0 @@ -<script lang="ts"> - import { - Glyph, - app_layout, - type CallbackPromise, - } from "@radroots/svelte-lib"; - - let el_zoom: HTMLElement | null; - - export let basis: { - callback: CallbackPromise; - }; -</script> - -<div - bind:this={el_zoom} - class={`z-10 absolute top-dim_map_offset_top_${$app_layout} left-6 flex flex-col w-full gap-8 justify-start items-start`} -> - <button - class={`flex flex-row h-8 w-8 justify-center items-center rounded-2xl bg-layer-1-surface`} - on:click={async () => { - await basis.callback(); - }} - > - <Glyph - basis={{ - key: `caret-left`, - dim: `sm-`, - weight: `bold`, - classes: `text-layer-2-glyph`, - }} - /> - </button> -</div> diff --git a/src/lib/components/map_full_envelope.svelte b/src/lib/components/map_full_envelope.svelte @@ -1,26 +0,0 @@ -<script lang="ts"> - import { Glyph, app_layout, route } from "@radroots/svelte-lib"; - - let el: HTMLElement | null; -</script> - -<div - bind:this={el} - class={`z-10 absolute top-dim_map_offset_top_${$app_layout} left-6 flex flex-col w-full gap-8 justify-start items-start`} -> - <button - class={`flex flex-row h-8 w-8 justify-center items-center rounded-2xl bg-layer-1-surface`} - on:click={async () => { - await route(`/`); - }} - > - <Glyph - basis={{ - key: `caret-left`, - dim: `sm-`, - weight: `bold`, - classes: `text-layer-2-glyph`, - }} - /> - </button> -</div> diff --git a/src/lib/components/map_marker_dot.svelte b/src/lib/components/map_marker_dot.svelte diff --git a/src/lib/components/map_popup_location_info.svelte b/src/lib/components/map_popup_location_info.svelte diff --git a/src/lib/conf.ts b/src/lib/conf.ts @@ -1,23 +1,15 @@ +import type { NumberTuple } from "@radroots/utils"; -/*type Conf = { - app: Record<string, string>; - pref: Record<string, string>; - cmd: Record<string, string>; - map: { - styles: { - base: Record<ColorMode, string>; - }, - popup: { - dot: { - offset: NumberTuple; - } - } +export const ks = { + nostr: { + conf_init_key: `conf:init:nostr:key`, + conf_init_profile: `conf:init:nostr:profile`, + nostr_key: (public_key: string) => `nostr:key:${public_key}`, + nostr_key_active: `nostr:key:active`, } -}*/ - -import type { NumberTuple } from "@radroots/utils"; +}; -export const _conf = { +export const cfg = { app: { root_symbol: "»--`--,---", title: `Radroots`, @@ -32,12 +24,7 @@ export const _conf = { mount_el: 500, nostr_relay_poll_document: 3000 }, - kv: { - nostr_key: (public_key: string) => `nostr:key:${public_key}`, - nostr_key_active: `nostr:key:active`, - }, cmd: { - //root_alert: `*-alert`, layout_route: `*-route` }, map: { diff --git a/src/lib/stores.ts b/src/lib/stores.ts @@ -1,7 +0,0 @@ -import { type NumberTuple } from "@radroots/utils"; -import { writable } from "svelte/store"; - -export const app_tok = writable<string>(''); - -export const map_full_center = writable<NumberTuple>([0, 0]); -export const map_full_zoom = writable<number>(4); diff --git a/src/lib/types.ts b/src/lib/types.ts @@ -1,6 +0,0 @@ -import type { NavigationPreviousParam } from "@radroots/svelte-lib"; - -export type NavParamPrev = NavigationPreviousParam[]; -export type NavParamTitle = { - label: string; -}; diff --git a/src/lib/utils/client.ts b/src/lib/utils/client.ts @@ -0,0 +1,25 @@ +import { keystore } from "$lib/client"; +import { app_notify, type NavigationRoute } from "@radroots/svelte-lib"; + +export const keystore_reset = async (): Promise<void> => { + try { + const ks_keys = await keystore.keys(); + if (`err` in ks_keys) return; //@todo + for (const ks_key of ks_keys.results) await keystore.remove(ks_key); + } catch (e) { + console.log(`(error) keystore_reset `, e); + } +}; + +export const restart = async (route_to: true | NavigationRoute, notify_message?: string): Promise<void> => { + try { + //await window.splash_show(); + if (notify_message) { + app_notify.set(notify_message); + } + //await route(typeof route_to === `string` ? route_to : `/`) + //location.reload(); + } catch (e) { + console.log(`(error) restart `, e); + } +}; diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts @@ -1,15 +0,0 @@ -import { app_notify, route, type NavigationRoute } from "@radroots/svelte-lib"; -import { lc } from "../client"; - -export const restart = async (route_to: true | NavigationRoute, notify_message?: string): Promise<void> => { - try { - await lc.window.splash_show(); - if (notify_message) { - app_notify.set(notify_message); - } - 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 @@ -1,11 +0,0 @@ -import { lc } from "$lib/client"; - -export const keystore_reset = async (): Promise<void> => { - try { - const ks_keys = await lc.keystore.keys(); - if (!ks_keys) return; - for (const ks_key of ks_keys) await lc.keystore.remove(ks_key); - } catch (e) { - console.log(`(error) keystore_reset `, e); - } -}; -\ No newline at end of file diff --git a/src/lib/utils/kv.ts b/src/lib/utils/kv.ts @@ -0,0 +1,55 @@ +import { parse_trade_product_form_keys, trade_product_form_fields, trade_product_form_vals, type TradeProductFormFields } from "@radroots/models"; +import { kv } from "@radroots/svelte-lib"; +import { err_msg, type ErrorMessage } from "@radroots/utils"; + +export const kv_init_trade_product_fields = async (kv_pref: string): Promise<void> => { + try { + for (const k of Object.keys( + trade_product_form_fields, + )) { + const field_k = parse_trade_product_form_keys(k); + if (!field_k) continue; + const field_id = `${kv_pref}-${field_k}` + await kv.delete(field_id); + } + + } catch (e) { + console.log(`(error) kv_init_trade_product_fields `, e); + } +}; + +export const kv_validate_trade_product_fields = async (opts: { + kv_pref: string; + no_validation?: string[] | true; +}): Promise<TradeProductFormFields | ErrorMessage<string>> => { + try { + let no_validation = opts.no_validation || []; + const vals = { + ...trade_product_form_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 = `${opts.kv_pref}-${field_k}`; + const field_val = await kv.get(field_id); + if (field_val) vals[field_k] = field_val; + if (no_validation === true) continue; + else if ( + (!field.optional && !field.validation.test(field_val)) || + (field.optional && + field_val && + !field.validation.test(field_val)) + ) { + if (no_validation.includes(field_k)) continue; + else return err_msg(field_k); + } + } + return vals; + } catch (e) { + console.log(`(error) trade_product_submit_preview `, e); + return err_msg(String(e)) + } +}; +\ No newline at end of file diff --git a/src/lib/utils/location_gcs.ts b/src/lib/utils/location_gcs.ts @@ -1,107 +0,0 @@ -import { geoc, lc } from "$lib/client"; -import type { GeocoderReverseResult } from "@radroots/geocoder"; -import type { LocationGcsFormFields } from "@radroots/models"; -import { err_msg, location_geohash, type ErrorMessage, type ResultId } from "@radroots/utils"; - -export const location_gcs_add_geoc = async (opts: { - geoc: GeocoderReverseResult; - label?: string; -}): Promise<ResultId | ErrorMessage<string>> => { - try { - const { geoc } = opts; - const fields: LocationGcsFormFields = { - lat: geoc.latitude.toString(), - lng: geoc.longitude.toString(), - geohash: location_geohash({ lat: geoc.latitude, lng: geoc.longitude }), - gc_id: geoc.id.toString(), - gc_name: geoc.name, - gc_admin1_id: geoc.admin1_id.toString(), - gc_admin1_name: geoc.admin1_name, - gc_country_id: geoc.country_id, - gc_country_name: geoc.country_name, - }; - if (opts.label) fields.label = opts.label; - - const res = - await lc.db.location_gcs_add(fields); - if (`id` in res) return res; - if (`err` in res && res.err === `*-location-gcs-geohash-unique`) - return err_msg(`This location has already been added.`); - - return err_msg(`There was an error`) - } catch (e) { - console.log(`(error) location_gcs_add_geoc `, e); - return err_msg(``) - } -}; - -export const location_gcs_add_current = async (): Promise<{ id: string } | false> => { - try { - const geoloc = await lc.geo.current(); - if (`err` in geoloc) { - const confirm = await lc.dialog.confirm( - `Location permissions are required to read geolocation.`, - ); - if (confirm) { - await lc.settings.open( - lc.platform === `ios` - ? { - ios: { - setting: `LocationServices`, - }, - } - : { - android: { - setting: `Location`, - }, - }, - ); - } - return false; - } - - const dialog_label = - await lc.dialog.prompt({ - title: `Geolocation Label`, - message: `What is the name of the location.`, - input_placeholder: `Enter location name`, - }); - if (dialog_label === false) return false; - else if (!dialog_label) { - await lc.dialog.alert(`A location name is required.`); - return false; - } - const fields: LocationGcsFormFields = { - lat: geoloc.lat.toString(), - lng: geoloc.lng.toString(), - geohash: location_geohash(geoloc), - label: dialog_label, - } - const geoc_res = await geoc.reverse({ - point: geoloc - }); - if (`results` in geoc_res && geoc_res.results.length > 0) { - const gc_result = geoc_res.results[0]; - fields.gc_id = gc_result.id.toString(); - fields.gc_name = gc_result.name; - fields.gc_admin1_id = gc_result.admin1_id.toString(); - fields.gc_admin1_name = gc_result.admin1_name; - fields.gc_country_id = gc_result.country_id; - fields.gc_country_name = gc_result.country_name; - }; - const res = - await lc.db.location_gcs_add(fields); - if (`id` in res) return res; - else if (`err` in res && res.err === `*-location-gcs-geohash-unique` - ) { - await lc.dialog.alert( - `This location has already been added.`, - ); - } - - return false; - } catch (e) { - console.log(`(error) location_gcs_add_current `, e); - return false; - } -}; -\ No newline at end of file diff --git a/src/lib/utils/models.ts b/src/lib/utils/models.ts @@ -0,0 +1,66 @@ +import { db, geoc } from "$lib/client"; +import type { IClientGeolocationPosition } from "@radroots/client"; +import type { GeocoderReverseResult } from "@radroots/geocoder"; +import type { ILocationGcsAddResolve, LocationGcsFormFields } from "@radroots/models"; +import { err_msg, location_geohash } from "@radroots/utils"; + +export const model_location_gcs_add_position = async (opts: { + label?: string; + geo_loc: IClientGeolocationPosition; +}): Promise<ILocationGcsAddResolve<string>> => { + try { + const { label, geo_loc } = opts; + const fields: LocationGcsFormFields = { + lat: geo_loc.lat.toString(), + lng: geo_loc.lng.toString(), + geohash: location_geohash(geo_loc), + } + if (label) fields.label = label; + const geoc_rev = await geoc.reverse({ + point: { + lat: geo_loc.lat, + lng: geo_loc.lng + } + }); + if (`results` in geoc_rev && geoc_rev.results.length > 0) { + const geoc_res = geoc_rev.results[0]; + fields.gc_id = geoc_res.id.toString(); + fields.gc_name = geoc_res.name; + fields.gc_admin1_id = geoc_res.admin1_id.toString(); + fields.gc_admin1_name = geoc_res.admin1_name; + fields.gc_country_id = geoc_res.country_id; + fields.gc_country_name = geoc_res.country_name; + }; + const res = await db.location_gcs_add(fields); + return res; + } catch (e) { + console.log(`(error) model_location_gcs_add_position `, e); + return err_msg(`*`) + } +}; + +export const model_location_gcs_add_geocode = async (opts: { + label?: string; + geo_code: GeocoderReverseResult; +}): Promise<ILocationGcsAddResolve<string>> => { + try { + const { label, geo_code } = opts; + const fields: LocationGcsFormFields = { + lat: geo_code.latitude.toString(), + lng: geo_code.longitude.toString(), + geohash: location_geohash({ lat: geo_code.latitude, lng: geo_code.longitude }), + gc_id: geo_code.id.toString(), + gc_name: geo_code.name, + gc_admin1_id: geo_code.admin1_id.toString(), + gc_admin1_name: geo_code.admin1_name, + gc_country_id: geo_code.country_id, + gc_country_name: geo_code.country_name, + }; + if (label) fields.label = label; + const res = await db.location_gcs_add(fields); + return res; + } catch (e) { + console.log(`(error) model_location_gcs_add_geocode `, e); + return err_msg(`*`) + } +}; diff --git a/src/lib/utils/nostr.ts b/src/lib/utils/nostr.ts @@ -1,43 +0,0 @@ -import { lc } from "$lib/client"; -import NDK, { NDKKind, NDKUser } from "@nostr-dev-kit/ndk"; -import { fmt_tags_basis_nip99, ndk_event } from "@radroots/utils"; - -export const nostr_sync_models_trade_product = async (opts: { - $ndk: NDK; - $ndk_user: NDKUser; -}): Promise<void> => { - try { - console.log(`(nostr_sync_models_trade_product) run`) - - const trade_products_all = await lc.db.trade_product_get({ - list: [`all`], - }); - if (`err` in trade_products_all) return; - for (const trade_product of trade_products_all.results) { - const tags_basis = await fmt_tags_basis_nip99({ - d_tag: trade_product.id, - title: trade_product.key, - summary: `${trade_product.key} ${trade_product.lot} ${trade_product.process}`, - }); - if (!tags_basis) continue; - - const { $ndk, $ndk_user } = opts; - const ev = await ndk_event({ - $ndk, - $ndk_user, - basis: { - kind: NDKKind.Classified, - content: `This is a rad roots posting of ${trade_product.key}`, - tags: [...tags_basis], - }, - }); - if (!ev) return; - await ev.publish(); - } - - console.log(`(nostr_sync_models_trade_product) done`) - - } catch (e) { - console.log(`(error) nostr_sync_models_trade_product `, e); - } -}; -\ No newline at end of file diff --git a/src/lib/utils/trade_product.ts b/src/lib/utils/trade_product.ts @@ -1,55 +0,0 @@ -import { parse_trade_product_form_keys, trade_product_form_fields, trade_product_form_vals, type TradeProductFormFields } from "@radroots/models"; -import { kv } from "@radroots/svelte-lib"; -import { err_msg, type ErrorMessage } from "@radroots/utils"; - -export const validate_trade_product_vals = async (opts: { - kv_pref: string; - no_validation?: string[] | true; -}): Promise<TradeProductFormFields | ErrorMessage<string>> => { - try { - let no_validation = opts.no_validation || []; - const vals = { - ...trade_product_form_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 = `${opts.kv_pref}-${field_k}`; - const field_val = await kv.get(field_id); - if (field_val) vals[field_k] = field_val; - if (no_validation === true) continue; - else if ( - (!field.optional && !field.validation.test(field_val)) || - (field.optional && - field_val && - !field.validation.test(field_val)) - ) { - if (no_validation.includes(field_k)) continue; - else return err_msg(field_k); - } - } - return vals; - } catch (e) { - console.log(`(error) trade_product_submit_preview `, e); - return err_msg(String(e)) - } -}; - -export const trade_product_kv_init = async (kv_pref: string): Promise<void> => { - try { - for (const k of Object.keys( - trade_product_form_fields, - )) { - const field_k = parse_trade_product_form_keys(k); - if (!field_k) continue; - const field_id = `${kv_pref}-${field_k}` - await kv.delete(field_id); - } - - } catch (e) { - console.log(`(error) trade_product_kv_init `, e); - } -}; diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte @@ -1,177 +1,16 @@ <script lang="ts"> - import { lc } from "$lib/client"; - import { _conf } from "$lib/conf"; - import { nostr_sync_models_trade_product } from "$lib/utils/nostr"; - import { - type NostrRelayFormFields, - parse_nostr_relay_form_keys, - } from "@radroots/models"; - import { - app_nostr_key, - ndk, - ndk_user, - nostr_ndk_configured, - nostr_relays_connected, - nostr_relays_poll_documents, - nostr_relays_poll_documents_count, - nostr_sync_prevent, - } from "@radroots/svelte-lib"; - import { - ndk_init, - parse_nostr_relay_information_document_fields, - } from "@radroots/utils"; + import { geoc } from "$lib/client"; + import { app_geoc } from "@radroots/svelte-lib"; + import { onMount } from "svelte"; - app_nostr_key.subscribe(async (_app_nostr_key) => { + onMount(async () => { try { - if (!_app_nostr_key) return; - const secret_key = await lc.keystore.get( - _conf.kv.nostr_key(_app_nostr_key), - ); - if (!secret_key) { - alert(`!secret_key - go to recovery (todo)`); //@todo - return; - } - const nostr_relays = await lc.db.nostr_relay_get({ - list: ["all"], - }); - if (`err` in nostr_relays) throw new Error(nostr_relays.err); - for (const { url } of nostr_relays.results) - $ndk.addExplicitRelay(url); - await $ndk.connect(); - const ndk_user = await ndk_init({ - $ndk, - secret_key, - }); - if (!ndk_user) { - nostr_ndk_configured.set(false); - return; - } - $ndk_user = ndk_user; - $ndk_user.ndk = $ndk; - nostr_ndk_configured.set(true); + const geoc_connected = await geoc.connect(); + app_geoc.set(!!geoc_connected); } catch (e) { - console.log(`(app_nostr_key) error `, e); + } finally { } }); - - nostr_ndk_configured.subscribe(async (_nostr_ndk_configured) => { - try { - if (!_nostr_ndk_configured) return; - console.log(`(nostr_ndk_configured) success`); - nostr_relays_poll_documents.set(true); - await sync_nostr(); - } catch (e) { - console.log(`(error) nostr_ndk_configured`, e); - } - }); - - nostr_relays_poll_documents.subscribe( - async (_nostr_relays_poll_documents) => { - try { - if (!_nostr_relays_poll_documents) return; - await fetch_relay_documents(); - } catch (e) { - console.log(`(error) nostr_relays_poll_documents`, e); - } - }, - ); - - const sync_nostr = async (): Promise<void> => { - try { - console.log(`!!! SYNC NOSTR`); - if (!$nostr_ndk_configured) { - console.log(`!!! SYNC NOSTR ndk not configured`); - return; - } - if ($nostr_sync_prevent) { - const confirm = await lc.dialog.confirm({ - message: `Sync to nostr network is disabled. Do you want to turn it on?`, - cancel_label: `No`, - ok_label: `Yes`, - }); - if (confirm === true) { - nostr_sync_prevent.set(false); - await sync_nostr(); - return; - } - return; - } - - await nostr_sync_models_trade_product({ $ndk, $ndk_user }); - } catch (e) { - console.log(`(error) sync_nostr `, e); - } - }; - - const fetch_relay_documents = async (): Promise<void> => { - try { - if ( - $nostr_relays_poll_documents_count >= - _conf.nostr.relay_polling_count_max - ) { - nostr_relays_poll_documents.set(false); - return; - } - nostr_relays_poll_documents_count.set( - $nostr_relays_poll_documents_count + 1, - ); - const nostr_relays = await lc.db.nostr_relay_get({ - list: [`on_profile`, { public_key: $app_nostr_key }], - }); - if (`err` in nostr_relays) throw new Error(nostr_relays.err); - - const unconnected_relays = nostr_relays.results.filter( - (i) => !$nostr_relays_connected.includes(i.id), - ); - if (unconnected_relays.length === 0) { - nostr_relays_poll_documents.set(false); - return; - } - - for (const nostr_relay of unconnected_relays) { - const res = await lc.http.fetch({ - url: nostr_relay.url.replace(`ws://`, `http://`), - headers: { - Accept: "application/nostr+json", - }, - }); - if (`err` in res) continue; - else if (res.status === 200 && res.data) { - const doc = parse_nostr_relay_information_document_fields( - res.data, - ); - if (!doc) continue; - const fields: Partial<NostrRelayFormFields> = {}; - for (const [k, v] of Object.entries(doc)) { - const field_k = parse_nostr_relay_form_keys(k); - if (field_k) fields[field_k] = v; - } - if (Object.keys(fields).length < 1) continue; - await lc.db.nostr_relay_update({ - on: { - url: nostr_relay.url, - }, - fields, - }); - nostr_relays_connected.set( - Array.from( - new Set([ - ...$nostr_relays_connected, - nostr_relay.id, - ]), - ), - ); - } - } - - setTimeout( - fetch_relay_documents, - _conf.delay.nostr_relay_poll_document, - ); - } catch (e) { - console.log(`(error) fetch_relay_documents `, e); - } - }; </script> <slot /> diff --git a/src/routes/(app)/+layout.ts b/src/routes/(app)/+layout.ts @@ -1,11 +0,0 @@ -import type { LayoutLoad, LayoutLoadEvent } from '../$types'; - -export const load: LayoutLoad = async ({ url }: LayoutLoadEvent) => { - try { - console.log(`layout (app) `, url.pathname); - } catch (e) { - console.log(`layout (app) error: `, e); - } finally { - return {} - } -}; diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte @@ -1,4 +1,5 @@ <script lang="ts"> + import { keyring, nostr } from "$lib/client"; import { app_nostr_key, type CallbackPromise, @@ -49,7 +50,7 @@ weight: `fill`, }, { - route: `/nostr/keys`, + route: `/`, label: `Keys`, key: `key`, weight: `fill`, @@ -168,7 +169,11 @@ { icon: `compass`, callback: async (tab_i) => { - await route(`/map/choose-location`); + // await route(`/map/choose-location`); + const new_sk = await nostr.lib.generate_key(); + console.log(`new_sk `, new_sk); + const res = keyring.set_nostr_key(new_sk); + console.log(`res `, res); }, }, { @@ -179,9 +184,7 @@ }, { icon: `bell-simple`, - callback: async (tab_i) => { - await route(`/test`); - }, + callback: async (tab_i) => {}, }, ], }} diff --git a/src/routes/(app)/map/+page.svelte b/src/routes/(app)/map/+page.svelte @@ -1,61 +0,0 @@ -<script lang="ts"> - import { lc } from "$lib/client"; - import MapControlFull from "$lib/components/map_control_full.svelte"; - import MapMarkerDot from "$lib/components/map_marker_dot.svelte"; - import MapPopupLocationInfo from "$lib/components/map_popup_location_info.svelte"; - import { _conf } from "$lib/conf"; - import { app_thc, LoadingView, route, sleep } from "@radroots/svelte-lib"; - import { MapLibre, Marker, Popup } from "@radroots/svelte-maplibre"; - import { type GeolocationCoordinatesPoint } from "@radroots/utils"; - import { onMount } from "svelte"; - - let loading_layout = true; - let map_coords: GeolocationCoordinatesPoint | undefined = undefined; - - onMount(async () => { - try { - const geoloc = await lc.geo.current(); - if (`err` in geoloc) return; - map_coords = geoloc; - await sleep(_conf.delay.load); - } catch (e) { - console.log(`e `, e); - } finally { - loading_layout = false; - } - }); -</script> - -{#if map_coords} - <MapLibre - center={map_coords} - zoom={10} - class={`map-full ${loading_layout ? `hidden` : ``}`} - style={_conf.map.styles.base[$app_thc]} - > - <Marker lngLat={map_coords}> - <MapMarkerDot /> - <Popup offset={_conf.map.popup.dot.offset}> - <MapPopupLocationInfo basis={{ point: map_coords }} /> - </Popup> - </Marker> - </MapLibre> -{/if} -{#if loading_layout} - <LoadingView /> -{:else} - <MapControlFull - basis={{ - callback: async () => { - await route(`/`); - }, - }} - /> -{/if} - -<style> - :global(.map-full) { - height: 100vh; - width: 100vh; - } -</style> diff --git a/src/routes/(app)/map/choose-location/+page.svelte b/src/routes/(app)/map/choose-location/+page.svelte @@ -1,89 +0,0 @@ -<script lang="ts"> - import { geoc, lc } from "$lib/client"; - import MapControlFull from "$lib/components/map_control_full.svelte"; - import MapMarkerDot from "$lib/components/map_marker_dot.svelte"; - import MapPopupLocationInfo from "$lib/components/map_popup_location_info.svelte"; - import { _conf } from "$lib/conf"; - import { location_gcs_add_current } from "$lib/utils/location_gcs"; - import { app_thc, LoadingView, route, sleep } from "@radroots/svelte-lib"; - import { MapLibre, Marker, Popup } from "@radroots/svelte-maplibre"; - import { type GeolocationCoordinatesPoint } from "@radroots/utils"; - import { onMount } from "svelte"; - - let loading_layout = true; - let map_coords_inital: GeolocationCoordinatesPoint | undefined = undefined; - let map_coords: GeolocationCoordinatesPoint | undefined = undefined; - - onMount(async () => { - try { - const geoloc = await lc.geo.current(); - if (`err` in geoloc) - map_coords_inital = { - lat: 0, - lng: 0, - }; - else { - map_coords_inital = geoloc; - map_coords = geoloc; - } - await sleep(_conf.delay.load); - } catch (e) { - console.log(`e `, e); - } finally { - loading_layout = false; - } - }); -</script> - -{#if map_coords} - <MapLibre - center={map_coords_inital} - zoom={10} - class={`map-full ${loading_layout ? `hidden` : ``}`} - style={_conf.map.styles.base[$app_thc]} - > - <Marker - bind:lngLat={map_coords} - draggable - on:dragend={async () => { - if (!map_coords) return; - const geoc_res = await geoc.reverse({ - point: map_coords, - limit: 1, - }); - if (`results` in geoc_res) { - console.log( - JSON.stringify(geoc_res.results, null, 4), - `geoc_res.results`, - ); - } - }} - > - <MapMarkerDot /> - <Popup offset={_conf.map.popup.dot.offset}> - <MapPopupLocationInfo basis={{ point: map_coords }} /> - </Popup> - </Marker> - </MapLibre> -{/if} -{#if loading_layout} - <LoadingView /> -{:else} - <MapControlFull - basis={{ - callback: async () => { - if (!map_coords) return; //@todo - const res = await location_gcs_add_current(); - if (res) - await route(`/models/trade-product/add`, [[`id`, res.id]]); - }, - }} - /> -{/if} - -<style> - :global(.map-full) { - height: 100vh; - width: 100vh; - } -</style> diff --git a/src/routes/(app)/models/location-gcs/+page.svelte b/src/routes/(app)/models/location-gcs/+page.svelte @@ -1,6 +1,5 @@ <script lang="ts"> - import { lc } from "$lib/client"; - import { location_gcs_add_current } from "$lib/utils/location_gcs"; + import { db } from "$lib/client"; import { type LocationGcs } from "@radroots/models"; import { app_notify, @@ -31,14 +30,14 @@ const load_data = async (): Promise<LoadData | undefined> => { try { - const location_gcss = await lc.db.location_gcs_get({ + const location_gcss = await db.location_gcs_get({ list: [`all`], }); if (`err` in location_gcss) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } else if (location_gcss.results.length < 1) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } @@ -50,6 +49,16 @@ console.log(`(error) load_data `, e); } }; + + const handle_add_location_gcs = async (): Promise<void> => { + try { + console.log(`@todo`); + //const res = await location_gcs_add_current(); + //if (res) ld = await load_data(); + } catch (e) { + console.log(`(error) handle_add_location_gcs `, e); + } + }; </script> <LayoutView> @@ -118,8 +127,7 @@ <button class={`flex flex-row justify-center items-center`} on:click={async () => { - const res = await location_gcs_add_current(); - if (res) ld = await load_data(); + await handle_add_location_gcs(); }} > <p @@ -151,8 +159,7 @@ classes: `tap-color`, }, callback: async () => { - const res = await location_gcs_add_current(); - if (res) await load_data(); + await handle_add_location_gcs(); }, } : undefined, diff --git a/src/routes/(app)/models/location-gcs/view-map/+page.svelte b/src/routes/(app)/models/location-gcs/view-map/+page.svelte @@ -1,4 +0,0 @@ -<script lang="ts"> -</script> - -<div></div> diff --git a/src/routes/(app)/models/nostr-profile/+page.svelte b/src/routes/(app)/models/nostr-profile/+page.svelte @@ -1,6 +1,5 @@ <script lang="ts"> - import { lc } from "$lib/client"; - import { location_gcs_add_current } from "$lib/utils/location_gcs"; + import { db, keystore } from "$lib/client"; import { nostr_profile_form_vals, parse_nostr_profile_form_keys, @@ -32,20 +31,39 @@ const load_data = async (): Promise<LoadData | undefined> => { try { - const nostr_profiles = await lc.db.nostr_profile_get({ + const nostr_profiles = await db.nostr_profile_get({ list: [`all`], }); if (`err` in nostr_profiles) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } else if (nostr_profiles.results.length < 1) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } } catch (e) { console.log(`(error) load_data `, e); } }; + + const handle_add_location_gcs = async (): Promise<void> => { + try { + console.log(`@todo`); + //const res = await location_gcs_add_current(); + //if (res) ld = await load_data(); + } catch (e) { + console.log(`(error) handle_add_location_gcs `, e); + } + }; + + const handle_add_nostr_profile = async (): Promise<void> => { + try { + const ks_keys = await keystore.keys(); + console.log(JSON.stringify(ks_keys, null, 4), `ks_keys`); + } catch (e) { + console.log(`(error) handle_add_nostr_profile `, e); + } + }; </script> <LayoutView> @@ -68,7 +86,7 @@ left: [ { classes: `capitalize`, - value: `${$t(`model_fields.${k}`, { default: k.replaceAll(`_`, ` `) })}`, + value: `${$t(`model.nostr_profile.${k}`, { default: k.replaceAll(`_`, ` `) })}`, }, ], right: [ @@ -110,8 +128,7 @@ <button class={`flex flex-row justify-center items-center`} on:click={async () => { - const res = await location_gcs_add_current(); - if (res) ld = await load_data(); + await handle_add_location_gcs(); }} > <p @@ -142,11 +159,7 @@ classes: `tap-color`, }, callback: async () => { - const ks_keys = await lc.keystore.keys(); - console.log(JSON.stringify(ks_keys, null, 4), `ks_keys`); - for (const ks_key of ks_keys || []) { - console.log(`ks_key `, ks_key); - } + await handle_add_nostr_profile(); }, } : undefined, diff --git a/src/routes/(app)/models/nostr-profile/edit/field/+page.svelte b/src/routes/(app)/models/nostr-profile/edit/field/+page.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { lc } from "$lib/client"; + import { db, dialog } from "$lib/client"; import { nostr_profile_form_fields, parse_nostr_profile_form_keys, @@ -9,7 +9,6 @@ } from "@radroots/models"; import { app_notify, - app_submit_route, Fill, fmt_id, kv, @@ -36,8 +35,12 @@ onMount(async () => { try { - if (!$qp_rkey || !$qp_nostr_pk) - app_notify.set(`Missing page params`); + if (!$qp_rkey || !$qp_nostr_pk) { + app_notify.set( + `${$t(`icu.error_loading_*`, { value: `${$t(`common.page`)}` })}`, + ); + return; + } ld = await load_page(); } catch (e) { @@ -56,25 +59,29 @@ let val_field_valid = false; $: translated_field_key = ld?.field_key - ? `${$t(`model_fields.${ld?.field_key}`, { default: ld?.field_key?.replaceAll(`_`, ` `) })}`.toLowerCase() + ? `${$t(`model.nostr_profile.${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({ + const nostr_profiles = await db.nostr_profile_get({ public_key: $qp_nostr_pk, }); if (`err` in nostr_profiles) { - app_notify.set(`Error loading profile`); + app_notify.set( + `${$t(`icu.error_loading_*`, { value: `${$t(`common.profile`)}` })}`, + ); return; } else if (nostr_profiles.results.length < 1) { - app_notify.set(`Error loading profile`); + app_notify.set( + `${$t(`icu.error_loading_*`, { value: `${$t(`common.page`)}` })}`, + ); return; } const field_key = parse_nostr_profile_form_keys($qp_rkey); if (!field_key) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } @@ -100,7 +107,7 @@ const validated = nostr_profile_form_fields[ld?.field_key].validation.test(val); if (!validated) { - lc.dialog.alert( + dialog.alert( `${$t(`icu.invalid_*_entry`, { value: translated_field_key })}`, ); return; @@ -109,26 +116,25 @@ const fields: Partial<NostrProfileFormFields> = {}; fields[ld?.field_key] = val; - const update_db = await lc.db.nostr_profile_update({ + const update_res = await 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 + if (`err` in update_res) { + await dialog.alert(`${$t(`common.error.client.unhandled`)}`); + return; //@todo } + + alert(`@todo sync to nostr`); + // @todo sync to nostr + //if ($app_submit_route) { + // await route($app_submit_route.route, $app_submit_route.params); + //} else { + // await route(`/nostr/keys`); + //} + return; } catch (e) { console.log(`(error) submit `, e); } diff --git a/src/routes/(app)/models/nostr-profile/view/+page.svelte b/src/routes/(app)/models/nostr-profile/view/+page.svelte @@ -1,6 +1,6 @@ <script lang="ts"> - import { lc } from "$lib/client"; - import { _conf } from "$lib/conf"; + import { db, keystore, nostr } from "$lib/client"; + import { ks } from "$lib/conf"; import type { NostrProfile, NostrRelay } from "@radroots/models"; import { app_nostr_key, @@ -36,7 +36,8 @@ onMount(async () => { try { - if (!$qp_nostr_pk) app_notify.set(`Error loading page`); + if (!$qp_nostr_pk) + app_notify.set(`${$t(`error.client.page.load`)}`); ld = await load_data(); } catch (e) { } finally { @@ -45,39 +46,38 @@ const load_data = async (): Promise<LoadData | undefined> => { try { - const nostr_profiles = await lc.db.nostr_profile_get({ + const nostr_profiles = await db.nostr_profile_get({ public_key: $qp_nostr_pk, }); if (`err` in nostr_profiles) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } else if (nostr_profiles.results.length < 1) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } - const secret_key = await lc.keystore.get( - _conf.kv.nostr_key($qp_nostr_pk), + const ks_secret_key = await keystore.get( + ks.nostr.nostr_key($qp_nostr_pk), ); - - if (!secret_key) { + if (`err` in ks_secret_key) { app_notify.set(`Error loading profile`); return; } - const nostr_relays = await lc.db.nostr_relay_get({ + const nostr_relays = await db.nostr_relay_get({ list: [`on_profile`, { public_key: $qp_nostr_pk }], sort: `oldest`, }); - const nostr_relays_unconnected = await lc.db.nostr_relay_get({ + const nostr_relays_unconnected = await db.nostr_relay_get({ list: [`off_profile`, { public_key: $qp_nostr_pk }], sort: `oldest`, }); const data: LoadData = { nostr_profile: nostr_profiles.results[0], - secret_key, + secret_key: ks_secret_key.result, nostr_relays: `results` in nostr_relays ? nostr_relays.results : [], nostr_relays_unconnected: @@ -205,7 +205,7 @@ value: show_public_key_hex ? ld.nostr_profile .public_key - : lc.nostr.lib.npub( + : nostr.lib.npub( ld.nostr_profile .public_key, ), @@ -239,7 +239,7 @@ show_public_key_hex ? ld?.nostr_profile .public_key - : lc.nostr.lib.npub( + : nostr.lib.npub( ld.nostr_profile .public_key, ), @@ -292,7 +292,7 @@ value: vl_secret_key_unlock ? show_secret_key_hex ? ld.secret_key - : lc.nostr.lib.nsec( + : nostr.lib.nsec( ld.secret_key, ) : `•`.repeat(40), @@ -325,7 +325,7 @@ await clipboard_copy( show_secret_key_hex ? ld.secret_key - : lc.nostr.lib.npub( + : nostr.lib.npub( ld.secret_key, ), ); diff --git a/src/routes/(app)/models/nostr-relay/+page.svelte b/src/routes/(app)/models/nostr-relay/+page.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { lc } from "$lib/client"; + import { db, dialog } from "$lib/client"; import type { NostrRelay } from "@radroots/models"; import { app_nostr_key, @@ -36,21 +36,21 @@ const load_data = async (): Promise<LoadData | undefined> => { try { - const nostr_relays = await lc.db.nostr_relay_get({ + const nostr_relays = await db.nostr_relay_get({ list: [`on_profile`, { public_key: $app_nostr_key }], sort: `oldest`, }); if (`err` in nostr_relays) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } - const nostr_relays_other = await lc.db.nostr_relay_get({ + const nostr_relays_other = await db.nostr_relay_get({ list: [`off_profile`, { public_key: $app_nostr_key }], sort: `oldest`, }); if (`err` in nostr_relays_other) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } @@ -145,7 +145,7 @@ ): Promise<void> => { try { loading_edit_id = nostr_relay.id; - const confirm = await lc.dialog.confirm( + const confirm = await dialog.confirm( `This action will disconnect relay ${nostr_relay.url}`, ); if (confirm === false) return; diff --git a/src/routes/(app)/models/nostr-relay/view/+page.svelte b/src/routes/(app)/models/nostr-relay/view/+page.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { lc } from "$lib/client"; + import { db, nostr } from "$lib/client"; import type { NostrProfile, NostrRelay } from "@radroots/models"; import { app_blur, @@ -25,7 +25,7 @@ onMount(async () => { try { - if (!$qp_id) app_notify.set(`Error loading page`); + if (!$qp_id) app_notify.set(`${$t(`error.client.page.load`)}`); ld = await load_data(); } catch (e) { } finally { @@ -34,24 +34,24 @@ const load_data = async (): Promise<LoadData | undefined> => { try { - const nostr_relays = await lc.db.nostr_relay_get({ + const nostr_relays = await db.nostr_relay_get({ id: $qp_id, }); if (`err` in nostr_relays) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } else if (nostr_relays.results.length < 1) { - app_notify.set(`Error loading page`); + app_notify.set(`${$t(`error.client.page.load`)}`); return; } const nostr_relay = nostr_relays.results[0]; - const nostr_profiles = await lc.db.nostr_profile_get({ + const nostr_profiles = await db.nostr_profile_get({ list: [`on_relay`, { id: nostr_relay.id }], }); - const nostr_profiles_unconnected = await lc.db.nostr_profile_get({ + const nostr_profiles_unconnected = await db.nostr_profile_get({ list: [`off_relay`, { id: nostr_relay.id }], }); @@ -171,7 +171,7 @@ args: { layer: 1, title: { - value: `${$t(`model_fields.pubkey`)}`, + value: `${$t(`model.nostr_relay.pubkey`)}`, }, list: [ { @@ -182,11 +182,11 @@ { classes: `text-layer-1-glyph`, value: ld.nostr_relay.pubkey - ? lc.nostr.lib.npub( + ? nostr.lib.npub( ld.nostr_relay.pubkey, true, ) - : `${$t(`icu.no_*_published`, { value: `${$t(`model_fields.pubkey`)}`.toLowerCase() })}`, + : `${$t(`icu.no_*_published`, { value: `${$t(`pubkey`)}`.toLowerCase() })}`, }, ], }, @@ -201,7 +201,7 @@ args: { layer: 1, title: { - value: `${$t(`model_fields.description`)}`, + value: `${$t(`model.nostr_relay.description`)}`, }, list: [ { @@ -214,7 +214,7 @@ value: ld.nostr_relay .description || - `${$t(`icu.no_*_published`, { value: `${$t(`model_fields.description`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`model.nostr_relay.description`)}`.toLowerCase() })}`, }, ], }, @@ -229,7 +229,7 @@ args: { layer: 1, title: { - value: `${$t(`model_fields.software`)}`, + value: `${$t(`model.nostr_relay.software`)}`, }, list: [ { @@ -241,7 +241,7 @@ classes: `text-layer-1-glyph`, value: ld.nostr_relay.software || - `${$t(`icu.no_*_published`, { value: `${$t(`model_fields.software`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`model.nostr_relay.software`)}`.toLowerCase() })}`, }, ], }, @@ -256,7 +256,7 @@ args: { layer: 1, title: { - value: `${$t(`model_fields.version`)}`, + value: `${$t(`model.nostr_relay.version`)}`, }, list: [ { @@ -268,7 +268,7 @@ classes: `text-layer-1-glyph`, value: ld.nostr_relay.version || - `${$t(`icu.no_*_published`, { value: `${$t(`model_fields.version`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`model.nostr_relay.version`)}`.toLowerCase() })}`, }, ], }, @@ -283,7 +283,7 @@ args: { layer: 1, title: { - value: `${$t(`model_fields.supported_nips`)}`, + value: `${$t(`model.nostr_relay.supported_nips`)}`, }, list: [ { @@ -296,7 +296,7 @@ value: ld.nostr_relay .supported_nips || - `${$t(`icu.no_*_published`, { value: `${$t(`model_fields.supported_nips`)}`.toLowerCase() })}`, + `${$t(`icu.no_*_published`, { value: `${$t(`supported_nips`)}`.toLowerCase() })}`, }, ], }, diff --git a/src/routes/(app)/models/trade-product/+page.svelte b/src/routes/(app)/models/trade-product/+page.svelte @@ -1,8 +1,9 @@ <script lang="ts"> - import { lc } from "$lib/client"; + import { db } from "$lib/client"; import { type TradeProduct } from "@radroots/models"; import { app_notify, + LayoutArea, LayoutTrellis, LayoutView, locale, @@ -29,11 +30,14 @@ const load_data = async (): Promise<LoadData | undefined> => { try { - const trade_products = await lc.db.trade_product_get({ + const trade_products = await db.trade_product_get({ list: [`all`], }); + console.log(`trade_products `, trade_products); if (`err` in trade_products) { - app_notify.set(`Error loading page`); + app_notify.set( + `${$t(`icu.error_loading_*`, { value: `${$t(`common.page`)}` })}`, + ); return; } @@ -47,9 +51,9 @@ }; </script> -<LayoutView> - <LayoutTrellis> - {#if ld && ld.trade_products.length > 0} +{#if ld && ld.trade_products.length > 0} + <LayoutView> + <LayoutTrellis> {#each ld.trade_products as li, li_i} <Trellis basis={{ @@ -148,24 +152,32 @@ }} /> {/each} - {:else} - <div - class={`flex flex-col w-full justify-center items-center px-4 gap-2`} + </LayoutTrellis> + </LayoutView> +{:else} + <LayoutArea> + <div + class={`flex flex-col h-full w-full gap-2 justify-center items-center`} + > + <p + class={`font-sans font-[400] text-layer-1-glyph text-line_display`} > - <p class={`font-sans font-[400] text-layer-2-glyph`}> - {`No items to display.`} - </p> - <a href={`/models/trade-product/add`}> - <p - class={`font-sans font-[400] text-layer-2-glyph-hl text-sm`} - > - {`Click to add a new product`} + {`${$t(`icu.no_*_to_display`, { value: `${$t(`common.items`)}`.toLowerCase() })}`} + </p> + <a href={`/models/trade-product/add`}> + <button + class={`flex flex-row justify-center items-center active:opacity-80`} + on:click={async () => {}} + > + <p class={`font-sans font-[400] text-layer-2-glyph-hl`}> + {`${$t(`icu.click_to_add_a_*`, { value: `${$t(`icu.new_*`, { value: `${$t(`common.product`)}` })}`.toLowerCase() })}`} </p> - </a> - </div> - {/if} - </LayoutTrellis> -</LayoutView> + </button> + </a> + </div> + </LayoutArea> +{/if} + <Nav basis={{ prev: { diff --git a/src/routes/(app)/models/trade-product/add/+page.svelte b/src/routes/(app)/models/trade-product/add/+page.svelte @@ -1,16 +1,16 @@ <!-- svelte-ignore a11y-no-noninteractive-tabindex --> <script lang="ts"> - import { lc } from "$lib/client"; + import { db, dialog, geol } from "$lib/client"; import MapChooseLocation from "$lib/components/map_choose_location.svelte"; - import { _conf } from "$lib/conf"; + import { cfg } from "$lib/conf"; import { - location_gcs_add_current, - location_gcs_add_geoc, - } from "$lib/utils/location_gcs"; + kv_init_trade_product_fields, + kv_validate_trade_product_fields, + } from "$lib/utils/kv"; import { - trade_product_kv_init, - validate_trade_product_vals, - } from "$lib/utils/trade_product"; + model_location_gcs_add_geocode, + model_location_gcs_add_position, + } from "$lib/utils/models"; import type { GeocoderReverseResult } from "@radroots/geocoder"; import { mass_units, @@ -24,12 +24,13 @@ carousel_next, carousel_prev, el_id, + EntryLine, + EntryMultiline, + EntryOption, Fill, fmt_id, Glyph, InputElement, - InputForm, - InputSelect, int_step, kv, LayoutTrellis, @@ -37,9 +38,7 @@ LayoutView, locale, Nav, - NotifyGlyph, t, - TextareaElement, view_effect, } from "@radroots/svelte-lib"; import { @@ -58,45 +57,43 @@ const trade_key_default: TradeKey = `coffee`; - type CarouselConf = { + type CarouselParam = { label_prev?: string; label_next: string; }; - const carousel_conf = new Map<number, CarouselConf>([ + const carousel_param = new Map<number, CarouselParam>([ [ 0, { - label_next: `Preview`, + label_next: `${$t(`common.preview`)}`, }, ], [ 1, { - label_next: `Listing`, + label_next: `${$t(`common.details`)}`, }, ], [ 2, { - label_next: `Location`, + label_next: `${$t(`common.location`)}`, }, ], [ 3, { - label_next: `Review`, + label_next: `${$t(`common.review`)}`, }, ], [ 4, { - label_next: `Post`, + label_next: `${$t(`common.post`)}`, }, ], ]); - let el_trellis_wrap_price: HTMLElement | null; - type View = `load` | `form_1` | `map`; let view: View = `load`; @@ -104,20 +101,26 @@ view_effect<View>(view); } - $: if (view === `map`) { - (async () => { - try { - loading_map = true; - const geoloc = await lc.geo.current(); - if (`err` in geoloc) return; - else { - map_point_location_gcs = geoloc; - map_point_location_gcs_select = geoloc; - } - loading_map = false; - } catch (e) {} - })(); - } + onMount(async () => { + try { + await handle_view(`load`); + carousel_index.set(0); + carousel_index_max.set(carousel_param.size - 1); + sel_trade_product_price_currency = "eur"; + sel_trade_product_price_qty_unit = "kg"; + sel_trade_product_qty_unit = "kg"; + await fetch_models_models_location_gcs(); + } catch (e) { + } finally { + await handle_view(`form_1`); + } + }); + + let el_trellis_wrap_price: HTMLElement | null; + + let loading_submit = false; + let loading_map = false; + let loading_location_gcs = false; let show_sel_trade_product_key_other = false; let sel_trade_product_key: string = trade_key_default; @@ -129,16 +132,16 @@ let sel_location_gcs_id = ``; let ls_models_location_gcs: LocationGcs[] = []; let map_point_location_gcs: GeolocationCoordinatesPoint = - _conf.map.coords.default; + cfg.map.coords.default; let map_point_location_gcs_select: GeolocationCoordinatesPoint = - _conf.map.coords.default; + cfg.map.coords.default; let map_point_location_gcs_select_geoc: GeocoderReverseResult | undefined = undefined; let show_sel_trade_product_qty_tup_other = false; let sel_trade_product_qty_tup = ``; - let show_sel_trade_product_price_currency = false; + // let show_sel_trade_product_price_currency = false; let sel_trade_product_price_currency = ``; let sel_trade_product_price_qty_unit = ``; @@ -150,10 +153,6 @@ let review_trade_product: TradeProductFormFields | undefined = undefined; let review_location_gcs: LocationGcs | undefined = undefined; - let loading_submit = false; - let loading_map = false; - let loading_location_gcs = false; - $: num_trade_product_qty_amt = preview_trade_product ? Number(preview_trade_product.qty_amt) : 0; @@ -224,21 +223,6 @@ })(); } - onMount(async () => { - try { - carousel_index.set(0); - carousel_index_max.set(Array.from(carousel_conf.keys()).length - 1); - - sel_trade_product_price_currency = "eur"; - sel_trade_product_price_qty_unit = "kg"; - sel_trade_product_qty_unit = "kg"; - await fetch_models_models_location_gcs(); - } catch (e) { - } finally { - view = `form_1`; - } - }); - carousel_index.subscribe(async (_carousel_index) => { if (_carousel_index === 1) { const kv_qty_avail = await kv.get(fmt_id(`qty_avail`)); @@ -247,52 +231,56 @@ } }); - const handle_carousel_prev = async (): Promise<void> => { + const handle_view = async (new_view: View): Promise<void> => { + try { + if (new_view === `map`) { + loading_map = true; + const geoloc = await geol.current(); + if (`err` in geoloc) return; + else { + map_point_location_gcs = geoloc; + map_point_location_gcs_select = geoloc; + } + loading_map = false; + } + view = new_view; + } catch (e) { + console.log(`(error) handle_view `, e); + } + }; + + const handle_back = async (): Promise<void> => { try { switch ($carousel_index) { - case 1: - { - await carousel_prev(view); - } - break; - case 2: - { - await carousel_prev(view); - } - break; - case 3: - { - await carousel_prev(view); - } - break; - case 4: + default: { await carousel_prev(view); } break; } } catch (e) { - console.log(`(error) handle_carousel_prev `, e); + console.log(`(error) handle_back `, e); } }; - const handle_carousel_next = async (): Promise<void> => { + const handle_continue = async (): Promise<void> => { try { switch ($carousel_index) { case 0: { - const vals_init = await validate_trade_product_vals({ - kv_pref: fmt_id(), - no_validation: [ - `year`, - `price_qty_amt`, - `qty_avail`, - `summary`, - `title`, - ], - }); + const vals_init = + await kv_validate_trade_product_fields({ + kv_pref: fmt_id(), + no_validation: [ + `year`, + `price_qty_amt`, + `qty_avail`, + `summary`, + `title`, + ], + }); if (`err` in vals_init) { - await lc.dialog.alert( + await dialog.alert( `${$t(`trade.product.fields.${vals_init.err}.err_invalid`, { default: `${$t(`icu.invalid_*`, { value: vals_init.err })}` })}`, ); return; @@ -308,12 +296,14 @@ if (!vals_init.qty_avail) await kv.set(fmt_id(`qty_avail`), `1`); - const vals = await validate_trade_product_vals({ + const vals = await kv_validate_trade_product_fields({ kv_pref: fmt_id(), no_validation: [`summary`, `title`], }); if (`err` in vals) { - await lc.dialog.alert(`The entry is incomplete`); + await dialog.alert( + `${$t(`trade.product.fields.${vals.err}.err_invalid`, { default: `${$t(`icu.invalid_*`, { value: vals.err })}` })}`, + ); return; } preview_trade_product = vals; @@ -327,11 +317,16 @@ break; case 2: { - const vals = await validate_trade_product_vals({ + const vals = await kv_validate_trade_product_fields({ kv_pref: fmt_id(), }); if (`err` in vals) { - await lc.dialog.alert(`Enter the listing details`); + await dialog.alert( + `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_title`, { value: `${$t(`common.listing`)}` })}`.toLowerCase() })}`, + ); + el_id(fmt_id(`${vals.err}_wrap`))?.classList.add( + `line-entry-highlight-1`, + ); return; } await carousel_next(`form_1`); @@ -343,38 +338,36 @@ fmt_id(`location_gcs_id`), ); if (!location_gcs_kv_id) { - await lc.dialog.alert( - `The product location is missing`, + await dialog.alert( + `${$t(`icu.the_*_is_missing`, { value: `${$t(`common.product_location`)}`.toLowerCase() })}`, ); - return; - //@todo + return; //@todo } - const location_gcs_get = await lc.db.location_gcs_get({ + const location_gcs_get = await db.location_gcs_get({ id: location_gcs_kv_id, }); if (`err` in location_gcs_get) { - await lc.dialog.alert( - `The product location is missing`, + await dialog.alert( + `${$t(`error.client.unhandled`)}`, ); preview_trade_product = undefined; - return; - //@todo + return; //@todo } else if (location_gcs_get.results.length < 1) { - await lc.dialog.alert( - `The product location is missing`, + await dialog.alert( + `${$t(`error.client.unhandled`)}`, ); preview_trade_product = undefined; - return; - //@todo + return; //@todo } review_location_gcs = location_gcs_get.results[0]; - const vals = await validate_trade_product_vals({ + const vals = await kv_validate_trade_product_fields({ kv_pref: fmt_id(), }); if (`err` in vals) { - await lc.dialog.alert(`The entry is incomplete`); - return; - //@todo + await dialog.alert( + `${$t(`trade.product.fields.${vals.err}.err_invalid`, { default: `${$t(`icu.invalid_*`, { value: vals.err })}` })}`, + ); + return; //@todo } review_trade_product = vals; await carousel_next(`form_1`); @@ -387,7 +380,7 @@ break; } } catch (e) { - console.log(`(error) handle_carousel_next `, e); + console.log(`(error) handle_continue `, e); } }; @@ -426,7 +419,7 @@ const fetch_models_models_location_gcs = async (): Promise<void> => { try { - const res = await lc.db.location_gcs_get({ + const res = await db.location_gcs_get({ list: [`all`], }); if (`results` in res) ls_models_location_gcs = res.results; @@ -438,7 +431,26 @@ const handle_add_current_location = async (): Promise<void> => { try { loading_location_gcs = true; - await location_gcs_add_current(); + const geo_loc = await geol.current(); + if (`err` in geo_loc) { + await dialog.alert( + `${$t(`error.geolocation.request.current`)}`, + ); + return; + } + const res = await model_location_gcs_add_position({ geo_loc }); + if (`err` in res) { + await dialog.alert( + `${$t(`icu.unable_to_save_*`, { value: `${$t(`common.location`)}. ${res.err}`.toLowerCase() })}`, + ); + return; //@todo + } else if (`err_s` in res) { + await dialog.alert( + `${$t(`icu.unable_to_save_*`, { value: `${$t(`common.location`)} ${res.err_s}`.toLowerCase() })}`, + ); + return; //@todo + } + sel_location_gcs_id = res.id; await fetch_models_models_location_gcs(); } catch (e) { console.log(`(error) handle_add_current_location `, e); @@ -450,17 +462,25 @@ const handle_add_map_location = async (): Promise<void> => { try { if (!map_point_location_gcs_select_geoc) { - await lc.dialog.alert(`No location selected`); + await dialog.alert( + `${$t(`icu.no_*_selected`, { value: `${$t(`common.location`)}`.toLowerCase() })}`, + ); return; } - const res = await location_gcs_add_geoc({ - geoc: map_point_location_gcs_select_geoc, + const res = await model_location_gcs_add_geocode({ + geo_code: map_point_location_gcs_select_geoc, }); if (`err` in res) { - await lc.dialog.alert(res.err || `There was an error`); - return; + await dialog.alert( + `${$t(`icu.unable_to_save_*`, { value: `${$t(`common.location`)}. ${res.err}`.toLowerCase() })}`, + ); + return; //@todo + } else if (`err_s` in res) { + await dialog.alert( + `${$t(`icu.unable_to_save_*`, { value: `${$t(`common.location`)} ${res.err_s}`.toLowerCase() })}`, + ); + return; //@todo } - sel_location_gcs_id = res.id; await fetch_models_models_location_gcs(); } catch (e) { @@ -480,851 +500,818 @@ </script> <LayoutView> - <LayoutTrellis> - <div - data-view={`load`} - class={`flex flex-col h-full w-full justify-start items-start`} - > - <Fill /> - </div> + <div + data-view={`load`} + class={`flex flex-col h-full w-full justify-start items-start`} + > + <Fill /> + </div> + <div + data-view={`form_1`} + class={`hidden flex flex-col h-full w-full justify-start items-center`} + > <div - data-view={`form_1`} data-carousel-container={`form_1`} - class={`hidden carousel-container carousel-container-trellis`} + class={`carousel-container flex h-full w-full`} > <div data-carousel-item={`form_1`} - class={`carousel-item carousel-item-trellis`} + class={`carousel-item flex flex-col w-full justify-start items-center`} > - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.product`)}`, - }, - notify: show_sel_trade_product_key_other - ? { - classes: `w-full justify-end`, - label: { - value: `Show Options`, - }, - callback: async () => { - await toggle_show_key_other(false); - }, - } - : undefined, - }} - > - {#if show_sel_trade_product_key_other} - <div - class={`relative flex flex-row w-full justify-center items-center`} - > - <InputForm - basis={{ - id: fmt_id(`key`), - sync: true, - placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`common.product_name`)}`.toLowerCase() })}`, - - field: { - charset: - trade_product_form_fields.key - .charset, - validate: - trade_product_form_fields.key - .validation, - validate_keypress: true, - }, - }} - /> - </div> - {:else} - <InputSelect - bind:value={sel_trade_product_key} - basis={{ - id_wrap: fmt_id(`key_wrap`), - id: fmt_id(`key`), - classes: `font-mono-display`, - sync: true, - options: [ - ...trade_keys.map((i) => ({ - value: i, - label: `${$t(`trade.product.key.${i}`, { default: i })}`, - })), - { - value: `other`, - label: `${$t(`common.other`)}`, - }, - ], - callback: async (val) => { - if (val === `other`) { - await toggle_show_key_other(true); - } - }, - }} - /> - {/if} - </LayoutTrellisLine> - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.price`)}`, - }, - }} - > - <div - bind:this={el_trellis_wrap_price} - id={fmt_id(`price_wrap`)} - tabindex={-1} - class={`relative form-line-active flex flex-row w-full gap-3 justify-between items-center h-form_line bg-layer-1-surface text-layer-1-glyph rounded-2xl transition-all`} - > - <InputForm - basis={{ - id: fmt_id(`price_amt`), - layer: false, - sync: true, - sync_init: false, - classes: `font-mono-display`, - placeholder: `${$t(`icu.enter_*`, { value: `${$t(`common.price`)}` })}`, - field: { - charset: - trade_product_form_fields.price_amt - .charset, - validate: - trade_product_form_fields.price_amt - .validation, - validate_keypress: true, - }, - callback: async ({ val, pass }) => { - const lastchar = val[val.length - 1]; - const period_count = - val.split(".").length - 1; - if ( - (pass && - lastchar !== `.` && - period_count < 2) || - val.length < 1 - ) { - el_trellis_wrap_price?.classList.remove( - `bg-layer-1-surface-err`, - ); - show_sel_trade_product_price_currency = false; - } else { - el_trellis_wrap_price?.classList.add( - `bg-layer-1-surface-err`, - ); - show_sel_trade_product_price_currency = true; - } - }, - }} - /> - <div - class={`flex flex-row gap-2 pr-4 justify-end items-center text-layer-1-glyph/70`} - > - <InputSelect - bind:value={sel_trade_product_price_currency} - basis={{ - id: fmt_id(`price_currency`), - classes: `w-fit font-mono-display font-[500] text-lg`, - layer: false, - hide_arrows: true, - sync: true, - options: fiat_currencies.map((i) => ({ - value: i, - label: `${$t(`currency.${i}.symbol`, { default: i })}`, - })), - }} - /> - <p - class={`font-sans font-[500] text-[1.1rem] -translate-y-[1px] scale-y-[110%]`} - > - {`/`} - </p> - <InputSelect - bind:value={sel_trade_product_price_qty_unit} - basis={{ - id: fmt_id(`price_qty_unit`), - classes: `w-fit font-mono-display font-[600] text-[0.95rem] leading-[1rem]`, - layer: false, - hide_arrows: true, - sync: true, - options: mass_units.map((i) => ({ - value: i, - label: `${$t(`measurement.mass.unit.${i}_ab`, { default: i })}`, - })), - }} - /> - </div> - {#if show_sel_trade_product_price_currency} - <NotifyGlyph - basis={{ - glyph: `warning-circle`, - layer: 2, - classes: `translate-x-[32px]`, - }} - /> - {/if} - </div> - </LayoutTrellisLine> - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.quantity`)}`, - }, - notify: show_sel_trade_product_qty_tup_other - ? { - classes: `w-full justify-end`, - label: { - value: `Show Options`, - }, - callback: async () => { - await toggle_show_qty_amt_other(false); - }, - } - : undefined, - }} - > - <div - id={fmt_id(`qty_wrap`)} - tabindex={-1} - class={`relative form-line-active flex flex-row w-full gap-3 justify-between items-center h-form_line bg-layer-1-surface text-layer-1-glyph rounded-2xl transition-all`} + <LayoutTrellis> + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`common.product`)}`, + }, + notify: show_sel_trade_product_key_other + ? { + classes: `w-full justify-end`, + label: { + value: `${$t(`icu.show_*`, { value: `${$t(`common.options`)}` })}`, + }, + callback: async () => { + await toggle_show_key_other(false); + }, + } + : undefined, + }} > - {#if show_sel_trade_product_qty_tup_other} + {#if show_sel_trade_product_key_other} <div - class={`relative flex flex-row w-full justify-center items-center`} + class={`relative flex flex-row w-full justify-center items-center rounded-2xl`} > - <InputForm + <EntryLine basis={{ - id: fmt_id(`qty_amt`), - layer: false, - sync: true, - placeholder: `${$t(`icu.enter_number_of_*_per_order`, { value: `${$t(`measurement.mass.unit.${sel_trade_product_price_qty_unit}_ab`, { default: sel_trade_product_price_qty_unit })}` })}`, - field: { - charset: - trade_product_form_fields - .qty_amt.charset, - validate: - trade_product_form_fields - .qty_amt.validation, - validate_keypress: true, + el: { + id: fmt_id(`title`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_title`, { value: `${$t(`common.listing`)}` })}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields + .title.charset, + validate: + trade_product_form_fields + .title.validation, + validate_keypress: true, + }, }, }} /> - <div - class={`absolute top-0 right-0 flex flex-row h-full gap-2 justify-center items-center`} - > - <InputSelect - bind:value={sel_trade_product_qty_unit} - basis={{ - id: fmt_id(`qty_unit`), - classes: `w-[3.5rem] text-layer-1-glyph font-[500]`, - layer: false, - sync: true, - options: mass_units.map((i) => ({ - value: i, - label: `${$t(`measurement.mass.unit.${i}_ab`, { default: i })}`, - })), - }} - /> - </div> </div> {:else} - <InputSelect - bind:value={sel_trade_product_qty_tup} + <EntryOption + bind:value={sel_trade_product_key} basis={{ + id_wrap: fmt_id(`key_wrap`), + id: fmt_id(`key`), classes: `font-mono-display`, + sync: true, options: [ - ...ls_trade_product_quantities.map( - (i) => ({ - value: fmt_trade_quantity_val( - i, - ), - label: `${i.mass} ${$t(`measurement.mass.unit.${i.mass_unit}_ab`, { default: i.mass_unit })} ${i.label}`, - }), - ), + ...trade_keys.map((i) => ({ + value: i, + label: `${$t(`trade.product.key.${i}`, { default: i })}`, + })), { value: `other`, label: `${$t(`common.other`)}`, }, ], callback: async (val) => { + el_id( + fmt_id(`key_wrap`), + )?.classList.remove( + `entry-layer-1-highlight`, + ); if (val === `other`) { - await toggle_show_qty_amt_other( - true, + await toggle_show_key_other(true); + } + }, + }} + /> + {/if} + </LayoutTrellisLine> + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`common.price`)}`, + }, + }} + > + <div + bind:this={el_trellis_wrap_price} + id={fmt_id(`price_wrap`)} + tabindex={-1} + class={`relative el-responsive flex flex-row w-full pl-2 justify-between items-center h-form_line bg-layer-1-surface rounded-2xl`} + > + <InputElement + basis={{ + id: fmt_id(`price_amt`), + layer: 1, + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_*`, { value: `${$t(`common.price`)}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.price_amt + .charset, + validate: + trade_product_form_fields.price_amt + .validation, + validate_keypress: true, + }, + callback: async ({ value, pass }) => { + const lastchar = + value[value.length - 1]; + const period_count = + value.split(".").length - 1; + if ( + (pass && + lastchar !== `.` && + period_count < 2) || + value.length < 1 + ) { + el_trellis_wrap_price?.classList.remove( + `entry-layer-1-highlight`, ); } else { - await kv.set( - fmt_id(`qty_avail`), - `1`, + el_trellis_wrap_price?.classList.add( + `entry-layer-1-highlight`, ); } }, }} /> - {/if} - </div> - </LayoutTrellisLine> - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.lot`)}`, - }, - }} - > - <InputForm + <div + class={`flex flex-row gap-2 pl-3 pr-4 justify-end items-center bg-layer-1-surface rounded-r-2xl text-layer-1-glyph/70`} + > + <EntryOption + bind:value={sel_trade_product_price_currency} + basis={{ + id: fmt_id(`price_currency`), + classes: `w-fit font-mono-display font-[500] text-lg`, + layer: false, + hide_arrows: true, + sync: true, + options: fiat_currencies.map((i) => ({ + value: i, + label: `${$t(`currency.${i}.symbol`, { default: i })}`, + })), + }} + /> + <p + class={`font-sans font-[500] text-[1.1rem] -translate-y-[1px] scale-y-[110%]`} + > + {`/`} + </p> + <EntryOption + bind:value={sel_trade_product_price_qty_unit} + basis={{ + id: fmt_id(`price_qty_unit`), + classes: `w-fit font-mono-display font-[600] text-[0.95rem] leading-[1rem]`, + layer: false, + hide_arrows: true, + sync: true, + options: mass_units.map((i) => ({ + value: i, + label: `${$t(`measurement.mass.unit.${i}_ab`, { default: i })}`, + })), + }} + /> + </div> + </div> + </LayoutTrellisLine> + <LayoutTrellisLine basis={{ - id: fmt_id(`lot`), - sync: true, - placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`common.lot_name`)}`.toLowerCase() })}`, - field: { - charset: trade_product_form_fields.lot.charset, - validate: - trade_product_form_fields.lot.validation, - validate_keypress: true, + label: { + value: `${$t(`common.quantity`)}`, }, + notify: show_sel_trade_product_qty_tup_other + ? { + classes: `w-full justify-end`, + label: { + value: `${$t(`icu.show_*`, { value: `${$t(`common.options`)}` })}`, + }, + callback: async () => { + await toggle_show_qty_amt_other( + false, + ); + }, + } + : undefined, }} - /> - </LayoutTrellisLine> - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`model_fields.process`)}`, - }, - }} - > - <InputForm + > + <div + id={fmt_id(`qty_wrap`)} + tabindex={-1} + class={`relative el-responsive flex flex-row w-full gap-3 justify-between items-center h-form_line bg-layer-1-surface text-layer-1-glyph rounded-2xl`} + > + {#if show_sel_trade_product_qty_tup_other} + <div + class={`relative flex flex-row w-full justify-center items-center`} + > + <EntryLine + basis={{ + el: { + id: fmt_id(`qty_amt`), + layer: false, + sync: true, + placeholder: `${$t(`icu.enter_number_of_*_per_order`, { value: `${$t(`measurement.mass.unit.${sel_trade_product_price_qty_unit}_ab`, { default: sel_trade_product_price_qty_unit })}` })}`, + field: { + charset: + trade_product_form_fields + .qty_amt.charset, + validate: + trade_product_form_fields + .qty_amt.validation, + validate_keypress: true, + }, + }, + }} + /> + <div + class={`absolute top-0 right-0 flex flex-row h-full gap-2 justify-center items-center`} + > + <EntryOption + bind:value={sel_trade_product_qty_unit} + basis={{ + id: fmt_id(`qty_unit`), + classes: `w-[3.5rem] text-layer-1-glyph font-[500]`, + layer: false, + sync: true, + options: mass_units.map( + (i) => ({ + value: i, + label: `${$t(`measurement.mass.unit.${i}_ab`, { default: i })}`, + }), + ), + }} + /> + </div> + </div> + {:else} + <EntryOption + bind:value={sel_trade_product_qty_tup} + basis={{ + classes: `font-mono-display`, + options: [ + ...ls_trade_product_quantities.map( + (i) => ({ + value: fmt_trade_quantity_val( + i, + ), + label: `${i.mass} ${$t(`measurement.mass.unit.${i.mass_unit}_ab`, { default: i.mass_unit })} ${i.label}`, + }), + ), + { + value: `other`, + label: `${$t(`common.other`)}`, + }, + ], + callback: async (val) => { + el_id( + fmt_id(`qty_wrap`), + )?.classList.remove( + `entry-layer-1-highlight`, + ); + if (val === `other`) { + await toggle_show_qty_amt_other( + true, + ); + } else { + await kv.set( + fmt_id(`qty_avail`), + `1`, + ); + } + }, + }} + /> + {/if} + </div> + </LayoutTrellisLine> + <LayoutTrellisLine basis={{ - id: fmt_id(`process`), - sync: true, - placeholder: `Enter the process description`, - field: { - charset: - trade_product_form_fields.process.charset, - validate: - trade_product_form_fields.process - .validation, - validate_keypress: true, + label: { + value: `${$t(`model.trade_product.lot`)}`, }, }} - /> - </LayoutTrellisLine> - </div> - <div - data-carousel-item={`form_1`} - class={`carousel-item carousel-item-trellis`} - > - {#if preview_trade_product && preview_trade_product_price_currency} + > + <EntryLine + basis={{ + el: { + id: fmt_id(`lot`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_*`, { value: `${$t(`common.lot_name`)}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.lot + .charset, + validate: + trade_product_form_fields.lot + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> <LayoutTrellisLine basis={{ label: { - value: `${$t(`icu.*_details`, { value: `${$t(`common.product`)}` })}`, + value: `${$t(`model.trade_product.process`)}`, }, }} > - <div - class={`relative flex flex-col h-[30rem] w-full px-4 py-2 gap-4 justify-around items-start bg-layer-1-surface rounded-3xl`} + <EntryLine + basis={{ + el: { + id: fmt_id(`process`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_*`, { value: `${$t(`icu.*_description`, { value: `${$t(`common.process`)}` })}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.process + .charset, + validate: + trade_product_form_fields.process + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> + </LayoutTrellis> + </div> + <div + data-carousel-item={`form_1`} + class={`carousel-item flex flex-col w-full justify-start items-center`} + > + <LayoutTrellis> + {#if preview_trade_product && preview_trade_product_price_currency} + <LayoutTrellisLine + basis={{ + label: { + value: `${$t(`icu.*_details`, { value: `${$t(`common.product`)}` })}`, + }, + }} > <div - class={`flex flex-col w-full gap-5 justify-around items-center`} + class={`relative flex flex-col h-[30rem] w-full px-4 py-2 gap-4 justify-around items-start bg-layer-1-surface rounded-3xl`} > <div - class={`flex flex-col w-full gap-2 justify-start items-start`} + class={`flex flex-col w-full gap-5 justify-around items-center`} > - <p - class={`font-mono font-[400] text-layer-1-glyph`} - > - {`${$t(`common.product`)}:`} - </p> <div - class={`flex flex-row w-full justify-between items-center`} + class={`flex flex-col w-full gap-2 justify-start items-start`} > - <div - class={`flex flex-row flex-grow gap-2 justify-start items-center`} + <p + class={`font-mono font-[400] text-layer-1-glyph`} > - <p - class={`font-mono font-[400] text-layer-2-glyph pr-2`} - > - {`-`} - </p> - - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {`${preview_trade_product.key}`} - </p> - </div> + {`${$t(`common.product`)}:`} + </p> <div - class={`flex flex-row justify-end items-center`} + class={`flex flex-row w-full justify-between items-center`} > - <button - class={`flex flex-row justify-start items-center active:opacity-60 transition-all`} - on:click={async () => { - const el = el_id( - fmt_id(`key_wrap`), - ); - if (el) el.focus(); - await handle_carousel_prev(); - }} + <div + class={`flex flex-row flex-grow gap-2 justify-start items-center`} > <p - class={`font-mono font-[500] text-layer-2-glyph text-sm`} + class={`font-mono font-[400] text-layer-2-glyph pr-2`} + > + {`-`} + </p> + + <p + class={`font-mono font-[400] text-layer-2-glyph`} > - {`${$t(`common.edit`)}`} + {`${preview_trade_product.key}`} </p> - </button> + </div> + <div + class={`flex flex-row justify-end items-center`} + > + <button + class={`flex flex-row justify-start items-center active:opacity-60 transition-all`} + on:click={async () => { + const el = el_id( + fmt_id(`key_wrap`), + ); + if (el) { + el.classList.add( + `entry-layer-1-highlight`, + ); + el.focus(); + } + await handle_back(); + }} + > + <p + class={`font-mono font-[500] text-layer-2-glyph text-sm`} + > + {`${$t(`common.edit`)}`} + </p> + </button> + </div> </div> </div> - </div> - <div - class={`flex flex-col w-full gap-2 justify-start items-start`} - > - <p - class={`font-mono font-[400] text-layer-1-glyph`} - > - {`${$t(`common.price`)}:`} - </p> <div - class={`flex flex-row w-full justify-between items-center`} + class={`flex flex-col w-full gap-2 justify-start items-start`} > + <p + class={`font-mono font-[400] text-layer-1-glyph`} + > + {`${$t(`common.price`)}:`} + </p> <div - class={`flex flex-row flex-grow gap-2 justify-start items-center`} + class={`flex flex-row w-full justify-between items-center`} > - <p - class={`font-mono font-[400] text-layer-2-glyph pr-2`} + <div + class={`flex flex-row flex-grow gap-2 justify-start items-center`} > - {`-`} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {preview_trade_product_price_currency.symbol} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {`${(preview_trade_product_price_currency.val_i + preview_trade_product_price_currency.val_f).toFixed(2)}`} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph lowercase`} - > - {`${$t(`common.per`)}`} - </p> - {#if preview_trade_product.price_qty_amt === `1`} + <p + class={`font-mono font-[400] text-layer-2-glyph pr-2`} + > + {`-`} + </p> <p class={`font-mono font-[400] text-layer-2-glyph`} > - {`${$t(`measurement.mass.unit.${preview_trade_product.price_qty_unit}_ab`, { default: preview_trade_product.price_qty_unit })}`} + {preview_trade_product_price_currency.symbol} + </p> + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {`${(preview_trade_product_price_currency.val_i + preview_trade_product_price_currency.val_f).toFixed(2)}`} </p> - {/if} - </div> - <div - class={`flex flex-row justify-end items-center`} - > - <button - class={`flex flex-row justify-start items-center active:opacity-60 transition-all`} - on:click={async () => { - const el = el_id( - fmt_id(`price_wrap`), - ); - if (el) el.focus(); - await handle_carousel_prev(); - }} - > <p - class={`font-mono font-[500] text-layer-2-glyph text-sm`} + class={`font-mono font-[400] text-layer-2-glyph lowercase`} > - {`${$t(`common.edit`)}`} + {`${$t(`common.per`)}`} </p> - </button> + {#if preview_trade_product.price_qty_amt === `1`} + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {`${$t(`measurement.mass.unit.${preview_trade_product.price_qty_unit}_ab`, { default: preview_trade_product.price_qty_unit })}`} + </p> + {/if} + </div> + <div + class={`flex flex-row justify-end items-center`} + > + <button + class={`flex flex-row justify-start items-center active:opacity-60 transition-all`} + on:click={async () => { + const el = el_id( + fmt_id( + `price_wrap`, + ), + ); + if (el) { + el.classList.add( + `entry-layer-1-highlight`, + ); + el.focus(); + } + await handle_back(); + }} + > + <p + class={`font-mono font-[500] text-layer-2-glyph text-sm`} + > + {`${$t(`common.edit`)}`} + </p> + </button> + </div> </div> </div> - </div> - <div - class={`flex flex-col w-full gap-2 justify-start items-start`} - > - <p - class={`font-mono font-[400] text-layer-1-glyph`} - > - {`${$t(`common.quantity`)}:`} - </p> <div - class={`flex flex-row w-full justify-between items-center`} + class={`flex flex-col w-full gap-2 justify-start items-start`} > - <div - class={`flex flex-row flex-grow gap-2 justify-start items-center`} + <p + class={`font-mono font-[400] text-layer-1-glyph`} > - <p - class={`font-mono font-[400] text-layer-2-glyph pr-2`} - > - {`-`} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {preview_trade_product.qty_amt} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {`${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })}`} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {preview_trade_product.qty_label} - </p> - </div> + {`${$t(`common.quantity`)}:`} + </p> <div - class={`flex flex-row justify-end items-center`} + class={`flex flex-row w-full justify-between items-center`} > - <button - class={`flex flex-row justify-start items-center active:opacity-60 transition-all`} - on:click={async () => { - const el = el_id( - fmt_id(`qty_wrap`), - ); - if (el) el.focus(); - await handle_carousel_prev(); - }} + <div + class={`flex flex-row flex-grow gap-2 justify-start items-center`} > <p - class={`font-mono font-[500] text-layer-2-glyph text-sm`} + class={`font-mono font-[400] text-layer-2-glyph pr-2`} + > + {`-`} + </p> + <p + class={`font-mono font-[400] text-layer-2-glyph`} > - {`${$t(`common.edit`)}`} + {preview_trade_product.qty_amt} </p> - </button> + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {`${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })}`} + </p> + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {preview_trade_product.qty_label} + </p> + </div> + <div + class={`flex flex-row justify-end items-center`} + > + <button + class={`flex flex-row justify-start items-center active:opacity-60 transition-all`} + on:click={async () => { + const el = el_id( + fmt_id(`qty_wrap`), + ); + if (el) { + el.classList.add( + `entry-layer-1-highlight`, + ); + el.focus(); + } + await handle_back(); + }} + > + <p + class={`font-mono font-[500] text-layer-2-glyph text-sm`} + > + {`${$t(`common.edit`)}`} + </p> + </button> + </div> </div> </div> - </div> - <div - class={`flex flex-col w-full gap-2 justify-start items-start`} - > - <p - class={`font-mono font-[400] text-layer-1-glyph`} - > - {`${$t(`icu.*_available`, { value: `${$t(`common.quantity`)}` })}:`} - </p> <div - class={`flex flex-row w-full justify-between items-center`} + class={`flex flex-col w-full gap-2 justify-start items-start`} > + <p + class={`font-mono font-[400] text-layer-1-glyph`} + > + {`${$t(`icu.*_available`, { value: `${$t(`common.quantity`)}` })}:`} + </p> <div - class={`flex flex-row flex-grow gap-2 justify-start items-center`} + class={`flex flex-row w-full justify-between items-center`} > - <p - class={`font-mono font-[400] text-layer-2-glyph pr-2`} - > - {`-`} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} + <div + class={`flex flex-row flex-grow gap-2 justify-start items-center`} > - {`${preview_trade_product_qty_avail} ${preview_trade_product.qty_label}`} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} + <p + class={`font-mono font-[400] text-layer-2-glyph pr-2`} + > + {`-`} + </p> + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {`${preview_trade_product_qty_avail} ${preview_trade_product.qty_label}`} + </p> + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {`(${(preview_trade_product_qty_avail * num_trade_product_qty_amt).toFixed(2)} ${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })})`} + </p> + </div> + <div + class={`flex flex-row gap-[10px] justify-center items-center`} > - {`(${(preview_trade_product_qty_avail * num_trade_product_qty_amt).toFixed(2)} ${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })})`} - </p> - </div> - <div - class={`flex flex-row gap-[10px] justify-center items-center`} - > - <Glyph - basis={{ - key: `arrow-down`, - dim: `xs`, - weight: `bold`, - classes: `h-6 w-6 text-layer-2-glyph bg-layer-2-surface active:opacity-60 rounded-full transition-all`, - callback: async () => { - preview_trade_product_qty_avail = - int_step( - preview_trade_product_qty_avail, - `-`, - 1, + <Glyph + basis={{ + key: `arrow-down`, + dim: `xs`, + weight: `bold`, + classes: `h-6 w-6 text-layer-2-glyph bg-layer-2-surface active:opacity-60 rounded-full transition-all`, + callback: async () => { + preview_trade_product_qty_avail = + int_step( + preview_trade_product_qty_avail, + `-`, + 1, + ); + await kv.set( + fmt_id( + `qty_avail`, + ), + preview_trade_product_qty_avail.toString(), ); - await kv.set( - fmt_id(`qty_avail`), - preview_trade_product_qty_avail.toString(), - ); - }, - }} - /> - <Glyph - basis={{ - key: `arrow-up`, - dim: `xs`, - weight: `bold`, - classes: `h-6 w-6 text-layer-2-glyph bg-layer-2-surface active:opacity-60 rounded-full transition-all`, - callback: async () => { - preview_trade_product_qty_avail = - int_step( - preview_trade_product_qty_avail, - `+`, + }, + }} + /> + <Glyph + basis={{ + key: `arrow-up`, + dim: `xs`, + weight: `bold`, + classes: `h-6 w-6 text-layer-2-glyph bg-layer-2-surface active:opacity-60 rounded-full transition-all`, + callback: async () => { + preview_trade_product_qty_avail = + int_step( + preview_trade_product_qty_avail, + `+`, + ); + await kv.set( + fmt_id( + `qty_avail`, + ), + preview_trade_product_qty_avail.toString(), ); - await kv.set( - fmt_id(`qty_avail`), - preview_trade_product_qty_avail.toString(), - ); - }, - }} - /> + }, + }} + /> + </div> </div> </div> </div> - </div> - <div - class={`flex flex-row w-full justify-start items-center`} - > <div - class={` flex flex-row h-[1px] w-full justify-start items-center bg-layer-2-surface`} + class={`flex flex-row w-full justify-start items-center`} > - <Fill /> + <div + class={` flex flex-row h-[1px] w-full justify-start items-center bg-layer-2-surface`} + > + <Fill /> + </div> </div> - </div> - <div - class={`flex flex-col w-full gap-4 justify-start items-start`} - > <div class={`flex flex-col w-full gap-4 justify-start items-start`} > <div - class={`flex flex-row w-full justify-between items-center`} + class={`flex flex-col w-full gap-4 justify-start items-start`} > <div - class={`flex flex-row justify-start items-center`} + class={`flex flex-row w-full justify-between items-center`} > - <p - class={`font-mono font-[400] text-layer-1-glyph text-lg`} + <div + class={`flex flex-row justify-start items-center`} > - {`${`${$t(`common.quantity`)}`}:`} - </p> - </div> - <div - class={`flex flex-row gap-2 justify-start items-center`} - > - <p - class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`} - > - {preview_trade_product_qty_avail} - </p> - <p - class={`font-mono font-[400] text-layer-2-glyph`} - > - {`x`} - </p> - <p - class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`} - > - {`${num_trade_product_qty_amt.toFixed(2)} ${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })}`} - </p> - <p - class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`} - > - {preview_trade_product.qty_label} - </p> - </div> - </div> - <div - class={`flex flex-row w-full justify-between items-center`} - > - <div - class={`flex flex-row justify-start items-center`} - > - <p - class={`font-mono font-[400] text-layer-1-glyph text-lg`} + <p + class={`font-mono font-[400] text-layer-1-glyph text-lg`} + > + {`${`${$t(`common.quantity`)}`}:`} + </p> + </div> + <div + class={`flex flex-row gap-2 justify-start items-center`} > - {`${$t(`icu.total_*`, { value: `${$t(`common.price`)}`.toLowerCase() })}:`} - </p> + <p + class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`} + > + {preview_trade_product_qty_avail} + </p> + <p + class={`font-mono font-[400] text-layer-2-glyph`} + > + {`x`} + </p> + <p + class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`} + > + {`${num_trade_product_qty_amt.toFixed(2)} ${$t(`measurement.mass.unit.${preview_trade_product.qty_unit}_ab`, { default: preview_trade_product.qty_unit })}`} + </p> + <p + class={`font-mono font-[500] text-layer-1-glyph/80 text-lg`} + > + {preview_trade_product.qty_label} + </p> + </div> </div> <div - class={`flex flex-row gap-2 justify-start items-center`} + class={`flex flex-row w-full justify-between items-center`} > - <p - class={`font-mono font-[400] text-layer-2-glyph`} + <div + class={`flex flex-row justify-start items-center`} > - {preview_trade_product_price_currency.symbol} - </p> - <p - class={`font-mono font-[600] text-layer-1-glyph/80 text-lg`} - > - {num_trade_product_price_total.toFixed( - 2, - )} - </p> - <p - class={`font-mono font-[600] text-layer-1-glyph/80 text-lg uppercase`} + <p + class={`font-mono font-[400] text-layer-1-glyph text-lg`} + > + {`${$t(`icu.total_*`, { value: `${$t(`common.price`)}`.toLowerCase() })}:`} + </p> + </div> + <div + class={`flex flex-row gap-2 justify-start items-center`} > - {preview_trade_product_price_currency.currency} - </p> + <p + class={`font-mono font-[400] text-layer-2-glyph text-lg`} + > + {preview_trade_product_price_currency.symbol} + </p> + <p + class={`font-mono font-[600] text-layer-1-glyph/80 text-lg`} + > + {num_trade_product_price_total.toFixed( + 2, + )} + </p> + <p + class={`font-mono font-[600] text-layer-1-glyph/80 text-lg uppercase`} + > + {preview_trade_product_price_currency.currency} + </p> + </div> </div> </div> </div> </div> - </div> - </LayoutTrellisLine> - {/if} + </LayoutTrellisLine> + {/if} + </LayoutTrellis> </div> <div data-carousel-item={`form_1`} - class={`carousel-item carousel-item-trellis`} + class={`carousel-item flex flex-col w-full justify-start items-center`} > - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.title`)}`, - }, - }} - > - <InputElement + <LayoutTrellis> + <LayoutTrellisLine basis={{ - id: fmt_id(`title`), - sync: true, - placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.listing_*`, { value: `${$t(`common.title`)}` })}`.toLowerCase() })}`, - field: { - charset: - trade_product_form_fields.title.charset, - validate: - trade_product_form_fields.title.validation, - validate_keypress: true, + label: { + value: `${$t(`common.title`)}`, }, }} - /> - </LayoutTrellisLine> - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.summary`)}`, - }, - }} - > - <TextareaElement + > + <EntryLine + basis={{ + id_wrap: fmt_id(`title_wrap`), + el: { + id: fmt_id(`title`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_title`, { value: `${$t(`common.listing`)}` })}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.title + .charset, + validate: + trade_product_form_fields.title + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> + <LayoutTrellisLine basis={{ - classes: `h-[25rem] p-4 rounded-3xl`, - id: fmt_id(`summary`), - sync: true, - placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.listing_*`, { value: `${$t(`common.summary`)}` })}`.toLowerCase() })}`, - field: { - charset: - trade_product_form_fields.summary.charset, - validate: - trade_product_form_fields.summary - .validation, - validate_keypress: true, + label: { + value: `${$t(`common.summary`)}`, }, }} - /> - </LayoutTrellisLine> + > + <EntryMultiline + basis={{ + id_wrap: fmt_id(`summary_wrap`), + el: { + classes: `h-[20rem]`, + id: fmt_id(`summary`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_the_*`, { value: `${$t(`icu.*_summary`, { value: `${$t(`common.listing`)}` })}`.toLowerCase() })}`, + field: { + charset: + trade_product_form_fields.summary + .charset, + validate: + trade_product_form_fields.summary + .validation, + validate_keypress: true, + }, + }, + }} + /> + </LayoutTrellisLine> + </LayoutTrellis> </div> <div data-carousel-item={`form_1`} - class={`carousel-item carousel-item-trellis`} + class={`carousel-item flex flex-col w-full justify-start items-center`} > - <LayoutTrellisLine - basis={{ - label: { - value: `${$t(`common.location`)}`, - }, - }} - > - <InputSelect - bind:value={sel_location_gcs_id} + <LayoutTrellis> + <MapChooseLocation basis={{ - id_wrap: fmt_id(`location_gcs_id_wrap`), - id: fmt_id(`location_gcs_id`), - classes: `font-mono-display`, - sync: true, - loading: loading_location_gcs, - options: ls_models_location_gcs.length - ? [ - ...ls_models_location_gcs.map((i) => ({ - value: i.id, - label: `${i.label}`, - })), - { - value: `add-current`, - label: `${$t(`common.add_current_location`)}`, - }, - { - value: `add-map`, - label: `${$t(`common.add_map_location`)}`, - }, - ] - : [ - { - value: ``, - disabled: true, - selected: true, - label: `${$t(`common.no_locations_saved`)}`, - }, - { - value: `add-current`, - label: `${$t(`common.add_current_location`)}`, - }, - { - value: `add-map`, - label: `${$t(`common.add_map_location`)}`, - }, - ], - callback: async (val) => { - if (val === `add-current`) { - sel_location_gcs_id = ``; - await handle_add_current_location(); - } else if (val === `add-map`) { - sel_location_gcs_id = ``; - view = `map`; - } + classes_map: `map-trellis-1`, + loading: loading_map, + reset: async () => { + map_point_location_gcs_select = + map_point_location_gcs; }, }} + bind:map_point_center={map_point_location_gcs} + bind:map_point_select={map_point_location_gcs_select} + bind:map_point_select_geoc={map_point_location_gcs_select_geoc} /> - </LayoutTrellisLine> - </div> - <div - data-carousel-item={`form_1`} - class={`carousel-item carousel-item-trellis`} - > - <div class={`flex flex-col gap-8 justify-start items-center`}> - <div - class={`flex flex-col gap-2 justify-start items-center`} - > - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {`Trade Product`} - </p> - <div - class={`flex flex-row w-trellis_line justify-start items-start`} - > - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {JSON.stringify(review_trade_product, null, 4)} - </p> - </div> - </div> - <div - class={`flex flex-col gap-2 justify-start items-center`} - > - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {`Location`} - </p> - </div> - </div> + </LayoutTrellis> </div> </div> - <div - data-view={`map`} - class={`hidden flex flex-col h-full w-full justify-start items-start`} - > - <MapChooseLocation - basis={{ - classes_map: `map-trellis-1`, - loading: loading_map, - reset: async () => { - map_point_location_gcs_select = map_point_location_gcs; - }, - }} - bind:map_point_center={map_point_location_gcs} - bind:map_point_select={map_point_location_gcs_select} - bind:map_point_select_geoc={map_point_location_gcs_select_geoc} - /> - </div> - </LayoutTrellis> + </div> </LayoutView> <Nav basis={{ @@ -1335,12 +1322,12 @@ $carousel_index > 0 ? { callback: async () => { - handle_carousel_prev(); + await handle_back(); }, } : undefined, callback: async () => { - await trade_product_kv_init(fmt_id()); + await kv_init_trade_product_fields(fmt_id()); }, }, title: { @@ -1348,11 +1335,8 @@ value: `${$t(`icu.add_*`, { value: `${$t(`common.product`)}` })}`, }, callback: async () => { - if (view === `map`) { - view = `form_1`; - } else { - view = `map`; - } + if (view === `map`) await handle_view(`form_1`); + else await handle_view(`map`); }, }, option: { @@ -1361,10 +1345,11 @@ value: view === `map` ? `Use Location` - : carousel_conf.get($carousel_index)?.label_next || ``, + : carousel_param.get($carousel_index)?.label_next || ``, classes: `text-layer-1-glyph-hl`, glyph: - $carousel_index > 0 && $carousel_index < $carousel_index_max + $carousel_index >= 1 && + $carousel_index + 1 !== $carousel_index_max ? { key: `caret-right`, classes: `text-layer-1-glyph-hl`, @@ -1375,7 +1360,7 @@ if (view === `map`) await handle_add_map_location(); else if ($carousel_index === $carousel_index_max) await submit(); - else await handle_carousel_next(); + else await handle_continue(); }, }, }} diff --git a/src/routes/(app)/nostr/+page.svelte b/src/routes/(app)/nostr/+page.svelte @@ -1,97 +0,0 @@ -<script lang="ts"> - import { - LayoutTrellis, - LayoutView, - Nav, - route, - Trellis, - } from "@radroots/svelte-lib"; -</script> - -<LayoutView> - <LayoutTrellis> - <Trellis - basis={{ - args: { - layer: 1, - title: { - value: `Nostr`, - }, - list: [ - { - touch: { - label: { - left: [ - { - value: `View Your Keys`, - classes: `font-[300]`, - }, - ], - }, - callback: async () => { - await route(`/nostr/keys`); - }, - end: { - icon: { - key: `caret-right`, - }, - }, - }, - }, - { - touch: { - label: { - left: [ - { - value: `View Your Profile`, - }, - ], - }, - callback: async () => { - await route(`/nostr/profile`); - }, - end: { - icon: { - key: `caret-right`, - }, - }, - }, - }, - { - touch: { - label: { - left: [ - { - value: `View Your Notes`, - }, - ], - }, - callback: async () => { - await route(`/nostr/notes`); - }, - end: { - icon: { - key: `caret-right`, - }, - }, - }, - }, - ], - }, - }} - /> - </LayoutTrellis> -</LayoutView> -<Nav - basis={{ - prev: { - label: `Home`, - route: `/`, - }, - title: { - label: { - value: `Nostr`, - }, - }, - }} -/> diff --git a/src/routes/(app)/nostr/keys/+page.svelte b/src/routes/(app)/nostr/keys/+page.svelte @@ -1,286 +0,0 @@ -<script lang="ts"> - import { lc } from "$lib/client"; - import { _conf } from "$lib/conf"; - import type { NostrProfile } from "@radroots/models"; - import { - Glyph, - LayoutTrellis, - LayoutView, - Nav, - SelectElement, - TrellisTitle, - app_nostr_key, - app_notify, - nav_prev, - route, - t, - type ISelectOption, - } from "@radroots/svelte-lib"; - import { onMount } from "svelte"; - - 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 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 { - } - }); - - 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> - <div class={`flex flex-col w-full 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-4 pb-5 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, - }); - }, - 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 - basis={{ - prev: { - label: `Nostr`, - route: `/nostr`, - }, - title: { - label: { - value: `Keys`, - }, - }, - }} -/> diff --git a/src/routes/(app)/nostr/notes/+page.svelte b/src/routes/(app)/nostr/notes/+page.svelte @@ -1,169 +0,0 @@ -<script lang="ts"> - import { NDKEvent, NDKKind, type NDKFilter } from "@nostr-dev-kit/ndk"; - import type { - ExtendedBaseType, - NDKEventStore, - } from "@nostr-dev-kit/ndk-svelte"; - import { - app_nostr_key, - LayoutTrellis, - LayoutView, - locale, - Nav, - ndk, - route, - time_fmt_epoch_s, - Trellis, - type ITrellisKindTouch, - } from "@radroots/svelte-lib"; - import { onDestroy } from "svelte"; - - let events_store: NDKEventStore<ExtendedBaseType<NDKEvent>>; - - $: { - let authors = [$app_nostr_key]; - let ndk_filter: NDKFilter = { - kinds: [NDKKind.Text], - ...{ authors }, - }; - - fetch_events(ndk_filter).then(() => { - events_store?.startSubscription(); - }); - } - - const fetch_events = async (filter: NDKFilter): Promise<void> => { - try { - events_store = $ndk.storeSubscribe(filter, { - closeOnEose: true, - groupable: false, - autoStart: false, - }); - if (events_store) events_store.onEose(() => {}); - } catch (e) { - console.log(`(error) fetch_events `, e); - } - }; - - 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 route(`/nostr/notes/post`); - }, - }, - }); - - trellis_list.push({ - hide_active: true, - touch: { - label: { - left: [ - { - value: `Published At:`, - }, - ], - right: [ - { - value: time_fmt_epoch_s($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> - {#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 Your First Note`, - }, - ], - }, - end: { - icon: { - key: `caret-right`, - }, - }, - callback: async () => { - await route(`/nostr/notes/post`); - }, - }, - }, - ], - }, - }} - /> - {/if} - </LayoutTrellis> -</LayoutView> -<Nav - basis={{ - prev: { - label: `Nostr`, - route: `/nostr`, - }, - title: { - label: { - value: `Notes`, - }, - }, - option: $events_store.length - ? { - label: { - value: `Post`, - }, - callback: async () => { - 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,81 +0,0 @@ -<script lang="ts"> - import { lc } from "$lib/client"; - import ButtonSubmit from "$lib/components/button-submit.svelte"; - import { NDKKind } from "@nostr-dev-kit/ndk"; - import { - LayoutTrellis, - LayoutView, - Nav, - ndk, - ndk_user, - route, - t, - } from "@radroots/svelte-lib"; - import { ndk_event } from "@radroots/utils"; - - let loading = false; - let value_note_content = ``; - - const nostr_note_publish = async (): Promise<void> => { - try { - if (!value_note_content) { - await lc.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 route(`/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: { - value: `${$t(`icu.post_*`, { value: `Note` })}`, - }, - }, - }} -/> diff --git a/src/routes/(app)/nostr/profile/+page.svelte b/src/routes/(app)/nostr/profile/+page.svelte @@ -1,195 +0,0 @@ -<script lang="ts"> - import { lc } from "$lib/client"; - import { NDKEvent, NDKKind, type NDKFilter } from "@nostr-dev-kit/ndk"; - import type { - ExtendedBaseType, - NDKEventStore, - } from "@nostr-dev-kit/ndk-svelte"; - import { - app_nostr_key, - LayoutTrellis, - LayoutView, - Nav, - ndk, - ndk_user, - t, - Trellis, - } from "@radroots/svelte-lib"; - import { ndk_event } from "@radroots/utils"; - import { onDestroy } from "svelte"; - - let events_store: NDKEventStore<ExtendedBaseType<NDKEvent>>; - - $: { - let authors = [$app_nostr_key]; - let ndk_filter: NDKFilter = { - kinds: [NDKKind.Metadata], - ...{ authors }, - }; - - 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); - } - } - - onDestroy(() => { - events_store?.unsubscribe(); - }); - - const nostr_metadata_publish = async (): Promise<void> => { - try { - const kind0_name = await lc.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 lc.dialog.prompt({ - title: `Profile Name`, - message: `What is your profile name.`, - input_placeholder: `Enter profile name`, - }); - if (kind0_display_name === false) return; - - const kind0_about = await lc.dialog.prompt({ - title: `About`, - message: `What is your about me blurb.`, - input_placeholder: `Enter about me`, - }); - if (kind0_about === false) return; - - const kind0_website = await lc.dialog.prompt({ - title: `About`, - message: `What is your website.`, - input_placeholder: `Enter website`, - }); - 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; - - if (Object.keys(content).length === 0) { - await lc.dialog.alert( - `You must specify at least one profile field.`, - ); - return; - } - const ev = await ndk_event({ - $ndk, - $ndk_user, - basis: { - kind: NDKKind.Metadata, - content: JSON.stringify(content), - }, - }); - if (ev) { - await ev.publish(); - events_store?.unsubscribe(); - events_store?.startSubscription(); - } - } catch (e) { - console.log(`(error) nostr_metadata_pub `, e); - } - }; -</script> - -<LayoutView basis={{ fade: true }}> - <LayoutTrellis> - <Trellis - basis={{ - args: { - layer: 1, - title: { - value: `Your Profile`, - }, - list: $events_store.length - ? Object.entries( - 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(`_`, ` `)}` })}:`, - classes: `capitalize`, - }, - ], - right: [ - { - value: `${entry_val}`, - }, - ], - }, - callback: async () => {}, - }, - })) - : [ - { - touch: { - label: { - left: [ - { - value: `Add Profile`, - }, - ], - }, - end: { - icon: { - key: `caret-right`, - }, - }, - callback: async () => { - await nostr_metadata_publish(); - }, - }, - }, - ], - }, - }} - /> - </LayoutTrellis> -</LayoutView> -<Nav - basis={{ - prev: { - label: `Nostr`, - route: `/nostr`, - }, - title: { - label: { - value: `${$t(`common.profile`)}`, - }, - }, - option: $events_store.length - ? { - label: { - value: `Edit`, - }, - callback: async () => { - await nostr_metadata_publish(); - }, - } - : undefined, - }} -/> diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte @@ -1,8 +1,8 @@ <script lang="ts"> - import { lc } from "$lib/client"; - import { _conf } from "$lib/conf"; - import { restart } from "$lib/utils"; + import { dialog, geol, haptics, keystore } from "$lib/client"; + import { ks } from "$lib/conf"; import { + app_notify, app_thc, LayoutTrellis, LayoutView, @@ -35,7 +35,7 @@ ], }, callback: async () => { - await lc.haptics.impact(); + await haptics.impact(); app_thc.set(toggle_color_mode($app_thc)); }, }, @@ -68,11 +68,12 @@ }, }, callback: async () => { - const public_key = await lc.preferences.get( - _conf.kv.nostr_key_active, + const public_key = await keystore.get( + ks.nostr.nostr_key_active, ); - await lc.dialog.alert( - `Hi! This is your nostr public key ${public_key}`, + if (`err` in public_key) return; + await dialog.alert( + `Hi! This is your nostr public key ${public_key.result}`, ); }, }, @@ -93,15 +94,16 @@ }, }, callback: async () => { - const public_key = await lc.preferences.get( - _conf.kv.nostr_key_active, + const public_key = await keystore.get( + ks.nostr.nostr_key_active, ); - console.log(`public_key `, public_key); - const secret_key = await lc.keystore.get( - `nostr:key:${public_key}`, + if (`err` in public_key) return; + const secret_key = await keystore.get( + ks.nostr.nostr_key(public_key.result), ); - await lc.dialog.alert( - `Hi! This is your nostr secret key ${secret_key}`, + if (`err` in secret_key) return; + await dialog.alert( + `Hi! This is your nostr secret key ${secret_key.result}`, ); }, }, @@ -134,27 +136,30 @@ }, }, callback: async () => { - const confirm = await lc.dialog.confirm( + const confirm = await dialog.confirm( `Hi! This will delete your saved keys.`, ); if (confirm) { - const nostr_public_key = - await lc.preferences.get( - _conf.kv.nostr_key_active, - ); - if (nostr_public_key) { - await lc.keystore.remove( - `nostr:key:${nostr_public_key}`, - ); - await lc.preferences.remove( - _conf.kv.nostr_key_active, - ); - await restart(true); - } else { - await lc.dialog.alert( - `There is no public key preference saved.`, + const ks_nostr_pk = await keystore.get( + ks.nostr.nostr_key_active, + ); + if (`err` in ks_nostr_pk) { + await dialog.alert( + `There was an error.`, ); + return; } + await keystore.remove( + ks.nostr.nostr_key( + ks_nostr_pk.result, + ), + ); + await keystore.remove( + ks.nostr.nostr_key_active, + ); + app_notify.set( + `Your device has been reset.`, + ); } }, }, @@ -182,8 +187,8 @@ ], }, callback: async () => { - const pos = await lc.geo.current(); - await lc.dialog.alert(JSON.stringify(pos)); + const pos = await geol.current(); + await dialog.alert(JSON.stringify(pos)); }, }, }, @@ -209,8 +214,8 @@ ], }, callback: async () => { - const url = `https://radroots.org`; - await lc.browser.open(url); + //const url = `https://radroots.org`; + //await browser.open(url); }, }, }, @@ -224,12 +229,12 @@ ], }, callback: async () => { - await lc.share.open({ - title: `Radroots Home Page`, - text: `Find farmers around the world.`, - url: `https://radroots.org`, - dialog_title: `This is the dialog title`, - }); + //await share.open({ + // title: `Radroots Home Page`, + // text: `Find farmers around the world.`, + // url: `https://radroots.org`, + // dialog_title: `This is the dialog title`, + //}); }, }, }, @@ -243,12 +248,12 @@ ], }, callback: async () => { - const public_key = await lc.preferences.get( - _conf.kv.nostr_key_active, - ); - const npub = lc.nostr.lib.npub(public_key); - const url = `https://primal.net/p/${npub}`; - await lc.browser.open(url); + //const public_key = await keystore.get( + // ks.nostr.nostr_key_active, + //); + //const npub = nostr.lib.npub(public_key); + //const url = `https://primal.net/p/${npub}`; + //await browser.open(url); }, }, }, @@ -274,8 +279,8 @@ ], }, callback: async () => { - const data = await lc.device.info(); - await lc.dialog.alert(JSON.stringify(data)); + //const data = await device.info(); + //await dialog.alert(JSON.stringify(data)); }, }, }, @@ -289,8 +294,8 @@ ], }, callback: async () => { - const data = await lc.device.battery(); - await lc.dialog.alert(JSON.stringify(data)); + //const data = await device.battery(); + //await dialog.alert(JSON.stringify(data)); }, }, }, @@ -322,7 +327,7 @@ }, }, callback: async () => { - await lc.haptics.impact("less"); + await haptics.impact(`light`); }, }, }, @@ -342,7 +347,7 @@ }, }, callback: async () => { - await lc.haptics.impact("more"); + await haptics.impact(`heavy`); }, }, }, @@ -362,7 +367,7 @@ }, }, callback: async () => { - await lc.haptics.vibrate(500); + await haptics.vibrate(500); }, }, }, diff --git a/src/routes/(app)/test/+page.svelte b/src/routes/(app)/test/+page.svelte @@ -1,67 +1,9 @@ <script lang="ts"> - import { - LayoutView, - Nav, - carousel_index, - carousel_index_max, - carousel_next, - carousel_prev, - } from "@radroots/svelte-lib"; - import { onMount } from "svelte"; - - onMount(async () => { - try { - carousel_index.set(0); - carousel_index_max.set(1); - } catch (e) { - } finally { - } - }); + import { LayoutView } from "@radroots/svelte-lib"; </script> <LayoutView> - <div - data-carousel-container={`start`} - class={`carousel-container flex flex-grow h-full w-full`} - > - <div - data-carousel-item={`start`} - class={`carousel-item flex flex-col w-full`} - > - <button - class={`flex flex-row justify-center items-center`} - on:click={async () => { - await carousel_next(`start`); - }} - > - <p class={`font-sans font-[400] text-layer-0-glyph`}>one</p> - </button> - </div> - <div - data-carousel-item={`start`} - class={`carousel-item flex flex-col w-full`} - > - <button - class={`flex flex-row justify-center items-center`} - on:click={async () => { - await carousel_prev(`start`); - }} - > - <p class={`font-sans font-[400] text-layer-0-glyph`}>two</p> - </button> - </div> + <div class={`flex flex-col p-20 justify-start items-center`}> + <p class={`font-sans font-[400] text-layer-0-glyph`}>test</p> </div> </LayoutView> -<Nav - basis={{ - prev: { - label: `Home`, - route: `/`, - }, - title: { - label: { - value: `Test`, - }, - }, - }} -/> diff --git a/src/routes/(conf)/+layout.svelte b/src/routes/(conf)/+layout.svelte @@ -1,7 +0,0 @@ -<script lang="ts"> - import { LayoutWindow } from "@radroots/svelte-lib"; -</script> - -<LayoutWindow> - <slot /> -</LayoutWindow> diff --git a/src/routes/(conf)/conf/error/+page.svelte b/src/routes/(conf)/conf/error/+page.svelte @@ -0,0 +1,22 @@ +<script lang="ts"> + import { restart } from "$lib/utils/client"; + import { LayoutView } from "@radroots/svelte-lib"; +</script> + +<LayoutView> + <div class={`flex flex-col gap-2 justify-start items-center`}> + <p class={`font-sans font-[400] text-layer-0-glyph`}> + The device is improperly configured. + </p> + <button + class={`flex flex-row justify-center items-center`} + on:click={async () => { + await restart(true); + }} + > + <p class={`font-sans font-[400] text-layer-0-glyph-hl`}> + Click to restart + </p> + </button> + </div> +</LayoutView> diff --git a/src/routes/(conf)/conf/init/+layout.ts b/src/routes/(conf)/conf/init/+layout.ts @@ -1,33 +1,27 @@ -import { lc } from '$lib/client'; -import { _conf } from '$lib/conf'; -import { default_locale, load_translations, locales, route, translations_loading } from '@radroots/svelte-lib'; +import { keystore } from '$lib/client'; +import { ks } from '$lib/conf'; +import { app_nostr_key, route } from '@radroots/svelte-lib'; import type { LayoutLoad, LayoutLoadEvent } from './$types'; -export const load: LayoutLoad = async ({ url }: LayoutLoadEvent) => { +export const load: LayoutLoad = async (_: LayoutLoadEvent) => { try { - console.log(`layout (conf) `, url.pathname); - - const { language: nav_locale } = navigator; - let locale = default_locale.toString(); - if (locales.get().some(i => i === nav_locale.toLowerCase())) locale = navigator.language; - else if (locales.get().some(i => i === nav_locale.slice(0, 2).toLowerCase())) locale = nav_locale.slice(0, 2); - await load_translations(locale.toLowerCase(), url.pathname); - await translations_loading.toPromise(); - 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}`, + const nostr_publickey = await keystore.get( + ks.nostr.nostr_key_active, + ); + if (`result` in nostr_publickey) { + const nostr_secretkey = await keystore.get( + ks.nostr.nostr_key(nostr_publickey.result), ); - if (active_nostr_key) { + if (`result` in nostr_secretkey) { + app_nostr_key.set(nostr_publickey.result); await route(`/`); - return + return; } } - } catch (e) { } finally { - await lc.window.splash_hide(); + } catch (e) { + console.log(`(load) (conf) init`, e) + } finally { + //await win.splash_hide(); return {}; }; }; diff --git a/src/routes/(conf)/conf/init/+page.svelte b/src/routes/(conf)/conf/init/+page.svelte @@ -3,183 +3,292 @@ PUBLIC_NOSTR_RELAY_DEFAULTS, PUBLIC_RADROOTS_URL, } from "$env/static/public"; - import { lc } from "$lib/client"; - import { _conf } from "$lib/conf"; - import { restart } from "$lib/utils"; - import { keystore_reset } from "$lib/utils/keystore"; + import { db, dialog, http, keystore, nostr } from "$lib/client"; + import ButtonAppearingPair from "$lib/components/button_appearing_pair.svelte"; + import { cfg, ks } from "$lib/conf"; + import { restart } from "$lib/utils/client"; import { app_layout, carousel_index, carousel_index_max, carousel_next, carousel_prev, - Fill, - fmt_capitalize, fmt_id, Glyph, InputElement, kv, LayoutView, + Loading, sleep, t, view_effect, - type GlyphKey, - type GlyphWeight, } from "@radroots/svelte-lib"; import { regex } from "@radroots/utils"; - import { onMount } from "svelte"; + import { onDestroy, onMount } from "svelte"; - type KeypairNewButtonKey = - | `keypair-profile-personal` - | `keypair-profile-wallet` - | `keypair-profile-links`; - type KeypairNewButton = { - key: KeypairNewButtonKey; - icon: GlyphKey; - weight?: GlyphWeight; - heading: string; - subtitle: string; - }; - const keypair_new_buttons: KeypairNewButton[] = [ - { - key: `keypair-profile-personal`, - icon: `user`, - heading: `${$t(`common.personal`)}`, - subtitle: [ - `${$t(`common.your_name`)}`, - `${$t(`common.business_name`)}`, - ].join(`, `), - }, - { - key: `keypair-profile-wallet`, - icon: `cardholder`, - heading: `${$t(`common.wallet`)}`, - subtitle: [ - `${$t(`common.bank_account`)}`, - fmt_capitalize(`lud06`), - fmt_capitalize(`lud16`), - ].join(`, `), - }, - { - key: `keypair-profile-links`, - icon: `globe-simple`, - weight: `bold`, - heading: `Links`, - subtitle: [ - `${$t(`common.website`)}`, - `${$t(`common.socials`)}`, - `${$t(`common.photos`)}`, - ].join(`, `), - }, - ]; - - let keypair_new_buttons_selected: KeypairNewButtonKey[] = []; - - const carousel_param: Record<View, { max: number }> = { - start: { - max: 1, - }, + const carousel_param: Record<View, { max_index: number }> = { setup: { - max: 1, - }, - keypair_new: { - max: 1, + max_index: 2, }, - keypair_own: { - max: 1, + profile_name: { + max_index: 2, }, eula: { - max: 1, + max_index: 1, }, }; - onMount(async () => { - try { - carousel_index.set(0); - carousel_index_max.set(carousel_param[view].max); - await keystore_reset(); - } catch (e) { - } finally { - } - }); + let el_eula: HTMLDivElement; + let el_eula_scrolled = false; - type View = `start` | `setup` | `keypair_new` | `keypair_own` | `eula`; + type KeypairOption = `nostr_key_gen` | `nostr_key_existing`; + let setup_keypair_option: KeypairOption | undefined = undefined; + + let profile_name_is_valid = false; + let profile_name_loading = false; + + type View = `setup` | `profile_name` | `eula`; let view: View = `setup`; $: { view_effect<View>(view); } - const handle_carousel_prev = async (): Promise<void> => { + onMount(async () => { + try { + handle_view(`setup`); + + await keystore.remove(ks.nostr.conf_init_key); + await keystore.remove(ks.nostr.conf_init_profile); + + el_eula.addEventListener("scroll", () => { + const client_h = el_eula.clientHeight; + const scroll_h = el_eula.scrollHeight; + const scroll_top = el_eula.scrollTop; + if (scroll_top + client_h >= scroll_h) el_eula_scrolled = true; + }); + } catch (e) { + } finally { + } + }); + + onDestroy(async () => { try { - await carousel_prev(view); + el_eula.removeEventListener("scroll", () => null); } catch (e) { - console.log(`(error) handle_carousel_prev `, e); + } finally { + } + }); + + const handle_view = (new_view: View): void => { + if (new_view === `setup` && view === `profile_name`) { + const offset = setup_keypair_option === `nostr_key_gen` ? 1 : 0; + carousel_index.set(carousel_param[new_view].max_index - offset); + } else { + carousel_index.set(0); } + carousel_index_max.set(carousel_param[new_view].max_index); + view = new_view; }; - const handle_carousel_next = async (): Promise<void> => { + const handle_back = async (): Promise<void> => { try { switch (view) { - case `start`: + case `setup`: { - await carousel_next(view); + switch ($carousel_index) { + case 1: + { + setup_keypair_option = undefined; + await carousel_prev(view); + } + break; + case 2: + { + await carousel_prev(view); + } + break; + } } break; - case `setup`: { + case `profile_name`: { switch ($carousel_index) { case 0: { - await carousel_next(view); + handle_view(`setup`); } break; - case 1: - { - const profile_name = await kv.get( - fmt_id(`profile_name`), - ); - if (!profile_name) { - await lc.dialog.alert( - `${$t(`icu.enter_a_*`, { value: `${$t(`common.profile_name`)}`.toLowerCase() })}`, - ); - return; - } + } + } + } + } catch (e) { + console.log(`(error) handle_back `, e); + } + }; - const valid_profile_name = - await validate_profile_name(profile_name); - if (typeof valid_profile_name === `string`) { - await lc.dialog.alert(valid_profile_name); - return; - } else if (!valid_profile_name) { - await lc.dialog.alert( - `${`${$t(`icu.the_*_is_registered`, { value: `${$t(`common.profile_name`)}` })}`}`, + const handle_continue = async (): Promise<void> => { + try { + switch (view) { + case `setup`: + { + switch ($carousel_index) { + case 0: + { + await carousel_next(view); + } + break; + case 1: + { + if ( + setup_keypair_option === `nostr_key_gen` + ) { + const nostr_sk_previous = + await keystore.get( + ks.nostr.conf_init_key, + ); + if (`result` in nostr_sk_previous) { + handle_view(`profile_name`); + return; + } + const nostr_sk = + nostr.lib.generate_key(); + const ks_set = await keystore.set( + ks.nostr.conf_init_key, + nostr_sk, + ); + if (`err` in ks_set) { + await dialog.alert( + `${$t(`error.client.unhandled`)}`, + ); + return; //@todo + } + handle_view(`profile_name`); + } else if ( + setup_keypair_option === + `nostr_key_existing` + ) + await carousel_next(view); + } + break; + case 2: + { + const nostr_key_existing = await kv.get( + fmt_id(`setup_nostr_key_existing`), + ); + if (!nostr_key_existing) { + await dialog.alert( + `${$t(`icu.enter_a_*`, { value: `${$t(`icu.valid_*`, { value: `${$t(`common.key`)}` })}`.toLowerCase() })}`, + ); + return; + } + const valid_nostr_key_nsec = + nostr.lib.nsec_decode( + nostr_key_existing, + ); + if (valid_nostr_key_nsec) { + const ks_set = await keystore.set( + ks.nostr.conf_init_key, + valid_nostr_key_nsec, + ); + if (`err` in ks_set) { + await dialog.alert( + `${$t(`error.client.unhandled`)}`, + ); + return; //@todo + } + handle_view(`eula`); + } + const valid_nostr_key_hex = + nostr.lib.public_key( + nostr_key_existing, + ); + if (valid_nostr_key_hex) { + const ks_set = await keystore.set( + ks.nostr.conf_init_key, + nostr_key_existing, + ); + if (`err` in ks_set) { + await dialog.alert( + `${$t(`error.client.unhandled`)}`, + ); + return; //@todo + } + handle_view(`eula`); + } + await dialog.alert( + `${$t(`icu.invalid_*`, { value: `${$t(`common.key`)}`.toLowerCase() })}`, ); - return; } + break; + } + } + break; + case `profile_name`: + { + switch ($carousel_index) { + case 0: + { + if (profile_name_loading) return; + const profile_name = await kv.get( + fmt_id(`profile_name`), + ); + if (!profile_name) { + await dialog.alert( + `${$t(`icu.enter_a_*`, { value: `${$t(`common.profile_name`)}`.toLowerCase() })}`, + ); + return; + } + const valid_profile_name = + await fetch_validate_profile_name( + profile_name, + ); + if ( + typeof valid_profile_name === `string` + ) { + await dialog.alert(valid_profile_name); + return; + } else if (!valid_profile_name) { + await dialog.alert( + `${`${$t(`icu.the_*_is_registered`, { value: `${$t(`common.profile_name`)}` })}`}`, + ); + return; + } - const confirm = await lc.dialog.confirm({ - message: `${`${$t(`icu.the_*_is_available`, { value: `${$t(`common.profile_name`).toLowerCase()} ${profile_name}` })}`}`, - cancel_label: `Back`, - ok_label: `Continue`, - }); - if (confirm === true) { - await carousel_next(view); + const confirm = await dialog.confirm({ + message: `${`${$t(`icu.the_*_is_available`, { value: `${$t(`common.profile_name`).toLowerCase()} "${profile_name}"` })}`}. Would you like to use it?`, + cancel_label: `${$t(`common.no`)}`, + ok_label: `${$t(`common.yes`)}`, + }); + if (confirm === true) { + const ks_set = await keystore.set( + ks.nostr.conf_init_profile, + profile_name, + ); + if (`err` in ks_set) { + await dialog.alert( + `${$t(`error.client.unhandled`)}`, + ); + return; //@todo + } + handle_view(`eula`); + } } - } - break; + break; + } } - } + break; } } catch (e) { - console.log(`(error) handle_carousel_next `, e); + console.log(`(error) handle_continue `, e); } }; - const validate_profile_name = async ( + const fetch_validate_profile_name = async ( profile_name: string, ): Promise<boolean | string> => { try { - const res = await lc.http.fetch({ + profile_name_loading = true; + const res = await http.fetch({ url: `${PUBLIC_RADROOTS_URL}/.well-known/nostr.json`, }); if (`err` in res) { @@ -195,62 +304,73 @@ return `error`; } catch (e) { - console.log(`(error) validate_profile_name `, e); + console.log(`(error) fetch_validate_profile_name `, e); return `catch`; + } finally { + profile_name_loading = false; } }; const configure_device = async (): Promise<void> => { try { - const secret_key = lc.nostr.lib.generate_key(); - const public_key = lc.nostr.lib.public_key(secret_key); + const conf_init_secret_key = await keystore.get( + ks.nostr.conf_init_key, + ); + if (`err` in conf_init_secret_key) { + alert(`!conf_init_secret_key`); + return; //@todo + } - const ks_key_add = await lc.keystore.set( - _conf.kv.nostr_key(public_key), + const secret_key = conf_init_secret_key.result; + const public_key = nostr.lib.public_key(secret_key); + const ks_key_add = await keystore.set( + ks.nostr.nostr_key(public_key), secret_key, ); if (!ks_key_add) { alert(`!ks_key_add`); - return; - //@todo reset + return; //@todo } - const pref_key_add = await lc.preferences.set( - _conf.kv.nostr_key_active, + const pref_key_add = await keystore.set( + ks.nostr.nostr_key_active, public_key, ); if (!pref_key_add) { alert(`!pref_key_add`); - return; - //@todo reset + return; //@todo + } + + let profile_name = ``; + const conf_init_profile = await keystore.get( + ks.nostr.conf_init_profile, + ); + if (`result` in conf_init_profile) { + profile_name = conf_init_profile.result; } - const nostr_profile_add = await lc.db.nostr_profile_add({ + const nostr_profile_add = await db.nostr_profile_add({ public_key, + name: profile_name ? profile_name : undefined, }); if (`err` in nostr_profile_add) { - await lc.dialog.alert(nostr_profile_add.err); - return; - //@todo + await dialog.alert(nostr_profile_add.err); + return; //@todo } else if (`err_s` in nostr_profile_add) { - await lc.dialog.alert(nostr_profile_add.err_s.join(` `)); - return; - //@todo + await dialog.alert(nostr_profile_add.err_s.join(` `)); + return; //@todo } for (const url of PUBLIC_NOSTR_RELAY_DEFAULTS.split(",") || []) { - const nostr_relay_add = await lc.db.nostr_relay_add({ url }); + const nostr_relay_add = await db.nostr_relay_add({ url }); if (`err` in nostr_relay_add) { - await lc.dialog.alert(nostr_relay_add.err); - return; - // @todo + await dialog.alert(nostr_relay_add.err); + return; //@todo } else if (`err_s` in nostr_relay_add) { - await lc.dialog.alert(nostr_relay_add.err_s.join(` `)); - return; - //@todo + return; //@todo } - await lc.db.set_nostr_profile_relay({ + await db.set_nostr_profile_relay({ nostr_profile: { id: nostr_profile_add.id, }, @@ -260,435 +380,535 @@ }); } - await sleep(_conf.delay.load); + await keystore.remove(ks.nostr.conf_init_key); + await keystore.remove(ks.nostr.conf_init_profile); + + await sleep(cfg.delay.load); await restart( true, - `Welcome! Your device was configured. To view or change your configuration go to Settings > Configuration.`, + `${$t(`app.page.conf.init.notification.welcome`)}`, ); } catch (e) { console.log(`(error) configure_device `, e); } }; - - const handle_keypair_buttons_select = (key: KeypairNewButtonKey): void => { - if (keypair_new_buttons_selected.includes(key)) { - keypair_new_buttons_selected = keypair_new_buttons_selected.filter( - (i) => i !== key, - ); - } else { - keypair_new_buttons_selected = [ - ...keypair_new_buttons_selected, - key, - ]; - } - }; </script> <LayoutView> <div - data-view={`start`} - class={`hidden flex flex-col h-full w-full py-12 justify-start items-center`} + data-view={`setup`} + class={`flex flex-col h-full w-full max-mobile_base:pt-12 pt-16 justify-start items-center`} > <div - class={`relative flex flex-col h-full w-full justify-start items-center`} + data-carousel-container={`setup`} + class={`carousel-container flex h-full w-full`} > <div - data-carousel-container={`start`} - class={`carousel-container flex h-full w-full rounded-2xl scrollbar-hide`} + data-carousel-item={`setup`} + class={`carousel-item flex flex-col w-full max-mobile_y:pt-28 pt-32 pb-4 justify-start items-center`} + > + <div class={`flex flex-col gap-8 justify-start items-center`}> + <div + class={`flex flex-col gap-1 justify-start items-center`} + > + <p + class={`font-mono font-[700] text-layer-0-glyph text-4xl`} + > + {`${`${$t(`app.name`)}`}`} + </p> + <p + class={`font-mono font-[700] text-layer-0-glyph text-4xl`} + > + {`${`${$t(`common.setup`)}`}`} + </p> + </div> + <div + class={`grid grid-cols-12 flex flex-col gap-4 w-full justify-start items-center`} + > + {#each [`Configure your device`, `Choose a profile name`, `Terms of Use agreement`] as li, li_i} + <div + class={`col-span-12 flex flex-row justify-start items-center`} + > + <p + class={`font-mono font-[400] text-layer-0-glyph text-xl`} + > + {`${li_i + 1}. ${li}`} + </p> + </div> + {/each} + </div> + </div> + </div> + <button + data-carousel-item={`setup`} + class={`carousel-item flex flex-col w-full max-mobile_y:pt-32 pt-36 pb-4 justify-start items-center`} + on:click={async () => { + setup_keypair_option = undefined; + }} > <div - data-carousel-item={`start`} - class={`carousel-item flex flex-col w-full py-32 justify-between items-center`} + class={`flex flex-col w-full gap-10 justify-start items-center`} > <div - class={`flex flex-col gap-2 justify-center items-center`} + class={`flex flex-row w-full justify-center items-center`} > <p - class={`font-mono font-[600] text-layer-0-glyph text-6xl`} + class={`font-mono font-[600] text-layer-0-glyph text-3xl`} > - {`rad`} + {`${$t(`icu.configure_*`, { value: `${$t(`common.device`)}` })}`} </p> + </div> + <div + class={`flex flex-col w-full gap-5 justify-center items-center`} + > <button - class={`flex flex-row justify-center items-center`} - on:click={async () => { - //@todo remove - await configure_device(); + class={`flex flex-col h-touch_bold w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-3xl touch-layer-1 touch-layer-1-raise-less ${setup_keypair_option === `nostr_key_gen` ? `layer-1-ring` : ``}`} + on:click|stopPropagation={async () => { + setup_keypair_option = `nostr_key_gen`; }} > <p - class={`font-mono font-[600] text-layer-0-glyph text-6xl`} + class={`font-sans font-[600] text-layer-0-glyph text-xl`} > - {`roots`} + {`${$t(`icu.create_new_*`, { value: `${$t(`common.keypair`)}`.toLowerCase() })}`} </p> </button> - </div> - <div class={`flex flex-col justify-start items-center`}> - <p - class={`font-mono font-[400] text-layer-0-glyph text-3xl`} - > - {`direct trade`} - </p> - <p - class={`font-mono font-[400] text-layer-0-glyph text-3xl`} + <button + class={`flex flex-col h-touch_bold w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-3xl touch-layer-1 touch-layer-1-raise-less ${setup_keypair_option === `nostr_key_existing` ? `layer-1-ring` : ``}`} + on:click|stopPropagation={async () => { + setup_keypair_option = `nostr_key_existing`; + }} > - {`network`} - </p> + <p + class={`font-sans font-[600] text-layer-0-glyph text-xl`} + > + {`${$t(`icu.use_existing_*`, { + value: `${$t(`common.keypair`)}`.toLowerCase(), + })}`} + </p> + </button> </div> </div> - </div> + </button> <div - class={`absolute bottom-0 left-0 flex flex-row h-12 w-full justify-center items-center`} + data-carousel-item={`setup`} + class={`carousel-item flex flex-col w-full max-mobile_y:pt-32 pt-36 pb-4 justify-start items-center`} > - <div class={`flex flex-row gap-8 justify-start items-center`}> - <Glyph - basis={{ - key: `caret-left`, - dim: `sm-`, - weight: `bold`, - classes: - $carousel_index > 0 - ? `h-glyph_btn_sm w-glyph_btn_sm text-layer-2-glyph bg-layer-2-surface rounded-full` - : `h-glyph_btn_sm w-glyph_btn_sm text-layer-2-glyph bg-layer-2-surface rounded-full opacity-60`, - callback: async () => { - if ($carousel_index > 0) - await handle_carousel_prev(); - }, - }} - /> - <Glyph - basis={{ - key: `caret-right`, - dim: `sm-`, - weight: `bold`, - classes: `h-glyph_btn_sm w-glyph_btn_sm text-layer-2-glyph bg-layer-2-surface rounded-full`, - callback: async () => { - if ( - $carousel_index !== carousel_param[view].max - ) - await handle_carousel_next(); - else view = `setup`; - }, - }} - /> + <div + class={`flex flex-col w-full gap-8 justify-start items-center ${view === `profile_name` ? `fade-in-long` : ``}`} + > + <div + class={`flex flex-col w-full gap-6 justify-center items-center`} + > + <p + class={`font-mono font-[600] text-layer-0-glyph text-3xl`} + > + {`${$t(`icu.add_existing_*`, { value: `${$t(`common.key`)}`.toLowerCase() })}`} + </p> + <InputElement + basis={{ + classes: `h-entry_guide w-${$app_layout} bg-layer-1-surface rounded-touch font-mono text-lg placeholder:opacity-60 items-end text-center`, + id: fmt_id(`setup_nostr_key_existing`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.enter_*`, { value: `nostr nsec/hex` })}`, + field: { + charset: regex.profile_name_ch, + validate: regex.profile_name, + validate_keypress: true, + }, + callback_keydown: async ({ key, el }) => { + if (key === `Enter`) { + el.blur(); + await handle_continue(); + } + }, + }} + /> + </div> </div> </div> </div> + <div + class={`absolute max-mobile_base:bottom-0 bottom-8 left-0 flex flex-col w-full justify-center items-center ${view === `profile_name` ? `fade-in-long` : ``}`} + > + <ButtonAppearingPair + basis={{ + continue: { + disabled: + $carousel_index === 1 && !setup_keypair_option, + callback: async () => await handle_continue(), + }, + back: { + visible: $carousel_index > 0, + callback: async () => await handle_back(), + }, + }} + /> + </div> </div> <div - data-view={`setup`} - class={`flex flex-col h-full w-full max-mobile_base:pt-12 pt-16 justify-start items-center`} + data-view={`profile_name`} + class={`hidden flex flex-col h-full w-full max-mobile_base:pt-12 pt-16 justify-start items-center`} > <div - class={`relative flex flex-col h-full w-full justify-start items-center`} + data-carousel-container={`profile_name`} + class={`carousel-container flex h-full w-full`} > <div - data-carousel-container={`setup`} - class={`carousel-container flex h-full w-full rounded-2xl scrollbar-hide`} + data-carousel-item={`profile_name`} + class={`carousel-item flex flex-col w-full max-mobile_y:pt-32 pt-36 pb-4 justify-start items-center`} > <div - data-carousel-item={`setup`} - class={`carousel-item flex flex-col w-full max-mobile_y:pt-28 pt-32 pb-4 justify-start items-center`} + class={`flex flex-col w-full gap-4 justify-start items-center ${view === `profile_name` ? `fade-in-long` : ``}`} > <div - class={`flex flex-col gap-8 justify-start items-center`} + class={`flex flex-col w-full gap-2 justify-center items-center`} > - <div - class={`flex flex-col gap-1 justify-start items-center`} + <p + class={`font-mono font-[600] text-layer-0-glyph text-3xl capitalize`} > - <p - class={`font-mono font-[700] text-layer-0-glyph text-4xl`} - > - {`${`${$t(`app.name`)}`}`} - </p> - <p - class={`font-mono font-[700] text-layer-0-glyph text-4xl`} - > - {`${`${$t(`common.setup`)}`}`} - </p> - </div> + {`${$t(`icu.add_*`, { value: `${$t(`common.profile`)}` })}`} + </p> + </div> + <div + class={`flex flex-col h-[6.7rem] w-${$app_layout} pt-6 pb-6 px-8 justify-start items-center bg-layer-1-surface rounded-3xl`} + > <div - class={`grid grid-cols-12 flex flex-col gap-4 w-full justify-start items-center`} + class={`relative flex flex-row w-full justify-center items-center border-b-[2px] border-b-layer-1-surface-edge`} > - {#each [`Choose a profile name`, `Configure your device`, `Terms of Use agreement`] as li, li_i} + <InputElement + basis={{ + classes: `font-mono text-[1.05rem] placeholder:text-layer-1-glyph/40 tracking-wider items-end text-center`, + id: fmt_id(`profile_name`), + sync: true, + sync_init: true, + placeholder: `${$t(`icu.name_your_*`, { value: `${$t(`common.profile`)}` })}`, + field: { + charset: regex.profile_name_ch, + validate: regex.profile_name, + validate_keypress: true, + }, + callback: async ({ pass }) => { + profile_name_is_valid = pass; + }, + callback_keydown: async ({ key, el }) => { + if (key === `Enter`) { + el.blur(); + await handle_continue(); + } + }, + }} + /> + {#if profile_name_loading} <div - class={`col-span-12 flex flex-row justify-start items-center`} + class={`absolute top-0 right-0 flex flex-row h-full pr-2 justify-center items-center`} > - <p - class={`font-mono font-[400] text-layer-0-glyph text-xl`} - > - {`${li_i + 1}. ${li}`} - </p> + <Loading /> </div> - {/each} + {/if} </div> </div> </div> + </div> + </div> + <div + class={`absolute top-16 left-4 flex flex-row gap-2 justify-start items-center ${view === `profile_name` ? `fade-in-long` : ``}`} + > + <button + class={`group flex flex-row justify-center items-center`} + on:click={async () => { + await handle_back(); + }} + > + <Glyph + basis={{ + classes: `text-layer-1-glyph-shade group-active:opacity-60 transition-all`, + key: `caret-left`, + dim: `lg`, + weight: `bold`, + }} + /> + <p + class={`font-sans font-[400] text-layer-0-glyph text-lg capitalize group-active:opacity-60 transition-all`} + > + {`${$t(`icu.go_*`, { value: `${$t(`common.back`)}` })}`} + </p> + </button> + </div> + <div + class={`absolute max-mobile_base:bottom-0 bottom-8 left-0 flex flex-col w-full justify-center items-center ${view === `profile_name` ? `fade-in-long` : ``}`} + > + <ButtonAppearingPair + basis={{ + continue: { + disabled: !profile_name_is_valid, + callback: async () => await handle_continue(), + }, + back: { + visible: true, + label: `${$t(`common.skip`)}`, + callback: async () => { + //@todo + await dialog.alert( + `${$t(`app.page.conf.init.notification.no_profile_name`)}`, + ); + handle_view(`eula`); + }, + }, + }} + /> + </div> + </div> + <div + data-view={`eula`} + class={`hidden flex flex-col h-full w-full max-mobile_base:pt-12 pt-12 justify-start items-center`} + > + <div + data-carousel-container={`eula`} + class={`carousel-container flex h-full w-full rounded-2xl scroll-hide`} + > + <div + data-carousel-item={`eula`} + class={`carousel-item flex flex-col w-full max-mobile_base:pt-16 justify-start items-center`} + > <div - data-carousel-item={`setup`} - class={`carousel-item flex flex-col w-full max-mobile_y:pt-32 pt-36 pb-4 justify-start items-center`} + class={`flex flex-col w-full px-4 pb-8 justify-start items-center ${view === `eula` ? `fade-in-long` : ``}`} > <div - class={`flex flex-col w-full gap-8 justify-start items-center`} + class={`flex flex-col w-full px-4 gap-4 justify-start items-center`} > <div class={`flex flex-row w-full justify-center items-center`} > <p - class={`font-mono font-[600] text-layer-0-glyph text-3xl`} + class={`font-mono font-[600] text-layer-0-glyph text-2xl`} > - {`2. ${`${$t(`common.device`)}`}`} + {`${$t(`eula.title`)}`} </p> </div> <div - class={`flex flex-col w-full gap-4 justify-center items-center`} + bind:this={el_eula} + class={`flex flex-col h-[34rem] w-full gap-6 justify-start items-center overflow-y-scroll scroll-hide`} > - <button - class={`flex flex-col h-[4.25rem] w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-3xl touch-layer-1 touch-layer-1-raise-less`} - on:click={async () => { - view = `keypair_new`; - }} + <div + class={`flex flex-col w-full gap-2 justify-start items-start`} > <p - class={`font-sans font-[600] text-layer-0-glyph text-xl`} + class={`font-mono font-[600] text-layer-0-glyph`} > - {`Create secure keypair`} + {`**${$t(`eula.introduction.title`)}**`} </p> - </button> - <button - class={`flex flex-col h-[4.25rem] w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-3xl touch-layer-1 touch-layer-1-raise-less`} - on:click={async () => { - view = `keypair_own`; - }} + <p + class={`font-mono font-[500] text-layer-0-glyph text-sm text-justify break-word`} + > + {`${$t(`eula.introduction.body`)}`} + </p> + </div> + <div + class={`flex flex-col w-full gap-2 justify-start items-start`} > <p - class={`font-sans font-[600] text-layer-0-glyph text-xl`} + class={`font-mono font-[600] text-layer-0-glyph`} > - {`Use existing keypair`} + {`**${$t(`eula.prohibited_content.title`)}**`} </p> - </button> - </div> - </div> - <div - class={`absolute bottom-0 left-0 flex flex-col w-full justify-center items-center ${$carousel_index > 0 ? `pb-2` : `pb-4`}`} - > - <button - class={`group flex flex-row h-[3.25rem] w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-touch touch-layer-1`} - on:click={async () => { - await handle_carousel_next(); - }} - > - <p - class={`font-sans font-[600] tracking-wide text-layer-1-glyph/80 group-active:text-layer-1-glyph/40 transition-all`} + <p + class={`font-mono font-[500] text-sm text-layer-0-glyph text-justify break-word`} + > + {`${$t(`eula.prohibited_content.body_0_title`)}`} + </p> + <div + class={`flex flex-col w-full justify-start items-start`} + > + {#each [0, 1, 2, 3, 4, 5] as li} + <div + class={`flex flex-row w-full justify-start items-center`} + > + <div + class={`flex flex-row h-full w-8 justify-start items-start`} + > + <p + class={` font-mono font-[500] text-sm text-layer-0-glyph text-justify break-word`} + > + {`*`} + </p> + </div> + <div + class={`flex flex-row h-full w-full justify-start items-start`} + > + <p + class={`col-span-10 font-mono font-[500] text-sm text-layer-0-glyph text-justify break-word`} + > + {`${$t(`eula.prohibited_content.body_li_0_${li}`)}`} + </p> + </div> + </div> + {/each} + </div> + </div> + <div + class={`flex flex-col w-full gap-2 justify-start items-start`} > - {`${$t(`common.continue`)}`} - </p> - </button> - <div - class={`flex flex-col justify-center items-center transition-all`} - > - {#if $carousel_index > 0} - <button - class={`group flex flex-row h-12 w-${$app_layout} justify-center items-center fade-in`} - on:click={async () => { - await handle_carousel_prev(); - }} + <p + class={`font-mono font-[600] text-layer-0-glyph`} > - <p - class={`font-sans font-[600] tracking-wide text-layer-1-glyph-shade group-active:text-layer-1-glyph/40 transition-all`} - > - {`${$t(`common.back`)}`} - </p> - </button> - {:else} + {`**${$t(`eula.prohibited_conduct.title`)}**`} + </p> <div - class={`flex flex-row h-1 w-full justify-start items-center`} + class={`flex flex-col w-full justify-start items-start`} > - <Fill /> + {#each [0, 1, 2, 3] as li} + <div + class={`flex flex-row w-full justify-start items-center`} + > + <div + class={`flex flex-row h-full w-8 justify-start items-start`} + > + <p + class={` font-mono font-[500] text-sm text-layer-0-glyph text-justify break-word`} + > + {`*`} + </p> + </div> + <div + class={`flex flex-row h-full w-full justify-start items-start`} + > + <p + class={`col-span-10 font-mono font-[500] text-sm text-layer-0-glyph text-justify break-word`} + > + {`${$t(`eula.prohibited_conduct.body_li_0_${li}`)}`} + </p> + </div> + </div> + {/each} </div> - {/if} - </div> - </div> - </div> - <div - data-carousel-item={`setup`} - class={`carousel-item flex flex-col w-full max-mobile_y:pt-32 pt-36 pb-4 justify-start items-center`} - > - <div - class={`flex flex-col w-full gap-8 justify-start items-center`} - > - <div - class={`flex flex-row w-full justify-center items-center`} - > - <p - class={`font-mono font-[600] text-layer-0-glyph text-3xl`} + </div> + <div + class={`flex flex-col w-full gap-2 justify-start items-start`} > - {`1. ${`${$t(`common.profile`)}`}`} - </p> - </div> - <div - class={`flex flex-col h-36 w-full py-4 px-4 gap-5 justify-start items-center bg-layer-1-surface rounded-3xl`} - > + <p + class={`font-mono font-[600] text-layer-0-glyph`} + > + {`**${$t(`eula.consequences_of_violation.title`)}**`} + </p> + <p + class={`font-mono font-[500] text-layer-0-glyph text-sm text-justify break-word`} + > + {`${$t(`eula.consequences_of_violation.body`)}`} + </p> + </div> + <div + class={`flex flex-col w-full gap-2 justify-start items-start`} + > + <p + class={`font-mono font-[600] text-layer-0-glyph`} + > + {`**${$t(`eula.disclaimer.title`)}**`} + </p> + <p + class={`font-mono font-[500] text-layer-0-glyph text-sm text-justify break-word`} + > + {`${$t(`eula.disclaimer.body`)}`} + </p> + </div> + <div + class={`flex flex-col w-full gap-2 justify-start items-start`} + > + <p + class={`font-mono font-[600] text-layer-0-glyph`} + > + {`**${$t(`eula.changes.title`)}**`} + </p> + <p + class={`font-mono font-[500] text-layer-0-glyph text-sm text-justify break-word`} + > + {`${$t(`eula.changes.body`)}`} + </p> + </div> <div - class={`flex flex-row w-full justify-center items-center`} + class={`flex flex-col w-full gap-2 justify-start items-start`} > <p - class={`font-sans font-[600] text-layer-0-glyph text-xl`} + class={`font-mono font-[600] text-layer-0-glyph`} > - {`Choose a profile name`} + {`**${$t(`eula.contact.title`)}**`} + </p> + <p + class={`font-mono font-[500] text-layer-0-glyph text-sm text-justify break-word`} + > + {`${$t(`eula.contact.body`)}`} </p> </div> <div - class={`flex flex-row w-full justify-center items-center border-b-line border-b-layer-1-surface-edge`} + class={`flex flex-col w-full gap-2 justify-start items-start`} > - <InputElement - basis={{ - classes: `h-10 font-mono placeholder:opacity-60 items-end text-center`, - id: fmt_id(`profile_name`), - sync: true, - sync_init: true, - placeholder: `Enter a profile name`, - field: { - charset: regex.profile_name_ch, - validate: regex.profile_name, - validate_keypress: true, - }, - callback_keydown: async ({ - key, - el, - }) => { - if (key === `Enter`) { - el.blur(); - await handle_carousel_next(); - } - }, - }} - /> + <p + class={`font-mono font-[600] text-layer-0-glyph`} + > + {`**${$t(`eula.acceptance_of_terms.title`)}**`} + </p> + <p + class={`font-mono font-[500] text-layer-0-glyph text-sm text-justify break-word`} + > + {`${$t(`eula.acceptance_of_terms.body`)}`} + </p> </div> </div> </div> - </div> - </div> - </div> - </div> - <div - data-view={`keypair_new`} - class={`hidden flex flex-col h-full w-full max-mobile_base:pt-12 pt-16 justify-start items-center fade-in`} - > - <div - class={`relative flex flex-col h-full w-full justify-start items-center`} - > - <div - data-carousel-container={`keypair_new`} - class={`carousel-container flex h-full w-full rounded-2xl scrollbar-hide`} - > - <div - data-carousel-item={`keypair_new`} - class={`carousel-item flex flex-col w-full max-mobile_y:pt-12 pt-12 pb-4 gap-8 justify-start items-center`} - > <div - class={`flex flex-col w-full gap-8 justify-start items-center`} + class={`flex flex-row h-20 w-full justify-center items-center`} > - <div - class={`flex flex-row w-full justify-center items-center`} + <button + class={`group flex flex-row basis-1/2 gap-4 justify-center items-center`} + on:click={async () => { + const confirm = await dialog.confirm({ + message: `${$t(`eula.error.required`)}`, + cancel_label: `${$t(`common.quit`)}`, + }); + if (confirm === false) location.reload(); //@todo + }} > <p - class={`font-mono font-[600] text-layer-0-glyph text-3xl`} + class={`font-mono font-[400] text-sm text-layer-0-glyph/60 group-active:text-layer-0-glyph transition-all`} > - {`Keypair Profile`} + {`-`} </p> - </div> - </div> - <div - class={`flex flex-col w-full gap-4 justify-start items-center`} - > - {#each keypair_new_buttons as btn} - <button - class={`flex flex-row h-16 w-${$app_layout} py-2 px-4 gap-4 justify-center items-center bg-layer-1-surface rounded-touch touch-layer-1 touch-layer-1-raise-less`} - on:click|preventDefault={async () => { - handle_keypair_buttons_select(btn.key); - }} + <p + class={`font-mono font-[400] text-sm text-layer-0-glyph/60 group-active:text-layer-0-glyph transition-all`} > - <div - class={`flex flex-row h-full w-12 justify-center items-center bg-layer-1-surface rounded-xl`} - > - <Glyph - basis={{ - classes: `text-layer-1-glyph`, - key: btn.icon, - dim: `lg`, - weight: btn.weight || `fill`, - }} - /> - </div> - <div - class={`flex flex-col flex-grow h-full justify-between items-start`} - > - <div class={`flex flex-row gap-[2px]`}> - <p - class={`font-sans text-[1.1rem] font-[500] text-layer-1-glyph/80`} - > - {btn.heading} - </p> - </div> - <p - class={`font-sans text-[0.9rem] text-layer-1-glyph-shade`} - > - {btn.subtitle} - </p> - </div> - <div - class={`flex flex-row h-full w-6 justify-end items-center`} - > - <Glyph - basis={{ - key: keypair_new_buttons_selected.includes( - btn.key, - ) - ? `check-circle` - : `circle`, - classes: - keypair_new_buttons_selected.includes( - btn.key, - ) - ? `text-layer-1-glyph-hl` - : `text-layer-1-glyph-shade`, - dim: `md+`, - weight: keypair_new_buttons_selected.includes( - btn.key, - ) - ? `fill` - : `bold`, - }} - /> - </div> - </button> - {/each} - </div> - </div> - </div> - <div - class={`absolute bottom-0 left-0 flex flex-col w-full justify-center items-center`} - > - {#if keypair_new_buttons_selected.length} - <button - class={`group flex flex-row h-[3.25rem] w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-touch touch-layer-1 fade-in`} - on:click={async () => { - alert(`@todo`); - }} - > - <p - class={`font-sans font-[600] tracking-wide text-layer-1-glyph/80 group-active:text-layer-1-glyph/40 transition-all`} + {`${`${$t(`common.disagree`)}`}`} + </p> + <p + class={`font-mono font-[400] text-sm text-layer-0-glyph/60 group-active:text-layer-0-glyph transition-all`} + > + {`-`} + </p> + </button> + <button + class={`group flex flex-row basis-1/2 gap-4 justify-center items-center ${el_eula_scrolled ? `` : `opacity-40`}`} + on:click={async () => { + if (el_eula_scrolled) await configure_device(); + }} > - {`${$t(`common.continue`)}`} - </p> - </button> - {:else} - <div - class={`flex flex-row h-12 w-full justify-start items-center`} - > - <Fill /> + <p + class={`font-mono font-[400] text-sm text-layer-0-glyph-hl group-active:text-layer-0-glyph-hl/80 transition-all`} + > + {`-`} + </p> + <p + class={`font-mono font-[400] text-sm text-layer-0-glyph-hl group-active:text-layer-0-glyph-hl/80 transition-all`} + > + {`${`${$t(`common.agree`)}`}`} + </p> + <p + class={`font-mono font-[400] text-sm text-layer-0-glyph-hl group-active:text-layer-0-glyph-hl/80 transition-all`} + > + {`- `} + </p> + </button> </div> - {/if} + </div> </div> </div> </div> diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte @@ -1,28 +1,29 @@ <script lang="ts"> import { page } from "$app/stores"; - import { LayoutView } from "@radroots/svelte-lib"; + import { Glyph, LayoutArea, Nav, t } from "@radroots/svelte-lib"; </script> -{#if $page} - <LayoutView> - <div class={`flex flex-col w-full justify-start items-start`}> - <div class={`flex flex-row w-full justify-center items-center`}> - <p class={`font-sans font-[400] text-layer-2-glyph`}> - {`${$page.status}: ${$page.error ? $page.error.message : `(no message)`}`} - </p> - </div> - <div - class={`flex flex-row w-full gap-2 justify-center items-center`} - > - <p class={`font-sans font-[400] text-layer-2-glyph`}> - {`There was an error.`} - </p> - <a href="/"> - <p class={`font-sans font-[400] text-layer-1-glyph-hl`}> - {`Click to return.`} - </p> - </a> - </div> +<LayoutArea> + <div class={`flex flex-col h-full w-full justify-center items-center`}> + <div class={`flex flex-col justify-start items-center`}> + <Glyph + basis={{ + classes: `text-layer-1-glyph-shade`, + key: `subtitles-slash`, + dim: `xl`, + }} + /> + <p class={`font-sans font-[400] text-layer-0-glyph`}> + {`${$t(`error.client.page.status.${$page.status}`, { default: `${$t(`error.client.unhandled`)}` })}`} + </p> </div> - </LayoutView> -{/if} + </div> +</LayoutArea> +<Nav + basis={{ + prev: { + label: `Home`, + route: `/`, + }, + }} +/> diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte @@ -1,66 +1,50 @@ <script lang="ts"> - import { browser } from "$app/environment"; - import { geoc, lc } from "$lib/client"; - import { _conf } from "$lib/conf"; - import { defineCustomElements as pwaElements } from "@ionic/pwa-elements/loader"; + import { goto } from "$app/navigation"; + import { dialog, keystore, notification } from "$lib/client"; + import { cfg, ks } from "$lib/conf"; import { app_config, app_db, app_geoc, - app_layout, + app_loading, app_nostr_key, app_notify, - app_pwa_polyfills, - app_render, app_th, app_thc, - app_win, AppControls, CssStatic, CssStyles, + LayoutWindow, + LoadingView, route, sleep, theme_set, + type NavigationRoute, } from "@radroots/svelte-lib"; import { parse_color_mode, parse_theme_key } from "@radroots/theme"; - import { - applyPolyfills, - defineCustomElements as jeepSqlite, - } from "jeep-sqlite/loader"; + import { onMount } from "svelte"; import "../app.css"; - $: { - if (browser && lc.platform === `web`) { - applyPolyfills().then(() => { - pwaElements(window); - jeepSqlite(window); - }); - const el = document.createElement(`jeep-sqlite`); - document.body.appendChild(el); - customElements - .whenDefined(`jeep-sqlite`) - .then(() => { - app_config.set(true); - }) - .catch((e) => { - console.log(`(pwa polyfills) error `, e); - app_pwa_polyfills.set(false); - }); - } else if (browser) { - app_config.set(true); + let route_render: NavigationRoute | undefined = undefined; + + onMount(async () => { + try { + app_loading.set(true); + } catch (e) { + } finally { } - } + }); app_thc.subscribe((app_thc) => { const color_mode = parse_color_mode(app_thc); theme_set(parse_theme_key($app_th), color_mode); - lc.window.status_style(color_mode); + //window.status_style(color_mode); }); app_th.subscribe((app_th) => { const color_mode = parse_color_mode($app_thc); theme_set(parse_theme_key(app_th), color_mode); - lc.window.status_style(color_mode); + //window.status_style(color_mode); }); app_db.subscribe((_app_db) => { @@ -73,84 +57,67 @@ console.log(`(app_geoc) success`); }); - app_config.subscribe(async (app_config) => { + app_config.subscribe(async (_app_config) => { try { - if (!app_config) return; - console.log(`app_config!`); - - const db_connected = await lc.db.connect(); - app_db.set(!!db_connected); + if (!_app_config) { + console.log(`(app_config) done`); + return; + } + console.log(`(app_config) start`); - const geoc_connected = await geoc.connect(); - app_geoc.set(!!geoc_connected); + await keystore.init(); + await notification.init(); - const active_key_public = await lc.preferences.get( - _conf.kv.nostr_key_active, - ); - if (active_key_public) { - const active_key_secret = await lc.keystore.get( - _conf.kv.nostr_key(active_key_public), + const ks_public_key = await keystore.get(ks.nostr.nostr_key_active); + if (`result` in ks_public_key) { + const ks_secret_key = await keystore.get( + ks.nostr.nostr_key(ks_public_key.result), ); - if (active_key_secret) { - app_nostr_key.set(active_key_public); - return; + if (`result` in ks_secret_key) { + app_nostr_key.set(ks_public_key.result); } + } else { + route_render = "/conf/init"; } - - await lc.preferences.remove(_conf.kv.nostr_key_active); - await route(`/conf/init`); - } catch (e) { - console.log(`(app_config) error `, e); - } finally { - app_render.set(true); - } - }); - - app_render.subscribe(async (app_render) => { - 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(_conf.cmd.layout_route); - if (app_init_route) { - init_route = app_init_route; - await kv.delete(_conf.cmd.layout_route); + await goto(`/`); + if (route_render) { + await sleep(cfg.delay.load); + await route(route_render); } - console.log(`init_route `, init_route); - */ - await sleep(_conf.delay.load); } catch (e) { - console.log(`(app_render) error `, e); + console.log(`(app_config) error `, e); } finally { - await lc.window.splash_hide(); + app_loading.set(false); + //await win.splash_hide(); } }); app_notify.subscribe(async (_app_notify) => { - if (!_app_notify) return; + if (!_app_notify) { + app_loading.set(false); + return; + } + app_loading.set(true); route(`/`); - await sleep(_conf.delay.notify); - lc.dialog.alert(_app_notify); + await sleep(cfg.delay.notify); + dialog.alert(_app_notify); app_notify.set(``); }); </script> <svelte:head> - <meta name="description" content={_conf.app.description} /> - <meta property="og:title" content={_conf.app.title} /> - <meta property="og:description" content={_conf.app.description} /> + <meta name="description" content={cfg.app.description} /> + <meta property="og:title" content={cfg.app.title} /> + <meta property="og:description" content={cfg.app.description} /> </svelte:head> -{#if $app_render} - <slot /> -{/if} + +<LayoutWindow> + {#if !$app_loading} + <slot /> + {:else} + <LoadingView /> + {/if} +</LayoutWindow> <AppControls /> <CssStatic /> <CssStyles /> -<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 top-dim_map_offset_top_base top-dim_map_offset_top_lg" -></div> -<div - class="hidden border-layer-1-surface-edge/40 text-blue-400 w-mobile_base w-mobile_y" -></div> diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts @@ -5,7 +5,7 @@ export const prerender = true; export const ssr = false; export const trailingSlash = 'always'; -export const load: LayoutLoad = async ({ url, }: LayoutLoadEvent) => { +export const load: LayoutLoad = async ({ url }: LayoutLoadEvent) => { try { const { language: nav_locale } = navigator; let locale = default_locale.toString(); diff --git a/static/splashscreen.html b/static/splashscreen.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> + <head> + <title>Radroots</title> + <style> + body { + margin: 0; + } + + .splashscreen-image { + background-color: #444; + background-image: url('logo.png'); + background-position: center; + background-repeat: no-repeat; + background-size: 50%; + width: 100vw !important; + height: 100vh !important; + overflow: hidden; + } + </style> + </head> + + <body> + <div class="splashscreen-image" /> + </body> +</html> +\ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts @@ -1,125 +1,151 @@ import { theme_colors, themes } from "@radroots/theme"; +import { wind } from "@radroots/utils"; import daisyui from "daisyui"; import type { Config } from "tailwindcss"; import tailwind_default from "tailwindcss/defaultTheme"; const { fontFamily: tw_font } = tailwind_default; const heights_form = { - line: "42px", + line: "42px", +}; + +const heights_responsive = { + tabs_mobile_base: `64px`, + tabs_mobile_y: `86px`, + nav_mobile_base: `71px`, + nav_mobile_y: `100px`, + view_mobile_base: `31rem`, + view_mobile_y: `42rem`, + view_offset_mobile_base: `1rem`, + view_offset_mobile_y: `2rem` }; const heights = { - line: `46px`, - tabs_base: `64px`, - tabs_lg: `86px`, - nav_base: `71px`, - nav_lg: `100px`, - envelope_top: "56px", - toast_min: `56px`, - envelope_button: `50px`, + ...heights_responsive, + entry_bold: `3.75rem`, + entry_guide: `3.6rem`, + touch_bold: `4.25rem`, + touch_guide: `3.4rem`, + line: `46px`, + envelope_top: "56px", + toast_min: `56px`, + envelope_button: `50px`, +}; + + +const widths_responsive = { + mobile_base: `335px`, + mobile_y: `345px` }; const widths = { - line: `320px`, - trellis_line: `349px`, - trellis_value: `180px`, - trellis_display: `290px` + ...widths_responsive, + line: `320px`, + trellis_line: `349px`, + trellis_value: `180px`, + trellis_display: `290px`, +}; + +const dimensions_responsive = { + map_offset_top_mobile_base: `32px`, + map_offset_top_mobile_y: `64px`, }; const dimensions = { - glyph_btn_sm: `28px`, - map_circle: `16px`, - map_circle_inner: `10px`, - map_offset_top_base: `32px`, - map_offset_top_lg: `64px`, -} + ...dimensions_responsive, + glyph_btn_sm: `28px`, + map_circle: `16px`, + map_circle_inner: `10px`, +}; const config: Config = { - content: [ - `src/**/*.{ts,svelte}`, - `../../packages/svelte-lib/src/**/*.{ts,svelte}`, - ], - theme: { - extend: { - colors: { - ...theme_colors, - }, - fontFamily: { - sans: ['SF Pro Display', ...tw_font.sans], - serif: [...tw_font.serif], - mono: [...tw_font.mono], - apercu: ['Apercu Mono Pro'], - magda: [`Magda Text`], - lust: [`Lust`], - }, - fontSize: { - lg_: ["1.0875rem", { lineHeight: "1.625", fontWeight: 400 }], - // font-size: 1.125rem; /* 18px */ - //line-height: 1.75rem; - 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 }], - navCurrent: ["1.09rem", { lineHeight: "1.33rem", fontWeight: 500 }], - envelopeTitle: ["1.05rem", { lineHeight: "1.75rem", fontWeight: 600 }], - envelopeTitlePrevious: ["1.02rem", { lineHeight: "1.75rem", fontWeight: 400 }], - envelopeTitleAction: ["1.02rem", { lineHeight: "1.75rem", fontWeight: 500 }], - envelopeButtonCancel: ["1.1rem", { lineHeight: "1.75rem", fontWeight: 600 }], - envelopeButtonLabel: ["1.1rem", { lineHeight: "1.75rem", fontWeight: 500 }], - }, - height: { - ...heights, - ...dimensions, - ...Object.fromEntries(Object.entries(heights_form).map(([k, v]) => [`form_${k}`, v])), - }, - width: { - ...widths, - ...dimensions, - }, - minHeight: { - ...heights - }, - minWidth: { - ...widths - }, - maxHeight: { - ...heights - }, - maxWidth: { - ...widths - }, - padding: { - ...Object.fromEntries(Object.entries(heights).map(([k, v]) => [`h_${k}`, v])), - ...Object.fromEntries(Object.entries(widths).map(([k, v]) => [`w_${k}`, v])), - ...Object.fromEntries(Object.entries(dimensions).map(([k, v]) => [`dim_${k}`, v])), - }, - translate: { - ...Object.fromEntries(Object.entries(heights).map(([k, v]) => [`h_${k}`, v])), - ...Object.fromEntries(Object.entries(widths).map(([k, v]) => [`w_${k}`, v])), - }, - spacing: { - ...Object.fromEntries(Object.entries(dimensions).map(([k, v]) => [`dim_${k}`, v])), - }, - borderWidth: { - "line": "1px" - }, - borderRadius: { - input_form: "8px", - }, - } - }, - plugins: [ - daisyui - ], - daisyui: { - themes: [ - themes.theme_earth_light, - themes.theme_earth_dark, - themes.theme_os_dark, - themes.theme_os_light, + content: [ + `src/**/*.{ts,svelte}`, + `../../packages/svelte-lib/src/**/*.{ts,svelte}`, + ], + theme: { + screens: { + mobile_y: { raw: `(orientation: portrait) and (min-height: ${wind.app.layout.mobile_y}px)` }, + mobile_base: { raw: `(orientation: portrait) and (max-height: ${wind.app.layout.mobile_base}px)` }, + }, + extend: { + colors: { + ...theme_colors, + }, + fontFamily: { + sans: ['SF Pro Display', ...tw_font.sans], + serif: [...tw_font.serif], + mono: [...tw_font.mono], + apercu: ['Apercu Mono Pro'], + magda: [`Magda Text`], + lust: [`Lust`], + }, + fontSize: { + trellisTitle: ["0.8rem", { lineHeight: "1rem", fontWeight: 200 }], + trellisTitleNote: ["0.76rem", { lineHeight: "1rem", fontWeight: 200 }], + line_display: ["1.05rem", { lineHeight: "1.33rem", fontWeight: 300 }], + trellisLabel: ["0.8rem", { lineHeight: "1rem", fontWeight: 200 }], + navPrevious: ["1.09rem", { lineHeight: "1.33rem", fontWeight: 400 }], + navCurrent: ["1.09rem", { lineHeight: "1.33rem", fontWeight: 500 }], + envelopeTitle: ["1.05rem", { lineHeight: "1.75rem", fontWeight: 600 }], + envelopeTitlePrevious: ["1.02rem", { lineHeight: "1.75rem", fontWeight: 400 }], + envelopeTitleAction: ["1.02rem", { lineHeight: "1.75rem", fontWeight: 500 }], + envelopeButtonCancel: ["1.1rem", { lineHeight: "1.75rem", fontWeight: 600 }], + envelopeButtonLabel: ["1.1rem", { lineHeight: "1.75rem", fontWeight: 500 }], + }, + height: { + ...heights, + ...dimensions, + ...Object.fromEntries(Object.entries(heights_form).map(([k, v]) => [`form_${k}`, v])), + }, + width: { + ...widths, + ...dimensions, + }, + minHeight: { + ...heights + }, + minWidth: { + ...widths + }, + maxHeight: { + ...heights + }, + maxWidth: { + ...widths + }, + padding: { + ...Object.fromEntries(Object.entries(heights).map(([k, v]) => [`h_${k}`, v])), + ...Object.fromEntries(Object.entries(widths).map(([k, v]) => [`w_${k}`, v])), + ...Object.fromEntries(Object.entries(dimensions).map(([k, v]) => [`dim_${k}`, v])), + }, + translate: { + ...Object.fromEntries(Object.entries(heights).map(([k, v]) => [`h_${k}`, v])), + ...Object.fromEntries(Object.entries(widths).map(([k, v]) => [`w_${k}`, v])), + }, + spacing: { + ...Object.fromEntries(Object.entries(dimensions).map(([k, v]) => [`dim_${k}`, v])), + }, + borderWidth: { + "line": "1px" + }, + borderRadius: { + input_form: "8px", + touch: "1.25rem" + }, + } + }, + plugins: [ + daisyui ], - }, + daisyui: { + themes: [ + themes.theme_earth_light, + themes.theme_earth_dark, + themes.theme_os_dark, + themes.theme_os_light, + ], + }, }; export default config; diff --git a/vite.config.ts b/vite.config.ts @@ -2,6 +2,7 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; const port = process.env.RADROOTS_APP_PORT ? Number(process.env.RADROOTS_APP_PORT) : 3000; +const host = process.env.TAURI_DEV_HOST ? process.env.TAURI_DEV_HOST : false; export default defineConfig({ plugins: [ @@ -11,6 +12,19 @@ export default defineConfig({ server: { port, strictPort: true, - host: "localhost", + host, + hmr: host + ? { + protocol: "ws", + host, + port: port + 1, + } + : undefined, + watch: { + ignored: [ + "**/target/**", + "**/crates/**", + ], + }, }, });