commit 56a8ba30f33169ea519d882d377fbef00a24b1d4
parent 845a983592e536ec2393eabd5e955ccc4189ed2b
Author: kernelkind <kernelkind@gmail.com>
Date: Thu, 5 Dec 2024 20:01:27 -0500
deck actions
Signed-off-by: kernelkind <kernelkind@gmail.com>
Diffstat:
10 files changed, 230 insertions(+), 54 deletions(-)
diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs
@@ -28,7 +28,7 @@ use tracing::{debug, error, info};
mod route;
-pub use route::{AccountsRoute, AccountsRouteResponse};
+pub use route::{AccountsAction, AccountsRoute, AccountsRouteResponse};
pub struct AccountRelayData {
filter: Filter,
@@ -225,6 +225,22 @@ pub struct Accounts {
needs_relay_config: bool,
}
+#[must_use = "You must call process_login_action on this to handle unknown ids"]
+pub struct RenderAccountAction {
+ pub accounts_action: Option<AccountsAction>,
+ pub unk_id_action: SingleUnkIdAction,
+}
+
+impl RenderAccountAction {
+ // Simple wrapper around processing the unknown action to expose too
+ // much internal logic. This allows us to have a must_use on our
+ // LoginAction type, otherwise the SingleUnkIdAction's must_use will
+ // be lost when returned in the login action
+ pub fn process_action(&mut self, ids: &mut UnknownIds, ndb: &Ndb, txn: &Transaction) {
+ self.unk_id_action.process_action(ids, ndb, txn);
+ }
+}
+
/// Render account management views from a route
#[allow(clippy::too_many_arguments)]
pub fn render_accounts_route(
@@ -236,7 +252,7 @@ pub fn render_accounts_route(
decks: &mut DecksCache,
login_state: &mut AcquireKeyState,
route: AccountsRoute,
-) -> SingleUnkIdAction {
+) -> RenderAccountAction {
let resp = match route {
AccountsRoute::Accounts => AccountsView::new(ndb, accounts, img_cache)
.ui(ui)
@@ -252,8 +268,11 @@ pub fn render_accounts_route(
if let Some(resp) = resp {
match resp {
AccountsRouteResponse::Accounts(response) => {
- process_accounts_view_response(accounts, decks, col, response);
- SingleUnkIdAction::no_action()
+ let action = process_accounts_view_response(accounts, decks, col, response);
+ RenderAccountAction {
+ accounts_action: action,
+ unk_id_action: SingleUnkIdAction::no_action(),
+ }
}
AccountsRouteResponse::AddAccount(response) => {
let action = process_login_view_response(accounts, decks, response);
@@ -266,7 +285,10 @@ pub fn render_accounts_route(
}
}
} else {
- SingleUnkIdAction::no_action()
+ RenderAccountAction {
+ accounts_action: None,
+ unk_id_action: SingleUnkIdAction::no_action(),
+ }
}
}
@@ -275,21 +297,28 @@ pub fn process_accounts_view_response(
decks: &mut DecksCache,
col: usize,
response: AccountsViewResponse,
-) {
+) -> Option<AccountsAction> {
let router = get_active_columns_mut(accounts, decks)
.column_mut(col)
.router_mut();
+ let mut selection = None;
match response {
AccountsViewResponse::RemoveAccount(index) => {
- accounts.remove_account(index);
+ let acc_sel = AccountsAction::Remove(index);
+ info!("account selection: {:?}", acc_sel);
+ selection = Some(acc_sel);
}
AccountsViewResponse::SelectAccount(index) => {
- accounts.select_account(index);
+ let acc_sel = AccountsAction::Switch(index);
+ info!("account selection: {:?}", acc_sel);
+ selection = Some(acc_sel);
}
AccountsViewResponse::RouteToLogin => {
router.route_to(Route::add_account());
}
}
+
+ selection
}
impl Accounts {
@@ -382,7 +411,7 @@ impl Accounts {
}
#[must_use = "UnknownIdAction's must be handled. Use .process_unknown_id_action()"]
- pub fn add_account(&mut self, account: Keypair) -> LoginAction {
+ pub fn add_account(&mut self, account: Keypair) -> RenderAccountAction {
let pubkey = account.pubkey;
let switch_to_index = if let Some(contains_acc) = self.contains_account(pubkey.bytes()) {
if account.secret_key.is_some() && !contains_acc.has_nsec {
@@ -404,9 +433,9 @@ impl Accounts {
self.accounts.len() - 1
};
- LoginAction {
- unk: SingleUnkIdAction::pubkey(pubkey),
- switch_to_index,
+ RenderAccountAction {
+ accounts_action: Some(AccountsAction::Switch(switch_to_index)),
+ unk_id_action: SingleUnkIdAction::pubkey(pubkey),
}
}
@@ -628,33 +657,22 @@ pub fn process_login_view_response(
manager: &mut Accounts,
decks: &mut DecksCache,
response: AccountLoginResponse,
-) -> SingleUnkIdAction {
- let (pubkey, login_action) = match response {
+) -> RenderAccountAction {
+ let (r, pubkey) = match response {
AccountLoginResponse::CreateNew => {
let kp = FullKeypair::generate().to_keypair();
- (kp.pubkey, manager.add_account(kp))
+ let pubkey = kp.pubkey;
+ (manager.add_account(kp), pubkey)
+ }
+ AccountLoginResponse::LoginWith(keypair) => {
+ let pubkey = keypair.pubkey;
+ (manager.add_account(keypair), pubkey)
}
- AccountLoginResponse::LoginWith(keypair) => (keypair.pubkey, manager.add_account(keypair)),
};
- manager.select_account(login_action.switch_to_index);
- decks.add_deck_default(pubkey);
- login_action.unk
-}
-#[must_use = "You must call process_login_action on this to handle unknown ids"]
-pub struct LoginAction {
- unk: SingleUnkIdAction,
- pub switch_to_index: usize,
-}
+ decks.add_deck_default(pubkey);
-impl LoginAction {
- // Simple wrapper around processing the unknown action to expose too
- // much internal logic. This allows us to have a must_use on our
- // LoginAction type, otherwise the SingleUnkIdAction's must_use will
- // be lost when returned in the login action
- pub fn process_action(&mut self, ids: &mut UnknownIds, ndb: &Ndb, txn: &Transaction) {
- self.unk.process_action(ids, ndb, txn);
- }
+ r
}
#[derive(Default)]
diff --git a/src/accounts/route.rs b/src/accounts/route.rs
@@ -11,3 +11,9 @@ pub enum AccountsRoute {
Accounts,
AddAccount,
}
+
+#[derive(Debug)]
+pub enum AccountsAction {
+ Switch(usize),
+ Remove(usize),
+}
diff --git a/src/app.rs b/src/app.rs
@@ -459,10 +459,6 @@ impl Damus {
Columns::new()
}
} else {
- info!(
- "Using columns from command line arguments: {:?}",
- parsed_args.columns
- );
let mut columns: Columns = Columns::new();
for col in parsed_args.columns {
if let Some(timeline) = col.into_timeline(&ndb, account) {
@@ -719,6 +715,7 @@ fn timelines_view(ui: &mut egui::Ui, sizes: Size, app: &mut Damus) {
)
.clip(true)
.horizontal(|mut strip| {
+ let mut side_panel_action: Option<nav::SwitchingAction> = None;
strip.cell(|ui| {
let rect = ui.available_rect_before_wrap();
let side_panel = DesktopSidePanel::new(
@@ -730,12 +727,14 @@ fn timelines_view(ui: &mut egui::Ui, sizes: Size, app: &mut Damus) {
.show(ui);
if side_panel.response.clicked() || side_panel.response.secondary_clicked() {
- DesktopSidePanel::perform_action(
+ if let Some(action) = DesktopSidePanel::perform_action(
&mut app.decks_cache,
&app.accounts,
&mut app.support,
side_panel.action,
- );
+ ) {
+ side_panel_action = Some(action);
+ }
}
// vertical sidebar line
@@ -765,6 +764,10 @@ fn timelines_view(ui: &mut egui::Ui, sizes: Size, app: &mut Damus) {
}
let mut save_cols = false;
+ if let Some(action) = side_panel_action {
+ save_cols = save_cols || action.process(app);
+ }
+
for response in responses {
let save = response.process_render_nav_response(app);
save_cols = save_cols || save;
diff --git a/src/column.rs b/src/column.rs
@@ -293,3 +293,8 @@ pub enum IntermediaryRoute {
Timeline(Timeline),
Route(Route),
}
+
+pub enum ColumnsAction {
+ // Switch(usize), TODO: could use for keyboard selection
+ Remove(usize),
+}
diff --git a/src/decks.rs b/src/decks.rs
@@ -16,10 +16,10 @@ pub static FALLBACK_PUBKEY: fn() -> Pubkey = || {
Pubkey::from_hex("aa733081e4f0f79dd43023d8983265593f2b41a988671cfcef3f489b91ad93fe").unwrap()
};
-//pub enum DecksAction {
-// Switch(usize),
-// Removing(usize),
-//}
+pub enum DecksAction {
+ Switch(usize),
+ Removing(usize),
+}
pub struct DecksCache {
account_to_decks: HashMap<Pubkey, Decks>,
diff --git a/src/nav.rs b/src/nav.rs
@@ -1,7 +1,10 @@
use crate::{
- accounts::render_accounts_route,
+ accounts::{render_accounts_route, AccountsAction},
actionbar::NoteAction,
- app::{get_active_columns, get_active_columns_mut},
+ app::{get_active_columns, get_active_columns_mut, get_decks_mut},
+ column::ColumnsAction,
+ deck_state::DeckState,
+ decks::{Deck, DecksAction},
notes_holder::NotesHolder,
profile::Profile,
relay_pool_manager::RelayPoolManager,
@@ -15,6 +18,8 @@ use crate::{
self,
add_column::render_add_column_routes,
column::NavTitle,
+ configure_deck::ConfigureDeckView,
+ edit_deck::{EditDeckResponse, EditDeckView},
note::{PostAction, PostType},
support::SupportView,
RelayView, View,
@@ -26,11 +31,45 @@ use egui_nav::{Nav, NavAction, NavResponse, NavUiType};
use nostrdb::{Ndb, Transaction};
use tracing::{error, info};
+#[allow(clippy::enum_variant_names)]
pub enum RenderNavAction {
Back,
RemoveColumn,
PostAction(PostAction),
NoteAction(NoteAction),
+ SwitchingAction(SwitchingAction),
+}
+
+pub enum SwitchingAction {
+ Accounts(AccountsAction),
+ Columns(ColumnsAction),
+ Decks(crate::decks::DecksAction),
+}
+
+impl SwitchingAction {
+ /// process the action, and return whether switching occured
+ pub fn process(&self, app: &mut Damus) -> bool {
+ match &self {
+ SwitchingAction::Accounts(account_action) => match *account_action {
+ AccountsAction::Switch(index) => app.accounts.select_account(index),
+ AccountsAction::Remove(index) => app.accounts.remove_account(index),
+ },
+ SwitchingAction::Columns(columns_action) => match *columns_action {
+ ColumnsAction::Remove(index) => {
+ get_active_columns_mut(&app.accounts, &mut app.decks_cache).delete_column(index)
+ }
+ },
+ SwitchingAction::Decks(decks_action) => match *decks_action {
+ DecksAction::Switch(index) => {
+ get_decks_mut(&app.accounts, &mut app.decks_cache).set_active(index)
+ }
+ DecksAction::Removing(index) => {
+ get_decks_mut(&app.accounts, &mut app.decks_cache).remove_deck(index)
+ }
+ },
+ }
+ true
+ }
}
impl From<PostAction> for RenderNavAction {
@@ -60,7 +99,7 @@ impl RenderNavResponse {
#[must_use = "Make sure to save columns if result is true"]
pub fn process_render_nav_response(&self, app: &mut Damus) -> bool {
- let mut col_changed: bool = false;
+ let mut switching_occured: bool = false;
let col = self.column;
if let Some(action) = self
@@ -82,7 +121,7 @@ impl RenderNavResponse {
}
app.columns_mut().delete_column(col);
- col_changed = true;
+ switching_occured = true;
}
RenderNavAction::PostAction(post_action) => {
@@ -109,6 +148,10 @@ impl RenderNavResponse {
&app.accounts.mutefun(),
);
}
+
+ RenderNavAction::SwitchingAction(switching_action) => {
+ switching_occured = switching_action.process(app);
+ }
}
}
@@ -148,7 +191,12 @@ impl RenderNavResponse {
&app.accounts.mutefun(),
);
}
- col_changed = true;
+
+ if let Some(Route::EditDeck(index)) = r {
+ SwitchingAction::Decks(DecksAction::Removing(index)).process(app);
+ }
+
+ switching_occured = true;
}
NavAction::Navigated => {
@@ -157,7 +205,7 @@ impl RenderNavResponse {
if cur_router.is_replacing() {
cur_router.remove_previous_routes();
}
- col_changed = true;
+ switching_occured = true;
}
NavAction::Dragging => {}
@@ -167,7 +215,7 @@ impl RenderNavResponse {
}
}
- col_changed
+ switching_occured
}
}
@@ -194,7 +242,7 @@ fn render_nav_body(
ui,
),
Route::Accounts(amr) => {
- let action = render_accounts_route(
+ let mut action = render_accounts_route(
ui,
&app.ndb,
col,
@@ -206,7 +254,9 @@ fn render_nav_body(
);
let txn = Transaction::new(&app.ndb).expect("txn");
action.process_action(&mut app.unknown_ids, &app.ndb, &txn);
- None
+ action
+ .accounts_action
+ .map(|f| RenderNavAction::SwitchingAction(SwitchingAction::Accounts(f)))
}
Route::Relays => {
let manager = RelayPoolManager::new(app.pool_mut());
@@ -235,11 +285,69 @@ fn render_nav_body(
None
}
-
Route::Support => {
SupportView::new(&mut app.support).show(ui);
None
}
+ Route::NewDeck => {
+ let id = ui.id().with("new-deck");
+ let new_deck_state = app.view_state.id_to_deck_state.entry(id).or_default();
+ let mut resp = None;
+ if let Some(config_resp) = ConfigureDeckView::new(new_deck_state).ui(ui) {
+ if let Some(cur_acc) = app.accounts.get_selected_account() {
+ app.decks_cache.add_deck(
+ cur_acc.pubkey,
+ Deck::new(config_resp.icon, config_resp.name),
+ );
+
+ // set new deck as active
+ let cur_index = get_decks_mut(&app.accounts, &mut app.decks_cache)
+ .decks()
+ .len()
+ - 1;
+ resp = Some(RenderNavAction::SwitchingAction(SwitchingAction::Decks(
+ DecksAction::Switch(cur_index),
+ )));
+ }
+
+ new_deck_state.clear();
+ get_active_columns_mut(&app.accounts, &mut app.decks_cache)
+ .get_first_router()
+ .go_back();
+ }
+ resp
+ }
+ Route::EditDeck(index) => {
+ let cur_deck = get_decks_mut(&app.accounts, &mut app.decks_cache)
+ .decks_mut()
+ .get_mut(*index)
+ .expect("index wasn't valid");
+ let id = ui.id().with((
+ "edit-deck",
+ app.accounts.get_selected_account().map(|k| k.pubkey),
+ index,
+ ));
+ let deck_state = app
+ .view_state
+ .id_to_deck_state
+ .entry(id)
+ .or_insert_with(|| DeckState::from_deck(cur_deck));
+ if let Some(resp) = EditDeckView::new(deck_state).ui(ui) {
+ match resp {
+ EditDeckResponse::Edit(configure_deck_response) => {
+ cur_deck.edit(configure_deck_response);
+ }
+ EditDeckResponse::Delete => {
+ deck_state.deleting = true;
+ }
+ }
+ get_active_columns_mut(&app.accounts, &mut app.decks_cache)
+ .get_first_router()
+ .go_back();
+ }
+
+ None
+ }
}
}
diff --git a/src/route.rs b/src/route.rs
@@ -21,6 +21,8 @@ pub enum Route {
ComposeNote,
AddColumn(AddColumnRoute),
Support,
+ NewDeck,
+ EditDeck(usize),
}
impl Route {
@@ -95,6 +97,8 @@ impl Route {
AddColumnRoute::Hashtag => Cow::Borrowed("Add Hashtag Column"),
},
Route::Support => Cow::Borrowed("Damus Support"),
+ Route::NewDeck => Cow::Borrowed("Add Deck"),
+ Route::EditDeck(_) => Cow::Borrowed("Edit Deck"),
}
}
}
@@ -204,6 +208,8 @@ impl fmt::Display for Route {
Route::AddColumn(_) => write!(f, "Add Column"),
Route::Support => write!(f, "Support"),
+ Route::NewDeck => write!(f, "Add Deck"),
+ Route::EditDeck(_) => write!(f, "Edit Deck"),
}
}
}
diff --git a/src/ui/column/header.rs b/src/ui/column/header.rs
@@ -205,6 +205,8 @@ impl<'a> NavTitle<'a> {
Route::AddColumn(_add_col_route) => {}
Route::Support => {}
Route::Relays => {}
+ Route::NewDeck => {}
+ Route::EditDeck(_) => {}
}
}
diff --git a/src/ui/side_panel.rs b/src/ui/side_panel.rs
@@ -8,8 +8,10 @@ use crate::{
app::get_active_columns_mut,
app_style, colors,
column::Column,
+ decks::DecksAction,
decks::DecksCache,
imgcache::ImageCache,
+ nav::SwitchingAction,
route::Route,
support::Support,
user_account::UserAccount,
@@ -48,6 +50,9 @@ pub enum SidePanelAction {
Search,
ExpandSidePanel,
Support,
+ NewDeck,
+ SwitchDeck(usize),
+ EditDeck(usize),
}
pub struct SidePanelResponse {
@@ -210,8 +215,9 @@ impl<'a> DesktopSidePanel<'a> {
accounts: &Accounts,
support: &mut Support,
action: SidePanelAction,
- ) {
+ ) -> Option<SwitchingAction> {
let router = get_active_columns_mut(accounts, decks_cache).get_first_router();
+ let mut switching_response = None;
match action {
SidePanelAction::Panel => {} // TODO
SidePanelAction::Account => {
@@ -268,7 +274,27 @@ impl<'a> DesktopSidePanel<'a> {
router.route_to(Route::Support);
}
}
+ SidePanelAction::NewDeck => {
+ if router.routes().iter().any(|&r| r == Route::NewDeck) {
+ router.go_back();
+ } else {
+ router.route_to(Route::NewDeck);
+ }
+ }
+ SidePanelAction::SwitchDeck(index) => {
+ switching_response = Some(crate::nav::SwitchingAction::Decks(DecksAction::Switch(
+ index,
+ )))
+ }
+ SidePanelAction::EditDeck(index) => {
+ if router.routes().iter().any(|&r| r == Route::EditDeck(index)) {
+ router.go_back();
+ } else {
+ router.route_to(Route::EditDeck(index));
+ }
+ }
}
+ switching_response
}
}
diff --git a/src/view_state.rs b/src/view_state.rs
@@ -1,11 +1,13 @@
use std::collections::HashMap;
+use crate::deck_state::DeckState;
use crate::login_manager::AcquireKeyState;
/// Various state for views
#[derive(Default)]
pub struct ViewState {
pub login: AcquireKeyState,
+ pub id_to_deck_state: HashMap<egui::Id, DeckState>,
pub id_state_map: HashMap<egui::Id, AcquireKeyState>,
pub id_string_map: HashMap<egui::Id, String>,
}