columns/decks: add home and notifications for new accounts

This is way more user friendly, and needed on mobile

Fixes: https://github.com/damus-io/notedeck/issues/937
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2025-07-10 17:16:30 -07:00
parent 26d027f03e
commit 217c1e5223
3 changed files with 95 additions and 60 deletions

View File

@@ -1,19 +1,19 @@
use enostr::{FullKeypair, Pubkey}; use enostr::{FullKeypair, Pubkey};
use nostrdb::{Ndb, Transaction}; use nostrdb::{Ndb, Transaction};
use notedeck::{Accounts, Images, SingleUnkIdAction, UnknownIds}; use notedeck::{Accounts, AppContext, SingleUnkIdAction, UnknownIds};
use crate::app::get_active_columns_mut; use crate::app::get_active_columns_mut;
use crate::decks::DecksCache; use crate::decks::DecksCache;
use crate::{ use crate::{
login_manager::AcquireKeyState, login_manager::AcquireKeyState,
route::Route, route::Route,
timeline::TimelineCache,
ui::{ ui::{
account_login_view::{AccountLoginResponse, AccountLoginView}, account_login_view::{AccountLoginResponse, AccountLoginView},
accounts::{AccountsView, AccountsViewResponse}, accounts::{AccountsView, AccountsViewResponse},
}, },
}; };
use egui_winit::clipboard::Clipboard;
use tracing::info; use tracing::info;
mod route; mod route;
@@ -63,22 +63,22 @@ pub struct AddAccountAction {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn render_accounts_route( pub fn render_accounts_route(
ui: &mut egui::Ui, ui: &mut egui::Ui,
ndb: &Ndb, app_ctx: &mut AppContext,
col: usize, col: usize,
img_cache: &mut Images,
accounts: &mut Accounts,
decks: &mut DecksCache, decks: &mut DecksCache,
timeline_cache: &mut TimelineCache,
login_state: &mut AcquireKeyState, login_state: &mut AcquireKeyState,
clipboard: &mut Clipboard,
route: AccountsRoute, route: AccountsRoute,
) -> AddAccountAction { ) -> AddAccountAction {
let resp = match route { let resp = match route {
AccountsRoute::Accounts => AccountsView::new(ndb, accounts, img_cache) AccountsRoute::Accounts => {
.ui(ui) AccountsView::new(app_ctx.ndb, app_ctx.accounts, app_ctx.img_cache)
.inner .ui(ui)
.map(AccountsRouteResponse::Accounts), .inner
.map(AccountsRouteResponse::Accounts)
}
AccountsRoute::AddAccount => AccountLoginView::new(login_state, clipboard) AccountsRoute::AddAccount => AccountLoginView::new(login_state, app_ctx.clipboard)
.ui(ui) .ui(ui)
.inner .inner
.map(AccountsRouteResponse::AddAccount), .map(AccountsRouteResponse::AddAccount),
@@ -87,16 +87,17 @@ pub fn render_accounts_route(
if let Some(resp) = resp { if let Some(resp) = resp {
match resp { match resp {
AccountsRouteResponse::Accounts(response) => { AccountsRouteResponse::Accounts(response) => {
let action = process_accounts_view_response(accounts, decks, col, response); let action = process_accounts_view_response(app_ctx.accounts, decks, col, response);
AddAccountAction { AddAccountAction {
accounts_action: action, accounts_action: action,
unk_id_action: SingleUnkIdAction::no_action(), unk_id_action: SingleUnkIdAction::no_action(),
} }
} }
AccountsRouteResponse::AddAccount(response) => { AccountsRouteResponse::AddAccount(response) => {
let action = process_login_view_response(accounts, decks, col, ndb, response); let action =
process_login_view_response(app_ctx, timeline_cache, decks, col, response);
*login_state = Default::default(); *login_state = Default::default();
let router = get_active_columns_mut(accounts, decks) let router = get_active_columns_mut(app_ctx.accounts, decks)
.column_mut(col) .column_mut(col)
.router_mut(); .router_mut();
router.go_back(); router.go_back();
@@ -140,27 +141,30 @@ pub fn process_accounts_view_response(
} }
pub fn process_login_view_response( pub fn process_login_view_response(
manager: &mut Accounts, app_ctx: &mut AppContext,
timeline_cache: &mut TimelineCache,
decks: &mut DecksCache, decks: &mut DecksCache,
col: usize, col: usize,
ndb: &Ndb,
response: AccountLoginResponse, response: AccountLoginResponse,
) -> AddAccountAction { ) -> AddAccountAction {
let (r, pubkey) = match response { let (r, pubkey) = match response {
AccountLoginResponse::CreateNew => { AccountLoginResponse::CreateNew => {
let kp = FullKeypair::generate().to_keypair(); let kp = FullKeypair::generate().to_keypair();
let pubkey = kp.pubkey; let pubkey = kp.pubkey;
let txn = Transaction::new(ndb).expect("txn"); let txn = Transaction::new(app_ctx.ndb).expect("txn");
(manager.add_account(ndb, &txn, kp), pubkey) (app_ctx.accounts.add_account(app_ctx.ndb, &txn, kp), pubkey)
} }
AccountLoginResponse::LoginWith(keypair) => { AccountLoginResponse::LoginWith(keypair) => {
let pubkey = keypair.pubkey; let pubkey = keypair.pubkey;
let txn = Transaction::new(ndb).expect("txn"); let txn = Transaction::new(app_ctx.ndb).expect("txn");
(manager.add_account(ndb, &txn, keypair), pubkey) (
app_ctx.accounts.add_account(app_ctx.ndb, &txn, keypair),
pubkey,
)
} }
}; };
decks.add_deck_default(pubkey); decks.add_deck_default(app_ctx, timeline_cache, pubkey);
if let Some(action) = r { if let Some(action) = r {
AddAccountAction { AddAccountAction {

View File

@@ -100,12 +100,27 @@ impl DecksCache {
.unwrap_or_else(|| panic!("fallback deck not found")) .unwrap_or_else(|| panic!("fallback deck not found"))
} }
pub fn add_deck_default(&mut self, key: Pubkey) { pub fn add_deck_default(
self.account_to_decks.insert(key, Decks::default()); &mut self,
ctx: &mut AppContext,
timeline_cache: &mut TimelineCache,
pubkey: Pubkey,
) {
let mut decks = Decks::default();
// add home and notifications for new accounts
add_demo_columns(
ctx,
timeline_cache,
pubkey,
&mut decks.decks_mut()[0].columns,
);
self.account_to_decks.insert(pubkey, decks);
info!( info!(
"Adding new default deck for {:?}. New decks size is {}", "Adding new default deck for {:?}. New decks size is {}",
key, pubkey,
self.account_to_decks.get(&key).unwrap().decks.len() self.account_to_decks.get(&pubkey).unwrap().decks.len()
); );
} }
@@ -303,20 +318,29 @@ pub struct Deck {
impl Default for Deck { impl Default for Deck {
fn default() -> Self { fn default() -> Self {
let mut columns = Columns::default(); let columns = Columns::default();
columns.new_column_picker();
Self { Self {
icon: '🇩',
name: String::from("Default Deck"),
columns, columns,
icon: Deck::default_icon(),
name: Deck::default_name().to_string(),
} }
} }
} }
impl Deck { impl Deck {
pub fn default_icon() -> char {
'🇩'
}
pub fn default_name() -> &'static str {
"Default Deck"
}
pub fn new(icon: char, name: String) -> Self { pub fn new(icon: char, name: String) -> Self {
let mut columns = Columns::default(); let mut columns = Columns::default();
columns.new_column_picker(); columns.new_column_picker();
Self { Self {
icon, icon,
name, name,
@@ -346,6 +370,39 @@ impl Deck {
} }
} }
pub fn add_demo_columns(
ctx: &mut AppContext,
timeline_cache: &mut TimelineCache,
pubkey: Pubkey,
columns: &mut Columns,
) {
let timeline_kinds = [
TimelineKind::contact_list(pubkey),
TimelineKind::notifications(pubkey),
];
let txn = Transaction::new(ctx.ndb).unwrap();
for kind in &timeline_kinds {
if let Some(results) = columns.add_new_timeline_column(
timeline_cache,
&txn,
ctx.ndb,
ctx.note_cache,
ctx.pool,
kind,
) {
results.process(
ctx.ndb,
ctx.note_cache,
&txn,
timeline_cache,
ctx.unknown_ids,
);
}
}
}
pub fn demo_decks( pub fn demo_decks(
demo_pubkey: Pubkey, demo_pubkey: Pubkey,
timeline_cache: &mut TimelineCache, timeline_cache: &mut TimelineCache,
@@ -354,37 +411,13 @@ pub fn demo_decks(
let deck = { let deck = {
let mut columns = Columns::default(); let mut columns = Columns::default();
let timeline_kinds = [ add_demo_columns(ctx, timeline_cache, demo_pubkey, &mut columns);
TimelineKind::contact_list(demo_pubkey),
TimelineKind::notifications(demo_pubkey),
];
let txn = Transaction::new(ctx.ndb).unwrap();
for kind in &timeline_kinds {
if let Some(results) = columns.add_new_timeline_column(
timeline_cache,
&txn,
ctx.ndb,
ctx.note_cache,
ctx.pool,
kind,
) {
results.process(
ctx.ndb,
ctx.note_cache,
&txn,
timeline_cache,
ctx.unknown_ids,
);
}
}
//columns.add_new_timeline_column(Timeline::hashtag("introductions".to_string())); //columns.add_new_timeline_column(Timeline::hashtag("introductions".to_string()));
Deck { Deck {
icon: '🇩', icon: Deck::default_icon(),
name: String::from("Demo Deck"), name: Deck::default_name().to_string(),
columns, columns,
} }
}; };

View File

@@ -456,13 +456,11 @@ fn render_nav_body(
Route::Accounts(amr) => { Route::Accounts(amr) => {
let mut action = render_accounts_route( let mut action = render_accounts_route(
ui, ui,
ctx.ndb, ctx,
col, col,
ctx.img_cache,
ctx.accounts,
&mut app.decks_cache, &mut app.decks_cache,
&mut app.timeline_cache,
&mut app.view_state.login, &mut app.view_state.login,
ctx.clipboard,
*amr, *amr,
); );
let txn = Transaction::new(ctx.ndb).expect("txn"); let txn = Transaction::new(ctx.ndb).expect("txn");