add tests to_record selection and improve it

[?]
Oct 31, 2025, 6:46 PM
5O4FWCFP4ZPAS7WKSYPHN76ML3O2S4JUOYWOV2ETD4TF2H6KZ6AQC

Dependencies

  • [2] KM5PSZ4A watch repo once loaded
  • [3] 23SFYK4Q big view refactor into a new crate
  • [4] PKJCFSBM theme improvements
  • [5] XIASAP3G clippy
  • [6] SASAN2XC use nav-scrollable
  • [7] KWTBNTO3 diffs selection and scrolling
  • [8] UR4J677R nav for log changes and refactors
  • [9] FJSVMFB4 add `iced_expl_widgets` with forked scrollable
  • [10] 3XRG4BB6 rewritten nav-scrollable!
  • [11] WAOGSCOJ very nice refactor, wip adding channels logs
  • [12] EJPSD5XO shared allowed actions conditions between update and view
  • [13] YK3MOJJL chonky refactor, wip other channels logs & diffs
  • [14] 7WCB5YQJ refactor msgs and modules
  • [15] AZ5D2LQU allow to set record description
  • [16] CULHFNIV add error report view
  • [17] LFEMJYYD start of to_record selection
  • [18] KEPKF3WO unify diffs handling, simplify view
  • [19] C5P3JIFC refactor out the nav-scrollable children len arg
  • [20] PKLUHYE4 allow to copy change hash
  • [21] U3EAZKHR allow to copy error report
  • [22] XSZZB47U refactor stuff into lib
  • [23] OJPGHVC3 entire log!
  • [24] MYGIBRRH wip custom theme
  • [25] UBRT5BAU fix new nav-scrollable to jump to first non-skip section
  • [*] 6YZAVBWU Initial commit

