initial refactor in preparation for routing

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2024-05-27 12:22:40 -07:00
parent df0377cb89
commit 31b2b5c950
19 changed files with 332 additions and 587 deletions

View File

@@ -1,5 +1,4 @@
use crate::colors::PINK;
use crate::ui::global_popup::FromApp;
use crate::{
account_manager::AccountManager,
app_style::NotedeckTextStyle,
@@ -7,7 +6,6 @@ use crate::{
};
use egui::{Align, Button, Frame, Image, Layout, RichText, ScrollArea, Vec2};
use super::global_popup::GlobalPopupType;
use super::profile::preview::SimpleProfilePreview;
use super::profile::{ProfilePreviewOp, SimpleProfilePreviewController};
@@ -39,7 +37,7 @@ impl<'a> AccountManagementView<'a> {
fn show(&mut self, ui: &mut egui::Ui) {
Frame::none().outer_margin(24.0).show(ui, |ui| {
ui.add(self.top_section_buttons_widget());
self.top_section_buttons_widget(ui);
ui.add_space(8.0);
scroll_area().show(ui, |ui| {
self.show_accounts(ui);
@@ -86,8 +84,9 @@ impl<'a> AccountManagementView<'a> {
fn show_mobile(&mut self, ui: &mut egui::Ui) -> egui::Response {
egui::CentralPanel::default()
.show(ui.ctx(), |ui| {
ui.add(mobile_title());
ui.add(self.top_section_buttons_widget());
mobile_title(ui);
self.top_section_buttons_widget(ui);
ui.add_space(8.0);
scroll_area().show(ui, |ui| {
self.show_accounts_mobile(ui);
@@ -96,34 +95,32 @@ impl<'a> AccountManagementView<'a> {
.response
}
fn top_section_buttons_widget(&mut self) -> impl egui::Widget + '_ {
|ui: &mut egui::Ui| {
ui.horizontal(|ui| {
ui.allocate_ui_with_layout(
Vec2::new(ui.available_size_before_wrap().x, 32.0),
Layout::left_to_right(egui::Align::Center),
|ui| {
if ui.add(add_account_button()).clicked() {
// TODO: route to AccountLoginView
}
},
);
fn top_section_buttons_widget(&mut self, ui: &mut egui::Ui) -> egui::Response {
ui.horizontal(|ui| {
ui.allocate_ui_with_layout(
Vec2::new(ui.available_size_before_wrap().x, 32.0),
Layout::left_to_right(egui::Align::Center),
|ui| {
if ui.add(add_account_button()).clicked() {
// TODO: route to AccountLoginView
}
},
);
// UNCOMMENT FOR LOGOUTALL BUTTON
// ui.allocate_ui_with_layout(
// Vec2::new(ui.available_size_before_wrap().x, 32.0),
// Layout::right_to_left(egui::Align::Center),
// |ui| {
// if ui.add(logout_all_button()).clicked() {
// for index in (0..self.account_manager.num_accounts()).rev() {
// self.account_manager.remove_account(index);
// }
// }
// },
// );
})
.response
}
// UNCOMMENT FOR LOGOUTALL BUTTON
// ui.allocate_ui_with_layout(
// Vec2::new(ui.available_size_before_wrap().x, 32.0),
// Layout::right_to_left(egui::Align::Center),
// |ui| {
// if ui.add(logout_all_button()).clicked() {
// for index in (0..self.account_manager.num_accounts()).rev() {
// self.account_manager.remove_account(index);
// }
// }
// },
// );
})
.response
}
}
@@ -166,26 +163,15 @@ fn account_card_ui() -> fn(
}
}
impl<'a> FromApp<'a> for AccountManagementView<'a> {
fn from_app(app: &'a mut crate::Damus) -> Self {
AccountManagementView::new(
&mut app.account_manager,
SimpleProfilePreviewController::new(&app.ndb, &mut app.img_cache),
)
}
}
fn mobile_title() -> impl egui::Widget {
|ui: &mut egui::Ui| {
ui.vertical_centered(|ui| {
ui.label(
RichText::new(GlobalPopupType::AccountManagement.title())
.text_style(NotedeckTextStyle::Heading2.text_style())
.strong(),
);
})
.response
}
fn mobile_title(ui: &mut egui::Ui) -> egui::Response {
ui.vertical_centered(|ui| {
ui.label(
RichText::new("Account Management")
.text_style(NotedeckTextStyle::Heading2.text_style())
.strong(),
);
})
.response
}
fn scroll_area() -> ScrollArea {

View File

@@ -1,22 +1,43 @@
use crate::{account_manager::UserAccount, colors::PINK, ui};
use crate::{
account_manager::{AccountManager, UserAccount},
colors::PINK,
profile::DisplayName,
ui, Result,
};
use egui::{
Align, Button, Color32, Frame, Id, Image, Layout, Margin, RichText, Rounding, ScrollArea,
Sense, Vec2,
};
use crate::account_manager::AccountManager;
use super::{
profile::{preview::SimpleProfilePreview, SimpleProfilePreviewController},
state_in_memory::{STATE_ACCOUNT_MANAGEMENT, STATE_ACCOUNT_SWITCHER, STATE_SIDE_PANEL},
};
use super::profile::{preview::SimpleProfilePreview, SimpleProfilePreviewController};
pub struct AccountSelectionWidget<'a> {
account_manager: &'a mut AccountManager,
account_manager: &'a AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>,
}
enum AccountSelectAction {
RemoveAccount { index: usize },
SelectAccount { index: usize },
OpenAccountManagement,
}
#[derive(Default)]
struct AccountSelectResponse {
action: Option<AccountSelectAction>,
}
impl<'a> AccountSelectionWidget<'a> {
pub fn new(
account_manager: &'a AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>,
) -> Self {
AccountSelectionWidget {
account_manager,
simple_preview_controller,
}
}
pub fn ui(&'a mut self, ui: &mut egui::Ui) {
if ui::is_mobile() {
self.show_mobile(ui);
@@ -25,33 +46,43 @@ impl<'a> AccountSelectionWidget<'a> {
}
}
fn show(&mut self, ui: &mut egui::Ui) {
fn show(&mut self, ui: &mut egui::Ui) -> AccountSelectResponse {
let mut res = AccountSelectResponse::default();
let mut selected_index = self.account_manager.get_selected_account_index();
Frame::none().outer_margin(8.0).show(ui, |ui| {
ui.add(top_section_widget());
res = top_section_widget(ui);
scroll_area().show(ui, |ui| {
self.show_accounts(ui);
if let Some(index) = self.show_accounts(ui) {
selected_index = Some(index);
res.action = Some(AccountSelectAction::SelectAccount { index });
}
});
ui.add_space(8.0);
ui.add(add_account_button());
if let Some(account_index) = self.account_manager.get_selected_account_index() {
ui.add_space(8.0);
if self.handle_sign_out(ui, account_index) {
self.account_manager.remove_account(account_index);
if let Some(index) = selected_index {
if let Some(account) = self.account_manager.get_account(index) {
ui.add_space(8.0);
if self.handle_sign_out(ui, account) {
res.action = Some(AccountSelectAction::RemoveAccount { index })
}
}
}
ui.add_space(8.0);
});
res
}
fn handle_sign_out(&mut self, ui: &mut egui::Ui, account_index: usize) -> bool {
if let Some(account) = self.account_manager.get_account(account_index) {
if let Some(response) = self.sign_out_button(ui, account) {
return response.clicked();
}
fn handle_sign_out(&mut self, ui: &mut egui::Ui, account: &UserAccount) -> bool {
if let Ok(response) = self.sign_out_button(ui, account) {
response.clicked()
} else {
false
}
false
}
fn show_mobile(&mut self, ui: &mut egui::Ui) -> egui::Response {
@@ -59,19 +90,19 @@ impl<'a> AccountSelectionWidget<'a> {
todo!()
}
fn show_accounts(&mut self, ui: &mut egui::Ui) {
fn show_accounts(&mut self, ui: &mut egui::Ui) -> Option<usize> {
self.simple_preview_controller.view_profile_previews(
self.account_manager,
ui,
account_switcher_card_ui(),
);
)
}
fn sign_out_button(&self, ui: &mut egui::Ui, account: &UserAccount) -> Option<egui::Response> {
fn sign_out_button(&self, ui: &mut egui::Ui, account: &UserAccount) -> Result<egui::Response> {
self.simple_preview_controller.show_with_nickname(
ui,
&account.key.pubkey,
|ui, username| {
account.pubkey.bytes(),
|ui: &mut egui::Ui, username: &DisplayName| {
let img_data = egui::include_image!("../../assets/icons/signout_icon_4x.png");
let img = Image::new(img_data).fit_to_exact_size(Vec2::new(16.0, 16.0));
let button = egui::Button::image_and_text(
@@ -88,18 +119,6 @@ impl<'a> AccountSelectionWidget<'a> {
}
}
impl<'a> AccountSelectionWidget<'a> {
pub fn new(
account_manager: &'a mut AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>,
) -> Self {
AccountSelectionWidget {
account_manager,
simple_preview_controller,
}
}
}
fn account_switcher_card_ui() -> fn(
ui: &mut egui::Ui,
preview: SimpleProfilePreview,
@@ -147,32 +166,29 @@ fn selection_widget() -> impl egui::Widget {
}
}
fn top_section_widget() -> impl egui::Widget {
|ui: &mut egui::Ui| {
ui.horizontal(|ui| {
ui.allocate_ui_with_layout(
Vec2::new(ui.available_size_before_wrap().x, 32.0),
Layout::left_to_right(egui::Align::Center),
|ui| ui.add(account_switcher_title()),
);
fn top_section_widget(ui: &mut egui::Ui) -> AccountSelectResponse {
ui.horizontal(|ui| {
let mut resp = AccountSelectResponse::default();
ui.allocate_ui_with_layout(
Vec2::new(ui.available_size_before_wrap().x, 32.0),
Layout::right_to_left(egui::Align::Center),
|ui| {
if ui.add(manage_accounts_button()).clicked() {
STATE_ACCOUNT_SWITCHER.set_state(ui.ctx(), false);
STATE_SIDE_PANEL.set_state(
ui.ctx(),
Some(ui::global_popup::GlobalPopupType::AccountManagement),
);
STATE_ACCOUNT_MANAGEMENT.set_state(ui.ctx(), true);
}
},
);
})
.response
}
ui.allocate_ui_with_layout(
Vec2::new(ui.available_size_before_wrap().x, 32.0),
Layout::left_to_right(egui::Align::Center),
|ui| ui.add(account_switcher_title()),
);
ui.allocate_ui_with_layout(
Vec2::new(ui.available_size_before_wrap().x, 32.0),
Layout::right_to_left(egui::Align::Center),
|ui| {
if ui.add(manage_accounts_button()).clicked() {
resp.action = Some(AccountSelectAction::OpenAccountManagement);
}
},
);
resp
})
.inner
}
fn manage_accounts_button() -> egui::Button<'static> {
@@ -227,7 +243,7 @@ mod previews {
impl View for AccountSelectionPreview {
fn ui(&mut self, ui: &mut egui::Ui) {
AccountSelectionWidget::new(
&mut self.account_manager,
&self.account_manager,
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
)
.ui(ui);

View File

@@ -1,168 +0,0 @@
use egui::{Align2, CentralPanel, RichText, Vec2, Window};
use crate::Damus;
use super::{
profile::SimpleProfilePreviewController,
state_in_memory::{STATE_ACCOUNT_MANAGEMENT, STATE_ACCOUNT_SWITCHER, STATE_SIDE_PANEL},
AccountManagementView, AccountSelectionWidget, View,
};
#[derive(Clone, Copy, Debug)]
pub enum GlobalPopupType {
AccountManagement,
AccountSwitcher,
}
static ACCOUNT_MANAGEMENT_TITLE: &str = "Manage accounts";
static ACCOUNT_SWITCHER_TITLE: &str = "Account switcher";
impl GlobalPopupType {
pub fn title(&self) -> &'static str {
match self {
Self::AccountManagement => ACCOUNT_MANAGEMENT_TITLE,
Self::AccountSwitcher => ACCOUNT_SWITCHER_TITLE,
}
}
}
pub trait FromApp<'a> {
fn from_app(app: &'a mut crate::Damus) -> Self
where
Self: Sized;
}
fn title(title_str: &'static str) -> RichText {
RichText::new(title_str).size(24.0)
}
fn overlay_window<'a>(
open: &'a mut bool,
window_size: Vec2,
title_str: &'static str,
) -> Window<'a> {
egui::Window::new(title(title_str))
.anchor(Align2::CENTER_CENTER, [0.0, 0.0])
.collapsible(false)
.auto_sized()
.movable(false)
.open(open)
.default_size(window_size)
}
fn account_switcher_window(open: &'_ mut bool) -> Window<'_> {
egui::Window::new("account switcher")
.title_bar(false)
.collapsible(false)
.anchor(Align2::LEFT_BOTTOM, Vec2::new(0.0, -52.0))
.fixed_size(Vec2::new(360.0, 406.0))
.open(open)
.movable(false)
}
static MARGIN: Vec2 = Vec2 { x: 100.0, y: 100.0 };
pub struct DesktopGlobalPopup<'a> {
app: &'a mut Damus,
}
impl<'a> View for DesktopGlobalPopup<'a> {
fn ui(&mut self, ui: &mut egui::Ui) {
DesktopGlobalPopup::global_popup(self.app, ui.ctx())
}
}
impl<'a> DesktopGlobalPopup<'a> {
pub fn new(app: &'a mut Damus) -> Self {
DesktopGlobalPopup { app }
}
pub fn global_popup(app: &mut Damus, ctx: &egui::Context) {
CentralPanel::default().show(ctx, |ui| {
if let Some(popup) = STATE_SIDE_PANEL.get_state(ctx) {
match popup {
GlobalPopupType::AccountManagement => {
Self::account_management(app, ctx, ui, popup.title());
}
GlobalPopupType::AccountSwitcher => {
let mut show_account_switcher = STATE_ACCOUNT_SWITCHER.get_state(ctx);
if show_account_switcher {
STATE_ACCOUNT_MANAGEMENT.set_state(ctx, false);
account_switcher_window(&mut show_account_switcher).show(ctx, |ui| {
AccountSelectionWidget::new(
&mut app.account_manager,
SimpleProfilePreviewController::new(
&app.ndb,
&mut app.img_cache,
),
)
.ui(ui);
});
}
}
}
}
});
}
fn account_management(
app: &mut Damus,
ctx: &egui::Context,
ui: &mut egui::Ui,
title: &'static str,
) {
let available_size = ui.available_size();
let window_size = available_size - MARGIN;
let mut show_account_management = STATE_ACCOUNT_MANAGEMENT.get_state(ctx);
if show_account_management {
overlay_window(&mut show_account_management, window_size, title).show(ctx, |ui| {
AccountManagementView::from_app(app).ui(ui);
});
// user could have closed the window, set the new state in egui memory
STATE_ACCOUNT_MANAGEMENT.set_state(ctx, show_account_management);
}
}
}
mod preview {
use crate::{
test_data,
ui::{profile::SimpleProfilePreviewController, DesktopSidePanel, Preview, View},
Damus,
};
use super::DesktopGlobalPopup;
pub struct GlobalPopupPreview {
app: Damus,
}
impl<'a> Preview for DesktopGlobalPopup<'a> {
type Prev = GlobalPopupPreview;
fn preview() -> Self::Prev {
GlobalPopupPreview::new()
}
}
impl GlobalPopupPreview {
fn new() -> Self {
let mut app = Damus::mock(".");
let accounts = test_data::get_test_accounts();
accounts
.into_iter()
.for_each(|acc| app.account_manager.add_account(acc.key, || {}));
GlobalPopupPreview { app }
}
}
impl View for GlobalPopupPreview {
fn ui(&mut self, ui: &mut egui::Ui) {
let mut panel = DesktopSidePanel::new(
&mut self.app.account_manager,
SimpleProfilePreviewController::new(&self.app.ndb, &mut self.app.img_cache),
);
DesktopSidePanel::panel().show(ui.ctx(), |ui| panel.ui(ui));
DesktopGlobalPopup::new(&mut self.app).ui(ui);
}
}
}

View File

@@ -2,19 +2,16 @@ pub mod account_login_view;
pub mod account_management;
pub mod account_switcher;
pub mod anim;
pub mod global_popup;
pub mod mention;
pub mod note;
pub mod preview;
pub mod profile;
pub mod relay;
pub mod side_panel;
pub mod state_in_memory;
pub mod username;
pub use account_management::AccountManagementView;
pub use account_switcher::AccountSelectionWidget;
pub use global_popup::DesktopGlobalPopup;
pub use mention::Mention;
pub use note::Note;
pub use preview::{Preview, PreviewApp};

View File

@@ -1,10 +1,6 @@
use enostr::Pubkey;
use nostrdb::{Ndb, Transaction};
use crate::{
account_manager::AccountManager, imgcache::ImageCache,
ui::state_in_memory::STATE_ACCOUNT_SWITCHER, DisplayName,
};
use crate::{account_manager::AccountManager, imgcache::ImageCache, DisplayName, Result};
use super::{
preview::{get_display_name, get_profile_url, SimpleProfilePreview},
@@ -42,36 +38,48 @@ impl<'a> SimpleProfilePreviewController<'a> {
let width = ui.available_width();
let txn = if let Ok(txn) = Transaction::new(self.ndb) {
txn
} else {
return None;
};
for i in 0..account_manager.num_accounts() {
if let Some(account) = account_manager.get_account(i) {
if let Ok(txn) = Transaction::new(self.ndb) {
let profile = self
.ndb
.get_profile_by_pubkey(&txn, account.key.pubkey.bytes());
let account = if let Some(account) = account_manager.get_account(i) {
account
} else {
continue;
};
if let Ok(profile) = profile {
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
let profile =
if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, account.pubkey.bytes()) {
profile
} else {
continue;
};
let is_selected =
if let Some(selected) = account_manager.get_selected_account_index() {
i == selected
} else {
false
};
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
if let Some(op) = add_preview_ui(ui, preview, width, is_selected) {
match op {
ProfilePreviewOp::RemoveAccount => {
if to_remove.is_none() {
to_remove = Some(Vec::new());
}
to_remove.as_mut().unwrap().push(i);
}
ProfilePreviewOp::SwitchTo => account_manager.select_account(i),
}
}
};
let is_selected = if let Some(selected) = account_manager.get_selected_account_index() {
i == selected
} else {
false
};
let op = if let Some(op) = add_preview_ui(ui, preview, width, is_selected) {
op
} else {
continue;
};
match op {
ProfilePreviewOp::RemoveAccount => {
if to_remove.is_none() {
to_remove = Some(Vec::new());
}
to_remove.as_mut().unwrap().push(i);
}
ProfilePreviewOp::SwitchTo => account_manager.select_account(i),
}
}
@@ -80,7 +88,7 @@ impl<'a> SimpleProfilePreviewController<'a> {
pub fn view_profile_previews(
&mut self,
account_manager: &mut AccountManager,
account_manager: &AccountManager,
ui: &mut egui::Ui,
add_preview_ui: fn(
ui: &mut egui::Ui,
@@ -89,60 +97,64 @@ impl<'a> SimpleProfilePreviewController<'a> {
is_selected: bool,
index: usize,
) -> bool,
) {
) -> Option<usize> {
let width = ui.available_width();
let txn = if let Ok(txn) = Transaction::new(self.ndb) {
txn
} else {
return None;
};
for i in 0..account_manager.num_accounts() {
if let Some(account) = account_manager.get_account(i) {
if let Ok(txn) = Transaction::new(self.ndb) {
let profile = self
.ndb
.get_profile_by_pubkey(&txn, account.key.pubkey.bytes());
let account = if let Some(account) = account_manager.get_account(i) {
account
} else {
continue;
};
if let Ok(profile) = profile {
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
let profile =
if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, account.pubkey.bytes()) {
profile
} else {
continue;
};
let is_selected =
if let Some(selected) = account_manager.get_selected_account_index() {
i == selected
} else {
false
};
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
if add_preview_ui(ui, preview, width, is_selected, i) {
account_manager.select_account(i);
STATE_ACCOUNT_SWITCHER.set_state(ui.ctx(), false);
}
}
}
let is_selected = if let Some(selected) = account_manager.get_selected_account_index() {
i == selected
} else {
false
};
if add_preview_ui(ui, preview, width, is_selected, i) {
return Some(i);
}
}
None
}
pub fn show_with_nickname(
&self,
ui: &mut egui::Ui,
key: &Pubkey,
key: &[u8; 32],
ui_element: fn(ui: &mut egui::Ui, username: &DisplayName) -> egui::Response,
) -> Option<egui::Response> {
if let Ok(txn) = Transaction::new(self.ndb) {
let profile = self.ndb.get_profile_by_pubkey(&txn, key.bytes());
if let Ok(profile) = profile {
return Some(ui_element(ui, &get_display_name(&profile)));
}
}
None
) -> Result<egui::Response> {
let txn = Transaction::new(self.ndb)?;
let profile = self.ndb.get_profile_by_pubkey(&txn, key)?;
Ok(ui_element(ui, &get_display_name(&profile)))
}
pub fn show_with_pfp(
&mut self,
self,
ui: &mut egui::Ui,
key: &Pubkey,
key: &[u8; 32],
ui_element: fn(ui: &mut egui::Ui, pfp: ProfilePic) -> egui::Response,
) -> Option<egui::Response> {
if let Ok(txn) = Transaction::new(self.ndb) {
let profile = self.ndb.get_profile_by_pubkey(&txn, key.bytes());
let profile = self.ndb.get_profile_by_pubkey(&txn, key);
if let Ok(profile) = profile {
return Some(ui_element(

View File

@@ -1,72 +1,75 @@
use egui::{Button, Layout, SidePanel, Vec2, Widget};
use crate::{account_manager::AccountManager, ui::global_popup::GlobalPopupType};
use crate::account_manager::AccountManager;
use super::{
profile::SimpleProfilePreviewController,
state_in_memory::{STATE_ACCOUNT_SWITCHER, STATE_SIDE_PANEL},
ProfilePic, View,
};
use super::{profile::SimpleProfilePreviewController, ProfilePic, View};
pub struct DesktopSidePanel<'a> {
account_manager: &'a mut AccountManager,
selected_account: Option<&'a [u8; 32]>,
simple_preview_controller: SimpleProfilePreviewController<'a>,
}
static ID: &str = "left panel";
impl<'a> View for DesktopSidePanel<'a> {
fn ui(&mut self, ui: &mut egui::Ui) {
self.inner(ui);
impl<'a> Widget for DesktopSidePanel<'a> {
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
self.show(ui)
}
}
impl<'a> DesktopSidePanel<'a> {
pub fn new(
account_manager: &'a mut AccountManager,
selected_account: Option<&'a [u8; 32]>,
simple_preview_controller: SimpleProfilePreviewController<'a>,
) -> Self {
DesktopSidePanel {
account_manager,
selected_account,
simple_preview_controller,
}
}
pub fn inner(&mut self, ui: &mut egui::Ui) {
let dark_mode = ui.ctx().style().visuals.dark_mode;
let spacing_amt = 16.0;
ui.with_layout(Layout::bottom_up(egui::Align::Center), |ui| {
ui.add_space(spacing_amt);
if self.pfp_button(ui).clicked() {
STATE_SIDE_PANEL.set_state(ui.ctx(), Some(GlobalPopupType::AccountSwitcher));
let previous_val = STATE_ACCOUNT_SWITCHER.get_state(ui.ctx());
STATE_ACCOUNT_SWITCHER.set_state(ui.ctx(), !previous_val);
}
ui.add_space(spacing_amt);
ui.add(settings_button(dark_mode));
ui.add_space(spacing_amt);
ui.add(add_column_button(dark_mode));
ui.add_space(spacing_amt);
});
pub fn panel() -> SidePanel {
egui::SidePanel::left("side_panel")
.resizable(false)
.exact_width(40.0)
}
fn pfp_button(&mut self, ui: &mut egui::Ui) -> egui::Response {
if let Some(selected_account) = self.account_manager.get_selected_account() {
if let Some(response) = self.simple_preview_controller.show_with_pfp(
ui,
&selected_account.key.pubkey,
show_pfp(),
) {
pub fn show(self, ui: &mut egui::Ui) -> egui::Response {
let dark_mode = ui.ctx().style().visuals.dark_mode;
let spacing_amt = 16.0;
let inner = ui
.with_layout(Layout::bottom_up(egui::Align::Center), |ui| {
ui.spacing_mut().item_spacing.y = spacing_amt;
let pfp_resp = self.pfp_button(ui);
let settings_resp = ui.add(settings_button(dark_mode));
let column_resp = ui.add(add_column_button(dark_mode));
if pfp_resp.clicked() || pfp_resp.hovered() {
egui::InnerResponse::new(SidePanelAction::Account, pfp_resp)
} else if settings_resp.clicked() || settings_resp.hovered() {
egui::InnerResponse::new(SidePanelAction::Settings, settings_resp)
} else if column_resp.clicked() || column_resp.hovered() {
egui::InnerResponse::new(SidePanelAction::Columns, column_resp)
} else {
egui::InnerResponse::new(SidePanelAction::Panel, pfp_resp)
}
})
.inner;
SidePanelResponse::new(inner.inner, inner.response)
}
fn pfp_button(self, ui: &mut egui::Ui) -> egui::Response {
if let Some(selected_account) = self.selected_account {
if let Some(response) =
self.simple_preview_controller
.show_with_pfp(ui, selected_account, show_pfp())
{
return response;
}
}
add_button_to_ui(ui, no_account_pfp())
}
pub fn panel() -> SidePanel {
egui::SidePanel::left(ID).resizable(false).exact_width(40.0)
}
}
fn show_pfp() -> fn(ui: &mut egui::Ui, pfp: ProfilePic) -> egui::Response {
@@ -126,10 +129,16 @@ mod preview {
impl View for DesktopSidePanelPreview {
fn ui(&mut self, ui: &mut egui::Ui) {
let mut panel = DesktopSidePanel::new(
&mut self.account_manager,
let selected_account = self
.account_manager
.get_selected_account()
.map(|x| x.pubkey.bytes());
let panel = DesktopSidePanel::new(
selected_account,
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
);
DesktopSidePanel::panel().show(ui.ctx(), |ui| panel.ui(ui));
}
}

View File

@@ -1,43 +0,0 @@
use std::any::Any;
use super::global_popup::GlobalPopupType;
/// StateInMemory is a helper struct for interacting with egui memory persisted data
#[derive(Clone)]
pub struct StateInMemory<T: 'static + Clone + Send> {
id: &'static str,
default_state: T,
}
impl<T: 'static + Any + Clone + Send + Sync> StateInMemory<T> {
pub fn get_state(&self, ctx: &egui::Context) -> T {
ctx.data_mut(|d| {
d.get_temp(egui::Id::new(self.id))
.unwrap_or(self.default_state.clone())
})
}
pub fn set_state(&self, ctx: &egui::Context, new_val: T) {
ctx.data_mut(|d| d.insert_temp(egui::Id::new(self.id), new_val));
}
}
pub static STATE_ACCOUNT_MANAGEMENT: StateInMemory<bool> = StateInMemory::<bool> {
id: ACCOUNT_MANAGEMENT_VIEW_STATE_ID,
default_state: false,
};
pub static STATE_SIDE_PANEL: StateInMemory<Option<GlobalPopupType>> =
StateInMemory::<Option<GlobalPopupType>> {
id: SIDE_PANEL_VIEW_STATE_ID,
default_state: None,
};
pub static STATE_ACCOUNT_SWITCHER: StateInMemory<bool> = StateInMemory::<bool> {
id: ACCOUNT_SWITCHER_VIEW_STATE_ID,
default_state: false,
};
static ACCOUNT_MANAGEMENT_VIEW_STATE_ID: &str = "account management view state";
static SIDE_PANEL_VIEW_STATE_ID: &str = "side panel view state";
static ACCOUNT_SWITCHER_VIEW_STATE_ID: &str = "account switcher view state";