diff --git a/src/ui/components/tokens_subscreen_chooser_panel.rs b/src/ui/components/tokens_subscreen_chooser_panel.rs index 2a1c92b53..6f1cf8e36 100644 --- a/src/ui/components/tokens_subscreen_chooser_panel.rs +++ b/src/ui/components/tokens_subscreen_chooser_panel.rs @@ -52,17 +52,19 @@ pub fn add_tokens_subscreen_chooser_panel(ctx: &Context, app_context: &AppContex // Handle navigation based on which subscreen is selected match subscreen { TokensSubscreen::MyTokens => { - action = AppAction::SetMainScreen( + action = AppAction::SetMainScreenThenGoToMainScreen( RootScreenType::RootScreenMyTokenBalances, ) } TokensSubscreen::SearchTokens => { - action = - AppAction::SetMainScreen(RootScreenType::RootScreenTokenSearch) + action = AppAction::SetMainScreenThenGoToMainScreen( + RootScreenType::RootScreenTokenSearch, + ) } TokensSubscreen::TokenCreator => { - action = - AppAction::SetMainScreen(RootScreenType::RootScreenTokenCreator) + action = AppAction::SetMainScreenThenGoToMainScreen( + RootScreenType::RootScreenTokenCreator, + ) } } } diff --git a/src/ui/tokens/add_token_by_id_screen.rs b/src/ui/tokens/add_token_by_id_screen.rs index 18ca57066..e41466992 100644 --- a/src/ui/tokens/add_token_by_id_screen.rs +++ b/src/ui/tokens/add_token_by_id_screen.rs @@ -12,6 +12,8 @@ use eframe::egui::{self, Color32, Context, RichText, Ui}; use crate::backend_task::contract::ContractTask; use crate::backend_task::BackendTaskSuccessResult; use crate::database::contracts::InsertTokensToo; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::tokens::tokens_screen::TokenInfo; use crate::{ app::AppAction, @@ -217,6 +219,16 @@ impl ScreenLike for AddTokenByIdScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { ui.heading("Add Token"); ui.add_space(10.0); diff --git a/src/ui/tokens/burn_tokens_screen.rs b/src/ui/tokens/burn_tokens_screen.rs index 662ee629c..e672de52a 100644 --- a/src/ui/tokens/burn_tokens_screen.rs +++ b/src/ui/tokens/burn_tokens_screen.rs @@ -7,6 +7,8 @@ use dash_sdk::dpp::platform_value::string_encoding::Encoding; use eframe::egui::{self, Color32, Context, Ui}; use egui::RichText; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use dash_sdk::dpp::identity::accessors::IdentityGettersV0; use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dash_sdk::dpp::identity::{KeyType, Purpose, SecurityLevel}; @@ -280,6 +282,16 @@ impl ScreenLike for BurnTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { // If we are in the "Complete" status, just show success screen if self.status == BurnTokensStatus::Complete { diff --git a/src/ui/tokens/claim_tokens_screen.rs b/src/ui/tokens/claim_tokens_screen.rs index e8349ae2e..e50fb9b6c 100644 --- a/src/ui/tokens/claim_tokens_screen.rs +++ b/src/ui/tokens/claim_tokens_screen.rs @@ -1,3 +1,5 @@ +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use std::collections::HashSet; use std::sync::{Arc, RwLock}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -315,6 +317,16 @@ impl ScreenLike for ClaimTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { if self.status == ClaimTokensStatus::Complete { action = self.show_success_screen(ui); diff --git a/src/ui/tokens/destroy_frozen_funds_screen.rs b/src/ui/tokens/destroy_frozen_funds_screen.rs index 22111c37d..cdf309b8b 100644 --- a/src/ui/tokens/destroy_frozen_funds_screen.rs +++ b/src/ui/tokens/destroy_frozen_funds_screen.rs @@ -7,6 +7,8 @@ use dash_sdk::dpp::platform_value::string_encoding::Encoding; use eframe::egui::{self, Color32, Context, Ui}; use egui::RichText; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use dash_sdk::dpp::identity::accessors::IdentityGettersV0; use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dash_sdk::dpp::identity::{KeyType, Purpose, SecurityLevel}; @@ -299,6 +301,16 @@ impl ScreenLike for DestroyFrozenFundsScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { if self.status == DestroyFrozenFundsStatus::Complete { action = self.show_success_screen(ui); diff --git a/src/ui/tokens/freeze_tokens_screen.rs b/src/ui/tokens/freeze_tokens_screen.rs index da55ece1d..314c1577b 100644 --- a/src/ui/tokens/freeze_tokens_screen.rs +++ b/src/ui/tokens/freeze_tokens_screen.rs @@ -18,6 +18,8 @@ use crate::backend_task::BackendTask; use crate::context::AppContext; use crate::model::qualified_identity::QualifiedIdentity; use crate::model::wallet::Wallet; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::components::wallet_unlock::ScreenWithWalletUnlock; use crate::ui::identities::get_selected_wallet; @@ -277,6 +279,16 @@ impl ScreenLike for FreezeTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { if self.status == FreezeTokensStatus::Complete { action = self.show_success_screen(ui); diff --git a/src/ui/tokens/mint_tokens_screen.rs b/src/ui/tokens/mint_tokens_screen.rs index 071f0230d..ae566906e 100644 --- a/src/ui/tokens/mint_tokens_screen.rs +++ b/src/ui/tokens/mint_tokens_screen.rs @@ -19,6 +19,8 @@ use crate::backend_task::BackendTask; use crate::context::AppContext; use crate::model::qualified_identity::QualifiedIdentity; use crate::model::wallet::Wallet; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::components::wallet_unlock::ScreenWithWalletUnlock; use crate::ui::identities::get_selected_wallet; @@ -325,6 +327,16 @@ impl ScreenLike for MintTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { // If we are in the "Complete" status, just show success screen if self.status == MintTokensStatus::Complete { diff --git a/src/ui/tokens/pause_tokens_screen.rs b/src/ui/tokens/pause_tokens_screen.rs index 0a069a6a5..84b36002e 100644 --- a/src/ui/tokens/pause_tokens_screen.rs +++ b/src/ui/tokens/pause_tokens_screen.rs @@ -17,6 +17,8 @@ use crate::backend_task::BackendTask; use crate::context::AppContext; use crate::model::qualified_identity::QualifiedIdentity; use crate::model::wallet::Wallet; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::components::wallet_unlock::ScreenWithWalletUnlock; use crate::ui::identities::get_selected_wallet; @@ -241,6 +243,16 @@ impl ScreenLike for PauseTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { if self.status == PauseTokensStatus::Complete { action = self.show_success_screen(ui); diff --git a/src/ui/tokens/resume_tokens_screen.rs b/src/ui/tokens/resume_tokens_screen.rs index 5bbd5dfc5..18f2f2785 100644 --- a/src/ui/tokens/resume_tokens_screen.rs +++ b/src/ui/tokens/resume_tokens_screen.rs @@ -17,6 +17,8 @@ use crate::backend_task::BackendTask; use crate::context::AppContext; use crate::model::qualified_identity::QualifiedIdentity; use crate::model::wallet::Wallet; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::components::wallet_unlock::ScreenWithWalletUnlock; use crate::ui::identities::get_selected_wallet; @@ -237,6 +239,16 @@ impl ScreenLike for ResumeTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { if self.status == ResumeTokensStatus::Complete { action = self.show_success_screen(ui); diff --git a/src/ui/tokens/transfer_tokens_screen.rs b/src/ui/tokens/transfer_tokens_screen.rs index 57944fbb1..b7bbdad8b 100644 --- a/src/ui/tokens/transfer_tokens_screen.rs +++ b/src/ui/tokens/transfer_tokens_screen.rs @@ -4,6 +4,8 @@ use crate::backend_task::BackendTask; use crate::context::AppContext; use crate::model::qualified_identity::QualifiedIdentity; use crate::model::wallet::Wallet; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::identities::keys::add_key_screen::AddKeyScreen; use crate::ui::identities::keys::key_info_screen::KeyInfoScreen; @@ -321,6 +323,16 @@ impl ScreenLike for TransferTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { // Show the success screen if the transfer was successful if self.transfer_tokens_status == TransferTokensStatus::Complete { diff --git a/src/ui/tokens/unfreeze_tokens_screen.rs b/src/ui/tokens/unfreeze_tokens_screen.rs index 43b33d5a5..c6e7e6652 100644 --- a/src/ui/tokens/unfreeze_tokens_screen.rs +++ b/src/ui/tokens/unfreeze_tokens_screen.rs @@ -18,6 +18,8 @@ use crate::backend_task::BackendTask; use crate::context::AppContext; use crate::model::qualified_identity::QualifiedIdentity; use crate::model::wallet::Wallet; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::components::wallet_unlock::ScreenWithWalletUnlock; use crate::ui::identities::get_selected_wallet; @@ -273,6 +275,16 @@ impl ScreenLike for UnfreezeTokensScreen { vec![], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + egui::CentralPanel::default().show(ctx, |ui| { if self.status == UnfreezeTokensStatus::Complete { action = self.show_success_screen(ui); diff --git a/src/ui/tokens/view_token_claims_screen.rs b/src/ui/tokens/view_token_claims_screen.rs index 49ff1ac2e..9f15ce4c8 100644 --- a/src/ui/tokens/view_token_claims_screen.rs +++ b/src/ui/tokens/view_token_claims_screen.rs @@ -2,14 +2,17 @@ use crate::app::{AppAction, DesiredAppAction}; use crate::backend_task::document::DocumentTask; use crate::backend_task::{BackendTask, BackendTaskSuccessResult}; use crate::context::AppContext; +use crate::ui::components::left_panel::add_left_panel; +use crate::ui::components::tokens_subscreen_chooser_panel::add_tokens_subscreen_chooser_panel; use crate::ui::components::top_panel::add_top_panel; use crate::ui::{MessageType, ScreenLike}; use chrono::{DateTime, Utc}; use dash_sdk::dpp::document::DocumentV0Getters; use dash_sdk::dpp::platform_value::Value; +use dash_sdk::drive::query::{WhereClause, WhereOperator}; use dash_sdk::platform::{Document, DocumentQuery}; -use egui::Color32; use egui::Context; +use egui::{Color32, RichText}; use std::sync::Arc; use super::tokens_screen::IdentityTokenBalance; @@ -26,6 +29,7 @@ pub struct ViewTokenClaimsScreen { message: Option<(String, MessageType, DateTime)>, fetch_status: FetchStatus, pub app_context: Arc, + claims: Vec, } impl ViewTokenClaimsScreen { @@ -34,11 +38,22 @@ impl ViewTokenClaimsScreen { app_context: &Arc, ) -> Self { Self { - identity_token_balance, + identity_token_balance: identity_token_balance.clone(), new_claims_query: DocumentQuery { data_contract: app_context.token_history_contract.clone(), document_type_name: "claim".to_string(), - where_clauses: vec![], + where_clauses: vec![ + WhereClause { + field: "tokenId".to_string(), + operator: WhereOperator::Equal, + value: Value::Identifier(identity_token_balance.token_id.into()), + }, + WhereClause { + field: "recipientId".to_string(), + operator: WhereOperator::Equal, + value: Value::Identifier(identity_token_balance.identity_id.into()), + }, + ], order_by_clauses: vec![], limit: 0, start: None, @@ -46,6 +61,7 @@ impl ViewTokenClaimsScreen { message: None, fetch_status: FetchStatus::NotFetching, app_context: app_context.clone(), + claims: vec![], } } } @@ -72,35 +88,9 @@ impl ScreenLike for ViewTokenClaimsScreen { match backend_task_success_result { BackendTaskSuccessResult::Documents(documents) => { self.fetch_status = FetchStatus::NotFetching; - if !documents.is_empty() { - let claims: Vec = - documents.into_iter().filter_map(|(_, doc)| doc).collect(); - let documents_string = claims - .iter() - .map(|doc| { - let amount_string = doc - .get("amount") - .unwrap_or(&Value::Text("None".to_string())) - .to_string(); - let timestamp_string = doc.created_at().unwrap_or_default().to_string(); - let block_height_string = doc - .created_at_block_height() - .unwrap_or_default() - .to_string(); - let note_string = doc - .get("note") - .unwrap_or(&Value::Text("None".to_string())) - .to_string(); - - format!( - "Claim: Amount: {}, Timestamp: {}, Block Height: {}, Note: {}", - amount_string, timestamp_string, block_height_string, note_string - ) - }) - .collect::>() - .join("\n"); - self.display_message(&documents_string, MessageType::Info); - } else { + self.claims = documents.into_iter().filter_map(|(_, doc)| doc).collect(); + + if self.claims.is_empty() { self.display_message("No claims found", MessageType::Info); } } @@ -109,6 +99,7 @@ impl ScreenLike for ViewTokenClaimsScreen { } fn ui(&mut self, ctx: &Context) -> AppAction { + // Top panel let mut action = add_top_panel( ctx, &self.app_context, @@ -128,11 +119,28 @@ impl ScreenLike for ViewTokenClaimsScreen { )], ); + // Left panel + action |= add_left_panel( + ctx, + &self.app_context, + crate::ui::RootScreenType::RootScreenMyTokenBalances, + ); + + // Subscreen chooser + action |= add_tokens_subscreen_chooser_panel(ctx, &self.app_context); + + // Central panel egui::CentralPanel::default().show(ctx, |ui| { ui.heading("View Token Claims"); ui.add_space(10.0); - if ui.button("Fetch Claims").clicked() { + let fetch_button = + egui::Button::new(RichText::new("Fetch claims").color(Color32::WHITE)) + .fill(Color32::from_rgb(0, 128, 255)) + .frame(true) + .corner_radius(3.0); + + if ui.add(fetch_button).clicked() { action |= AppAction::BackendTask(BackendTask::DocumentTask( DocumentTask::FetchDocuments(self.new_claims_query.clone()), )); @@ -164,6 +172,70 @@ impl ScreenLike for ViewTokenClaimsScreen { _ => {} } } + + ui.add_space(10.0); + + if !self.claims.is_empty() { + egui::ScrollArea::both() + .auto_shrink([false; 2]) + .show(ui, |ui| { + egui::Grid::new("claims_table") + .striped(true) + .spacing([20.0, 8.0]) + .show(ui, |ui| { + // Header + ui.label("Amount"); + ui.label("Timestamp"); + ui.label("Block Height"); + ui.label("Note"); + ui.end_row(); + + for claim in &self.claims { + // Amount + let amount = match claim.get("amount") { + Some(Value::U64(amount)) => format!("{}", amount), + Some(Value::I64(amount)) => format!("{}", amount), + Some(Value::Text(s)) => s.clone(), + Some(other) => other.to_string(), + None => "None".to_string(), + }; + + // Timestamp + let timestamp = match claim.created_at() { + Some(ts) => { + let dt = chrono::NaiveDateTime::from_timestamp_millis( + ts as i64, + ) + .unwrap_or_else(|| { + chrono::NaiveDateTime::from_timestamp(0, 0) + }); + dt.format("%Y-%m-%d %H:%M:%S").to_string() + } + None => "Unknown".to_string(), + }; + + // Block Height + let block_height = claim + .created_at_block_height() + .map(|h| h.to_string()) + .unwrap_or_else(|| "Unknown".to_string()); + + // Note + let note = match claim.get("note") { + Some(Value::Text(note)) => note.clone(), + Some(other) => other.to_string(), + None => "".to_string(), + }; + + ui.label(amount); + ui.label(timestamp); + ui.label(block_height); + ui.label(note); + ui.end_row(); + } + }); + }); + } }); action