Change contents

  • replacement in inflorescence_view/src/view.rs at line 270
    [13.462][11.6065:6138](),[11.6065][11.6065:6138]()
    diff::view(state, nav, file, *diff_selected)
    [13.462]
    [11.6138]
    diff::view(state, nav, file, *diff_selected, false)
  • replacement in inflorescence_view/src/view.rs at line 293
    [13.794][11.7123:7196](),[11.7123][11.7123:7196]()
    diff::view(state, nav, file, *diff_selected)
    [13.794]
    [11.7196]
    diff::view(state, nav, file, *diff_selected, true)
  • replacement in inflorescence_view/src/view.rs at line 518
    [13.3903][11.12678:12751](),[11.12678][11.12678:12751]()
    diff::view(state, nav, file, *diff_selected)
    [13.3903]
    [11.12751]
    diff::view(state, nav, file, *diff_selected, false)
  • replacement in inflorescence_view/src/view.rs at line 757
    [13.12339][13.12339:12412]()
    diff::view(state, nav, file, *diff_selected)
    [13.12339]
    [13.12412]
    diff::view(state, nav, file, *diff_selected, false)
  • replacement in inflorescence_view/src/view.rs at line 919
    [13.15815][11.16434:16507](),[11.16434][11.16434:16507]()
    diff::view(state, nav, file, *diff_selected)
    [13.15815]
    [11.16507]
    diff::view(state, nav, file, *diff_selected, false)
  • edit in inflorescence_view/src/theme.rs at line 49
    [16.5480]
    [4.874]
    const NAV_SECTION_BORDER_WIDTH: f32 = 2.0;
  • edit in inflorescence_view/src/theme.rs at line 102
    [16.5550]
    [5.20]
    NavNonSelectedSection,
    NavSelectedSection,
  • edit in inflorescence_view/src/theme.rs at line 255
    [16.6446]
    [4.2391]
    Container::NavNonSelectedSection => container::Style {
    border: Border {
    color: Color::TRANSPARENT,
    width: NAV_SECTION_BORDER_WIDTH,
    ..default()
    },
    ..default()
    },
    Container::NavSelectedSection => container::Style {
    border: Border {
    color: MAGENTA_LIGHT,
    width: NAV_SECTION_BORDER_WIDTH,
    ..default()
    },
    ..default()
    },
  • replacement in inflorescence_view/src/diff.rs at line 9
    [11.3375][11.3375:3413]()
    use iced_expl_widget::nav_scrollable;
    [11.3375]
    [3.432]
    use iced_expl_widget::{nav_scrollable, nav_selectable};
  • edit in inflorescence_view/src/diff.rs at line 21
    [7.5302]
    [10.1506]
    select_sections: bool,
  • replacement in inflorescence_view/src/diff.rs at line 27
    [3.3566][7.5334:5375](),[7.5375][8.131:197](),[8.197][7.5436:5446](),[7.5436][7.5436:5446]()
    File::Decoded(decoded_file) => {
    view_decoded(state, nav, decoded_file, diff_selected)
    }
    [3.3566]
    [3.3640]
    File::Decoded(decoded_file) => view_decoded(
    state,
    nav,
    decoded_file,
    diff_selected,
    select_sections,
    ),
  • edit in inflorescence_view/src/diff.rs at line 45
    [7.5542]
    [10.1615]
    select_sections: bool,
  • replacement in inflorescence_view/src/diff.rs at line 99
    [3.5499][10.1662:1860]()
    let sections =
    el(nav_scrollable(nav, sections_view).class(if diff_selected {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    }));
    [3.5499]
    [6.919]
    let nav = if diff_selected && select_sections {
    nav_selectable(
    nav,
    sections_view,
    || theme::Container::NavNonSelectedSection,
    || theme::Container::NavSelectedSection,
    )
    } else {
    nav_scrollable(nav, sections_view)
    }
    .class(if diff_selected {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    });
    let sections = el(nav);
  • edit in inflorescence_model/src/to_record.rs at line 2
    [17.2556]
    [17.2556]
    #[cfg(test)]
    mod test;
  • replacement in inflorescence_model/src/to_record.rs at line 23
    [17.2857][17.2857:2887]()
    #[derive(Clone, Copy, Debug)]
    [17.2857]
    [17.2887]
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  • replacement in inflorescence_model/src/to_record.rs at line 29
    [17.2932][17.2932:2971]()
    #[derive(Clone, Copy, Debug, Default)]
    [17.2932]
    [17.2971]
    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
  • replacement in inflorescence_model/src/to_record.rs at line 84
    [17.4624][17.4624:4755]()
    if matches!(state.overall, PickSet::Include | PickSet::Exclude) {
    // Clear out the last partial states
    [17.4624]
    [17.4755]
    // Set a pick for files that don't have it
    {
    let unset_file_pick = match state.overall {
    PickSet::Include | PickSet::Exclude => state.overall,
    PickSet::Partial => PickSet::Exclude,
    };
  • replacement in inflorescence_model/src/to_record.rs at line 91
    [17.4814][17.4814:4891]()
    state.files.insert(changed_file.clone(), state.overall);
    [17.4814]
    [17.4891]
    if !state.files.contains_key(changed_file) {
    state
    .files
    .insert(changed_file.clone(), unset_file_pick);
    }
  • edit in inflorescence_model/src/to_record.rs at line 97
    [17.4909][17.4909:4948]()
    state.changes.clear();
  • replacement in inflorescence_model/src/to_record.rs at line 105
    [17.5208][17.5208:5339]()
    if matches!(state.overall, PickSet::Include | PickSet::Exclude) {
    // Clear out the last partial states
    [17.5208]
    [17.5339]
    dbg!(&state);
    // Set a pick for files that don't have it
    {
    let unset_file_pick = match state.overall {
    PickSet::Include | PickSet::Exclude => state.overall,
    PickSet::Partial => PickSet::Exclude,
    };
  • replacement in inflorescence_model/src/to_record.rs at line 113
    [17.5398][17.5398:5475]()
    state.files.insert(changed_file.clone(), state.overall);
    [17.5398]
    [17.5475]
    if !state.files.contains_key(changed_file) {
    state
    .files
    .insert(changed_file.clone(), unset_file_pick);
    }
    }
    }
    // Set a pick for this file's changes that don't have it
    {
    let unset_pick = match state
    .files
    .get(&file)
    .copied()
    .unwrap_or(state.overall)
    {
    PickSet::Include => Pick::Include,
    PickSet::Exclude | PickSet::Partial => Pick::Exclude,
    };
    let PartialFile { changes } =
    state.changes.entry(file.clone()).or_default();
    for change in changed_files.get(&file).unwrap() {
    if !changes.contains_key(change) {
    changes.insert(change.clone(), unset_pick);
    }
  • edit in inflorescence_model/src/to_record.rs at line 138
    [17.5493][17.5493:5532]()
    state.changes.clear();
  • edit in inflorescence_model/src/to_record.rs at line 144
    [17.5701]
    [17.5701]
    .or_else(|| {
    state.files.get(&file).and_then(|pick| {
    if matches!(pick, PickSet::Partial) {
    Some(Pick::Include)
    } else {
    None
    }
    })
    })
  • replacement in inflorescence_model/src/to_record.rs at line 161
    [17.6041][17.6041:6191]()
    .unwrap_or(match pick {
    Pick::Include => PickSet::Include,
    Pick::Exclude => PickSet::Exclude,
    [17.6041]
    [17.6191]
    .unwrap_or_else(|| {
    if changed_files.get(&file).unwrap().len() > 1 {
    PickSet::Partial
    } else {
    match pick {
    Pick::Include => PickSet::Include,
    Pick::Exclude => PickSet::Exclude,
    }
    }
  • edit in inflorescence_model/src/to_record.rs at line 174
    [17.6335]
    [17.6335]
    dbg!(&state);
  • edit in inflorescence_model/src/to_record.rs at line 177
    [17.6351][17.6351:6369]()
    dbg!(&state);
  • edit in inflorescence_model/src/to_record.rs at line 211
    [17.7172]
    [17.7172]
    }
    pub fn next_file_change_pick(
    file: &str,
    diff: &repo::ChangedFileDiff,
    state: &State,
    ) -> Pick {
    let current = state
    .changes
    .get(file)
    .and_then(|PartialFile { changes }| changes.get(diff))
    .copied()
    .unwrap_or_else(|| default_pick(state));
    next_pick(current)
  • replacement in inflorescence_model/src/to_record.rs at line 255
    [17.7933][17.7933:7950]()
    changes,
    [17.7933]
    [17.7950]
    changes: _,
  • edit in inflorescence_model/src/to_record.rs at line 262
    [17.8125][17.8125:8287]()
    || changes.values().any(|file| {
    file.changes
    .values()
    .any(|pick| matches!(pick, Pick::Exclude))
    })
  • replacement in inflorescence_model/src/to_record.rs at line 369
    [17.11810][17.11810:11860]()
    pick = Some(default_pick_set(state));
    [17.11810]
    [17.11860]
    // dbg!(default_pick_set(state));
    // pick = Some(default_pick_set(state));
    return Some(PickSet::Partial);
  • edit in inflorescence_model/src/to_record.rs at line 375
    [17.11965]
    [17.11965]
    dbg!((*pick, change_pick));
  • replacement in inflorescence_model/src/to_record.rs at line 390
    [17.12648][17.12648:12703]()
    Pick::Exclude => PickSet::Include,
    [17.12648]
    [17.12703]
    Pick::Exclude => PickSet::Exclude,
  • edit in inflorescence_model/src/to_record.rs at line 395
    [17.12753]
    [17.12753]
    dbg!(&pick);
  • file addition: to_record (d--r------)
    [11.29627]
  • file addition: test.rs (----------)
    [0.5185]
    use super::*;
    #[test]
    fn toggle_overall() {
    let mut state = State::default();
    assert_eq!(state.overall, PickSet::Include);
    let changed_files = repo::ChangedFiles::default();
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Exclude);
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Include);
    }
    // TODO add test in which files (and/or changes) are added and rm'd
    #[test]
    fn toggle_file() {
    let mut state = State::default();
    assert_eq!(state.overall, PickSet::Include);
    let file_a = "A";
    let file_b = "B";
    let file_c = "C";
    let changed_files = repo::ChangedFiles::from_iter([
    (file_a.to_owned(), repo::ChangedFile::default()),
    (file_b.to_owned(), repo::ChangedFile::default()),
    (file_c.to_owned(), repo::ChangedFile::default()),
    ]);
    let toggle_file = |state: &mut State, file: &str| {
    update(
    state,
    Msg::ToggleFile {
    file: file.to_owned(),
    },
    &changed_files,
    )
    };
    let file = |state: &State, file: &str| *state.files.get(file).unwrap();
    // Exclude A
    toggle_file(&mut state, file_a);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude all
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Exclude);
    // Include all
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Include);
    // Include A
    toggle_file(&mut state, file_a);
    assert_eq!(file(&state, file_a), PickSet::Include);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Include);
    // Exclude A
    toggle_file(&mut state, file_a);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude B
    toggle_file(&mut state, file_b);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude C
    toggle_file(&mut state, file_c);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Exclude);
    assert_eq!(state.overall, PickSet::Exclude);
    // Include A
    toggle_file(&mut state, file_a);
    assert_eq!(file(&state, file_a), PickSet::Include);
    assert_eq!(file(&state, file_b), PickSet::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Exclude);
    assert_eq!(state.overall, PickSet::Partial);
    // Include B
    toggle_file(&mut state, file_b);
    assert_eq!(file(&state, file_a), PickSet::Include);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(file(&state, file_c), PickSet::Exclude);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude all
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Exclude);
    // Include all
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Include);
    // Include C
    toggle_file(&mut state, file_c);
    assert_eq!(file(&state, file_a), PickSet::Include);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Include);
    // Exclude A
    toggle_file(&mut state, file_a);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude all
    update(&mut state, Msg::ToggleOverall, &changed_files);
    assert_eq!(state.overall, PickSet::Exclude);
    // Exclude B
    toggle_file(&mut state, file_b);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Partial);
    }
    #[test]
    fn toggle_change() {
    let mut state = State::default();
    assert_eq!(state.overall, PickSet::Include);
    let file_a = "A";
    let file_b = "B";
    let file_c = "C";
    let change_a_1 = repo::ChangedFileDiff::Move;
    let change_b_1 = repo::ChangedFileDiff::Del;
    let change_b_2 = repo::ChangedFileDiff::Undel;
    let change_c_1 = repo::ChangedFileDiff::Add;
    let change_c_2 = repo::ChangedFileDiff::DelRoot;
    let change_c_3 = repo::ChangedFileDiff::AddRoot;
    let changed_files = repo::ChangedFiles::from_iter([
    (
    file_a.to_owned(),
    repo::ChangedFile::from_iter([change_a_1.clone()]),
    ),
    (
    file_b.to_owned(),
    repo::ChangedFile::from_iter([
    change_b_1.clone(),
    change_b_2.clone(),
    ]),
    ),
    (
    file_c.to_owned(),
    repo::ChangedFile::from_iter([
    change_c_1.clone(),
    change_c_2.clone(),
    change_c_3.clone(),
    ]),
    ),
    ]);
    let toggle_change =
    |state: &mut State, file: &str, change: &repo::ChangedFileDiff| {
    update(
    state,
    Msg::ToggleChange {
    file: file.to_owned(),
    change: change.clone(),
    },
    &changed_files,
    )
    };
    let file = |state: &State, file: &str| *state.files.get(file).unwrap();
    let change = |state: &State, file: &str, change: &repo::ChangedFileDiff| {
    *state
    .changes
    .get(file)
    .unwrap()
    .changes
    .get(change)
    .unwrap()
    };
    // Exclude A.1
    toggle_change(&mut state, file_a, &change_a_1);
    assert_eq!(change(&state, file_a, &change_a_1), Pick::Exclude);
    assert_eq!(file(&state, file_a), PickSet::Exclude);
    assert_eq!(state.overall, PickSet::Partial);
    // Include A.1
    toggle_change(&mut state, file_a, &change_a_1);
    assert_eq!(change(&state, file_a, &change_a_1), Pick::Include);
    assert_eq!(file(&state, file_a), PickSet::Include);
    assert_eq!(state.overall, PickSet::Include);
    // Exclude B.1
    toggle_change(&mut state, file_b, &change_b_1);
    assert_eq!(change(&state, file_b, &change_b_1), Pick::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude B.2
    toggle_change(&mut state, file_b, &change_b_2);
    assert_eq!(change(&state, file_b, &change_b_2), Pick::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Exclude);
    assert_eq!(state.overall, PickSet::Partial);
    // Include B.1
    toggle_change(&mut state, file_b, &change_b_1);
    assert_eq!(change(&state, file_b, &change_b_1), Pick::Include);
    assert_eq!(file(&state, file_b), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Include B.2
    toggle_change(&mut state, file_b, &change_b_2);
    assert_eq!(change(&state, file_b, &change_b_2), Pick::Include);
    assert_eq!(file(&state, file_b), PickSet::Include);
    assert_eq!(state.overall, PickSet::Include);
    // Exclude C.1
    toggle_change(&mut state, file_c, &change_c_1);
    assert_eq!(change(&state, file_c, &change_c_1), Pick::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude C.2
    toggle_change(&mut state, file_c, &change_c_2);
    assert_eq!(change(&state, file_c, &change_c_2), Pick::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude C.3
    toggle_change(&mut state, file_c, &change_c_3);
    assert_eq!(change(&state, file_c, &change_c_3), Pick::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Exclude);
    assert_eq!(state.overall, PickSet::Partial);
    // Include C.1
    toggle_change(&mut state, file_c, &change_c_1);
    assert_eq!(change(&state, file_c, &change_c_1), Pick::Include);
    assert_eq!(file(&state, file_c), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Include C.2
    toggle_change(&mut state, file_c, &change_c_2);
    assert_eq!(change(&state, file_c, &change_c_2), Pick::Include);
    assert_eq!(file(&state, file_c), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Include C.3
    toggle_change(&mut state, file_c, &change_c_3);
    assert_eq!(change(&state, file_c, &change_c_3), Pick::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Include);
    // Exclude C.1
    toggle_change(&mut state, file_c, &change_c_1);
    assert_eq!(change(&state, file_c, &change_c_1), Pick::Exclude);
    assert_eq!(file(&state, file_c), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Exclude B.1
    toggle_change(&mut state, file_b, &change_b_1);
    assert_eq!(change(&state, file_b, &change_b_1), Pick::Exclude);
    assert_eq!(file(&state, file_b), PickSet::Partial);
    assert_eq!(state.overall, PickSet::Partial);
    // Include C.1
    toggle_change(&mut state, file_c, &change_c_1);
    assert_eq!(change(&state, file_c, &change_c_1), Pick::Include);
    assert_eq!(file(&state, file_c), PickSet::Include);
    assert_eq!(state.overall, PickSet::Partial);
    }
  • replacement in inflorescence_model/src/action.rs at line 37
    [17.12994][17.12994:13126]()
    /// Same purpose as `to_record::ToggleFile`, but without file name for
    /// action filtering
    ToRecordToggleSelectedFile,
    [17.12994]
    [12.4320]
    /// Same purpose as `to_record::ToggleFile` or `to_record::ToggleChange`,
    /// but without file name for action filtering
    ToRecordToggleSelectedFileOrChange,
  • edit in inflorescence_model/src/action.rs at line 81
    [17.13187][17.13187:13261]()
    (ToRecordToggleSelectedFile, ToRecordToggleSelectedFile) => true,
  • replacement in inflorescence_model/src/action.rs at line 82
    [17.13271][17.13271:13373]()
    ToRecord(to_record::Msg::ToggleFile { file: _ }),
    ToRecordToggleSelectedFile,
    [17.13271]
    [17.13373]
    ToRecordToggleSelectedFileOrChange,
    ToRecordToggleSelectedFileOrChange,
  • replacement in inflorescence_model/src/action.rs at line 86
    [17.13402][17.13402:13504]()
    ToRecordToggleSelectedFile,
    ToRecord(to_record::Msg::ToggleFile { file: _ }),
    [17.13402]
    [17.13504]
    ToRecord(to_record::Msg::ToggleFile { file: _ })
    | ToRecord(to_record::Msg::ToggleChange { file: _, change: _ }),
    ToRecordToggleSelectedFileOrChange,
    ) => true,
    (
    ToRecordToggleSelectedFileOrChange,
    ToRecord(to_record::Msg::ToggleFile { file: _ })
    | ToRecord(to_record::Msg::ToggleChange { file: _, change: _ }),
  • replacement in inflorescence_model/src/action.rs at line 114
    [17.13559][17.13559:13609]()
    (ToRecordToggleSelectedFile, _) => false,
    [17.13559]
    [12.5587]
    (ToRecordToggleSelectedFileOrChange, _) => false,
  • replacement in inflorescence_model/src/action.rs at line 316
    [17.14435][17.14435:14499]()
    msg: Some(FilteredMsg::ToRecordToggleSelectedFile),
    [17.14435]
    [17.14499]
    msg: Some(FilteredMsg::ToRecordToggleSelectedFileOrChange),
    }
    };
    let to_record_toggle_file_change = |next: to_record::Pick| {
    let label = match next {
    to_record::Pick::Include => "include selected change",
    to_record::Pick::Exclude => "exclude selected change",
    };
    Binding {
    key: "t",
    label,
    msg: Some(FilteredMsg::ToRecordToggleSelectedFileOrChange),
  • edit in inflorescence_model/src/action.rs at line 389
    [17.14835]
    [17.14835]
    next_to_record_file_change_pick,
  • replacement in inflorescence_model/src/action.rs at line 402
    [15.3593][17.14851:14930]()
    push_if_some(next_to_record_file_pick, to_record_toggle_file, ma);
    [15.3593]
    [12.10821]
    // TODO maybe in here S+t should control file pick and lowercase
    // used for selected change
    let _ = next_to_record_file_pick;
    // push_if_some(next_to_record_file_pick, to_record_toggle_file,
    // ma);
    push_if_some(
    next_to_record_file_change_pick,
    to_record_toggle_file_change,
    ma,
    );
  • edit in inflorescence_model/src/action.rs at line 575
    [17.15327]
    [12.13835]
    next_to_record_file_change_pick: Option<to_record::Pick>,
  • edit in inflorescence_model/src/action.rs at line 694
    [17.15697]
    [17.15697]
    next_to_record_file_change_pick: None,
  • edit in inflorescence_model/src/action.rs at line 736
    [13.22543]
    [17.16080]
    let diff_ix = navigation
    .files_diffs
    .diffs_nav
    .get_selected_section_ix();
    let selected_diff = diff_ix.and_then(|diff_ix| {
    changed_files
    .get(path)
    .and_then(|diffs| diffs.iter().nth(diff_ix))
    });
    let next_to_record_file_change_pick = selected_diff
    .map(|selected_diff| {
    to_record::next_file_change_pick(
    path,
    selected_diff,
    to_record,
    )
    });
  • edit in inflorescence_model/src/action.rs at line 756
    [17.16224]
    [17.16224]
    next_to_record_file_change_pick,
  • edit in inflorescence_model/src/action.rs at line 787
    [17.16576]
    [17.16576]
    next_to_record_file_change_pick: None,
  • replacement in inflorescence/src/main.rs at line 515
    [17.17536][17.17536:17597]()
    action::FilteredMsg::ToRecordToggleSelectedFile => {
    [17.17536]
    [17.17597]
    action::FilteredMsg::ToRecordToggleSelectedFileOrChange => {
  • edit in inflorescence/src/main.rs at line 520
    [17.17710]
    [17.17710]
    navigation,
  • replacement in inflorescence/src/main.rs at line 526
    [17.17898][17.17898:17936]()
    diff_selected: _,
    [17.17898]
    [17.17936]
    diff_selected,
  • replacement in inflorescence/src/main.rs at line 529
    [17.17997][17.17997:18146]()
    let msg = to_record::Msg::ToggleFile { file: path.clone() };
    to_record::update(to_record, msg, &repo.changed_files);
    [17.17997]
    [17.18146]
    if *diff_selected {
    let diff_ix = navigation
    .files_diffs
    .diffs_nav
    .get_selected_section_ix()
    .unwrap();
    let selected_diff = repo
    .changed_files
    .get(path)
    .and_then(|diffs| diffs.iter().nth(diff_ix))
    .cloned();
    if let Some(change) = selected_diff {
    let msg = to_record::Msg::ToggleChange {
    file: path.clone(),
    change,
    };
    to_record::update(to_record, msg, &repo.changed_files);
    }
    } else {
    let msg = to_record::Msg::ToggleFile { file: path.clone() };
    to_record::update(to_record, msg, &repo.changed_files);
    }
  • edit in inflorescence/src/main.rs at line 1102
    [2.1650]
    [11.92481]
    // TODO update to_record state
  • replacement in inflorescence/src/main.rs at line 1468
    [14.13939][17.18266:18397]()
    "t" => {
    action(action::FilteredMsg::ToRecordToggleSelectedFile)
    }
    [14.13939]
    [14.13939]
    "t" => action(
    action::FilteredMsg::ToRecordToggleSelectedFileOrChange,
    ),
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 132
    [10.31979]
    [10.31979]
    /// Only used when `NavScrollable::select_sections` is set. It cannot
    /// contain any index from `skip_sections`
    selected_section: Option<usize>,
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 175
    [10.33262][10.33262:33298]()
    if let Some((y, delay)) = state
    [10.33262]
    [10.33298]
    if let Some((ix, y, delay)) = state
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 183
    [10.33551]
    [10.33551]
    // Frame of the nav's visible region is reduced by the
    // `context_height` on top and bottom
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 190
    [10.33786][10.33786:33940]()
    // The top edge of the section is visible, but the bottom
    // edge of is below the bottom edge of nav, scroll down
    [10.33786]
    [10.33940]
    // The top edge of the section is above the bottom frame,
    // but the bottom edge of is below the
    // bottom frame, scroll down to see the rest of it
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 198
    [10.34165][10.34165:34338]()
    Some((state.offset_y + offset_delta, Delay::Start))
    } else if *offset > bottom_frame {
    // Scroll to the next section
    [10.34165]
    [10.34338]
    Some((ix, state.offset_y + offset_delta, Delay::Start))
    } else if *offset > bottom_frame
    || state
    .selected_section
    .map(|section| section < ix)
    .unwrap_or_default()
    {
    // Section is below the bottom frame, or the previous
    // section is selected, scroll down to see this one
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 208
    [10.34365]
    [10.34365]
    ix,
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 247
    [10.35629]
    [10.35629]
    // Set the new selection
    if state.selected_section.is_some() {
    state.selected_section = Some(ix);
    }
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 260
    [10.35891][10.35891:35927]()
    if let Some((y, delay)) = state
    [10.35891]
    [10.35927]
    if let Some((ix, y, delay)) = state
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 269
    [10.36195]
    [10.36195]
    // Frame of the nav's visible region is reduced by the
    // `context_height` on top and bottom
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 273
    [10.36332][10.36332:36481]()
    // The bottom edge of the section is visible, but the top
    // edge of is above the top edge of nav, scroll up
    [10.36332]
    [10.36481]
    // The bottom edge of the section is below the top frame,
    // but the top edge of is above the top
    // farme, scroll up to see the rest of it
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 282
    [10.36733]
    [10.36733]
    ix,
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 286
    [10.36864][10.36864:36920]()
    } else if offset + height < top_frame {
    [10.36864]
    [10.36920]
    } else if offset + height < top_frame
    || state
    .selected_section
    .map(|section| section > ix)
    .unwrap_or_default()
    {
    // Section is above the top frame, or the following section
    // is selected, scroll up to see this one
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 295
    [10.36947]
    [10.36947]
    ix,
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 347
    [10.38856]
    [10.38856]
    // Set the new selection
    if state.selected_section.is_some() {
    state.selected_section = Some(ix);
    }
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 372
    [10.39371]
    [10.39371]
    // TODO update selected_section, if some
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 386
    [10.39810]
    [10.39810]
    // TODO update selected_section, if some
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 476
    [10.42641][10.42641:42793]()
    let iterator = children.into_iter();
    let mut children = Vec::with_capacity(iterator.size_hint().0);
    children.extend(iterator);
    [10.42641]
    [10.42793]
    let children: Vec<_> = children.into_iter().collect();
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 628
    [10.47553]
    [10.47553]
    }
    }
    impl<'a, Message, Theme, Renderer> NavScrollable<'a, Message, Theme, Renderer>
    where
    Message: 'a,
    Theme: 'a + Catalog + container::Catalog,
    Renderer: 'a + iced::advanced::Renderer,
    {
    /// Creates a new [`NavScrollable`] with section selection.
    pub fn with_selection(
    state: &'a State,
    children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
    non_selected_section: impl Fn() -> <Theme as container::Catalog>::Class<'a>,
    selected_section: impl Fn() -> <Theme as container::Catalog>::Class<'a>,
    ) -> Self {
    let selected_section_ix = state.select_fst_section();
    // Add border for selected section
    let children: Vec<_> = children
    .into_iter()
    .enumerate()
    .map(|(ix, child)| {
    Element::from(if ix == selected_section_ix {
    container(child).class(selected_section())
    } else {
    container(child).class(non_selected_section())
    })
    })
    .collect();
    let content = iced::widget::column(children).into();
    NavScrollable {
    state,
    width: Length::Shrink,
    height: Length::Shrink,
    direction: Direction::default(),
    content,
    on_scroll: None,
    class: <Theme as Catalog>::default(),
    last_status: None,
    }
    .validate()
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 695
    [10.48122]
    [10.48122]
    selected_section: None,
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 702
    [13.67796][13.67796:67869]()
    pub fn set_skip_sections(&mut self, skip_sections: HashSet<usize>) {
    [13.67796]
    [13.67869]
    pub fn set_skip_sections(&self, skip_sections: HashSet<usize>) {
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 708
    [10.48205][10.48205:48282]()
    pub fn with_skip_sections(self, skip_sections: HashSet<usize>) -> Self {
    [10.48205]
    [10.48282]
    /// Select first non-skip section if nothing is yet selected.
    /// Returns the selected index.
    pub fn select_fst_section(&self) -> usize {
  • replacement in iced_expl_widget/src/nav_scrollable.rs at line 712
    [10.48317][10.48317:48511]()
    let inner = RefCell::into_inner(inner);
    let inner = StateInner {
    skip_sections,
    ..inner
    };
    Self {
    inner: RefCell::new(inner),
    [10.48317]
    [10.48511]
    let mut inner = inner.borrow_mut();
    if let Some(ix) = inner.selected_section {
    ix
    } else {
    debug_assert!(
    inner.skip_sections.len() < inner.section_heights.len(),
    "There has to be at least one non-skip section"
    );
    let mut selected_section: usize = 0;
    while inner.skip_sections.contains(&selected_section) {
    selected_section += 1;
    }
    inner.selected_section = Some(selected_section);
    selected_section
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 728
    [10.48521]
    [10.48521]
    }
    /// Get the index of selected section within the selectable sections only
    /// (the index range excludes `skip_sections`)
    pub fn get_selected_section_ix(&self) -> Option<usize> {
    let Self { inner } = self;
    let inner = inner.borrow();
    inner.selected_section.map(|ix| {
    ix - inner
    .skip_sections
    .iter()
    .filter(|section| **section < ix)
    .count()
    })
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 1883
    [10.87918]
    [10.87918]
    // TODO how do I add borders for sections?
  • edit in iced_expl_widget/src/lib.rs at line 10
    [9.73986]
    [9.73986]
    use iced::widget::container;
  • edit in iced_expl_widget/src/lib.rs at line 86
    [10.116581]
    [9.75048]
    }
    pub fn nav_selectable<'a, Message, Theme, Renderer>(
    state: &'a nav_scrollable::State,
    children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
    non_selected_section: impl Fn() -> <Theme as container::Catalog>::Class<'a>,
    selected_section: impl Fn() -> <Theme as container::Catalog>::Class<'a>,
    ) -> NavScrollable<'a, Message, Theme, Renderer>
    where
    Message: 'a,
    Theme: 'a + nav_scrollable::Catalog + container::Catalog,
    Renderer: 'a + iced_core::Renderer,
    {
    NavScrollable::with_selection(
    state,
    children,
    non_selected_section,
    selected_section,
    )