changelog shortlog graph tags branches files raw help

Mercurial > demo / changeset: revamp

changeset 43: cc2204bc6109
parent 42: 5c58d05abae6
child 44: 99d4ab4f8d53
author: Richard Westhaver <ellis@rwest.io>
date: Sun, 28 Jul 2024 21:18:52 -0400
files: .gitlab-ci.yml Cargo.toml Containerfile demo.asd makefile pkg.lisp run.lisp rustfmt.toml skelfile src/cfg.lisp src/cli/cli.lisp src/cli/package.lisp src/crates/obj/Cargo.toml src/crates/obj/proc_macros/Cargo.toml src/crates/obj/proc_macros/src/derive.rs src/crates/obj/proc_macros/src/lib.rs src/crates/obj/src/auth.rs src/crates/obj/src/cfg.rs src/crates/obj/src/database.rs src/crates/obj/src/err.rs src/crates/obj/src/hash.rs src/crates/obj/src/id.rs src/crates/obj/src/lib.rs src/crates/obj/src/network.rs src/crates/obj/src/types.rs src/crates/service/Cargo.toml src/crates/service/lib.rs src/crates/service/main.rs src/crates/service/tests.rs src/crates/ui/Cargo.toml src/crates/ui/build.rs src/crates/ui/config.slint src/crates/ui/img/ayo.jpeg src/crates/ui/img/treez.png src/crates/ui/index.html src/crates/ui/lib.rs src/crates/ui/main.rs src/crates/ui/pages.slint src/crates/ui/pages/about.slint src/crates/ui/pages/controls.slint src/crates/ui/pages/list_view.slint src/crates/ui/pages/page.slint src/crates/ui/pages/table_view.slint src/crates/ui/pages/text_edit.slint src/crates/ui/sidebar.slint src/crates/ui/ui.slint src/db/db.lisp src/package.lisp src/tests/clients/cli.lisp src/tests/clients/web.lisp src/tests/package.lisp src/tests/services/weather.lisp src/tests/utils.lisp src/ui/ui.lisp src/utils/rs.lisp src/utils/utils.lisp system-index.txt
description: revamp
     1.1--- a/.gitlab-ci.yml	Thu Jun 20 22:31:58 2024 -0400
     1.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3@@ -1,32 +0,0 @@
     1.4-image: fukamachi/sbcl
     1.5-before_script:
     1.6-- apt-get mercurial
     1.7-- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
     1.8-- rustup default nightly
     1.9-- hg clone https://lab.rwest.io/otom8/demo ~/quicklisp/local-projects/demo
    1.10-stages:
    1.11-  - build
    1.12-  - test
    1.13-  - deploy
    1.14-build-job:
    1.15-  stage: build
    1.16-  script:
    1.17-    - echo "Compiling the code..."
    1.18-    - make build
    1.19-    - echo "Compile complete."
    1.20-unit-test-job:
    1.21-  stage: test
    1.22-  script:
    1.23-    - echo "Running unit tests..."
    1.24-    - make test
    1.25-lint-test-job:
    1.26-  stage: test
    1.27-  script:
    1.28-    - echo "Linting code..."
    1.29-    - make fmt
    1.30-    - echo "No lint issues found."
    1.31-deploy-job:
    1.32-  stage: deploy
    1.33-  script:
    1.34-    - echo "Deploying application..."
    1.35-    - echo "Application successfully deployed."
    1.36\ No newline at end of file
     2.1--- a/Cargo.toml	Thu Jun 20 22:31:58 2024 -0400
     2.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3@@ -1,2 +0,0 @@
     2.4-[workspace]
     2.5-members = ["src/crates/obj","src/crates/ui","src/crates/service"]
     3.1--- a/Containerfile	Thu Jun 20 22:31:58 2024 -0400
     3.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3@@ -1,10 +0,0 @@
     3.4-FROM clfoundation/sbcl:latest
     3.5-ENV QUICKLISP_ADD_TO_INIT_FILE=true
     3.6-ENV QUICKLISP_DIST_VERSION=latest
     3.7-ENV LISP=sbcl
     3.8-WORKDIR /usr/src/demo
     3.9-COPY . .
    3.10-RUN mkdir -p ~/.config/common-lisp/source-registry.conf.d && \
    3.11-    echo '(:tree "/usr/src/demo")' >  ~/.config/common-lisp/source-registry.conf.d/workspace.conf && \
    3.12-    /usr/local/bin/install-quicklisp
    3.13-CMD [ "make", "ci" ]
    3.14\ No newline at end of file
     4.1--- a/demo.asd	Thu Jun 20 22:31:58 2024 -0400
     4.2+++ b/demo.asd	Sun Jul 28 21:18:52 2024 -0400
     4.3@@ -1,40 +1,15 @@
     4.4 ;;; demo.asd
     4.5 (defsystem "demo"
     4.6   :version "0.1.0"
     4.7-  :author "ellis <ellis@rwest.io>"
     4.8-  :maintainer "ellis <ellis@rwest.io>"
     4.9+  :author "Richard Westhaver <richard.westhaver@gmail.com>"
    4.10+  :maintainer "Richard Westhaver <richard.westhaver@gmail.com>"
    4.11   :description "comp demo system"
    4.12   :homepage "https://rwest.io/demo"
    4.13-  :bug-tracker "https://lab.rwest.io/otom8/demo/issues"
    4.14-  :source-control (:hg "https://lab.rwest.io/otom8/demo")
    4.15+  :bug-tracker "https://vc.compiler.ocmpany/demo/issues"
    4.16+  :source-control (:hg "https://vc.compiler.company/demo")
    4.17   :license "WTF"
    4.18-  :depends-on (:sxp :log4cl :bordeaux-threads :clog)
    4.19-  :in-order-to ((test-op (test-op "demo/tests")))
    4.20-  :components ((:file "src/package")
    4.21-	       (:file "src/cfg")))
    4.22+  :depends-on (:user)
    4.23+  :components ((:file "pkg")))
    4.24 
    4.25 (defmethod perform :after ((op load-op) (c (eql (find-system :demo))))
    4.26   (pushnew :demo *features*))
    4.27-
    4.28-(defsystem "demo/cli"
    4.29-  :depends-on ("demo" "clingon")
    4.30-  :components ((:module "src/cli"
    4.31-		:components ((:file "cli"))))
    4.32-  :in-order-to ((test-op (test-op "demo/tests")))
    4.33-  :build-operation "program-op"
    4.34-  :build-pathname "bin/demo")
    4.35-
    4.36-(defsystem "demo/tests"
    4.37-  :depends-on ("demo" "demo-cli" "fiveam")
    4.38-  :components ((:module "src/tests"
    4.39-		:serial t
    4.40-		:components
    4.41-		((:file "package")
    4.42-		 (:file "utils")
    4.43-		 (:module "clients"
    4.44-		  :serial t
    4.45-		  :components
    4.46-		  ((:file "cli")
    4.47-		   (:file "web"))))))
    4.48-  :perform (test-op (op component)
    4.49-		    (uiop:symbol-call '#:demo-tests '#:run-tests)))
     5.1--- a/makefile	Thu Jun 20 22:31:58 2024 -0400
     5.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3@@ -1,23 +0,0 @@
     5.4-# otom8/demo makefile
     5.5-MODE?=release
     5.6-LISP?=sbcl
     5.7-CFG?=default.cfg
     5.8-L_C=$(L) --no-userinit
     5.9-L_D=$(L) --load demo.asd --eval '(ql:quickload "demo")'
    5.10-L_S=$(L) --script
    5.11-ARCH?=
    5.12-A_C=ifeq ($(ARCH),x86_64) A_C=arch -$(ARCH) endif
    5.13-.PHONY:build
    5.14-RS:Cargo.toml rustfmt.toml src/crates/*
    5.15-CL:*/*.asd */*.lisp
    5.16-deps:;
    5.17-clean:;rm -rf **/*.fasl;cargo clean
    5.18-fmt:$(RS);cargo fmt
    5.19-build:$(RS) $(CL);cargo build --$(MODE);$(L_D)
    5.20-	--eval '(asdf:make "demo")' \
    5.21-	--eval '(quit)'
    5.22-docs:$(RS);cargo doc
    5.23-test:$(RS) $(CL);cargo test;$(L_D) --eval '(asdf:test "demo")' --eval '(quit)'
    5.24-#pack:;scripts/pack.ros
    5.25-#check:;scripts/check.ros
    5.26-ci:clean fmt build docs test;
     6.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2+++ b/pkg.lisp	Sun Jul 28 21:18:52 2024 -0400
     6.3@@ -0,0 +1,9 @@
     6.4+;; demo packages.lisp
     6.5+(defpackage :demo-int
     6.6+  (:use :cl :std))
     6.7+
     6.8+(defpackage :demo
     6.9+  (:use #:cl #:demo-int))
    6.10+
    6.11+(std:defpkg :demo-user
    6.12+  (:use-reexport :demo))
     7.1--- a/run.lisp	Thu Jun 20 22:31:58 2024 -0400
     7.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3@@ -1,2 +0,0 @@
     7.4-(defparameter *cwd* (asdf:system-source-directory :demo))
     7.5-(load (merge-pathnames "tools/build-image.lisp" *cwd*))
     8.1--- a/rustfmt.toml	Thu Jun 20 22:31:58 2024 -0400
     8.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3@@ -1,3 +0,0 @@
     8.4-edition = "2021"
     8.5-tab_spaces = 2
     8.6-wrap_comments = true
     8.7\ No newline at end of file
     9.1--- a/skelfile	Thu Jun 20 22:31:58 2024 -0400
     9.2+++ b/skelfile	Sun Jul 28 21:18:52 2024 -0400
     9.3@@ -1,4 +1,4 @@
     9.4-;;; demo/skelfile --- Demo Skeleton
     9.5+;;; demo/skelfile --- Demo Skelfile
     9.6 :name demo
     9.7 :author "Richard Westhaver <richard.westhaver@gmail.com>"
     9.8 :version "0.1.0"
    11.1--- a/src/cli/cli.lisp	Thu Jun 20 22:31:58 2024 -0400
    11.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3@@ -1,45 +0,0 @@
    11.4-;; cli.lisp
    11.5-(in-package :demo-cli)
    11.6-
    11.7-(defparameter demo-path (merge-pathnames "demo" (uiop:temporary-directory)))
    11.8-
    11.9-(defvar db-path (merge-pathnames "db" demo-path))
   11.10-
   11.11-(defun cli-opts ()
   11.12-  "Returns the top-level CLI options."
   11.13-  (list
   11.14-   (clingon:make-option
   11.15-    :string
   11.16-    :description "demo app to run"
   11.17-    :short-name #\x
   11.18-    :long-name "app"
   11.19-    :initial-value "client"
   11.20-    :env-vars '("DEMO_APP")
   11.21-    :key :app)
   11.22-   (clingon:make-option
   11.23-    :string
   11.24-    :description "path to config"
   11.25-    :short-name #\c
   11.26-    :long-name "config"
   11.27-    :initial-value "$DEMO_PATH/.fig"
   11.28-    :env-vars '("DEMO_CONFIG"))))
   11.29-
   11.30-(defun cli-handler (cmd)
   11.31-  "Handler for the `demo' command."
   11.32-  (let ((app (clingon:getopt cmd :app)))
   11.33-    (format t "running: ~A!~%" app)))
   11.34-
   11.35-(defun cli-cmd ()
   11.36-  "Our demo command."
   11.37-  (clingon:make-command
   11.38-   :name "demo"
   11.39-   :description "A collection of demos"
   11.40-   :version "1.0.0"
   11.41-   :authors '("ellis <ellis@rwest.io>")
   11.42-   :license "WTFPL"
   11.43-   :options (cli-opts)
   11.44-   :handler #'cli-handler))
   11.45-
   11.46-(defun run-cli ()
   11.47-  "A demo of some common-lisp functionality."
   11.48-  (clingon:run (cli-cmd)))
    12.1--- a/src/cli/package.lisp	Thu Jun 20 22:31:58 2024 -0400
    12.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3@@ -1,9 +0,0 @@
    12.4-(defpackage :demo-cli
    12.5-  (:use :demo)
    12.6-  (:export
    12.7-   #:run-cli
    12.8-   #:demo-path
    12.9-   #:db-path
   12.10-   #:cli-opts
   12.11-   #:cli-handler
   12.12-   #:cli-cmd))
    13.1--- a/src/crates/obj/Cargo.toml	Thu Jun 20 22:31:58 2024 -0400
    13.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3@@ -1,27 +0,0 @@
    13.4-[package]
    13.5-name = "obj"
    13.6-version = "0.1.0"
    13.7-edition = "2021"
    13.8-[features]
    13.9-oauth = ["yup-oauth2"]
   13.10-
   13.11-[dependencies]
   13.12-ron = "0.7.0"
   13.13-bincode = "1.3.3"
   13.14-serde_json = "1.0.68"
   13.15-serde = { version = "1.0.130", features = ["derive"] }
   13.16-chrono = { version = "0.4.19", features = ["serde"] }
   13.17-mime = "0.3.16"
   13.18-regex = "1.5.4"
   13.19-rusty_ulid = "0.11.0"
   13.20-uuid = { version = "0.8", features = ["serde"] }
   13.21-yup-oauth2 = { version = "5.1.0", optional = true }
   13.22-blake3 = "1.0.0"
   13.23-hashbrown = "0.11.2"
   13.24-rand = "0.8.0"
   13.25-sha2 = "0.9.5"
   13.26-hex = "0.4.3"
   13.27-ulid = "1.0.0"
   13.28-
   13.29-[target.'cfg(target_arch = "wasm32")'.dependencies]
   13.30-uuid = { version = "0.8", features = ["wasm-bindgen"] }
    14.1--- a/src/crates/obj/proc_macros/Cargo.toml	Thu Jun 20 22:31:58 2024 -0400
    14.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3@@ -1,10 +0,0 @@
    14.4-[package]
    14.5-name = "proc_macros"
    14.6-version = "0.1.0"
    14.7-edition = "2021"
    14.8-[lib]
    14.9-proc-macro = true
   14.10-[dependencies]
   14.11-quote = "1.0"
   14.12-proc-macro2 = "1.0"
   14.13-syn = "1.0"
   14.14\ No newline at end of file
    15.1--- a/src/crates/obj/proc_macros/src/derive.rs	Thu Jun 20 22:31:58 2024 -0400
    15.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3@@ -1,5 +0,0 @@
    15.4-mod derive;
    15.5-use proc_macro::TokenStream;
    15.6-pub fn derive_static_type(input: TokenStream) -> TokenStream {
    15.7-    derive::derive_static_type(input)
    15.8-}
    16.1--- a/src/crates/obj/proc_macros/src/lib.rs	Thu Jun 20 22:31:58 2024 -0400
    16.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3@@ -1,1 +0,0 @@
    16.4-
    17.1--- a/src/crates/obj/src/auth.rs	Thu Jun 20 22:31:58 2024 -0400
    17.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3@@ -1,72 +0,0 @@
    17.4-//! Auth Configs
    17.5-use serde::{Deserialize, Serialize};
    17.6-
    17.7-#[cfg(feature = "oauth")]
    17.8-use yup_oauth2::ApplicationSecret;
    17.9-
   17.10-#[derive(Serialize, Deserialize, Debug, Default, Hash)]
   17.11-pub struct AuthConfig {
   17.12-  pub provider: String,
   17.13-  #[cfg(feature = "oauth")]
   17.14-  pub oauth: Option<Oauth2Config>,
   17.15-  pub ssh: Option<SshConfig>,
   17.16-  pub pw: Option<PasswordConfig>,
   17.17-}
   17.18-
   17.19-#[derive(Serialize, Deserialize, Default, Debug, Hash)]
   17.20-pub struct PasswordConfig(String, String);
   17.21-
   17.22-#[cfg(feature = "oauth")]
   17.23-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone, Default)]
   17.24-pub struct Oauth2Config {
   17.25-  pub client_id: String,
   17.26-  pub client_secret: String,
   17.27-  pub redirect_uris: Vec<String>,
   17.28-  pub auth_uri: String,
   17.29-  pub token_uri: String,
   17.30-  pub project_id: Option<String>, //for apptoken
   17.31-  pub client_email: Option<String>,
   17.32-  /// The URL of the public x509 certificate, used to verify the signature on
   17.33-  /// JWTs, such as ID tokens, signed by the authentication provider.
   17.34-  pub auth_provider_x509_cert_url: Option<String>,
   17.35-  ///  The URL of the public x509 certificate, used to verify JWTs signed by the
   17.36-  /// client.
   17.37-  pub client_x509_cert_url: Option<String>,
   17.38-}
   17.39-
   17.40-#[cfg(feature = "oauth")]
   17.41-impl From<ApplicationSecret> for Oauth2Config {
   17.42-  fn from(shh: ApplicationSecret) -> Self {
   17.43-    Oauth2Config {
   17.44-      client_id: shh.client_id,
   17.45-      client_secret: shh.client_secret,
   17.46-      redirect_uris: shh.redirect_uris,
   17.47-      auth_uri: shh.auth_uri,
   17.48-      token_uri: shh.token_uri,
   17.49-      project_id: shh.project_id,
   17.50-      client_email: shh.client_email,
   17.51-      auth_provider_x509_cert_url: shh.auth_provider_x509_cert_url,
   17.52-      client_x509_cert_url: shh.client_x509_cert_url,
   17.53-    }
   17.54-  }
   17.55-}
   17.56-
   17.57-#[cfg(feature = "oauth")]
   17.58-impl From<Oauth2Config> for ApplicationSecret {
   17.59-  fn from(cfg: Oauth2Config) -> Self {
   17.60-    ApplicationSecret {
   17.61-      client_id: cfg.client_id,
   17.62-      client_secret: cfg.client_secret,
   17.63-      redirect_uris: cfg.redirect_uris,
   17.64-      auth_uri: cfg.auth_uri,
   17.65-      token_uri: cfg.token_uri,
   17.66-      project_id: cfg.project_id,
   17.67-      client_email: cfg.client_email,
   17.68-      auth_provider_x509_cert_url: cfg.auth_provider_x509_cert_url,
   17.69-      client_x509_cert_url: cfg.client_x509_cert_url,
   17.70-    }
   17.71-  }
   17.72-}
   17.73-
   17.74-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone, Default)]
   17.75-pub struct SshConfig {}
    18.1--- a/src/crates/obj/src/cfg.rs	Thu Jun 20 22:31:58 2024 -0400
    18.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3@@ -1,51 +0,0 @@
    18.4-/// common trait for all config modules. This trait provides functions
    18.5-/// for de/serializing to/from RON, updating fields, and formatting.
    18.6-use serde::{Serialize, Deserialize};
    18.7-use crate::Objective;
    18.8-use std::collections::HashMap as M;
    18.9-use std::path::PathBuf;
   18.10-use std::string::String as S;
   18.11-use std::error::Error as E;
   18.12-use std::boxed::Box as B;
   18.13-type R<X> = std::result::Result<X,B<dyn E>>;
   18.14-
   18.15-pub trait Configure: Objective {
   18.16-  fn update(&self) -> R<()> {
   18.17-    Ok(())
   18.18-  }
   18.19-}
   18.20-
   18.21-#[derive(Serialize, Deserialize, Debug, Default)]
   18.22-pub struct ShellConfig {
   18.23-  pub env: M<S,S>,
   18.24-  pub cmds: M<S,S>,
   18.25-  pub shell: ShellType,
   18.26-}
   18.27-
   18.28-impl Objective for ShellConfig {}
   18.29-
   18.30-#[derive(Serialize, Deserialize, Debug, Hash, Default)]
   18.31-pub enum ShellType {
   18.32-  #[default]
   18.33-  Bash,
   18.34-  Zsh,
   18.35-  Sh,
   18.36-}
   18.37-
   18.38-#[derive(Serialize, Deserialize, Debug, Default)]
   18.39-pub enum EditorType {
   18.40-  #[default]
   18.41-  Emacs,
   18.42-  Vi,
   18.43-  Nano,
   18.44-}
   18.45-
   18.46-#[derive(Serialize, Deserialize, Debug, Default)]
   18.47-pub struct EditorConfig {
   18.48-  pub editor: EditorType,
   18.49-  pub cmds: M<S,S>,
   18.50-  pub init_file: PathBuf,
   18.51-}
   18.52-
   18.53-#[cfg(test)]
   18.54-mod tests;
    19.1--- a/src/crates/obj/src/database.rs	Thu Jun 20 22:31:58 2024 -0400
    19.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3@@ -1,18 +0,0 @@
    19.4-//! cfg::config::database
    19.5-//!
    19.6-//! Database configuration primitives
    19.7-use serde::{Deserialize, Serialize};
    19.8-
    19.9-#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq)]
   19.10-pub struct DatabaseConfig {
   19.11-  engine: DatabaseType,
   19.12-  path: String,
   19.13-  cfs: Vec<String>,
   19.14-}
   19.15-
   19.16-#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq)]
   19.17-pub enum DatabaseType {
   19.18-  RocksDB,
   19.19-  Postgres,
   19.20-  Alch,
   19.21-}
    20.1--- a/src/crates/obj/src/err.rs	Thu Jun 20 22:31:58 2024 -0400
    20.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3@@ -1,81 +0,0 @@
    20.4-//! obj errors
    20.5-use std::{fmt, io};
    20.6-
    20.7-/// obj Result wrapper
    20.8-pub type Result<T> = std::result::Result<T, Error>;
    20.9-
   20.10-/// obj Error type
   20.11-#[derive(Debug)]
   20.12-pub enum Error {
   20.13-  Message(String),
   20.14-  Ron(ron::error::Error),
   20.15-  Json(serde_json::error::Error),
   20.16-  Io(io::Error),
   20.17-  Bincode(bincode::Error),
   20.18-  Utf8(std::string::FromUtf8Error),
   20.19-  Parse(std::string::ParseError),
   20.20-}
   20.21-
   20.22-impl serde::ser::Error for Error {
   20.23-  fn custom<T: fmt::Display>(msg: T) -> Self {
   20.24-    Error::Message(msg.to_string())
   20.25-  }
   20.26-}
   20.27-
   20.28-impl serde::de::Error for Error {
   20.29-  fn custom<T: fmt::Display>(msg: T) -> Self {
   20.30-    Error::Message(msg.to_string())
   20.31-  }
   20.32-}
   20.33-
   20.34-impl fmt::Display for Error {
   20.35-  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
   20.36-    match self {
   20.37-      Error::Message(msg) => f.write_str(msg),
   20.38-      Error::Io(ref err) => write!(f, "obj IO error: {}", err),
   20.39-      Error::Ron(ref err) => write!(f, "obj Ron error: {}", err),
   20.40-      Error::Json(ref err) => write!(f, "obj Json error: {}", err),
   20.41-      Error::Bincode(ref err) => write!(f, "obj Bincode error: {}", err),
   20.42-      Error::Utf8(ref err) => write!(f, "obj Utf8 error: {}", err),
   20.43-      Error::Parse(ref err) => write!(f, "obj Parse error: {}", err),
   20.44-    }
   20.45-  }
   20.46-}
   20.47-
   20.48-impl From<io::Error> for Error {
   20.49-  fn from(e: io::Error) -> Self {
   20.50-    Error::Io(e)
   20.51-  }
   20.52-}
   20.53-
   20.54-impl From<std::string::ParseError> for Error {
   20.55-  fn from(e: std::string::ParseError) -> Self {
   20.56-    Error::Parse(e)
   20.57-  }
   20.58-}
   20.59-
   20.60-impl From<std::string::FromUtf8Error> for Error {
   20.61-  fn from(err: std::string::FromUtf8Error) -> Self {
   20.62-    Error::Utf8(err)
   20.63-  }
   20.64-}
   20.65-
   20.66-impl From<ron::Error> for Error {
   20.67-  fn from(e: ron::Error) -> Self {
   20.68-    Error::Ron(e)
   20.69-  }
   20.70-}
   20.71-
   20.72-impl From<serde_json::Error> for Error {
   20.73-  fn from(e: serde_json::Error) -> Self {
   20.74-    Error::Json(e)
   20.75-  }
   20.76-}
   20.77-
   20.78-impl From<bincode::Error> for Error {
   20.79-  fn from(e: bincode::Error) -> Self {
   20.80-    Error::Bincode(e)
   20.81-  }
   20.82-}
   20.83-
   20.84-impl std::error::Error for Error {}
    21.1--- a/src/crates/obj/src/hash.rs	Thu Jun 20 22:31:58 2024 -0400
    21.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3@@ -1,51 +0,0 @@
    21.4-//! hash - wrapper for hash algorithms and types
    21.5-
    21.6-pub use blake3::{derive_key, hash, keyed_hash, Hash as B3Hash, Hasher as B3Hasher, OutputReader};
    21.7-pub use hex;
    21.8-pub use sha2::Sha512;
    21.9-
   21.10-pub use std::hash::{Hash, Hasher};
   21.11-
   21.12-pub const KEY_LEN: usize = 32;
   21.13-pub const OUT_LEN: usize = 32;
   21.14-pub const OUT_LEN_HEX: usize = OUT_LEN * 2;
   21.15-
   21.16-#[cfg(test)]
   21.17-mod tests {
   21.18-  use super::*;
   21.19-  use crate::*;
   21.20-  #[test]
   21.21-  fn id_state_hash() {
   21.22-    let id = id::Id(vec![0; KEY_LEN]);
   21.23-    let hash = id.state_hash(&mut B3Hasher::new());
   21.24-    assert_eq!(hash, id.state_hash(&mut B3Hasher::new()));
   21.25-  }
   21.26-
   21.27-  #[test]
   21.28-  fn id_hex() {
   21.29-    let id = id::Id(vec![255; KEY_LEN]);
   21.30-
   21.31-    assert_eq!(
   21.32-      hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(),
   21.33-      id.0
   21.34-    );
   21.35-  }
   21.36-
   21.37-  #[test]
   21.38-  fn rand_id() {
   21.39-    let id = id::Id::rand();
   21.40-    let hash = id.state_hash(&mut B3Hasher::new());
   21.41-    assert_eq!(hash, id.state_hash(&mut B3Hasher::new()));
   21.42-  }
   21.43-
   21.44-  #[test]
   21.45-  fn random_demon_id_is_valid() {
   21.46-    use id::PeerId;
   21.47-    for _ in 0..5000 {
   21.48-      let did = PeerId::rand();
   21.49-      let did2 = PeerId::rand();
   21.50-      assert_eq!(did, did);
   21.51-      assert_ne!(did, did2);
   21.52-    }
   21.53-  }
   21.54-}
    22.1--- a/src/crates/obj/src/id.rs	Thu Jun 20 22:31:58 2024 -0400
    22.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3@@ -1,120 +0,0 @@
    22.4-use crate::hash::{B3Hasher, KEY_LEN, OUT_LEN};
    22.5-use rand::Rng;
    22.6-use serde::{Deserialize, Serialize};
    22.7-use std::{fmt, str::FromStr};
    22.8-pub use ulid::Ulid;
    22.9-pub use uuid::Uuid;
   22.10-/// a simple Id abstraction
   22.11-#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Serialize, Deserialize, Hash)]
   22.12-pub struct Id(pub Vec<u8>);
   22.13-
   22.14-impl Id {
   22.15-  pub fn rand() -> Self {
   22.16-    let mut rng = rand::thread_rng();
   22.17-    let vals: Vec<u8> = (0..KEY_LEN).map(|_| rng.gen_range(0..u8::MAX)).collect();
   22.18-    Id(vals)
   22.19-  }
   22.20-
   22.21-  pub fn state_hash(&self, state: &mut B3Hasher) -> Self {
   22.22-    let mut output = vec![0; OUT_LEN];
   22.23-    state.update(&self.0);
   22.24-    let mut res = state.finalize_xof();
   22.25-    res.fill(&mut output);
   22.26-    Id(output)
   22.27-  }
   22.28-
   22.29-  pub fn to_hex(&self) -> String {
   22.30-    hex::encode(&self.0)
   22.31-  }
   22.32-}
   22.33-
   22.34-/// PeerId
   22.35-///
   22.36-/// identifies a unique Peer
   22.37-#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
   22.38-pub struct PeerId {
   22.39-  id: [u8; 32],
   22.40-}
   22.41-
   22.42-impl PeerId {
   22.43-  pub fn new() -> Self {
   22.44-    Self::default()
   22.45-  }
   22.46-
   22.47-  pub fn rand() -> Self {
   22.48-    let pd = rand::thread_rng().gen::<[u8; 32]>();
   22.49-    Self { id: pd }
   22.50-  }
   22.51-
   22.52-  pub fn from_bytes(data: &[u8]) -> Self {
   22.53-    let pd = blake3::hash(data);
   22.54-    let hash = pd.as_bytes();
   22.55-    Self { id: *hash }
   22.56-  }
   22.57-}
   22.58-
   22.59-impl Default for PeerId {
   22.60-  fn default() -> Self {
   22.61-    PeerId { id: [0; 32] }
   22.62-  }
   22.63-}
   22.64-
   22.65-/// Identity trait
   22.66-///
   22.67-/// Defines Identity-related behaviors
   22.68-pub trait Identity: Sized {
   22.69-  /// return the hashed bytes of an ObjectId
   22.70-  fn id(&self) -> Id;
   22.71-}
   22.72-
   22.73-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
   22.74-pub struct ObjectId(u128);
   22.75-
   22.76-pub struct NameSpace {
   22.77-  pub prefix: Option<String>,
   22.78-  pub capacity: u64,
   22.79-  pub route: Vec<Id>,
   22.80-  pub key: Option<Id>,
   22.81-}
   22.82-
   22.83-pub struct Domain {
   22.84-  pub ns: NameSpace,
   22.85-  pub id: Id,
   22.86-}
   22.87-
   22.88-impl From<Uuid> for ObjectId {
   22.89-  fn from(uuid: Uuid) -> Self {
   22.90-    ObjectId(uuid.as_u128())
   22.91-  }
   22.92-}
   22.93-
   22.94-impl From<Ulid> for ObjectId {
   22.95-  fn from(ulid: Ulid) -> Self {
   22.96-    ObjectId(u128::from(ulid))
   22.97-  }
   22.98-}
   22.99-
  22.100-impl From<u128> for ObjectId {
  22.101-  fn from(src: u128) -> Self {
  22.102-    ObjectId(src)
  22.103-  }
  22.104-}
  22.105-
  22.106-impl FromStr for ObjectId {
  22.107-  type Err = ();
  22.108-  fn from_str(input: &str) -> std::result::Result<ObjectId, Self::Err> {
  22.109-    match input {
  22.110-      i => Ok(ObjectId(u128::from(Ulid::from_str(i).unwrap()))),
  22.111-    }
  22.112-  }
  22.113-}
  22.114-
  22.115-impl fmt::Display for ObjectId {
  22.116-  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  22.117-    match *self {
  22.118-      ObjectId(i) => {
  22.119-        write!(f, "{}", Ulid::from(i))
  22.120-      }
  22.121-    }
  22.122-  }
  22.123-}
    23.1--- a/src/crates/obj/src/lib.rs	Thu Jun 20 22:31:58 2024 -0400
    23.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3@@ -1,148 +0,0 @@
    23.4-//! obj/src/lib.rs --- Objective type library
    23.5-#![feature(associated_type_bounds)]
    23.6-mod err;
    23.7-pub use err::{Error, Result};
    23.8-mod types;
    23.9-pub use types::*;
   23.10-pub mod auth;
   23.11-pub mod database;
   23.12-pub mod hash;
   23.13-pub mod id;
   23.14-pub mod network;
   23.15-pub use bincode;
   23.16-pub use ron;
   23.17-use ron::extensions::Extensions;
   23.18-use serde::{de::DeserializeOwned, Deserialize, Serialize};
   23.19-pub use serde_json;
   23.20-use std::collections::{BTreeMap, HashMap};
   23.21-use std::io;
   23.22-
   23.23-/// Objective trait
   23.24-/// Define Object behaviors, implemented by Objects
   23.25-pub trait Objective {
   23.26-  fn encode(&self) -> Result<Vec<u8>>
   23.27-  where
   23.28-    Self: Serialize,
   23.29-  {
   23.30-    Ok(bincode::serialize(self)?)
   23.31-  }
   23.32-
   23.33-  fn encode_into<W>(&self, writer: W) -> Result<()>
   23.34-  where
   23.35-    W: io::Write,
   23.36-    Self: Serialize,
   23.37-  {
   23.38-    Ok(bincode::serialize_into(writer, self)?)
   23.39-  }
   23.40-
   23.41-  fn decode<'a>(bytes: &'a [u8]) -> Result<Self>
   23.42-  where
   23.43-    Self: Deserialize<'a>,
   23.44-  {
   23.45-    Ok(bincode::deserialize(bytes)?)
   23.46-  }
   23.47-
   23.48-  fn decode_from<R>(&self, rdr: R) -> Result<Self>
   23.49-  where
   23.50-    R: io::Read,
   23.51-    Self: DeserializeOwned,
   23.52-  {
   23.53-    Ok(bincode::deserialize_from(rdr)?)
   23.54-  }
   23.55-
   23.56-  fn to_ron_writer<W>(&self, writer: W) -> Result<()>
   23.57-  where
   23.58-    W: io::Write,
   23.59-    Self: Serialize,
   23.60-  {
   23.61-    Ok(ron::ser::to_writer_pretty(
   23.62-      writer,
   23.63-      &self,
   23.64-      ron::ser::PrettyConfig::new()
   23.65-        .indentor("  ".to_owned())
   23.66-        .extensions(Extensions::all()),
   23.67-    )?)
   23.68-  }
   23.69-
   23.70-  fn to_ron_string(&self) -> Result<String>
   23.71-  where
   23.72-    Self: Serialize,
   23.73-  {
   23.74-    Ok(ron::ser::to_string_pretty(
   23.75-      &self,
   23.76-      ron::ser::PrettyConfig::new().indentor("  ".to_owned()),
   23.77-    )?)
   23.78-  }
   23.79-
   23.80-  fn from_ron_reader<R>(&self, mut rdr: R) -> Result<Self>
   23.81-  where
   23.82-    R: io::Read,
   23.83-    Self: DeserializeOwned,
   23.84-  {
   23.85-    let mut bytes = Vec::new();
   23.86-    rdr.read_to_end(&mut bytes)?;
   23.87-    Ok(ron::de::from_bytes(&bytes)?)
   23.88-  }
   23.89-
   23.90-  fn from_ron_str<'a>(s: &'a str) -> Result<Self>
   23.91-  where
   23.92-    Self: Deserialize<'a>,
   23.93-  {
   23.94-    Ok(ron::de::from_bytes(s.as_bytes())?)
   23.95-  }
   23.96-
   23.97-  fn to_json_writer<W>(&self, writer: W) -> Result<()>
   23.98-  where
   23.99-    W: io::Write,
  23.100-    Self: Serialize,
  23.101-  {
  23.102-    //    let formatter = serde_json::ser::PrettyFormatter::with_indent(b"  ");
  23.103-    Ok(serde_json::ser::to_writer_pretty(writer, &self)?)
  23.104-  }
  23.105-
  23.106-  fn to_json_string(&self) -> Result<String>
  23.107-  where
  23.108-    Self: Serialize,
  23.109-  {
  23.110-    Ok(serde_json::ser::to_string_pretty(&self)?)
  23.111-  }
  23.112-
  23.113-  fn from_json_reader<R>(&self, mut rdr: R) -> Result<Self>
  23.114-  where
  23.115-    R: io::Read,
  23.116-    Self: DeserializeOwned,
  23.117-  {
  23.118-    let mut bytes = Vec::new();
  23.119-    rdr.read_to_end(&mut bytes)?;
  23.120-    Ok(serde_json::de::from_slice(&bytes)?)
  23.121-  }
  23.122-
  23.123-  fn from_json_str<'a>(s: &'a str) -> Result<Self>
  23.124-  where
  23.125-    Self: Deserialize<'a>,
  23.126-  {
  23.127-    Ok(serde_json::de::from_slice(s.as_bytes())?)
  23.128-  }
  23.129-}
  23.130-
  23.131-impl<T> Objective for Vec<T> {}
  23.132-impl<K, V> Objective for HashMap<K, V> {}
  23.133-impl<K, V> Objective for BTreeMap<K, V> {}
  23.134-impl Objective for std::path::PathBuf {}
  23.135-impl Objective for std::path::Path {}
  23.136-impl Objective for std::string::String {}
  23.137-impl Objective for std::any::TypeId {}
  23.138-impl Objective for u8 {}
  23.139-impl Objective for u16 {}
  23.140-impl Objective for u32 {}
  23.141-impl Objective for u64 {}
  23.142-impl Objective for u128 {}
  23.143-impl Objective for i8 {}
  23.144-impl Objective for i16 {}
  23.145-impl Objective for i32 {}
  23.146-impl Objective for i64 {}
  23.147-impl Objective for i128 {}
  23.148-impl Objective for isize {}
  23.149-impl Objective for usize {}
  23.150-impl Objective for f32 {}
  23.151-impl Objective for f64 {}
    24.1--- a/src/crates/obj/src/network.rs	Thu Jun 20 22:31:58 2024 -0400
    24.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3@@ -1,59 +0,0 @@
    24.4-//! cfg::config::network
    24.5-//!
    24.6-//! Network configuration primitives
    24.7-use serde::{Deserialize, Serialize};
    24.8-use std::{fmt, net::SocketAddr};
    24.9-
   24.10-/// Network configuration
   24.11-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone)]
   24.12-pub struct NetworkConfig {
   24.13-  /// a socket to bind
   24.14-  pub socket: SocketAddr,
   24.15-  /// a proxy to forward packets from
   24.16-  pub proxy: Option<SocketAddr>,
   24.17-  /// tunnel to use
   24.18-  pub tunnel: Option<String>,
   24.19-  /// network engine to attach
   24.20-  pub engine: EngineType,
   24.21-  /// peers to register AOT
   24.22-  pub peers: Option<Vec<SocketAddr>>,
   24.23-}
   24.24-
   24.25-impl Default for NetworkConfig {
   24.26-  fn default() -> Self {
   24.27-    NetworkConfig {
   24.28-      socket: "127.0.0.1:0".parse().unwrap(),
   24.29-      proxy: None,
   24.30-      tunnel: None,
   24.31-      engine: EngineType::default(),
   24.32-      peers: None,
   24.33-    }
   24.34-  }
   24.35-}
   24.36-
   24.37-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone)]
   24.38-pub enum EngineType {
   24.39-  Quic,
   24.40-  Http,
   24.41-  Dns,
   24.42-  Ssh,
   24.43-  Uds,
   24.44-}
   24.45-
   24.46-impl Default for EngineType {
   24.47-  fn default() -> Self {
   24.48-    Self::Http
   24.49-  }
   24.50-}
   24.51-
   24.52-impl std::fmt::Display for EngineType {
   24.53-  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
   24.54-    match self {
   24.55-      EngineType::Quic => write!(f, "quic"),
   24.56-      EngineType::Http => write!(f, "http"),
   24.57-      EngineType::Dns => write!(f, "dns"),
   24.58-      EngineType::Ssh => write!(f, "ssh"),
   24.59-      EngineType::Uds => write!(f, "uds"),
   24.60-    }
   24.61-  }
   24.62-}
    25.1--- a/src/crates/obj/src/types.rs	Thu Jun 20 22:31:58 2024 -0400
    25.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3@@ -1,70 +0,0 @@
    25.4-//! obj/src/types.rs --- OBJ type descriptions used by our demo
    25.5-use crate::{Deserialize, Objective, Result, Serialize};
    25.6-use std::collections::HashMap;
    25.7-
    25.8-/// APPLICATION TYPES
    25.9-#[derive(Serialize, Deserialize, Default)]
   25.10-pub enum Service {
   25.11-  Weather,
   25.12-  Stocks,
   25.13-  Dynamic(Vec<Service>),
   25.14-  Custom(CustomService),
   25.15-  #[default]
   25.16-  Bench,
   25.17-}
   25.18-
   25.19-impl Objective for Service {}
   25.20-
   25.21-impl From<&str> for Service {
   25.22-  fn from(value: &str) -> Self {
   25.23-    match value {
   25.24-      "weather" => Service::Weather,
   25.25-      "stocks" => Service::Stocks,
   25.26-      "bench" => Service::Bench,
   25.27-      s => {
   25.28-        if s.contains(",") {
   25.29-          let x = s.split(",");
   25.30-          Service::Dynamic(
   25.31-            x.map(|y| Service::Custom(y.into()))
   25.32-              .collect::<Vec<Service>>(),
   25.33-          )
   25.34-        } else {
   25.35-          Service::Custom(s.into())
   25.36-        }
   25.37-      }
   25.38-    }
   25.39-  }
   25.40-}
   25.41-
   25.42-#[derive(Serialize, Deserialize, Default)]
   25.43-pub struct CustomService {
   25.44-  name: String,
   25.45-  registry: HashMap<String, Vec<u8>>,
   25.46-}
   25.47-
   25.48-impl Objective for CustomService {}
   25.49-impl From<CustomService> for Service {
   25.50-  fn from(value: CustomService) -> Self {
   25.51-    Service::Custom(value)
   25.52-  }
   25.53-}
   25.54-impl From<&str> for CustomService {
   25.55-  fn from(value: &str) -> Self {
   25.56-    let name = value.to_owned();
   25.57-    let registry = HashMap::new();
   25.58-    CustomService { name, registry }
   25.59-  }
   25.60-}
   25.61-
   25.62-#[derive(Serialize, Deserialize, Default)]
   25.63-pub struct Complex<X: Objective> {
   25.64-  data: X,
   25.65-  stack: Vec<u8>,
   25.66-  registry: HashMap<String, Vec<u8>>,
   25.67-}
   25.68-
   25.69-impl Objective for Complex<Service> {}
   25.70-
   25.71-pub fn generate_complex() -> Result<Complex<Service>> {
   25.72-  Ok(Complex::<Service>::from_json_str("hi")?)
   25.73-}
    26.1--- a/src/crates/service/Cargo.toml	Thu Jun 20 22:31:58 2024 -0400
    26.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3@@ -1,21 +0,0 @@
    26.4-[package]
    26.5-name = "demo_service"
    26.6-version = "0.1.0"
    26.7-edition = "2021"
    26.8-[lib]
    26.9-path = "lib.rs"
   26.10-[[bin]]
   26.11-name = "demo-service"
   26.12-path = "main.rs"
   26.13-[[test]]
   26.14-name = "tests"
   26.15-path = "tests.rs"
   26.16-
   26.17-[dependencies]
   26.18-obj = { version = "0.1.0", path = "../obj" }
   26.19-tokio = { version = "1.28.2", features = ["full"] }
   26.20-sqlx = { version = "0.6.3", features = ["runtime-tokio-rustls", "any", "postgres"] }
   26.21-axum = { version = "0.6.18" }
   26.22-tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
   26.23-tracing = "0.1.37"
   26.24-
    27.1--- a/src/crates/service/lib.rs	Thu Jun 20 22:31:58 2024 -0400
    27.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3@@ -1,1 +0,0 @@
    27.4-
    28.1--- a/src/crates/service/main.rs	Thu Jun 20 22:31:58 2024 -0400
    28.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3@@ -1,17 +0,0 @@
    28.4-
    28.5-use tokio::net::TcpListener;
    28.6-use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
    28.7-
    28.8-#[tokio::main]
    28.9-async fn main() {
   28.10-  tracing_subscriber::registry()
   28.11-    .with(
   28.12-      tracing_subscriber::EnvFilter::try_from_default_env()
   28.13-        .unwrap_or_else(|_| "demo_service=debug".into()),
   28.14-    )
   28.15-    .with(tracing_subscriber::fmt::layer())
   28.16-    .init();
   28.17-
   28.18-  let listener = TcpListener::bind("127.0.0.1:8888").await.unwrap();
   28.19-  tracing::debug!("listening on {}", listener.local_addr().unwrap());
   28.20-}
    29.1--- a/src/crates/service/tests.rs	Thu Jun 20 22:31:58 2024 -0400
    29.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3@@ -1,1 +0,0 @@
    29.4-
    30.1--- a/src/crates/ui/Cargo.toml	Thu Jun 20 22:31:58 2024 -0400
    30.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3@@ -1,22 +0,0 @@
    30.4-[package]
    30.5-name = "ui"
    30.6-version = "0.1.0"
    30.7-edition = "2021"
    30.8-build = "build.rs"
    30.9-[lib]
   30.10-path = "lib.rs"
   30.11-crate-type = ["rlib","cdylib"]
   30.12-[[bin]]
   30.13-name = "demo-ui"
   30.14-path = "main.rs"
   30.15-[build-dependencies]
   30.16-slint-build = "1.0.2"
   30.17-[dependencies]
   30.18-obj = {version = "0.1.0",path = "../obj"}
   30.19-env_logger = "0.10.0"
   30.20-log = "0.4.17"
   30.21-slint = "1.0.2"
   30.22-[target.'cfg(target_arch = "wasm32")'.dependencies]
   30.23-wasm-bindgen = { version = "0.2" }
   30.24-web-sys = { version = "0.3", features=["console"] }
   30.25-console_error_panic_hook = "0.1.5"
    31.1--- a/src/crates/ui/build.rs	Thu Jun 20 22:31:58 2024 -0400
    31.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3@@ -1,3 +0,0 @@
    31.4-fn main() {
    31.5-  slint_build::compile("ui.slint").unwrap();
    31.6-}
    32.1--- a/src/crates/ui/config.slint	Thu Jun 20 22:31:58 2024 -0400
    32.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3@@ -1,3 +0,0 @@
    32.4-export global UiConfig  {
    32.5-    in property<bool> widgets-disabled: false;
    32.6-}
    32.7\ No newline at end of file
    33.1Binary file src/crates/ui/img/ayo.jpeg has changed
    34.1Binary file src/crates/ui/img/treez.png has changed
    35.1--- a/src/crates/ui/index.html	Thu Jun 20 22:31:58 2024 -0400
    35.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3@@ -1,9 +0,0 @@
    35.4-<html>
    35.5-  <body>
    35.6-    <canvas id="canvas">>/canvas>
    35.7-    <script type="module">
    35.8-      import init from './pkg/ui.js';
    35.9-      init();
   35.10-    </script>
   35.11-  </body>
   35.12-</html>
    36.1--- a/src/crates/ui/lib.rs	Thu Jun 20 22:31:58 2024 -0400
    36.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3@@ -1,77 +0,0 @@
    36.4-#![deny(unsafe_code)]
    36.5-
    36.6-#[cfg(target_arch = "wasm32")]
    36.7-use wasm_bindgen::prelude::*;
    36.8-
    36.9-slint::include_modules!();
   36.10-
   36.11-use std::rc::Rc;
   36.12-
   36.13-use slint::{Model, StandardListViewItem, VecModel};
   36.14-
   36.15-#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
   36.16-pub fn run() {
   36.17-  // This provides better error messages in debug mode.
   36.18-  // It's disabled in release mode so it doesn't bloat up the file size.
   36.19-  #[cfg(all(debug_assertions, target_arch = "wasm32"))]
   36.20-  console_error_panic_hook::set_once();
   36.21-
   36.22-  let app = App::new().unwrap();
   36.23-
   36.24-  let row_data: Rc<VecModel<slint::ModelRc<StandardListViewItem>>> = Rc::new(VecModel::default());
   36.25-
   36.26-  for r in 1..101 {
   36.27-    let items = Rc::new(VecModel::default());
   36.28-
   36.29-    for c in 1..5 {
   36.30-      items.push(slint::format!("Item {r}.{c}").into());
   36.31-    }
   36.32-
   36.33-    row_data.push(items.into());
   36.34-  }
   36.35-
   36.36-  app
   36.37-    .global::<TableViewPageAdapter>()
   36.38-    .set_row_data(row_data.clone().into());
   36.39-
   36.40-  app.global::<TableViewPageAdapter>().on_sort_ascending({
   36.41-    let app_weak = app.as_weak();
   36.42-    let row_data = row_data.clone();
   36.43-    move |index| {
   36.44-      let row_data = row_data.clone();
   36.45-
   36.46-      let sort_model = Rc::new(row_data.sort_by(move |r_a, r_b| {
   36.47-        let c_a = r_a.row_data(index as usize).unwrap();
   36.48-        let c_b = r_b.row_data(index as usize).unwrap();
   36.49-
   36.50-        c_a.text.cmp(&c_b.text)
   36.51-      }));
   36.52-
   36.53-      app_weak
   36.54-        .unwrap()
   36.55-        .global::<TableViewPageAdapter>()
   36.56-        .set_row_data(sort_model.into());
   36.57-    }
   36.58-  });
   36.59-
   36.60-  app.global::<TableViewPageAdapter>().on_sort_descending({
   36.61-    let app_weak = app.as_weak();
   36.62-    move |index| {
   36.63-      let row_data = row_data.clone();
   36.64-
   36.65-      let sort_model = Rc::new(row_data.sort_by(move |r_a, r_b| {
   36.66-        let c_a = r_a.row_data(index as usize).unwrap();
   36.67-        let c_b = r_b.row_data(index as usize).unwrap();
   36.68-
   36.69-        c_b.text.cmp(&c_a.text)
   36.70-      }));
   36.71-
   36.72-      app_weak
   36.73-        .unwrap()
   36.74-        .global::<TableViewPageAdapter>()
   36.75-        .set_row_data(sort_model.into());
   36.76-    }
   36.77-  });
   36.78-
   36.79-  app.run().unwrap();
   36.80-}
    37.1--- a/src/crates/ui/main.rs	Thu Jun 20 22:31:58 2024 -0400
    37.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3@@ -1,4 +0,0 @@
    37.4-use ui::run;
    37.5-fn main() {
    37.6-  run();
    37.7-}
    38.1--- a/src/crates/ui/pages.slint	Thu Jun 20 22:31:58 2024 -0400
    38.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3@@ -1,7 +0,0 @@
    38.4-import { AboutPage } from "pages/about.slint";
    38.5-import { ControlsPage } from "pages/controls.slint";
    38.6-import { ListViewPage } from "pages/list_view.slint";
    38.7-import { TableViewPage, TableViewPageAdapter } from "pages/table_view.slint";
    38.8-import { TextEditPage } from "pages/text_edit.slint";
    38.9-
   38.10-export { AboutPage, ControlsPage, ListViewPage, TextEditPage, TableViewPage, TableViewPageAdapter }
   38.11\ No newline at end of file
    39.1--- a/src/crates/ui/pages/about.slint	Thu Jun 20 22:31:58 2024 -0400
    39.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.3@@ -1,10 +0,0 @@
    39.4-import { AboutSlint } from "std-widgets.slint";
    39.5-import { UiConfig } from "../config.slint";
    39.6-import { Page } from "page.slint";
    39.7-
    39.8-export component AboutPage inherits Page {
    39.9-    title: "About";
   39.10-    description: "Are you curious now? Check out the docs and gettings start from the Github repository and the website https://slint-ui.com and try it yourself.";
   39.11-
   39.12-    AboutSlint {}
   39.13-}
   39.14\ No newline at end of file
    40.1--- a/src/crates/ui/pages/controls.slint	Thu Jun 20 22:31:58 2024 -0400
    40.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.3@@ -1,145 +0,0 @@
    40.4-import { Button, GroupBox, SpinBox, ComboBox, CheckBox, LineEdit, TabWidget, VerticalBox, HorizontalBox,
    40.5-    Slider, SpinBox } from "std-widgets.slint";
    40.6-import { UiConfig } from "../config.slint";
    40.7-import { Page } from "page.slint";
    40.8-
    40.9-export component ControlsPage inherits Page {
   40.10-    title: "Controls";
   40.11-    description: "This page gives an overview of the default widget set provided by Slint. The widgets are available in different styles native, fluent-(dark/light) and material-(dark/light). The widgets can be imported from \"std-widgets.slint\".";
   40.12-
   40.13-    GroupBox {
   40.14-        vertical-stretch: 0;
   40.15-        title: "Buttons";
   40.16-
   40.17-        HorizontalLayout {
   40.18-            spacing: 8px;
   40.19-            alignment: start;
   40.20-
   40.21-            Button {
   40.22-                text: "Regular Button";
   40.23-                enabled: !UiConfig.widgets-disabled;
   40.24-            }
   40.25-
   40.26-            Button {
   40.27-                text: "Button with Icon";
   40.28-                icon: @image-url("../img/treez.png");
   40.29-                enabled: !UiConfig.widgets-disabled;
   40.30-            }
   40.31-
   40.32-            Button {
   40.33-                checkable: true;
   40.34-                text: self.checked ? "ON" : "OFF";
   40.35-                enabled: !UiConfig.widgets-disabled;
   40.36-            }
   40.37-        }
   40.38-    }
   40.39-
   40.40-    GroupBox {
   40.41-        title: "CheckBox - SpinBox - ComboBox";
   40.42-        vertical-stretch: 0;
   40.43-
   40.44-        HorizontalBox {
   40.45-            alignment: start;
   40.46-            checkbox := CheckBox {
   40.47-                text: checkbox.checked ? "(checked)" : "(unchecked)";
   40.48-                checked: true;
   40.49-                enabled: !UiConfig.widgets-disabled;
   40.50-            }
   40.51-
   40.52-
   40.53-        SpinBox {
   40.54-            vertical-stretch: 0;
   40.55-            value: 42;
   40.56-            enabled: !UiConfig.widgets-disabled;
   40.57-        }
   40.58-
   40.59-            ComboBox {
   40.60-                model: ["Select Something", "From this", "Combobox"];
   40.61-                enabled: !UiConfig.widgets-disabled;
   40.62-            }
   40.63-        }
   40.64-
   40.65-
   40.66-    }
   40.67-
   40.68-    GroupBox {
   40.69-        title: "LineEdit";
   40.70-        vertical-stretch: 0;
   40.71-
   40.72-        LineEdit {
   40.73-            placeholder-text: "Enter some text";
   40.74-            enabled: !UiConfig.widgets-disabled;
   40.75-        }
   40.76-    }
   40.77-
   40.78-    GroupBox {
   40.79-        title: "Slider";
   40.80-        vertical-stretch: 0;
   40.81-
   40.82-        Slider {
   40.83-            min-width: 160px;
   40.84-            minimum: -100;
   40.85-            maximum: 100;
   40.86-            value: 42;
   40.87-            enabled: !UiConfig.widgets-disabled;
   40.88-        }
   40.89-    }
   40.90-
   40.91-    GroupBox {
   40.92-        title: "TabWidget";
   40.93-
   40.94-        TabWidget {
   40.95-            Tab {
   40.96-                title: "Tab 1";
   40.97-
   40.98-                VerticalBox {
   40.99-                    alignment: start;
  40.100-
  40.101-                    GroupBox {
  40.102-                        title: "Content of tab 1";
  40.103-
  40.104-                        HorizontalBox {
  40.105-                            alignment: start;
  40.106-
  40.107-                            Button {
  40.108-                                text: "Click me";
  40.109-                                enabled: !UiConfig.widgets-disabled;
  40.110-                            }
  40.111-                        }
  40.112-                    }
  40.113-                }
  40.114-            }
  40.115-
  40.116-            Tab {
  40.117-                title: "Tab 2";
  40.118-
  40.119-                VerticalBox {
  40.120-                    alignment: start;
  40.121-
  40.122-                    GroupBox {
  40.123-                        title: "Content of tab 2";
  40.124-
  40.125-                        VerticalBox {
  40.126-                            alignment: start;
  40.127-
  40.128-                            CheckBox {
  40.129-                                text: "Check me";
  40.130-                                enabled: !UiConfig.widgets-disabled;
  40.131-                            }
  40.132-                        }
  40.133-                    }
  40.134-                }
  40.135-            }
  40.136-
  40.137-            Tab {
  40.138-                title: "Tab 3";
  40.139-
  40.140-                VerticalBox {
  40.141-                    Text {
  40.142-                        text: "Content of tab 3";
  40.143-                    }
  40.144-                }
  40.145-            }
  40.146-        }
  40.147-    }
  40.148-}
  40.149\ No newline at end of file
    41.1--- a/src/crates/ui/pages/list_view.slint	Thu Jun 20 22:31:58 2024 -0400
    41.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.3@@ -1,45 +0,0 @@
    41.4-import { HorizontalBox, VerticalBox, ListView, StandardListView, GroupBox } from "std-widgets.slint";
    41.5-import { UiConfig } from "../config.slint";
    41.6-import { Page } from "page.slint";
    41.7-
    41.8-export component ListViewPage inherits Page {
    41.9-    title: "ListView";
   41.10-    description: "ListViews can be used to display a list of elements. The StandardListBox is like the default ListView just with a default text based definition of the visual items. Both can be imported from \"std-widgets.slint\"";
   41.11-
   41.12-    HorizontalBox {
   41.13-        vertical-stretch: 1;
   41.14-        GroupBox {
   41.15-            title: "ListView";
   41.16-
   41.17-            ListView {
   41.18-                vertical-stretch: 0;
   41.19-                for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] : HorizontalBox {
   41.20-                   Image {
   41.21-                        width: 24px;
   41.22-                        source: @image-url("../img/ayo.jpeg");
   41.23-                   }
   41.24-                   Text {
   41.25-                        text: "Item " + i;
   41.26-                   }
   41.27-                }
   41.28-            }
   41.29-        }
   41.30-
   41.31-        GroupBox {
   41.32-            title: "StandardListView";
   41.33-            vertical-stretch: 0;
   41.34-
   41.35-            StandardListView {
   41.36-                model: [
   41.37-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.38-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.39-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.40-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.41-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.42-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.43-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   41.44-                ];
   41.45-            }
   41.46-        }
   41.47-    }
   41.48-}
   41.49\ No newline at end of file
    42.1--- a/src/crates/ui/pages/page.slint	Thu Jun 20 22:31:58 2024 -0400
    42.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.3@@ -1,27 +0,0 @@
    42.4-import { CheckBox, GridBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
    42.5-
    42.6-import { UiConfig } from "../config.slint";
    42.7-
    42.8-export component Page inherits VerticalBox {
    42.9-    in property<string> title: "title";
   42.10-    in property<string> description: "description";
   42.11-
   42.12-    HorizontalLayout {
   42.13-        height: 24px;
   42.14-        Text {
   42.15-            font-size: 20px;
   42.16-            text <=> root.title;
   42.17-        }
   42.18-
   42.19-        // Spacer
   42.20-        Rectangle {}
   42.21-
   42.22-        CheckBox {
   42.23-            horizontal-stretch: 0;
   42.24-            text: "Disable widgets";
   42.25-            checked <=> UiConfig.widgets-disabled;
   42.26-        }
   42.27-    }
   42.28-
   42.29-    @children
   42.30-}
   42.31\ No newline at end of file
    43.1--- a/src/crates/ui/pages/table_view.slint	Thu Jun 20 22:31:58 2024 -0400
    43.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3@@ -1,48 +0,0 @@
    43.4-import { HorizontalBox, VerticalBox, StandardTableView, GroupBox} from "std-widgets.slint";
    43.5-import { UiConfig } from "../config.slint";
    43.6-import { Page } from "page.slint";
    43.7-
    43.8-export global TableViewPageAdapter  {
    43.9-    callback sort_ascending(int);
   43.10-    callback sort_descending(int);
   43.11-    in property <[[StandardListViewItem]]> row_data: [
   43.12-        [ { text: "Item 1.1" }, { text: "Item 1.2" }, { text: "Item 1.3" }, { text: "Item 1.4" }, ],
   43.13-        [ { text: "Item 2.1" }, { text: "Item 2.2" }, { text: "Item 2.3" }, { text: "Item 2.4" }, ],
   43.14-        [ { text: "Item 3.1" }, { text: "Item 3.2" }, { text: "Item 3.3" }, { text: "Item 3.4" }, ],
   43.15-        [ { text: "Item 4.1" }, { text: "Item 4.2" }, { text: "Item 4.3" }, { text: "Item 4.4" }, ],
   43.16-        [ { text: "Item 5.1" }, { text: "Item 5.2" }, { text: "Item 5.3" }, { text: "Item 5.4" }, ],
   43.17-        [ { text: "Item 6.1" }, { text: "Item 6.2" }, { text: "Item 6.3" }, { text: "Item 6.4" }, ],
   43.18-    ];
   43.19-}
   43.20-
   43.21-export component TableViewPage inherits Page {
   43.22-    title: "TableView";
   43.23-    description: "StandardTableView can be used to display a list of text elements in columns and rows. It can be imported from \"std-widgets.slint\"";
   43.24-
   43.25-    HorizontalBox {
   43.26-        vertical-stretch: 1;
   43.27-
   43.28-        GroupBox {
   43.29-            title: "StandardTableView";
   43.30-            vertical-stretch: 0;
   43.31-
   43.32-            StandardTableView {
   43.33-                sort-ascending(index) => {
   43.34-                    TableViewPageAdapter.sort_ascending(index);
   43.35-                }
   43.36-
   43.37-                sort-descending(index) => {
   43.38-                    TableViewPageAdapter.sort-descending(index);
   43.39-                }
   43.40-
   43.41-                columns: [
   43.42-                    { title: "Header 1" },
   43.43-                    { title: "Header 2" },
   43.44-                    { title: "Header 3" },
   43.45-                    { title: "Header 4" },
   43.46-                ];
   43.47-                rows: TableViewPageAdapter.row_data;
   43.48-            }
   43.49-        }
   43.50-    }
   43.51-}
   43.52\ No newline at end of file
    44.1--- a/src/crates/ui/pages/text_edit.slint	Thu Jun 20 22:31:58 2024 -0400
    44.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.3@@ -1,32 +0,0 @@
    44.4-import { HorizontalBox, GroupBox, TextEdit } from "std-widgets.slint";
    44.5-import { UiConfig } from "../config.slint";
    44.6-import { Page } from "page.slint";
    44.7-
    44.8-export component TextEditPage inherits Page {
    44.9-    title: "TextEdit";
   44.10-    description: "Similar to LineEdit, but can be used to enter several lines of text. The widget can be imported from \"std-widgets.slint\".";
   44.11-
   44.12-    HorizontalBox {
   44.13-        GroupBox {
   44.14-            vertical-stretch: 0;
   44.15-            title: "Word-Wrap";
   44.16-            te1 := TextEdit {
   44.17-                min-width: 200px;
   44.18-                text: "This is our TextEdit widget, which allows for editing text that spans over multiple paragraphs.\nFor example this line starts in a new paragraph.\n\nWhen the amount of lines - due to wrapping and number of paragraphs - exceeds the available vertical height, a vertical scrollbar is shown that allows scrolling.\nYou may want to enter a bit of text here then in order to make them visible.";
   44.19-                wrap: word-wrap;
   44.20-                enabled: !UiConfig.widgets-disabled;
   44.21-            }
   44.22-        }
   44.23-
   44.24-        GroupBox {
   44.25-            title: "No-Wrap";
   44.26-            vertical-stretch: 0;
   44.27-            te2 := TextEdit {
   44.28-                min-width: 200px;
   44.29-                text <=> te1.text;
   44.30-                wrap: no-wrap;
   44.31-                enabled: !UiConfig.widgets-disabled;
   44.32-            }
   44.33-        }
   44.34-    }
   44.35-}
   44.36\ No newline at end of file
    45.1--- a/src/crates/ui/sidebar.slint	Thu Jun 20 22:31:58 2024 -0400
    45.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.3@@ -1,127 +0,0 @@
    45.4-import { StyleMetrics } from "std-widgets.slint";
    45.5-
    45.6-component SideBarItem inherits Rectangle {
    45.7-    callback clicked <=> touch.clicked;
    45.8-    in-out property<string> text <=> label.text;
    45.9-    in property<bool> selected;
   45.10-    in property<bool> has-focus;
   45.11-
   45.12-    min-height: l.preferred-height;
   45.13-
   45.14-    state := Rectangle {
   45.15-        opacity: 0;
   45.16-        background: StyleMetrics.window-background;
   45.17-
   45.18-        animate opacity { duration: 150ms; }
   45.19-    }
   45.20-
   45.21-    l := HorizontalLayout {
   45.22-        y: (parent.height - self.height) / 2;
   45.23-        padding: StyleMetrics.layout-padding;
   45.24-        spacing: 0px;
   45.25-
   45.26-        label := Text {
   45.27-            color: StyleMetrics.default-text-color;
   45.28-            vertical-alignment: center;
   45.29-         }
   45.30-    }
   45.31-
   45.32-    touch := TouchArea {
   45.33-        width: 100%;
   45.34-        height: 100%;
   45.35-    }
   45.36-
   45.37-    states [
   45.38-        pressed when touch.pressed : {
   45.39-            state.opacity: 0.8;
   45.40-        }
   45.41-        hover when touch.has-hover : {
   45.42-            state.opacity: 0.6;
   45.43-        }
   45.44-        selected when root.selected : {
   45.45-            state.opacity: 1;
   45.46-        }
   45.47-        focused when root.has-focus : {
   45.48-            state.opacity: 0.8;
   45.49-        }
   45.50-    ]
   45.51-}
   45.52-
   45.53-export component SideBar inherits Rectangle {
   45.54-    in property<[string]> model: [];
   45.55-    out property<int> current-item: 0;
   45.56-    in property<string> title <=> label.text;
   45.57-    out property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
   45.58-    width: 180px;
   45.59-
   45.60-    forward-focus: fs;
   45.61-
   45.62-    accessible-role: tab;
   45.63-    accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
   45.64-
   45.65-    Rectangle {
   45.66-        background: StyleMetrics.window-background.darker(0.2);
   45.67-
   45.68-        fs := FocusScope {
   45.69-            x:0;
   45.70-            width: 0px; // Do not react on clicks
   45.71-            property<int> focused-tab: 0;
   45.72-
   45.73-            key-pressed(event) => {
   45.74-                if (event.text == "\n") {
   45.75-                     root.current-item = root.current-focused;
   45.76-                     return accept;
   45.77-                }
   45.78-                if (event.text == Key.UpArrow) {
   45.79-                     self.focused-tab = Math.max(self.focused-tab - 1,  0);
   45.80-                     return accept;
   45.81-                }
   45.82-                if (event.text == Key.DownArrow) {
   45.83-                     self.focused-tab = Math.min(self.focused-tab + 1, root.model.length - 1);
   45.84-                     return accept;
   45.85-                }
   45.86-                return reject;
   45.87-            }
   45.88-
   45.89-            key-released(event) => {
   45.90-                if (event.text == " ") {
   45.91-                     root.current-item = root.current-focused;
   45.92-                     return accept;
   45.93-                }
   45.94-                return reject;
   45.95-            }
   45.96-        }
   45.97-    }
   45.98-
   45.99-    VerticalLayout {
  45.100-        padding-top: StyleMetrics.layout-padding;
  45.101-        padding-bottom: StyleMetrics.layout-padding;
  45.102-        spacing: StyleMetrics.layout-spacing;
  45.103-        alignment: start;
  45.104-
  45.105-        label := Text {
  45.106-            font-size: 16px;
  45.107-            horizontal-alignment: center;
  45.108-        }
  45.109-
  45.110-        navigation := VerticalLayout {
  45.111-            alignment: start;
  45.112-            vertical-stretch: 0;
  45.113-            for item[index] in root.model : SideBarItem {
  45.114-                has-focus: index == root.current-focused;
  45.115-                text: item;
  45.116-                selected: index == root.current-item;
  45.117-                clicked => { root.current-item = index; }
  45.118-            }
  45.119-        }
  45.120-
  45.121-        VerticalLayout {
  45.122-            bottom := VerticalLayout {
  45.123-                padding-left: StyleMetrics.layout-padding;
  45.124-                padding-right: StyleMetrics.layout-padding;
  45.125-
  45.126-                @children
  45.127-             }
  45.128-        }
  45.129-    }
  45.130-}
  45.131\ No newline at end of file
    46.1--- a/src/crates/ui/ui.slint	Thu Jun 20 22:31:58 2024 -0400
    46.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3@@ -1,20 +0,0 @@
    46.4-import {CheckBox, StandardListView, StyleMetrics} from "std-widgets.slint";
    46.5-import {AboutPage, ControlsPage, ListViewPage, TableViewPage, TableViewPageAdapter, TextEditPage} from "pages.slint";
    46.6-import {UiConfig} from "config.slint";
    46.7-import {SideBar} from "sidebar.slint";
    46.8-export {TableViewPageAdapter}
    46.9-export component App inherits Window {
   46.10-  title: "Demo";
   46.11-  icon: @image-url("img/treez.png");
   46.12-  HorizontalLayout {
   46.13-    side-bar := SideBar {
   46.14-      title: "Demo";
   46.15-      model: ["Controls", "ListView", "TableView", "TextEdit", "About"];
   46.16-    }
   46.17-    if(side-bar.current-item == 0) : ControlsPage {}
   46.18-    if(side-bar.current-item == 1) : ListViewPage {}
   46.19-    if(side-bar.current-item == 2) : TableViewPage {}
   46.20-    if(side-bar.current-item == 3) : TextEditPage {}
   46.21-    if(side-bar.current-item == 4) : AboutPage {}
   46.22-  }
   46.23-}
   46.24\ No newline at end of file
    47.1--- a/src/db/db.lisp	Thu Jun 20 22:31:58 2024 -0400
    47.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3@@ -1,1 +0,0 @@
    47.4-(in-package :demo-db)
    48.1--- a/src/package.lisp	Thu Jun 20 22:31:58 2024 -0400
    48.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3@@ -1,36 +0,0 @@
    48.4-;; demo packages.lisp
    48.5-
    48.6-(defpackage :demo-core
    48.7-  (:use :cl))
    48.8-
    48.9-(defpackage :demo-utils
   48.10-  (:use :demo-core)
   48.11-  (:export
   48.12-   #:source-dir
   48.13-   #:random-id
   48.14-   #:scan-dir
   48.15-   #:*cargo-target*
   48.16-   #:*rs-macros*
   48.17-   #:rs-defmacro
   48.18-   #:rs-macroexpand-1
   48.19-   #:rs-macroexpand))
   48.20-
   48.21-(defpackage :demo-db
   48.22-  (:use :demo-core))
   48.23-
   48.24-(defpackage :demo-ui
   48.25-  (:use :demo-core)
   48.26-  (:export
   48.27-   #:on-new-window
   48.28-   #:start-ui))
   48.29-
   48.30-(defpackage :demo
   48.31-  (:use #:cl #:demo-core #:demo-utils #:demo-db #:demo-ui)
   48.32-  (:local-nicknames
   48.33-   (#:bt #:bordeaux-threads)))
   48.34-
   48.35-(defpackage :demo-cli
   48.36-  (:use :demo :clingon))
   48.37-
   48.38-(defpackage :demo-user
   48.39-  (:use :demo))
    49.1--- a/src/tests/clients/cli.lisp	Thu Jun 20 22:31:58 2024 -0400
    49.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3@@ -1,7 +0,0 @@
    49.4-(in-package #:demo-tests)
    49.5-
    49.6-(def-suite* :demo.cli
    49.7-  :in :demo)
    49.8-
    49.9-(test cli.args
   49.10-      (is (= 2 2)))
    50.1--- a/src/tests/clients/web.lisp	Thu Jun 20 22:31:58 2024 -0400
    50.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3@@ -1,7 +0,0 @@
    50.4-(in-package #:demo-tests)
    50.5-
    50.6-(def-suite* :demo.web
    50.7-  :in :demo)
    50.8-
    50.9-(test web.index
   50.10-      (is (= 2 2)))
    51.1--- a/src/tests/package.lisp	Thu Jun 20 22:31:58 2024 -0400
    51.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3@@ -1,11 +0,0 @@
    51.4-(defpackage #:demo-tests
    51.5-  (:use #:demo #:fiveam)
    51.6-  (:shadowing-import-from #:fiveam #:test)
    51.7-  (:export #:run-tests))
    51.8-
    51.9-(in-package #:demo-tests)
   51.10-
   51.11-(def-suite :demo)
   51.12-
   51.13-(defun run-tests ()
   51.14-  (run! :demo))
    53.1--- a/src/tests/utils.lisp	Thu Jun 20 22:31:58 2024 -0400
    53.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.3@@ -1,46 +0,0 @@
    53.4-(in-package #:demo-tests)
    53.5-
    53.6-(def-suite* :demo.utils
    53.7-  :in :demo)
    53.8-
    53.9-(defun gen-word ()
   53.10-  (gen-one-element "lorem" "ipsum"))
   53.11-
   53.12-(defun gen-text-element ()
   53.13-  (let ((word (gen-word)))
   53.14-    (lambda ()
   53.15-      (case (random 10)
   53.16-        (9 #\Newline)
   53.17-        (t (funcall word))))))
   53.18-
   53.19-(defun gen-text (&key (length (gen-integer :min 1 :max 20))
   53.20-                      (element (gen-text-element)))
   53.21-  (let ((elements (gen-list :length length :elements element)))
   53.22-    (lambda ()
   53.23-      (with-output-to-string (stream)
   53.24-        (loop for previous = nil then element
   53.25-              for element in (funcall elements)
   53.26-              do (cond ((and previous (not (eql previous #\Newline)) (not (eql element #\Newline)))
   53.27-                        (write-char #\Space stream)
   53.28-                        (write-string element stream))
   53.29-                       (t ; (and (eql previous #\Newline) (not (eql element #\Newline)))
   53.30-                        (princ element stream))))))))
   53.31-
   53.32-(defun gen-offset (&key (integer (gen-integer :min -10 :max 10)))
   53.33-  (lambda ()
   53.34-    (case (random 10)
   53.35-      ((8 9 10) nil)
   53.36-      (t        (funcall integer)))))
   53.37-
   53.38-(defun gen-margin (&key (integer (gen-integer :min 1 :max 10)))
   53.39-  (lambda ()
   53.40-    (case (random 10)
   53.41-      ((8 9 10) nil)
   53.42-      (t        (funcall integer)))))
   53.43-
   53.44-(defun gen-count (&key (integer (gen-integer :min 1 :max 10)))
   53.45-  (lambda ()
   53.46-    (case (random 10)
   53.47-      ((8 9 10) nil)
   53.48-      (t        (funcall integer)))))
   53.49-
    54.1--- a/src/ui/ui.lisp	Thu Jun 20 22:31:58 2024 -0400
    54.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3@@ -1,43 +0,0 @@
    54.4-(in-package :demo-ui)
    54.5-
    54.6-(defparameter ui-server-port 8080)
    54.7-(defparameter ui-server-host "0.0.0.0")
    54.8-
    54.9-(defclass ui-element (clog-element) ()
   54.10-  (:documentation "UI Element Object."))
   54.11-
   54.12-(defgeneric create-ui-element (obj &key hidden class id mode)
   54.13-  (:documentation "Create a new ui-element as a child of OBJ."))
   54.14-(defmethod create-ui-element ((obj clog:clog-obj)
   54.15-			      &key (class nil)
   54.16-				(hidden nil)
   54.17-				(id nil)
   54.18-				(mode 'auto))
   54.19-  (let ((new (clog:create-div obj
   54.20-			      :class class
   54.21-			      :hidden hidden
   54.22-			      :id id
   54.23-			      :mode mode)))
   54.24-    (clog:set-geometry new :width 200 :height 100)
   54.25-    (change-class new 'ui-element)))
   54.26-			      
   54.27-(defun on-new-window (body)
   54.28-  "Handle new window event."
   54.29-  (clog:debug-mode body)
   54.30-  (let ((elt (clog:create-child body "<h1>foobar</h1>")))
   54.31-    (clog:set-on-click
   54.32-     elt
   54.33-     (lambda (o)
   54.34-       (setf (clog:color elt) "green")))))
   54.35-
   54.36-(defun start-ui ()
   54.37-  "Start the UI."
   54.38-  (clog:initialize #'on-new-window
   54.39-		   :extended-routing t
   54.40-		   :host ui-server-host
   54.41-		   :port ui-server-port)
   54.42-  (clog:open-browser))
   54.43-
   54.44-(defun stop-ui ()
   54.45-  "Stop the UI."
   54.46-  (clog:shutdown))
    55.1--- a/src/utils/rs.lisp	Thu Jun 20 22:31:58 2024 -0400
    55.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3@@ -1,78 +0,0 @@
    55.4-;;; RUST DSL
    55.5-
    55.6-;; So basically, this was born out of personal frustration with how
    55.7-;; cbindgen and Rust macros work (they don't). Rust macros in general
    55.8-;; are something of a pain in my opinion, so I thought why not just
    55.9-;; generate Rust code from Lisp instead?
   55.10-
   55.11-(in-package :demo-utils)
   55.12-
   55.13-(defvar *cargo-target* #p"/Users/ellis/dev/otom8/demo/target/")
   55.14-(defvar *rs-macros* nil)
   55.15-
   55.16-;; TODO gensyms
   55.17-(defmacro rs-defmacro (name args &body body)
   55.18-  "Define a macro which can be used within the body of a 'with-rs' form."
   55.19-  `(prog1
   55.20-       (defmacro ,name ,@(mapcar #`(,a1) args) ,@body)
   55.21-     (push ',name *rs-macros*)))
   55.22-
   55.23-(defun rs-mod-form (crate &optional mods pub)
   55.24-  "Generate a basic mod form (CRATE . [MODS] [PUB])"
   55.25-    `(,crate ,mods ,pub))
   55.26-
   55.27-(defmacro with-rs-env (imports &body body)
   55.28-  "Generate an environment for use within a Rust generator macro."
   55.29-  `(let ((imports ,(mapcar #'rs-mod-form imports)))
   55.30-     (format nil "~A~&~A" imports ',body)))
   55.31-
   55.32-(defun rs-use (crate &optional mods pub)
   55.33-  "Generate a single Rust use statement."
   55.34-  (concatenate
   55.35-   'string
   55.36-   (if pub "pub " "")
   55.37-   "use " crate "::{"
   55.38-   (cond
   55.39-     ((consp mods)
   55.40-      (reduce
   55.41-       (lambda (x y) (format nil "~A,~A" x y))
   55.42-       mods))
   55.43-     (t mods))
   55.44-   "};"))
   55.45-
   55.46-(defun rs-mod (mod &optional pub)
   55.47-  "Generate a single Rust mod statement."
   55.48-  (concatenate
   55.49-   'string
   55.50-   (if pub "pub " "")
   55.51-   "mod " mod ";"))
   55.52-
   55.53-(defun rs-imports (&rest imports)
   55.54-  "Generate a string of Rust 'use' statements."
   55.55-  (cond
   55.56-    ((consp imports)
   55.57-     (mapcar (lambda (x) (apply #'rs-use (apply #'rs-mod-form x))) imports))
   55.58-    (t imports)))
   55.59-
   55.60-(defmacro rs-extern-c-fn (name args &optional pub unsafe no-mangle &body body)
   55.61-  "Generate a Rust extern 'C' fn."
   55.62-  `(concatenate
   55.63-   'string
   55.64-   ,(when no-mangle (format nil "#[no_mangle]~&"))
   55.65-   ,(when pub "pub ")
   55.66-   ,(when unsafe "unsafe ")
   55.67-   "extern \"C\" fn " ,name "("
   55.68-   ,(cond
   55.69-      ((consp args) (reduce (lambda (x y) (format nil "~A,~A" x y)) args))
   55.70-      (t args))
   55.71-   ")" "{" ,@body "}"))
   55.72-
   55.73-(defun rs-obj-impl (obj)
   55.74-  "Implement Objective for give OBJ."
   55.75-  (format nil "impl Objective for ~A {};" obj))
   55.76-
   55.77-;; (defun rs-macroexpand-1 (form &optional env))
   55.78-
   55.79-;; (defun rs-macroexpand (env &rest body)
   55.80-
   55.81-;;; 
    56.1--- a/src/utils/utils.lisp	Thu Jun 20 22:31:58 2024 -0400
    56.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.3@@ -1,28 +0,0 @@
    56.4-(in-package :demo-utils)
    56.5-
    56.6-(defun mkstr (&rest args)
    56.7-  (with-output-to-string (s)
    56.8-    (dolist (a args) (princ a s))))
    56.9-
   56.10-(defun symb (&rest args)
   56.11-  (values (intern (apply #'mkstr args))))
   56.12-
   56.13-(defun random-id ()
   56.14-  (format NIL "~8,'0x-~8,'0x" (random #xFFFFFFFF) (get-universal-time)))
   56.15-
   56.16-(defun scan-dir (dir filename callback)
   56.17-  (dolist (path (directory (merge-pathnames (merge-pathnames filename "**/") dir)))
   56.18-    (funcall callback path)))
   56.19-
   56.20-(defun sbq-reader (stream sub-char numarg)
   56.21-  "The anaphoric sharp-backquote reader: #`((,a1))"
   56.22-  (declare (ignore sub-char))
   56.23-  (unless numarg (setq numarg 1))
   56.24-  `(lambda ,(loop for i from 1 to numarg
   56.25-		  collect (symb 'a i))
   56.26-     ,(funcall
   56.27-       (get-macro-character #\`) stream nil)))
   56.28-
   56.29-(eval-when (:load-toplevel)
   56.30-  (set-dispatch-macro-character
   56.31-   #\# #\` #'sbq-reader))
    57.1--- a/system-index.txt	Thu Jun 20 22:31:58 2024 -0400
    57.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3@@ -1,3 +0,0 @@
    57.4-demo.asd
    57.5-examples/examples.asd
    57.6-examples/db/xdb/xdb.asd