Skip to content

Commit

Permalink
Flexible routing
Browse files Browse the repository at this point in the history
Another massive refactor to change the way routing works. Now any
column can route anywhere.

Also things are generally just much better and more modular via the
new struct split borrowing technique.

I didn't even try to split this into smaller commits for my sanity.

Signed-off-by: William Casarin <[email protected]>
  • Loading branch information
jb55 committed Sep 16, 2024
1 parent b4a8cdd commit 36c0971
Show file tree
Hide file tree
Showing 27 changed files with 972 additions and 962 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export JB55=32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245

export JACK=npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m
export VROD=npub1h50pnxqw9jg7dhr906fvy4mze2yzawf895jhnc3p7qmljdugm6gsrurqev
export JEFFG=npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc
95 changes: 78 additions & 17 deletions src/account_manager.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
use std::cmp::Ordering;

use enostr::{FilledKeypair, FullKeypair, Keypair};
use nostrdb::Ndb;

pub use crate::user_account::UserAccount;
use crate::{
column::Columns,
imgcache::ImageCache,
key_storage::{KeyStorage, KeyStorageResponse, KeyStorageType},
login_manager::LoginState,
route::{Route, Router},
ui::{
account_login_view::AccountLoginResponse, account_management::AccountManagementViewResponse,
account_login_view::{AccountLoginResponse, AccountLoginView},
account_management::{AccountsView, AccountsViewResponse},
},
};
use tracing::info;

pub use crate::user_account::UserAccount;

