chonky refactor, wip other channels logs & diffs

[?]
Aug 13, 2025, 3:35 PM
YK3MOJJLRYEKZ4FUCNJ3YKMTKOINWIYOJKR3ER7IRSGTC7O6FJZQC

Dependencies

  • [2] 6YZAVBWU Initial commit
  • [3] ELG3UDT6 allow to rm added files
  • [4] W7IUT3ZV start recording impl
  • [5] AMPZ2BXK show changed files diffs (only Edit atm)
  • [6] L6KSEFQI move cursor related stuff into its module
  • [7] BFN2VHZS refactor file stuff into sub-mod
  • [8] GWZGYNIB add view crate
  • [9] 23SFYK4Q big view refactor into a new crate
  • [10] OPXFZKEB view tests setup
  • [11] 3QVNMRNM test non-empty repo app view
  • [12] MYGIBRRH wip custom theme
  • [13] 3BK22XE5 add a test for hover btn and more refactors
  • [14] ACDXXAX2 refactor main's updates into smaller fns
  • [15] FVA36HBV restart repo manager task if it crashes
  • [16] I56UGW7U make record test, fix log update
  • [17] X6AK4QPX finish recording test
  • [18] KMB6FND3 test view update fn rather than direct fn calls
  • [19] YYKXNBFL test: add untracked file
  • [20] 5CYU7UT7 test: rm added file
  • [21] TSFQFCB2 test got repo change
  • [22] 7SSBM4UQ view: refactor repo view
  • [23] OC6DLIZ3 test record when nothing to record
  • [24] I2AG42PA new cols layout
  • [25] SASAN2XC use nav-scrollable
  • [26] GOLHUD6R nav-scrollable: set skip-able sections
  • [27] KWTBNTO3 diffs selection and scrolling
  • [28] 5MUEECMJ smooth scrolling nav
  • [29] 3TLPJ57B alt scroll via context and couple fixes
  • [30] BNHJU2DU clippy fixes
  • [31] AI3IMKC3 refactor stairs
  • [32] PTWZYQFR use nav-scrollable for repo status
  • [33] UR4J677R nav for log changes and refactors
  • [34] A6Z4O6RC actions menu
  • [35] JZXYSIYD channel selection!
  • [36] 5ZRDYL6K fork channel, fix recording esc key
  • [37] NZD56PVB fix mouse selection
  • [38] OJPGHVC3 entire log!
  • [39] 3XRG4BB6 rewritten nav-scrollable!
  • [40] WAOGSCOJ very nice refactor, wip adding channels logs
  • [41] WH57EHNM update tests
  • [42] EJPSD5XO shared allowed actions conditions between update and view
  • [43] KEPKF3WO unify diffs handling, simplify view
  • [44] IQDCHWCP load a pijul repo
  • [45] ZVI4AWER woot contents_diff
  • [46] A5YBC77V record!
  • [47] UF5NJKAS test load repo
  • [48] WT3GA27P add cursor with selection
  • [49] S2NVIFXR allow to enter record msg
  • [50] YKHE3XMW refactor diffs handling
  • [51] WGID4LS4 absolutely slayed testing with iced task
  • [52] V55EAIWQ add src file LRU cache
  • [53] VCNKFNUF app init test
  • [54] NWJD6VM6 mv libflowers libflorescence
  • [55] 7BLZN73O add a key to refresh repo
  • [56] SWWE2R6M display basic repo stuff
  • [57] S2T7RUKW add nav back placeholder
  • [58] RDRBP7AL auto-scroll status selection
  • [59] ZIUHKVJK update tests
  • [60] B4RMW5AE add syntax highlighter to untracked files contents
  • [61] YBJRDOTC make all repo actions async
  • [62] K63JN6CR refactor out non-view field from cursor
  • [63] MJDGPSHG WIP contents diff
  • [64] QMAUTRB6 refactor diff

