mirror of
https://code.gri.mw/GUI/grim.git
synced 2026-07-05 22:47:28 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 875bd11bdb | |||
| 19e4cb664d | |||
| 18bc327a99 | |||
| 88e2fb0715 | |||
| feb38dc7cf | |||
| 28ecb5b1f4 | |||
| 024a9d0098 | |||
| 59cf46e1cb | |||
| 22255e0f2a | |||
| 7fdb8d272b | |||
| d043562058 |
@@ -27,7 +27,7 @@ jobs:
|
||||
[[ ${{ forgejo.ref_type }} == 'tag' ]] && app_ver=${{ forgejo.ref_name }} || app_ver=v${ver}
|
||||
echo "v=${app_ver}" >> "$FORGEJO_OUTPUT"
|
||||
echo $app_ver
|
||||
[[ ${{ forgejo.ref_type }} == 'tag' ]] && pre=false || pre=true
|
||||
[[ ${{ forgejo.ref_type }} == 'tag' ]] && pre='false' || pre='true'
|
||||
echo "pre=${pre}" >> "$FORGEJO_OUTPUT"
|
||||
echo "pre-release: ${pre}"
|
||||
- name: Check existing release
|
||||
@@ -331,11 +331,11 @@ jobs:
|
||||
- name: Archive Universal
|
||||
working-directory: macos
|
||||
run: |
|
||||
zip -r grim-${{ needs.version.outputs.v }}-macos.zip Grim.app
|
||||
mv grim-${{ needs.version.outputs.v }}-macos.zip ../release
|
||||
zip -r grim-${{ needs.version.outputs.v }}-macos-universal.zip Grim.app
|
||||
mv grim-${{ needs.version.outputs.v }}-macos-universal.zip ../release
|
||||
- name: Checksum Release Universal
|
||||
working-directory: release
|
||||
run: sha256sum grim-${{ needs.version.outputs.v }}-macos.zip > grim-${{ needs.version.outputs.v }}-macos-sha256sum.txt
|
||||
run: sha256sum grim-${{ needs.version.outputs.v }}-macos-universal.zip > grim-${{ needs.version.outputs.v }}-macos-universal-sha256sum.txt
|
||||
- name: Upload artifacts
|
||||
run: |
|
||||
tar -czf macos.tar.gz release
|
||||
@@ -396,7 +396,7 @@ jobs:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
tag: ${{ needs.version.outputs.v }}
|
||||
override: true
|
||||
prerelease: ${{ needs.version.outputs.pre }}
|
||||
prerelease: ${{ needs.version.outputs.pre == 'true' }}
|
||||
release-dir: release
|
||||
release-notes: "Full Changelog: [${{ needs.version.outputs.last_tag }}...${{ needs.version.outputs.v }}](https://code.gri.mw/${{ forgejo.repository }}/compare/${{ needs.version.outputs.last_tag }}...${{ needs.version.outputs.v }})"
|
||||
- name: Telegram Notify Channel
|
||||
@@ -432,6 +432,6 @@ jobs:
|
||||
release/grim-${{ needs.version.outputs.v }}-android-x86_64.apk
|
||||
release/grim-${{ needs.version.outputs.v }}-linux-arm.AppImage
|
||||
release/grim-${{ needs.version.outputs.v }}-linux-x86_64.AppImage
|
||||
release/grim-${{ needs.version.outputs.v }}-macos.zip
|
||||
release/grim-${{ needs.version.outputs.v }}-macos-universal.zip
|
||||
release/grim-${{ needs.version.outputs.v }}-win-x86_64.msi
|
||||
release/grim-${{ needs.version.outputs.v }}-win-x86_64.zip
|
||||
@@ -5,7 +5,7 @@ REPO_NAME=$1
|
||||
TAG=$2
|
||||
DOWNLOAD_URL=${HOST}/${REPO_NAME}/releases/download/${TAG}
|
||||
|
||||
FILES=( "grim-${TAG}-android.apk" "grim-${TAG}-android-x86_64.apk" "grim-${TAG}-linux-arm.AppImage" "grim-${TAG}-linux-x86_64.AppImage" "grim-${TAG}-macos.zip" "grim-${TAG}-win-x86_64.msi" "grim-${TAG}-win-x86_64.zip" )
|
||||
FILES=( "grim-${TAG}-android.apk" "grim-${TAG}-android-x86_64.apk" "grim-${TAG}-linux-arm.AppImage" "grim-${TAG}-linux-x86_64.AppImage" "grim-${TAG}-macos-universal.zip" "grim-${TAG}-win-x86_64.msi" "grim-${TAG}-win-x86_64.zip" )
|
||||
|
||||
# Download release files
|
||||
for f in "${FILES[@]}"; do
|
||||
|
||||
@@ -26,6 +26,6 @@ jobs:
|
||||
grim-${{ github.ref_name }}-android-x86_64.apk
|
||||
grim-${{ github.ref_name }}-linux-arm.AppImage
|
||||
grim-${{ github.ref_name }}-linux-x86_64.AppImage
|
||||
grim-${{ github.ref_name }}-macos.zip
|
||||
grim-${{ github.ref_name }}-macos-universal.zip
|
||||
grim-${{ github.ref_name }}-win-x86_64.msi
|
||||
grim-${{ github.ref_name }}-win-x86_64.zip
|
||||
Generated
+13
-13
@@ -4000,7 +4000,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grim"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
dependencies = [
|
||||
"android-activity",
|
||||
"android_logger",
|
||||
@@ -4091,7 +4091,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_api"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"bytes 1.11.1",
|
||||
@@ -4124,7 +4124,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_chain"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"bit-vec 0.6.3",
|
||||
"bitflags 1.3.2",
|
||||
@@ -4146,7 +4146,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_config"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"dirs 2.0.2",
|
||||
"grin_core",
|
||||
@@ -4161,7 +4161,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_core"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"blake2-rfc",
|
||||
"byteorder",
|
||||
@@ -4186,7 +4186,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_keychain"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"blake2-rfc",
|
||||
"byteorder",
|
||||
@@ -4207,7 +4207,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_p2p"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bytes 0.5.6",
|
||||
@@ -4228,7 +4228,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_pool"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"blake2-rfc",
|
||||
"chrono",
|
||||
@@ -4244,9 +4244,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_secp256k1zkp"
|
||||
version = "0.7.14"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06832645c3d28079245827908045946db48e5d62b4c54b40701c7e21327e2571"
|
||||
checksum = "bf7bb95f155b1eede2648a1b9afbba82bc3d9f2af0518b478767559a572bd973"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.6",
|
||||
"cc",
|
||||
@@ -4259,7 +4259,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_servers"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"chrono",
|
||||
@@ -4290,7 +4290,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_store"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"croaring",
|
||||
@@ -4308,7 +4308,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "grin_util"
|
||||
version = "5.4.0-alpha.0"
|
||||
version = "5.4.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"backtrace",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "grim"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
authors = ["Ardocrat <ardocrat@gri.mw>"]
|
||||
description = "Cross-platform GUI for Grin with focus on usability and availability to be used by anyone, anywhere."
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -12,7 +12,7 @@ android {
|
||||
minSdk 24
|
||||
targetSdk 36
|
||||
versionCode 5
|
||||
versionName "0.3.0"
|
||||
versionName "0.3.1"
|
||||
}
|
||||
|
||||
lint {
|
||||
|
||||
+1
-1
Submodule node updated: 376c85bab5...2ec7b4d5cd
+2
-2
@@ -44,7 +44,6 @@ const BLUE_DARK: Color32 =
|
||||
const FILL: Color32 = Color32::from_gray(244);
|
||||
const FILL_DARK: Color32 = Color32::from_gray(26);
|
||||
|
||||
const FILL_DEEP: Color32 = Color32::from_gray(238);
|
||||
const FILL_DEEP_DARK: Color32 = Color32::from_gray(32);
|
||||
|
||||
const FILL_LITE: Color32 = Color32::from_gray(249);
|
||||
@@ -85,6 +84,7 @@ fn use_dark() -> bool {
|
||||
}
|
||||
|
||||
impl Colors {
|
||||
pub const FILL_DEEP: Color32 = Color32::from_gray(238);
|
||||
pub const TRANSPARENT: Color32 = Color32::from_rgba_premultiplied(0, 0, 0, 0);
|
||||
pub const STROKE: Color32 = Color32::from_gray(200);
|
||||
|
||||
@@ -172,7 +172,7 @@ impl Colors {
|
||||
if use_dark() {
|
||||
FILL_DEEP_DARK
|
||||
} else {
|
||||
FILL_DEEP
|
||||
Self::FILL_DEEP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-18
@@ -12,21 +12,21 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::sync::Arc;
|
||||
use parking_lot::RwLock;
|
||||
use std::thread;
|
||||
use egui::load::SizedTexture;
|
||||
use egui::{Pos2, Rect, RichText, TextureOptions, UiBuilder, Widget};
|
||||
use image::{DynamicImage, EncodableLayout};
|
||||
use grin_keychain::mnemonic::WORDS;
|
||||
use grin_util::ZeroingString;
|
||||
use grin_wallet_libwallet::SlatepackAddress;
|
||||
use grin_keychain::mnemonic::WORDS;
|
||||
use image::{DynamicImage, EncodableLayout};
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::CAMERA_ROTATE;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::types::{QrScanResult, QrScanState};
|
||||
use crate::gui::views::View;
|
||||
use crate::gui::Colors;
|
||||
use crate::wallet::types::PhraseSize;
|
||||
use crate::wallet::WalletUtils;
|
||||
|
||||
@@ -51,16 +51,13 @@ impl CameraContent {
|
||||
/// Draw camera content.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
let rect = if let Some(img_data) = cb.camera_image() {
|
||||
if let Ok(img) =
|
||||
image::load_from_memory(&*img_data.0) {
|
||||
if let Ok(img) = image::load_from_memory(&*img_data.0) {
|
||||
// Process image to find QR code.
|
||||
self.scan_qr(&img);
|
||||
|
||||
// Draw image.
|
||||
let img_rect = self.image_ui(ui, img, img_data.1);
|
||||
|
||||
// Show UR scan progress.
|
||||
self.ur_progress_ui(ui);
|
||||
img_rect
|
||||
} else {
|
||||
self.loading_ui(ui)
|
||||
@@ -69,6 +66,9 @@ impl CameraContent {
|
||||
self.loading_ui(ui)
|
||||
};
|
||||
|
||||
// Show UR scan progress.
|
||||
self.ur_progress_ui(ui, &rect);
|
||||
|
||||
// Show button to switch cameras.
|
||||
if cb.can_switch_camera() {
|
||||
let r = {
|
||||
@@ -84,6 +84,7 @@ impl CameraContent {
|
||||
});
|
||||
});
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
ui.ctx().request_repaint();
|
||||
}
|
||||
|
||||
@@ -125,7 +126,11 @@ impl CameraContent {
|
||||
egui::Image::from_texture(sized_img)
|
||||
// Setup to crop image at square.
|
||||
.uv(Rect::from([
|
||||
Pos2::new(1.0 - (img_size.y / img_size.x), 0.0),
|
||||
if img_size.y > img_size.x {
|
||||
Pos2::new(0.0, 1.0 - (img_size.x / img_size.y))
|
||||
} else {
|
||||
Pos2::new(1.0 - (img_size.y / img_size.x), 0.0)
|
||||
},
|
||||
Pos2::new(1.0, 1.0)
|
||||
]))
|
||||
.max_height(ui.available_width())
|
||||
@@ -135,15 +140,17 @@ impl CameraContent {
|
||||
}
|
||||
|
||||
/// Draw animated QR code scanning progress.
|
||||
fn ur_progress_ui(&self, ui: &mut egui::Ui) {
|
||||
fn ur_progress_ui(&self, ui: &mut egui::Ui, rect: &Rect) {
|
||||
let show_ur_progress = {
|
||||
self.ur_data.as_ref().read().is_some()
|
||||
};
|
||||
if show_ur_progress {
|
||||
ui.centered_and_justified(|ui| {
|
||||
ui.label(RichText::new(format!("{}%", self.ur_progress()))
|
||||
.size(17.0)
|
||||
.color(Colors::green()));
|
||||
ui.scope_builder(UiBuilder::new().max_rect(rect.clone()), |ui| {
|
||||
ui.centered_and_justified(|ui| {
|
||||
ui.label(RichText::new(format!("{}%", self.ur_progress()))
|
||||
.size(32.0)
|
||||
.color(Colors::gold_dark()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -201,8 +208,7 @@ impl CameraContent {
|
||||
let on_scan = async move {
|
||||
// Prepare image data.
|
||||
let img = image_data.to_luma8();
|
||||
let mut img: rqrr::PreparedImage<image::GrayImage>
|
||||
= rqrr::PreparedImage::prepare(img);
|
||||
let mut img: rqrr::PreparedImage<image::GrayImage> = rqrr::PreparedImage::prepare(img);
|
||||
// Scan and save results.
|
||||
let grids = img.detect_grids();
|
||||
if let Some(g) = grids.get(0) {
|
||||
|
||||
+11
-2
@@ -14,7 +14,7 @@
|
||||
|
||||
use egui::epaint::{RectShape, Shadow};
|
||||
use egui::os::OperatingSystem;
|
||||
use egui::{Align2, CornerRadius, RichText, Stroke, StrokeKind, UiBuilder, Vec2};
|
||||
use egui::{Align2, Color32, CornerRadius, RichText, Stroke, StrokeKind, UiBuilder, Vec2};
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -43,6 +43,8 @@ pub struct Modal {
|
||||
title: Option<String>,
|
||||
/// Flag to check first content render.
|
||||
first_draw: Arc<AtomicBool>,
|
||||
/// Background color.
|
||||
fill: Color32,
|
||||
}
|
||||
|
||||
impl Modal {
|
||||
@@ -61,6 +63,7 @@ impl Modal {
|
||||
closeable: Arc::new(AtomicBool::new(true)),
|
||||
title: None,
|
||||
first_draw: Arc::new(AtomicBool::new(true)),
|
||||
fill: Colors::fill(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +298,12 @@ impl Modal {
|
||||
(align, offset)
|
||||
}
|
||||
|
||||
/// Set custom background color.
|
||||
pub fn set_background_color(&self, color: Color32) {
|
||||
let mut w_state = MODAL_STATE.write();
|
||||
w_state.modal.as_mut().unwrap().fill = color;
|
||||
}
|
||||
|
||||
/// Draw provided content.
|
||||
fn content_ui(&self,
|
||||
ui: &mut egui::Ui,
|
||||
@@ -312,7 +321,7 @@ impl Modal {
|
||||
sw: 8.0 as u8,
|
||||
se: 8.0 as u8,
|
||||
}
|
||||
}, Colors::fill(), Stroke::NONE, StrokeKind::Outside);
|
||||
}, self.fill, Stroke::NONE, StrokeKind::Outside);
|
||||
let bg_idx = ui.painter().add(bg_shape.clone());
|
||||
|
||||
rect.min += egui::emath::vec2(6.0, 0.0);
|
||||
|
||||
+1
-1
@@ -304,7 +304,7 @@ impl QrCodeContent {
|
||||
let qr_state = self.qr_image_state.clone();
|
||||
let text = self.text.clone();
|
||||
thread::spawn(move || {
|
||||
let mut encoder = ur::Encoder::bytes(text.as_bytes(), 100).unwrap();
|
||||
let mut encoder = ur::Encoder::bytes(text.as_bytes(), 64).unwrap();
|
||||
let mut data = Vec::with_capacity(encoder.fragment_count());
|
||||
for _ in 0..encoder.fragment_count() {
|
||||
let ur = encoder.next_part().unwrap();
|
||||
|
||||
@@ -160,9 +160,9 @@ impl ContentContainer for WalletsContent {
|
||||
}
|
||||
|
||||
fn container_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
let is_android = OperatingSystem::from_target_os() == OperatingSystem::Android;
|
||||
let account_list_showing = self.wallet_content.account_content.list_content.is_some();
|
||||
// Small repaint delay is needed for Android back navigation and account list opening.
|
||||
let is_android = OperatingSystem::from_target_os() == OperatingSystem::Android;
|
||||
let account_list_showing = self.wallet_content.account_content.show_list;
|
||||
ui.ctx().request_repaint_after(Duration::from_millis(if account_list_showing {
|
||||
10
|
||||
} else if is_android {
|
||||
@@ -516,6 +516,7 @@ impl WalletsContent {
|
||||
}
|
||||
}, ui);
|
||||
if show_settings {
|
||||
self.wallet_content.back(cb);
|
||||
self.settings_content = Some(SettingsContent::default());
|
||||
}
|
||||
}
|
||||
@@ -753,7 +754,7 @@ impl WalletsContent {
|
||||
|
||||
/// Select wallet to make some actions on it.
|
||||
fn select_wallet(&mut self, w: &Wallet, data: Option<String>, cb: &dyn PlatformCallbacks) {
|
||||
self.wallet_content.account_content.close_qr_scan(cb);
|
||||
self.wallet_content.back(cb);
|
||||
if let Some(data) = data {
|
||||
w.task(WalletTask::OpenMessage(data));
|
||||
}
|
||||
|
||||
@@ -7,29 +7,30 @@
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distr1ibuted on an "AS IS" BASIS,
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Align, Layout, RichText, StrokeKind};
|
||||
use egui::{Align, Layout, RichText, ScrollArea, StrokeKind};
|
||||
use egui::scroll_area::ScrollBarVisibility;
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
|
||||
use crate::gui::icons::{FOLDER_USER, PACKAGE, SCAN, SPINNER, USERS_THREE, USER_PLUS};
|
||||
use crate::gui::icons::{CHECK, FOLDER_USER, PACKAGE, PATH, SCAN, SPINNER, USERS_THREE, USER_PLUS};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::types::{ModalPosition, QrScanResult};
|
||||
use crate::gui::views::wallets::wallet::account::create::CreateAccountContent;
|
||||
use crate::gui::views::wallets::wallet::account::list::WalletAccountsContent;
|
||||
use crate::gui::views::wallets::wallet::types::{WalletContentContainer, GRIN};
|
||||
use crate::gui::views::{CameraContent, CameraScanContent, Content, Modal, View};
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::views::wallets::wallet::request::SendRequestContent;
|
||||
use crate::wallet::{Wallet, WalletConfig};
|
||||
use crate::wallet::types::WalletTask;
|
||||
use crate::wallet::types::{WalletAccount, WalletTask};
|
||||
|
||||
/// Wallet account panel content.
|
||||
pub struct AccountContent {
|
||||
/// Account list content.
|
||||
pub list_content: Option<WalletAccountsContent>,
|
||||
pub struct WalletAccountContent {
|
||||
/// Flag to show account list content.
|
||||
pub show_list: bool,
|
||||
/// Account creation [`Modal`] content.
|
||||
create_account_content: CreateAccountContent,
|
||||
|
||||
@@ -37,15 +38,20 @@ pub struct AccountContent {
|
||||
qr_scan_content: Option<CameraContent>,
|
||||
/// QR code scan result
|
||||
qr_scan_result: Option<QrScanResult>,
|
||||
/// Send request creation [`Modal`] content.
|
||||
send_content: Option<SendRequestContent>,
|
||||
}
|
||||
|
||||
/// Account creation [`Modal`] identifier.
|
||||
const CREATE_MODAL_ID: &'static str = "create_account_modal";
|
||||
/// Identifier for sending request creation [`Modal`].
|
||||
const SEND_MODAL_ID: &'static str = "account_send_request_modal";
|
||||
|
||||
impl WalletContentContainer for AccountContent {
|
||||
impl WalletContentContainer for WalletAccountContent {
|
||||
fn modal_ids(&self) -> Vec<&'static str> {
|
||||
vec![
|
||||
CREATE_MODAL_ID
|
||||
CREATE_MODAL_ID,
|
||||
SEND_MODAL_ID
|
||||
]
|
||||
}
|
||||
|
||||
@@ -56,6 +62,11 @@ impl WalletContentContainer for AccountContent {
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
match modal.id {
|
||||
CREATE_MODAL_ID => self.create_account_content.ui(ui, wallet, modal, cb),
|
||||
SEND_MODAL_ID => {
|
||||
if let Some(c) = self.send_content.as_mut() {
|
||||
c.modal_ui(ui, wallet, modal, cb);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +76,7 @@ impl WalletContentContainer for AccountContent {
|
||||
self.qr_scan_ui(ui, wallet, cb);
|
||||
} else {
|
||||
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
|
||||
if self.list_content.is_some() {
|
||||
if self.show_list {
|
||||
self.list_ui(ui, wallet);
|
||||
} else {
|
||||
// Show account content.
|
||||
@@ -76,18 +87,21 @@ impl WalletContentContainer for AccountContent {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AccountContent {
|
||||
impl Default for WalletAccountContent {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
list_content: None,
|
||||
show_list: false,
|
||||
create_account_content: CreateAccountContent::default(),
|
||||
qr_scan_content: None,
|
||||
qr_scan_result: None,
|
||||
send_content: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AccountContent {
|
||||
const ACCOUNT_ITEM_HEIGHT: f32 = 75.0;
|
||||
|
||||
impl WalletAccountContent {
|
||||
/// Check if QR code scanner was opened.
|
||||
pub fn qr_scan_showing(&self) -> bool {
|
||||
self.qr_scan_content.is_some() || self.qr_scan_result.is_some()
|
||||
@@ -105,15 +119,15 @@ impl AccountContent {
|
||||
|
||||
/// Check if it's possible to go back at navigation stack.
|
||||
pub fn can_back(&self) -> bool {
|
||||
self.qr_scan_showing() || self.list_content.is_some()
|
||||
self.qr_scan_showing() || self.show_list
|
||||
}
|
||||
|
||||
/// Navigate back on navigation stack.
|
||||
pub fn back(&mut self, cb: &dyn PlatformCallbacks) {
|
||||
if self.qr_scan_showing() {
|
||||
self.close_qr_scan(cb);
|
||||
} else if self.list_content.is_some() {
|
||||
self.list_content = None;
|
||||
} else if self.show_list {
|
||||
self.show_list = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,13 +156,10 @@ impl AccountContent {
|
||||
|
||||
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
|
||||
// Draw button to show QR code scanner.
|
||||
let wallet_synced = wallet.synced_from_node();
|
||||
if wallet_synced {
|
||||
View::item_button(ui, View::item_rounding(0, 2, true), SCAN, None, || {
|
||||
self.qr_scan_content = Some(CameraContent::default());
|
||||
cb.start_camera();
|
||||
});
|
||||
}
|
||||
View::item_button(ui, View::item_rounding(0, 2, true), SCAN, None, || {
|
||||
self.qr_scan_content = Some(CameraContent::default());
|
||||
cb.start_camera();
|
||||
});
|
||||
|
||||
// Draw button to show list of accounts.
|
||||
let accounts = wallet.accounts();
|
||||
@@ -157,11 +168,7 @@ impl AccountContent {
|
||||
} else {
|
||||
USER_PLUS
|
||||
};
|
||||
let rounding = if wallet_synced {
|
||||
View::item_rounding(1, 3, true)
|
||||
} else {
|
||||
View::item_rounding(0, 2, true)
|
||||
};
|
||||
let rounding = View::item_rounding(1, 3, true);
|
||||
View::item_button(ui, rounding, accounts_icon, None, || {
|
||||
if accounts.len() == 1 {
|
||||
self.create_account_content = CreateAccountContent::default();
|
||||
@@ -170,9 +177,7 @@ impl AccountContent {
|
||||
.title(t!("wallets.accounts"))
|
||||
.show();
|
||||
} else {
|
||||
self.list_content = Some(
|
||||
WalletAccountsContent::new(accounts, wallet.get_config().account)
|
||||
);
|
||||
self.show_list = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -240,19 +245,26 @@ impl AccountContent {
|
||||
|
||||
/// Draw account list content.
|
||||
fn list_ui(&mut self, ui: &mut egui::Ui, wallet: &Wallet) {
|
||||
if let Some(accounts) = self.list_content.as_mut() {
|
||||
let mut selected = false;
|
||||
accounts.ui(ui, |acc| {
|
||||
let _ = wallet.set_active_account(&acc.label);
|
||||
selected = true;
|
||||
let accounts = wallet.accounts();
|
||||
let size = accounts.len();
|
||||
ScrollArea::vertical()
|
||||
.id_salt("account_list_scroll")
|
||||
.scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden)
|
||||
.max_height(411.0)
|
||||
.auto_shrink([true; 2])
|
||||
.show_rows(ui, ACCOUNT_ITEM_HEIGHT, size, |ui, row_range| {
|
||||
for index in row_range {
|
||||
let acc = accounts.get(index).unwrap().clone();
|
||||
let current = wallet.get_config().account == acc.label;
|
||||
account_item_ui(ui, &acc, current, index, size, || {
|
||||
let _ = wallet.set_active_account(&acc.label);
|
||||
self.show_list = false;
|
||||
});
|
||||
if index == size - 1 {
|
||||
ui.add_space(4.0);
|
||||
}
|
||||
}
|
||||
});
|
||||
if selected {
|
||||
self.list_content = None;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
ui.add_space(2.0);
|
||||
View::horizontal_line(ui, Colors::item_stroke());
|
||||
@@ -265,12 +277,12 @@ impl AccountContent {
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || {
|
||||
self.list_content = None;
|
||||
self.show_list = false;
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.add"), Colors::white_or_black(false), || {
|
||||
self.list_content = None;
|
||||
self.show_list = false;
|
||||
self.create_account_content = CreateAccountContent::default();
|
||||
Modal::new(CREATE_MODAL_ID)
|
||||
.position(ModalPosition::CenterTop)
|
||||
@@ -290,8 +302,17 @@ impl AccountContent {
|
||||
cb.stop_camera();
|
||||
self.qr_scan_content = None;
|
||||
match result {
|
||||
QrScanResult::Address(_) => {
|
||||
//TODO: send with address
|
||||
QrScanResult::Address(a) => {
|
||||
if let Some(data) = wallet.get_data() {
|
||||
if data.info.amount_currently_spendable > 0 {
|
||||
let address = Some(a.to_string());
|
||||
self.send_content = Some(SendRequestContent::new(address));
|
||||
Modal::new(SEND_MODAL_ID)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("wallets.send"))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
QrScanResult::Slatepack(m) => {
|
||||
wallet.task(WalletTask::OpenMessage(m));
|
||||
@@ -321,4 +342,72 @@ impl AccountContent {
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw account item.
|
||||
fn account_item_ui(ui: &mut egui::Ui,
|
||||
acc: &WalletAccount,
|
||||
current: bool,
|
||||
index: usize,
|
||||
size: usize,
|
||||
mut on_select: impl FnMut()) {
|
||||
// Setup layout size.
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.set_height(ACCOUNT_ITEM_HEIGHT);
|
||||
|
||||
// Draw round background.
|
||||
let bg_rect = rect.clone();
|
||||
let item_rounding = View::item_rounding(index, size, false);
|
||||
ui.painter().rect(bg_rect,
|
||||
item_rounding,
|
||||
Colors::fill(),
|
||||
View::item_stroke(),
|
||||
StrokeKind::Outside);
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
|
||||
// Draw button to select account.
|
||||
if current {
|
||||
View::selected_item_check(ui);
|
||||
} else {
|
||||
let button_rounding = View::item_rounding(index, size, true);
|
||||
View::item_button(ui, button_rounding, CHECK, None, || {
|
||||
on_select();
|
||||
});
|
||||
}
|
||||
|
||||
let layout_size = ui.available_size();
|
||||
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
|
||||
ui.add_space(8.0);
|
||||
ui.vertical(|ui| {
|
||||
ui.add_space(3.0);
|
||||
// Show spendable amount.
|
||||
let amount = amount_to_hr_string(acc.spendable_amount, true);
|
||||
let amount_text = format!("{} {}", amount, GRIN);
|
||||
ui.with_layout(Layout::left_to_right(Align::Min), |ui| {
|
||||
ui.add_space(1.0);
|
||||
ui.label(RichText::new(amount_text)
|
||||
.size(18.0)
|
||||
.color(Colors::white_or_black(true)));
|
||||
});
|
||||
ui.add_space(-2.0);
|
||||
|
||||
// Show account name.
|
||||
let default_acc_label = WalletConfig::DEFAULT_ACCOUNT_LABEL.to_string();
|
||||
let acc_label = if acc.label == default_acc_label {
|
||||
t!("wallets.default_account").into()
|
||||
} else {
|
||||
acc.label.to_owned()
|
||||
};
|
||||
let acc_name = format!("{} {}", FOLDER_USER, acc_label);
|
||||
View::ellipsize_text(ui, acc_name, 15.0, Colors::text(false));
|
||||
|
||||
// Show account BIP32 derivation path.
|
||||
let acc_path = format!("{} {}", PATH, acc.path);
|
||||
ui.label(RichText::new(acc_path).size(15.0).color(Colors::gray()));
|
||||
ui.add_space(3.0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
// Copyright 2025 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::scroll_area::ScrollBarVisibility;
|
||||
use egui::{Align, Layout, RichText, ScrollArea, StrokeKind};
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
|
||||
use crate::gui::icons::{CHECK, FOLDER_USER, PATH};
|
||||
use crate::gui::views::wallets::wallet::types::GRIN;
|
||||
use crate::gui::views::View;
|
||||
use crate::gui::Colors;
|
||||
use crate::wallet::types::WalletAccount;
|
||||
use crate::wallet::WalletConfig;
|
||||
|
||||
/// Wallet account list content.
|
||||
pub struct WalletAccountsContent {
|
||||
/// List of wallet accounts.
|
||||
accounts: Vec<WalletAccount>,
|
||||
/// Current wallet account label.
|
||||
current_label: String,
|
||||
}
|
||||
|
||||
const ACCOUNT_ITEM_HEIGHT: f32 = 75.0;
|
||||
|
||||
impl WalletAccountsContent {
|
||||
/// Create new accounts content.
|
||||
pub fn new(accounts: Vec<WalletAccount>, current: String) -> Self {
|
||||
Self { accounts, current_label: current }
|
||||
}
|
||||
|
||||
/// Draw account list content.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, mut on_select: impl FnMut(WalletAccount)) {
|
||||
let size = self.accounts.len();
|
||||
ScrollArea::vertical()
|
||||
.id_salt("account_list_scroll")
|
||||
.scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden)
|
||||
.max_height(411.0)
|
||||
.auto_shrink([true; 2])
|
||||
.show_rows(ui, ACCOUNT_ITEM_HEIGHT, size, |ui, row_range| {
|
||||
for index in row_range {
|
||||
let acc = self.accounts.get(index).unwrap().clone();
|
||||
self.account_item_ui(ui, &acc, index, size, || {
|
||||
on_select(acc.clone());
|
||||
});
|
||||
if index == size - 1 {
|
||||
ui.add_space(4.0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw account item.
|
||||
fn account_item_ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
acc: &WalletAccount,
|
||||
index: usize,
|
||||
size: usize,
|
||||
mut on_select: impl FnMut()) {
|
||||
// Setup layout size.
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.set_height(ACCOUNT_ITEM_HEIGHT);
|
||||
|
||||
// Draw round background.
|
||||
let bg_rect = rect.clone();
|
||||
let item_rounding = View::item_rounding(index, size, false);
|
||||
ui.painter().rect(bg_rect,
|
||||
item_rounding,
|
||||
Colors::fill(),
|
||||
View::item_stroke(),
|
||||
StrokeKind::Outside);
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
|
||||
// Draw button to select account.
|
||||
if self.current_label == acc.label {
|
||||
View::selected_item_check(ui);
|
||||
} else {
|
||||
let button_rounding = View::item_rounding(index, size, true);
|
||||
View::item_button(ui, button_rounding, CHECK, None, || {
|
||||
on_select();
|
||||
});
|
||||
}
|
||||
|
||||
let layout_size = ui.available_size();
|
||||
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
|
||||
ui.add_space(8.0);
|
||||
ui.vertical(|ui| {
|
||||
ui.add_space(3.0);
|
||||
// Show spendable amount.
|
||||
let amount = amount_to_hr_string(acc.spendable_amount, true);
|
||||
let amount_text = format!("{} {}", amount, GRIN);
|
||||
ui.with_layout(Layout::left_to_right(Align::Min), |ui| {
|
||||
ui.add_space(1.0);
|
||||
ui.label(RichText::new(amount_text)
|
||||
.size(18.0)
|
||||
.color(Colors::white_or_black(true)));
|
||||
});
|
||||
ui.add_space(-2.0);
|
||||
|
||||
// Show account name.
|
||||
let default_acc_label = WalletConfig::DEFAULT_ACCOUNT_LABEL.to_string();
|
||||
let acc_label = if acc.label == default_acc_label {
|
||||
t!("wallets.default_account").into()
|
||||
} else {
|
||||
acc.label.to_owned()
|
||||
};
|
||||
let acc_name = format!("{} {}", FOLDER_USER, acc_label);
|
||||
View::ellipsize_text(ui, acc_name, 15.0, Colors::text(false));
|
||||
|
||||
// Show account BIP32 derivation path.
|
||||
let acc_path = format!("{} {}", PATH, acc.path);
|
||||
ui.label(RichText::new(acc_path).size(15.0).color(Colors::gray()));
|
||||
ui.add_space(3.0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
mod content;
|
||||
mod list;
|
||||
mod create;
|
||||
pub use content::*;
|
||||
|
||||
pub use content::*;
|
||||
mod create;
|
||||
@@ -19,7 +19,7 @@ use grin_chain::SyncStatus;
|
||||
use crate::gui::icons::{ARROWS_CLOCKWISE, FILE_ARROW_DOWN, FILE_ARROW_UP, FILE_TEXT, GEAR_FINE, POWER, STACK};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::types::{LinePosition, ModalPosition};
|
||||
use crate::gui::views::wallets::wallet::account::AccountContent;
|
||||
use crate::gui::views::wallets::wallet::account::WalletAccountContent;
|
||||
use crate::gui::views::wallets::wallet::message::MessageInputContent;
|
||||
use crate::gui::views::wallets::wallet::request::{InvoiceRequestContent, SendRequestContent};
|
||||
use crate::gui::views::wallets::wallet::transport::WalletTransportContent;
|
||||
@@ -42,7 +42,7 @@ pub struct WalletContent {
|
||||
pub settings_content: Option<WalletSettingsContent>,
|
||||
|
||||
/// Account panel content.
|
||||
pub account_content: AccountContent,
|
||||
pub account_content: WalletAccountContent,
|
||||
/// Transport panel content.
|
||||
pub transport_content: WalletTransportContent,
|
||||
|
||||
@@ -150,9 +150,13 @@ impl WalletContentContainer for WalletContent {
|
||||
}
|
||||
});
|
||||
|
||||
// Close scanner when account panel got hidden.
|
||||
if !show_account && self.account_content.qr_scan_showing() {
|
||||
self.account_content.close_qr_scan(cb);
|
||||
// Close scanner or account list when account panel got hidden.
|
||||
if !show_account {
|
||||
if self.account_content.qr_scan_showing() {
|
||||
self.account_content.close_qr_scan(cb);
|
||||
} else {
|
||||
self.account_content.show_list = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Flag to check if account panel is opened.
|
||||
@@ -204,7 +208,11 @@ impl WalletContentContainer for WalletContent {
|
||||
bottom: 1.0 as i8,
|
||||
},
|
||||
fill: if top_panel_expanded {
|
||||
Colors::fill_lite()
|
||||
if self.transport_content.qr_address_content.is_some() {
|
||||
Colors::FILL_DEEP
|
||||
} else {
|
||||
Colors::fill_lite()
|
||||
}
|
||||
} else {
|
||||
Colors::TRANSPARENT
|
||||
},
|
||||
@@ -302,7 +310,7 @@ impl Default for WalletContent {
|
||||
Self {
|
||||
txs_content: Some(WalletTransactionsContent::new(None)),
|
||||
settings_content: None,
|
||||
account_content: AccountContent::default(),
|
||||
account_content: WalletAccountContent::default(),
|
||||
transport_content: WalletTransportContent::default(),
|
||||
invoice_content: None,
|
||||
send_content: None,
|
||||
@@ -316,7 +324,7 @@ impl WalletContent {
|
||||
pub fn title(&self) -> impl Into<String> {
|
||||
if self.account_content.qr_scan_showing() {
|
||||
t!("scan_qr")
|
||||
} else if self.account_content.list_content.is_some() {
|
||||
} else if self.account_content.show_list {
|
||||
t!("wallets.accounts")
|
||||
} else if self.transport_content.settings_content.is_some() {
|
||||
t!("wallets.transport")
|
||||
@@ -378,8 +386,7 @@ impl WalletContent {
|
||||
self.settings_content = None;
|
||||
});
|
||||
});
|
||||
let active = if wallet.synced_from_node() &&
|
||||
has_wallet_data { Some(false) } else { None };
|
||||
let active = if has_wallet_data { Some(false) } else { None };
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
if wallet.invoice_creating() {
|
||||
ui.add_space(4.0);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
use egui::{Align, CornerRadius, Layout, RichText, StrokeKind};
|
||||
|
||||
use crate::AppConfig;
|
||||
use crate::gui::icons::{CIRCLE_HALF, DOTS_THREE_CIRCLE, PLUGS, PLUGS_CONNECTED, POWER, QR_CODE, SHIELD_CHECKERED, SHIELD_SLASH, WARNING_CIRCLE, WRENCH};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::wallets::wallet::transport::settings::WalletTransportSettingsContent;
|
||||
@@ -40,13 +41,10 @@ impl WalletContentContainer for WalletTransportContent {
|
||||
|
||||
fn container_ui(&mut self, ui: &mut egui::Ui, wallet: &Wallet, cb: &dyn PlatformCallbacks) {
|
||||
if let Some(content) = self.qr_address_content.as_mut() {
|
||||
// Close panel on wallet change.
|
||||
if let Some(address) = wallet.slatepack_address() {
|
||||
if address != content.text {
|
||||
self.qr_address_content = None;
|
||||
return;
|
||||
}
|
||||
}
|
||||
let dark_theme = AppConfig::dark_theme().unwrap_or(false);
|
||||
// Set light theme for better scanning.
|
||||
AppConfig::set_dark_theme(false);
|
||||
crate::setup_visuals(ui.ctx());
|
||||
// Draw QR code content.
|
||||
ui.add_space(6.0);
|
||||
content.ui(ui, cb);
|
||||
@@ -56,6 +54,9 @@ impl WalletContentContainer for WalletTransportContent {
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
// Set color theme back.
|
||||
AppConfig::set_dark_theme(dark_theme);
|
||||
crate::setup_visuals(ui.ctx());
|
||||
} else if let Some(content) = self.settings_content.as_mut() {
|
||||
let mut closed = false;
|
||||
content.ui(ui, wallet, cb, || {
|
||||
|
||||
@@ -52,7 +52,7 @@ impl WalletContentContainer for WalletTransactionsContent {
|
||||
match m.id {
|
||||
TX_INFO_MODAL => {
|
||||
if let Some(content) = self.tx_info_content.as_mut() {
|
||||
content.ui(ui, w, cb);
|
||||
content.ui(ui, m, w, cb);
|
||||
}
|
||||
}
|
||||
CANCEL_TX_CONFIRMATION_MODAL => {
|
||||
|
||||
@@ -19,6 +19,7 @@ use grin_util::ToHex;
|
||||
use grin_wallet_libwallet::TxLogEntryType;
|
||||
use std::fs;
|
||||
|
||||
use crate::AppConfig;
|
||||
use crate::gui::icons::{CIRCLE_HALF, COPY, CUBE, FILE_ARCHIVE, FILE_TEXT, HASH_STRAIGHT, PROHIBIT, QR_CODE, SEAL_CHECK};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::wallets::wallet::proof::PaymentProofContent;
|
||||
@@ -54,7 +55,11 @@ impl WalletTransactionContent {
|
||||
}
|
||||
|
||||
/// Draw [`Modal`] content.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, wallet: &Wallet, cb: &dyn PlatformCallbacks) {
|
||||
pub fn ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
modal: &Modal,
|
||||
wallet: &Wallet,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
// Check values and setup transaction data.
|
||||
let wallet_data = wallet.get_data();
|
||||
if wallet_data.is_none() {
|
||||
@@ -73,6 +78,12 @@ impl WalletTransactionContent {
|
||||
let tx = txs.get(0).unwrap();
|
||||
|
||||
if let Some(content) = self.qr_code_content.as_mut() {
|
||||
let dark_theme = AppConfig::dark_theme().unwrap_or(false);
|
||||
// Set light theme for better scanning.
|
||||
AppConfig::set_dark_theme(false);
|
||||
crate::setup_visuals(ui.ctx());
|
||||
modal.set_background_color(Colors::FILL_DEEP);
|
||||
|
||||
ui.add_space(6.0);
|
||||
content.ui(ui, cb);
|
||||
|
||||
@@ -93,7 +104,11 @@ impl WalletTransactionContent {
|
||||
});
|
||||
});
|
||||
});
|
||||
// Set color theme back.
|
||||
AppConfig::set_dark_theme(dark_theme);
|
||||
crate::setup_visuals(ui.ctx());
|
||||
} else {
|
||||
modal.set_background_color(Colors::fill());
|
||||
// Show transaction information.
|
||||
self.info_ui(ui, tx, wallet, cb);
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<?endif ?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*" Version="0.3.0" UpgradeCode="C19F9B41-CD13-4F0E-B27D-E0EF8CF1CE91" Language="1033" Name="Grim" Manufacturer="Ardocrat">
|
||||
<Product Id="*" Version="0.3.1" UpgradeCode="C19F9B41-CD13-4F0E-B27D-E0EF8CF1CE91" Language="1033" Name="Grim" Manufacturer="Ardocrat">
|
||||
<Package Id="FA6823B7-7FB1-49A4-BF64-0442BCD2724B" InstallerVersion="300" Compressed="yes"/>
|
||||
<Media Id="1" Cabinet="grim.cab" EmbedCab="yes" />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user