A6Z4O6RC33HYWP7JIVQ6FDWE4EOCQWQTIGENK2WAHUGSHDDLSA7QC WT3GA27PQ2AOAIGK65O3Q4DMX4AZDVNULBLRL6GF4QW6QCASUEAAC KT5UYXGKEEXUHURNOYFVIG7WQ3Y3SJZMM2TP4OSW6NXSXQ5XXRHAC ELG3UDT6OJFEYSJR7HZEC65IUWBMGPPPCXEW3CDW5T74R6KC5LIAC S2NVIFXRFER4SRA37WCT5XTXHDHAL5WIGGKY4A4XOTPLTKTZSRGQC D7A7MSIHJS3IAOLEPK52M4CZLDPLO7JB3Y62XACT2AM6UUCPQ6BAC ZVI4AWERNOTDJ3765HJXRBZT57XPNKVONQ6TGOGNPOL2VN42KMJQC AHWWRC73FXLSUDAJBU5UU76MZETHD3DSGJ7OLZPFEHXBDJ733QNAC L6KSEFQIWICZJ6HJUFKLZQDEH6X2QMFM4Z7ZZUGMLDMFF7EHRXWAC 23SFYK4Q5NKBPJG53PQNPWQH6UOUU2YKJEL7RLXYBRLJOJYV7AWQC OPXFZKEBDHZZLXEJ2JRDYBOJH6YIN7UZNZYHVHMWMQVDTE2ZD53QC 3QVNMRNMI63L2VOFVTMPCVPXH3J4JXLXVTIIPNOMACQCPCAPWILQC MYGIBRRHHXPKVRAMQQRJTZH74L2XOK3SF7J57JPCRKSVRLZ2D6NQC PKJCFSBMXXA2H3US47IJEB7QMIYLEKTLGWQUYEZSKCDODDQTD6HQC XSZZB47UXR6KGYFZZQFQR63X2LDKOH6TPNNBRRGHUCI5JJ4JIWVAC 3BK22XE5LPOH2EK5AMRXFXHNQNCJ54HEPYRINHJT4DA7INT32I7AC ACDXXAX26ZJJFKJDGRC2GOSJY5JHQWCSTP55SYI6D6LH5UIRYUBAC I56UGW7UUKLSR4753EYRGNROZB5PD522REEOGHVAQOZZTSVRUEEQC X6AK4QPXKTGTWIMJ5CIR46CVIXVUXV5WKTP73CNQOIRANQN4MD5QC KMB6FND35LWT4XTRUNEJZ7SQXFZEUYIJAADGWJVB4RY4IIAT4KSQC YYKXNBFL44LLOBABLXBKOF7IFUIGIEL2SYIPLGDH6UOEY5EZZZSQC 5CYU7UT74NXJWCC36GNQGVBXH676BHBXWZQVIINRMPDEJ27SBRGAC ESMM3FELOBYIX7FUNOU37FYKRJHFU2IMX6LY6EGJTVPTBDU3SEEQC TSFQFCB2NXDOBLBRUSAT63VJIXLPPTJGSTIDNOTLGHVVWSHITRNQC 7SSBM4UQMYVRL6L3ICYZQPSMYLZZQNMDWH6JKA3KOOSXZDJHESHQC OC6DLIZ3BKN5ZCDK77653XBR4DSTCFRXUGWDSKVGGJQNM7QZHJBAC ZD56BUSUGTPPDSHHTOC2H5RJJG4FUUUPOSM2BHRY3UA5D6OA43XQC I2AG42PAVOII4V4TWDJV5ZVNDIHKBRDT254BFQLFUIY723TW6CCQC SASAN2XCWDQ2VEHZ7TAQEN2R3Y7AG7JUGEFVRL4DZAGHXDFEZFRQC YKHE3XMWOWPGOWYSISF73MIAKN7WB3AHCV2OA4ECAFPF47YHUXEAC KWTBNTO3QUUE2YADF6SYW6G6ZOKYEWRJQKIWDGZXR33S3YNDVIZQC 5MUEECMJHU44FL5RDUR3VFBIWK3H4X2L5MVJ73J37PYHZWLUKU2AC PTWZYQFRWWUOE2WMQT26CKZKFSHAIJVJS3QWHJFYUFDRRTVPHSUAC UR4J677RWA3OFG6HQTD46BUUE5YFPSBEFCJAEM5OMT4V5A7SBNNQC K63JN6CRRCP4S5NY2FPH46Q7QLWH4B6QXQHKFPVQBHHIHNDVXFDQC FLQWY7L4SH25TQWYM5G7J7ITFRBW6DQQ3M44DDZHVQ6PKUX257BQC VCNKFNUF7OWVSWC6I5D25KUZ3XZZICZ3LHWVPF2N5ZSP7LQ2JOUQC 6YZAVBWU6E5FYOI5JGEIPXGZLIKAW6LS2AOFIQWEE5DMOPPCD5PQC WW36JYLR4AILV7RHQEDJWMX74P74B7G7DRBHH3O2V5TCHRTZJWZQC let is_selected = matches!(cursor.selection.as_ref() ,Some(cursor::Selection::UntrackedFile{ ix: selected_ix, .. }) if &ix == selected_ix
let is_selected = matches!(selection.as_ref() ,Some(Selection::UntrackedFile{ ix: selected_ix, .. }) if &ix == selected_ix
let is_selected = matches!(cursor.selection.as_ref(),Some(cursor::Selection::ChangedFile{ ix: selected_ix, .. }) if &ix == selected_ix
let is_selected = matches!(selection.as_ref(),Some(Selection::ChangedFile{ ix: selected_ix, .. }) if &ix == selected_ix
let is_selected = matches!(cursor.selection.as_ref(),Some(cursor::Selection::LogChange { ix: selected_ix, .. }) if &ix == selected_ix
let is_selected = matches!(selection.as_ref(),Some(Selection::Log { ix: selected_ix, .. }) if &ix == selected_ix
cursor::Selection::UntrackedFile { .. }| cursor::Selection::ChangedFile { .. }| cursor::Selection::LogChange { file: None, .. } => 1,cursor::Selection::LogChange { file: Some(_), .. } => 2,
Selection::UntrackedFile { .. }| Selection::ChangedFile { .. }| Selection::Log { file: None, .. } => 1,Selection::Log { file: Some(_), .. } => 2,
el(row(cols).spacing(SPACING))}
el(row(cols).spacing(SPACING).width(Length::Fill).height(Length::Fill))};let actions_inner = view_actions(action_state(repo, record_msg, selection));let actions = el(container(actions_inner).class(theme::Container::ActionsBg).width(Length::Fill).height(Length::Shrink).padding(Padding::from([4, 6])));el(column([main, actions]))
}fn view_actions<'a>(state: ActionState) -> Element<'a, Msg, Theme> {let left = || {action_button("← | h",Msg::Cursor(cursor::Msg::PressDir(cursor::Dir::Left)),)};let down = || {action_button("↓ | j",Msg::Cursor(cursor::Msg::PressDir(cursor::Dir::Down)),)};let up = || {action_button("↑ | k",Msg::Cursor(cursor::Msg::PressDir(cursor::Dir::Up)),)};let right = || {action_button("→ | l",Msg::Cursor(cursor::Msg::PressDir(cursor::Dir::Right)),)};let down_no_skip = || {action_button("S-(↓ | j): no skip",Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Down)),)};let up_no_skip = || {action_button("S-(↑ | k): no skip",Msg::Cursor(cursor::Msg::AltPressDir(cursor::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 add_if = |predicate: bool,button: Element<'a, Msg, Theme>,row: row::Row<'a, Msg, Theme>| {if predicate {row.push(button)} else {row}};let buttons = match state {ActionState::Main {selection,can_select_right,can_record,} => {let row = row([down(), up()]);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)}}}ActionState::LogChange {can_select_right,can_record,} => {let row = row([left(), down(), up()]);let row = add_if(can_select_right, right(), row);add_if(can_record, start_record(), row)}ActionState::Diff { can_record } => {let row = row([left(), down(), up(), down_no_skip(), up_no_skip()]);add_if(can_record, start_record(), row)}ActionState::Recording => {row([save_record(), postpone_record(), discard_record()])}};el(buttons.spacing(2).wrap())
enum ActionState {/// Main statusMain {selection: MainSelection,can_select_right: bool,can_record: bool,},/// Selected a log change, but not diffLogChange {can_select_right: bool,can_record: bool,},/// Untracked, changed of log change's diffDiff { can_record: bool },/// Making a record from current changesRecording,}enum MainSelection {Untracked,AddedFromUntracked,Other,}/// Determine state for actions menufn action_state<'a>(repo: &'a Repo,record_msg: Option<&'a RecordMsg>,selection: Option<Selection<'a>>,) -> ActionState {match record_msg {Some(RecordMsg::Typing(_)) => return ActionState::Recording,Some(RecordMsg::Canceled { .. }) | None => {}}
let can_record = !repo.state.changed_files.is_empty();match selection {Some(Selection::UntrackedFile {ix: _,path: _,diff,}) => {if let Some(diff) = diff {if diff.is_selected {ActionState::Diff { can_record }} else {ActionState::Main {selection: MainSelection::Untracked,can_select_right: matches!(diff.nav.ready,Some(iced_nav_scrollable::NeedsScrolling::Yes)),can_record,}}} else {ActionState::Main {selection: MainSelection::Untracked,can_select_right: false,can_record,}}}Some(Selection::ChangedFile {ix: _,path: _,diff,is_added_from_untracked,}) => {let main_selection = || {if is_added_from_untracked {MainSelection::AddedFromUntracked} else {MainSelection::Other}};if let Some(diff) = diff {if diff.is_selected {ActionState::Diff { can_record }} else {ActionState::Main {selection: main_selection(),can_select_right: matches!(diff.nav.ready,Some(iced_nav_scrollable::NeedsScrolling::Yes)),can_record,}}} else {ActionState::Main {selection: main_selection(),can_select_right: false,can_record,}}}Some(Selection::Log {ix: _,hash: _,message: _,file,nav,}) => match file {Some(LogChangeFileSelection {ix: _,path: _,diff,}) => {if let Some(diff) = diff {if diff.is_selected {ActionState::Diff { can_record }} else {ActionState::LogChange {can_select_right: matches!(diff.nav.ready,Some(iced_nav_scrollable::NeedsScrolling::Yes)),can_record,}}} else {ActionState::LogChange {can_select_right: false,can_record,}}}None => ActionState::Main {selection: MainSelection::Other,can_select_right: nav.and_then(|nav| nav.ready).is_some(),can_record,},},None => ActionState::Main {selection: MainSelection::Other,can_select_right: false,can_record,},}}fn action_button<'a>(label: &'a str, on_press: Msg) -> Element<'a, Msg, Theme> {el(button(text(label).shaping(text::Shaping::Advanced)).on_press(on_press))}
let cursor = cursor::State {selection: Some(cursor::Selection::UntrackedFile {ix: 0,path: "".to_string(),diff_selected: false,}),held_key: None,};
let selection = Some(Selection::UntrackedFile {ix: 0,path: "",diff: None,});
"r" => Some(Msg::StartRecord),"x" => Some(Msg::RmAddedFile),
"r" => Some(Msg::View(app::Msg::StartRecord)),"x" => Some(Msg::View(app::Msg::RmAddedFile)),