diff --git a/Cargo.lock b/Cargo.lock
index c83a5b7..5b08863 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -540,6 +540,18 @@ dependencies = [
"arrayvec",
]
+[[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.7.3"
@@ -652,9 +664,13 @@ dependencies = [
"log",
"password-hash",
"rand 0.9.0",
+ "resvg 0.45.0",
"serde",
"serde_json",
"simple_logger",
+ "tiny-skia",
+ "toml",
+ "usvg 0.45.0",
"zeroize",
]
@@ -1057,6 +1073,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "core_maths"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
+dependencies = [
+ "libm",
+]
+
[[package]]
name = "cpufeatures"
version = "0.2.17"
@@ -1132,6 +1157,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
+[[package]]
+name = "data-url"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
+
[[package]]
name = "deranged"
version = "0.4.0"
@@ -1328,6 +1359,7 @@ dependencies = [
"enum-map",
"log",
"mime_guess2",
+ "resvg 0.37.0",
"serde",
]
@@ -1551,6 +1583,35 @@ dependencies = [
"miniz_oxide",
]
+[[package]]
+name = "float-cmp"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+
+[[package]]
+name = "fontconfig-parser"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7"
+dependencies = [
+ "roxmltree 0.20.0",
+]
+
+[[package]]
+name = "fontdb"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905"
+dependencies = [
+ "fontconfig-parser",
+ "log",
+ "memmap2",
+ "slotmap",
+ "tinyvec",
+ "ttf-parser",
+]
+
[[package]]
name = "foreign-types"
version = "0.5.0"
@@ -2140,6 +2201,18 @@ dependencies = [
"quick-error",
]
+[[package]]
+name = "imagesize"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
+
+[[package]]
+name = "imagesize"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285"
+
[[package]]
name = "imgref"
version = "1.11.0"
@@ -2275,6 +2348,25 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
+[[package]]
+name = "kurbo"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b"
+dependencies = [
+ "arrayvec",
+]
+
+[[package]]
+name = "kurbo"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f"
+dependencies = [
+ "arrayvec",
+ "smallvec",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -2323,6 +2415,12 @@ dependencies = [
"windows-targets 0.52.6",
]
+[[package]]
+name = "libm"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
+
[[package]]
name = "libredox"
version = "0.1.3"
@@ -2923,6 +3021,12 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+[[package]]
+name = "pico-args"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
+
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@@ -3257,6 +3361,12 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "rctree"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f"
+
[[package]]
name = "redox_syscall"
version = "0.3.5"
@@ -3321,11 +3431,57 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
+[[package]]
+name = "resvg"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cadccb3d99a9efb8e5e00c16fbb732cbe400db2ec7fc004697ee7d97d86cf1f4"
+dependencies = [
+ "log",
+ "pico-args",
+ "rgb",
+ "svgtypes 0.13.0",
+ "tiny-skia",
+ "usvg 0.37.0",
+]
+
+[[package]]
+name = "resvg"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd43d1c474e9dadf09a8fdf22d713ba668b499b5117b9b9079500224e26b5b29"
+dependencies = [
+ "gif",
+ "image-webp",
+ "log",
+ "pico-args",
+ "rgb",
+ "svgtypes 0.15.3",
+ "tiny-skia",
+ "usvg 0.45.0",
+ "zune-jpeg",
+]
+
[[package]]
name = "rgb"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "roxmltree"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
+
+[[package]]
+name = "roxmltree"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
[[package]]
name = "rustc-hash"
@@ -3379,6 +3535,24 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
+[[package]]
+name = "rustybuzz"
+version = "0.20.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702"
+dependencies = [
+ "bitflags 2.9.0",
+ "bytemuck",
+ "core_maths",
+ "log",
+ "smallvec",
+ "ttf-parser",
+ "unicode-bidi-mirroring",
+ "unicode-ccc",
+ "unicode-properties",
+ "unicode-script",
+]
+
[[package]]
name = "ryu"
version = "1.0.20"
@@ -3524,6 +3698,27 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "simplecss"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c"
+dependencies = [
+ "log",
+]
+
+[[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
+name = "siphasher"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
+
[[package]]
name = "slab"
version = "0.4.9"
@@ -3654,6 +3849,9 @@ name = "strict-num"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
+dependencies = [
+ "float-cmp",
+]
[[package]]
name = "subtle"
@@ -3661,6 +3859,26 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+[[package]]
+name = "svgtypes"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70"
+dependencies = [
+ "kurbo 0.9.5",
+ "siphasher 0.3.11",
+]
+
+[[package]]
+name = "svgtypes"
+version = "0.15.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc"
+dependencies = [
+ "kurbo 0.11.1",
+ "siphasher 1.0.1",
+]
+
[[package]]
name = "syn"
version = "1.0.109"
@@ -3810,6 +4028,7 @@ dependencies = [
"bytemuck",
"cfg-if",
"log",
+ "png",
"tiny-skia-path",
]
@@ -3930,6 +4149,9 @@ name = "ttf-parser"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
+dependencies = [
+ "core_maths",
+]
[[package]]
name = "type-map"
@@ -3963,6 +4185,24 @@ version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
+[[package]]
+name = "unicode-bidi"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
+name = "unicode-bidi-mirroring"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe"
+
+[[package]]
+name = "unicode-ccc"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e"
+
[[package]]
name = "unicode-ident"
version = "1.0.18"
@@ -3978,12 +4218,30 @@ 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-script"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f"
+
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+[[package]]
+name = "unicode-vo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94"
+
[[package]]
name = "unicode-width"
version = "0.1.14"
@@ -4017,6 +4275,77 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "usvg"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b0a51b72ab80ca511d126b77feeeb4fb1e972764653e61feac30adc161a756"
+dependencies = [
+ "base64 0.21.7",
+ "log",
+ "pico-args",
+ "usvg-parser",
+ "usvg-tree",
+ "xmlwriter",
+]
+
+[[package]]
+name = "usvg"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ac8e0e3e4696253dc06167990b3fe9a2668ab66270adf949a464db4088cb354"
+dependencies = [
+ "base64 0.22.1",
+ "data-url",
+ "flate2",
+ "fontdb",
+ "imagesize 0.13.0",
+ "kurbo 0.11.1",
+ "log",
+ "pico-args",
+ "roxmltree 0.20.0",
+ "rustybuzz",
+ "simplecss",
+ "siphasher 1.0.1",
+ "strict-num",
+ "svgtypes 0.15.3",
+ "tiny-skia-path",
+ "unicode-bidi",
+ "unicode-script",
+ "unicode-vo",
+ "xmlwriter",
+]
+
+[[package]]
+name = "usvg-parser"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bd4e3c291f45d152929a31f0f6c819245e2921bfd01e7bd91201a9af39a2bdc"
+dependencies = [
+ "data-url",
+ "flate2",
+ "imagesize 0.12.0",
+ "kurbo 0.9.5",
+ "log",
+ "roxmltree 0.19.0",
+ "simplecss",
+ "siphasher 0.3.11",
+ "svgtypes 0.13.0",
+ "usvg-tree",
+]
+
+[[package]]
+name = "usvg-tree"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ee3d202ebdb97a6215604b8f5b4d6ef9024efd623cf2e373a6416ba976ec7d3"
+dependencies = [
+ "rctree",
+ "strict-num",
+ "svgtypes 0.13.0",
+ "tiny-skia-path",
+]
+
[[package]]
name = "utf16_iter"
version = "1.0.5"
@@ -4888,6 +5217,12 @@ version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4"
+[[package]]
+name = "xmlwriter"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
+
[[package]]
name = "yoke"
version = "0.7.5"
diff --git a/bitvault-ui/Cargo.toml b/bitvault-ui/Cargo.toml
index 9ac6cb4..250a947 100644
--- a/bitvault-ui/Cargo.toml
+++ b/bitvault-ui/Cargo.toml
@@ -22,7 +22,7 @@ getrandom.workspace = true
# egui dependencies
eframe = "0.26.2"
egui = "0.26.2"
-egui_extras = "0.26.2"
+egui_extras = { version = "0.26.2", features = ["svg"] }
egui_plot = "0.26.2"
# Logging
@@ -40,3 +40,7 @@ image = "0.25.5"
# Internal dependencies
bitvault-core = { path = "../bitvault-core" }
+toml = "0.8.20"
+usvg = "0.45.0"
+resvg = "0.45.0"
+tiny-skia = "0.11.4"
diff --git a/bitvault-ui/assets/NotoSans-Regular.ttf b/bitvault-ui/assets/NotoSans-Regular.ttf
new file mode 100644
index 0000000..d552209
Binary files /dev/null and b/bitvault-ui/assets/NotoSans-Regular.ttf differ
diff --git a/bitvault-ui/assets/onboarding1.svg b/bitvault-ui/assets/onboarding1.svg
new file mode 100644
index 0000000..fc043e8
--- /dev/null
+++ b/bitvault-ui/assets/onboarding1.svg
@@ -0,0 +1,40 @@
+
diff --git a/bitvault-ui/assets/onboarding2.svg b/bitvault-ui/assets/onboarding2.svg
new file mode 100644
index 0000000..4ace4b2
--- /dev/null
+++ b/bitvault-ui/assets/onboarding2.svg
@@ -0,0 +1,12 @@
+
diff --git a/bitvault-ui/assets/onboarding3.svg b/bitvault-ui/assets/onboarding3.svg
new file mode 100644
index 0000000..1833cd1
--- /dev/null
+++ b/bitvault-ui/assets/onboarding3.svg
@@ -0,0 +1,12 @@
+
diff --git a/bitvault-ui/assets/telegram.png b/bitvault-ui/assets/telegram.png
new file mode 100644
index 0000000..bc912dd
Binary files /dev/null and b/bitvault-ui/assets/telegram.png differ
diff --git a/bitvault-ui/src/app.rs b/bitvault-ui/src/app.rs
index edae925..c817578 100644
--- a/bitvault-ui/src/app.rs
+++ b/bitvault-ui/src/app.rs
@@ -6,12 +6,13 @@ use std::sync::OnceLock;
use anyhow::Result;
use eframe::{
- egui::{self, Color32, Context, Id, Rect, RichText, Ui},
+ egui::{self, Color32, Context, RichText, Ui},
CreationContext,
};
use serde::{Deserialize, Serialize};
use std::sync::RwLock;
+use crate::config::Settings;
use crate::wallet;
use bitvault_core::crypto;
@@ -41,6 +42,9 @@ pub enum View {
Wallet,
LockScreen,
SplashScreen,
+ OnboardingOne,
+ OnboardingTwo,
+ OnboardingThree,
}
// Define a struct to hold the global state
@@ -58,6 +62,8 @@ pub struct AppState {
pub encrypted_wallet_data: Option, // Encrypted wallet data stored on disk
pub lock_error: Option, // Error message when unlocking fails
pub splash_timer: Option, // Timer for splash screen (in seconds)
+ pub testing_mode: bool, // Flag for testing mode to bypass lock screen
+ pub onboarding_completed: bool, // Flag to track if onboarding has been completed
}
// Create a type alias for a thread-safe, shared reference to the state
@@ -65,17 +71,166 @@ pub type SharedAppState = Arc>;
pub struct BitVaultApp {
state: SharedAppState,
+ settings: Settings,
+}
+
+// Add this helper module for asset management at the top level before BitVaultApp struct
+mod assets {
+ use eframe::egui;
+ use std::path::PathBuf;
+ use std::sync::OnceLock;
+
+ // Base paths to try for asset loading
+ const BASE_PATHS: [&str; 3] = ["bitvault-ui", ".", ".."];
+
+ // Find the correct base path once
+ fn get_base_path() -> &'static PathBuf {
+ static BASE_PATH: OnceLock = OnceLock::new();
+
+ BASE_PATH.get_or_init(|| {
+ for base in BASE_PATHS {
+ let path = PathBuf::from(base);
+ if path.exists() {
+ return path;
+ }
+ }
+ // Default to current directory if nothing found
+ PathBuf::from(".")
+ })
+ }
+
+ // Load a font file
+ pub fn load_font(font_name: &str) -> Option> {
+ let base = get_base_path();
+ let font_path = base.join("assets").join(font_name);
+
+ std::fs::read(&font_path).ok()
+ }
+
+ // Load an image file
+ pub fn load_image(path: &str) -> Option> {
+ let base = get_base_path();
+ let img_path = base.join(path);
+
+ std::fs::read(&img_path).ok()
+ }
+
+ // SVG loading function that works with the existing dependencies
+ pub fn load_svg_as_texture(
+ ctx: &egui::Context,
+ name: &str,
+ path: &str,
+ ) -> Option {
+ let base = get_base_path();
+ let svg_path = base.join(path);
+
+ log::debug!("Loading SVG from: {:?}", svg_path);
+
+ // First read the SVG file
+ let svg_data = std::fs::read_to_string(&svg_path).ok()?;
+
+ // Parse SVG with usvg
+ let opt = usvg::Options {
+ ..Default::default()
+ };
+
+ let tree = usvg::Tree::from_str(&svg_data, &opt).ok()?;
+
+ // Get the size and create a pixmap
+ let size = tree.size();
+
+ // Apply a scale factor to increase resolution (2.0 = double resolution)
+ let scale_factor = 2.0;
+ let scaled_width = (size.width() * scale_factor) as u32;
+ let scaled_height = (size.height() * scale_factor) as u32;
+
+ let pixmap_size = tiny_skia::IntSize::from_wh(scaled_width, scaled_height)?;
+
+ // Create a pixmap (tiny-skia's bitmap for rendering)
+ let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height())?;
+
+ // Render the SVG tree to the pixmap with the scale transform
+ resvg::render(
+ &tree,
+ tiny_skia::Transform::from_scale(scale_factor, scale_factor),
+ &mut pixmap.as_mut(),
+ );
+
+ // Convert to egui texture
+ let image_size = [pixmap_size.width() as _, pixmap_size.height() as _];
+ let image_data = pixmap.data();
+
+ // Create the color image and texture
+ let color_image = egui::ColorImage::from_rgba_unmultiplied(image_size, image_data);
+
+ Some(ctx.load_texture(name, color_image, Default::default()))
+ }
+
+ // Get a texture handle for an image
+ pub fn get_image_texture(
+ ctx: &egui::Context,
+ name: &str,
+ path: &str,
+ ) -> Option {
+ load_image(path).and_then(|image_data| {
+ image::load_from_memory(&image_data).ok().map(|image| {
+ let size = [image.width() as _, image.height() as _];
+ let image_buffer = image.to_rgba8();
+ let pixels = image_buffer.as_flat_samples();
+
+ let color_image = egui::ColorImage::from_rgba_unmultiplied(size, pixels.as_slice());
+ ctx.load_texture(name, color_image, Default::default())
+ })
+ })
+ }
}
impl BitVaultApp {
- pub fn new(_cc: &CreationContext<'_>) -> Self {
+ pub fn new(cc: &CreationContext<'_>) -> Self {
+ // Attempt to configure a font with good Unicode support
+ let mut fonts = egui::FontDefinitions::default();
+
+ // Try to add Noto Sans which has good Unicode character support
+ if let Some(font_data) = assets::load_font("NotoSans-Regular.ttf") {
+ log::info!("Successfully loaded Noto Sans font");
+
+ // Add font data
+ fonts
+ .font_data
+ .insert("noto".to_owned(), egui::FontData::from_owned(font_data));
+
+ // Set as primary font
+ fonts
+ .families
+ .get_mut(&egui::FontFamily::Proportional)
+ .unwrap()
+ .insert(0, "noto".to_owned());
+
+ // Apply the font configuration
+ cc.egui_ctx.set_fonts(fonts);
+ log::info!("Applied custom font configuration");
+ } else {
+ log::warn!("Could not load Noto Sans font - using default fonts");
+ }
+
+ // Check for testing mode environment variable
+ let testing_mode = std::env::var("TESTING").unwrap_or_default() == "1";
+ if testing_mode {
+ log::info!("Running in TESTING mode - lock screen will be bypassed");
+ }
+
+ // Load settings or use defaults
+ let settings = Settings::load();
+
// Create the app with default state
let app = Self {
state: Arc::new(RwLock::new(AppState {
current_view: View::SplashScreen,
splash_timer: Some(1.0), // 1 second splash screen
+ testing_mode,
..Default::default()
})),
+ settings,
};
// Check if a wallet file exists and load it
@@ -187,15 +342,12 @@ impl BitVaultApp {
ui.label("Choose a secure PIN to protect your wallet");
ui.add_space(10.0);
- let mut pin_input = String::new();
- let mut pin_confirm = String::new();
- let mut back_button_clicked = false;
-
- // Read current state values
- if let Ok(state) = self.state.read() {
- pin_input = state.pin_input.clone();
- pin_confirm = state.pin_confirm.clone();
- }
+ // Read current state values once
+ let (mut pin_input, mut pin_confirm) = if let Ok(state) = self.state.read() {
+ (state.pin_input.clone(), state.pin_confirm.clone())
+ } else {
+ (String::new(), String::new())
+ };
// PIN input fields
ui.horizontal(|ui| {
@@ -207,7 +359,7 @@ impl BitVaultApp {
.desired_width(200.0),
);
- // Update state with new input
+ // Update state with new input if changed
if response.changed() {
if let Ok(mut state) = self.state.write() {
state.pin_input = pin_input.clone();
@@ -226,22 +378,12 @@ impl BitVaultApp {
.desired_width(200.0),
);
- // Update state with new input
+ // Update state with new input if changed
if response.changed() {
if let Ok(mut state) = self.state.write() {
state.pin_confirm = pin_confirm.clone();
}
}
-
- // Check for Enter key press
- let enter_pressed =
- response.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
- if enter_pressed {
- // Store the enter key state in memory for use outside this scope
- ui.memory_mut(|mem| {
- mem.data.insert_temp(Id::new("pin_enter_pressed"), true);
- });
- }
});
ui.add_space(20.0);
@@ -249,51 +391,35 @@ impl BitVaultApp {
// Calculate pin_valid based on current values
let pin_valid = !pin_input.is_empty() && pin_input == pin_confirm;
- // Get the enter key state from memory
- let enter_pressed = ui
- .memory(|mem| mem.data.get_temp::(Id::new("pin_enter_pressed")))
- .unwrap_or(false);
-
// Set PIN button
if ui
.add_enabled(pin_valid, egui::Button::new("Set PIN"))
.clicked()
- || (enter_pressed && pin_valid)
+ && pin_valid
{
- log::info!("Set PIN button clicked, PIN is valid: {}", pin_valid);
+ if let Ok(mut state) = self.state.write() {
+ // Store the PIN
+ state.user_pin = Some(pin_input);
+ log::info!("PIN set successfully");
- if pin_valid {
- if let Ok(mut state) = self.state.write() {
- // Store the PIN
- state.user_pin = Some(pin_input.clone());
- log::info!("PIN set successfully");
-
- // Clear the input fields for security
- state.pin_input.clear();
- state.pin_confirm.clear();
-
- // Move to the next step
- if state.wallet_state == WalletState::Creating {
- log::info!("Moving to Seed view for new wallet creation");
- // For creating a new wallet, move to the seed view
- state.current_view = View::Seed;
- } else if state.wallet_state == WalletState::Restoring {
- log::info!("Moving to Seed view for wallet restoration");
- // For restoring, go to the seed view where the user can enter their seed phrase
- state.current_view = View::Seed;
- }
+ // Clear the input fields for security
+ state.pin_input.clear();
+ state.pin_confirm.clear();
+
+ // Move to the next step
+ if state.wallet_state == WalletState::Creating {
+ log::info!("Moving to Seed view for new wallet creation");
+ state.current_view = View::Seed;
+ } else if state.wallet_state == WalletState::Restoring {
+ log::info!("Moving to Seed view for wallet restoration");
+ state.current_view = View::Seed;
}
}
}
- // Back button
+ // Back button with simpler structure
let back_response = ui.button("Go Back");
if back_response.clicked() {
- back_button_clicked = true;
- }
-
- // Handle back button click outside the state read lock
- if back_button_clicked {
if let Ok(mut state) = self.state.write() {
state.current_view = View::Disclaimer;
}
@@ -457,16 +583,14 @@ impl BitVaultApp {
);
// Read state once to get the values we need
- let (original_seed, mut verification_input, mut verification_result) =
- if let Ok(state) = self.state.read() {
- (
- state.seed_phrase.clone().unwrap_or_default(),
- state.verification_input.clone(),
- None,
- )
- } else {
- (String::new(), String::new(), None)
- };
+ let (original_seed, mut verification_input) = if let Ok(state) = self.state.read() {
+ (
+ state.seed_phrase.clone().unwrap_or_default(),
+ state.verification_input.clone(),
+ )
+ } else {
+ (String::new(), String::new())
+ };
ui.add_space(20.0);
@@ -485,10 +609,6 @@ impl BitVaultApp {
}
}
- // Check for Enter key press
- let enter_pressed =
- response.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
-
ui.add_space(20.0);
// Check if the entered text matches the original seed phrase
@@ -505,53 +625,25 @@ impl BitVaultApp {
ui.add_space(10.0);
- let verify_clicked = ui.button("Verify").clicked();
- let back_button = ui.add(egui::Button::new("Go Back"));
- let back_clicked = back_button.clicked();
-
- // Store the back button rect for the icon
- if back_button.rect.width() > 0.0 {
- ui.memory_mut(|mem| {
- mem.data
- .insert_temp(Id::new("back_button"), back_button.rect)
- });
- }
-
- // Handle button clicks outside of any locks
- if verify_clicked || enter_pressed {
- if is_correct {
- // Verification successful - update state once
- if let Ok(mut state) = self.state.write() {
- log::info!("Seed verification successful, moving to wallet view");
- state.current_view = View::Wallet;
- state.wallet_state = WalletState::Unlocked;
- }
- } else {
- // Verification failed
- log::warn!("Seed verification failed - phrases don't match");
- verification_result = Some(false);
+ // Verify button
+ if ui.button("Verify").clicked() && is_correct {
+ if let Ok(mut state) = self.state.write() {
+ log::info!("Seed verification successful, moving to wallet view");
+ state.current_view = View::Wallet;
+ state.wallet_state = WalletState::Unlocked;
}
}
- if back_clicked {
+ // Back button with simpler structure
+ let back_button = ui.button("Go Back");
+ if back_button.clicked() {
if let Ok(mut state) = self.state.write() {
state.current_view = View::Seed;
}
}
- // Show verification result if needed
- if let Some(false) = verification_result {
- ui.add_space(5.0);
- ui.label(
- RichText::new("Verification failed. Please check your recovery phrase.")
- .color(Color32::RED),
- );
- }
-
// Draw back button icon
- if let Some(rect) = ui.memory(|m| m.data.get_temp::(Id::new("back_button"))) {
- crate::icons::draw_caret_left(ui, rect, Color32::WHITE);
- }
+ crate::icons::draw_caret_left(ui, back_button.rect, Color32::WHITE);
});
}
@@ -778,55 +870,32 @@ impl BitVaultApp {
// Center the logo
ui.vertical_centered(|ui| {
- // Center vertically - push down less to make it more centered
- ui.add_space(screen_rect.height() / 4.0);
-
// Use a static texture handle to avoid reloading on every frame
static TEXTURE_ID: OnceLock