feat: enhance diary navigation with LoadPrev action and pagination hints
This commit is contained in:
19
Cargo.lock
generated
19
Cargo.lock
generated
@@ -1708,6 +1708,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c"
|
||||
dependencies = [
|
||||
"log",
|
||||
"security-framework 2.11.1",
|
||||
"security-framework 3.7.0",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -2887,7 +2889,7 @@ dependencies = [
|
||||
"openssl-probe",
|
||||
"rustls-pki-types",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework 3.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2915,7 +2917,7 @@ dependencies = [
|
||||
"rustls-native-certs",
|
||||
"rustls-platform-verifier-android",
|
||||
"rustls-webpki",
|
||||
"security-framework",
|
||||
"security-framework 3.7.0",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
@@ -2975,6 +2977,19 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"core-foundation 0.9.4",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "3.7.0"
|
||||
|
||||
@@ -6,7 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
ratatui = "0.30.0"
|
||||
|
||||
keyring = "3"
|
||||
keyring = { version = "3", features = ["apple-native"] }
|
||||
directories = "6"
|
||||
csv = "1"
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ pub enum Action {
|
||||
SetupSubmit,
|
||||
InputChar(char), Backspace, FocusNext, FocusPrev,
|
||||
LoginSubmit,
|
||||
ScrollDown, ScrollUp, OpenHistory, LoadMore,
|
||||
ScrollDown, ScrollUp, OpenHistory, LoadMore, LoadPrev,
|
||||
DeleteInit, DeleteConfirm, DeleteCancel,
|
||||
RatingUp, RatingDown, ReviewSubmit,
|
||||
BulkParseFile, BulkImportAll, BulkCancel,
|
||||
@@ -301,7 +301,7 @@ pub fn update(app: &mut App, action: Action) -> Vec<Command> {
|
||||
m.bulk_import.stage = BulkImportStage::EnterPath;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
Tab::AddReview | Tab::Settings => { m.tab = Tab::Diary; }
|
||||
}
|
||||
}
|
||||
vec![]
|
||||
@@ -435,8 +435,14 @@ pub fn update(app: &mut App, action: Action) -> Vec<Command> {
|
||||
return vec![];
|
||||
}
|
||||
app.api_url = url.clone();
|
||||
app.screen = Screen::Login(LoginState::default());
|
||||
return vec![Command::SaveConfig(url)];
|
||||
let cmds = if app.token.is_some() {
|
||||
app.screen = Screen::Main(MainState::new(url.clone()));
|
||||
vec![Command::SaveConfig(url), Command::LoadDiary { offset: 0 }]
|
||||
} else {
|
||||
app.screen = Screen::Login(LoginState::default());
|
||||
vec![Command::SaveConfig(url)]
|
||||
};
|
||||
return cmds;
|
||||
}
|
||||
vec![]
|
||||
}
|
||||
@@ -515,6 +521,17 @@ pub fn update(app: &mut App, action: Action) -> Vec<Command> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
Action::LoadPrev => {
|
||||
if let Screen::Main(m) = &mut app.screen {
|
||||
if m.diary.offset > 0 {
|
||||
let prev = m.diary.offset.saturating_sub(20);
|
||||
m.diary.offset = prev;
|
||||
return vec![Command::LoadDiary { offset: prev }];
|
||||
}
|
||||
}
|
||||
vec![]
|
||||
}
|
||||
|
||||
Action::DiaryLoaded { entries, total } => {
|
||||
app.loading = false;
|
||||
if let Screen::Main(m) = &mut app.screen {
|
||||
@@ -701,7 +718,11 @@ pub fn update(app: &mut App, action: Action) -> Vec<Command> {
|
||||
|
||||
Action::BulkCancel => {
|
||||
if let Screen::Main(m) = &mut app.screen {
|
||||
m.bulk_import = BulkImportState::default();
|
||||
if m.bulk_import.stage == BulkImportStage::EnterPath {
|
||||
m.tab = Tab::Diary;
|
||||
} else {
|
||||
m.bulk_import = BulkImportState::default();
|
||||
}
|
||||
}
|
||||
vec![]
|
||||
}
|
||||
|
||||
@@ -246,6 +246,7 @@ fn key_to_action(app: &App, key: ratatui::crossterm::event::KeyEvent) -> Option<
|
||||
KeyCode::Tab => Some(Action::TabNext),
|
||||
KeyCode::BackTab => Some(Action::TabPrev),
|
||||
KeyCode::Char('>') | KeyCode::Char('m') => Some(Action::LoadMore),
|
||||
KeyCode::Char('<') | KeyCode::Char('b') => Some(Action::LoadPrev),
|
||||
KeyCode::Char('1') => Some(Action::TabSelect(Tab::Diary)),
|
||||
KeyCode::Char('2') => Some(Action::TabSelect(Tab::AddReview)),
|
||||
KeyCode::Char('3') => Some(Action::TabSelect(Tab::BulkImport)),
|
||||
@@ -279,6 +280,10 @@ fn key_to_action(app: &App, key: ratatui::crossterm::event::KeyEvent) -> Option<
|
||||
KeyCode::Tab if !in_path => Some(Action::TabNext),
|
||||
KeyCode::BackTab if !in_path => Some(Action::TabPrev),
|
||||
KeyCode::Char('q') if !in_path => Some(Action::Quit),
|
||||
KeyCode::Char('1') if !in_path => Some(Action::TabSelect(Tab::Diary)),
|
||||
KeyCode::Char('2') if !in_path => Some(Action::TabSelect(Tab::AddReview)),
|
||||
KeyCode::Char('3') if !in_path => Some(Action::TabSelect(Tab::BulkImport)),
|
||||
KeyCode::Char('4') if !in_path => Some(Action::TabSelect(Tab::Settings)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -296,6 +301,10 @@ fn key_to_action(app: &App, key: ratatui::crossterm::event::KeyEvent) -> Option<
|
||||
},
|
||||
KeyCode::Esc => Some(Action::Escape),
|
||||
KeyCode::Char('q') => Some(Action::Quit),
|
||||
KeyCode::Char('1') if !on_url => Some(Action::TabSelect(Tab::Diary)),
|
||||
KeyCode::Char('2') if !on_url => Some(Action::TabSelect(Tab::AddReview)),
|
||||
KeyCode::Char('3') if !on_url => Some(Action::TabSelect(Tab::BulkImport)),
|
||||
KeyCode::Char('4') if !on_url => Some(Action::TabSelect(Tab::Settings)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,11 +215,13 @@ fn draw_diary(frame: &mut Frame, area: Rect, state: &DiaryState) {
|
||||
.collect();
|
||||
|
||||
let can_load_more = (state.offset as u64 + state.entries.len() as u64) < state.total;
|
||||
let list_title = if can_load_more {
|
||||
format!(" Diary ({} entries) [m: load more] ", state.total)
|
||||
} else {
|
||||
format!(" Diary ({} entries) ", state.total)
|
||||
};
|
||||
let can_load_prev = state.offset > 0;
|
||||
let page = state.offset / 20 + 1;
|
||||
let total_pages = state.total.div_ceil(20).max(1);
|
||||
let mut hints = format!(" Diary ({} entries, page {}/{}) ", state.total, page, total_pages);
|
||||
if can_load_prev { hints.push_str("[b: prev] "); }
|
||||
if can_load_more { hints.push_str("[m: next] "); }
|
||||
let list_title = hints;
|
||||
let mut list_state = ListState::default();
|
||||
list_state.select(Some(state.selected));
|
||||
let list = List::new(items).block(Block::default().title(list_title).borders(Borders::ALL));
|
||||
|
||||
Reference in New Issue
Block a user