/// The interface for managing the user's accounts.
/// Represents all user-facing operations related to account management.
pub struct AccountManager {
Expand All @@ -19,6 +26,75 @@ pub struct AccountManager {
key_store: KeyStorageType,
}

// TODO(jb55): move to accounts/route.rs
pub enum AccountsRouteResponse {
Accounts(AccountsViewResponse),
AddAccount(AccountLoginResponse),
}

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum AccountsRoute {
Accounts,
AddAccount,
}

/// Render account management views from a route
#[allow(clippy::too_many_arguments)]
pub fn render_accounts_route(
ui: &mut egui::Ui,
ndb: &Ndb,
col: usize,
columns: &mut Columns,
img_cache: &mut ImageCache,
accounts: &mut AccountManager,
login_state: &mut LoginState,
route: AccountsRoute,
) {
let router = columns.column_mut(col).router_mut();
let resp = match route {
AccountsRoute::Accounts => AccountsView::new(ndb, accounts, img_cache)
.ui(ui)
.inner
.map(AccountsRouteResponse::Accounts),

AccountsRoute::AddAccount => AccountLoginView::new(login_state)
.ui(ui)
.inner
.map(AccountsRouteResponse::AddAccount),
};

if let Some(resp) = resp {
match resp {
AccountsRouteResponse::Accounts(response) => {
process_accounts_view_response(accounts, response, router);
}
AccountsRouteResponse::AddAccount(response) => {
process_login_view_response(accounts, response);
*login_state = Default::default();
router.go_back();
}
}
}
}

pub fn process_accounts_view_response(
manager: &mut AccountManager,
response: AccountsViewResponse,
router: &mut Router<Route>,
) {
match response {
AccountsViewResponse::RemoveAccount(index) => {
manager.remove_account(index);
}
AccountsViewResponse::SelectAccount(index) => {
manager.select_account(index);
}
AccountsViewResponse::RouteToLogin => {
router.route_to(Route::add_account());
}
}
}

impl AccountManager {
pub fn new(currently_selected_account: Option<usize>, key_store: KeyStorageType) -> Self {
let accounts = if let KeyStorageResponse::ReceivedResult(res) = key_store.get_keys() {
Expand Down Expand Up @@ -122,21 +198,6 @@ impl AccountManager {
}
}

pub fn process_management_view_response_stateless(
manager: &mut AccountManager,
response: AccountManagementViewResponse,
) {
match response {
AccountManagementViewResponse::RemoveAccount(index) => {
manager.remove_account(index);
}
AccountManagementViewResponse::SelectAccount(index) => {
manager.select_account(index);
}
AccountManagementViewResponse::RouteToLogin => {}
}
}

pub fn process_login_view_response(manager: &mut AccountManager, response: AccountLoginResponse) {
match response {
AccountLoginResponse::CreateNew => {
Expand Down
61 changes: 41 additions & 20 deletions src/actionbar.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::{
column::Column,
note::NoteRef,
notecache::NoteCache,
route::Route,
route::{Route, Router},
thread::{Thread, ThreadResult, Threads},
};
use enostr::{NoteId, RelayPool};
Expand All @@ -12,8 +11,8 @@ use uuid::Uuid;

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum BarAction {
Reply,
OpenThread,
Reply(NoteId),
OpenThread(NoteId),
}

pub struct NewThreadNotes {
Expand All @@ -33,17 +32,15 @@ pub enum BarResult {
fn open_thread(
ndb: &Ndb,
txn: &Transaction,
column: &mut Column,
router: &mut Router<Route>,
note_cache: &mut NoteCache,
pool: &mut RelayPool,
threads: &mut Threads,
selected_note: &[u8; 32],
) -> Option<BarResult> {
{
column
.routes_mut()
.push(Route::Thread(NoteId::new(selected_note.to_owned())));
column.navigating = true;
router.route_to(Route::thread(NoteId::new(selected_note.to_owned())));
router.navigating = true;
}

let root_id = crate::note::root_note_id_from_selected_id(ndb, note_cache, txn, selected_note);
Expand All @@ -52,7 +49,7 @@ fn open_thread(
let (thread, result) = match thread_res {
ThreadResult::Stale(thread) => {
// The thread is stale, let's update it
let notes = Thread::new_notes(&thread.view.notes, root_id, txn, ndb);
let notes = Thread::new_notes(&thread.view().notes, root_id, txn, ndb);
let bar_result = if notes.is_empty() {
None
} else {
Expand Down Expand Up @@ -120,33 +117,57 @@ impl BarAction {
pub fn execute(
self,
ndb: &Ndb,
column: &mut Column,
router: &mut Router<Route>,
threads: &mut Threads,
note_cache: &mut NoteCache,
pool: &mut RelayPool,
replying_to: &[u8; 32],
txn: &Transaction,
) -> Option<BarResult> {
match self {
BarAction::Reply => {
column
.routes_mut()
.push(Route::Reply(NoteId::new(replying_to.to_owned())));
column.navigating = true;
BarAction::Reply(note_id) => {
router.route_to(Route::reply(note_id));
router.navigating = true;
None
}

BarAction::OpenThread => {
open_thread(ndb, txn, column, note_cache, pool, threads, replying_to)
BarAction::OpenThread(note_id) => {
open_thread(ndb, txn, router, note_cache, pool, threads, note_id.bytes())
}
}
}

/// Execute the BarAction and process the BarResult
pub fn execute_and_process_result(
self,
ndb: &Ndb,
router: &mut Router<Route>,
threads: &mut Threads,
note_cache: &mut NoteCache,
pool: &mut RelayPool,
txn: &Transaction,
) {
if let Some(br) = self.execute(ndb, router, threads, note_cache, pool, txn) {
br.process(ndb, txn, threads);
}
}
}

impl BarResult {
pub fn new_thread_notes(notes: Vec<NoteRef>, root_id: NoteId) -> Self {
BarResult::NewThreadNotes(NewThreadNotes::new(notes, root_id))
}

pub fn process(&self, ndb: &Ndb, txn: &Transaction, threads: &mut Threads) {
match self {
// update the thread for next render if we have new notes
BarResult::NewThreadNotes(new_notes) => {
let thread = threads
.thread_mut(ndb, txn, new_notes.root_id.bytes())
.get_ptr();
new_notes.process(thread);
}
}
}
}

impl NewThreadNotes {
Expand All @@ -159,6 +180,6 @@ impl NewThreadNotes {
pub fn process(&self, thread: &mut Thread) {
// threads are chronological, ie reversed from reverse-chronological, the default.
let reversed = true;
thread.view.insert(&self.notes, reversed);
thread.view_mut().insert(&self.notes, reversed);
}
}
Loading

0 comments on commit 36c0971

Please sign in to comment.