use nav-scrollable for repo status
[?]
Jul 16, 2025, 5:36 PM
PTWZYQFRWWUOE2WMQT26CKZKFSHAIJVJS3QWHJFYUFDRRTVPHSUACDependencies
- [2]
SWWE2R6Mdisplay basic repo stuff - [3]
WT3GA27Padd cursor with selection - [4]
W7IUT3ZVstart recording impl - [5]
YBJRDOTCmake all repo actions async - [6]
A5YBC77Vrecord! - [7]
D7A7MSIHallow to defer or abandon record, add buttons - [8]
AMPZ2BXKshow changed files diffs (only Edit atm) - [9]
ONRCENKTrm unnecessary state from repo's internal state - [10]
23SFYK4Qbig view refactor into a new crate - [11]
OPXFZKEBview tests setup - [12]
3QVNMRNMtest non-empty repo app view - [13]
PKJCFSBMtheme improvements - [14]
XSZZB47Urefactor stuff into lib - [15]
3BK22XE5add a test for hover btn and more refactors - [16]
WGID4LS4absolutely slayed testing with iced task - [17]
ACDXXAX2refactor main's updates into smaller fns - [18]
I56UGW7Umake record test, fix log update - [19]
YYKXNBFLtest: add untracked file - [20]
5CYU7UT7test: rm added file - [21]
ESMM3FELtest selection reindexing - [22]
UF5NJKAStest load repo - [23]
7SSBM4UQview: refactor repo view - [24]
OC6DLIZ3test record when nothing to record - [25]
I2AG42PAnew cols layout - [26]
DXAYDIMQupdate to latest pijul - [27]
WW36JYLRadd iced_nav_scrollable widget crate - [28]
SASAN2XCuse nav-scrollable - [29]
XZ6D3UUEavoid alloc - [30]
KEPKF3WOunify diffs handling, simplify view - [31]
GOLHUD6Rnav-scrollable: set skip-able sections - [32]
K5YUSV2Wauto-scroll to last offset - [33]
KWTBNTO3diffs selection and scrolling - [34]
5MUEECMJsmooth scrolling nav - [35]
WXQBBQ2Aupdate nightly - [36]
65DXFP3Yfix status overflow - [37]
KM5PSZ4Awatch repo once loaded - [38]
4WO3ZJM2show untracked files' contents - [39]
ZVI4AWERwoot contents_diff - [40]
MYGIBRRHwip custom theme - [41]
X6AK4QPXfinish recording test - [42]
WIFVLV37nav-scrollabe: detect size to determine if needs scrolling, msg when ready - [43]
IQDCHWCPload a pijul repo - [44]
KMB6FND3test view update fn rather than direct fn calls - [45]
DST3HRZZfix emoji rendering - [46]
SWDPAGF6test channel name - [47]
EC3TVL4Xadd untracked files - [48]
W4LFX7IHgroup diffs by file name - [49]
BJXUYQ2Yshow untracked file contents in read-only text editor - [50]
YKHE3XMWrefactor diffs handling - [51]
ELG3UDT6allow to rm added files - [52]
S2NVIFXRallow to enter record msg - [*]
VCNKFNUFapp init test - [*]
6YZAVBWUInitial commit
Change contents
- edit in libflorescence/src/repo.rs at line 205
}pub fn load(path: &Path) -> Result<(InternalState, State), LoadError> {match std::fs::exists(path) {Ok(true) => {}Ok(false) => return Err(LoadError::DoesntExist),Err(e) => return Err(LoadError::Inaccessible(e)),}let repo = pijul::Repository::find_root(Some(path)).map_err(|_e| LoadError::NotPijulRepo)?;let internal_state = InternalState { repo };let state = get_state(&internal_state);Ok((internal_state, state))}pub fn hash_bytes(bytes: &[u8]) -> ChangeHash {let mut hasher = pijul::pristine::Hasher::default();hasher.update(bytes);hasher.finish()}/// Number of sections for nav-scrollable, containing untracked files, changed/// files, most recent log changes and a header for each of these 3 sections.pub fn nav_contents_count(repo: &State) -> usize {3 + repo.untracked_files.len() + repo.changed_files.len() + repo.log.len() - edit in libflorescence/src/repo.rs at line 296[9.1392]→[5.3056:3058](∅→∅),[5.3056]→[5.3056:3058](∅→∅),[5.3058]→[2.662:663](∅→∅),[2.662]→[2.662:663](∅→∅),[2.663]→[26.263:376](∅→∅),[26.376]→[22.1657:1906](∅→∅),[22.1657]→[22.1657:1906](∅→∅),[22.1906]→[9.1445:1538](∅→∅),[4.217]→[9.1445:1538](∅→∅),[9.1538]→[22.1907:1939](∅→∅)
}pub(crate) fn load(path: &Path) -> Result<(InternalState, State), LoadError> {match std::fs::exists(path) {Ok(true) => {}Ok(false) => return Err(LoadError::DoesntExist),Err(e) => return Err(LoadError::Inaccessible(e)),}let repo = pijul::Repository::find_root(Some(path)).map_err(|_e| LoadError::NotPijulRepo)?;let internal_state = InternalState { repo };let state = get_state(&internal_state);Ok((internal_state, state)) - edit in libflorescence/src/repo.rs at line 298
pub fn hash_bytes(bytes: &[u8]) -> ChangeHash {let mut hasher = pijul::pristine::Hasher::default();hasher.update(bytes);hasher.finish()} - edit in inflorescence_view/src/app.rs at line 7
use iced_nav_scrollable::NavScrollable; - replacement in inflorescence_view/src/app.rs at line 28
pub repo: Option<&'a repo::State>,pub repo: Option<&'a Repo>, - edit in inflorescence_view/src/app.rs at line 36
#[derive(Debug)]pub struct Repo {pub state: repo::State,/// Scrollable status view contains the overview of untracked files,/// changed files and most recent log changes.pub status_nav: NavScrollable,} - edit in inflorescence_view/src/app.rs at line 48
StatusNav(iced_nav_scrollable::Msg), - replacement in inflorescence_view/src/app.rs at line 74
let inner = if let Some(repo) = state.repo.as_ref() {let inner = if let Some(repo) = state.repo { - replacement in inflorescence_view/src/app.rs at line 85[10.15950]→[30.565:583](∅→∅),[30.583]→[23.279:329](∅→∅),[23.279]→[23.279:329](∅→∅),[23.329]→[30.584:615](∅→∅)
fn view_repo<'a>(state: &State<'a>,repo: &'a repo::State,) -> Element<'a, Msg, Theme> {fn view_repo<'a>(state: &State<'a>, repo: &'a Repo) -> Element<'a, Msg, Theme> {let Repo {state: repo,status_nav,} = repo; - replacement in inflorescence_view/src/app.rs at line 101
el(column(repo.untracked_files.iter().enumerate().map(repo.untracked_files.iter().enumerate().map( - replacement in inflorescence_view/src/app.rs at line 116
)))) - replacement in inflorescence_view/src/app.rs at line 120
el(column(repo.changed_files.iter().enumerate().map(repo.changed_files.iter().enumerate().map( - replacement in inflorescence_view/src/app.rs at line 136
)))) - replacement in inflorescence_view/src/app.rs at line 140
el(column(repo.log.iter().enumerate().map(repo.log.iter().enumerate().map( - replacement in inflorescence_view/src/app.rs at line 160
)))) - replacement in inflorescence_view/src/app.rs at line 228
let entry = state.repo.as_ref().unwrap().log.get(*ix).unwrap();let entry = repo.log.get(*ix).unwrap(); - edit in inflorescence_view/src/app.rs at line 279
let status_nav_children = [el(text("Untracked files:"))].into_iter().chain(untracked_files()).chain([el(text("Changed files:"))]).chain(changed_files()).chain([el(text("Recent changes:"))]).chain(log());let status_nav_children_len = repo::nav_contents_count(repo); - replacement in inflorescence_view/src/app.rs at line 291
el(scrollable(column([el(column([el(text("Untracked files:")), untracked_files()])),el(column([el(text("Changed files:")), changed_files()])),el(column([el(text("Recent changes:")), log()])),]))),el(iced_nav_scrollable::view(status_nav,status_nav_children,status_nav_children_len,Msg::StatusNav,)), - replacement in inflorescence_view/src/app/test.rs at line 1
use super::{cursor, view, State};use super::{cursor, view, Repo, State}; - replacement in inflorescence_view/src/app/test.rs at line 11
use std::collections::{BTreeMap, BTreeSet};use std::collections::{BTreeMap, BTreeSet, HashSet}; - replacement in inflorescence_view/src/app/test.rs at line 49
let repo = Some(repo::State {let repo_state = repo::State { - edit in inflorescence_view/src/app/test.rs at line 55
};let contents_count = repo::nav_contents_count(&repo_state);let (status_nav, _task) =iced_nav_scrollable::init(contents_count, HashSet::new());let repo = Some(Repo {state: repo_state,status_nav, - replacement in inflorescence_view/src/app/test.rs at line 77
let repo = Some(repo::State {let repo_state = repo::State { - edit in inflorescence_view/src/app/test.rs at line 96
};let contents_count = repo::nav_contents_count(&repo_state);let (status_nav, _task) =iced_nav_scrollable::init(contents_count, HashSet::new());let repo = Some(Repo {state: repo_state,status_nav, - replacement in inflorescence/src/test.rs at line 78
assert_eq!(state.repo.as_ref().unwrap().log.len(), INITIAL_LOG_LEN);assert_eq!(state.repo.as_ref().unwrap().state.log.len(),INITIAL_LOG_LEN); - replacement in inflorescence/src/test.rs at line 158
assert_eq!(state.repo.as_ref().unwrap().log.len(), INITIAL_LOG_LEN + 1);assert_eq!(state.repo.as_ref().unwrap().state.log.len(),INITIAL_LOG_LEN + 1); - replacement in inflorescence/src/test.rs at line 301
assert!(state.repo.as_ref().unwrap().untracked_files.is_empty());assert!(state.repo.as_ref().unwrap().changed_files.is_empty());{let repo_state = &state.repo.as_ref().unwrap().state;assert!(repo_state.untracked_files.is_empty());assert!(repo_state.changed_files.is_empty());} - replacement in inflorescence/src/test.rs at line 327
assert_eq!(state.repo.as_ref().unwrap().untracked_files.len(), 1);assert!(state.repo.as_ref().unwrap().untracked_files.contains(file_to_record));assert!(state.repo.as_ref().unwrap().changed_files.is_empty());{let repo_state = &state.repo.as_ref().unwrap().state;assert_eq!(repo_state.untracked_files.len(), 1);assert!(repo_state.untracked_files.contains(file_to_record));assert!(repo_state.changed_files.is_empty());} - replacement in inflorescence/src/test.rs at line 358
assert!(state.repo.as_ref().unwrap().untracked_files.is_empty());assert_eq!(state.repo.as_ref().unwrap().changed_files.len(), 1);assert!(state.repo.as_ref().unwrap().changed_files.contains_key(file_to_record));assert_eq!(state.repo.as_ref().unwrap().changed_files.get(file_to_record).unwrap(),&BTreeSet::from_iter([repo::ChangedFileDiff::Add]));{let repo_state = &state.repo.as_ref().unwrap().state;assert!(repo_state.untracked_files.is_empty());assert_eq!(repo_state.changed_files.len(), 1);assert!(repo_state.changed_files.contains_key(file_to_record));assert_eq!(repo_state.changed_files.get(file_to_record).unwrap(),&BTreeSet::from_iter([repo::ChangedFileDiff::Add]));} - replacement in inflorescence/src/test.rs at line 391
assert_eq!(state.repo.as_ref().unwrap().untracked_files.len(), 1);assert!(state.repo.as_ref().unwrap().untracked_files.contains(file_to_record));assert!(state.repo.as_ref().unwrap().changed_files.is_empty());{let repo_state = &state.repo.as_ref().unwrap().state;assert_eq!(repo_state.untracked_files.len(), 1);assert!(repo_state.untracked_files.contains(file_to_record));assert!(repo_state.changed_files.is_empty());} - replacement in inflorescence/src/test.rs at line 426
} = &state.repo.as_ref().unwrap();} = &state.repo.as_ref().unwrap().state; - replacement in inflorescence/src/test.rs at line 750
let log = &state.repo.as_ref().unwrap().log;let log = &state.repo.as_ref().unwrap().state.log; - replacement in inflorescence/src/main.rs at line 26
use std::collections::BTreeSet;use std::collections::{BTreeSet, HashSet}; - replacement in inflorescence/src/main.rs at line 116
repo: Option<repo::State>,repo: Option<app::Repo>, - replacement in inflorescence/src/main.rs at line 177
let loaded =file::update(&mut state.files, state.repo.as_ref(), msg);let loaded = file::update(&mut state.files,state.repo.as_ref().map(|repo| &repo.state),msg,); - replacement in inflorescence/src/main.rs at line 271
state.repo.as_ref(),state.repo.as_ref().map(|repo| &repo.state), - edit in inflorescence/src/main.rs at line 335
app::Msg::StatusNav(msg) => {if let Some(nav) =state.repo.as_mut().map(|repo| &mut repo.status_nav){iced_nav_scrollable::update(nav, msg).map(|msg| Msg::View(app::Msg::StatusNav(msg)))} else {Task::none()}} - replacement in inflorescence/src/main.rs at line 372
if let Some(repo) = state.repo.as_mut()if let Some(app::Repo {state: repo_state,status_nav,}) = state.repo.as_mut() - replacement in inflorescence/src/main.rs at line 387
let removed = repo.untracked_files.remove(path);debug_assert!(removed, "{:?}, path: {path}", repo.untracked_files);repo.changed_fileslet removed = repo_state.untracked_files.remove(path);debug_assert!(removed,"{:?}, path: {path}",repo_state.untracked_files);repo_state.changed_files - edit in inflorescence/src/main.rs at line 398
// Re-initialize navlet contents_count = repo::nav_contents_count(repo_state);let (new_status_nav, status_nav_task) =iced_nav_scrollable::init(contents_count, HashSet::default());*status_nav = new_status_nav; - replacement in inflorescence/src/main.rs at line 406
state.cursor.selection = if repo.untracked_files.is_empty() {state.cursor.selection = if repo_state.untracked_files.is_empty() { - replacement in inflorescence/src/main.rs at line 409
let ix = cmp::min(*ix, repo.untracked_files.len() - 1);Some(cursor::untracked_file_selection(repo, ix, &mut state.files))let ix = cmp::min(*ix, repo_state.untracked_files.len() - 1);Some(cursor::untracked_file_selection(repo_state,ix,&mut state.files,)) - edit in inflorescence/src/main.rs at line 416
return status_nav_task.map(|msg| Msg::View(app::Msg::StatusNav(msg))); - replacement in inflorescence/src/main.rs at line 423
if let Some(repo) = state.repo.as_mut()if let Some(app::Repo {state: repo_state,status_nav,}) = state.repo.as_mut() - replacement in inflorescence/src/main.rs at line 433
let diffs = repo.changed_files.get(path).unwrap();let diffs = repo_state.changed_files.get(path).unwrap(); - replacement in inflorescence/src/main.rs at line 444
let removed = repo.changed_files.remove(path);let removed = repo_state.changed_files.remove(path); - replacement in inflorescence/src/main.rs at line 449
repo.changed_filesrepo_state.changed_files - replacement in inflorescence/src/main.rs at line 452
repo.untracked_files.insert(path.clone());repo_state.untracked_files.insert(path.clone());// Re-initialize navlet contents_count = repo::nav_contents_count(repo_state);let (new_status_nav, status_nav_task) =iced_nav_scrollable::init(contents_count, HashSet::default());*status_nav = new_status_nav; - replacement in inflorescence/src/main.rs at line 461
state.cursor.selection = if repo.changed_files.is_empty() {state.cursor.selection = if repo_state.changed_files.is_empty() { - replacement in inflorescence/src/main.rs at line 464
let ix = cmp::min(*ix, repo.changed_files.len() - 1);Some(cursor::changed_file_selection(repo, ix, &mut state.files))let ix = cmp::min(*ix, repo_state.changed_files.len() - 1);Some(cursor::changed_file_selection(repo_state,ix,&mut state.files,)) - edit in inflorescence/src/main.rs at line 471
return status_nav_task.map(|msg| Msg::View(app::Msg::StatusNav(msg))); - replacement in inflorescence/src/main.rs at line 484
if repo.changed_files.is_empty() {if repo.state.changed_files.is_empty() { - replacement in inflorescence/src/main.rs at line 528
state.repo.as_mut().unwrap().changed_files =state.repo.as_mut().unwrap().state.changed_files = - replacement in inflorescence/src/main.rs at line 633
state.repo = Some(repo);let contents_count = repo::nav_contents_count(&repo);let (status_nav, status_nav_task) =iced_nav_scrollable::init(contents_count, HashSet::default());state.repo = Some(app::Repo {state: repo,status_nav,}); - replacement in inflorescence/src/main.rs at line 677
watch_taskTask::batch([status_nav_task.map(|msg| Msg::View(app::Msg::StatusNav(msg))),watch_task,]) - replacement in inflorescence/src/main.rs at line 695
let task = reindex_selection(let cursor_task = reindex_selection( - replacement in inflorescence/src/main.rs at line 703
state.repo = Some(repo);let contents_count = repo::nav_contents_count(&repo);let (status_nav, status_nav_task) =iced_nav_scrollable::init(contents_count, HashSet::default()); - replacement in inflorescence/src/main.rs at line 707
taskstate.repo = Some(app::Repo {state: repo,status_nav,});Task::batch([cursor_task,status_nav_task.map(|msg| Msg::View(app::Msg::StatusNav(msg))),]) - replacement in inflorescence/src/main.rs at line 1030
let nav_subs = match state.cursor.selection.as_ref() {let status_nav_sub = if state.repo.is_some() {iced_nav_scrollable::subs().map(|msg| Msg::View(app::Msg::StatusNav(msg)))} else {Subscription::none()};let diff_nav_subs = match state.cursor.selection.as_ref() { - replacement in inflorescence/src/main.rs at line 1093
nav_subs,status_nav_sub,diff_nav_subs, - replacement in iced_nav_scrollable/src/lib.rs at line 239
debug_assert_eq!(nav.section_heights.len(), children_len, "The `NavScrollable` was most likely initialized with a count different from the number of actual children given to the the view function. Count is {}, but got {} children", nav.section_heights.len(), children_len);debug_assert_eq!(nav.section_heights.len(), children_len, "The `NavScrollable` was most likely initialized with a count different from the number of actual children given to the the view function. Actual number is {}, but got {} children_len arg", nav.section_heights.len(), children_len);