shared allowed actions conditions between update and view
[?]
Aug 11, 2025, 9:46 AM
EJPSD5XO43DWUBBZGNQMY4TMCAXL5EWCGX3OEHUERQ5GRASGWQLQCDependencies
- [2]
WT3GA27Padd cursor with selection - [3]
UB2ITZJSrefresh changed files on FS changes - [4]
EC3TVL4Xadd untracked files - [5]
S2NVIFXRallow to enter record msg - [6]
YBJRDOTCmake all repo actions async - [7]
D7A7MSIHallow to defer or abandon record, add buttons - [8]
NRCUG4R2load changed files src when selected - [9]
ZVI4AWERwoot contents_diff - [10]
AHWWRC73navigate log entries - [11]
TEI5NQ3Sadd log files selection - [12]
BFN2VHZSrefactor file stuff into sub-mod - [13]
23SFYK4Qbig view refactor into a new crate - [14]
MYGIBRRHwip custom theme - [15]
PKJCFSBMtheme improvements - [16]
XSZZB47Urefactor stuff into lib - [17]
ACDXXAX2refactor main's updates into smaller fns - [18]
FVA36HBVrestart repo manager task if it crashes - [19]
ESMM3FELtest selection reindexing - [20]
7SSBM4UQview: refactor repo view - [21]
I2AG42PAnew cols layout - [22]
SASAN2XCuse nav-scrollable - [23]
YKHE3XMWrefactor diffs handling - [24]
K5YUSV2Wauto-scroll to last offset - [25]
5MUEECMJsmooth scrolling nav - [26]
3TLPJ57Balt scroll via context and couple fixes - [27]
PTWZYQFRuse nav-scrollable for repo status - [28]
UR4J677Rnav for log changes and refactors - [29]
A6Z4O6RCactions menu - [30]
7BLZN73Oadd a key to refresh repo - [31]
JZXYSIYDchannel selection! - [32]
5ZRDYL6Kfork channel, fix recording esc key - [33]
BAUK5BONpimp-up action buttons - [34]
OJPGHVC3entire log! - [35]
3XRG4BB6rewritten nav-scrollable! - [36]
S4WH75Y3allow to select channels if there are any other. Conditional switch - [37]
WAOGSCOJvery nice refactor, wip adding channels logs - [38]
WH57EHNMupdate tests - [39]
ELG3UDT6allow to rm added files - [40]
HC7ROIBCmove main diffs state out of cursor - [41]
RDRBP7ALauto-scroll status selection - [42]
KM5PSZ4Awatch repo once loaded - [43]
3SYSJKYLadd app icon - [44]
A5YBC77Vrecord! - [45]
Y5ATDI2Hconvert changed file diffs and load src only if any needs it - [46]
JE44NYHMdisplay log files diffs - [47]
4ELJZGRJload and store all change diffs at once - [48]
WGID4LS4absolutely slayed testing with iced task - [49]
L6KSEFQImove cursor related stuff into its module - [50]
6YZAVBWUInitial commit - [51]
FDDPOH5Radd arrow controls - [52]
KWTBNTO3diffs selection and scrolling - [53]
KT5UYXGKfix selection after adding file, add changed file diffs - [54]
4WO3ZJM2show untracked files' contents
Change contents
- replacement in inflorescence_view/src/app.rs at line 9
get_entire_log_diffs_nav, get_entire_log_files_nav, get_files_diffs_nav,get_status_log_diffs_nav, get_status_log_files_nav, selection, Log,ReadyState, RecordMsg, SubState,self as model, action, get_entire_log_diffs_nav, get_entire_log_files_nav,get_files_diffs_nav, get_status_log_diffs_nav, get_status_log_files_nav,selection, Log, ReadyState, RecordMsg, SubState, - edit in inflorescence_view/src/app.rs at line 29
#[derive(Debug, Clone)]pub enum Msg {/// Actions bound to keysAction(action::Msg),EditRecordMsg(text_editor::Action),EditForkChannelName(String),} - replacement in inflorescence_view/src/app.rs at line 38
state: &'a inflorescence_model::State,state: &'a model::State, - replacement in inflorescence_view/src/app.rs at line 45
let inflorescence_model::State {let model::State { - edit in inflorescence_view/src/app.rs at line 49
allowed_actions, - replacement in inflorescence_view/src/app.rs at line 60
SubState::Ready(state) => {view_ready(*window_size, repo_path, state, get_diff)}SubState::Ready(state) => view_ready(*window_size,repo_path,state,get_diff,allowed_actions,), - edit in inflorescence_view/src/app.rs at line 81
allowed_actions: &[action::Binding], - replacement in inflorescence_view/src/app.rs at line 112
has_other_channels.then_some(Msg::SelectChannel),has_other_channels.then_some(Msg::Action(action::Msg::SelectChannel)), - replacement in inflorescence_view/src/app.rs at line 129
.on_press(Msg::Selection(selection::Msg::Select(.on_press(Msg::Action(action::Msg::Selection(selection::Msg::Select( - replacement in inflorescence_view/src/app.rs at line 131
))))))) - replacement in inflorescence_view/src/app.rs at line 149
.on_press(Msg::Selection(selection::Msg::Select(.on_press(Msg::Action(action::Msg::Selection(selection::Msg::Select( - replacement in inflorescence_view/src/app.rs at line 151
))))))) - replacement in inflorescence_view/src/app.rs at line 179
el(button(text("Save")).on_press(Msg::SaveRecord)),el(button(text("Postpone")).on_press(Msg::PostponeRecord)),el(button(text("Discard")).on_press(Msg::DiscardRecord)),el(button(text("Save")).on_press(Msg::Action(action::Msg::SaveRecord))),el(button(text("Postpone")).on_press(Msg::Action(action::Msg::PostponeRecord))),el(button(text("Discard")).on_press(Msg::Action(action::Msg::DiscardRecord))), - replacement in inflorescence_view/src/app.rs at line 268
Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))Msg::Action(action::Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))) - replacement in inflorescence_view/src/app.rs at line 397
.on_press(Msg::Selection(selection::Msg::PressDir(selection::Dir::Left),.on_press(Msg::Action(action::Msg::Selection(selection::Msg::PressDir(selection::Dir::Left,)), - replacement in inflorescence_view/src/app.rs at line 448
.on_press(Msg::Selection(selection::Msg::PressDir(selection::Dir::Left),.on_press(Msg::Action(action::Msg::Selection(selection::Msg::PressDir(selection::Dir::Left,)), - replacement in inflorescence_view/src/app.rs at line 542
Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))Msg::Action(action::Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))) - replacement in inflorescence_view/src/app.rs at line 576
.on_press(Msg::Selection(selection::Msg::PressDir(selection::Dir::Left),.on_press(Msg::Action(action::Msg::Selection(selection::Msg::PressDir(selection::Dir::Left,)), - replacement in inflorescence_view/src/app.rs at line 626
.on_press(Msg::Selection(selection::Msg::PressDir(selection::Dir::Left),.on_press(Msg::Action(action::Msg::Selection(selection::Msg::PressDir(selection::Dir::Left,)), - replacement in inflorescence_view/src/app.rs at line 648
.on_press(Msg::Confirm).on_press(Msg::Action(action::Msg::Confirm)) - replacement in inflorescence_view/src/app.rs at line 731
.on_input(Msg::ForkChannelName);.on_input(Msg::EditForkChannelName); - replacement in inflorescence_view/src/app.rs at line 736
let actions_inner = actions_inner.push(view_actions(action_state(state)));let actions_inner = actions_inner.push(view_actions(allowed_actions)); - edit in inflorescence_view/src/app.rs at line 746[37.20176]→[37.20176:20593](∅→∅),[29.2274]→[13.24344:24347](∅→∅),[15.3137]→[13.24344:24347](∅→∅),[21.4091]→[13.24344:24347](∅→∅),[20.5817]→[13.24344:24347](∅→∅),[37.20593]→[13.24344:24347](∅→∅),[13.24344]→[13.24344:24347](∅→∅)
#[derive(Debug, Clone)]pub enum Msg {Confirm,Cancel,Selection(selection::Msg),ToRepo(repo::MsgIn),EditRecordMsg(text_editor::Action),PostponeRecord,SaveRecord,DiscardRecord,AddUntrackedFile,RmAddedFile,StartRecord,/// Show a list of channels to switch toSelectChannel,ForkChannel,ForkChannelName(String),RefreshRepo,ShowEntireLog,} - edit in inflorescence_view/src/app.rs at line 751[13.24506]→[29.2275:2390](∅→∅),[29.2390]→[33.242:280](∅→∅),[33.280]→[31.7503:7579](∅→∅),[29.2413]→[31.7503:7579](∅→∅),[31.7579]→[29.2480:2540](∅→∅),[29.2480]→[29.2480:2540](∅→∅),[29.2540]→[33.281:319](∅→∅),[33.319]→[31.7580:7656](∅→∅),[29.2563]→[31.7580:7656](∅→∅),[31.7656]→[29.2630:2688](∅→∅),[29.2630]→[29.2630:2688](∅→∅),[29.2688]→[33.320:358](∅→∅),[33.358]→[31.7657:7731](∅→∅),[29.2711]→[31.7657:7731](∅→∅),[31.7731]→[29.2776:2837](∅→∅),[29.2776]→[29.2776:2837](∅→∅),[29.2837]→[33.359:397](∅→∅),[33.397]→[31.7732:7809](∅→∅),[29.2860]→[31.7732:7809](∅→∅),[31.7809]→[29.2928:2996](∅→∅),[29.2928]→[29.2928:2996](∅→∅),[29.2996]→[33.398:447](∅→∅),[33.447]→[31.7810:7889](∅→∅),[29.3032]→[31.7810:7889](∅→∅),[31.7889]→[29.3102:3168](∅→∅),[29.3102]→[29.3102:3168](∅→∅),[29.3168]→[33.448:497](∅→∅),[33.497]→[31.7890:7967](∅→∅),[29.3204]→[31.7890:7967](∅→∅),[31.7967]→[29.3272:3289](∅→∅),[29.3272]→[29.3272:3289](∅→∅),[29.3289]→[32.3702:3703](∅→∅),[32.3703]→[29.3289:3313](∅→∅),[29.3289]→[29.3289:3313](∅→∅),[29.3313]→[33.498:647](∅→∅),[33.647]→[32.3704:3705](∅→∅),[29.3458]→[32.3704:3705](∅→∅),[32.3705]→[33.648:801](∅→∅),[33.801]→[29.3607:3633](∅→∅),[29.3607]→[29.3607:3633](∅→∅),[29.3633]→[33.802:875](∅→∅),[33.875]→[29.3704:3729](∅→∅),[29.3704]→[29.3704:3729](∅→∅),[29.3729]→[33.876:947](∅→∅),[33.947]→[32.3706:3707](∅→∅),[29.3798]→[32.3706:3707](∅→∅),[32.3707]→[36.173:267](∅→∅),[36.267]→[33.1017:1097](∅→∅),[33.1017]→[33.1017:1097](∅→∅),[33.1097]→[32.3786:3787](∅→∅),[32.3786]→[32.3786:3787](∅→∅),[32.3787]→[33.1098:1188](∅→∅),[33.1188]→[32.3788:3789](∅→∅),[30.126]→[32.3788:3789](∅→∅),[32.3789]→[36.268:361](∅→∅),[36.361]→[37.20594:20688](∅→∅),[37.20688]→[33.1360:1425](∅→∅),[33.1360]→[33.1360:1425](∅→∅),[30.126]→[29.3798:3799](∅→∅),[33.1425]→[29.3798:3799](∅→∅),[31.8192]→[29.3798:3799](∅→∅),[29.3798]→[29.3798:3799](∅→∅),[29.3799]→[32.3790:3869](∅→∅),[32.3869]→[29.4038:4039](∅→∅),[29.4038]→[29.4038:4039](∅→∅),[29.4039]→[34.12899:12936](∅→∅),[31.8230]→[30.127:155](∅→∅),[34.12936]→[30.127:155](∅→∅),[29.4039]→[30.127:155](∅→∅),[30.155]→[29.4071:4176](∅→∅),[29.4071]→[29.4071:4176](∅→∅),[29.4176]→[36.362:394](∅→∅),[36.394]→[29.4176:4234](∅→∅),[29.4176]→[29.4176:4234](∅→∅),[29.4234]→[31.8231:8271](∅→∅),[31.8271]→[29.4264:4367](∅→∅),[29.4264]→[29.4264:4367](∅→∅),[29.4367]→[32.3870:3996](∅→∅),[32.3996]→[29.4497:4627](∅→∅),[29.4497]→[29.4497:4627](∅→∅),[29.4627]→[32.3997:4123](∅→∅),[32.4123]→[29.4757:4817](∅→∅),[29.4757]→[29.4757:4817](∅→∅),[29.4817]→[32.4124:4250](∅→∅),[32.4250]→[29.4947:4965](∅→∅),[29.4947]→[29.4947:4965](∅→∅),[29.4965]→[31.8272:8287](∅→∅),[31.8287]→[36.395:466](∅→∅),[36.466]→[34.13001:13017](∅→∅),[34.13001]→[34.13001:13017](∅→∅),[32.4304]→[29.4979:5076](∅→∅),[31.8369]→[29.4979:5076](∅→∅),[34.13017]→[29.4979:5076](∅→∅),[29.4979]→[29.4979:5076](∅→∅),[29.5076]→[36.467:499](∅→∅),[36.499]→[29.5076:5142](∅→∅),[29.5076]→[29.5076:5142](∅→∅),[29.5142]→[32.4305:4426](∅→∅),[32.4426]→[36.500:571](∅→∅),[36.571]→[34.13082:13098](∅→∅),[34.13082]→[34.13082:13098](∅→∅),[32.4479]→[29.5256:5266](∅→∅),[31.8515]→[29.5256:5266](∅→∅),[34.13098]→[29.5256:5266](∅→∅),[29.5256]→[29.5256:5266](∅→∅),[29.5266]→[36.572:671](∅→∅),[36.671]→[29.5312:5393](∅→∅),[29.5312]→[29.5312:5393](∅→∅),[29.5393]→[32.4480:4541](∅→∅),[32.4541]→[36.672:743](∅→∅),[36.743]→[34.13163:13179](∅→∅),[34.13163]→[34.13163:13179](∅→∅),[32.4594]→[29.5445:5571](∅→∅),[31.8661]→[29.5445:5571](∅→∅),[34.13179]→[29.5445:5571](∅→∅),[29.5445]→[29.5445:5571](∅→∅),[29.5571]→[37.20689:20751](∅→∅),[37.20751]→[31.8724:8911](∅→∅),[31.8724]→[31.8724:8911](∅→∅),[31.8911]→[36.744:874](∅→∅),[36.874]→[37.20752:20941](∅→∅),[37.20941]→[36.874:975](∅→∅),[36.874]→[36.874:975](∅→∅),[36.975]→[31.9026:9051](∅→∅),[31.9026]→[31.9026:9051](∅→∅),[31.9051]→[32.4595:4685](∅→∅),[32.4685]→[36.976:1057](∅→∅),[36.1057]→[37.20942:21045](∅→∅),[37.21045]→[34.13180:13777](∅→∅),[33.1499]→[34.13180:13777](∅→∅),[34.13777]→[32.5080:5090](∅→∅),[32.5080]→[32.5080:5090](∅→∅),[32.5090]→[29.5571:5579](∅→∅),[31.9051]→[29.5571:5579](∅→∅),[29.5571]→[29.5571:5579](∅→∅),[29.5579]→[32.5091:5150](∅→∅),[32.5150]→[30.156:227](∅→∅),[29.5579]→[30.156:227](∅→∅),[30.227]→[13.24506:24508](∅→∅),[29.5613]→[13.24506:24508](∅→∅),[13.24506]→[13.24506:24508](∅→∅),[13.24508]→[29.5614:5615](∅→∅),[29.5615]→[32.5151:5398](∅→∅),[32.5398]→[29.5615:5757](∅→∅),[29.5615]→[29.5615:5757](∅→∅),[29.5757]→[36.1058:1092](∅→∅),[36.1092]→[29.5757:5882](∅→∅),[29.5757]→[29.5757:5882](∅→∅),[29.5882]→[36.1093:1127](∅→∅),[36.1127]→[29.5882:5889](∅→∅),[29.5882]→[29.5882:5889](∅→∅),[29.5889]→[34.13778:13833](∅→∅),[34.13833]→[31.9052:9089](∅→∅),[29.5937]→[31.9052:9089](∅→∅),[31.9089]→[36.1128:1162](∅→∅),[36.1162]→[31.9089:9096](∅→∅),[31.9089]→[31.9089:9096](∅→∅),[31.9096]→[29.5968:6028](∅→∅),[29.5968]→[29.5968:6028](∅→∅),[29.6028]→[37.21046:21091](∅→∅),[37.21091]→[32.5399:5463](∅→∅),[31.9142]→[32.5399:5463](∅→∅),[32.5463]→[34.13834:13916](∅→∅),[34.13916]→[32.5463:5470](∅→∅),[32.5463]→[32.5463:5470](∅→∅),[32.5470]→[34.13917:14119](∅→∅)
}fn view_actions<'a>(state: ActionState) -> Element<'a, Msg, Theme> {let left = || {action_button("←| h","",Msg::Selection(selection::Msg::PressDir(selection::Dir::Left)),)};let down = || {action_button("↓| j","",Msg::Selection(selection::Msg::PressDir(selection::Dir::Down)),)};let up = || {action_button("↑| k","",Msg::Selection(selection::Msg::PressDir(selection::Dir::Up)),)};let right = || {action_button("→| l","",Msg::Selection(selection::Msg::PressDir(selection::Dir::Right)),)};let down_no_skip = || {action_button("S-(↓| j)","no skip",Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Down)),)};let up_no_skip = || {action_button("S-(↑| k)","no skip",Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Up)),)};let add_untracked =|| action_button("a", "track file", Msg::AddUntrackedFile);let rm_added_file = || action_button("x", "untrack file", Msg::RmAddedFile);let start_record = || action_button("r", "record", Msg::StartRecord);let save_record = || action_button("C-s", "save record", Msg::SaveRecord);let postpone_record =|| action_button("C-d", "postpone record", Msg::PostponeRecord);let discard_record =|| action_button("C-d", "discard record", Msg::DiscardRecord);let select_channel =|| action_button("c", "select channel", Msg::SelectChannel);let fork_channel = || action_button("f", "fork channel", Msg::ForkChannel);let refresh_repo =|| action_button("C-r", "refresh repo", Msg::RefreshRepo);let confirm =|label: &'static str| action_button("Enter", label, Msg::Confirm);let cant_confirm =|label: &'static str| el(action_button_inner("Enter", label));let cancel = || action_button("Esc", "cancel", Msg::Cancel);let forking_channel = matches!(state, ActionState::ForkingChannel { .. });#[allow(clippy::let_and_return)]let row = match state {ActionState::Main {selection,can_select_right,can_record,has_other_channels,} => {let row = row([down(), up()]);let row = match selection {MainSelection::Untracked => {let row = row.push(add_untracked());let row = add_if(can_select_right, right, row);add_if(can_record, start_record, row)}MainSelection::AddedFromUntracked => {let row = row.push(rm_added_file());let row = add_if(can_select_right, right, row);add_if(can_record, start_record, row)}MainSelection::Other => {let row = add_if(can_select_right, right, row);add_if(can_record, start_record, row)}};let row = add_if(has_other_channels, select_channel, row);row}ActionState::LogChange {can_select_right,can_record,has_other_channels,} => {let row = row([left(), down(), up()]);let row = add_if(can_select_right, right, row);let row = add_if(can_record, start_record, row);let row = add_if(has_other_channels, select_channel, row);row}ActionState::Diff {can_record,has_other_channels,} => {let row = row([left(), down(), up(), down_no_skip(), up_no_skip()]);let row = add_if(can_record, start_record, row);let row = add_if(has_other_channels, select_channel, row);row}ActionState::Recording => {row([save_record(), postpone_record(), discard_record()])}ActionState::SelectingChannel(state) => match state {SwitchingChannelState::NoOtherChannels => row([cancel()]),SwitchingChannelState::NothingSelected => {row([down(), up(), cancel()])}SwitchingChannelState::SomethingSelected { can_switch } => {let row = row([down(), up(), cancel()]);let row = add_if(!can_switch,|| cant_confirm("cannot switch with unrecorded changes"),row,);let row = add_if(can_switch, || confirm("switch channel"), row);row}},ActionState::ForkingChannel { empty, unique } => {let row = row([]);let row = add_if(!empty && unique, || confirm("confirm fork"), row);let row =add_if(!unique, || cant_confirm("channel already exists"), row);let row = row.push(cancel());row}ActionState::EntireLog { can_select_right } => {let row = row([down(), up()]);let row = add_if(can_select_right, right, row);row}ActionState::EntireLogChange { can_select_right } => {let row = row([left(), down(), up()]);let row = add_if(can_select_right, right, row);row}ActionState::EntireLogChangeDiff => {let row = row([left(), down(), up(), down_no_skip(), up_no_skip()]);row}};let row = add_if(!forking_channel, fork_channel, row);let row = row.push(refresh_repo());el(row.spacing(2).wrap())}fn add_if<'a, F>(predicate: bool,button: F,row: row::Row<'a, Msg, Theme>,) -> row::Row<'a, Msg, Theme>whereF: Fn() -> Element<'a, Msg, Theme>,{if predicate {row.push(button())} else {row}}enum ActionState {/// Main statusMain {selection: MainSelection,can_select_right: bool,can_record: bool,has_other_channels: bool,},/// Selected a log change, but not diffLogChange {can_select_right: bool,can_record: bool,has_other_channels: bool,},/// Untracked, changed or status log change's diffDiff {can_record: bool,has_other_channels: bool,},/// Making a record from current changesRecording,SelectingChannel(SwitchingChannelState),ForkingChannel {empty: bool,unique: bool,},/// Viewing entire logEntireLog {can_select_right: bool,},/// Viewing entire log with some change selectedEntireLogChange {can_select_right: bool,},/// Viewing entire log with some diff of a change selectedEntireLogChangeDiff, - edit in inflorescence_view/src/app.rs at line 752[29.6030]→[29.6030:6105](∅→∅),[29.6105]→[31.9143:9214](∅→∅),[31.9214]→[36.1163:1207](∅→∅),[36.1207]→[31.9237:9240](∅→∅),[31.9237]→[31.9237:9240](∅→∅),[31.9240]→[29.6105:6142](∅→∅),[29.6105]→[29.6105:6142](∅→∅),[29.6142]→[38.279:332](∅→∅),[38.332]→[37.21152:21748](∅→∅),[37.21152]→[37.21152:21748](∅→∅)
enum MainSelection {Untracked,AddedFromUntracked,Other,}enum SwitchingChannelState {NoOtherChannels,NothingSelected,SomethingSelected { can_switch: bool },}/// Determine state for actions menufn action_state(state: &ReadyState) -> ActionState {let ReadyState {user_id: _,repo:repo::State {dir_name: _,channel,other_channels,untracked_files: _,changed_files,short_log: _,},selection,navigation,record_msg,forking_channel_name,logs: _,} = state;let selection::State {primary,status: status_selection,channel: channel_selection,entire_log: entire_log_selection,held_key: _,} = selection; - replacement in inflorescence_view/src/app.rs at line 753[37.21749]→[29.6279:6425](∅→∅),[29.6279]→[29.6279:6425](∅→∅),[29.6425]→[31.9348:9355](∅→∅),[31.9355]→[37.21750:21806](∅→∅),[37.21806]→[32.5527:5596](∅→∅),[32.5527]→[32.5527:5596](∅→∅),[32.5596]→[37.21807:21902](∅→∅),[37.21902]→[32.5671:5740](∅→∅),[32.5671]→[32.5671:5740](∅→∅),[32.5740]→[37.21903:23159](∅→∅),[37.23159]→[34.14560:14589](∅→∅),[34.14560]→[34.14560:14589](∅→∅),[34.14589]→[37.23160:23410](∅→∅),[37.23410]→[34.14858:14906](∅→∅),[34.14858]→[34.14858:14906](∅→∅),[34.15053]→[34.15053:15071](∅→∅),[34.15071]→[37.23411:25396](∅→∅),[37.25396]→[36.1532:1554](∅→∅),[36.1532]→[36.1532:1554](∅→∅),[36.1554]→[37.25397:27432](∅→∅),[36.1599]→[29.7118:7158](∅→∅),[37.27432]→[29.7118:7158](∅→∅),[29.7118]→[29.7118:7158](∅→∅),[29.7158]→[37.27433:27530](∅→∅),[37.27530]→[29.7272:7349](∅→∅),[29.7272]→[29.7272:7349](∅→∅),[29.7349]→[36.1600:1640](∅→∅),[36.1640]→[37.27531:27550](∅→∅),[37.27550]→[29.7367:7391](∅→∅),[29.7367]→[29.7367:7391](∅→∅),[29.7391]→[37.27551:27965](∅→∅),[37.27965]→[29.7761:7776](∅→∅),[29.7761]→[29.7761:7776](∅→∅),[29.7776]→[38.333:386](∅→∅),[38.386]→[37.28027:28269](∅→∅),[37.28027]→[37.28027:28269](∅→∅),[37.28269]→[38.387:416](∅→∅),[38.416]→[37.28305:29160](∅→∅),[37.28305]→[37.28305:29160](∅→∅),[36.1828]→[29.8258:8280](∅→∅),[37.29160]→[29.8258:8280](∅→∅),[29.8258]→[29.8258:8280](∅→∅),[29.8280]→[37.29161:29399](∅→∅),[37.29399]→[38.417:435](∅→∅)
match record_msg {Some(RecordMsg::Typing(_)) => return ActionState::Recording,Some(RecordMsg::Canceled { .. }) | None => {}}if let Some(name) = forking_channel_name.as_ref() {let name = name.trim();let empty = name.is_empty();let unique =channel != name && !other_channels.iter().any(|n| n == name);return ActionState::ForkingChannel { empty, unique };}match primary {selection::Primary::Status => {let can_record = !changed_files.is_empty();let has_other_channels = !other_channels.is_empty();match status_selection {Some(selection::Status::UntrackedFile {ix: _,path,diff_selected,}) => {let id_hash =file::id_parts_hash(path, file::Kind::Untracked);let nav = get_files_diffs_nav(navigation, id_hash);if let Some(nav) = nav {if *diff_selected {ActionState::Diff {can_record,has_other_channels,}} else {ActionState::Main {selection: MainSelection::Untracked,can_select_right:nav_scrollable::needs_scrolling(nav),can_record,has_other_channels,}}} else {ActionState::Main {selection: MainSelection::Untracked,can_select_right: false,can_record,has_other_channels,}}}Some(selection::Status::ChangedFile {ix: _,path,diff_selected,}) => {let is_added_from_untracked = changed_files.get(path).map(|diffs| {diffs.iter().any(|diff| {matches!(diff, repo::ChangedFileDiff::Add)})}).unwrap_or_default();let main_selection = || {if is_added_from_untracked {MainSelection::AddedFromUntracked} else {MainSelection::Other}};let id_hash =file::id_parts_hash(path, file::Kind::Changed);let nav = get_files_diffs_nav(navigation, id_hash);if let Some(nav) = nav {if *diff_selected {ActionState::Diff {can_record,has_other_channels,}} else {ActionState::Main {selection: main_selection(),can_select_right:nav_scrollable::needs_scrolling(nav),can_record,has_other_channels,}}} else {ActionState::Main {selection: main_selection(),can_select_right: false,can_record,has_other_channels,}}}Some(selection::Status::LogChange(selection::LogChange {ix: _,hash,message: _,file,})) => {let nav = get_status_log_files_nav(navigation, *hash);match file {Some(selection::LogChangeFileSelection {ix: _,path: _,diff_selected,}) => {if let Some(nav) = nav {if *diff_selected {ActionState::Diff {can_record,has_other_channels,}} else {ActionState::LogChange {can_select_right:nav_scrollable::needs_scrolling(nav),can_record,has_other_channels,}}} else {ActionState::LogChange {can_select_right: false,can_record,has_other_channels,}}}None => ActionState::Main {selection: MainSelection::Other,can_select_right: nav.map(nav_scrollable::needs_scrolling).unwrap_or_default(),can_record,has_other_channels,},}}None => ActionState::Main {selection: MainSelection::Other,can_select_right: false,can_record,has_other_channels,},}}selection::Primary::Channel => {let sub_state = if other_channels.is_empty() {SwitchingChannelState::NoOtherChannels} else if channel_selection.is_some() {let can_switch = changed_files.is_empty();SwitchingChannelState::SomethingSelected { can_switch }} else {SwitchingChannelState::NothingSelected};ActionState::SelectingChannel(sub_state)}selection::Primary::EntireLog => {if let Some(selection::LogChange { hash, file, .. }) =entire_log_selection{let nav = get_entire_log_files_nav(navigation, *hash);match file {Some(selection::LogChangeFileSelection {ix: _,path: _,diff_selected,}) => {if let Some(nav) = nav {if *diff_selected {ActionState::EntireLogChangeDiff} else {ActionState::EntireLogChange {can_select_right:nav_scrollable::needs_scrolling(nav),}}} else {ActionState::EntireLogChange {can_select_right: false,}}}None => ActionState::EntireLog {can_select_right: nav.map(nav_scrollable::needs_scrolling).unwrap_or_default(),},}fn view_actions<'a>(allowed_actions: &[action::Binding],) -> Element<'a, Msg, Theme> {let buttons: Vec<_> = allowed_actions.iter().map(|action::Binding { key, label, msg }| {if let Some(msg) = msg {action_button(key, label, Msg::Action(msg.clone())) - replacement in inflorescence_view/src/app.rs at line 762[29.8319]→[37.29419:29460](∅→∅),[37.29460]→[29.8404:8449](∅→∅),[29.8404]→[29.8404:8449](∅→∅),[36.1869]→[29.8481:8499](∅→∅),[29.8481]→[29.8481:8499](∅→∅)
ActionState::EntireLog {can_select_right: false,}el(action_button_inner(key, label)) - replacement in inflorescence_view/src/app.rs at line 764
}}}).collect();let row = row(buttons);el(row.spacing(2).wrap()) - replacement in inflorescence_view/src/app.rs at line 825
.on_press(Msg::Selection(selection::Msg::Select(selection::Select::LogChange {.on_press(Msg::Action(action::Msg::Selection(selection::Msg::Select(selection::Select::LogChange { - replacement in inflorescence_view/src/app.rs at line 830
},}), - replacement in inflorescence_model/src/selection.rs at line 5
#[derive(Debug, Clone)]#[derive(Debug, Clone, PartialEq)] - replacement in inflorescence_model/src/selection.rs at line 84
#[derive(Debug, Clone)]#[derive(Debug, Clone, PartialEq)] - edit in inflorescence_model/src/lib.rs at line 1
pub mod action; - edit in inflorescence_model/src/lib.rs at line 34
/// Cache allowed actions. Used for action filter and for view.pub allowed_actions: Vec<action::Binding>, - file addition: action.rs[37.29627]
use crate::{self as model, get_entire_log_diffs_nav, get_entire_log_files_nav,get_files_diffs_nav, get_status_log_diffs_nav, get_status_log_files_nav,selection, ReadyState, RecordMsg,};use iced_expl_widget::nav_scrollable;use libflorescence::{file, repo};#[derive(Debug)]pub struct Binding {pub key: &'static str,pub label: &'static str,pub msg: Option<Msg>,}/// Msgs that are bound to some key(s) and that are only allowed depending on the current state.#[derive(Debug, Clone)]pub enum Msg {Confirm,Cancel,Selection(selection::Msg),PostponeRecord,SaveRecord,DiscardRecord,AddUntrackedFile,RmAddedFile,StartRecord,/// Show a list of channels to switch toSelectChannel,ForkChannel,RefreshRepo,ShowEntireLog,}/// Eq used for action filters. Properties that are not determined by which actions are allowed are ignored.pub fn is_same_msg(left: &Msg, right: &Msg) -> bool {use Msg::*;match (left, right) {(Confirm, Confirm) => true,(Cancel, Cancel) => true,(Selection(left), Selection(right)) => left == right,(PostponeRecord, PostponeRecord) => true,(SaveRecord, SaveRecord) => true,(DiscardRecord, DiscardRecord) => true,(AddUntrackedFile, AddUntrackedFile) => true,(RmAddedFile, RmAddedFile) => true,(StartRecord, StartRecord) => true,(SelectChannel, SelectChannel) => true,(ForkChannel, ForkChannel) => true,(RefreshRepo, RefreshRepo) => true,(ShowEntireLog, ShowEntireLog) => true,(Confirm, _) => false,(Cancel, _) => false,(Selection(_), _) => false,(PostponeRecord, _) => false,(SaveRecord, _) => false,(DiscardRecord, _) => false,(AddUntrackedFile, _) => false,(RmAddedFile, _) => false,(StartRecord, _) => false,(SelectChannel, _) => false,(ForkChannel, _) => false,(RefreshRepo, _) => false,(ShowEntireLog, _) => false,}}pub fn get_allowed(state: &model::SubState) -> Vec<Binding> {match state {model::SubState::Loading { .. } => vec![],model::SubState::SelectingId { .. } => todo!(),model::SubState::Ready(ready_state) => get_ready_allowed(ready_state),}}fn get_ready_allowed(state: &ReadyState) -> Vec<Binding> {let State {has_other_channels,sub,} = derive_state(state);let left = || Binding {key: "←| h",label: "",msg: Some(Msg::Selection(selection::Msg::PressDir(selection::Dir::Left,))),};let down = || Binding {key: "↓| j",label: "",msg: Some(Msg::Selection(selection::Msg::PressDir(selection::Dir::Down,))),};let up = || Binding {key: "↑| k",label: "",msg: Some(Msg::Selection(selection::Msg::PressDir(selection::Dir::Up))),};let right = || Binding {key: "→| l",label: "",msg: Some(Msg::Selection(selection::Msg::PressDir(selection::Dir::Right,))),};let down_no_skip = || Binding {key: "S-(↓| j)",label: "no skip",msg: Some(Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Down,))),};let up_no_skip = || Binding {key: "S-(↑| k)",label: "no skip",msg: Some(Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Up,))),};let add_untracked = || Binding {key: "a",label: "track file",msg: Some(Msg::AddUntrackedFile),};let rm_added_file = || Binding {key: "x",label: "untrack file",msg: Some(Msg::RmAddedFile),};let start_record = || Binding {key: "r",label: "record",msg: Some(Msg::StartRecord),};let save_record = || Binding {key: "C-s",label: "save record",msg: Some(Msg::SaveRecord),};let postpone_record = || Binding {key: "C-d",label: "postpone record",msg: Some(Msg::PostponeRecord),};let discard_record = || Binding {key: "C-d",label: "discard record",msg: Some(Msg::DiscardRecord),};let select_channel = || Binding {key: "c",label: "select channel",msg: Some(Msg::SelectChannel),};let fork_channel = || Binding {key: "f",label: "fork channel",msg: Some(Msg::ForkChannel),};let refresh_repo = || Binding {key: "C-r",label: "refresh repo",msg: Some(Msg::RefreshRepo),};let confirm = |label: &'static str| Binding {key: "Enter",label,msg: Some(Msg::Confirm),};let cant_confirm = |label: &'static str| Binding {key: "Enter",label,msg: None,};let cancel = || Binding {key: "Esc",label: "cancel",msg: Some(Msg::Cancel),};let exit_entire_log = || Binding {key: "Esc",label: "exit entire log",msg: Some(Msg::Cancel),};let show_entire_log = || Binding {key: "e",label: "entire log",msg: Some(Msg::ShowEntireLog),};let forking_channel = matches!(sub, SubState::ForkingChannel { .. });let mut actions = vec![];let ma = &mut actions;match sub {SubState::Main {selection,can_select_right,can_record,} => {ma.push(down());ma.push(up());match selection {MainSelection::Untracked => {ma.push(add_untracked());push_if(can_select_right, right, ma);push_if(can_record, start_record, ma)}MainSelection::AddedFromUntracked => {ma.push(rm_added_file());push_if(can_select_right, right, ma);push_if(can_record, start_record, ma)}MainSelection::Other => {push_if(can_select_right, right, ma);push_if(can_record, start_record, ma)}};ma.push(show_entire_log());push_if(has_other_channels, select_channel, ma);}SubState::StatusLogChange {can_select_right,can_record,} => {ma.push(left());ma.push(down());ma.push(up());push_if(can_select_right, right, ma);push_if(can_record, start_record, ma);ma.push(show_entire_log());push_if(has_other_channels, select_channel, ma);}SubState::StatusLogDiff { can_record } => {ma.push(left());ma.push(down());ma.push(up());ma.push(down_no_skip());ma.push(up_no_skip());push_if(can_record, start_record, ma);ma.push(show_entire_log());push_if(has_other_channels, select_channel, ma);}SubState::Recording => {ma.push(save_record());ma.push(postpone_record());ma.push(discard_record());}SubState::SelectingChannel(state) => {match state {SwitchingChannelState::NoOtherChannels => ma.push(cancel()),SwitchingChannelState::NothingSelected => {ma.push(down());ma.push(up());ma.push(cancel());}SwitchingChannelState::SomethingSelected { can_switch } => {ma.push(down());ma.push(up());ma.push(cancel());push_if(!can_switch,|| {cant_confirm("cannot switch with unrecorded changes",)},ma,);push_if(can_switch, || confirm("switch channel"), ma);}};ma.push(show_entire_log());}SubState::ForkingChannel { empty, unique } => {push_if(!empty && unique, || confirm("confirm fork"), ma);push_if(!unique, || cant_confirm("channel already exists"), ma);ma.push(cancel());}SubState::EntireLog { can_select_right } => {ma.push(down());ma.push(up());push_if(can_select_right, right, ma);ma.push(exit_entire_log());push_if(has_other_channels, select_channel, ma);}SubState::EntireLogChange { can_select_right } => {ma.push(left());ma.push(down());ma.push(up());push_if(can_select_right, right, ma);ma.push(exit_entire_log());push_if(has_other_channels, select_channel, ma);}SubState::EntireLogChangeDiff => {ma.push(left());ma.push(down());ma.push(up());ma.push(down_no_skip());ma.push(up_no_skip());ma.push(exit_entire_log());}};push_if(!forking_channel, fork_channel, ma);ma.push(refresh_repo());actions}fn push_if<'a, F>(predicate: bool, to_add: F, actions: &mut Vec<Binding>)whereF: Fn() -> Binding,{if predicate {actions.push(to_add())}}#[derive(Debug, Clone, Copy)]struct State {has_other_channels: bool,sub: SubState,}#[derive(Debug, Clone, Copy)]enum SubState {/// Main statusMain {selection: MainSelection,can_select_right: bool,can_record: bool,},/// Selected a log change, but not diffStatusLogChange {can_select_right: bool,can_record: bool,},/// Untracked, changed or status log change's diffStatusLogDiff {can_record: bool,},/// Making a record from current changesRecording,SelectingChannel(SwitchingChannelState),ForkingChannel {empty: bool,unique: bool,},/// Viewing entire logEntireLog {can_select_right: bool,},/// Viewing entire log with some change selectedEntireLogChange {can_select_right: bool,},/// Viewing entire log with some diff of a change selectedEntireLogChangeDiff,}#[derive(Debug, Clone, Copy)]enum MainSelection {Untracked,AddedFromUntracked,Other,}#[derive(Debug, Clone, Copy)]enum SwitchingChannelState {NoOtherChannels,NothingSelected,SomethingSelected { can_switch: bool },}/// Determine state for actions menufn derive_state(state: &ReadyState) -> State {let has_other_channels = !state.repo.other_channels.is_empty();let sub = derive_sub_state(state);State {has_other_channels,sub,}}/// Determine state for actions menufn derive_sub_state(state: &ReadyState) -> SubState {let ReadyState {user_id: _,repo:repo::State {dir_name: _,channel,other_channels,untracked_files: _,changed_files,short_log: _,},selection,navigation,record_msg,forking_channel_name,logs: _,} = state;let selection::State {primary,status: status_selection,channel: channel_selection,entire_log: entire_log_selection,held_key: _,} = selection;match record_msg {Some(RecordMsg::Typing(_)) => return SubState::Recording,Some(RecordMsg::Canceled { .. }) | None => {if let Some(name) = forking_channel_name.as_ref() {let name = name.trim();let empty = name.is_empty();let unique = channel != name&& !other_channels.iter().any(|n| n == name);return SubState::ForkingChannel { empty, unique };}}}match primary {selection::Primary::Status => {let can_record = !changed_files.is_empty();match status_selection {Some(selection::Status::UntrackedFile {ix: _,path,diff_selected,}) => {let id_hash =file::id_parts_hash(path, file::Kind::Untracked);let nav = get_files_diffs_nav(navigation, id_hash);if let Some(nav) = nav {if *diff_selected {SubState::StatusLogDiff { can_record }} else {SubState::Main {selection: MainSelection::Untracked,can_select_right:nav_scrollable::needs_scrolling(nav),can_record,}}} else {SubState::Main {selection: MainSelection::Untracked,can_select_right: false,can_record,}}}Some(selection::Status::ChangedFile {ix: _,path,diff_selected,}) => {let is_added_from_untracked = changed_files.get(path).map(|diffs| {diffs.iter().any(|diff| {matches!(diff, repo::ChangedFileDiff::Add)})}).unwrap_or_default();let main_selection = || {if is_added_from_untracked {MainSelection::AddedFromUntracked} else {MainSelection::Other}};let id_hash =file::id_parts_hash(path, file::Kind::Changed);let nav = get_files_diffs_nav(navigation, id_hash);if let Some(nav) = nav {if *diff_selected {SubState::StatusLogDiff { can_record }} else {SubState::Main {selection: main_selection(),can_select_right:nav_scrollable::needs_scrolling(nav),can_record,}}} else {SubState::Main {selection: main_selection(),can_select_right: false,can_record,}}}Some(selection::Status::LogChange(selection::LogChange {ix: _,hash,message: _,file,})) => match file {Some(selection::LogChangeFileSelection {ix: _,path,diff_selected,}) => {let log_id = file::log_id_parts_hash(*hash, path);let nav = get_status_log_diffs_nav(navigation, log_id);if let Some(nav) = nav {if *diff_selected {SubState::StatusLogDiff { can_record }} else {SubState::StatusLogChange {can_record,can_select_right:nav_scrollable::needs_scrolling(nav),}}} else {SubState::StatusLogChange {can_record,can_select_right: false,}}}None => {let nav = get_status_log_files_nav(navigation, *hash);SubState::Main {selection: MainSelection::Other,can_select_right: nav.is_some(),can_record,}}},None => SubState::Main {selection: MainSelection::Other,can_select_right: false,can_record,},}}selection::Primary::Channel => {let sub_state = if other_channels.is_empty() {SwitchingChannelState::NoOtherChannels} else if channel_selection.is_some() {let can_switch = changed_files.is_empty();SwitchingChannelState::SomethingSelected { can_switch }} else {SwitchingChannelState::NothingSelected};SubState::SelectingChannel(sub_state)}selection::Primary::EntireLog => {if let Some(selection::LogChange { hash, file, .. }) =entire_log_selection{match file {Some(selection::LogChangeFileSelection {ix: _,path,diff_selected,}) => {let log_id = file::log_id_parts_hash(*hash, path);let nav = get_entire_log_diffs_nav(navigation, log_id);if let Some(nav) = nav {if *diff_selected {SubState::EntireLogChangeDiff} else {SubState::EntireLogChange {can_select_right:nav_scrollable::needs_scrolling(nav),}}} else {SubState::EntireLogChange {can_select_right: false,}}}None => {let nav = get_entire_log_files_nav(navigation, *hash);SubState::EntireLog {can_select_right: nav.is_some(),}}}} else {SubState::EntireLog {can_select_right: false,}}}}} - edit in inflorescence/src/selection.rs at line 14
use inflorescence_view::app; - edit in inflorescence/src/selection.rs at line 1560
dbg!(diff::any_diff_has_contents(diffs)); - replacement in inflorescence/src/selection.rs at line 1602
Task::done(crate::Msg::View(app::Msg::ToRepo(repo::MsgIn::LoadOtherChannelLog(name.clone()),Task::done(crate::Msg::ToRepo(repo::MsgIn::LoadOtherChannelLog(name.clone(), - replacement in inflorescence/src/selection.rs at line 1653
Task::done(crate::Msg::View(app::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash },)))Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash })) - replacement in inflorescence/src/selection.rs at line 1705
Task::done(crate::Msg::View(app::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash },)))Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash })) - replacement in inflorescence/src/main.rs at line 11
self as model, Log, Logs, ReadyState, RecordMsg, State as MState,SubState as MSubState,self as model, action, Log, Logs, ReadyState, RecordMsg, - edit in inflorescence/src/main.rs at line 92
let sub = model::State {window_size,repo_path,sub: model::SubState::Loading {user_ids: Vec::new(),repo: None,},allowed_actions: default(),}; - replacement in inflorescence/src/main.rs at line 106
sub: MState {window_size,repo_path,sub: MSubState::Loading {user_ids: Vec::new(),repo: None,},},sub, - edit in inflorescence/src/main.rs at line 128
ToRepo(repo::MsgIn), - replacement in inflorescence/src/main.rs at line 134[11.534]→[6.6702:6718](∅→∅),[8.756]→[6.6702:6718](∅→∅),[10.945]→[6.6702:6718](∅→∅),[13.25858]→[6.6702:6718](∅→∅),[4.2512]→[6.6702:6718](∅→∅)
match msg {let task = match msg { - replacement in inflorescence/src/main.rs at line 136
Msg::View(msg) => update_from_app_view(state, msg),Msg::View(msg) => update_from_app(state, msg), - replacement in inflorescence/src/main.rs at line 140
MSubState::Loading { user_ids, repo } => {model::SubState::Loading { user_ids, repo } => { - replacement in inflorescence/src/main.rs at line 143
state.sub.sub = MSubState::Ready(ReadyState {state.sub.sub = model::SubState::Ready(ReadyState { - replacement in inflorescence/src/main.rs at line 156
MSubState::SelectingId { .. } => unreachable!(),MSubState::Ready(..) => {model::SubState::SelectingId { .. } => unreachable!(),model::SubState::Ready(..) => { - edit in inflorescence/src/main.rs at line 173
}Msg::ToRepo(msg) => {state.repo_tx_in.send(msg).unwrap();Task::none() - replacement in inflorescence/src/main.rs at line 230
}};state.sub.allowed_actions = action::get_allowed(&state.sub.sub);task - replacement in inflorescence/src/main.rs at line 274
fn update_from_app_view(state: &mut State, msg: app::Msg) -> Task<Msg> {fn update_from_app(state: &mut State, msg: app::Msg) -> Task<Msg> {// Return early if the action is not allowed in the current stateif let app::Msg::Action(msg) = &msg&& let Some(_ready_state) = model::ready(&mut state.sub){if !state.sub.allowed_actions.iter().any(|action::Binding {msg: allowed_msg, ..}| {if let Some(allowed_msg) = allowed_msg {action::is_same_msg(msg, allowed_msg)} else {false}},) {return Task::none();}} - replacement in inflorescence/src/main.rs at line 295
app::Msg::Confirm => {app::Msg::Action(msg) => update_from_action(state, msg),app::Msg::EditRecordMsg(action) => edit_record_msg(state, action),app::Msg::EditForkChannelName(name) => {if let Some(ReadyState {forking_channel_name,..}) = model::ready_mut(&mut state.sub){*forking_channel_name = Some(name);}Task::none()}}}fn update_from_action(state: &mut State, msg: action::Msg) -> Task<Msg> {match msg {action::Msg::Confirm => { - replacement in inflorescence/src/main.rs at line 358
app::Msg::Cancel => {action::Msg::Cancel => { - replacement in inflorescence/src/main.rs at line 385
app::Msg::Selection(msg) => {action::Msg::Selection(msg) => { - replacement in inflorescence/src/main.rs at line 405[24.3499]→[13.26614:26733](∅→∅),[23.4246]→[13.26614:26733](∅→∅),[22.6527]→[13.26614:26733](∅→∅),[28.9204]→[13.26614:26733](∅→∅),[37.85298]→[13.26614:26733](∅→∅),[13.26614]→[13.26614:26733](∅→∅),[27.4982]→[17.343:470](∅→∅),[13.26733]→[17.343:470](∅→∅),[17.470]→[29.12719:12834](∅→∅),[28.9883]→[29.12835:13009](∅→∅),[29.13009]→[36.3160:3197](∅→∅),[36.3197]→[37.85299:85404](∅→∅)
app::Msg::ToRepo(msg) => {state.repo_tx_in.send(msg).unwrap();Task::none()}app::Msg::EditRecordMsg(action) => edit_record_msg(state, action),app::Msg::SaveRecord => save_record(state),app::Msg::PostponeRecord => defer_record(state),app::Msg::DiscardRecord => abandon_record(state),app::Msg::AddUntrackedFile => add_untracked_file(state),app::Msg::RmAddedFile => rm_added_file(state),app::Msg::StartRecord => start_record(state),app::Msg::SelectChannel => {if let Some(ReadyState { selection, .. }) =model::ready_mut(&mut state.sub)action::Msg::SaveRecord => save_record(state),action::Msg::PostponeRecord => defer_record(state),action::Msg::DiscardRecord => abandon_record(state),action::Msg::AddUntrackedFile => add_untracked_file(state),action::Msg::RmAddedFile => rm_added_file(state),action::Msg::StartRecord => start_record(state),action::Msg::SelectChannel => {if let Some(ReadyState {selection, repo, ..}) = model::ready_mut(&mut state.sub)&& !repo.other_channels.is_empty() - replacement in inflorescence/src/main.rs at line 421
app::Msg::ForkChannel => {action::Msg::ForkChannel => { - replacement in inflorescence/src/main.rs at line 432[31.19164]→[32.7615:7660](∅→∅),[32.7660]→[37.85704:85914](∅→∅),[37.85914]→[32.7765:7814](∅→∅),[32.7765]→[32.7765:7814](∅→∅),[32.7814]→[30.237:272](∅→∅),[31.19164]→[30.237:272](∅→∅),[29.13009]→[30.237:272](∅→∅)
app::Msg::ForkChannelName(name) => {if let Some(ReadyState {forking_channel_name,..}) = model::ready_mut(&mut state.sub){*forking_channel_name = Some(name);}Task::none()}app::Msg::RefreshRepo => {action::Msg::RefreshRepo => { - replacement in inflorescence/src/main.rs at line 439
app::Msg::ShowEntireLog => {action::Msg::ShowEntireLog => { - replacement in inflorescence/src/main.rs at line 701
MSubState::Loading { user_ids, repo: _ } => {model::SubState::Loading { user_ids, repo: _ } => { - replacement in inflorescence/src/main.rs at line 704
MSubState::Ready(ReadyState {model::SubState::Ready(ReadyState { - replacement in inflorescence/src/main.rs at line 714
MSubState::SelectingId {model::SubState::SelectingId { - replacement in inflorescence/src/main.rs at line 722
MSubState::SelectingId { repo, .. } => *repo = Some(repo_state),MSubState::Ready(_) => {}model::SubState::SelectingId { repo, .. } => *repo = Some(repo_state),model::SubState::Ready(_) => {} - replacement in inflorescence/src/main.rs at line 755
Msg::View(app::Msg::ToRepo(repo::MsgIn::RefreshChangedAndUntrackedFiles,))Msg::ToRepo(repo::MsgIn::RefreshChangedAndUntrackedFiles) - replacement in inflorescence/src/main.rs at line 769
MSubState::Loading { user_ids: _, repo } => *repo = Some(repo_state),MSubState::SelectingId { repo, .. } => *repo = Some(repo_state),MSubState::Ready(ReadyState {model::SubState::Loading { user_ids: _, repo } => {*repo = Some(repo_state)}model::SubState::SelectingId { repo, .. } => *repo = Some(repo_state),model::SubState::Ready(ReadyState { - replacement in inflorescence/src/main.rs at line 909
Task::done(Msg::View(app::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash },)))Task::done(Msg::ToRepo(repo::MsgIn::GetChangeDiffs {hash,})) - replacement in inflorescence/src/main.rs at line 943
Task::done(Msg::View(app::Msg::ToRepo(repo::MsgIn::LoadOtherChannelLog(name.clone()),Task::done(Msg::ToRepo(repo::MsgIn::LoadOtherChannelLog(name.clone(), - replacement in inflorescence/src/main.rs at line 1004
Task::done(Msg::View(app::Msg::ToRepo(repo::MsgIn::LoadEntireLog)))Task::done(Msg::ToRepo(repo::MsgIn::LoadEntireLog)) - edit in inflorescence/src/main.rs at line 1190
let action = |msg| Some(Msg::View(app::Msg::Action(msg)));let selection = |selection| action(action::Msg::Selection(selection)); - replacement in inflorescence/src/main.rs at line 1198[32.8155]→[31.22615:22750](∅→∅),[34.54338]→[31.22615:22750](∅→∅),[31.22615]→[31.22615:22750](∅→∅),[31.22750]→[25.1058:1083](∅→∅),[25.1058]→[25.1058:1083](∅→∅),[25.1083]→[31.22751:22884](∅→∅),[31.22884]→[25.1207:1232](∅→∅),[25.1207]→[25.1207:1232](∅→∅),[25.1232]→[31.22885:23020](∅→∅),[31.23020]→[25.1358:1383](∅→∅),[25.1358]→[25.1358:1383](∅→∅),[25.1383]→[31.23021:23157](∅→∅),[31.23157]→[25.1510:1535](∅→∅),[25.1510]→[25.1510:1535](∅→∅)
"j" => Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Down),))),"k" => Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Up),))),"h" => Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Left),))),"l" => Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Right),))),"j" => selection(selection::Msg::PressDir(selection::Dir::Down,)),"k" => {selection(selection::Msg::PressDir(selection::Dir::Up))}"h" => selection(selection::Msg::PressDir(selection::Dir::Left,)),"l" => selection(selection::Msg::PressDir(selection::Dir::Right,)), - replacement in inflorescence/src/main.rs at line 1212[34.54476]→[34.54476:54548](∅→∅),[34.54548]→[36.3487:3556](∅→∅),[36.3556]→[35.21801:21870](∅→∅),[34.54617]→[35.21801:21870](∅→∅),[35.21870]→[34.54682:54749](∅→∅),[34.54682]→[34.54682:54749](∅→∅),[34.54749]→[29.13083:13217](∅→∅),[25.1535]→[29.13083:13217](∅→∅)
"a" => Some(Msg::View(app::Msg::AddUntrackedFile)),"c" => Some(Msg::View(app::Msg::SelectChannel)),"e" => Some(Msg::View(app::Msg::ShowEntireLog)),"f" => Some(Msg::View(app::Msg::ForkChannel)),"r" => Some(Msg::View(app::Msg::StartRecord)),"x" => Some(Msg::View(app::Msg::RmAddedFile)),"a" => action(action::Msg::AddUntrackedFile),"c" => action(action::Msg::SelectChannel),"e" => action(action::Msg::ShowEntireLog),"f" => action(action::Msg::ForkChannel),"r" => action(action::Msg::StartRecord),"x" => action(action::Msg::RmAddedFile), - replacement in inflorescence/src/main.rs at line 1220
Key::Named(key::Named::Enter) => {Some(Msg::View(app::Msg::Confirm))}Key::Named(key::Named::Escape) => {Some(Msg::View(app::Msg::Cancel))}Key::Named(key::Named::Enter) => action(action::Msg::Confirm),Key::Named(key::Named::Escape) => action(action::Msg::Cancel), - replacement in inflorescence/src/main.rs at line 1223
Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Down),)))selection(selection::Msg::PressDir(selection::Dir::Down)) - replacement in inflorescence/src/main.rs at line 1226
Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Up),)))selection(selection::Msg::PressDir(selection::Dir::Up)) - replacement in inflorescence/src/main.rs at line 1229
Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Left),)))selection(selection::Msg::PressDir(selection::Dir::Left)) - replacement in inflorescence/src/main.rs at line 1232
Some(Msg::View(app::Msg::Selection(selection::Msg::PressDir(selection::Dir::Right),)))selection(selection::Msg::PressDir(selection::Dir::Right)) - replacement in inflorescence/src/main.rs at line 1240
Some(Msg::View(app::Msg::DiscardRecord))action(action::Msg::DiscardRecord) - replacement in inflorescence/src/main.rs at line 1243
Some(Msg::View(app::Msg::PostponeRecord))action(action::Msg::PostponeRecord) - replacement in inflorescence/src/main.rs at line 1246
Some(Msg::View(app::Msg::SaveRecord))action(action::Msg::SaveRecord) - replacement in inflorescence/src/main.rs at line 1249[30.505]→[30.505:590](∅→∅),[30.590]→[26.128:185](∅→∅),[26.128]→[26.128:185](∅→∅),[26.185]→[31.24305:24444](∅→∅),[31.24444]→[26.315:422](∅→∅),[26.315]→[26.315:422](∅→∅),[26.422]→[31.24445:24582](∅→∅),[31.24582]→[26.550:578](∅→∅),[26.550]→[26.550:578](∅→∅)
Some(Msg::View(app::Msg::RefreshRepo))}"j" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Down),)))}"k" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Up),)))action(action::Msg::RefreshRepo) - replacement in inflorescence/src/main.rs at line 1251[7.2363]→[26.579:636](∅→∅),[26.636]→[31.24583:24722](∅→∅),[31.24722]→[26.766:873](∅→∅),[26.766]→[26.766:873](∅→∅),[26.873]→[31.24723:24863](∅→∅),[31.24863]→[26.1004:1054](∅→∅),[26.1004]→[26.1004:1054](∅→∅)
"h" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Left),)))}"l" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Right),)))}"j" if mods == Modifiers::SHIFT => selection(selection::Msg::AltPressDir(selection::Dir::Down),),"k" if mods == Modifiers::SHIFT => selection(selection::Msg::AltPressDir(selection::Dir::Up),),"h" if mods == Modifiers::SHIFT => selection(selection::Msg::AltPressDir(selection::Dir::Left),),"l" if mods == Modifiers::SHIFT => selection(selection::Msg::AltPressDir(selection::Dir::Right),), - replacement in inflorescence/src/main.rs at line 1268
Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Down),)))selection(selection::Msg::AltPressDir(selection::Dir::Down)) - replacement in inflorescence/src/main.rs at line 1271
Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Up),)))selection(selection::Msg::AltPressDir(selection::Dir::Up)) - replacement in inflorescence/src/main.rs at line 1276
Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Left),)))selection(selection::Msg::AltPressDir(selection::Dir::Left)) - replacement in inflorescence/src/main.rs at line 1281
Some(Msg::View(app::Msg::Selection(selection::Msg::AltPressDir(selection::Dir::Right),)))selection(selection::Msg::AltPressDir(selection::Dir::Right,)) - replacement in inflorescence/src/main.rs at line 1294
"j" => Some(Msg::View(app::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Down),"j" => Some(Msg::View(app::Msg::Action(action::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Down,)), - replacement in inflorescence/src/main.rs at line 1299
"k" => Some(Msg::View(app::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Up),"k" => Some(Msg::View(app::Msg::Action(action::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Up,)), - replacement in inflorescence/src/main.rs at line 1304
"h" => Some(Msg::View(app::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Left),"h" => Some(Msg::View(app::Msg::Action(action::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Left,)), - replacement in inflorescence/src/main.rs at line 1309
"l" => Some(Msg::View(app::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Right),"l" => Some(Msg::View(app::Msg::Action(action::Msg::Selection(selection::Msg::ReleaseDir(selection::Dir::Right,)), - replacement in inflorescence/src/main.rs at line 1317
Some(Msg::View(app::Msg::Selection(Some(Msg::View(app::Msg::Action(action::Msg::Selection( - replacement in inflorescence/src/main.rs at line 1319
))))))) - replacement in inflorescence/src/main.rs at line 1322
Some(Msg::View(app::Msg::Selection(Some(Msg::View(app::Msg::Action(action::Msg::Selection( - replacement in inflorescence/src/main.rs at line 1324
))))))) - replacement in inflorescence/src/main.rs at line 1327
Some(Msg::View(app::Msg::Selection(Some(Msg::View(app::Msg::Action(action::Msg::Selection( - replacement in inflorescence/src/main.rs at line 1329
))))))) - replacement in inflorescence/src/main.rs at line 1332
Some(Msg::View(app::Msg::Selection(Some(Msg::View(app::Msg::Action(action::Msg::Selection( - replacement in inflorescence/src/main.rs at line 1334
)))))))