From 3f03d145e890af3cdc0c935795b85e9144f63671 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Mon, 27 May 2024 00:20:16 +0300 Subject: [PATCH] ur: scanning and creating qr codes for slatepack messages --- Cargo.lock | 73 +++++++++ Cargo.toml | 1 + src/gui/views/camera.rs | 182 +++++++++++++++++----- src/gui/views/qr.rs | 173 ++++++++++++++------ src/gui/views/types.rs | 30 ++-- src/gui/views/wallets/wallet/content.rs | 2 +- src/gui/views/wallets/wallet/messages.rs | 6 +- src/gui/views/wallets/wallet/transport.rs | 6 +- src/gui/views/wallets/wallet/txs.rs | 8 +- src/wallet/utils.rs | 2 - 10 files changed, 373 insertions(+), 110 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd87566..35084d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1059,6 +1059,21 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +[[package]] +name = "bitcoin-private" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" + +[[package]] +name = "bitcoin_hashes" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +dependencies = [ + "bitcoin-private", +] + [[package]] name = "bitflags" version = "0.9.1" @@ -1800,6 +1815,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.0" @@ -3705,6 +3735,7 @@ dependencies = [ "tor-keymgr", "tor-llcrypto", "tor-rtcompat", + "ur", "url", "wgpu", "winit", @@ -5492,6 +5523,26 @@ dependencies = [ "unicase", ] +[[package]] +name = "minicbor" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7005aaf257a59ff4de471a9d5538ec868a21586534fff7f85dd97d4043a6139" +dependencies = [ + "minicbor-derive", +] + +[[package]] +name = "minicbor-derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1154809406efdb7982841adb6311b3d095b46f78342dd646736122fe6b19e267" +dependencies = [ + "proc-macro2 1.0.81", + "quote 1.0.36", + "syn 1.0.109", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -7102,6 +7153,15 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "range-alloc" version = "0.1.3" @@ -10258,6 +10318,19 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ur" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "010f24a953db5d22d0010969ca3bbf40b3857b89f47c0f7be0da4c2d7ded0760" +dependencies = [ + "bitcoin_hashes", + "crc", + "minicbor", + "phf", + "rand_xoshiro", +] + [[package]] name = "url" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index bce792c..1bbfb5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ tokio = { version = "1.37.0", features = ["full"] } image = "0.25.1" rqrr = "0.7.1" qrcodegen = "1.8.0" +ur = "0.4.1" ## tor arti = { version = "1.2.0", features = ["pt-client", "static"] } diff --git a/src/gui/views/camera.rs b/src/gui/views/camera.rs index bdb9954..9918881 100644 --- a/src/gui/views/camera.rs +++ b/src/gui/views/camera.rs @@ -35,18 +35,26 @@ use crate::wallet::WalletUtils; /// Camera QR code scanner. pub struct CameraContent { /// QR code scanning progress and result. - qr_scan_state: Arc> + qr_scan_state: Arc>, + + /// Uniform Resources URIs collected from QR code scanning. + ur_data: Arc>>>, + + start: i64, } impl Default for CameraContent { fn default() -> Self { Self { qr_scan_state: Arc::new(RwLock::new(QrScanState::default())), + ur_data: Arc::new(RwLock::new(None)), + start: 0, } } } impl CameraContent { + /// Draw camera content. pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { // Draw last image from camera or loader. if let Some(img_data) = cb.camera_image() { @@ -138,8 +146,13 @@ impl CameraContent { r_scan.image_processing } + /// Get UR scanning progress in percents. + fn ur_progress(&self) -> i32 { + 0 + } + /// Parse QR code from provided image data. - fn scan_qr(&self, data: &DynamicImage) { + fn scan_qr(&self, image_data: &DynamicImage) { // Do not scan when another image is processing. if self.image_processing() { return; @@ -149,55 +162,117 @@ impl CameraContent { let mut w_scan = self.qr_scan_state.write(); w_scan.image_processing = true; } - // Launch scanner at separate thread. - let data = data.clone(); + + let image_data = image_data.clone(); let qr_scan_state = self.qr_scan_state.clone(); + let ur_data = self.ur_data.clone(); + + let on_scan = async move { + // Prepare image data. + let img = image_data.to_luma8(); + let mut img: rqrr::PreparedImage + = rqrr::PreparedImage::prepare(img); + // Scan and save results. + let grids = img.detect_grids(); + if let Some(g) = grids.get(0) { + let mut qr_data = vec![]; + if let Ok(_) = g.decode_to(&mut qr_data) { + // Setup scanned data into text. + let text = String::from_utf8(qr_data.clone()).unwrap_or("".to_string()); + // Setup current text. + let cur_text = { + let r_scan = qr_scan_state.read(); + let text = if let Some(res) = r_scan.qr_scan_result.clone() { + res.text() + } else { + "".to_string() + }; + text + }; + // Parse non-empty data if parsed text is different from saved. + if !qr_data.is_empty() && (cur_text.is_empty() || text != cur_text) { + let res = Self::parse_qr_code(qr_data); + match res { + QrScanResult::URPart(uri, index, total) => { + // Setup current UR data. + let mut cur_data = { + let r_data = ur_data.read(); + let mut cur_data = vec!["".to_string(); total]; + if let Some(d) = r_data.clone() { + cur_data = d; + } + cur_data + }; + if !cur_data.contains(&uri) { + // Save part of UR data. + { + cur_data.insert(index, uri); + let mut w_data = ur_data.write(); + *w_data = Some(cur_data.clone()); + } + // Setup UR decoder. + let mut decoder = ur::Decoder::default(); + for m in cur_data { + if !m.is_empty() { + if let Ok(_) = decoder.receive(m.as_str()) { + continue; + } else { + break; + } + } + } + // Check if UR data is complete. + if decoder.complete() { + if let Ok(data) = decoder.message() { + // Parse complete data. + let res = Self::parse_qr_code(data.unwrap_or(vec![])); + // Clean UR data. + let mut w_data = ur_data.write(); + *w_data = None; + // Save scan result. + let mut w_scan = qr_scan_state.write(); + w_scan.qr_scan_result = Some(res); + return; + } + } + } + } + _ => { + // Clean UR data. + let mut w_data = ur_data.write(); + *w_data = None; + // Save scan result. + let mut w_scan = qr_scan_state.write(); + w_scan.qr_scan_result = Some(res); + return; + } + } + } + } + } + // Reset scanning flag to process again. + { + let mut w_scan = qr_scan_state.write(); + w_scan.image_processing = false; + } + }; + + // Launch scanner at separate thread. thread::spawn(move || { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() - .block_on(async { - // Prepare image data. - let img = data.to_luma8(); - let mut img: rqrr::PreparedImage - = rqrr::PreparedImage::prepare(img); - // Scan and save results. - let grids = img.detect_grids(); - if let Some(g) = grids.get(0) { - let mut data = vec![]; - if let Ok(_) = g.decode_to(&mut data) { - let cur_text = { - let r_scan = qr_scan_state.read(); - let text = if let Some(res) = r_scan.qr_scan_result.clone() { - res.value() - } else { - "".to_string() - }; - text - }; - let text = String::from_utf8(data.clone()).unwrap_or("".to_string()); - if !data.is_empty() && (cur_text.is_empty() || text != cur_text) { - let result = Self::parse_scan_result(&data); - let mut w_scan = qr_scan_state.write(); - w_scan.qr_scan_result = Some(result); - return; - } - } - } - // Reset scanning flag to process again. - { - let mut w_scan = qr_scan_state.write(); - w_scan.image_processing = false; - } - }); + .block_on(on_scan); }); } - fn parse_scan_result(data: &Vec) -> QrScanResult { + /// Parse QR code scan result. + fn parse_qr_code(data: Vec) -> QrScanResult { // Check if string starts with Grin address prefix. let text_string = String::from_utf8(data.clone()).unwrap_or("".to_string()); - let text = text_string.as_str(); + println!("data: {}", text_string); + let text = text_string.trim(); if text.starts_with("tgrin") || text.starts_with("grin") { if SlatepackAddress::try_from(text).is_ok() { return QrScanResult::Address(ZeroingString::from(text)); @@ -209,7 +284,25 @@ impl CameraContent { return QrScanResult::Slatepack(ZeroingString::from(text)); } - // Check Compact SeedQR format (https://github.com/SeedSigner/seedsigner/blob/dev/docs/seed_qr/README.md#compactseedqr-specification). + // Check Uniform Resource data. + // https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md + if text.starts_with("ur:bytes/") { + let split = text.split("/").collect::>(); + if let Some(index_total) = split.get(1) { + if let Some((index, total)) = index_total.split_once("-") { + let index = index.parse::(); + let total = total.parse::(); + if index.is_ok() && total.is_ok() { + let index = index.unwrap() - 1; + let total = total.unwrap(); + return QrScanResult::URPart(text_string, index, total); + } + } + } + } + + // Check Compact SeedQR format. + // https://github.com/SeedSigner/seedsigner/blob/dev/docs/seed_qr/README.md#compactseedqr-specification if data.len() <= 32 && 16 <= data.len() && data.len() % 4 == 0 { // Setup words amount. let total_bits = data.len() * 8; @@ -259,7 +352,8 @@ impl CameraContent { } } - // Check Standard SeedQR format (https://github.com/SeedSigner/seedsigner/blob/dev/docs/seed_qr/README.md#standard-seedqr-specification). + // Check Standard SeedQR format. + // https://github.com/SeedSigner/seedsigner/blob/dev/docs/seed_qr/README.md#standard-seedqr-specification let only_numbers = || { for c in text.chars() { if !c.is_numeric() { @@ -316,7 +410,11 @@ impl CameraContent { /// Reset camera content state to default. pub fn clear_state(&mut self) { + // Clear QR code scanning state. let mut w_scan = self.qr_scan_state.write(); *w_scan = QrScanState::default(); + // Clear UR data. + let mut w_data = self.ur_data.write(); + *w_data = None; } } \ No newline at end of file diff --git a/src/gui/views/qr.rs b/src/gui/views/qr.rs index e2f141c..7d85adf 100644 --- a/src/gui/views/qr.rs +++ b/src/gui/views/qr.rs @@ -28,16 +28,27 @@ pub struct QrCodeContent { /// Text to create QR code. pub(crate) text: String, + /// Flag to draw animated QR with Uniform Resources + /// https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md + animated: bool, + /// Index of current image at animation. + animated_index: Option, + /// Time of last image draw. + animation_time: Option, + /// Texture handle to show image when created. texture_handle: Option, /// QR code image creation progress and result. - qr_creation_state: Arc> + qr_creation_state: Arc>, } impl QrCodeContent { - pub fn new(text: String) -> Self { + pub fn new(text: String, animated: bool) -> Self { Self { text, + animated, + animated_index: None, + animation_time: None, texture_handle: None, qr_creation_state: Arc::new(RwLock::new(QrCreationState::default())), } @@ -45,67 +56,141 @@ impl QrCodeContent { /// Draw QR code. pub fn ui(&mut self, ui: &mut egui::Ui, text: String) { - // Get saved QR code image or load new one. - if !self.has_image() { - let space = (ui.available_width() - View::BIG_SPINNER_SIZE) / 2.0; - ui.vertical_centered(|ui| { - ui.add_space(space); - View::big_loading_spinner(ui); - ui.add_space(space); - }); + if self.animated { + // Create animated QR code image if not created. + if !self.has_image() { + let space = (ui.available_width() - View::BIG_SPINNER_SIZE) / 2.0; + ui.vertical_centered(|ui| { + ui.add_space(space); + View::big_loading_spinner(ui); + ui.add_space(space); + }); - // Create image from text if not loading. - self.create_image(text); + // Create multiple vector images from text if not creating. + if !self.creating() { + self.create_svg_list(text); + } + } else { + let svg_list = { + let r_create = self.qr_creation_state.read(); + r_create.svg_list.clone().unwrap() + }; + + // Setup animated index. + let now = chrono::Utc::now().timestamp_millis(); + if now - *self.animation_time.get_or_insert(now) > 100 { + if let Some(i) = self.animated_index { + self.animated_index = Some(i + 1); + } + if *self.animated_index.get_or_insert(0) == svg_list.len() { + self.animated_index = Some(0); + } + self.animation_time = Some(now); + } + + let svg = svg_list[self.animated_index.unwrap_or(0)].clone(); + + // Create images from SVG data. + let size = SizeHint::Size(ui.available_width() as u32, ui.available_width() as u32); + let color_img = load_svg_bytes_with_size(svg.as_slice(), Some(size)).unwrap(); + // Create image texture. + let texture_handle = ui.ctx().load_texture("qr_code", + color_img.clone(), + TextureOptions::default()); + self.texture_handle = Some(texture_handle.clone()); + let img_size = egui::emath::vec2(color_img.width() as f32, + color_img.height() as f32); + let sized_img = SizedTexture::new(texture_handle.id(), img_size); + // Add image to content. + ui.add(egui::Image::from_texture(sized_img) + .max_height(ui.available_width()) + .fit_to_original_size(1.0)); + ui.ctx().request_repaint(); + } } else { - // Create image from SVG data. - let r_create = self.qr_creation_state.read(); - let svg = r_create.svg.as_ref().unwrap(); - let size = SizeHint::Size(ui.available_width() as u32, ui.available_width() as u32); - let color_img = load_svg_bytes_with_size(svg, Some(size)).unwrap(); - // Create image texture. - let texture_handle = ui.ctx().load_texture("qr_code", - color_img.clone(), - TextureOptions::default()); - self.texture_handle = Some(texture_handle.clone()); - let img_size = egui::emath::vec2(color_img.width() as f32, - color_img.height() as f32); - let sized_img = SizedTexture::new(texture_handle.id(), img_size); - // Add image to content. - ui.add(egui::Image::from_texture(sized_img) - .max_height(ui.available_width()) - .fit_to_original_size(1.0)); + // Create vector QR code image if not created. + if !self.has_image() { + let space = (ui.available_width() - View::BIG_SPINNER_SIZE) / 2.0; + ui.vertical_centered(|ui| { + ui.add_space(space); + View::big_loading_spinner(ui); + ui.add_space(space); + }); + + // Create vector image from text if not creating. + if !self.creating() { + self.create_svg(text); + } + } else { + // Create image from SVG data. + let r_create = self.qr_creation_state.read(); + let svg = r_create.svg.as_ref().unwrap(); + let size = SizeHint::Size(ui.available_width() as u32, ui.available_width() as u32); + let color_img = load_svg_bytes_with_size(svg, Some(size)).unwrap(); + // Create image texture. + let texture_handle = ui.ctx().load_texture("qr_code", + color_img.clone(), + TextureOptions::default()); + self.texture_handle = Some(texture_handle.clone()); + let img_size = egui::emath::vec2(color_img.width() as f32, + color_img.height() as f32); + let sized_img = SizedTexture::new(texture_handle.id(), img_size); + // Add image to content. + ui.add(egui::Image::from_texture(sized_img) + .max_height(ui.available_width()) + .fit_to_original_size(1.0)); + } } } - /// Check if image is creating. + /// Check if QR code is creating. fn creating(&self) -> bool { let r_create = self.qr_creation_state.read(); r_create.creating } + /// Create multiple vector QR code images at separate thread. + fn create_svg_list(&self, text: String) { + let qr_creation_state = self.qr_creation_state.clone(); + thread::spawn(move || { + let mut encoder = ur::Encoder::bytes(text.as_bytes(), 100).unwrap(); + let mut data = Vec::with_capacity(encoder.fragment_count()); + for _ in 0..encoder.fragment_count() { + let ur = encoder.next_part().unwrap(); + if let Ok(qr) = QrCode::encode_text(ur.as_str(), qrcodegen::QrCodeEcc::Low) { + let svg = Self::qr_to_svg(qr, 0); + data.push(svg.into_bytes()); + } + } + let mut w_create = qr_creation_state.write(); + if !data.is_empty() { + w_create.svg_list = Some(data); + } + w_create.creating = false; + }); + } + /// Check if image was created. fn has_image(&self) -> bool { let r_create = self.qr_creation_state.read(); - r_create.svg.is_some() + r_create.svg.is_some() || r_create.svg_list.is_some() } - /// Create QR code image at separate thread. - fn create_image(&self, text: String) { + /// Create vector QR code image at separate thread. + fn create_svg(&self, text: String) { let qr_creation_state = self.qr_creation_state.clone(); - if !self.creating() { - thread::spawn(move || { - if let Ok(qr) = QrCode::encode_text(text.as_str(), qrcodegen::QrCodeEcc::Medium) { - let svg = Self::qr_to_svg(qr, 0); - let mut w_create = qr_creation_state.write(); - w_create.creating = false; - w_create.svg = Some(svg.into_bytes()); - } - }); - } + thread::spawn(move || { + if let Ok(qr) = QrCode::encode_text(text.as_str(), qrcodegen::QrCodeEcc::Low) { + let svg = Self::qr_to_svg(qr, 0); + let mut w_create = qr_creation_state.write(); + w_create.creating = false; + w_create.svg = Some(svg.into_bytes()); + } + }); } /// Convert QR code to SVG string. - fn qr_to_svg(qr: qrcodegen::QrCode, border: i32) -> String { + fn qr_to_svg(qr: QrCode, border: i32) -> String { let mut result = String::new(); let dimension = qr.size().checked_add(border.checked_mul(2).unwrap()).unwrap(); result += "\n"; diff --git a/src/gui/views/types.rs b/src/gui/views/types.rs index c1581eb..21f93b0 100644 --- a/src/gui/views/types.rs +++ b/src/gui/views/types.rs @@ -154,19 +154,24 @@ pub enum QrScanResult { Address(ZeroingString), /// Parsed text. Text(ZeroingString), - /// Parsed SeedQR https://github.com/SeedSigner/seedsigner/blob/dev/docs/seed_qr/README.md. - SeedQR(ZeroingString) + /// Recovery phrase in standard or compact SeedQR format. + /// https://github.com/SeedSigner/seedsigner/blob/dev/docs/seed_qr/README.md + SeedQR(ZeroingString), + /// Part of Uniform Resources as URI with current index and total messages amount. + /// https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md + URPart(String, usize, usize), } impl QrScanResult { - /// Get scan result value. - pub fn value(&self) -> String { + /// Get text scanning result. + pub fn text(&self) -> String { match self { - QrScanResult::Slatepack(text) => text, - QrScanResult::Address(text) => text, - QrScanResult::Text(text) => text, - QrScanResult::SeedQR(text) => text - }.to_string() + QrScanResult::Slatepack(text) => text.to_string(), + QrScanResult::Address(text) => text.to_string(), + QrScanResult::Text(text) => text.to_string(), + QrScanResult::SeedQR(text) => text.to_string(), + QrScanResult::URPart(uri, _, _) => uri.to_string(), + } } } @@ -191,8 +196,10 @@ impl Default for QrScanState { pub struct QrCreationState { // Flag to check if QR code image is creating. pub creating: bool, - // Found QR code content. - pub svg: Option> + // Vector image data. + pub svg: Option>, + // Multiple vector image data. + pub svg_list: Option>> } impl Default for QrCreationState { @@ -200,6 +207,7 @@ impl Default for QrCreationState { Self { creating: false, svg: None, + svg_list: None, } } } \ No newline at end of file diff --git a/src/gui/views/wallets/wallet/content.rs b/src/gui/views/wallets/wallet/content.rs index 14cf73b..1e5d9d2 100644 --- a/src/gui/views/wallets/wallet/content.rs +++ b/src/gui/views/wallets/wallet/content.rs @@ -371,7 +371,7 @@ impl WalletContent { cb: &dyn PlatformCallbacks) { // Show scan result if exists or show camera content while scanning. if let Some(result) = &self.qr_scan_result { - let mut result_text = result.value(); + let mut result_text = result.text(); View::horizontal_line(ui, Colors::ITEM_STROKE); ui.add_space(3.0); ScrollArea::vertical() diff --git a/src/gui/views/wallets/wallet/messages.rs b/src/gui/views/wallets/wallet/messages.rs index 5e33829..5f800b8 100644 --- a/src/gui/views/wallets/wallet/messages.rs +++ b/src/gui/views/wallets/wallet/messages.rs @@ -173,13 +173,13 @@ impl WalletMessages { request_edit: "".to_string(), request_error: None, request_qr: false, - request_qr_content: QrCodeContent::new("".to_string()), + request_qr_content: QrCodeContent::new("".to_string(), true), request_loading: false, request_result: Arc::new(RwLock::new(None)), message_camera_content: CameraContent::default(), message_scan_error: false, qr_message_text: None, - qr_message_content: QrCodeContent::new("".to_string()), + qr_message_content: QrCodeContent::new("".to_string(), true), } } @@ -472,7 +472,7 @@ impl WalletMessages { } else { t!("wallets.send_request_desc","amount" => amount_format) }; - ui.label(RichText::new(desc_text).size(16.0).color(Colors::INACTIVE_TEXT)); + ui.label(RichText::new(desc_text).size(16.0).color(Colors::GRAY)); }); ui.add_space(6.0); diff --git a/src/gui/views/wallets/wallet/transport.rs b/src/gui/views/wallets/wallet/transport.rs index 310532e..a7b210c 100644 --- a/src/gui/views/wallets/wallet/transport.rs +++ b/src/gui/views/wallets/wallet/transport.rs @@ -145,7 +145,7 @@ impl WalletTransport { show_address_scan: false, address_scan_content: CameraContent::default(), modal_just_opened: false, - qr_address_content: QrCodeContent::new(addr), + qr_address_content: QrCodeContent::new(addr, false), tor_settings_changed: false, bridge_bin_path_edit: bin_path, bridge_conn_line_edit: conn_line, @@ -327,7 +327,7 @@ impl WalletTransport { }; if let Some(result) = self.bridge_qr_scan_content.qr_scan_result() { - self.bridge_conn_line_edit = result.value(); + self.bridge_conn_line_edit = result.text(); on_stop(&mut self.bridge_qr_scan_content); cb.show_keyboard(); } else { @@ -688,7 +688,7 @@ impl WalletTransport { }; if let Some(result) = self.address_scan_content.qr_scan_result() { - self.address_edit = result.value(); + self.address_edit = result.text(); self.modal_just_opened = true; on_stop(&mut self.address_scan_content); cb.show_keyboard(); diff --git a/src/gui/views/wallets/wallet/txs.rs b/src/gui/views/wallets/wallet/txs.rs index 86b3261..9b03e45 100644 --- a/src/gui/views/wallets/wallet/txs.rs +++ b/src/gui/views/wallets/wallet/txs.rs @@ -80,7 +80,7 @@ impl Default for WalletTransactions { tx_info_finalizing: false, tx_info_final_result: Arc::new(RwLock::new(None)), tx_info_show_qr: false, - tx_info_qr_code_content: QrCodeContent::new("".to_string()), + tx_info_qr_code_content: QrCodeContent::new("".to_string(), true), tx_info_show_scanner: false, tx_info_scanner_content: CameraContent::default(), confirm_cancel_tx_id: None, @@ -708,7 +708,7 @@ impl WalletTransactions { self.tx_info_scanner_content.clear_state(); // Setup value to finalization input field. - self.tx_info_finalize_edit = result.value(); + self.tx_info_finalize_edit = result.text(); self.on_finalization_input_change(tx, wallet, modal, cb); modal.enable_closing(); @@ -737,7 +737,7 @@ impl WalletTransactions { let desc_color = if self.tx_info_finalize_error { Colors::RED } else { - Colors::INACTIVE_TEXT + Colors::GRAY }; ui.label(RichText::new(desc_text).size(16.0).color(desc_color)); } else { @@ -754,7 +754,7 @@ impl WalletTransactions { t!("wallets.parse_s1_slatepack_desc", "amount" => amount) } }; - ui.label(RichText::new(desc_text).size(16.0).color(Colors::INACTIVE_TEXT)); + ui.label(RichText::new(desc_text).size(16.0).color(Colors::GRAY)); } }); ui.add_space(6.0); diff --git a/src/wallet/utils.rs b/src/wallet/utils.rs index 97a56f9..26ec913 100644 --- a/src/wallet/utils.rs +++ b/src/wallet/utils.rs @@ -23,8 +23,6 @@ impl WalletUtils { let mut hasher = Sha256::new(); hasher.update(data.clone()); let checksum = hasher.finalize(); - println!("BEFORE data: {}, checksum: {}", data.len(), checksum.len()); data.extend(checksum); - println!("AFTER data: {}", data.len()); } } \ No newline at end of file