diffs selection and scrolling
[?]
Jul 10, 2025, 8:48 PM
KWTBNTO3QUUE2YADF6SYW6G6ZOKYEWRJQKIWDGZXR33S3YNDVIZQCDependencies
- [2]
6YZAVBWUInitial commit - [3]
IQDCHWCPload a pijul repo - [4]
SWWE2R6Mdisplay basic repo stuff - [5]
WT3GA27Padd cursor with selection - [6]
UB2ITZJSrefresh changed files on FS changes - [7]
KT5UYXGKfix selection after adding file, add changed file diffs - [8]
ELG3UDT6allow to rm added files - [9]
S2NVIFXRallow to enter record msg - [10]
W7IUT3ZVstart recording impl - [11]
YBJRDOTCmake all repo actions async - [12]
A5YBC77Vrecord! - [13]
D7A7MSIHallow to defer or abandon record, add buttons - [14]
4WO3ZJM2show untracked files' contents - [15]
BJXUYQ2Yshow untracked file contents in read-only text editor - [16]
W4LFX7IHgroup diffs by file name - [17]
AMPZ2BXKshow changed files diffs (only Edit atm) - [18]
FDDPOH5Radd arrow controls - [19]
V55EAIWQadd src file LRU cache - [20]
ZVI4AWERwoot contents_diff - [21]
OQ6HSAWHshow record log - [22]
WI2BVQ6Jrm client lib crate - [23]
DCSUCH6Radd undecoded diff view, improve decoded view style - [24]
JE44NYHMdisplay log files diffs - [25]
ONRCENKTrm unnecessary state from repo's internal state - [26]
4ELJZGRJload and store all change diffs at once - [27]
FR52XEMWadd action for log change file diff - [28]
L6KSEFQImove cursor related stuff into its module - [29]
BFN2VHZSrefactor file stuff into sub-mod - [30]
VJNWIGSXclippy - [31]
GWZGYNIBadd view crate - [32]
23SFYK4Qbig view refactor into a new crate - [33]
MYGIBRRHwip custom theme - [34]
PKJCFSBMtheme improvements - [35]
XSZZB47Urefactor stuff into lib - [36]
XIASAP3Gclippy - [37]
3BK22XE5add a test for hover btn and more refactors - [38]
WGID4LS4absolutely slayed testing with iced task - [39]
VCNKFNUFapp init test - [40]
ACDXXAX2refactor main's updates into smaller fns - [41]
I56UGW7Umake record test, fix log update - [42]
X6AK4QPXfinish recording test - [43]
5CYU7UT7test: rm added file - [44]
ESMM3FELtest selection reindexing - [45]
TSFQFCB2test got repo change - [46]
UF5NJKAStest load repo - [47]
7SSBM4UQview: refactor repo view - [48]
S2T7RUKWadd nav back placeholder - [49]
I2AG42PAnew cols layout - [50]
4PNWU55Oreplace the circular hor navigation - [51]
WW36JYLRadd iced_nav_scrollable widget crate - [52]
WIFVLV37nav-scrollabe: detect size to determine if needs scrolling, msg when ready - [53]
SASAN2XCuse nav-scrollable - [54]
YKHE3XMWrefactor diffs handling - [55]
KEPKF3WOunify diffs handling, simplify view - [56]
GOLHUD6Rnav-scrollable: set skip-able sections - [57]
XHWLKCLDauto-scroll past skip sections on load - [58]
K5YUSV2Wauto-scroll to last offset - [59]
KM5PSZ4Awatch repo once loaded - [60]
Y5ATDI2Hconvert changed file diffs and load src only if any needs it - [61]
F542TMBEtest log - [62]
B4RMW5AEadd syntax highlighter to untracked files contents - [63]
SWDPAGF6test channel name - [64]
QMAUTRB6refactor diff - [65]
XZ6D3UUEavoid alloc - [66]
AHWWRC73navigate log entries - [67]
NWJD6VM6mv libflowers libflorescence - [68]
Z2CJPWZEfocus record message text_editor on spawn - [69]
HC7ROIBCmove main diffs state out of cursor - [70]
PTFDJ567add untracked files encoding - [71]
YYKXNBFLtest: add untracked file - [72]
UMO6U2ZTpartition the change files diffs on whether they have content - [73]
SGOJEZNOfix - [*]
OPXFZKEBview tests setup - [*]
MJDGPSHGWIP contents diff
Change contents
- edit in libflorescence/src/repo.rs at line 4
#[doc(inline)]pub use pijul::Hash as ChangeHash; - replacement in libflorescence/src/repo.rs at line 17
working_copy, ChannelMutTxnT, ChannelTxnT, Encoding, Hash, HashSet,MutTxnT, MutTxnTExt, TxnT, TxnTExt,working_copy, ChannelMutTxnT, ChannelTxnT, Encoding, HashSet, MutTxnT,MutTxnTExt, TxnT, TxnTExt, - replacement in libflorescence/src/repo.rs at line 143
hash: pijul::Hash,hash: ChangeHash, - replacement in libflorescence/src/repo.rs at line 160
hash: pijul::Hash,hash: ChangeHash, - replacement in libflorescence/src/repo.rs at line 165
pub type Diff = LocalChange<Hunk<Option<Hash>, Local>, Author>;pub type Diff = LocalChange<Hunk<Option<ChangeHash>, Local>, Author>; - replacement in libflorescence/src/repo.rs at line 171
pub hash: pijul::Hash,pub hash: ChangeHash, - edit in libflorescence/src/repo.rs at line 176[21.252]→[24.136:204](∅→∅),[24.204]→[55.6:64](∅→∅),[55.64]→[24.238:263](∅→∅),[24.238]→[24.238:263](∅→∅)
#[derive(Debug, Clone, Hash, PartialEq, Eq)]pub struct LogFileId {/// Hash of the log changepub hash: pijul::Hash,pub path: String,} - edit in libflorescence/src/repo.rs at line 286
pub fn hash_bytes(bytes: &[u8]) -> ChangeHash {let mut hasher = pijul::pristine::Hasher::default();hasher.update(bytes);hasher.finish()} - replacement in libflorescence/src/repo.rs at line 605
match dbg!(change) {// match dbg!(change) {match change { - replacement in libflorescence/src/repo.rs at line 838
let entry = mk_log_entry(repo, pijul::Hash::from(hash));let entry = mk_log_entry(repo, ChangeHash::from(hash)); - replacement in libflorescence/src/repo.rs at line 852
fn mk_log_entry(repo: &pijul::Repository, hash: pijul::Hash) -> LogEntry {fn mk_log_entry(repo: &pijul::Repository, hash: ChangeHash) -> LogEntry { - edit in libflorescence/src/lib.rs at line 10[39.2186]
#[doc(inline)]pub use std::hash::DefaultHasher;pub type AHash = u64;pub fn hasher() -> DefaultHasher {DefaultHasher::new()}pub fn hash_one<T>(x: T) -> u64whereT: std::hash::Hash,{let mut hasher = hasher();x.hash(&mut hasher);std::hash::Hasher::finish(&hasher)}pub type NoHashMap<K, V> = std::collections::HashMap<K, V, BuildNoHashHasher>;pub type BuildNoHashHasher = std::hash::BuildHasherDefault<NoHashHasher>;#[derive(Debug, Default)]pub struct NoHashHasher(u64);impl std::hash::Hasher for NoHashHasher {fn write(&mut self, _: &[u8]) {unimplemented!("Invalid use of NoHashHasher")}fn write_u8(&mut self, n: u8) {self.0 = u64::from(n)}fn write_u16(&mut self, n: u16) {self.0 = u64::from(n)}fn write_u32(&mut self, n: u32) {self.0 = u64::from(n)}fn write_u64(&mut self, n: u64) {self.0 = n}fn write_usize(&mut self, n: usize) {self.0 = n as u64}fn write_i8(&mut self, n: i8) {self.0 = n as u64}fn write_i16(&mut self, n: i16) {self.0 = n as u64}fn write_i32(&mut self, n: i32) {self.0 = n as u64}fn write_i64(&mut self, n: i64) {self.0 = n as u64}fn write_isize(&mut self, n: isize) {self.0 = n as u64}fn finish(&self) -> u64 {self.0}} - replacement in libflorescence/src/file.rs at line 1
use crate::diff;use crate::{diff, hash_one, repo, AHash, NoHashMap}; - edit in libflorescence/src/file.rs at line 6
pub file_kind: Kind,}#[derive(Debug, Clone, Hash, PartialEq, Eq)]pub struct IdRef<'a> {pub path: &'a str, - edit in libflorescence/src/file.rs at line 13
}#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]pub struct IdHash(pub AHash);pub type IdMap<V> = NoHashMap<IdHash, V>;#[derive(Debug, Clone, Hash, PartialEq, Eq)]pub struct LogId {/// Hash of the log changepub hash: repo::ChangeHash,pub path: String,}#[derive(Debug, Clone, Hash, PartialEq, Eq)]pub struct LogIdRef<'a> {pub hash: repo::ChangeHash,pub path: &'a str, - edit in libflorescence/src/file.rs at line 32
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]pub struct LogIdHash(pub AHash);pub type LogIdMap<V> = NoHashMap<LogIdHash, V>; - edit in libflorescence/src/file.rs at line 48
}pub fn id_hash(id: &Id) -> IdHash {IdHash(hash_one(id))}pub fn id_ref_hash(id: &IdRef<'_>) -> IdHash {IdHash(hash_one(id))}pub fn id_parts_hash(path: &str, file_kind: Kind) -> IdHash {id_ref_hash(&IdRef { path, file_kind })}pub fn log_id_hash(id: &LogId) -> LogIdHash {LogIdHash(hash_one(id))}pub fn log_id_ref_hash(id: &LogIdRef<'_>) -> LogIdHash {LogIdHash(hash_one(id))}pub fn log_id_parts_hash(hash: repo::ChangeHash, path: &str) -> LogIdHash {log_id_ref_hash(&LogIdRef { path, hash })}#[cfg(test)]mod test {use super::*;#[test]fn id_hash_eq_id_ref_hash() {let path = "some random path";let file_kind = Kind::Untracked;assert_eq!(id_ref_hash(&IdRef { path, file_kind }),id_hash(&Id {path: path.to_string(),file_kind}));assert_eq!(id_ref_hash(&IdRef { path, file_kind }),id_parts_hash(path, file_kind),);assert_ne!(id_ref_hash(&IdRef { path, file_kind }),id_hash(&Id {path: path.to_string(),file_kind: Kind::Changed}));}#[test]fn log_id_hash_eq_log_id_ref_hash() {let path = "some change file path";let hash = repo::hash_bytes(&[0, 1, 2]);assert_eq!(log_id_ref_hash(&LogIdRef { path, hash }),log_id_hash(&LogId {path: path.to_string(),hash}));assert_eq!(log_id_ref_hash(&LogIdRef { path, hash }),log_id_parts_hash(hash, path),);assert_ne!(log_id_ref_hash(&LogIdRef { path, hash }),log_id_hash(&LogId {path: path.to_string(),hash: repo::hash_bytes(&[255])}));} - edit in inflorescence_view/src/theme.rs at line 91
Selected, - replacement in inflorescence_view/src/theme.rs at line 218
let background =palette::Background::new(PALETTE.background, PALETTE.text);let background = palette::Background::new(match class {Scrollable::Normal => PALETTE.background,Scrollable::Selected => MAGENTA_DARKEST,},PALETTE.text,); - replacement in inflorescence_view/src/theme.rs at line 230
color: background.strong.color,color: match class {Scrollable::Normal => background.strong.color,Scrollable::Selected => MAGENTA_LIGHTEST,}, - replacement in inflorescence_view/src/diff.rs at line 28
pub fn view<'a>(state: &'a State, file: &'a File) -> Element<'a, Msg, Theme> {pub fn view<'a>(state: &'a State,file: &'a File,diff_selected: bool,) -> Element<'a, Msg, Theme> { - replacement in inflorescence_view/src/diff.rs at line 34
File::Decoded(decoded_file) => view_decoded(state, decoded_file),File::Decoded(decoded_file) => {view_decoded(state, decoded_file, diff_selected)} - replacement in inflorescence_view/src/diff.rs at line 38
view_undecodable(state, undecodable_file)view_undecodable(state, undecodable_file, diff_selected) - edit in inflorescence_view/src/diff.rs at line 46
diff_selected: bool, - replacement in inflorescence_view/src/diff.rs at line 104
))).class(if diff_selected {theme::Scrollable::Selected} else {theme::Scrollable::Normal})) - edit in inflorescence_view/src/diff.rs at line 129
diff_selected: bool, - replacement in inflorescence_view/src/diff.rs at line 147
el(iced_nav_scrollable::view(nav,diffs,diffs_len,Msg::NavScrollable,))el(iced_nav_scrollable::view(nav,diffs,diffs_len,Msg::NavScrollable,).class(if diff_selected {theme::Scrollable::Selected} else {theme::Scrollable::Normal}),) - edit in inflorescence_view/src/cursor.rs at line 22
diff_selected: bool, - edit in inflorescence_view/src/cursor.rs at line 27
diff_selected: bool, - edit in inflorescence_view/src/cursor.rs at line 41
pub diff_selected: bool, - replacement in inflorescence_view/src/app.rs at line 44
id: file::Id,id_hash: file::IdHash, - replacement in inflorescence_view/src/app.rs at line 169
Some(cursor::Selection::UntrackedFile { ix: _, path }) => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Untracked,};Some(cursor::Selection::UntrackedFile {ix: _,path,diff_selected,}) => {let id_hash = file::id_parts_hash(path, file::Kind::Untracked); - replacement in inflorescence_view/src/app.rs at line 176[55.668]→[55.668:770](∅→∅),[54.629]→[47.2046:2253](∅→∅),[55.770]→[47.2046:2253](∅→∅),[47.2046]→[47.2046:2253](∅→∅)
Some((file, state)) => {diff::view(state, file).map(move |msg| {Msg::FileDiffsContentsAction {id: id.clone(),action: msg,}})}Some((file, state)) => diff::view(state, file, *diff_selected).map(move |msg| Msg::FileDiffsContentsAction {id_hash,action: msg,}), - replacement in inflorescence_view/src/app.rs at line 190
Some(cursor::Selection::ChangedFile { path, ix: _ }) => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};Some(cursor::Selection::ChangedFile {path,ix: _,diff_selected,}) => {let id_hash = file::id_parts_hash(path, file::Kind::Changed); - replacement in inflorescence_view/src/app.rs at line 197[55.877]→[55.877:979](∅→∅),[54.705]→[47.2987:3194](∅→∅),[55.979]→[47.2987:3194](∅→∅),[47.2987]→[47.2987:3194](∅→∅)
Some((file, state)) => {diff::view(state, file).map(move |msg| {Msg::FileDiffsContentsAction {id: id.clone(),action: msg,}})}Some((file, state)) => diff::view(state, file, *diff_selected).map(move |msg| Msg::FileDiffsContentsAction {id_hash,action: msg,}), - replacement in inflorescence_view/src/app.rs at line 299
file: Some(cursor::LogChangeFileSelection { ix: _, path }),file:Some(cursor::LogChangeFileSelection {ix: _,path,diff_selected,}), - replacement in inflorescence_view/src/app.rs at line 313
diff::view(state, file).map(|action| {diff::view(state, file, *diff_selected).map(|action| { - replacement in inflorescence_view/src/app.rs at line 324
.width(Length::Fill).height(Length::Fill)// .width(Length::Fill)// .height(Length::Fill) - edit in inflorescence_view/src/app/test.rs at line 131
diff_selected: false, - edit in inflorescence/src/test.rs at line 7
use libflorescence::prelude::pijul; - edit in inflorescence/src/test.rs at line 184
diff_selected: false, - edit in inflorescence/src/test.rs at line 380
let _msg = task::await_next_msg(&mut tasks).await; - edit in inflorescence/src/test.rs at line 461
diff_selected: false, - replacement in inflorescence/src/test.rs at line 474
cursor::Selection::UntrackedFile { ix, path }if *ix == 1 && path == "untracked_1.rs"cursor::Selection::UntrackedFile { ix, path, diff_selected }if *ix == 1 && path == "untracked_1.rs" && !diff_selected - replacement in inflorescence/src/test.rs at line 481
state.files.diffs_cache.inner.peek(&file::Id {path: "untracked_1.rs".to_string(),file_kind: file::Kind::Untracked}),state.files.diffs_cache.inner.peek(&file::id_parts_hash("untracked_1.rs",file::Kind::Untracked)), - edit in inflorescence/src/test.rs at line 496
diff_selected: false, - edit in inflorescence/src/test.rs at line 527
diff_selected: false, - replacement in inflorescence/src/test.rs at line 540
cursor::Selection::ChangedFile { ix, path }if *ix == 0 && path == "changed_0.rs"cursor::Selection::ChangedFile { ix, path, diff_selected }if *ix == 0 && path == "changed_0.rs" && !diff_selected - replacement in inflorescence/src/test.rs at line 547
state.files.diffs_cache.inner.peek(&file::Id {path: "changed_0.rs".to_string(),file_kind: file::Kind::Changed}),state.files.diffs_cache.inner.peek(&file::id_parts_hash("changed_0.rs", file::Kind::Changed)), - edit in inflorescence/src/test.rs at line 564
diff_selected: false, - replacement in inflorescence/src/test.rs at line 577
cursor::Selection::ChangedFile { ix, path }if *ix == 1 && path == "changed_1.rs"cursor::Selection::ChangedFile { ix, path, diff_selected }if *ix == 1 && path == "changed_1.rs" && !diff_selected - edit in inflorescence/src/test.rs at line 590
diff_selected: false, - replacement in inflorescence/src/test.rs at line 608
let change_hash_0 = change_hash(&[0]);let change_hash_1 = change_hash(&[1]);let change_hash_2 = change_hash(&[2]);let change_hash_0 = repo::hash_bytes(&[0]);let change_hash_1 = repo::hash_bytes(&[1]);let change_hash_2 = repo::hash_bytes(&[2]); - edit in inflorescence/src/test.rs at line 659
diff_selected: false, - replacement in inflorescence/src/test.rs at line 687
let change_hash_0 = change_hash(&[0]);let change_hash_1 = change_hash(&[1]);let change_hash_0 = repo::hash_bytes(&[0]);let change_hash_1 = repo::hash_bytes(&[1]); - replacement in inflorescence/src/test.rs at line 724
// Initializes nav-scrollables for diffsassert!(task.is_some());assert!(task.is_none()); - edit in inflorescence/src/test.rs at line 771
/// Tasks to open window, set icon, tasks replies from repo, load user id/// and files - edit in inflorescence/src/test.rs at line 780
fn change_hash(bytes: &[u8]) -> pijul::Hash {let mut hasher = pijul::pristine::Hasher::default();hasher.update(bytes);hasher.finish()} - replacement in inflorescence/src/main.rs at line 14
use iced::widget::{scrollable, text_editor};use iced::widget::text_editor; - replacement in inflorescence/src/main.rs at line 26
use std::collections::{BTreeSet, HashMap};use std::collections::BTreeSet; - replacement in inflorescence/src/main.rs at line 102
files_diffs: HashMap::new(),log_diffs: HashMap::new(),files_diffs: diff::FilesState::default(),logs: diff::LogFilesAndState::default(), - replacement in inflorescence/src/main.rs at line 122
files_diffs: HashMap<file::Id, diff::State>,files_diffs: diff::FilesState, - replacement in inflorescence/src/main.rs at line 124
log_diffs: HashMap<repo::LogFileId, LogFileDiff>,logs: diff::LogFilesAndState, - replacement in inflorescence/src/main.rs at line 139
DiffStateNav {id: file::Id,DiffNav {id_hash: file::IdHash, - replacement in inflorescence/src/main.rs at line 143
LogChangeDiff {hash: pijul::Hash,file: String,LogDiffNav {id_hash: file::LogIdHash, - edit in inflorescence/src/main.rs at line 149[54.3368]→[54.3368:3460](∅→∅),[15.122]→[5.735:737](∅→∅),[27.134]→[5.735:737](∅→∅),[13.216]→[5.735:737](∅→∅),[9.240]→[5.735:737](∅→∅),[8.649]→[5.735:737](∅→∅),[10.1205]→[5.735:737](∅→∅),[17.1921]→[5.735:737](∅→∅),[53.2662]→[5.735:737](∅→∅),[14.2792]→[5.735:737](∅→∅),[54.3460]→[5.735:737](∅→∅),[7.4637]→[5.735:737](∅→∅),[5.735]→[5.735:737](∅→∅),[5.737]→[2.3098:3099](∅→∅),[4.5117]→[2.3098:3099](∅→∅),[2.3098]→[2.3098:3099](∅→∅)
#[derive(Debug)]struct LogFileDiff {pub diff: diff::File,pub state: diff::State,} - replacement in inflorescence/src/main.rs at line 180
id,id_hash: id, - replacement in inflorescence/src/main.rs at line 192
let id_clone = id.clone();return tasks.map(move |msg| Msg::DiffStateNav {id: id_clone.clone(),return tasks.map(move |msg| Msg::DiffNav {id_hash: id, - replacement in inflorescence/src/main.rs at line 199
Msg::DiffStateNav { id, msg } => {Msg::DiffNav { id_hash: id, msg } => { - replacement in inflorescence/src/main.rs at line 203
return task.map(move |msg| Msg::DiffStateNav {id: id_clone.clone(),return task.map(move |msg| Msg::DiffNav {id_hash: id_clone.clone(), - replacement in inflorescence/src/main.rs at line 210[53.3747]→[53.3747:3799](∅→∅),[53.3799]→[55.2963:3018](∅→∅),[55.3018]→[53.3874:3963](∅→∅),[53.3874]→[53.3874:3963](∅→∅),[53.3963]→[54.3604:3680](∅→∅),[54.3680]→[53.4024:4073](∅→∅),[53.4024]→[53.4024:4073](∅→∅)
Msg::LogChangeDiff { hash, file, msg } => {if let Some(cursor::Selection::LogChange {ix: _,hash: selection_hash,message: _,file: Some(cursor::LogChangeFileSelection { ix: _, path }),}) = state.cursor.selection.as_mut()Msg::LogDiffNav { id_hash: id, msg } => {if let Some(diff::FileAndState { file: _, state }) =state.logs.diffs.get_mut(&id) - replacement in inflorescence/src/main.rs at line 214[53.4087]→[53.4087:4132](∅→∅),[53.4132]→[55.3019:3066](∅→∅),[55.3066]→[54.3722:4021](∅→∅),[54.3722]→[54.3722:4021](∅→∅),[54.4021]→[53.4276:4531](∅→∅),[53.4276]→[53.4276:4531](∅→∅)
if selection_hash == &hash {let id = repo::LogFileId {hash,path: path.clone(),};if let Some(LogFileDiff { diff: _, state }) =state.log_diffs.get_mut(&id){let task = diff::update(state, msg);return task.map(move |msg| Msg::LogChangeDiff {hash,file: file.clone(),msg,});}}let task = diff::update(state, msg);return task.map(move |msg| Msg::LogDiffNav {id_hash: id.clone(),msg,}); - edit in inflorescence/src/main.rs at line 266
msg, - replacement in inflorescence/src/main.rs at line 270
msg,&state.files_diffs,&state.logs, - replacement in inflorescence/src/main.rs at line 275
// If the selected file's diff is already loaded, scroll back to its// last offsetlet scroll_task = match state.cursor.selection.as_ref() {Some(cursor::Selection::UntrackedFile { ix: _, path }) => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Untracked,};if let Some(nav) = state.files_diffs.get(&id).and_then(|state| state.nav.as_ref()){task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset {x: 0.0,y: nav.offset,},)} else {Task::none()}}Some(cursor::Selection::ChangedFile { ix: _, path }) => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};if let Some(nav) = state.files_diffs.get(&id).and_then(|state| state.nav.as_ref()){task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset {x: 0.0,y: nav.offset,},)} else {Task::none()}}Some(cursor::Selection::LogChange {let init_log_nav_task =if let Some(cursor::Selection::LogChange { - replacement in inflorescence/src/main.rs at line 280
file: Some(cursor::LogChangeFileSelection { ix: _, path }),}) => {let id = repo::LogFileId {hash: *hash,path: path.clone(),};if let Some(nav) = state.log_diffs.get(&id).and_then(|diff| diff.state.nav.as_ref()){task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset {x: 0.0,y: nav.offset,},)} else {Task::none()file:Some(cursor::LogChangeFileSelection {ix: _,path,diff_selected: false,}),}) = state.cursor.selection.as_ref(){let id_hash = file::log_id_parts_hash(*hash, path);match state.logs.diffs.get_mut(&id_hash) {Some(log) if log.state.nav.is_none() => {let contents_count =diff::contents_count(&log.file);let unchanged_sections =diff::unchanged_sections(&log.file);let (nav, tasks) = iced_nav_scrollable::init(contents_count,unchanged_sections,);log.state.nav = Some(nav);tasks.map(move |msg| Msg::LogDiffNav {id_hash,msg: diff::Msg::NavScrollable(msg),})}_ => Task::none(), - edit in inflorescence/src/main.rs at line 307
} else {Task::none()};let get_diffs_task = if let Some(cursor::Selection::LogChange {ix: _,hash,message: _,file: None,}) = state.cursor.selection.as_ref(){if !state.logs.change_hashes.contains(hash) {Task::done(Msg::View(app::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash: *hash },)))} else {Task::none() - replacement in inflorescence/src/main.rs at line 325
Some(cursor::Selection::LogChange {ix: _,hash: _,message: _,file: None,})| None => Task::none(),} else {Task::none() - replacement in inflorescence/src/main.rs at line 329
Task::batch([cursor_task, scroll_task])Task::batch([cursor_task, get_diffs_task, init_log_nav_task]) - replacement in inflorescence/src/main.rs at line 339
app::Msg::FileDiffsContentsAction { id, action } => {file_diffs_contents_action(state, id, action)app::Msg::FileDiffsContentsAction { id_hash, action } => {file_diffs_contents_action(state, id_hash, action) - replacement in inflorescence/src/main.rs at line 363
if let Some(cursor::Selection::UntrackedFile { ix, path }) =state.cursor.selection.as_ref()if let Some(cursor::Selection::UntrackedFile {ix,path,diff_selected: _,}) = state.cursor.selection.as_ref() - replacement in inflorescence/src/main.rs at line 398
if let Some(cursor::Selection::ChangedFile { ix, path }) =state.cursor.selection.as_ref()if let Some(cursor::Selection::ChangedFile {ix,path,diff_selected: _,}) = state.cursor.selection.as_ref() - replacement in inflorescence/src/main.rs at line 524
id: file::Id,id_hash: file::IdHash, - replacement in inflorescence/src/main.rs at line 528[40.6538]→[40.6538:6738](∅→∅),[40.6738]→[54.4247:4325](∅→∅),[54.4325]→[53.6606:6825](∅→∅),[53.6606]→[53.6606:6825](∅→∅)
match (selection, id.file_kind) {(cursor::Selection::UntrackedFile { ix: _, path },file::Kind::Untracked,) if path == &id.path => {let diffs = state.files_diffs.entry(id.clone()).or_default();return diff::update(diffs, action).map(move |msg| {Msg::DiffStateNav {id: id.clone(),msg,}});match selection {cursor::Selection::UntrackedFile {ix: _,path,diff_selected: _,} => {let selection_hash =file::id_parts_hash(path, file::Kind::Untracked);if id_hash == selection_hash {let diffs = state.files_diffs.entry(id_hash).or_default();return diff::update(diffs, action).map(move |msg| Msg::DiffNav { id_hash, msg });} - replacement in inflorescence/src/main.rs at line 542[14.7369]→[40.6854:7008](∅→∅),[40.7008]→[54.4326:4404](∅→∅),[54.4404]→[53.6904:7104](∅→∅),[53.6904]→[53.6904:7104](∅→∅)
(cursor::Selection::ChangedFile { ix: _, path },file::Kind::Changed,) if path == &id.path => {let diffs = state.files_diffs.entry(id.clone()).or_default();let task = diff::update(diffs, action);return task.map(move |msg| Msg::DiffStateNav {id: id.clone(),msg,});cursor::Selection::ChangedFile {ix: _,path,diff_selected: _,} => {let selection_hash =file::id_parts_hash(path, file::Kind::Changed);if id_hash == selection_hash {let diffs = state.files_diffs.entry(id_hash).or_default();let task = diff::update(diffs, action);return task.map(move |msg| Msg::DiffNav { id_hash, msg });} - edit in inflorescence/src/main.rs at line 577
diff_selected: _, - replacement in inflorescence/src/main.rs at line 582
let id = repo::LogFileId {hash,path: file.clone(),};if let Some(LogFileDiff { diff: _, state }) =state.log_diffs.get_mut(&id)let id_hash = file::log_id_parts_hash(hash, &file);if let Some(diff::FileAndState { file: _, state }) =state.logs.diffs.get_mut(&id_hash) - replacement in inflorescence/src/main.rs at line 586
return diff::update(state, action).map(move |msg| {Msg::LogChangeDiff {hash,file: file.clone(),msg,}});return diff::update(state, action).map(move |msg| Msg::LogDiffNav { id_hash, msg }); - replacement in inflorescence/src/main.rs at line 668
cursor::Selection::UntrackedFile { ix: _, path } => {cursor::Selection::UntrackedFile {ix: _,path,diff_selected,} => { - edit in inflorescence/src/main.rs at line 680
diff_selected, - replacement in inflorescence/src/main.rs at line 695
cursor::Selection::ChangedFile { ix: _, path } => {cursor::Selection::ChangedFile {ix: _,path,diff_selected,} => { - edit in inflorescence/src/main.rs at line 708
diff_selected, - replacement in inflorescence/src/main.rs at line 739[40.11737]→[40.11737:12196](∅→∅),[29.1165]→[20.15057:15117](∅→∅),[40.12196]→[20.15057:15117](∅→∅),[20.15057]→[20.15057:15117](∅→∅),[20.15117]→[40.12197:12298](∅→∅)
let file = file.and_then(|file| {entry.file_paths.iter().enumerate().find(|(_ix, path)| *path == &file.path).map(|(ix, path)| {cursor::LogChangeFileSelection {ix,path: path.clone(),}})});let file = file.and_then(|cursor::LogChangeFileSelection {ix: _,path: selected_path,diff_selected,}| {entry.file_paths.iter().enumerate().find(|(_ix, path)| *path == &selected_path).map(|(ix, path)| {cursor::LogChangeFileSelection {ix,path: path.clone(),diff_selected,}})},); - edit in inflorescence/src/main.rs at line 801
let mut tasks = Vec::with_capacity(diffs.len()); - replacement in inflorescence/src/main.rs at line 804
let diff = diff::init_file(let file = diff::init_file( - replacement in inflorescence/src/main.rs at line 808[54.5282]→[54.5282:5348](∅→∅),[54.5348]→[56.361:596](∅→∅),[56.596]→[54.5450:5601](∅→∅),[54.5450]→[54.5450:5601](∅→∅)
let contents_count = diff::contents_count(&diff);let unchanged_sections = diff::unchanged_sections(&diff);let (nav, nav_tasks) = iced_nav_scrollable::init(contents_count,unchanged_sections,);let diff_state = diff::State {nav: Some(nav),state: libflorescence::diff::State::default(),let id_hash = file::log_id_parts_hash(hash, &path);let log_file_diff = diff::FileAndState {file,// The nav is initialized only once a file is selected,// because its tasks need it to be visible to completestate: diff::State::default(), - edit in inflorescence/src/main.rs at line 815[54.5620]→[54.5620:5667](∅→∅),[54.5667]→[55.3107:3164](∅→∅),[55.3164]→[54.5718:5852](∅→∅),[54.5718]→[54.5718:5852](∅→∅)
let path_clone = path.clone();let id = repo::LogFileId { hash, path };let log_file_diff = LogFileDiff {diff,state: diff_state,}; - replacement in inflorescence/src/main.rs at line 816
state.log_diffs.insert(id, log_file_diff);tasks.push(nav_tasks.map(move |msg| Msg::LogChangeDiff {hash,file: path_clone.clone(),msg: diff::Msg::NavScrollable(msg),}))state.logs.change_hashes.insert(hash);state.logs.diffs.insert(id_hash, log_file_diff); - edit in inflorescence/src/main.rs at line 819
return Task::batch(tasks); - replacement in inflorescence/src/main.rs at line 824
fn subs(_state: &State) -> Subscription<Msg> {fn subs(state: &State) -> Subscription<Msg> { - replacement in inflorescence/src/main.rs at line 877
Subscription::batch([key_subs, window_subs])let nav_subs = match state.cursor.selection.as_ref() {Some(cursor::Selection::UntrackedFile {ix: _,path,diff_selected: true,}) => {let id_hash = file::id_parts_hash(path, file::Kind::Untracked);iced_nav_scrollable::subs().with(id_hash).map(|(id_hash, msg)| Msg::DiffNav {id_hash,msg: diff::Msg::NavScrollable(msg),})}Some(cursor::Selection::ChangedFile {ix: _,path,diff_selected: true,}) => {let id_hash = file::id_parts_hash(path, file::Kind::Changed);iced_nav_scrollable::subs().with(id_hash).map(|(id_hash, msg)| Msg::DiffNav {id_hash,msg: diff::Msg::NavScrollable(msg),})}Some(cursor::Selection::LogChange {ix: _,hash,message: _,file:Some(cursor::LogChangeFileSelection {ix: _,path,diff_selected: true,}),}) => {let id_hash = file::log_id_parts_hash(*hash, path);iced_nav_scrollable::subs().with(id_hash).map(|(id_hash, msg)| Msg::LogDiffNav {id_hash,msg: diff::Msg::NavScrollable(msg),})}Some(cursor::Selection::UntrackedFile { .. })| Some(cursor::Selection::ChangedFile { .. })| Some(cursor::Selection::LogChange { .. })| None => Subscription::none(),};Subscription::batch([key_subs, window_subs, nav_subs]) - replacement in inflorescence/src/main.rs at line 943
files_diffs: diffs_state,log_diffs,files_diffs,logs: log_diffs, - replacement in inflorescence/src/main.rs at line 948
Some(cursor::Selection::UntrackedFile { ix: _, path }) => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Untracked,};let file = files.diffs_cache.inner.peek(&id);Some(cursor::Selection::UntrackedFile {ix: _,path,diff_selected: _,}) => {let id_hash = file::id_parts_hash(path, file::Kind::Untracked);let file = files.diffs_cache.inner.peek(&id_hash); - replacement in inflorescence/src/main.rs at line 957
diffs_state.get(&id).map(|state| (file, state))files_diffs.get(&id_hash).map(|state| (file, state)) - replacement in inflorescence/src/main.rs at line 962
Some(cursor::Selection::ChangedFile { path, ix: _ }) => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};let file = files.diffs_cache.inner.peek(&id);Some(cursor::Selection::ChangedFile {path,ix: _,diff_selected: _,}) => {let id_hash = file::id_parts_hash(path, file::Kind::Changed);let file = files.diffs_cache.inner.peek(&id_hash); - replacement in inflorescence/src/main.rs at line 971
diffs_state.get(&id).map(|state| (file, state))files_diffs.get(&id_hash).map(|state| (file, state)) - replacement in inflorescence/src/main.rs at line 980
file: Some(cursor::LogChangeFileSelection { ix: _, path }),file:Some(cursor::LogChangeFileSelection {ix: _,path,diff_selected: _,}), - replacement in inflorescence/src/main.rs at line 987
let id = repo::LogFileId {hash: *hash,path: path.clone(),};let id_hash = file::log_id_parts_hash(*hash, path); - replacement in inflorescence/src/main.rs at line 989
.get(&id).map(|LogFileDiff { diff: file, state }| (file, state)).diffs.get(&id_hash).map(|diff::FileAndState { file, state }| (file, state)) - replacement in inflorescence/src/file.rs at line 4
pub use libflorescence::file::{Diff, Id, Kind};pub use libflorescence::file::{id_hash, id_parts_hash, log_id_parts_hash, Diff, Id, IdHash, IdMap, Kind,LogIdHash, LogIdMap,}; - replacement in inflorescence/src/file.rs at line 53
CLruCache<Id, Diff, std::hash::RandomState, DiffsCacheWeight>;CLruCache<IdHash, Diff, std::hash::RandomState, DiffsCacheWeight>; - replacement in inflorescence/src/file.rs at line 97
pub id: Id,pub id_hash: IdHash, - edit in inflorescence/src/file.rs at line 122
let id_hash = id_hash(&id); - replacement in inflorescence/src/file.rs at line 133
id.clone(),id_hash, - replacement in inflorescence/src/file.rs at line 138
id,id_hash, - replacement in inflorescence/src/file.rs at line 156
id.clone(),id_hash, - replacement in inflorescence/src/file.rs at line 161
id,id_hash, - replacement in inflorescence/src/file.rs at line 196
if !state.diffs_cache.inner.contains(&id) {diffs_cache_put(&mut state.diffs_cache, id.clone(), Diff::Loading);let id_hash = id_hash(&id);if !state.diffs_cache.inner.contains(&id_hash) {diffs_cache_put(&mut state.diffs_cache, id_hash, Diff::Loading); - replacement in inflorescence/src/file.rs at line 211
fn diffs_cache_put(cache: &mut DiffsCache, key: Id, value: Diff) {fn diffs_cache_put(cache: &mut DiffsCache, key: IdHash, value: Diff) { - replacement in inflorescence/src/file.rs at line 214
info!("Source file cache is too small to hold {}. Resizing cache to to {kv_weight} fit it.", key.path);info!("Source file cache is too small to fit new key. Resizing cache to {kv_weight} fit it."); - replacement in inflorescence/src/file.rs at line 221
impl WeightScale<Id, Diff> for DiffsCacheWeight {fn weight(&self, key: &Id, value: &Diff) -> usize {let key_weight = key.path.len();impl WeightScale<IdHash, Diff> for DiffsCacheWeight {fn weight(&self, _key: &IdHash, value: &Diff) -> usize {const KEY_WEIGHT: usize = mem::size_of::<IdHash>(); - replacement in inflorescence/src/file.rs at line 248
key_weight + val_weightKEY_WEIGHT + val_weight - edit in inflorescence/src/diff.rs at line 12
use crate::file; - edit in inflorescence/src/diff.rs at line 19
pub type FilesState = file::IdMap<State>;#[derive(Debug, Default)]pub struct LogFilesAndState {/// All the hashes in this set have `diffs` loadedpub change_hashes: HashSet<repo::ChangeHash>,/// All the diffs in this map have the change hash present in/// `change_hashes`pub diffs: file::LogIdMap<FileAndState>,} - edit in inflorescence/src/diff.rs at line 31
#[derive(Debug)]pub struct FileAndState {pub file: File,pub state: State,} - edit in inflorescence/src/diff.rs at line 203
}pub fn file_diff_needs_scrolling(files_diffs: &FilesState,id: file::IdHash,) -> bool {matches!(files_diffs.get(&id).and_then(|diff| diff.nav.as_ref()).and_then(|nav| nav.ready),Some(iced_nav_scrollable::NeedsScrolling::Yes))}pub fn log_diff_needs_scrolling(logs: &LogFilesAndState,id_hash: file::LogIdHash,) -> bool {matches!(logs.diffs.get(&id_hash).and_then(|diff| diff.state.nav.as_ref()).and_then(|nav| nav.ready),Some(iced_nav_scrollable::NeedsScrolling::Yes)) - replacement in inflorescence/src/cursor.rs at line 10
pub fn update(pub fn update<M>(msg: Msg, - replacement in inflorescence/src/cursor.rs at line 15
msg: Msg,) -> Task<repo::MsgIn> {files_diffs: &diff::FilesState,log_diffs: &diff::LogFilesAndState,) -> Task<M> { - replacement in inflorescence/src/cursor.rs at line 19[28.2495]→[30.939:962](∅→∅),[30.962]→[28.2524:3023](∅→∅),[28.2524]→[28.2524:3023](∅→∅),[28.3023]→[29.8609:8742](∅→∅),[29.8742]→[28.3339:3741](∅→∅),[28.3339]→[28.3339:3741](∅→∅),[28.3741]→[29.8743:8800](∅→∅),[29.8800]→[28.3942:4163](∅→∅),[28.3942]→[28.3942:4163](∅→∅),[28.4163]→[29.8801:8928](∅→∅),[29.8928]→[28.4457:4594](∅→∅),[28.4457]→[28.4457:4594](∅→∅)
Msg::Down => {if let Some(repo) = repo.as_ref() {let (selection, task) = match state.selection.take() {Some(Selection::UntrackedFile { ix, path: _ }) => {let (selection, task) =if repo.untracked_files.len().saturating_sub(1)== ix{if !repo.changed_files.is_empty() {let ix = 0;let selection =changed_file_selection(repo, ix, files);(selection, Task::none())} else if !repo.log.is_empty() {let ix = 0;log_selection(repo, ix)} else {let ix = 0;let selection = untracked_file_selection(repo, ix, files,);(selection, Task::none())}} else {let ix = ix + 1;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())};(Some(selection), task)Msg::Down => select_down(state, files, repo, files_diffs, log_diffs),Msg::Up => select_up(state, files, repo, files_diffs, log_diffs),Msg::Left => select_left(state, repo),Msg::Right => select_right(state, repo, files_diffs, log_diffs),Msg::Select(select) => {select_exact(select, state, files, repo, files_diffs, log_diffs)}}}pub fn untracked_file_selection(repo: &repo::State,ix: usize,files: &mut file::State,) -> Selection {let path = repo.untracked_files.iter().nth(ix).unwrap().clone();let id = file::Id {path: path.clone(),file_kind: file::Kind::Untracked,};file::load_src_file_if_not_cached(files, id);Selection::UntrackedFile {ix,path,diff_selected: false,}}pub fn changed_file_selection(repo: &repo::State,ix: usize,files: &mut file::State,) -> Selection {let (path, diffs) = repo.changed_files.iter().nth(ix).unwrap();if diff::any_diff_has_contents(diffs) {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};file::load_src_file_if_not_cached(files, id);}Selection::ChangedFile {ix,path: path.clone(),diff_selected: false,}}pub fn log_selection(repo: &repo::State, ix: usize) -> Selection {let entry = repo.log.get(ix).unwrap();Selection::LogChange {ix,hash: entry.hash,message: entry.message.clone(),file: None,}}pub fn log_file_selection(log_entry: &repo::LogEntry,file_ix: usize,) -> LogChangeFileSelection {let path = log_entry.file_paths.get(file_ix).unwrap().clone();LogChangeFileSelection {ix: file_ix,path,diff_selected: false,}}fn select_down<M>(state: &mut State,files: &mut file::State,repo: Option<&repo::State>,files_diffs: &diff::FilesState,logs: &diff::LogFilesAndState,) -> Task<M> {// TODO stairif let Some(repo) = repo.as_ref() {let (selection, task) = match state.selection.take() {Some(Selection::UntrackedFile {ix,path,diff_selected,}) => {let (selection, task) = if diff_selected {let id_hash =file::id_parts_hash(&path, file::Kind::Untracked);(Selection::UntrackedFile {ix,path,diff_selected,},if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_down(nav)} else {Task::none()},)} else if repo.untracked_files.len().saturating_sub(1) == ix {if !repo.changed_files.is_empty() {let ix = 0;let selection = changed_file_selection(repo, ix, files);(selection, Task::none())} else if !repo.log.is_empty() {let ix = 0;(log_selection(repo, ix), Task::none())} else {let ix = 0;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none()) - replacement in inflorescence/src/cursor.rs at line 140[28.4616]→[28.4616:5213](∅→∅),[28.5213]→[29.8929:8986](∅→∅),[29.8986]→[28.5414:5604](∅→∅),[28.5414]→[28.5414:5604](∅→∅),[28.5604]→[29.8987:9120](∅→∅),[29.9120]→[28.5920:6102](∅→∅),[28.5920]→[28.5920:6102](∅→∅),[28.6102]→[29.9121:9246](∅→∅),[29.9246]→[28.6394:6531](∅→∅),[28.6394]→[28.6394:6531](∅→∅)
Some(Selection::ChangedFile { ix, path: _ }) => {let (selection, task) =if repo.changed_files.len().saturating_sub(1) == ix{if !repo.log.is_empty() {let ix = 0;log_selection(repo, ix)} else if !repo.untracked_files.is_empty() {let ix = 0;let selection = untracked_file_selection(repo, ix, files,);(selection, Task::none())} else {let ix = 0;let selection =changed_file_selection(repo, ix, files);(selection, Task::none())}} else {let ix = ix + 1;let selection =changed_file_selection(repo, ix, files);(selection, Task::none())};(Some(selection), task)} else {let ix = ix + 1;let selection = untracked_file_selection(repo, ix, files);(selection, Task::none())};(Some(selection), task)}Some(Selection::ChangedFile {ix,path,diff_selected,}) => {let (selection, task) = if diff_selected {let id_hash =file::id_parts_hash(&path, file::Kind::Changed);(Selection::ChangedFile {ix,path,diff_selected,},if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_down(nav)} else {Task::none()},)} else if repo.changed_files.len().saturating_sub(1) == ix {if !repo.log.is_empty() {let ix = 0;(log_selection(repo, ix), Task::none())} else if !repo.untracked_files.is_empty() {let ix = 0;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())} else {let ix = 0;let selection = changed_file_selection(repo, ix, files);(selection, Task::none()) - replacement in inflorescence/src/cursor.rs at line 184
Some(Selection::LogChange {ix: log_ix,hash,message,file,} else {let ix = ix + 1;let selection = changed_file_selection(repo, ix, files);(selection, Task::none())};(Some(selection), task)}Some(Selection::LogChange {ix: log_ix,hash,message,file,}) => {let (selection, task) = match file {Some(LogChangeFileSelection {ix: file_ix,path,diff_selected, - replacement in inflorescence/src/cursor.rs at line 203
let (selection, task) = match file {Some(LogChangeFileSelection {ix: file_ix,path: _,}) => {let log_entry = repo.log.get(log_ix).unwrap();if diff_selected {let id_hash = file::log_id_parts_hash(hash, &path);(Selection::LogChange {ix: log_ix,hash,message,file: Some(LogChangeFileSelection {ix: file_ix,path,diff_selected,}),},if let Some(nav) = logs.diffs.get(&id_hash).and_then(|diff| diff.state.nav.as_ref()){iced_nav_scrollable::scroll_down(nav)} else {Task::none()},)} else {let log_entry = repo.log.get(log_ix).unwrap(); - replacement in inflorescence/src/cursor.rs at line 229
let file_ix = if log_entry.file_paths.len().saturating_sub(1)let file_ix =if log_entry.file_paths.len().saturating_sub(1) - replacement in inflorescence/src/cursor.rs at line 238
let file =log_file_selection(log_entry, file_ix);let file = log_file_selection(log_entry, file_ix); - replacement in inflorescence/src/cursor.rs at line 240[28.7679]→[28.7679:7919](∅→∅),[28.7966]→[28.7966:8750](∅→∅),[28.8750]→[29.9247:9312](∅→∅),[29.9312]→[28.8983:9307](∅→∅),[28.8983]→[28.8983:9307](∅→∅),[28.9307]→[29.9313:9374](∅→∅),[29.9374]→[28.9524:9832](∅→∅),[28.9524]→[28.9524:9832](∅→∅)
(Selection::LogChange {ix: log_ix,hash,message,file: Some(file),},Task::none(),)}None => {let (selection, task) = if repo.log.len().saturating_sub(1)== log_ix{if !repo.untracked_files.is_empty() {let ix = 0;let selection =untracked_file_selection(repo, ix, files,);(selection, Task::none())} else if !repo.changed_files.is_empty() {let ix = 0;let selection = changed_file_selection(repo, ix, files,);(selection, Task::none())} else {let ix = 0;log_selection(repo, ix)}(Selection::LogChange {ix: log_ix,hash,message,file: Some(file),},Task::none(),)}}None => {let selection =if repo.log.len().saturating_sub(1) == log_ix {if !repo.untracked_files.is_empty() {let ix = 0;untracked_file_selection(repo, ix, files)} else if !repo.changed_files.is_empty() {let ix = 0;changed_file_selection(repo, ix, files) - replacement in inflorescence/src/cursor.rs at line 261
let ix = log_ix + 1;let ix = 0; - replacement in inflorescence/src/cursor.rs at line 263
};(selection, task)}};(Some(selection), task)}} else {let ix = log_ix + 1;log_selection(repo, ix)};(selection, Task::none()) - replacement in inflorescence/src/cursor.rs at line 270
None => {let (selection, task) = if !repo.untracked_files.is_empty()};(Some(selection), task)}None => {let (selection, task) = if !repo.untracked_files.is_empty() {let ix = 0;let selection =Some(untracked_file_selection(repo, ix, files));(selection, Task::none())} else if !repo.changed_files.is_empty() {let ix = 0;let selection =Some(changed_file_selection(repo, ix, files));(selection, Task::none())} else if !repo.log.is_empty() {let ix = repo.log.len() - 1;let selection = log_selection(repo, ix);(Some(selection), Task::none())} else {(None, Task::none())};(selection, task)}};state.selection = selection;task} else {Task::none()}}fn select_up<M>(state: &mut State,files: &mut file::State,repo: Option<&repo::State>,files_diffs: &diff::FilesState,logs: &diff::LogFilesAndState,) -> Task<M> {// TODO stairif let Some(repo) = repo.as_ref() {let (selection, task) = match state.selection.take() {Some(Selection::UntrackedFile {ix,path,diff_selected,}) => {let (selection, task) = if diff_selected {let id_hash =file::id_parts_hash(&path, file::Kind::Untracked);(Selection::UntrackedFile {ix,path,diff_selected,},if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()) - replacement in inflorescence/src/cursor.rs at line 329
let ix = 0;let selection =Some(untracked_file_selection(repo, ix, files));(selection, Task::none())} else if !repo.changed_files.is_empty() {let ix = 0;let selection =Some(changed_file_selection(repo, ix, files));(selection, Task::none())} else if !repo.log.is_empty() {let ix = repo.log.len() - 1;let (selection, task) = log_selection(repo, ix);(Some(selection), task)iced_nav_scrollable::scroll_up(nav) - replacement in inflorescence/src/cursor.rs at line 331
(None, Task::none())};(selection, task)Task::none()},)} else if 0 == ix {if !repo.log.is_empty() {let ix = repo.log.len() - 1;(log_selection(repo, ix), Task::none())} else if !repo.changed_files.is_empty() {let ix = repo.changed_files.len() - 1;let selection = changed_file_selection(repo, ix, files);(selection, Task::none())} else {let ix = repo.untracked_files.len() - 1;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none()) - edit in inflorescence/src/cursor.rs at line 348
} else {let ix = ix - 1;let selection = untracked_file_selection(repo, ix, files);(selection, Task::none()) - replacement in inflorescence/src/cursor.rs at line 353
state.selection = selection;task} else {Task::none()(Some(selection), task)}Some(Selection::ChangedFile {ix,path,diff_selected,}) => {let (selection, task) = if diff_selected {let id_hash =file::id_parts_hash(&path, file::Kind::Changed);(Selection::ChangedFile {ix,path,diff_selected,},if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_up(nav)} else {Task::none()},)} else if 0 == ix {let selection = if !repo.untracked_files.is_empty() {let ix = repo.untracked_files.len() - 1;untracked_file_selection(repo, ix, files)} else if !repo.log.is_empty() {let ix = repo.log.len() - 1;log_selection(repo, ix)} else {let ix = repo.changed_files.len() - 1;changed_file_selection(repo, ix, files)};(selection, Task::none())} else {let ix = ix - 1;let selection = changed_file_selection(repo, ix, files);(selection, Task::none())};(Some(selection), task) - replacement in inflorescence/src/cursor.rs at line 397[28.11812]→[28.11812:11822](∅→∅),[28.11822]→[30.963:984](∅→∅),[30.984]→[28.11849:12414](∅→∅),[28.11849]→[28.11849:12414](∅→∅),[28.12414]→[29.10399:10524](∅→∅),[29.10524]→[28.12706:12874](∅→∅),[28.12706]→[28.12706:12874](∅→∅),[28.12874]→[29.10525:10652](∅→∅),[29.10652]→[28.13168:13256](∅→∅),[28.13168]→[28.13168:13256](∅→∅)
}Msg::Up => {if let Some(repo) = repo.as_ref() {let (selection, task) = match state.selection.take() {Some(Selection::UntrackedFile { ix, path: _ }) => {let (selection, task) = if 0 == ix {if !repo.log.is_empty() {let ix = repo.log.len() - 1;log_selection(repo, ix)} else if !repo.changed_files.is_empty() {let ix = repo.changed_files.len() - 1;let selection =changed_file_selection(repo, ix, files);(selection, Task::none())} else {let ix = repo.untracked_files.len() - 1;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())}Some(Selection::LogChange {ix: log_ix,hash,message,file,}) => {let (selection, task) = match file {Some(LogChangeFileSelection {ix: file_ix,path,diff_selected,}) => {if diff_selected {let id_hash = file::log_id_parts_hash(hash, &path);(Selection::LogChange {ix: log_ix,hash,message,file: Some(LogChangeFileSelection {ix: file_ix,path,diff_selected,}),},if let Some(nav) = logs.diffs.get(&id_hash).and_then(|diff| diff.state.nav.as_ref()){iced_nav_scrollable::scroll_up(nav)} else {Task::none()},) - replacement in inflorescence/src/cursor.rs at line 433[28.13289]→[28.13289:13334](∅→∅),[28.13334]→[29.10653:10772](∅→∅),[29.10772]→[28.13604:13733](∅→∅),[28.13604]→[28.13604:13733](∅→∅)
let ix = ix - 1;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())};(Some(selection), task)let log_entry = repo.log.get(log_ix).unwrap();let file_ix = if 0 == file_ix {log_entry.file_paths.len() - 1} else {file_ix - 1};let file = log_file_selection(log_entry, file_ix);(Selection::LogChange {ix: log_ix,hash,message,file: Some(file),},Task::none(),)} - replacement in inflorescence/src/cursor.rs at line 453
Some(Selection::ChangedFile { ix, path: _ }) => {let (selection, task) = if 0 == ix {if !repo.untracked_files.is_empty() {None => {let selection = if 0 == log_ix {if !repo.changed_files.is_empty() {let ix = repo.changed_files.len() - 1;changed_file_selection(repo, ix, files)} else if !repo.untracked_files.is_empty() { - replacement in inflorescence/src/cursor.rs at line 460
let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())} else if !repo.log.is_empty() {untracked_file_selection(repo, ix, files)} else { - edit in inflorescence/src/cursor.rs at line 464[28.14555]→[28.14555:14663](∅→∅),[28.14663]→[29.10901:11026](∅→∅),[29.11026]→[28.14955:15013](∅→∅),[28.14955]→[28.14955:15013](∅→∅)
} else {let ix = repo.changed_files.len() - 1;let selection =changed_file_selection(repo, ix, files);(selection, Task::none()) - replacement in inflorescence/src/cursor.rs at line 466[28.15076]→[28.15076:15121](∅→∅),[28.15121]→[29.11027:11144](∅→∅),[29.11144]→[28.15389:15443](∅→∅),[28.15389]→[28.15389:15443](∅→∅)
let ix = ix - 1;let selection =changed_file_selection(repo, ix, files);(selection, Task::none())let ix = log_ix - 1;log_selection(repo, ix) - replacement in inflorescence/src/cursor.rs at line 469
(Some(selection), task)(selection, Task::none()) - edit in inflorescence/src/cursor.rs at line 471
};(Some(selection), task)}None => {let (selection, task) = if !repo.log.is_empty() {let ix = repo.log.len() - 1;let selection = log_selection(repo, ix);(Some(selection), Task::none())} else if !repo.changed_files.is_empty() {let ix = repo.changed_files.len() - 1;let selection = changed_file_selection(repo, ix, files);(Some(selection), Task::none())} else if !repo.untracked_files.is_empty() {let ix = repo.untracked_files.len() - 1;let selection = untracked_file_selection(repo, ix, files);(Some(selection), Task::none())} else {(None, Task::none())};(selection, task)}};state.selection = selection;task} else {Task::none()}}fn select_left<M>(state: &mut State, repo: Option<&repo::State>) -> Task<M> {if let Some(_repo) = repo.as_ref() {let selection: Option<Selection> = match state.selection.take() {Some(Selection::LogChange {ix,hash,message,file:Some(LogChangeFileSelection {ix: file_ix,path,diff_selected,}),}) => {if diff_selected {Some(Selection::LogChange {ix,hash,message,file: Some(LogChangeFileSelection {ix: file_ix,path,diff_selected: false,}),})} else { - replacement in inflorescence/src/cursor.rs at line 528
ix: log_ix,ix, - replacement in inflorescence/src/cursor.rs at line 531
file,}) => {let (selection, task) = match file {Some(LogChangeFileSelection {ix: file_ix,path: _,}) => {let log_entry = repo.log.get(log_ix).unwrap();file: None,})}}Some(Selection::UntrackedFile {ix,path,diff_selected: true,}) => Some(Selection::UntrackedFile {ix,path,diff_selected: false,}),Some(Selection::ChangedFile {ix,path,diff_selected: true,}) => Some(Selection::ChangedFile {ix,path,diff_selected: false,}),selection @ (Some(Selection::UntrackedFile { .. })| Some(Selection::ChangedFile { .. })| Some(Selection::LogChange { file: None, .. })| None) => selection,};state.selection = selection;}Task::none()} - replacement in inflorescence/src/cursor.rs at line 563[28.16097]→[28.16097:16712](∅→∅),[28.16759]→[28.16759:17312](∅→∅),[28.17312]→[29.11145:11206](∅→∅),[29.11206]→[28.17529:17926](∅→∅),[28.17529]→[28.17529:17926](∅→∅),[28.17926]→[29.11207:11272](∅→∅),[29.11272]→[28.18159:18836](∅→∅),[28.18159]→[28.18159:18836](∅→∅)
let file_ix = if 0 == file_ix {log_entry.file_paths.len() - 1} else {file_ix - 1};let file =log_file_selection(log_entry, file_ix);(Selection::LogChange {ix: log_ix,hash,message,file: Some(file),},Task::none(),)}None => {let (selection, task) = if 0 == log_ix {if !repo.changed_files.is_empty() {let ix = repo.changed_files.len() - 1;let selection = changed_file_selection(repo, ix, files,);(selection, Task::none())} else if !repo.untracked_files.is_empty() {let ix = repo.untracked_files.len() - 1;let selection =untracked_file_selection(repo, ix, files,);(selection, Task::none())} else {let ix = repo.log.len() - 1;log_selection(repo, ix)}} else {let ix = log_ix - 1;log_selection(repo, ix)};(selection, task)}};(Some(selection), task)fn select_right<M>(state: &mut State,repo: Option<&repo::State>,files_diffs: &diff::FilesState,logs: &diff::LogFilesAndState,) -> Task<M> {if let Some(repo) = repo.as_ref() {let (selection, task): (Option<Selection>, Task<M>) = match state.selection.take(){Some(Selection::UntrackedFile {ix,path,diff_selected: false,}) => {let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);let diff_selected =diff::file_diff_needs_scrolling(files_diffs, id_hash);// If the selected file's diff is already loaded (it has an// attached state), scroll back to its last offset// TODO: simplify in rust 1.88let task = if diff_selected {if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_to_stored_offset(nav)} else {Task::none()}} else {Task::none()};(Some(Selection::UntrackedFile {ix,path,diff_selected,}),task,)}Some(Selection::ChangedFile {ix,path,diff_selected: false,}) => {let id_hash = file::id_parts_hash(&path, file::Kind::Changed);let diff_selected =diff::file_diff_needs_scrolling(files_diffs, id_hash);// If the selected file's diff is already loaded (it has an// attached state), scroll back to its last offset// TODO: simplify in rust 1.88let task = if diff_selected {if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_to_stored_offset(nav)} else {Task::none() - replacement in inflorescence/src/cursor.rs at line 626[28.18858]→[28.18858:19282](∅→∅),[28.19282]→[29.11273:11390](∅→∅),[29.11390]→[28.19550:19748](∅→∅),[28.19550]→[28.19550:19748](∅→∅),[28.19748]→[29.11391:11510](∅→∅),[29.11510]→[28.20018:20229](∅→∅),[28.20018]→[28.20018:20229](∅→∅)
None => {let (selection, task) = if !repo.log.is_empty() {let ix = repo.log.len() - 1;let (selection, task) = log_selection(repo, ix);(Some(selection), task)} else if !repo.changed_files.is_empty() {let ix = repo.changed_files.len() - 1;let selection =changed_file_selection(repo, ix, files);(Some(selection), Task::none())} else if !repo.untracked_files.is_empty() {let ix = repo.untracked_files.len() - 1;let selection =untracked_file_selection(repo, ix, files);(Some(selection), Task::none())} else {(None, Task::none())};(selection, task)} else {Task::none()};(Some(Selection::ChangedFile {ix,path,diff_selected,}),task,)}Some(Selection::LogChange {ix,hash,message,file:Some(LogChangeFileSelection {ix: file_ix,path,diff_selected: false,}),}) => {let id_hash = file::log_id_parts_hash(hash, &path);let diff_selected =diff::log_diff_needs_scrolling(logs, id_hash);// If the selected file's diff is already loaded (it has an// attached state), scroll back to its last offset// TODO: simplify in rust 1.88let task = if diff_selected {if let Some(nav) = logs.diffs.get(&id_hash).and_then(|diff| diff.state.nav.as_ref()){iced_nav_scrollable::scroll_to_stored_offset(nav)} else {Task::none() - edit in inflorescence/src/cursor.rs at line 665
} else {Task::none() - replacement in inflorescence/src/cursor.rs at line 668
state.selection = selection;task} else {Task::none()(Some(Selection::LogChange {ix,hash,message,file: Some(LogChangeFileSelection {ix: file_ix,path,diff_selected,}),}),task,) - replacement in inflorescence/src/cursor.rs at line 682[28.20401]→[28.20401:20411](∅→∅),[28.20411]→[50.43:401](∅→∅),[50.436]→[50.436:682](∅→∅),[50.721]→[50.721:765](∅→∅)
}Msg::Left => {if let Some(_repo) = repo.as_ref() {let (selection, task): (Option<Selection>, Task<repo::MsgIn>) =match state.selection.take() {Some(Selection::LogChange {ix,hash,message,file: Some(_),}) => (Some(Selection::LogChange {ix,hash,message,file: None,Some(Selection::LogChange {ix,hash,message,file: None,}) => {let log_entry = repo.log.get(ix).unwrap();let (file, task) =if let Some(path) = log_entry.file_paths.first() {(Some(LogChangeFileSelection {ix: 0,path: path.clone(),diff_selected: false, - replacement in inflorescence/src/cursor.rs at line 698
),selection @ (Some(Selection::UntrackedFile {..})| Some(Selection::ChangedFile {..})| Some(Selection::LogChange {file: None,..})| None) => (selection, Task::none()),)} else {(None, Task::none()) - replacement in inflorescence/src/cursor.rs at line 702
state.selection = selection;task(Some(Selection::LogChange {ix,hash,message,file,}),task,)}selection => (selection, Task::none()),};state.selection = selection;task} else {Task::none()}}fn select_exact<M>(select: Select,state: &mut State,files: &mut file::State,repo: Option<&repo::State>,files_diffs: &diff::FilesState,logs: &diff::LogFilesAndState,) -> Task<M> {let (selection, task) = match select {Select::UntrackedFile { ix, path } => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};let id_hash = file::id_hash(&id);file::load_src_file_if_not_cached(files, id);// If the selected file's diff is already loaded (it has an attached// state), scroll back to its last offset// TODO: simplify in rust 1.88let is_diff_scrollable =diff::file_diff_needs_scrolling(files_diffs, id_hash);let task = if is_diff_scrollable {if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_to_stored_offset(nav)} else {Task::none()} - edit in inflorescence/src/cursor.rs at line 753
};(Some(Selection::UntrackedFile {ix,path,diff_selected: false,}),task,)}Select::ChangedFile { ix, path } => {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};let id_hash = file::id_hash(&id);if let Some(diffs) =repo.as_ref().and_then(|repo| repo.changed_files.get(&path)){if diff::any_diff_has_contents(diffs) {file::load_src_file_if_not_cached(files, id);} - replacement in inflorescence/src/cursor.rs at line 776[50.1474]→[50.1474:1508](∅→∅),[30.1021]→[28.20459:20793](∅→∅),[50.1508]→[28.20459:20793](∅→∅),[28.20459]→[28.20459:20793](∅→∅),[28.20828]→[50.1509:1549](∅→∅),[50.1549]→[28.20862:20894](∅→∅),[28.20862]→[28.20862:20894](∅→∅),[28.20894]→[50.1550:1779](∅→∅),[50.1779]→[28.21679:21713](∅→∅),[28.21679]→[28.21679:21713](∅→∅),[28.21713]→[50.1780:1953](∅→∅),[50.1953]→[28.22009:22049](∅→∅),[28.22009]→[28.22009:22049](∅→∅),[28.22049]→[50.1954:2004](∅→∅),[50.2004]→[28.22091:22162](∅→∅),[28.22091]→[28.22091:22162](∅→∅),[28.22162]→[50.2005:2306](∅→∅),[50.2349]→[50.2349:2495](∅→∅),[50.2495]→[28.22652:22861](∅→∅),[28.22652]→[28.22652:22861](∅→∅),[28.22861]→[50.2496:2651](∅→∅),[50.2651]→[28.22861:23070](∅→∅),[28.22861]→[28.22861:23070](∅→∅)
}Msg::Right => {if let Some(repo) = repo.as_ref() {let (selection, task): (Option<Selection>, Task<repo::MsgIn>) =match state.selection.take() {Some(Selection::LogChange {ix,hash,message,file: None,}) => {let log_entry = repo.log.get(ix).unwrap();let (file, task) = if let Some(path) =log_entry.file_paths.first(){(Some(LogChangeFileSelection {ix: 0,path: path.clone(),}),Task::none(),)} else {(None, Task::none())};(Some(Selection::LogChange {ix,hash,message,file,}),task,)}selection @ (Some(Selection::UntrackedFile {..})| Some(Selection::ChangedFile {..})| Some(Selection::LogChange {file: Some(_),..})| None) => (selection, Task::none()),};state.selection = selection;task// If the selected file's diff is already loaded (it has an attached// state), scroll back to its last offset// TODO: simplify in rust 1.88let is_diff_scrollable =diff::file_diff_needs_scrolling(files_diffs, id_hash);let task = if is_diff_scrollable {if let Some(nav) = files_diffs.get(&id_hash).and_then(|state| state.nav.as_ref()){iced_nav_scrollable::scroll_to_stored_offset(nav)} else {Task::none()} - replacement in inflorescence/src/cursor.rs at line 792
}};(Some(Selection::ChangedFile {ix,path,diff_selected: false,}),task,) - replacement in inflorescence/src/cursor.rs at line 802[28.23144]→[30.1022:1055](∅→∅),[30.1055]→[28.23183:23290](∅→∅),[28.23183]→[28.23183:23290](∅→∅),[28.23290]→[29.11511:11632](∅→∅),[29.11632]→[28.23451:23499](∅→∅),[28.23451]→[28.23451:23499](∅→∅),[28.23499]→[29.11633:11695](∅→∅),[29.11695]→[28.23559:23999](∅→∅),[28.23559]→[28.23559:23999](∅→∅),[28.23999]→[29.11696:11841](∅→∅),[29.11841]→[28.24192:24248](∅→∅),[28.24192]→[28.24192:24248](∅→∅),[28.24248]→[29.11842:11910](∅→∅),[29.11910]→[28.24314:24380](∅→∅),[28.24314]→[28.24314:24380](∅→∅)
Msg::Select(select) => {let (selection, task) = match select {Select::UntrackedFile { ix, path } => {file::load_src_file_if_not_cached(files,file::Id {path: path.clone(),file_kind: file::Kind::Untracked,},);(Some(Selection::UntrackedFile { ix, path }), Task::none())}Select::ChangedFile { ix, path } => {if let Some(diffs) = repo.as_ref().and_then(|repo| repo.changed_files.get(&path)){if diff::any_diff_has_contents(diffs) {file::load_src_file_if_not_cached(files,file::Id {path: path.clone(),file_kind: file::Kind::Changed,},);Select::LogChange { ix, hash, message } => (Some(Selection::LogChange {ix,hash,message,file: None,}),Task::none(),),Select::LogChangeFile { ix: file_ix, path } => {match state.selection.take() {Some(Selection::LogChange {ix: change_ix,hash,message,file: _,}) => {let id_hash = file::log_id_parts_hash(hash, &path);let diff_selected =diff::log_diff_needs_scrolling(logs, id_hash);// If the selected file's diff is already loaded (it has an// attached state), scroll back to its last offset// TODO: simplify in rust 1.88let task = if diff_selected {if let Some(nav) = logs.diffs.get(&id_hash).and_then(|diff| diff.state.nav.as_ref()){iced_nav_scrollable::scroll_to_stored_offset(nav)} else {Task::none() - replacement in inflorescence/src/cursor.rs at line 835
}(Some(Selection::ChangedFile { ix, path }), Task::none())}Select::LogChange { ix, hash, message } => {// Request to get the diffslet task = Task::done(repo::MsgIn::GetChangeDiffs { hash });} else {Task::none()};let file = LogChangeFileSelection {ix: file_ix,path,diff_selected: false,}; - replacement in inflorescence/src/cursor.rs at line 845
ix,ix: change_ix, - replacement in inflorescence/src/cursor.rs at line 848
file: None,file: Some(file), - edit in inflorescence/src/cursor.rs at line 852
}Select::LogChangeFile { ix: file_ix, path } => {match state.selection.take() {Some(Selection::LogChange {ix: change_ix,hash,message,file: _,}) => {let file =LogChangeFileSelection { ix: file_ix, path };(Some(Selection::LogChange {ix: change_ix,hash,message,file: Some(file),}),Task::none(),)}selection => (selection, Task::none()),} - replacement in inflorescence/src/cursor.rs at line 853
};state.selection = selection;taskselection => (selection, Task::none()),} - edit in inflorescence/src/cursor.rs at line 856[28.26223]→[28.26223:26304](∅→∅),[28.26304]→[29.11911:11940](∅→∅),[29.11940]→[28.26393:26480](∅→∅),[28.26393]→[28.26393:26480](∅→∅),[28.26480]→[29.11941:11965](∅→∅),[29.11965]→[28.26502:26530](∅→∅),[28.26502]→[28.26502:26530](∅→∅),[28.26530]→[29.11966:12008](∅→∅)
}}pub fn untracked_file_selection(repo: &repo::State,ix: usize,files: &mut file::State,) -> Selection {let path = repo.untracked_files.iter().nth(ix).unwrap().clone();let id = file::Id {path: path.clone(),file_kind: file::Kind::Untracked, - replacement in inflorescence/src/cursor.rs at line 857[28.26577]→[29.12009:12059](∅→∅),[29.12059]→[28.26645:26761](∅→∅),[28.26645]→[28.26645:26761](∅→∅),[28.26761]→[29.12060:12089](∅→∅),[29.12089]→[28.26850:26980](∅→∅),[28.26850]→[28.26850:26980](∅→∅),[28.26980]→[29.12090:12118](∅→∅),[29.12118]→[28.27006:27038](∅→∅),[28.27006]→[28.27006:27038](∅→∅),[28.27038]→[29.12119:12163](∅→∅),[29.12163]→[28.27080:27091](∅→∅),[28.27080]→[28.27080:27091](∅→∅),[28.27091]→[29.12164:12218](∅→∅),[29.12218]→[28.27163:27245](∅→∅),[28.27163]→[28.27163:27245](∅→∅)
file::load_src_file_if_not_cached(files, id);Selection::UntrackedFile { ix, path }}pub fn changed_file_selection(repo: &repo::State,ix: usize,files: &mut file::State,) -> Selection {let (path, diffs) = repo.changed_files.iter().nth(ix).unwrap();if diff::any_diff_has_contents(diffs) {let id = file::Id {path: path.clone(),file_kind: file::Kind::Changed,};file::load_src_file_if_not_cached(files, id);}Selection::ChangedFile {ix,path: path.clone(),}state.selection = selection;task - edit in inflorescence/src/cursor.rs at line 860
pub fn log_selection(repo: &repo::State,ix: usize,) -> (Selection, Task<repo::MsgIn>) {let entry = repo.log.get(ix).unwrap();// Request to get the diffslet task = Task::done(repo::MsgIn::GetChangeDiffs { hash: entry.hash });(Selection::LogChange {ix,hash: entry.hash,message: entry.message.clone(),file: None,},task,)}pub fn log_file_selection(log_entry: &repo::LogEntry,file_ix: usize,) -> LogChangeFileSelection {let path = log_entry.file_paths.get(file_ix).unwrap().clone();LogChangeFileSelection { ix: file_ix, path }} - replacement in iced_nav_scrollable/src/lib.rs at line 8
use iced::widget::{self, container, scrollable};use iced::widget::{self, container, scrollable, Scrollable}; - edit in iced_nav_scrollable/src/lib.rs at line 43
ScrollToPrev,ScrollToNext, - edit in iced_nav_scrollable/src/lib.rs at line 185[52.3895]→[51.2369:2435](∅→∅),[51.2369]→[51.2369:2435](∅→∅),[51.2435]→[52.3896:4101](∅→∅),[52.4101]→[51.2614:2632](∅→∅),[51.2614]→[51.2614:2632](∅→∅),[51.2632]→[53.13381:13425](∅→∅),[53.13425]→[51.2682:2847](∅→∅),[51.2682]→[51.2682:2847](∅→∅)
Task::none()}Msg::ScrollToNext => {if nav.pending_tasks.is_none() {if let Some(y) = nav.section_offsets.iter().find(|offset| *offset > &nav.offset){return task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset { x: 0.0, y: *y },);}} - edit in iced_nav_scrollable/src/lib.rs at line 187[51.2882]→[51.2882:2913](∅→∅),[51.2913]→[52.4102:4147](∅→∅),[52.4147]→[51.2981:3018](∅→∅),[51.2981]→[51.2981:3018](∅→∅),[51.3018]→[52.4148:4185](∅→∅),[52.4185]→[51.3047:3102](∅→∅),[51.3047]→[51.3047:3102](∅→∅),[51.3102]→[52.4186:4244](∅→∅),[52.4244]→[51.3162:3180](∅→∅),[51.3162]→[51.3162:3180](∅→∅),[51.3180]→[53.13426:13470](∅→∅),[53.13470]→[51.3230:3430](∅→∅),[51.3230]→[51.3230:3430](∅→∅)
Msg::ScrollToPrev => {if nav.pending_tasks.is_none() {if let Some(y) = nav.section_offsets.iter().rev().find(|offset| *offset < &nav.offset){return task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset { x: 0.0, y: *y },);}}Task::none()} - replacement in iced_nav_scrollable/src/lib.rs at line 197
) -> Element<'a, Message, Theme, Renderer>) -> Scrollable<'a, Message, Theme, Renderer> - replacement in iced_nav_scrollable/src/lib.rs at line 210[51.4371]→[53.13471:13500](∅→∅),[53.13500]→[51.4390:4549](∅→∅),[51.4390]→[51.4390:4549](∅→∅),[51.4549]→[53.13501:13531](∅→∅)
let nav = Element::from(widget::scrollable(widget::column(children)).id(nav.id.clone()).on_scroll(move |viewport| map_msg(Msg::Scrolled(viewport))),);Element::from(nav)widget::scrollable(widget::column(children)).id(nav.id.clone()).on_scroll(move |viewport| map_msg(Msg::Scrolled(viewport)))}/// A task to scroll to the last stored offsetpub fn scroll_to_stored_offset<M>(nav: &NavScrollable) -> Task<M> {task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset {x: 0.0,y: nav.offset,},)}// TODO: time deltaconst DELTA: f32 = 10.0;/// Scroll down, skipping any sections that are marked to skippub fn scroll_down<M>(nav: &NavScrollable) -> Task<M> {if let Some(y) = nav.section_offsets.iter().zip(nav.section_heights.values()).enumerate().find_map(|(ix, (offset, height))| {if !nav.skip_sections.contains(&ix) {// dbg!(ix, offset, height, nav.offset);let bottom_frame = saturating_sub(nav.offset + nav.height,VISIBLE_CONTEXT_HEIGHT,);if *offset < bottom_frame && offset + height > bottom_frame {// The top edge of the section is visible, but the bottom// edge of is below the bottom edge of nav, scroll downSome(nav.offset + DELTA)} else if *offset > nav.offset + nav.height {// Scroll to the next sectionSome(saturating_sub(*offset, VISIBLE_CONTEXT_HEIGHT))} else {None}} else {None}}){return task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset { x: 0.0, y },);}Task::none()}/// Scroll up, skipping any sections that are marked to skippub fn scroll_up<M>(nav: &NavScrollable) -> Task<M> {if let Some(y) = nav.section_offsets.iter().zip(nav.section_heights.values()).enumerate().rev().find_map(|(ix, (offset, height))| {if !nav.skip_sections.contains(&ix) {// dbg!(ix, offset, height, nav.offset);let top_frame = nav.offset + VISIBLE_CONTEXT_HEIGHT;if offset + height > top_frame && *offset < top_frame {// The bottom edge of the section is visible, but the top// edge of is above the top edge of nav, scroll upSome(saturating_sub(nav.offset, DELTA))} else if// offset + height < nav.offset &&offset + height< saturating_sub(nav.offset, VISIBLE_CONTEXT_HEIGHT){// Scroll to the bottom of the prev sectionSome(saturating_sub(offset + height + VISIBLE_CONTEXT_HEIGHT,nav.height,))} else {None}} else {None}}){return task::scroll_to(nav.id.clone(),scrollable::AbsoluteOffset { x: 0.0, y },);}Task::none() - replacement in iced_nav_scrollable/src/lib.rs at line 360
let y = if *y > -VISIBLE_CONTEXT_HEIGHT {*y - VISIBLE_CONTEXT_HEIGHT} else {0.0};let y = saturating_sub(*y, VISIBLE_CONTEXT_HEIGHT); - edit in iced_nav_scrollable/src/lib.rs at line 453[51.6289]
fn saturating_sub(left: f32, right: f32) -> f32 {if left > right {left - right} else {0.0}}