Change contents

  • edit in justfile at line 23
    [2.297]
    [2.297]
    cargo check --release
  • replacement in inflorescence_view/src/app.rs at line 9
    [40.3495][42.27:236]()
    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,
    [40.3495]
    [40.3681]
    self as model, action, selection, Log, ReadyState, RecordMsg, SubState,
  • replacement in inflorescence_view/src/app.rs at line 198
    [40.5638][40.5638:5672]()
    let id_hash =
    [40.5638]
    [40.5672]
    let file_id =
  • replacement in inflorescence_view/src/app.rs at line 200
    [40.5746][40.5746:6065]()
    let diff = get_diff(id_hash);
    let state = navigation.files_diffs.diffs.get(&id_hash);
    let nav = get_files_diffs_nav(navigation, id_hash);
    let diffs = match diff.zip(state).zip(nav) {
    Some(((file, state), nav)) => {
    [40.5746]
    [40.6065]
    let diff = get_diff(file_id);
    let state = navigation.files_diffs.diffs.get(&file_id);
    let nav = &navigation.files_diffs.diffs_nav;
    let diffs = match diff.zip(state) {
    Some((file, state)) => {
  • replacement in inflorescence_view/src/app.rs at line 223
    [40.6698][40.6698:6732]()
    let id_hash =
    [40.6698]
    [40.6732]
    let file_id =
  • replacement in inflorescence_view/src/app.rs at line 225
    [40.6804][40.6804:7123]()
    let diff = get_diff(id_hash);
    let state = navigation.files_diffs.diffs.get(&id_hash);
    let nav = get_files_diffs_nav(navigation, id_hash);
    let diffs = match diff.zip(state).zip(nav) {
    Some(((file, state), nav)) => {
    [40.6804]
    [40.7123]
    let diff = get_diff(file_id);
    let state = navigation.files_diffs.diffs.get(&file_id);
    let nav = &navigation.files_diffs.diffs_nav;
    let diffs = match diff.zip(state) {
    Some((file, state)) => {
  • edit in inflorescence_view/src/app.rs at line 248
    [32.1734][9.18975:18976](),[22.3689][9.18975:18976](),[33.5022][9.18975:18976](),[40.7769][9.18975:18976](),[9.18975][9.18975:18976]()
  • replacement in inflorescence_view/src/app.rs at line 250
    [9.21516][40.7834:8404]()
    let nav = get_status_log_files_nav(navigation, *hash);
    let view = match nav {
    Some(nav) => {
    let change_selected = match file.as_ref() {
    Some(selection::LogChangeFileSelection {
    ix: _,
    path: _,
    diff_selected,
    }) => *diff_selected,
    _ => false,
    };
    [9.21516]
    [40.8404]
    let change_selected = match file.as_ref() {
    Some(selection::LogChangeFileSelection {
    ix: _,
    path: _,
    diff_selected,
    }) => !*diff_selected,
    _ => false,
    };
  • replacement in inflorescence_view/src/app.rs at line 259
    [40.8405][40.8405:8737](),[40.8737][42.1433:1590](),[42.1590][40.8873:9495](),[40.8873][40.8873:9495](),[40.9495][38.2839:2862](),[38.2839][38.2839:2862]()
    let files = entry.file_paths.iter().enumerate().map(|(ix, path)| {
    let is_selected = matches!(file, Some(selection::LogChangeFileSelection{ path: selected_path, .. }) if selected_path == path);
    el(button(text(path)).on_press_with(move || {
    Msg::Action(action::Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() })))
    }).class(selectable_button_class(is_selected)))
    });
    el(nav_scrollable(nav, files)
    .class(if change_selected {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill))
    }
    None => el(text("Loading...")),
    };
    [40.8405]
    [38.2862]
    let files = entry.file_paths.iter().enumerate().map(|(ix, path)| {
    let is_selected = matches!(file, Some(selection::LogChangeFileSelection{ path: selected_path, .. }) if selected_path == path);
    el(button(text(path)).on_press_with(move || {
    Msg::Action(action::Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() })))
    }).class(selectable_button_class(is_selected)))
    });
    let nav = &navigation.status_logs_navs.files_nav;
    let files = el(nav_scrollable(nav, files)
    .class(if change_selected {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill));
  • replacement in inflorescence_view/src/app.rs at line 279
    [40.9752][40.9752:9782]()
    view,
    [40.9752]
    [40.9782]
    files,
  • replacement in inflorescence_view/src/app.rs at line 301
    [24.1006][40.10021:10142](),[40.10142][38.3662:3751](),[38.3662][38.3662:3751](),[38.3751][40.10143:10219]()
    } else if let selection::Unified::EntireLog(Some(selection::LogChange {
    file,
    ..
    })) = selection
    {
    if file.is_none() {
    1
    } else {
    2
    }
    } else if let selection::Unified::Status(Some(selection)) = selection {
    [24.1006]
    [24.1076]
    } else {
  • replacement in inflorescence_view/src/app.rs at line 303
    [24.1102][40.10220:10418]()
    selection::Status::UntrackedFile { .. }
    | selection::Status::ChangedFile { .. }
    | selection::Status::LogChange(selection::LogChange {
    file: None,
    [24.1102]
    [40.10418]
    selection::Unified::EntireLog(Some(selection::LogChange {
    file,
  • replacement in inflorescence_view/src/app.rs at line 306
    [40.10437][40.10437:10593]()
    }) => 1,
    selection::Status::LogChange(selection::LogChange {
    file: Some(_),
    ..
    }) => 2,
    [40.10437]
    [24.1343]
    })) => {
    if file.is_none() {
    1
    } else {
    2
    }
    }
    selection::Unified::Status(Some(selection)) => match selection {
    selection::Status::UntrackedFile { .. }
    | selection::Status::ChangedFile { .. }
    | selection::Status::LogChange(selection::LogChange {
    file: None,
    ..
    }) => 1,
    selection::Status::LogChange(selection::LogChange {
    file: Some(_),
    ..
    }) => 2,
    },
    selection::Unified::Channel(Some(selection)) => match selection {
    selection::Channel { log: None, .. } => 1,
    selection::Channel {
    log: Some(selection::LogChange { file: None, .. }),
    ..
    } => 2,
    selection::Channel {
    log: Some(selection::LogChange { file: Some(_), .. }),
    ..
    } => 3,
    },
    selection::Unified::Status(None)
    | selection::Unified::Channel(None)
    | selection::Unified::EntireLog(None) => 0,
  • edit in inflorescence_view/src/app.rs at line 340
    [24.1353][24.1353:1376]()
    } else {
    0
  • replacement in inflorescence_view/src/app.rs at line 431
    [40.12134][40.12134:12362]()
    let id_hash = file::log_id_parts_hash(*hash, path);
    let state = navigation.log_diffs.diffs.get(&id_hash);
    let nav = get_status_log_diffs_nav(navigation, id_hash);
    Some(el(column([
    [40.12134]
    [40.12362]
    let file_id = file::log_id_parts_hash(*hash, path);
    let state = navigation.log_diffs.diffs.get(&file_id);
    el(column([
  • replacement in inflorescence_view/src/app.rs at line 439
    [40.12558][40.12558:12678]()
    match state.zip(nav) {
    Some((diff::FileAndState { file, state }, nav)) => {
    [40.12558]
    [40.12678]
    match state {
    Some(diff::FileAndState { file, state }) => {
    let nav = &navigation.status_logs_navs.diffs_nav;
  • replacement in inflorescence_view/src/app.rs at line 465
    [40.13462][40.13462:13494]()
    .spacing(SPACING)))
    [40.13462]
    [40.13494]
    .spacing(SPACING))
    }
    _ => el(column([])),
    };
    let other_channels_selected = || match selection {
    selection::Unified::Channel(channel) => match channel {
    Some(selection::Channel { log, .. }) => log.is_none(),
    None => true,
    },
    _ => false,
    };
    let other_channel_log_selected = || match selection {
    selection::Unified::Channel(Some(selection::Channel {
    ix: _,
    name: _,
    log: Some(selection::LogChange { file, .. }),
    })) => file.is_none(),
    _ => false,
    };
    let other_channel_log_change_selected = || match selection {
    selection::Unified::Channel(Some(selection::Channel {
    ix: _,
    name: _,
    log:
    Some(selection::LogChange {
    file:
    Some(selection::LogChangeFileSelection {
    diff_selected,
    ..
    }),
    ..
    }),
    })) => !*diff_selected,
    _ => false,
    };
    let view_channels = || {
    other_channels.iter().enumerate().map(|(ix, channel)| {
    let is_selected = matches!(selection,
    selection::Unified::Channel(Some(selection::Channel{ ix: selected_ix, .. })) if &ix == selected_ix
    );
    el(button(text(channel))
    .on_press(Msg::Action(action::Msg::Confirm))
    .class(selectable_button_class(is_selected)))
    })
    };
    // Other channel selection
    let channel_col_0 = || {
    el(column([
    el(text(format!("Current channel: {channel}"))),
    el(
    nav_scrollable(&navigation.other_channels_nav, view_channels())
    .class(if other_channels_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill),
    ),
    ]))
    };
    // Other channel change selection in selected channel
    let channel_col_1 = || match selection {
    selection::Unified::Channel(Some(selection::Channel {
    ix: _channel_ix,
    name,
    log: _,
    })) => {
    let Some(Log::Loaded { log }) = logs.other_channels_logs.get(name)
    else {
    return el(column([]));
    };
    let entries = log.iter().enumerate().map(|(ix, entry)| {
    let is_selected = matches!(selection,
    selection::Unified::Channel(Some(selection::Channel { log: Some(selection::LogChange { ix: selected_ix, .. }), .. })) if &ix == selected_ix
    );
    view_log_change(ix, entry, is_selected)
    });
    let len = log.len();
    let selected_ix = match selection {
    selection::Unified::EntireLog(Some(selection::LogChange {
    ix,
    ..
    })) => Some(len - *ix),
    _ => None,
    };
    el(column([
    if let Some(selected_ix) = selected_ix {
    el(text(format!(
    "Channel {name} log ({selected_ix}/{len})"
    )))
    } else {
    el(text(format!("Channel {name} log ({len})")))
    },
    el(nav_scrollable(&navigation.entire_log_nav, entries)
    .class(if other_channel_log_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill)),
    if hidden_cols == 1 {
    el(button(row([el(text("← Other channels")
    .shaping(text::Shaping::Advanced))]))
    .on_press(Msg::Action(action::Msg::Selection(
    selection::Msg::PressDir(selection::Dir::Left),
    ))))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill))
  • replacement in inflorescence_view/src/app.rs at line 588
    [40.13504][40.13504:13523]()
    _ => None,
    [40.13504]
    [38.5462]
    _ => el(column([])),
    };
    // Other channel log file selection in selected channel's change
    let channel_col_2 = || match selection {
    selection::Unified::Channel(Some(selection::Channel {
    ix: _channel_ix,
    name,
    log:
    Some(selection::LogChange {
    ix,
    hash,
    message,
    file,
    }),
    })) => {
    let short_hash = display_short_hash(hash);
    let nav = &navigation.other_channel_logs_navs.files_nav;
    let view = match logs.other_channels_logs.get(name) {
    Some(Log::Loaded { log }) => {
    let entry = log.get(*ix).unwrap();
    let files = entry.file_paths.iter().enumerate().map(|(ix, path)| {
    let is_selected = matches!(file, Some(selection::LogChangeFileSelection{ path: selected_path, .. }) if selected_path == path);
    el(button(text(path)).on_press_with(move || {
    Msg::Action(action::Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() })))
    }).class(selectable_button_class(is_selected)))
    });
    el(nav_scrollable(nav, files)
    .class(if other_channel_log_change_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill))
    }
    _ => el(text("Loading...")),
    };
    let files_view = el(column([
    view_diff_header(format!("{short_hash} message:")),
    el(text(message).shaping(text::Shaping::Advanced)),
    view_diff_header("Changed files:".to_string()),
    view,
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING));
    el(column([
    files_view,
    if hidden_cols == 2 {
    el(button(row([el(
    text("← Log").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Action(
    action::Msg::Selection(selection::Msg::PressDir(
    selection::Dir::Left,
    )),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    }
    _ => el(row([])),
  • edit in inflorescence_view/src/app.rs at line 659
    [38.5470]
    [40.13524]
    // Other channel log diff selection in selected channel's change's file
    let channel_col_3 = || match selection {
    selection::Unified::Channel(Some(selection::Channel {
    name: _,
    log:
    Some(selection::LogChange {
    ix: _,
    hash,
    message: _,
    file:
    Some(selection::LogChangeFileSelection {
    ix: _,
    path,
    diff_selected,
    }),
    }),
    ..
    })) => {
    let file_id = file::log_id_parts_hash(*hash, path);
    let state = navigation.log_diffs.diffs.get(&file_id);
    el(column([
    el(column([
    view_diff_header(format!(
    "{path} changes in {}:",
    display_short_hash(hash)
    )),
    match state {
    Some(diff::FileAndState { file, state }) => {
    let nav =
    &navigation.other_channel_logs_navs.diffs_nav;
    diff::view(state, nav, file, *diff_selected)
    }
    None => el(text("Loading diff..")),
    },
    ])
    .spacing(SPACING)),
    if hidden_cols == 3 {
    el(button(row([el(
    text("← Files").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Action(
    action::Msg::Selection(selection::Msg::PressDir(
    selection::Dir::Left,
    )),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    }
    _ => el(column([])),
    };
  • edit in inflorescence_view/src/app.rs at line 727
    [41.278][38.5942:5969](),[40.14184][38.5942:5969](),[38.5942][38.5942:5969](),[38.5969][40.14185:14408]()
    _ => false,
    };
    let other_channels_selected = || match selection {
    selection::Unified::Channel(channel) => match channel {
    Some(selection::Channel { log, .. }) => log.is_none(),
    None => true,
    },
  • edit in inflorescence_view/src/app.rs at line 730
    [38.5970]
    [38.5970]
    // Entire log change selection
  • replacement in inflorescence_view/src/app.rs at line 771
    [38.7254][38.7254:7286](),[38.7286][40.14971:15084](),[40.15084][38.7387:7476](),[38.7387][38.7387:7476](),[38.7476][40.15085:15106](),[40.15106][38.7517:7576](),[38.7517][38.7517:7576](),[38.7576][40.15107:15314](),[40.15314][38.7723:7873](),[38.7723][38.7723:7873]()
    let entire_log_col_1 = || {
    let files_view = match selection {
    selection::Unified::EntireLog(Some(selection::LogChange {
    ix,
    hash,
    message,
    file,
    })) => {
    let short_hash = display_short_hash(hash);
    let nav = get_entire_log_files_nav(navigation, *hash);
    let view = match nav.as_ref().zip(logs.entire_log.as_ref()) {
    Some((nav, Log::Loaded { log })) => {
    let entry = log.get(*ix).unwrap();
    let files = entry.file_paths.iter().enumerate().map(|(ix, path)| {
    [38.7254]
    [40.15315]
    // Entire log file selection in selected change
    let entire_log_col_1 = || match selection {
    selection::Unified::EntireLog(Some(selection::LogChange {
    ix,
    hash,
    message,
    file,
    })) => {
    let short_hash = display_short_hash(hash);
    let view = match logs.entire_log.as_ref() {
    Some(Log::Loaded { log }) => {
    let nav = &navigation.entire_logs_navs.files_nav;
    let entry = log.get(*ix).unwrap();
    let files = entry.file_paths.iter().enumerate().map(|(ix, path)| {
  • replacement in inflorescence_view/src/app.rs at line 790
    [38.8327][39.3759:4168](),[39.4168][38.8869:8959](),[38.8869][38.8869:8959]()
    el(nav_scrollable(nav, files)
    .class(if entire_log_change_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill))
    }
    _ => el(text("Loading...")),
    };
    [38.8327]
    [9.24230]
    el(nav_scrollable(nav, files)
    .class(if entire_log_change_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill))
    }
    _ => el(text("Loading...")),
    };
  • replacement in inflorescence_view/src/app.rs at line 802
    [9.24231][38.8960:9060](),[38.9060][40.15471:15543](),[40.15543][38.9133:9370](),[38.9133][38.9133:9370](),[38.9370][40.15544:15574](),[40.15574][38.9403:9414](),[38.9403][38.9403:9414]()
    el(column([
    view_diff_header(format!("{short_hash} message:")),
    el(text(message).shaping(text::Shaping::Advanced)),
    view_diff_header("Changed files:".to_string()),
    view,
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    }
    _ => el(row([])),
    };
    [9.24231]
    [38.9414]
    let files_view = el(column([
    view_diff_header(format!("{short_hash} message:")),
    el(text(message).shaping(text::Shaping::Advanced)),
    view_diff_header("Changed files:".to_string()),
    view,
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING));
  • replacement in inflorescence_view/src/app.rs at line 812
    [38.9415][38.9415:9618](),[38.9618][42.2119:2297](),[42.2297][38.9728:9909](),[38.9728][38.9728:9909]()
    el(column([
    files_view,
    if hidden_cols == 1 {
    el(button(row([el(
    text("← Log").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Action(
    action::Msg::Selection(selection::Msg::PressDir(
    selection::Dir::Left,
    )),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    [38.9415]
    [38.9909]
    el(column([
    files_view,
    if hidden_cols == 1 {
    el(button(row([el(
    text("← Log").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Action(
    action::Msg::Selection(selection::Msg::PressDir(
    selection::Dir::Left,
    )),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    }
    _ => el(row([])),
  • replacement in inflorescence_view/src/app.rs at line 834
    [38.9917][39.4169:4212]()
    // TODO more re-use with status_col_2?
    [38.9917]
    [40.15575]
    // TODO more re-use with status_col_2
    // Entire log diff selection in selected change's file
  • replacement in inflorescence_view/src/app.rs at line 848
    [40.15890][40.15890:16118]()
    let id_hash = file::log_id_parts_hash(*hash, path);
    let state = navigation.log_diffs.diffs.get(&id_hash);
    let nav = get_entire_log_diffs_nav(navigation, id_hash);
    Some(el(column([
    [40.15890]
    [40.16118]
    let file_id = file::log_id_parts_hash(*hash, path);
    let state = navigation.log_diffs.diffs.get(&file_id);
    el(column([
  • replacement in inflorescence_view/src/app.rs at line 856
    [40.16314][40.16314:16434]()
    match state.zip(nav) {
    Some((diff::FileAndState { file, state }, nav)) => {
    [40.16314]
    [40.16434]
    match state {
    Some(diff::FileAndState { file, state }) => {
    let nav = &navigation.entire_logs_navs.diffs_nav;
  • replacement in inflorescence_view/src/app.rs at line 882
    [40.17218][40.17218:17250]()
    .spacing(SPACING)))
    [40.17218]
    [40.17250]
    .spacing(SPACING))
  • replacement in inflorescence_view/src/app.rs at line 884
    [40.17260][40.17260:17279](),[40.17279][38.11701:11709](),[38.11701][38.11701:11709](),[38.11709][35.6521:6614](),[9.24231][35.6521:6614](),[35.6614][40.17280:17445](),[40.17445][35.6758:6810](),[35.6758][35.6758:6810](),[35.6810][42.2493:2554](),[42.2554][35.6850:6923](),[35.6850][35.6850:6923]()
    _ => None,
    };
    let view_channels = || {
    other_channels.iter().enumerate().map(|(ix, channel)| {
    let is_selected = matches!(selection,
    selection::Unified::Channel(Some(selection::Channel{ ix: selected_ix, .. })) if &ix == selected_ix
    );
    el(button(text(channel))
    .on_press(Msg::Action(action::Msg::Confirm))
    .class(selectable_button_class(is_selected)))
    })
    [40.17260]
    [35.6923]
    _ => el(column([])),
  • replacement in inflorescence_view/src/app.rs at line 889
    [40.17522][40.17522:17653](),[40.17653][38.12199:12272](),[38.12199][38.12199:12272](),[38.12272][40.17654:18052]()
    if let Some(status_col_2) = status_col_2() {
    let cols = [status_col_0(), status_col_1(), status_col_2]
    .into_iter()
    .skip(hidden_cols);
    el(row(cols)
    .spacing(SPACING)
    .width(Length::Fill)
    .height(Length::Fill))
    } else {
    let cols = [status_col_0(), status_col_1()];
    el(row(cols)
    .spacing(SPACING)
    .width(Length::Fill)
    .height(Length::Fill))
    }
    [40.17522]
    [40.18052]
    let cols = [status_col_0(), status_col_1(), status_col_2()]
    .into_iter()
    .skip(hidden_cols);
    el(row(cols)
    .spacing(SPACING)
    .width(Length::Fill)
    .height(Length::Fill))
  • replacement in inflorescence_view/src/app.rs at line 903
    [40.18331][40.18331:18672](),[40.18672][38.12331:12368](),[38.12331][38.12331:12368](),[38.12368][40.18673:18857](),[40.18857][38.12548:12624](),[38.12548][38.12548:12624]()
    let nav = nav_scrollable(
    &navigation.other_channels_nav,
    view_channels(),
    )
    .class(if other_channels_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill);
    el(column([
    el(text(format!("Current channel: {channel}"))),
    el(nav),
    ])
    .width(Length::Fill)
    .height(Length::Fill))
    [40.18331]
    [40.18858]
    let cols = [
    channel_col_0(),
    channel_col_1(),
    channel_col_2(),
    channel_col_3(),
    ]
    .into_iter()
    .skip(hidden_cols);
    el(row(cols).width(Length::Fill).height(Length::Fill))
  • replacement in inflorescence_view/src/app.rs at line 923
    [40.19211][40.19211:19988]()
    if let Some(entire_log_col_2) = entire_log_col_2() {
    let cols = [
    entire_log_col_0(),
    entire_log_col_1(),
    entire_log_col_2,
    ]
    .into_iter()
    .skip(hidden_cols);
    el(row(cols)
    .spacing(SPACING)
    .width(Length::Fill)
    .height(Length::Fill))
    } else {
    let cols = [entire_log_col_0(), entire_log_col_1()];
    el(row(cols)
    .spacing(SPACING)
    .width(Length::Fill)
    .height(Length::Fill))
    }
    [40.19211]
    [40.19988]
    let cols = [
    entire_log_col_0(),
    entire_log_col_1(),
    entire_log_col_2(),
    ]
    .into_iter()
    .skip(hidden_cols);
    el(row(cols)
    .spacing(SPACING)
    .width(Length::Fill)
    .height(Length::Fill))
  • edit in inflorescence_view/src/app/test.rs at line 43
    [41.820]
    [10.5139]
    allowed_actions: vec![],
  • edit in inflorescence_view/src/app/test.rs at line 73
    [41.1273]
    [11.289]
    allowed_actions: vec![],
  • edit in inflorescence_view/src/app/test.rs at line 116
    [41.1755]
    [12.8460]
    allowed_actions: vec![],
  • edit in inflorescence_view/src/app/test.rs at line 155
    [41.2566]
    [10.5822]
    allowed_actions: vec![],
  • replacement in inflorescence_model/src/log.rs at line 20
    [40.31462][40.31462:31532]()
    pub files_nav: Option<(repo::ChangeHash, nav_scrollable::State)>,
    [40.31462]
    [40.31532]
    pub files_nav: nav_scrollable::State,
  • replacement in inflorescence_model/src/log.rs at line 23
    [40.31622][40.31622:31691]()
    pub diffs_nav: Option<(file::LogIdHash, nav_scrollable::State)>,
    [40.31622]
    [40.31691]
    pub diffs_nav: nav_scrollable::State,
    #[cfg(debug_assertions)]
    pub change_hash: Option<repo::ChangeHash>,
    #[cfg(debug_assertions)]
    pub file_id: Option<file::LogIdHash>,
    }
    pub fn init_files_nav(navs: &mut Navs, hash: repo::ChangeHash) {
    navs.files_nav = nav_scrollable::State::default();
    #[cfg(debug_assertions)]
    {
    navs.change_hash = Some(hash);
    navs.file_id = None;
    }
    #[cfg(not(debug_assertions))]
    let _ = hash;
    }
    pub fn init_diffs_nav(
    navs: &mut Navs,
    file_id: file::LogIdHash,
    ) -> &mut nav_scrollable::State {
    navs.diffs_nav = nav_scrollable::State::default();
    #[cfg(debug_assertions)]
    {
    navs.file_id = Some(file_id);
    }
    #[cfg(not(debug_assertions))]
    let _ = file_id;
    &mut navs.diffs_nav
  • replacement in inflorescence_model/src/lib.rs at line 8
    [40.31846][40.31846:31880]()
    use libflorescence::{file, repo};
    [40.31846]
    [40.31880]
    use libflorescence::repo;
  • replacement in inflorescence_model/src/lib.rs at line 15
    [40.31969][40.31969:32022]()
    pub fn ready(state: &State) -> Option<&ReadyState> {
    [40.31969]
    [40.32022]
    pub fn is_ready(state: &State) -> Option<&ReadyState> {
  • replacement in inflorescence_model/src/lib.rs at line 22
    [40.32117][40.32117:32182]()
    pub fn ready_mut(state: &mut State) -> Option<&mut ReadyState> {
    [40.32117]
    [40.32182]
    pub fn is_ready_mut(state: &mut State) -> Option<&mut ReadyState> {
  • edit in inflorescence_model/src/lib.rs at line 84
    [40.33559]
    [40.33559]
    #[cfg(debug_assertions)]
    pub other_channel_name: Option<String>,
  • replacement in inflorescence_model/src/lib.rs at line 87
    [40.33625][40.33625:33686]()
    pub other_channel_log_navs: Option<(String, log::Navs)>,
    [40.33625]
    [40.33686]
    pub other_channel_logs_navs: log::Navs,
  • edit in inflorescence_model/src/lib.rs at line 111
    [40.34389][40.34389:35107]()
    }
    /// Get untracked or changes files diff's nav if it matches given file ID
    pub fn get_files_diffs_nav(
    navigation: &Navigation,
    id_hash: file::IdHash,
    ) -> Option<&nav_scrollable::State> {
    navigation
    .files_diffs
    .diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    }
    /// Get untracked or changes files diff's nav if it matches given file ID
    pub fn get_files_diffs_nav_mut(
    navigation: &mut Navigation,
    id_hash: file::IdHash,
    ) -> Option<&mut nav_scrollable::State> {
    navigation
    .files_diffs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
  • replacement in inflorescence_model/src/lib.rs at line 113
    [40.35110][40.35110:35550]()
    /// Get status log files nav if it matches given change hash
    pub fn get_status_log_files_nav(
    navigation: &Navigation,
    hash: repo::ChangeHash,
    ) -> Option<&nav_scrollable::State> {
    navigation
    .status_logs_navs
    .files_nav
    .as_ref()
    .and_then(|(nav_hash, nav)| (*nav_hash == hash).then_some(nav))
    }
    /// Get status log files nav if it matches given change hash
    pub fn get_status_log_files_nav_mut(
    [40.35110]
    [40.35550]
    pub fn init_channel_nav(
  • replacement in inflorescence_model/src/lib.rs at line 115
    [40.35583][40.35583:35803]()
    hash: repo::ChangeHash,
    ) -> Option<&mut nav_scrollable::State> {
    navigation
    .status_logs_navs
    .files_nav
    .as_mut()
    .and_then(|(nav_hash, nav)| (*nav_hash == hash).then_some(nav))
    [40.35583]
    [40.35803]
    #[cfg(debug_assertions)] name: String,
    ) {
    navigation.other_channel_logs_navs = log::Navs::default();
    #[cfg(debug_assertions)]
    {
    navigation.other_channel_name = Some(name);
    }
  • edit in inflorescence_model/src/lib.rs at line 123
    [40.35805][40.35805:37937]()
    /// Get status log diffs nav if it matches given log file ID
    pub fn get_status_log_diffs_nav(
    navigation: &Navigation,
    id_hash: file::LogIdHash,
    ) -> Option<&nav_scrollable::State> {
    navigation
    .status_logs_navs
    .diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    }
    /// Get status log diffs nav if it matches given log file ID
    pub fn get_status_log_diffs_nav_mut(
    navigation: &mut Navigation,
    id_hash: file::LogIdHash,
    ) -> Option<&mut nav_scrollable::State> {
    navigation
    .status_logs_navs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    }
    /// Get entire log files nav if it matches given change hash
    pub fn get_entire_log_files_nav(
    navigation: &Navigation,
    hash: repo::ChangeHash,
    ) -> Option<&nav_scrollable::State> {
    navigation
    .entire_logs_navs
    .files_nav
    .as_ref()
    .and_then(|(nav_hash, nav)| (*nav_hash == hash).then_some(nav))
    }
    /// Get entire log files nav if it matches given change hash
    pub fn get_entire_log_files_nav_mut(
    navigation: &mut Navigation,
    hash: repo::ChangeHash,
    ) -> Option<&mut nav_scrollable::State> {
    navigation
    .entire_logs_navs
    .files_nav
    .as_mut()
    .and_then(|(nav_hash, nav)| (*nav_hash == hash).then_some(nav))
    }
    /// Get entire log diffs nav if it matches given log file ID
    pub fn get_entire_log_diffs_nav(
    navigation: &Navigation,
    id_hash: file::LogIdHash,
    ) -> Option<&nav_scrollable::State> {
    navigation
    .entire_logs_navs
    .diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    }
    /// Get entire log diffs nav if it matches given log file ID
    pub fn get_entire_log_diffs_nav_mut(
    navigation: &mut Navigation,
    id_hash: file::LogIdHash,
    ) -> Option<&mut nav_scrollable::State> {
    navigation
    .entire_logs_navs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    }
  • replacement in inflorescence_model/src/diff.rs at line 26
    [40.38734][40.38734:38800]()
    pub diffs_nav: Option<(file::IdHash, nav_scrollable::State)>,
    [40.38734]
    [40.38800]
    pub diffs_nav: nav_scrollable::State,
    #[cfg(debug_assertions)]
    pub file_id: Option<file::IdHash>,
    }
    pub fn init_diffs_nav(
    navs: &mut FilesState,
    #[cfg(debug_assertions)] file_id: file::IdHash,
    ) -> &mut nav_scrollable::State {
    navs.diffs_nav = nav_scrollable::State::default();
    #[cfg(debug_assertions)]
    {
    navs.file_id = Some(file_id);
    }
    &mut navs.diffs_nav
  • replacement in inflorescence_model/src/action.rs at line 1
    [42.3501][42.3502:3704]()
    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,
    };
    [42.3501]
    [42.3704]
    use crate::{self as model, selection, ReadyState, RecordMsg};
  • replacement in inflorescence_model/src/action.rs at line 3
    [42.3742][42.3742:3776]()
    use libflorescence::{file, repo};
    [42.3742]
    [42.3776]
    use libflorescence::repo;
  • replacement in inflorescence_model/src/action.rs at line 12
    [42.3900][42.3900:3997]()
    /// Msgs that are bound to some key(s) and that are only allowed depending on the current state.
    [42.3900]
    [42.3997]
    /// Msgs that are bound to some key(s) and that are only allowed depending on
    /// the current state.
  • replacement in inflorescence_model/src/action.rs at line 32
    [42.4323][42.4323:4432]()
    /// Eq used for action filters. Properties that are not determined by which actions are allowed are ignored.
    [42.4323]
    [42.4432]
    pub fn is_allowed(allowed_actions: &[Binding], msg: &Msg) -> bool {
    // Always allow actions that do not need to be explicitly enabled
    match msg {
    Msg::Selection(
    // Mouse selections
    selection::Msg::Select(_) |
    // Button release
    selection::Msg::ReleaseDir(_),
    ) => {
    return true;
    }
    Msg::Confirm
    | Msg::Cancel
    | Msg::Selection(
    selection::Msg::PressDir(_) | selection::Msg::AltPressDir(_),
    )
    | Msg::PostponeRecord
    | Msg::SaveRecord
    | Msg::DiscardRecord
    | Msg::AddUntrackedFile
    | Msg::RmAddedFile
    | Msg::StartRecord
    | Msg::SelectChannel
    | Msg::ForkChannel
    | Msg::RefreshRepo
    | Msg::ShowEntireLog => {}
    }
    allowed_actions.iter().any(
    |Binding {
    msg: allowed_msg, ..
    }| {
    if let Some(allowed_msg) = allowed_msg {
    is_same_msg(msg, allowed_msg)
    } else {
    false
    }
    },
    )
    }
    /// Eq used for action filters. Properties that are not determined by which
    /// actions are allowed are ignored.
  • edit in inflorescence_model/src/action.rs at line 230
    [42.8811]
    [42.8811]
    let exit_other_channels = || Binding {
    key: "Esc",
    label: "exit channel selection",
    msg: Some(Msg::Cancel),
    };
  • replacement in inflorescence_model/src/action.rs at line 301
    [42.11062][42.11062:11199]()
    SwitchingChannelState::NoOtherChannels => ma.push(cancel()),
    SwitchingChannelState::NothingSelected => {
    [42.11062]
    [42.11199]
    SelectingChannelState::NoOtherChannels => ma.push(cancel()),
    SelectingChannelState::NothingSelected => {
  • replacement in inflorescence_model/src/action.rs at line 307
    [42.11328][42.11328:11405]()
    SwitchingChannelState::SomethingSelected { can_switch } => {
    [42.11328]
    [42.11405]
    SelectingChannelState::SomethingSelected {
    can_switch,
    can_select_right,
    } => {
  • edit in inflorescence_model/src/action.rs at line 313
    [42.11477]
    [42.11477]
    push_if(can_select_right, right, ma);
  • edit in inflorescence_model/src/action.rs at line 327
    [42.11942]
    [42.11942]
    ma.push(show_entire_log());
    }
    SubState::OtherChannelLog { can_select_right } => {
    ma.push(left());
    ma.push(down());
    ma.push(up());
    push_if(can_select_right, right, ma);
    ma.push(exit_other_channels());
    ma.push(show_entire_log());
    }
    SubState::OtherChannelLogChange { can_select_right } => {
    ma.push(left());
    ma.push(down());
    ma.push(up());
    push_if(can_select_right, right, ma);
    ma.push(exit_other_channels());
  • edit in inflorescence_model/src/action.rs at line 344
    [42.11982]
    [42.11982]
    }
    SubState::OtherChannelLogChangeDiff => {
    ma.push(left());
    ma.push(down());
    ma.push(up());
    ma.push(down_no_skip());
    ma.push(up_no_skip());
    ma.push(exit_other_channels());
  • replacement in inflorescence_model/src/action.rs at line 388
    [42.13165][42.13165:13239]()
    fn push_if<'a, F>(predicate: bool, to_add: F, actions: &mut Vec<Binding>)
    [42.13165]
    [42.13239]
    fn push_if<F>(predicate: bool, to_add: F, actions: &mut Vec<Binding>)
  • replacement in inflorescence_model/src/action.rs at line 422
    [42.13902][42.13902:13947]()
    SelectingChannel(SwitchingChannelState),
    [42.13902]
    [42.13947]
    /// Selecting an other channel
    SelectingChannel(SelectingChannelState),
    /// Viewing other channel's log
    OtherChannelLog {
    can_select_right: bool,
    },
    /// Viewing other channel's log with some change selected
    OtherChannelLogChange {
    can_select_right: bool,
    },
    /// Viewing other channel's log with some diff of a change selected
    OtherChannelLogChangeDiff,
  • replacement in inflorescence_model/src/action.rs at line 458
    [42.14439][42.14439:14468]()
    enum SwitchingChannelState {
    [42.14439]
    [42.14468]
    enum SelectingChannelState {
  • replacement in inflorescence_model/src/action.rs at line 461
    [42.14510][42.14510:14554]()
    SomethingSelected { can_switch: bool },
    [42.14510]
    [42.14554]
    SomethingSelected {
    can_switch: bool,
    can_select_right: bool,
    },
  • replacement in inflorescence_model/src/action.rs at line 494
    [42.15269][42.15269:15286]()
    logs: _,
    [42.15269]
    [42.15286]
    logs,
  • replacement in inflorescence_model/src/action.rs at line 524
    [42.16235][42.16235:16261]()
    path,
    [42.16235]
    [42.16261]
    path: _,
  • replacement in inflorescence_model/src/action.rs at line 527
    [42.16320][42.16320:17027]()
    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,
    }
    }
    [42.16320]
    [42.17027]
    if *diff_selected {
    SubState::StatusLogDiff { can_record }
  • edit in inflorescence_model/src/action.rs at line 530
    [42.17056]
    [42.17056]
    let diffs_nav = &navigation.files_diffs.diffs_nav;
    let can_select_right =
    nav_scrollable::needs_scrolling(diffs_nav);
  • replacement in inflorescence_model/src/action.rs at line 535
    [42.17162][42.17162:17215]()
    can_select_right: false,
    [42.17162]
    [42.17215]
    can_select_right,
  • replacement in inflorescence_model/src/action.rs at line 560
    [42.18150][42.18150:18847]()
    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,
    }
    }
    [42.18150]
    [42.18847]
    if *diff_selected {
    SubState::StatusLogDiff { can_record }
  • edit in inflorescence_model/src/action.rs at line 563
    [42.18876]
    [42.18876]
    let diffs_nav = &navigation.files_diffs.diffs_nav;
    let can_select_right =
    nav_scrollable::needs_scrolling(diffs_nav);
  • replacement in inflorescence_model/src/action.rs at line 568
    [42.18974][42.18974:19027]()
    can_select_right: false,
    [42.18974]
    [42.19027]
    can_select_right,
  • replacement in inflorescence_model/src/action.rs at line 575
    [42.19233][42.19233:19259]()
    hash,
    [42.19233]
    [42.19259]
    hash: _,
  • replacement in inflorescence_model/src/action.rs at line 581
    [42.19445][42.19445:19475]()
    path,
    [42.19445]
    [42.19475]
    path: _,
  • replacement in inflorescence_model/src/action.rs at line 584
    [42.19542][42.19542:20206]()
    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),
    }
    }
    [42.19542]
    [42.20206]
    if *diff_selected {
    SubState::StatusLogDiff { can_record }
  • edit in inflorescence_model/src/action.rs at line 587
    [42.20239]
    [42.20239]
    let diffs_nav =
    &navigation.status_logs_navs.diffs_nav;
    let can_select_right =
    nav_scrollable::needs_scrolling(diffs_nav);
  • replacement in inflorescence_model/src/action.rs at line 593
    [42.20339][42.20339:20396]()
    can_select_right: false,
    [42.20339]
    [42.20396]
    can_select_right,
  • replacement in inflorescence_model/src/action.rs at line 598
    [42.20504][42.20504:20583]()
    let nav = get_status_log_files_nav(navigation, *hash);
    [42.20504]
    [42.20583]
    let files_nav = &navigation.status_logs_navs.files_nav;
    let can_select_right =
    nav_scrollable::has_sections(files_nav);
  • replacement in inflorescence_model/src/action.rs at line 603
    [42.20685][42.20685:20746]()
    can_select_right: nav.is_some(),
    [42.20685]
    [42.20746]
    can_select_right,
  • replacement in inflorescence_model/src/action.rs at line 615
    [42.21067][42.21067:21556]()
    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)
    }
    [42.21067]
    [42.21556]
    selection::Primary::Channel => match channel_selection {
    Some(selection::Channel {
    log: None, name, ..
    }) => {
    let sub_state = if other_channels.is_empty() {
    SelectingChannelState::NoOtherChannels
    } else {
    let log = logs.other_channels_logs.get(name);
    let can_switch = changed_files.is_empty();
    let can_select_right = log.is_some();
    SelectingChannelState::SomethingSelected {
    can_switch,
    can_select_right,
    }
    };
    SubState::SelectingChannel(sub_state)
    }
    Some(selection::Channel {
    log: Some(selection::LogChange { file: None, .. }),
    ..
    }) => {
    let files_nav = &navigation.other_channel_logs_navs.files_nav;
    let can_select_right = nav_scrollable::has_sections(files_nav);
    SubState::OtherChannelLog { can_select_right }
    }
    Some(selection::Channel {
    log:
    Some(selection::LogChange {
    file:
    Some(selection::LogChangeFileSelection {
    diff_selected,
    ..
    }),
    ..
    }),
    ..
    }) => {
    if *diff_selected {
    SubState::OtherChannelLogChangeDiff
    } else {
    let diffs_nav =
    &navigation.other_channel_logs_navs.diffs_nav;
    let can_select_right =
    nav_scrollable::needs_scrolling(diffs_nav);
    SubState::OtherChannelLogChange { can_select_right }
    }
    }
    None => SubState::SelectingChannel(
    SelectingChannelState::NothingSelected,
    ),
    },
  • replacement in inflorescence_model/src/action.rs at line 667
    [42.21599][42.21599:21666]()
    if let Some(selection::LogChange { hash, file, .. }) =
    [42.21599]
    [42.21666]
    if let Some(selection::LogChange { file, .. }) =
  • edit in inflorescence_model/src/action.rs at line 672
    [42.21807][42.21807:21868]()
    ix: _,
    path,
  • edit in inflorescence_model/src/action.rs at line 673
    [42.21907]
    [42.21907]
    ..
  • replacement in inflorescence_model/src/action.rs at line 675
    [42.21935][42.21935:22542]()
    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),
    }
    }
    [42.21935]
    [42.22542]
    if *diff_selected {
    SubState::EntireLogChangeDiff
  • replacement in inflorescence_model/src/action.rs at line 678
    [42.22575][42.22575:22718]()
    SubState::EntireLogChange {
    can_select_right: false,
    }
    [42.22575]
    [42.22718]
    let diffs_nav =
    &navigation.entire_logs_navs.diffs_nav;
    let can_select_right =
    nav_scrollable::needs_scrolling(diffs_nav);
    SubState::EntireLogChange { can_select_right }
  • replacement in inflorescence_model/src/action.rs at line 686
    [42.22796][42.22796:23008]()
    let nav = get_entire_log_files_nav(navigation, *hash);
    SubState::EntireLog {
    can_select_right: nav.is_some(),
    }
    [42.22796]
    [42.23008]
    let files_nav = &navigation.entire_logs_navs.files_nav;
    let can_select_right =
    nav_scrollable::has_sections(files_nav);
    SubState::EntireLog { can_select_right }
  • replacement in inflorescence/src/test.rs at line 5
    [21.140][41.2814:2874]()
    use inflorescence_model::{ReadyState, RecordMsg, SubState};
    [21.140]
    [16.1459]
    use inflorescence_model::{action, ReadyState, RecordMsg, SubState};
  • replacement in inflorescence/src/test.rs at line 97
    [16.2601][16.2601:2705]()
    Msg::View(app::Msg::ToRepo(
    repo::MsgIn::RefreshChangedAndUntrackedFiles
    ))
    [16.2601]
    [16.2705]
    Msg::ToRepo(repo::MsgIn::RefreshChangedAndUntrackedFiles)
  • replacement in inflorescence/src/test.rs at line 115
    [18.120][35.10537:10646]()
    Msg::View(app::Msg::Selection(selection::Msg::Select(
    selection::Select::UntrackedFile {
    [18.120]
    [18.220]
    Msg::View(app::Msg::Action(action::Msg::Selection(
    selection::Msg::Select(selection::Select::UntrackedFile {
  • replacement in inflorescence/src/test.rs at line 119
    [18.293][18.293:308]()
    },
    [18.293]
    [18.308]
    }),
  • replacement in inflorescence/src/test.rs at line 126
    [16.3182][34.10273:10348]()
    let _task = update(&mut state, Msg::View(app::Msg::AddUntrackedFile));
    [16.3182]
    [16.3241]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::AddUntrackedFile)),
    );
  • replacement in inflorescence/src/test.rs at line 139
    [16.3483][34.10349:10419]()
    let _task = update(&mut state, Msg::View(app::Msg::StartRecord));
    [16.3483]
    [41.3280]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::StartRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 171
    [16.4114][18.648:717]()
    let _task = update(&mut state, Msg::View(app::Msg::SaveRecord));
    [16.4114]
    [16.4155]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::SaveRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 203
    [17.484][17.484:588]()
    Msg::View(app::Msg::ToRepo(
    repo::MsgIn::RefreshChangedAndUntrackedFiles
    ))
    [17.484]
    [17.588]
    Msg::ToRepo(repo::MsgIn::RefreshChangedAndUntrackedFiles)
  • replacement in inflorescence/src/test.rs at line 213
    [17.899][41.4157:4418]()
    {
    let ready_state = get_ready_state_mut(&mut state);
    ready_state.selection.status = Some(selection::Status::UntrackedFile {
    ix: 0,
    path: file_to_record.to_string(),
    diff_selected: false,
    });
    }
    [17.899]
    [17.1033]
    update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::Selection(
    selection::Msg::Select(selection::Select::UntrackedFile {
    ix: 0,
    path: file_to_record.to_string(),
    }),
    ))),
    );
    // Selection triggers `LoadedSrcFile`
    let msg = task::await_next_msg(&mut tasks).await;
    let id = file::Id {
    path: file_to_record.to_string(),
    file_kind: file::Kind::Untracked,
    };
    assert_matches!(
    &msg,
    Msg::File(crate::file::Msg::LoadedSrcFile { id: loaded_id, .. })
    if *loaded_id == id
    );
  • replacement in inflorescence/src/test.rs at line 236
    [17.1065][34.10495:10570]()
    let _task = update(&mut state, Msg::View(app::Msg::AddUntrackedFile));
    [17.1065]
    [17.1124]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::AddUntrackedFile)),
    );
  • replacement in inflorescence/src/test.rs at line 249
    [17.1366][34.10571:10641]()
    let _task = update(&mut state, Msg::View(app::Msg::StartRecord));
    [17.1366]
    [41.4419]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::StartRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 281
    [17.1991][34.10642:10714]()
    let _task = update(&mut state, Msg::View(app::Msg::DiscardRecord));
    [17.1991]
    [41.4930]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::DiscardRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 294
    [17.2135][34.10715:10785]()
    let _task = update(&mut state, Msg::View(app::Msg::StartRecord));
    [17.2135]
    [41.5045]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::StartRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 326
    [17.2766][34.10786:10859]()
    let _task = update(&mut state, Msg::View(app::Msg::PostponeRecord));
    [17.2766]
    [41.5556]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::PostponeRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 341
    [17.3067][34.10860:10930]()
    let _task = update(&mut state, Msg::View(app::Msg::StartRecord));
    [17.3067]
    [41.5830]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::StartRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 367
    [23.548][34.10931:11000]()
    let task = update(&mut state, Msg::View(app::Msg::StartRecord));
    [23.548]
    [23.601]
    let task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::StartRecord)),
    );
  • replacement in inflorescence/src/test.rs at line 406
    [19.865][19.865:969]()
    Msg::View(app::Msg::ToRepo(
    repo::MsgIn::RefreshChangedAndUntrackedFiles
    ))
    [19.865]
    [19.969]
    Msg::ToRepo(repo::MsgIn::RefreshChangedAndUntrackedFiles)
  • replacement in inflorescence/src/test.rs at line 432
    [19.1581][35.10725:10834]()
    Msg::View(app::Msg::Selection(selection::Msg::Select(
    selection::Select::UntrackedFile {
    [19.1581]
    [19.1681]
    Msg::View(app::Msg::Action(action::Msg::Selection(
    selection::Msg::Select(selection::Select::UntrackedFile {
  • replacement in inflorescence/src/test.rs at line 436
    [19.1754][19.1754:1769]()
    },
    [19.1754]
    [19.1769]
    }),
  • edit in inflorescence/src/test.rs at line 439
    [19.1789]
    [19.1789]
  • replacement in inflorescence/src/test.rs at line 441
    [19.1831][19.1831:1886]()
    let _msg = task::await_next_msg(&mut tasks).await;
    [19.1831]
    [19.1886]
    let msg = task::await_next_msg(&mut tasks).await;
    let id = file::Id {
    path: file_to_record.to_string(),
    file_kind: file::Kind::Untracked,
    };
    assert_matches!(
    &msg,
    Msg::File(crate::file::Msg::LoadedSrcFile { id: loaded_id, .. })
    if *loaded_id == id
    );
  • replacement in inflorescence/src/test.rs at line 453
    [19.1918][34.11001:11076]()
    let _task = update(&mut state, Msg::View(app::Msg::AddUntrackedFile));
    [19.1918]
    [19.1977]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::AddUntrackedFile)),
    );
  • replacement in inflorescence/src/test.rs at line 481
    [20.141][35.10835:10942]()
    Msg::View(app::Msg::Selection(selection::Msg::Select(
    selection::Select::ChangedFile {
    [20.141]
    [20.239]
    Msg::View(app::Msg::Action(action::Msg::Selection(
    selection::Msg::Select(selection::Select::ChangedFile {
  • replacement in inflorescence/src/test.rs at line 485
    [20.312][20.312:327]()
    },
    [20.312]
    [20.327]
    }),
  • edit in inflorescence/src/test.rs at line 487
    [20.340]
    [20.340]
    );
    // Selection triggers `LoadedSrcFile`
    let msg = task::await_next_msg(&mut tasks).await;
    let id = file::Id {
    path: file_to_record.to_string(),
    file_kind: file::Kind::Changed,
    };
    assert_matches!(
    &msg,
    Msg::File(crate::file::Msg::LoadedSrcFile { id: loaded_id, .. })
    if *loaded_id == id
  • replacement in inflorescence/src/test.rs at line 502
    [20.456][34.11077:11147]()
    let _task = update(&mut state, Msg::View(app::Msg::RmAddedFile));
    [20.456]
    [20.510]
    let _task = update(
    &mut state,
    Msg::View(app::Msg::Action(action::Msg::RmAddedFile)),
    );
  • replacement in inflorescence/src/selection.rs at line 9
    [40.39532][40.39532:39742]()
    use inflorescence_model::{
    get_entire_log_diffs_nav_mut, get_entire_log_files_nav_mut,
    get_files_diffs_nav_mut, get_status_log_diffs_nav_mut,
    get_status_log_files_nav_mut, Log, Logs, Navigation,
    };
    [40.39532]
    [28.4188]
    use inflorescence_model::{self as model, Log, Logs, Navigation};
  • replacement in inflorescence/src/selection.rs at line 116
    [40.40996][40.40996:41050]()
    Primary::Channel => select_down_channel(ctx),
    [40.40996]
    [40.41050]
    Primary::Channel => select_down_channel(ctx, delta),
  • replacement in inflorescence/src/selection.rs at line 132
    [31.349][31.349:430](),[31.430][40.41280:41402](),[40.41402][39.6155:6234](),[39.6155][39.6155:6234]()
    let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);
    if let Some(nav) =
    get_files_diffs_nav_mut(ctx.navigation, id_hash)
    {
    nav_scrollable::scroll_down(nav, delta);
    }
    [31.349]
    [31.430]
    nav_scrollable::scroll_down(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • replacement in inflorescence/src/selection.rs at line 169
    [31.1818][31.1818:1897](),[31.1897][40.41855:41977](),[40.41977][39.6497:6576](),[39.6497][39.6497:6576]()
    let id_hash = file::id_parts_hash(&path, file::Kind::Changed);
    if let Some(nav) =
    get_files_diffs_nav_mut(ctx.navigation, id_hash)
    {
    nav_scrollable::scroll_down(nav, delta);
    }
    [31.1818]
    [31.1897]
    nav_scrollable::scroll_down(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 213
    [31.3498][31.3498:3574]()
    let id_hash = file::log_id_parts_hash(hash, &path);
  • replacement in inflorescence/src/selection.rs at line 223
    [38.21812][40.42426:42608](),[40.42608][39.6725:6793](),[39.6725][39.6725:6793](),[39.6793][33.24563:24590](),[33.24563][33.24563:24590]()
    if let Some(nav) = get_status_log_diffs_nav_mut(
    ctx.navigation,
    id_hash,
    ) {
    nav_scrollable::scroll_down(nav, delta)
    };
    [38.21812]
    [39.6794]
    nav_scrollable::scroll_down(
    &mut ctx.navigation.status_logs_navs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 249
    [31.4947][6.7558:7559](),[38.22130][6.7558:7559](),[33.24767][6.7558:7559](),[6.7558][6.7558:7559](),[6.7559][40.43075:43197](),[40.43197][33.24960:24986](),[33.24960][33.24960:24986](),[33.24986][39.6970:7051](),[39.7051][33.25209:25236](),[33.25209][33.25209:25236]()
    if let Some(nav) =
    get_status_log_files_nav_mut(ctx.navigation, hash)
    {
    nav_scrollable::scroll_down_to_section(nav, file_ix)
    };
  • replacement in inflorescence/src/selection.rs at line 305
    [27.30877][40.44273:44383]()
    fn select_down_channel(ctx: &mut Ctx<'_>) -> Task<crate::Msg> {
    let ix = match ctx.state.channel.take() {
    [27.30877]
    [40.44383]
    fn select_down_channel(
    ctx: &mut Ctx<'_>,
    delta: Option<Duration>,
    ) -> Task<crate::Msg> {
    let (selection, task) = match ctx.state.channel.take() {
  • replacement in inflorescence/src/selection.rs at line 313
    [40.44443][40.44443:44463]()
    log: _,
    [40.44443]
    [40.44463]
    log: None,
  • replacement in inflorescence/src/selection.rs at line 315
    [40.44479][40.44479:44536]()
    if ix == ctx.repo.other_channels.len() - 1 {
    [40.44479]
    [40.44536]
    let ix = if ix == ctx.repo.other_channels.len() - 1 {
  • replacement in inflorescence/src/selection.rs at line 319
    [40.44598][40.44598:44612]()
    }
    [40.44598]
    [40.44612]
    };
    channel_selection(ix, VDir::Down, ctx)
  • replacement in inflorescence/src/selection.rs at line 322
    [40.44622][40.44622:44757](),[40.44757][41.10743:10752](),[41.10752][40.44774:44827](),[40.44774][40.44774:44827](),[33.27417][28.6526:6555](),[40.44827][28.6526:6555](),[28.6526][28.6526:6555](),[28.6555][33.27418:27442](),[33.27442][40.44828:44898](),[39.7179][38.22765:22902](),[40.44898][38.22765:22902](),[38.22765][38.22765:22902](),[38.22902][40.44899:44940](),[40.44940][38.22944:23025](),[38.22944][38.22944:23025]()
    None => 0,
    };
    let (selection, task) = channel_selection(ix, VDir::Down, ctx);
    ctx.state.channel = Some(selection);
    task
    }
    fn select_down_entire_log(
    ctx: &mut Ctx<'_>,
    delta: Option<Duration>,
    ) -> Task<crate::Msg> {
    if let Some(Log::Loaded { log }) = ctx.logs.entire_log.as_ref() {
    let (selection, task) = if let Some(LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) = ctx.state.entire_log.take()
    {
    match file {
    Some(LogChangeFileSelection {
    [40.44622]
    [38.23025]
    None => {
    let ix = 0;
    channel_selection(ix, VDir::Down, ctx)
    }
    Some(Channel {
    ix: channel_ix,
    name,
    log:
    Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file,
    }),
    }) => {
    if let Some(Log::Loaded { log }) =
    ctx.logs.other_channels_logs.get(&name)
    {
    if let Some(LogChangeFileSelection {
  • replacement in inflorescence/src/selection.rs at line 344
    [38.23119][38.23119:23143]()
    }) => {
    [38.23119]
    [38.23143]
    }) = file
    {
  • replacement in inflorescence/src/selection.rs at line 347
    [38.23182][38.23182:23615]()
    let id_hash = file::log_id_parts_hash(hash, &path);
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    [38.23182]
    [38.23615]
    let selection = Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
  • edit in inflorescence/src/selection.rs at line 360
    [38.23647][38.23647:23674](),[38.23674][40.44941:45074](),[39.7235][38.23740:23951](),[40.45074][38.23740:23951](),[38.23740][38.23740:23951](),[38.23951][39.7236:7293](),[39.7293][40.45075:45143]()
    };
    if let Some(nav) = ctx
    .navigation
    .entire_logs_navs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    })
    {
    nav_scrollable::scroll_down(nav, delta)
  • edit in inflorescence/src/selection.rs at line 361
    [38.24156]
    [39.7360]
    nav_scrollable::scroll_down(
    &mut ctx.navigation.entire_logs_navs.diffs_nav,
    delta,
    );
  • replacement in inflorescence/src/selection.rs at line 369
    [38.24227][38.24227:24293]()
    let log_entry = log.get(log_ix).unwrap();
    [38.24227]
    [38.24293]
    let log_entry = log.get(channel_ix).unwrap();
  • replacement in inflorescence/src/selection.rs at line 380
    [38.24524][38.24524:24604]()
    let (file, selection_task) = entire_log_file_selection(
    [38.24524]
    [40.45478]
    let (file, selection_task) = channel_log_file_selection(
  • replacement in inflorescence/src/selection.rs at line 388
    [38.24783][40.45634:45756](),[40.45756][38.24982:25008](),[38.24982][38.24982:25008](),[38.25008][40.45757:45865](),[39.7641][35.14764:14765](),[38.25256][35.14764:14765](),[40.45865][35.14764:14765](),[35.14764][35.14764:14765](),[35.14765][38.25257:25466]()
    if let Some(nav) =
    get_entire_log_files_nav_mut(ctx.navigation, hash)
    {
    nav_scrollable::scroll_down_to_section(nav, file_ix)
    };
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    [38.24783]
    [38.25466]
    let selection = Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file: Some(file),
    }),
  • edit in inflorescence/src/selection.rs at line 400
    [38.25595]
    [38.25595]
    } else {
    let (selection, task) =
    if log.len().saturating_sub(1) == change_ix {
    let ix = 0;
    channel_log_selection(ix, VDir::Up, ctx, log)
    } else {
    let ix = change_ix + 1;
    channel_log_selection(ix, VDir::Down, ctx, log)
    };
    let selection = Channel {
    ix: channel_ix,
    name,
    log: Some(selection),
    };
    (selection, task)
  • replacement in inflorescence/src/selection.rs at line 416
    [38.25613][38.25613:25639](),[38.25639][40.45866:46034](),[40.46034][38.25992:26021](),[38.25992][38.25992:26021](),[38.26021][40.46035:46151](),[40.46151][38.26318:26340](),[38.26318][38.26318:26340]()
    None => {
    if log.len().saturating_sub(1) == log_ix {
    let ix = 0;
    entire_log_selection(ix, VDir::Up, ctx, log)
    } else {
    let ix = log_ix + 1;
    entire_log_selection(ix, VDir::Down, ctx, log)
    }
    [38.25613]
    [38.26340]
    } else {
    let selection = Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file,
    }),
    };
    (selection, Task::none())
    }
    }
    };
    ctx.state.channel = Some(selection);
    task
    }
    fn select_down_entire_log(
    ctx: &mut Ctx<'_>,
    delta: Option<Duration>,
    ) -> Task<crate::Msg> {
    if let Some(Log::Loaded { log }) = ctx.logs.entire_log.as_ref() {
    let (selection, task) = if let Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file,
    }) = ctx.state.entire_log.take()
    {
    if let Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) = file
    {
    if diff_selected {
    let selection = LogChange {
    ix: change_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    };
    nav_scrollable::scroll_down(
    &mut ctx.navigation.entire_logs_navs.diffs_nav,
    delta,
    );
    (selection, Task::none())
    } else {
    let log_entry = log.get(change_ix).unwrap();
    let file_ix =
    if log_entry.file_paths.len().saturating_sub(1)
    == file_ix
    {
    0
    } else {
    file_ix + 1
    };
    let (file, selection_task) = entire_log_file_selection(
    file_ix,
    hash,
    VDir::Down,
    ctx.navigation,
    log_entry,
    );
    let selection = LogChange {
    ix: change_ix,
    hash,
    message,
    file: Some(file),
    };
    (selection, selection_task)
  • edit in inflorescence/src/selection.rs at line 499
    [38.26358]
    [38.26358]
    } else if log.len().saturating_sub(1) == change_ix {
    let ix = 0;
    entire_log_selection(ix, VDir::Up, ctx, log)
    } else {
    let ix = change_ix + 1;
    entire_log_selection(ix, VDir::Down, ctx, log)
  • replacement in inflorescence/src/selection.rs at line 535
    [31.7328][31.7328:7409](),[31.7409][40.46730:47024](),[40.47024][39.7922:7998](),[39.7922][39.7922:7998]()
    let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);
    if let Some(nav) =
    ctx.navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::scroll_up(nav, delta)
    }
    [31.7328]
    [31.7409]
    nav_scrollable::scroll_up(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • replacement in inflorescence/src/selection.rs at line 572
    [31.8825][31.8825:8904](),[31.8904][40.47582:47876](),[40.47876][39.8261:8337](),[39.8261][39.8261:8337]()
    let id_hash = file::id_parts_hash(&path, file::Kind::Changed);
    if let Some(nav) =
    ctx.navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::scroll_up(nav, delta)
    }
    [31.8825]
    [31.8904]
    nav_scrollable::scroll_up(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 616
    [31.10556][31.10556:10632]()
    let id_hash = file::log_id_parts_hash(hash, &path);
  • replacement in inflorescence/src/selection.rs at line 626
    [38.26900][40.48432:48565](),[39.8428][33.30187:30398](),[38.26966][33.30187:30398](),[40.48565][33.30187:30398](),[33.30187][33.30187:30398](),[33.30398][39.8429:8552](),[39.8552][33.30576:30603](),[33.30576][33.30576:30603]()
    if let Some(nav) = ctx
    .navigation
    .status_logs_navs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    })
    {
    nav_scrollable::scroll_up(nav, delta)
    };
    [38.26900]
    [39.8553]
    nav_scrollable::scroll_up(
    &mut ctx.navigation.status_logs_navs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 649
    [38.27218][33.30779:30780](),[33.30779][33.30779:30780](),[33.30780][40.49070:49192](),[40.49192][33.30972:30998](),[33.30972][33.30972:30998](),[33.30998][39.8729:8808](),[39.8808][33.31219:31246](),[33.31219][33.31219:31246]()
    if let Some(nav) =
    get_entire_log_files_nav_mut(ctx.navigation, hash)
    {
    nav_scrollable::scroll_up_to_section(nav, file_ix)
    };
  • replacement in inflorescence/src/selection.rs at line 737
    [40.51353][40.51353:52723]()
    match file {
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) => {
    if diff_selected {
    let id_hash = file::log_id_parts_hash(hash, &path);
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    };
    if let Some(nav) = get_entire_log_diffs_nav_mut(
    ctx.navigation,
    id_hash,
    ) {
    nav_scrollable::scroll_up(nav, delta)
    };
    (selection, Task::none())
    } else {
    let log_entry = log.get(log_ix).unwrap();
    let file_ix = if 0 == file_ix {
    log_entry.file_paths.len().saturating_sub(1)
    } else {
    file_ix - 1
    };
    [40.51353]
    [40.52723]
    if let Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) = file
    {
    if diff_selected {
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    };
  • replacement in inflorescence/src/selection.rs at line 755
    [40.52724][40.52724:53023]()
    let (file, selection_task) = entire_log_file_selection(
    file_ix,
    hash,
    VDir::Up,
    ctx.navigation,
    log_entry,
    );
    [40.52724]
    [40.53023]
    nav_scrollable::scroll_up(
    &mut ctx.navigation.entire_logs_navs.diffs_nav,
    delta,
    );
  • replacement in inflorescence/src/selection.rs at line 760
    [40.53024][40.53024:53277]()
    if let Some(nav) =
    get_entire_log_files_nav_mut(ctx.navigation, hash)
    {
    nav_scrollable::scroll_up_to_section(nav, file_ix)
    }
    [40.53024]
    [40.53277]
    (selection, Task::none())
    } else {
    let log_entry = log.get(log_ix).unwrap();
  • replacement in inflorescence/src/selection.rs at line 764
    [40.53278][40.53278:53802]()
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    };
    (selection, selection_task)
    }
    }
    None => {
    if 0 == log_ix {
    let ix = log.len().saturating_sub(1);
    entire_log_selection(ix, VDir::Down, ctx, log)
    [40.53278]
    [40.53802]
    let file_ix = if 0 == file_ix {
    log_entry.file_paths.len().saturating_sub(1)
  • replacement in inflorescence/src/selection.rs at line 767
    [40.53831][40.53831:53967]()
    let ix = log_ix - 1;
    entire_log_selection(ix, VDir::Up, ctx, log)
    }
    [40.53831]
    [40.53967]
    file_ix - 1
    };
    let (file, selection_task) = entire_log_file_selection(
    file_ix,
    hash,
    VDir::Up,
    ctx.navigation,
    log_entry,
    );
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    };
    (selection, selection_task)
  • edit in inflorescence/src/selection.rs at line 786
    [40.53985]
    [40.53985]
    } else if 0 == log_ix {
    let ix = log.len().saturating_sub(1);
    entire_log_selection(ix, VDir::Down, ctx, log)
    } else {
    let ix = log_ix - 1;
    entire_log_selection(ix, VDir::Up, ctx, log)
  • edit in inflorescence/src/selection.rs at line 806
    [35.15256][29.4420:4457](),[29.4420][29.4420:4457]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 807
    [29.4490]
    [29.4490]
    ..
  • replacement in inflorescence/src/selection.rs at line 809
    [29.4506][30.296:372](),[30.372][33.33350:33381](),[33.33381][40.54323:54438](),[40.54438][33.33523:33588](),[33.33523][33.33523:33588](),[33.33588][40.54439:54480](),[33.33611][29.4715:4729](),[40.54480][29.4715:4729](),[29.4715][29.4715:4729](),[29.4729][39.8893:8953](),[39.8953][29.4844:4858](),[29.4844][29.4844:4858]()
    let id_hash = file::id_parts_hash(path, file::Kind::Untracked);
    if let Some(nav) =
    ctx.navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::alt_scroll_down(nav, delta)
    }
    [29.4506]
    [39.8954]
    nav_scrollable::alt_scroll_down(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 817
    [35.15292][29.4906:4943](),[29.4906][29.4906:4943]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 818
    [29.4976]
    [29.4976]
    ..
  • replacement in inflorescence/src/selection.rs at line 820
    [29.4992][30.373:447](),[30.447][33.33612:33643](),[33.33643][40.54481:54596](),[40.54596][33.33785:33850](),[33.33785][33.33785:33850](),[33.33850][40.54597:54638](),[33.33873][29.5199:5213](),[40.54638][29.5199:5213](),[29.5199][29.5199:5213](),[29.5213][39.9011:9071](),[39.9071][29.5328:5342](),[29.5328][29.5328:5342]()
    let id_hash = file::id_parts_hash(path, file::Kind::Changed);
    if let Some(nav) =
    ctx.navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::alt_scroll_down(nav, delta)
    }
    [29.4992]
    [39.9072]
    nav_scrollable::alt_scroll_down(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 828
    [35.15326][29.5388:5449](),[38.27707][29.5388:5449](),[29.5388][29.5388:5449]()
    ix: _,
    hash,
    message: _,
  • edit in inflorescence/src/selection.rs at line 830
    [29.5513][29.5513:5566]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 831
    [29.5607]
    [29.5607]
    ..
  • edit in inflorescence/src/selection.rs at line 833
    [29.5627]
    [38.27708]
    ..
  • replacement in inflorescence/src/selection.rs at line 835
    [38.27725][30.448:512](),[29.5643][30.448:512](),[30.512][33.33874:33905](),[33.33905][40.54639:54865](),[33.34057][29.5860:5874](),[40.54865][29.5860:5874](),[29.5860][29.5860:5874](),[29.5874][39.9171:9231](),[39.9231][29.5989:6003](),[29.5989][29.5989:6003]()
    let id_hash = file::log_id_parts_hash(*hash, path);
    if let Some(nav) =
    ctx.navigation.status_logs_navs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::alt_scroll_down(nav, delta)
    }
    [38.27725]
    [39.9232]
    nav_scrollable::alt_scroll_down(
    &mut ctx.navigation.status_logs_navs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 852
    [35.15531][29.6434:6471](),[29.6434][29.6434:6471]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 853
    [29.6504]
    [29.6504]
    ..
  • replacement in inflorescence/src/selection.rs at line 855
    [29.6520][30.513:589](),[30.589][33.34058:34089](),[33.34089][40.54982:55097](),[40.55097][33.34231:34296](),[33.34231][33.34231:34296](),[33.34296][40.55098:55139](),[33.34319][29.6729:6743](),[40.55139][29.6729:6743](),[29.6729][29.6729:6743](),[29.6743][39.9289:9347](),[39.9347][29.6856:6870](),[29.6856][29.6856:6870]()
    let id_hash = file::id_parts_hash(path, file::Kind::Untracked);
    if let Some(nav) =
    ctx.navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::alt_scroll_up(nav, delta)
    }
    [29.6520]
    [39.9348]
    nav_scrollable::alt_scroll_down(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 863
    [35.15567][29.6918:6955](),[29.6918][29.6918:6955]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 864
    [29.6988]
    [29.6988]
    ..
  • replacement in inflorescence/src/selection.rs at line 866
    [29.7004][30.590:664](),[30.664][33.34320:34351](),[33.34351][40.55140:55255](),[40.55255][33.34493:34558](),[33.34493][33.34493:34558](),[33.34558][40.55256:55297](),[33.34581][29.7211:7225](),[40.55297][29.7211:7225](),[29.7211][29.7211:7225](),[29.7225][39.9405:9463](),[39.9463][29.7338:7352](),[29.7338][29.7338:7352]()
    let id_hash = file::id_parts_hash(path, file::Kind::Changed);
    if let Some(nav) =
    ctx.navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::alt_scroll_up(nav, delta)
    }
    [29.7004]
    [39.9464]
    nav_scrollable::alt_scroll_down(
    &mut ctx.navigation.files_diffs.diffs_nav,
    delta,
    );
  • edit in inflorescence/src/selection.rs at line 874
    [35.15601][29.7398:7459](),[38.27822][29.7398:7459](),[29.7398][29.7398:7459]()
    ix: _,
    hash,
    message: _,
  • edit in inflorescence/src/selection.rs at line 876
    [29.7523][29.7523:7576]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 877
    [29.7617]
    [29.7617]
    ..
  • edit in inflorescence/src/selection.rs at line 879
    [29.7637]
    [38.27823]
    ..
  • replacement in inflorescence/src/selection.rs at line 881
    [38.27840][30.665:729](),[29.7653][30.665:729](),[30.729][33.34582:34613](),[33.34613][40.55298:55524](),[33.34765][29.7870:7884](),[40.55524][29.7870:7884](),[29.7870][29.7870:7884](),[29.7884][39.9563:9621](),[39.9621][29.7997:8011](),[29.7997][29.7997:8011]()
    let id_hash = file::log_id_parts_hash(*hash, path);
    if let Some(nav) =
    ctx.navigation.status_logs_navs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::alt_scroll_up(nav, delta)
    }
    [38.27840]
    [39.9622]
    nav_scrollable::alt_scroll_down(
    &mut ctx.navigation.status_logs_navs.diffs_nav,
    delta,
    );
  • replacement in inflorescence/src/selection.rs at line 968
    [40.58164][40.58164:58189]()
    return task;
    [40.58164]
    [40.58189]
    task
  • replacement in inflorescence/src/selection.rs at line 971
    [40.58229][40.58229:58252]()
    // todo!()
    [40.58229]
    [40.58252]
    let (selection, task) = match ctx.state.channel.take() {
    Some(Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange { file: None, .. }),
    }) => {
    let selection = Channel {
    ix: channel_ix,
    name,
    log: None,
    };
    (Some(selection), Task::none())
    }
    Some(Channel {
    ix: channel_ix,
    name,
    log:
    Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    }),
    }) => {
    if diff_selected {
    let selection = Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    }),
    };
    (Some(selection), Task::none())
    } else {
    let selection = Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file: None,
    }),
    };
    (Some(selection), Task::none())
    }
    }
    selection @ (Some(Channel { .. }) | None) => {
    (selection, Task::none())
    }
    };
    ctx.state.channel = selection;
    task
  • replacement in inflorescence/src/selection.rs at line 1079
    [40.59677][40.59677:59702]()
    return task;
    [40.59677]
    [40.59702]
    task
  • edit in inflorescence/src/selection.rs at line 1082
    [38.34138][40.59713:59730]()
    Task::none()
  • replacement in inflorescence/src/selection.rs at line 1086
    [40.59820][40.59820:59969](),[40.59969][39.10753:10860](),[39.10753][39.10753:10860](),[39.10860][40.59970:60685](),[40.60685][39.11336:11411](),[39.11336][39.11336:11411]()
    Primary::Status => {
    let (selection, task): (Option<Status>, Task<crate::Msg>) =
    match ctx.state.status.take() {
    Some(Status::UntrackedFile {
    ix,
    path,
    diff_selected: false,
    }) => {
    let id_hash =
    file::id_parts_hash(&path, file::Kind::Untracked);
    let diff_selected = diff::file_diff_needs_scrolling(
    &ctx.navigation.files_diffs,
    id_hash,
    );
    (
    Some(Status::UntrackedFile {
    ix,
    path,
    diff_selected,
    }),
    Task::none(),
    )
    }
    Some(Status::ChangedFile {
    ix,
    [40.59820]
    [39.11411]
    Primary::Status => select_right_status(ctx),
    Primary::Channel => select_right_channel(ctx),
    Primary::EntireLog => select_right_entire_log(ctx),
    }
    }
    fn select_right_status(ctx: &mut Ctx<'_>) -> Task<crate::Msg> {
    let (selection, task): (Option<Status>, Task<crate::Msg>) = match ctx
    .state
    .status
    .take()
    {
    Some(Status::UntrackedFile {
    ix,
    path,
    diff_selected: false,
    }) => {
    let diff_selected =
    diff::file_diff_needs_scrolling(&ctx.navigation.files_diffs);
    (
    Some(Status::UntrackedFile {
    ix,
    path,
    diff_selected,
    }),
    Task::none(),
    )
    }
    Some(Status::ChangedFile {
    ix,
    path,
    diff_selected: false,
    }) => {
    let diff_selected =
    diff::file_diff_needs_scrolling(&ctx.navigation.files_diffs);
    (
    Some(Status::ChangedFile {
    ix,
    path,
    diff_selected,
    }),
    Task::none(),
    )
    }
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file: None,
    })) => {
    let log_entry = ctx.repo.short_log.get(ix).unwrap();
    let (file, task) = if let Some(path) = log_entry.file_paths.first()
    {
    let file_id = file::log_id_parts_hash(log_entry.hash, path);
    // If the log is not loaded yet, the nav will be initialized
    // once it's loaded (`repo::MsgOut::GotChangeDiffs`)
    if let Some(log) = ctx.navigation.log_diffs.diffs.get(&file_id)
    {
    // Init log diffs nav
    let unchanged_sections =
    diff::unchanged_sections(&log.file);
    log::init_diffs_nav(
    &mut ctx.navigation.status_logs_navs,
    file_id,
    )
    .set_skip_sections(unchanged_sections);
    };
    let (selection, task) = status_log_file_selection(
    0,
    hash,
    VDir::Down,
    ctx.navigation,
    log_entry,
    );
    (Some(selection), task)
    } else {
    (None, Task::none())
    };
    (
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file,
    })),
    task,
    )
    }
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    })) => {
    let is_diff_scrollable =
    log::diff_needs_scrolling(&ctx.navigation.status_logs_navs);
    (
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
  • replacement in inflorescence/src/selection.rs at line 1196
    [39.11441][40.60686:61480]()
    diff_selected: false,
    }) => {
    let id_hash =
    file::id_parts_hash(&path, file::Kind::Changed);
    let diff_selected = diff::file_diff_needs_scrolling(
    &ctx.navigation.files_diffs,
    id_hash,
    );
    (
    Some(Status::ChangedFile {
    ix,
    path,
    diff_selected,
    }),
    Task::none(),
    )
    }
    Some(Status::LogChange(LogChange {
    ix,
    [39.11441]
    [40.61480]
    diff_selected: is_diff_scrollable,
    }),
    })),
    Task::none(),
    )
    }
    selection => (selection, Task::none()),
    };
    ctx.state.status = selection;
    task
    }
    fn select_right_channel(ctx: &mut Ctx<'_>) -> Task<crate::Msg> {
    if let Some(channel) = ctx.state.channel.take() {
    let (selection, task) = match channel {
    Channel {
    ix: channel_ix,
    name,
    log: None,
    } => {
    if let Some(Log::Loaded { log }) =
    ctx.logs.other_channels_logs.get(&name)
    {
    let change_ix = 0;
    let (log_selection, task) =
    channel_log_selection(change_ix, VDir::Down, ctx, log);
    let selection = Some(Channel {
    ix: channel_ix,
    name,
    log: Some(log_selection),
    });
    (selection, task)
    } else {
    (
    Some(Channel {
    ix: channel_ix,
    name,
    log: None,
    }),
    Task::none(),
    )
    }
    }
    Channel {
    ix: channel_ix,
    name,
    log:
    Some(LogChange {
    ix: change_ix,
  • replacement in inflorescence/src/selection.rs at line 1248
    [40.61579][40.61579:61873]()
    })) => {
    let log_entry = ctx.repo.short_log.get(ix).unwrap();
    let (file, task) = if let Some(path) =
    log_entry.file_paths.first()
    {
    let id_hash =
    [40.61579]
    [40.61873]
    }),
    } => {
    if let Some(Log::Loaded { log }) =
    ctx.logs.other_channels_logs.get(&name)
    {
    let log_entry = log.get(change_ix).unwrap();
    let (file, task) =
    if let Some(path) = log_entry.file_paths.first() {
    let file_id =
  • replacement in inflorescence/src/selection.rs at line 1260
    [40.62082][40.62082:62152]()
    // loaded (`repo::MsgOut::GotChangeDifs`)
    [40.62082]
    [40.62152]
    // loaded (`repo::MsgOut::GotChangeDiffs`)
  • replacement in inflorescence/src/selection.rs at line 1262
    [40.62199][40.62199:62276]()
    ctx.navigation.log_diffs.diffs.get(&id_hash)
    [40.62199]
    [40.62276]
    ctx.navigation.log_diffs.diffs.get(&file_id)
  • edit in inflorescence/src/selection.rs at line 1264
    [40.62306][40.62306:62360]()
    // Init log diffs nav
  • replacement in inflorescence/src/selection.rs at line 1266
    [40.62490][40.62490:62776]()
    let nav = nav_scrollable::State::default()
    .with_skip_sections(unchanged_sections);
    ctx.navigation.status_logs_navs.diffs_nav =
    Some((id_hash, nav));
    [40.62490]
    [40.62776]
    log::init_diffs_nav(
    &mut ctx.navigation.other_channel_logs_navs,
    file_id,
    )
    .set_skip_sections(unchanged_sections);
  • replacement in inflorescence/src/selection.rs at line 1273
    [39.12465][40.62808:63169]()
    (
    Some(LogChangeFileSelection {
    ix: 0,
    path: path.clone(),
    diff_selected: false,
    }),
    Task::none(),
    )
    [39.12465]
    [40.63169]
    let (file, task) = channel_log_file_selection(
    0,
    hash,
    VDir::Down,
    ctx.navigation,
    log_entry,
    );
    (Some(file), task)
  • replacement in inflorescence/src/selection.rs at line 1284
    [40.63278][40.63278:63403]()
    (
    Some(Status::LogChange(LogChange {
    ix,
    [40.63278]
    [40.63403]
    (
    Some(Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
  • replacement in inflorescence/src/selection.rs at line 1294
    [40.63520][40.63520:63690]()
    })),
    task,
    )
    }
    Some(Status::LogChange(LogChange {
    [40.63520]
    [40.63690]
    }),
    }),
    task,
    )
    } else {
    (
    Some(Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix: change_ix,
    hash,
    message,
    file: None,
    }),
    }),
    Task::none(),
    )
    }
    }
    Channel {
    ix: channel_ix,
    name,
    log:
    Some(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1328
    [40.64038][40.64038:64894]()
    })) => {
    let id_hash = file::log_id_parts_hash(hash, &path);
    let is_diff_scrollable = log::log_diff_needs_scrolling(
    &ctx.navigation.status_logs_navs,
    id_hash,
    );
    (
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: is_diff_scrollable,
    }),
    })),
    Task::none(),
    [40.64038]
    [40.64894]
    }),
    } => {
    let navs = &ctx.navigation.other_channel_logs_navs;
    let is_diff_scrollable = log::diff_needs_scrolling(navs);
    (
    Some(Channel {
    ix: channel_ix,
    name,
    log: Some(LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: is_diff_scrollable,
    }),
    }),
    }),
    Task::none(),
    )
    }
    selection @ Channel { .. } => (Some(selection), Task::none()),
    };
    ctx.state.channel = selection;
    return task;
    }
    Task::none()
    }
    fn select_right_entire_log(ctx: &mut Ctx<'_>) -> Task<crate::Msg> {
    if let Some(Log::Loaded { log }) = ctx.logs.entire_log.as_ref()
    && let Some(entire_log) = ctx.state.entire_log.take()
    {
    let (selection, task) = match entire_log {
    LogChange {
    ix,
    hash,
    message,
    file: None,
    } => {
    let log_entry = log.get(ix).unwrap();
    let (file, task) = if let Some(path) =
    log_entry.file_paths.first()
    {
    let file_id = file::log_id_parts_hash(log_entry.hash, path);
    // If the log is not loaded yet, the nav will be
    // initialized once it's
    // loaded (`repo::MsgOut::GotChangeDiffs`)
    if let Some(log) =
    ctx.navigation.log_diffs.diffs.get(&file_id)
    {
    let unchanged_sections =
    diff::unchanged_sections(&log.file);
    log::init_diffs_nav(
    &mut ctx.navigation.entire_logs_navs,
    file_id,
  • replacement in inflorescence/src/selection.rs at line 1386
    [40.64920][40.64920:65002]()
    }
    selection => (selection, Task::none()),
    [40.64920]
    [27.41935]
    .set_skip_sections(unchanged_sections);
    };
    (
    Some(LogChangeFileSelection {
    ix: 0,
    path: path.clone(),
    diff_selected: false,
    }),
    Task::none(),
    )
    } else {
    (None, Task::none())
  • replacement in inflorescence/src/selection.rs at line 1400
    [27.41954][40.65003:65423]()
    ctx.state.status = selection;
    return task;
    }
    Primary::Channel => {
    // TODO
    }
    Primary::EntireLog => {
    if let Some(Log::Loaded { log }) = ctx.logs.entire_log.as_ref()
    && let Some(entire_log) = ctx.state.entire_log.take()
    {
    let (selection, task) = match entire_log {
    LogChange {
    [27.41954]
    [39.12884]
    (
    Some(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1405
    [39.12975][40.65424:67512]()
    file: None,
    } => {
    let log_entry = log.get(ix).unwrap();
    let (file, task) = if let Some(path) =
    log_entry.file_paths.first()
    {
    let id_hash =
    file::log_id_parts_hash(log_entry.hash, path);
    // If the log is not loaded yet, the nav will be
    // initialized once it's
    // loaded (`repo::MsgOut::GotChangeDifs`)
    if let Some(log) =
    ctx.navigation.log_diffs.diffs.get(&id_hash)
    {
    // Init log diffs nav
    let unchanged_sections =
    diff::unchanged_sections(&log.file);
    let nav = nav_scrollable::State::default()
    .with_skip_sections(unchanged_sections);
    ctx.navigation.entire_logs_navs.diffs_nav =
    Some((id_hash, nav));
    };
    (
    Some(LogChangeFileSelection {
    ix: 0,
    path: path.clone(),
    diff_selected: false,
    }),
    Task::none(),
    )
    } else {
    (None, Task::none())
    };
    (
    Some(LogChange {
    ix,
    hash,
    message,
    file,
    }),
    task,
    )
    }
    LogChange {
    [39.12975]
    [39.13556]
    file,
    }),
    task,
    )
    }
    LogChange {
    ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    } => {
    let is_diff_scrollable =
    log::diff_needs_scrolling(&ctx.navigation.entire_logs_navs);
    (
    Some(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1428
    [39.13647][40.67513:68883]()
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    } => {
    let id_hash = file::log_id_parts_hash(hash, &path);
    let is_diff_scrollable = log::log_diff_needs_scrolling(
    &ctx.navigation.entire_logs_navs,
    id_hash,
    );
    (
    Some(LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: is_diff_scrollable,
    }),
    }),
    Task::none(),
    )
    }
    selection @ LogChange { .. } => {
    (Some(selection), Task::none())
    }
    };
    ctx.state.entire_log = selection;
    return task;
    [39.13647]
    [39.13950]
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: is_diff_scrollable,
    }),
    }),
    Task::none(),
    )
  • replacement in inflorescence/src/selection.rs at line 1437
    [39.13964][40.68884:68894]()
    }
    [39.13964]
    [40.68894]
    selection @ LogChange { .. } => (Some(selection), Task::none()),
    };
    ctx.state.entire_log = selection;
    return task;
  • edit in inflorescence/src/selection.rs at line 1442
    [40.68900][40.68900:68901]()
  • edit in inflorescence/src/selection.rs at line 1459
    [35.16953][28.7534:7587](),[28.7534][28.7534:7587]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 1460
    [28.7628]
    [28.7628]
    ..
  • replacement in inflorescence/src/selection.rs at line 1462
    [28.7652][28.7652:7686](),[28.7686][30.730:804](),[30.804][40.69133:69451](),[40.69451][39.14028:14091](),[33.42811][39.14028:14091](),[39.14091][28.7986:8008](),[28.7986][28.7986:8008]()
    let id_hash =
    file::id_parts_hash(path, file::Kind::Untracked);
    if let Some(nav) =
    navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::reset_skip_delay(nav);
    }
    [28.7652]
    [28.8008]
    let nav = &mut navigation.files_diffs.diffs_nav;
    nav_scrollable::reset_skip_delay(nav);
  • edit in inflorescence/src/selection.rs at line 1466
    [35.16997][28.8072:8125](),[28.8072][28.8072:8125]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 1467
    [28.8166]
    [28.8166]
    ..
  • replacement in inflorescence/src/selection.rs at line 1469
    [28.8190][28.8190:8224](),[28.8224][30.805:877](),[30.877][40.69452:69770](),[40.69770][39.14092:14155](),[33.43059][39.14092:14155](),[39.14155][28.8522:8544](),[28.8522][28.8522:8544]()
    let id_hash =
    file::id_parts_hash(path, file::Kind::Changed);
    if let Some(nav) =
    navigation.files_diffs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::reset_skip_delay(nav);
    }
    [28.8190]
    [28.8544]
    let nav = &mut navigation.files_diffs.diffs_nav;
    nav_scrollable::reset_skip_delay(nav);
  • edit in inflorescence/src/selection.rs at line 1473
    [35.17039][28.8606:8691](),[38.35224][28.8606:8691](),[28.8606][28.8606:8691]()
    ix: _,
    hash,
    message: _,
  • edit in inflorescence/src/selection.rs at line 1475
    [28.8771][28.8771:8840]()
    ix: _,
    path,
  • edit in inflorescence/src/selection.rs at line 1476
    [28.8889]
    [28.8889]
    ..
  • edit in inflorescence/src/selection.rs at line 1478
    [28.8917]
    [38.35225]
    ..
  • replacement in inflorescence/src/selection.rs at line 1480
    [38.35250][28.8941:9013](),[28.8941][28.8941:9013](),[28.9013][40.69771:70094](),[40.70094][39.14156:14219](),[33.43300][39.14156:14219](),[39.14219][28.9271:9293](),[28.9271][28.9271:9293]()
    let id_hash = file::log_id_parts_hash(*hash, path);
    if let Some(nav) =
    navigation.status_logs_navs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    )
    {
    nav_scrollable::reset_skip_delay(nav);
    }
    [38.35250]
    [28.9293]
    let nav = &mut navigation.status_logs_navs.diffs_nav;
    nav_scrollable::reset_skip_delay(nav);
  • replacement in inflorescence/src/selection.rs at line 1500
    [40.70418][40.70418:70474]()
    file_kind: file::Kind::Changed,
    [40.70418]
    [40.70474]
    file_kind: file::Kind::Untracked,
  • replacement in inflorescence/src/selection.rs at line 1664
    [33.44381][33.44381:44449](),[33.44449][39.16041:16092]()
    let id_hash = file::id_parts_hash(path, file::Kind::Untracked);
    match file::try_get_src_file(files, id_hash) {
    [33.44381]
    [33.44515]
    let file_id = file::id_parts_hash(path, file::Kind::Untracked);
    match file::try_get_src_file(files, file_id) {
  • replacement in inflorescence/src/selection.rs at line 1669
    [33.44745][39.16093:16205](),[39.16205][40.75117:75186]()
    let nav = nav_scrollable::State::default()
    .with_skip_sections(unchanged_sections);
    navigation.files_diffs.diffs_nav = Some((id_hash, nav));
    [33.44745]
    [33.45121]
    diff::init_diffs_nav(
    &mut navigation.files_diffs,
    #[cfg(debug_assertions)]
    file_id,
    )
    .set_skip_sections(unchanged_sections);
  • replacement in inflorescence/src/selection.rs at line 1721
    [33.46348][33.46348:46414](),[33.46414][39.16536:16587]()
    let id_hash = file::id_parts_hash(path, file::Kind::Changed);
    match file::try_get_src_file(files, id_hash) {
    [33.46348]
    [33.46480]
    let file_id = file::id_parts_hash(path, file::Kind::Changed);
    match file::try_get_src_file(files, file_id) {
  • replacement in inflorescence/src/selection.rs at line 1726
    [33.46710][39.16588:16700](),[39.16700][40.75540:75609]()
    let nav = nav_scrollable::State::default()
    .with_skip_sections(unchanged_sections);
    navigation.files_diffs.diffs_nav = Some((id_hash, nav));
    [33.46710]
    [33.47086]
    diff::init_diffs_nav(
    &mut navigation.files_diffs,
    #[cfg(debug_assertions)]
    file_id,
    )
    .set_skip_sections(unchanged_sections);
  • edit in inflorescence/src/selection.rs at line 1764
    [39.16976]
    [40.75867]
    }
    fn status_log_selection(
    ix: usize,
    dir: VDir,
    ctx: &mut Ctx<'_>,
    ) -> (Status, Task<crate::Msg>) {
    let Ctx {
    state: _,
    files: _,
    navigation,
    repo,
    logs: _,
    } = ctx;
    let entry = repo.short_log.get(ix).unwrap();
    let hash = entry.hash;
    let task = if !navigation
    .log_diffs
    .changes_with_loaded_diffs
    .contains(&hash)
    {
    Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash }))
    } else {
    Task::none()
    };
    log::init_files_nav(&mut navigation.status_logs_navs, hash);
    match dir {
    VDir::Up => nav_scrollable::scroll_up_to_section(
    &mut navigation.status_nav,
    status_section_ix(repo, ix, StatusSectionKind::Log),
    ),
    VDir::Down => nav_scrollable::scroll_down_to_section(
    &mut navigation.status_nav,
    status_section_ix(repo, ix, StatusSectionKind::Log),
    ),
    }
    let selection = Status::LogChange(LogChange {
    ix,
    hash,
    message: entry.message.clone(),
    file: None,
    });
    (selection, task)
  • edit in inflorescence/src/selection.rs at line 1813
    [40.75869]
    [40.75869]
    fn status_log_file_selection(
    ix: usize,
    hash: repo::ChangeHash,
    dir: VDir,
    navigation: &mut Navigation,
    log_entry: &repo::LogEntry,
    ) -> (LogChangeFileSelection, Task<crate::Msg>) {
    let path = log_entry.file_paths.get(ix).unwrap().clone();
    log::init_diffs_nav(
    &mut navigation.status_logs_navs,
    file::log_id_parts_hash(hash, &path),
    );
  • edit in inflorescence/src/selection.rs at line 1828
    [40.75870]
    [40.75870]
    let nav = &mut navigation.status_logs_navs.files_nav;
    match dir {
    VDir::Up => nav_scrollable::scroll_up_to_section(nav, ix),
    VDir::Down => nav_scrollable::scroll_down_to_section(nav, ix),
    }
    (
    LogChangeFileSelection {
    ix,
    path,
    diff_selected: false,
    },
    Task::none(),
    )
    }
  • replacement in inflorescence/src/selection.rs at line 1857
    [40.76152][40.76152:76251]()
    let task = if logs.other_channels_logs.contains_key(&name) {
    Task::none()
    } else {
    [40.76152]
    [42.23242]
    let task = if !logs.other_channels_logs.contains_key(&name) {
  • edit in inflorescence/src/selection.rs at line 1862
    [40.76377]
    [40.76377]
    } else {
    Task::none()
  • edit in inflorescence/src/selection.rs at line 1866
    [40.76385]
    [40.76385]
    model::init_channel_nav(
    navigation,
    #[cfg(debug_assertions)]
    name.clone(),
    );
  • replacement in inflorescence/src/selection.rs at line 1891
    [33.48079][38.39088:39113]()
    fn status_log_selection(
    [33.48079]
    [33.48192]
    fn channel_log_selection(
  • replacement in inflorescence/src/selection.rs at line 1895
    [40.76821][35.17682:17716](),[33.48225][35.17682:17716]()
    ) -> (Status, Task<crate::Msg>) {
    [40.76821]
    [40.76822]
    log: &repo::Log,
    ) -> (LogChange, Task<crate::Msg>) {
  • replacement in inflorescence/src/selection.rs at line 1901
    [40.76892][40.76892:76906]()
    repo,
    [40.76892]
    [40.76906]
    repo: _,
  • replacement in inflorescence/src/selection.rs at line 1904
    [40.76936][40.76936:76985]()
    let entry = repo.short_log.get(ix).unwrap();
    [40.76936]
    [33.48305]
    let entry = log.get(ix).unwrap();
  • replacement in inflorescence/src/selection.rs at line 1907
    [33.48333][40.76986:77015]()
    let task = if navigation
    [33.48333]
    [40.77015]
    let task = if !navigation
  • replacement in inflorescence/src/selection.rs at line 1912
    [40.77100][39.17089:17173](),[39.17089][39.17089:17173](),[39.17173][40.77101:77168]()
    // Init log changes nav
    let nav = nav_scrollable::State::default();
    navigation.status_logs_navs.files_nav = Some((hash, nav));
    [40.77100]
    [39.17219]
    Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash }))
    } else {
  • edit in inflorescence/src/selection.rs at line 1915
    [39.17240][39.17240:17382](),[39.17382][42.23341:23418]()
    } else {
    // If the log is not loaded yet, the nav will be initialized once
    // it's loaded (`repo::MsgOut::GotChangeDifs`)
    Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash }))
  • edit in inflorescence/src/selection.rs at line 1916
    [33.49047]
    [33.49047]
    log::init_files_nav(&mut navigation.other_channel_logs_navs, hash);
  • replacement in inflorescence/src/selection.rs at line 1921
    [40.77227][40.77227:77267](),[39.17600][33.49148:49213](),[40.77267][33.49148:49213](),[33.49148][33.49148:49213]()
    &mut navigation.status_nav,
    status_section_ix(repo, ix, StatusSectionKind::Log),
    [40.77227]
    [39.17601]
    &mut navigation.other_channels_nav,
    ix,
  • replacement in inflorescence/src/selection.rs at line 1925
    [40.77330][40.77330:77370](),[40.77370][33.49318:49383](),[33.49318][33.49318:49383]()
    &mut navigation.status_nav,
    status_section_ix(repo, ix, StatusSectionKind::Log),
    [40.77330]
    [33.49407]
    &mut navigation.other_channels_nav,
    ix,
  • replacement in inflorescence/src/selection.rs at line 1930
    [38.39195][38.39195:39245]()
    let selection = Status::LogChange(LogChange {
    [38.39195]
    [38.39245]
    let selection = LogChange {
  • replacement in inflorescence/src/selection.rs at line 1935
    [38.39331][38.39331:39339]()
    });
    [38.39331]
    [38.39339]
    };
  • edit in inflorescence/src/selection.rs at line 1938
    [39.17707]
    [38.39394]
    }
    fn channel_log_file_selection(
    ix: usize,
    hash: repo::ChangeHash,
    dir: VDir,
    navigation: &mut Navigation,
    log_entry: &repo::LogEntry,
    ) -> (LogChangeFileSelection, Task<crate::Msg>) {
    let path = log_entry.file_paths.get(ix).unwrap().clone();
    log::init_diffs_nav(
    &mut navigation.other_channel_logs_navs,
    file::log_id_parts_hash(hash, &path),
    );
    let nav = &mut navigation.other_channel_logs_navs.files_nav;
    match dir {
    VDir::Up => nav_scrollable::scroll_up_to_section(nav, ix),
    VDir::Down => nav_scrollable::scroll_down_to_section(nav, ix),
    }
    (
    LogChangeFileSelection {
    ix,
    path,
    diff_selected: false,
    },
    Task::none(),
    )
  • replacement in inflorescence/src/selection.rs at line 1986
    [33.49426][40.77549:77578]()
    let task = if navigation
    [33.49426]
    [40.77578]
    let task = if !navigation
  • replacement in inflorescence/src/selection.rs at line 1991
    [40.77663][39.17813:17897](),[39.17813][39.17813:17897](),[39.17897][40.77664:77731]()
    // Init log changes nav
    let nav = nav_scrollable::State::default();
    navigation.entire_logs_navs.files_nav = Some((hash, nav));
    [40.77663]
    [39.17943]
    Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash }))
    } else {
  • edit in inflorescence/src/selection.rs at line 1994
    [39.17964][39.17964:18106](),[39.18106][42.23419:23496]()
    } else {
    // If the log is not loaded yet, the nav will be initialized once
    // it's loaded (`repo::MsgOut::GotChangeDifs`)
    Task::done(crate::Msg::ToRepo(repo::MsgIn::GetChangeDiffs { hash }))
  • edit in inflorescence/src/selection.rs at line 1995
    [38.40434]
    [38.40434]
    log::init_files_nav(&mut navigation.entire_logs_navs, hash);
  • edit in inflorescence/src/selection.rs at line 2018
    [33.49619][33.49619:49620](),[33.49620][40.77995:78040](),[40.78040][33.49714:49742](),[33.49714][33.49714:49742](),[33.49742][40.78041:78121](),[40.78121][33.49762:49812](),[33.49762][33.49762:49812](),[33.49812][40.78122:78184](),[40.78184][33.49879:49936](),[33.49879][33.49879:49936](),[33.49936][39.18413:18534](),[39.18534][40.78185:78424](),[40.78424][39.18650:18932](),[39.18650][39.18650:18932](),[39.18932][40.78425:78499](),[37.2715][33.50570:50580](),[39.18983][33.50570:50580](),[40.78499][33.50570:50580](),[33.50570][33.50570:50580](),[33.50767][33.50767:50774]()
    fn status_log_file_selection(
    ix: usize,
    hash: repo::ChangeHash,
    dir: VDir,
    navigation: &mut Navigation,
    log_entry: &repo::LogEntry,
    ) -> (LogChangeFileSelection, Task<crate::Msg>) {
    let path = log_entry.file_paths.get(ix).unwrap().clone();
    let id_hash = file::log_id_parts_hash(hash, &path);
    // If the log is not loaded yet, the nav will be initialized once
    // it's loaded (`repo::MsgOut::GotChangeDifs`)
    if navigation
    .log_diffs
    .changes_with_loaded_diffs
    .contains(&hash)
    {
    let needs_new_nav = navigation.status_logs_navs.diffs_nav.is_none()
    || navigation
    .status_logs_navs
    .diffs_nav
    .as_ref()
    .map(|(nav_id_hash, _nav)| *nav_id_hash != id_hash)
    .unwrap_or_default();
    if needs_new_nav {
    // Init log change diff nav
    let nav = nav_scrollable::State::default();
    navigation.status_logs_navs.diffs_nav = Some((id_hash, nav));
    }
    };
  • edit in inflorescence/src/selection.rs at line 2019
    [40.78501][40.78501:78814](),[40.78814][33.50774:50814](),[33.50774][33.50774:50814](),[33.50814][40.78815:78831](),[40.78831][33.50839:50902](),[33.50839][33.50839:50902](),[33.50902][39.18984:19006](),[39.19006][33.50920:50926](),[33.50920][33.50920:50926](),[33.50926][35.17758:17761]()
    if let Some((selected_hash, nav)) =
    &mut navigation.status_logs_navs.files_nav
    && *selected_hash == hash
    {
    match dir {
    VDir::Up => nav_scrollable::scroll_up_to_section(nav, ix),
    VDir::Down => nav_scrollable::scroll_down_to_section(nav, ix),
    }
    }
    (
    LogChangeFileSelection {
    ix,
    path,
    diff_selected: false,
    },
    Task::none(),
    )
    }
  • replacement in inflorescence/src/selection.rs at line 2028
    [38.40931][38.40931:40987](),[38.40987][39.19007:19128](),[39.19128][40.78992:79231](),[40.79231][39.19244:19526](),[39.19244][39.19244:19526](),[39.19526][40.79232:79306](),[39.19577][38.41933:41943](),[40.79306][38.41933:41943](),[38.41933][38.41933:41943](),[38.42133][38.42133:42140]()
    let id_hash = file::log_id_parts_hash(hash, &path);
    // If the log is not loaded yet, the nav will be initialized once
    // it's loaded (`repo::MsgOut::GotChangeDifs`)
    if navigation
    .log_diffs
    .changes_with_loaded_diffs
    .contains(&hash)
    {
    let needs_new_nav = navigation.entire_logs_navs.diffs_nav.is_none()
    || navigation
    .entire_logs_navs
    .diffs_nav
    .as_ref()
    .map(|(nav_id_hash, _nav)| *nav_id_hash != id_hash)
    .unwrap_or_default();
    if needs_new_nav {
    // Init log change diff nav
    let nav = nav_scrollable::State::default();
    navigation.entire_logs_navs.diffs_nav = Some((id_hash, nav));
    }
    };
    [38.40931]
    [38.42140]
    log::init_diffs_nav(
    &mut navigation.entire_logs_navs,
    file::log_id_parts_hash(hash, &path),
    );
  • replacement in inflorescence/src/selection.rs at line 2033
    [38.42141][40.79307:79614]()
    if let Some((selected_hash, nav)) =
    &mut navigation.entire_logs_navs.files_nav
    && *selected_hash == hash
    {
    match dir {
    VDir::Up => nav_scrollable::scroll_up_to_section(nav, ix),
    VDir::Down => nav_scrollable::scroll_down_to_section(nav, ix),
    }
    [38.42141]
    [40.79614]
    let nav = &mut navigation.entire_logs_navs.files_nav;
    match dir {
    VDir::Up => nav_scrollable::scroll_up_to_section(nav, ix),
    VDir::Down => nav_scrollable::scroll_down_to_section(nav, ix),
  • edit in inflorescence/src/main.rs at line 8
    [5.1220][39.19602:19640]()
    use iced_expl_widget::nav_scrollable;
  • edit in inflorescence/src/main.rs at line 180
    [4.1653][3.2041:2051](),[3.2041][3.2041:2051](),[14.342][9.26159:26187](),[3.2051][9.26159:26187](),[9.26187][40.81093:81276](),[40.81276][26.188:202](),[26.188][26.188:202](),[26.202][40.81277:82922](),[39.19864][25.3698:3737](),[40.82922][25.3698:3737](),[25.3698][25.3698:3737]()
    }
    Msg::File(msg) => {
    if let Some(ReadyState {
    repo,
    navigation,
    selection,
    ..
    }) = model::ready_mut(&mut state.sub)
    {
    let loaded = file::update(&mut state.files, repo, msg);
    if let Some(file::Loaded {
    id_hash,
    unchanged_sections,
    }) = loaded
    {
    let is_selected = match selection.status.as_ref() {
    Some(selection::Status::UntrackedFile {
    ix: _,
    path,
    diff_selected: _,
    }) => {
    let selected_id_hash = file::id_parts_hash(
    path,
    file::Kind::Untracked,
    );
    selected_id_hash == id_hash
    }
    Some(selection::Status::ChangedFile {
    ix: _,
    path,
    diff_selected: _,
    }) => {
    let selected_id_hash =
    file::id_parts_hash(path, file::Kind::Changed);
    selected_id_hash == id_hash
    }
    _ => false,
    };
    if is_selected {
    let nav = nav_scrollable::State::default()
    .with_skip_sections(unchanged_sections);
    navigation.files_diffs.diffs_nav = Some((id_hash, nav));
    }
    navigation.files_diffs.diffs.entry(id_hash).or_default();
    }
    }
    Task::none()
  • edit in inflorescence/src/main.rs at line 181
    [25.3747]
    [42.24288]
    Msg::File(msg) => update_file(state, msg),
  • edit in inflorescence/src/main.rs at line 187
    [42.24375]
    [15.452]
    }
    fn update_file(state: &mut State, msg: file::Msg) -> Task<Msg> {
    if let Some(ReadyState {
    repo,
    navigation,
    selection,
    ..
    }) = model::is_ready_mut(&mut state.sub)
    {
    let loaded = file::update(&mut state.files, repo, msg);
    if let Some(file::Loaded {
    file_id,
    unchanged_sections,
    }) = loaded
    {
    let is_selected = match selection.status.as_ref() {
    Some(selection::Status::UntrackedFile {
    ix: _,
    path,
    diff_selected: _,
    }) => {
    let selected_file_id =
    file::id_parts_hash(path, file::Kind::Untracked);
    selected_file_id == file_id
    }
    Some(selection::Status::ChangedFile {
    ix: _,
    path,
    diff_selected: _,
    }) => {
    let selected_file_id =
    file::id_parts_hash(path, file::Kind::Changed);
    selected_file_id == file_id
    }
    _ => false,
    };
    if is_selected {
    diff::init_diffs_nav(
    &mut navigation.files_diffs,
    #[cfg(debug_assertions)]
    file_id,
    )
    .set_skip_sections(unchanged_sections);
    }
    navigation.files_diffs.diffs.entry(file_id).or_default();
    }
    }
    Task::none()
  • replacement in inflorescence/src/main.rs at line 279
    [42.24554][42.24554:24619]()
    && let Some(_ready_state) = model::ready(&mut state.sub)
    [42.24554]
    [42.24619]
    && !action::is_allowed(&state.sub.allowed_actions, msg)
  • replacement in inflorescence/src/main.rs at line 281
    [42.24625][42.24625:25016]()
    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();
    }
    [42.24625]
    [42.25016]
    // dbg!("Action not allowed", msg);
    // dbg!(&state.sub.allowed_actions);
    return Task::none();
  • replacement in inflorescence/src/main.rs at line 293
    [42.25307][42.25307:25357]()
    }) = model::ready_mut(&mut state.sub)
    [42.25307]
    [42.25357]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 303
    [42.25555][42.25555:25571]()
    match msg {
    [42.25555]
    [42.25571]
    let task = match msg {
  • replacement in inflorescence/src/main.rs at line 311
    [40.83140][40.83140:83190]()
    }) = model::ready_mut(&mut state.sub)
    [40.83140]
    [40.83190]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 356
    [40.84007][40.84007:84057]()
    }) = model::ready_mut(&mut state.sub)
    [40.84007]
    [35.18722]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 384
    [40.84946][40.84946:84996]()
    }) = model::ready_mut(&mut state.sub)
    [40.84946]
    [40.84996]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 386
    [40.85010][40.85010:85052]()
    return selection::update(
    [40.85010]
    [40.85052]
    selection::update(
  • replacement in inflorescence/src/main.rs at line 393
    [40.85230][40.85230:85249]()
    );
    [40.85230]
    [40.85249]
    )
    } else {
    Task::none()
  • edit in inflorescence/src/main.rs at line 397
    [40.85263][40.85263:85288]()
    Task::none()
  • replacement in inflorescence/src/main.rs at line 407
    [42.26154][42.26154:26204]()
    }) = model::ready_mut(&mut state.sub)
    [42.26154]
    [42.26204]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 418
    [40.85578][40.85578:85628]()
    }) = model::ready_mut(&mut state.sub)
    [40.85578]
    [40.85628]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 421
    [40.85703][36.7564:7614](),[36.7564][36.7564:7614]()
    return task::widget_focus_next();
    [40.85703]
    [35.19115]
    task::widget_focus_next()
    } else {
    Task::none()
  • edit in inflorescence/src/main.rs at line 425
    [35.19129][35.19129:19154]()
    Task::none()
  • replacement in inflorescence/src/main.rs at line 436
    [40.85988][40.85988:86038]()
    }) = model::ready_mut(&mut state.sub)
    [40.85988]
    [40.86038]
    }) = model::is_ready_mut(&mut state.sub)
  • edit in inflorescence/src/main.rs at line 451
    [38.46253]
    [38.46253]
    }
    };
    #[cfg(debug_assertions)]
    {
    // Check that selection coreesponds to the navigation state
    if let Some(ReadyState {
    selection,
    navigation,
    ..
    }) = model::is_ready(&state.sub)
    {
    let selection::State {
    primary: _,
    status,
    channel,
    entire_log,
    held_key: _,
    } = selection;
    if let Some(selection) = status {
    match selection {
    selection::Status::UntrackedFile { .. } => {}
    selection::Status::ChangedFile { .. } => {}
    selection::Status::LogChange(selection::LogChange {
    hash,
    file,
    ..
    }) => {
    if let Some(selection::LogChangeFileSelection {
    path,
    ..
    }) = file
    {
    assert_eq!(
    navigation.status_logs_navs.change_hash,
    Some(*hash)
    );
    assert_eq!(
    navigation.status_logs_navs.file_id,
    Some(file::log_id_parts_hash(*hash, path))
    );
    } else {
    assert_eq!(
    navigation.status_logs_navs.change_hash,
    Some(*hash)
    );
    }
    }
    }
    }
    if let Some(selection::Channel { name, log, .. }) = channel {
    assert_eq!(navigation.other_channel_name.as_ref(), Some(name));
    match log {
    None => {}
    Some(selection::LogChange {
    hash, file: None, ..
    }) => {
    assert_eq!(
    navigation.other_channel_logs_navs.change_hash,
    Some(*hash)
    );
    }
    Some(selection::LogChange {
    hash,
    file:
    Some(selection::LogChangeFileSelection { path, .. }),
    ..
    }) => {
    assert_eq!(
    navigation.other_channel_logs_navs.change_hash,
    Some(*hash)
    );
    assert_eq!(
    navigation.other_channel_logs_navs.file_id,
    Some(file::log_id_parts_hash(*hash, path))
    );
    }
    }
    }
    if let Some(selection::LogChange { hash, file, .. }) = entire_log {
    assert_eq!(
    navigation.entire_logs_navs.change_hash,
    Some(*hash)
    );
    if let Some(selection::LogChangeFileSelection {
    path, ..
    }) = file
    {
    assert_eq!(
    navigation.entire_logs_navs.change_hash,
    Some(*hash)
    );
    assert_eq!(
    navigation.entire_logs_navs.file_id,
    Some(file::log_id_parts_hash(*hash, path))
    );
    } else {
    assert_eq!(
    navigation.entire_logs_navs.change_hash,
    Some(*hash)
    );
    }
    }
  • edit in inflorescence/src/main.rs at line 559
    [14.856]
    [14.856]
    task
  • replacement in inflorescence/src/main.rs at line 589
    [40.86701][40.86701:86743]()
    }) = model::ready_mut(&mut state.sub)
    [40.86701]
    [35.19196]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 642
    [40.87603][40.87603:87645]()
    }) = model::ready_mut(&mut state.sub)
    [40.87603]
    [35.19814]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 701
    [40.88554][40.88554:88596]()
    }) = model::ready_mut(&mut state.sub)
    [40.88554]
    [40.88596]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 732
    [40.88931][40.88931:88973]()
    }) = model::ready_mut(&mut state.sub)
    [40.88931]
    [40.88973]
    }) = model::is_ready_mut(&mut state.sub)
  • edit in inflorescence/src/main.rs at line 745
    [40.89079][40.89079:89099]()
    navigation,
  • replacement in inflorescence/src/main.rs at line 746
    [40.89110][40.89110:89152]()
    }) = model::ready_mut(&mut state.sub)
    [40.89110]
    [41.10764]
    }) = model::is_ready_mut(&mut state.sub)
  • edit in inflorescence/src/main.rs at line 764
    [41.11367][41.11367:11570]()
    // Status view fields
    navigation.files_diffs.diffs_nav = None;
    navigation.status_logs_navs.files_nav = None;
    navigation.status_logs_navs.diffs_nav = None;
  • replacement in inflorescence/src/main.rs at line 773
    [40.90170][40.90170:90211]()
    model::ready_mut(&mut state.sub)
    [40.90170]
    [41.11636]
    model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 788
    [40.90552][40.90552:90593]()
    model::ready_mut(&mut state.sub)
    [40.90552]
    [41.11887]
    model::is_ready_mut(&mut state.sub)
  • edit in inflorescence/src/main.rs at line 1122
    [40.96397][40.96397:96416]()
    selection,
  • replacement in inflorescence/src/main.rs at line 1123
    [40.96436][40.96436:96450]()
    logs,
    [40.96436]
    [40.96450]
    selection,
  • replacement in inflorescence/src/main.rs at line 1125
    [40.96461][40.96461:96503]()
    }) = model::ready_mut(&mut state.sub)
    [40.96461]
    [40.96503]
    }) = model::is_ready_mut(&mut state.sub)
  • replacement in inflorescence/src/main.rs at line 1136
    [38.50369][38.50369:50433]()
    let id_hash = file::log_id_parts_hash(hash, &path);
    [38.50369]
    [38.50433]
    let file_id = file::log_id_parts_hash(hash, &path);
  • replacement in inflorescence/src/main.rs at line 1144
    [38.50714][40.96580:96651]()
    navigation.log_diffs.diffs.insert(id_hash, log_file_diff);
    [38.50714]
    [38.50782]
    navigation.log_diffs.diffs.insert(file_id, log_file_diff);
  • replacement in inflorescence/src/main.rs at line 1147
    [40.96653][40.96653:96697]()
    match selection::unify(selection) {
    [40.96653]
    [40.96697]
    // If a file is selected, init the nav for its diff
    let selected_file_and_its_navs = match selection::unify(selection) {
  • replacement in inflorescence/src/main.rs at line 1156
    [40.96955][40.96955:97351](),[38.51529][33.13321:13322](),[40.97351][33.13321:13322](),[33.13321][33.13321:13322](),[33.13322][40.97352:97618](),[39.21381][38.52081:52082](),[40.97618][38.52081:52082](),[38.52081][38.52081:52082](),[38.52082][40.97619:97748](),[40.97748][38.52295:52309](),[38.52295][38.52295:52309]()
    ))) => {
    if *selected_hash != hash {
    return Task::none();
    }
    if let Some(file) = file.as_ref() {
    // If a file is selected, init the nav for its diff
    let diffs_nav = nav_scrollable::State::default();
    let id_hash = file::log_id_parts_hash(hash, &file.path);
    navigation.status_logs_navs.diffs_nav =
    Some((id_hash, diffs_nav));
    } else {
    // Init scrollable nav for log files
    let changes_nav = nav_scrollable::State::default();
    navigation.status_logs_navs.files_nav =
    Some((hash, changes_nav));
    }
    }
    [40.96955]
    [40.97749]
    ))) if *selected_hash == hash => file
    .as_ref()
    .map(|file| (file, &mut navigation.status_logs_navs)),
  • replacement in inflorescence/src/main.rs at line 1164
    [38.52935][40.97908:98032](),[38.53140][33.14135:14136](),[40.98032][33.14135:14136](),[33.14135][33.14135:14136](),[33.14136][40.98033:98855]()
    })) => {
    if *selected_hash != hash {
    return Task::none();
    }
    let Some(Log::Loaded { .. }) = logs.entire_log.as_ref() else {
    return Task::none();
    };
    if let Some(file) = file.as_ref() {
    // If a file is selected, init the nav for its diff
    let diffs_nav = nav_scrollable::State::default();
    let id_hash = file::log_id_parts_hash(hash, &file.path);
    navigation.entire_logs_navs.diffs_nav =
    Some((id_hash, diffs_nav));
    } else {
    // Init scrollable nav for log files
    let changes_nav = nav_scrollable::State::default();
    navigation.entire_logs_navs.files_nav =
    Some((hash, changes_nav));
    };
    }
    [38.52935]
    [40.98855]
    })) if *selected_hash == hash => file
    .as_ref()
    .map(|file| (file, &mut navigation.entire_logs_navs)),
  • replacement in inflorescence/src/main.rs at line 1169
    [40.98944][40.98944:98966]()
    name,
    [40.98944]
    [40.98966]
    name: _,
  • replacement in inflorescence/src/main.rs at line 1177
    [40.99201][40.99201:99325]()
    })) => {
    if *selected_hash != hash {
    return Task::none();
    }
    [40.99201]
    [40.99325]
    })) if *selected_hash == hash => file
    .as_ref()
    .map(|file| (file, &mut navigation.other_channel_logs_navs)),
    selection::Unified::Status(_)
    | selection::Unified::Channel(_)
    | selection::Unified::EntireLog(_) => None,
    };
  • replacement in inflorescence/src/main.rs at line 1185
    [40.99326][40.99326:100323]()
    let Some(Log::Loaded { .. }) =
    logs.other_channels_logs.get(name)
    else {
    return Task::none();
    };
    if let Some((selected_name, navs)) =
    navigation.other_channel_log_navs.as_mut()
    && name == selected_name
    {
    if let Some(file) = file.as_ref() {
    // If a file is selected, init the nav for its diff
    let diffs_nav = nav_scrollable::State::default();
    let id_hash = file::log_id_parts_hash(hash, &file.path);
    navs.diffs_nav = Some((id_hash, diffs_nav));
    } else {
    // Init scrollable nav for log files
    let changes_nav = nav_scrollable::State::default();
    navs.files_nav = Some((hash, changes_nav));
    };
    }
    [40.99326]
    [40.100323]
    if let Some((file, navs)) = selected_file_and_its_navs {
    let file_id = file::log_id_parts_hash(hash, &file.path);
    if let Some(log) = navigation.log_diffs.diffs.get(&file_id) {
    let unchanged_sections = diff::unchanged_sections(&log.file);
    log::init_diffs_nav(navs, file_id)
    .set_skip_sections(unchanged_sections);
  • edit in inflorescence/src/main.rs at line 1192
    [40.100337][40.100337:100357]()
    _ => {}
  • replacement in inflorescence/src/main.rs at line 1198
    [38.53345][40.100386:100464]()
    if let Some(ReadyState { logs, .. }) = model::ready_mut(&mut state.sub) {
    [38.53345]
    [40.100464]
    if let Some(ReadyState { logs, .. }) = model::is_ready_mut(&mut state.sub) {
  • replacement in inflorescence/src/main.rs at line 1209
    [40.100663][40.100663:101097](),[39.21752][38.54189:54199](),[40.101097][38.54189:54199](),[38.54189][38.54189:54199](),[38.54199][40.101098:101099]()
    if let Some(ReadyState {
    navigation,
    selection,
    logs,
    ..
    }) = model::ready_mut(&mut state.sub)
    {
    if let Some(selection::Channel {
    name: selection_name,
    ..
    }) = selection.channel.as_ref()
    && selection_name == &channel
    {
    navigation.other_channel_log_navs =
    Some((channel.clone(), log::Navs::default()));
    }
    [40.100663]
    [40.101099]
    if let Some(ReadyState { logs, .. }) = model::is_ready_mut(&mut state.sub) {
  • replacement in inflorescence/src/log.rs at line 4
    [40.101378][40.101378:101418]()
    pub use inflorescence_model::log::Navs;
    [40.101378]
    [40.101418]
    pub use inflorescence_model::log::{init_diffs_nav, init_files_nav, Navs};
  • edit in inflorescence/src/log.rs at line 6
    [40.101419][40.101419:101436]()
    use crate::file;
  • replacement in inflorescence/src/log.rs at line 8
    [40.101475][40.101475:101749]()
    pub fn log_diff_needs_scrolling(logs: &Navs, id_hash: file::LogIdHash) -> bool {
    logs.diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    .map(nav_scrollable::needs_scrolling)
    .unwrap_or_default()
    [40.101475]
    [40.101749]
    pub fn diff_needs_scrolling(logs: &Navs) -> bool {
    nav_scrollable::needs_scrolling(&logs.diffs_nav)
  • edit in inflorescence/src/file.rs at line 6
    [40.101855][40.101855:101870]()
    LogIdHash,
  • replacement in inflorescence/src/file.rs at line 19
    [7.2060][7.2060:2125]()
    use tokio::sync::watch;
    use tokio_stream::wrappers::WatchStream;
    [7.2044]
    [7.2125]
    use tokio::sync::mpsc;
    use tokio_stream::wrappers::UnboundedReceiverStream;
  • replacement in inflorescence/src/file.rs at line 28
    [7.2283][7.2283:2333]()
    pub file_load_tx: watch::Sender<(Id, usize)>,
    [7.2283]
    [7.2333]
    // TODO watch bad, it has to queue things!
    pub file_load_tx: mpsc::UnboundedSender<(Id, usize)>,
  • replacement in inflorescence/src/file.rs at line 59
    [7.3284][7.3284:3537]()
    let (src_file_load_tx, src_file_load_rx) = watch::channel((
    Id {
    path: "".to_string(),
    file_kind: Kind::Untracked,
    },
    0,
    ));
    let src_file_load_rx = WatchStream::from_changes(src_file_load_rx);
    [7.3284]
    [7.3537]
    let (src_file_load_tx, src_file_load_rx) = mpsc::unbounded_channel();
    let src_file_load_rx = UnboundedReceiverStream::from(src_file_load_rx);
  • edit in inflorescence/src/file.rs at line 67
    [7.3795]
    [7.3795]
    dbg!("LOAD", &id);
  • replacement in inflorescence/src/file.rs at line 92
    [25.7756][27.18899:18924]()
    pub id_hash: IdHash,
    [25.7756]
    [26.630]
    pub file_id: IdHash,
  • replacement in inflorescence/src/file.rs at line 131
    [26.836][27.19008:19045]()
    id_hash,
    [26.836]
    [26.912]
    file_id: id_hash,
  • replacement in inflorescence/src/file.rs at line 150
    [40.102466][40.102466:102503]()
    id_hash,
    [40.102466]
    [40.102503]
    file_id: id_hash,
  • edit in inflorescence/src/file.rs at line 155
    [7.5922]
    [7.5922]
    } else {
    // Reload for a new cache counter
    state
    .file_load_tx
    .send((id, state.diffs_cache.counter))
    .unwrap();
  • replacement in inflorescence/src/diff.rs at line 5
    [40.102633][13.1781:1845](),[13.1781][13.1781:1845]()
    contents_to_lines, Combined, DecodedFile, DiffWithContents,
    [40.102633]
    [40.102634]
    contents_to_lines, init_diffs_nav, Combined, DecodedFile, DiffWithContents,
  • edit in inflorescence/src/diff.rs at line 10
    [8.732][27.19675:19692]()
    use crate::file;
  • replacement in inflorescence/src/diff.rs at line 157
    [27.20128][27.20128:20192](),[27.20192][33.20317:20344](),[33.20344][27.20214:20226](),[27.20214][27.20214:20226](),[27.20226][39.22540:22575](),[39.22769][39.22769:22943]()
    pub fn file_diff_needs_scrolling(
    files_diffs: &FilesState,
    id_hash: file::IdHash,
    ) -> bool {
    files_diffs
    .diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav))
    .map(nav_scrollable::needs_scrolling)
    .unwrap_or_default()
    [27.20128]
    [26.1917]
    pub fn file_diff_needs_scrolling(files_diffs: &FilesState) -> bool {
    nav_scrollable::needs_scrolling(&files_diffs.diffs_nav)
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 138
    [39.32074]
    [39.32074]
    pub fn has_sections(state: &State) -> bool {
    !state.inner.borrow().section_heights.is_empty()
    }
  • edit in iced_expl_widget/src/nav_scrollable.rs at line 621
    [39.48198]
    [39.48198]
    }
    pub fn set_skip_sections(&mut self, skip_sections: HashSet<usize>) {
    let Self { inner } = self;
    let mut inner = inner.borrow_mut();
    inner.skip_sections = skip_sections;