entire log!

[?]
Jul 29, 2025, 8:24 PM
OJPGHVC3RFBQ7TTSCZH6URSSATII3TESD74EISDNOTNXXSX7PQMAC

Dependencies

  • [2] SWWE2R6M display basic repo stuff
  • [3] WT3GA27P add cursor with selection
  • [4] UB2ITZJS refresh changed files on FS changes
  • [5] YBJRDOTC make all repo actions async
  • [6] AMPZ2BXK show changed files diffs (only Edit atm)
  • [7] V55EAIWQ add src file LRU cache
  • [8] Y5ATDI2H convert changed file diffs and load src only if any needs it
  • [9] ZVI4AWER woot contents_diff
  • [10] OQ6HSAWH show record log
  • [11] ONRCENKT rm unnecessary state from repo's internal state
  • [12] 4ELJZGRJ load and store all change diffs at once
  • [13] FR52XEMW add action for log change file diff
  • [14] L6KSEFQI move cursor related stuff into its module
  • [15] BFN2VHZS refactor file stuff into sub-mod
  • [16] 23SFYK4Q big view refactor into a new crate
  • [17] MYGIBRRH wip custom theme
  • [18] XSZZB47U refactor stuff into lib
  • [19] ACDXXAX2 refactor main's updates into smaller fns
  • [20] 7SSBM4UQ view: refactor repo view
  • [21] FL2ULDJN test record
  • [22] S2T7RUKW add nav back placeholder
  • [23] I2AG42PA new cols layout
  • [24] SK3WVX7A add wee spacing for nav back
  • [25] SASAN2XC use nav-scrollable
  • [26] YKHE3XMW refactor diffs handling
  • [27] KEPKF3WO unify diffs handling, simplify view
  • [28] KWTBNTO3 diffs selection and scrolling
  • [29] 5MUEECMJ smooth scrolling nav
  • [30] 3TLPJ57B alt scroll via context and couple fixes
  • [31] BNHJU2DU clippy fixes
  • [32] KQABQCCZ update rust to 1.88
  • [33] AI3IMKC3 refactor stairs
  • [34] WXQBBQ2A update nightly
  • [35] 65DXFP3Y fix status overflow
  • [36] DST3HRZZ fix emoji rendering
  • [37] PTWZYQFR use nav-scrollable for repo status
  • [38] RDRBP7AL auto-scroll status selection
  • [39] 4G6DZDO6 rename diff msg for nav-scrollable
  • [40] UR4J677R nav for log changes and refactors
  • [41] K63JN6CR refactor out non-view field from cursor
  • [42] C5P3JIFC refactor out the nav-scrollable children len arg
  • [43] GYZWZ33T fix unwraps on navs for view
  • [44] A6Z4O6RC actions menu
  • [45] 7BLZN73O add a key to refresh repo
  • [46] JZXYSIYD channel selection!
  • [47] 5ZRDYL6K fork channel, fix recording esc key
  • [48] BAUK5BON pimp-up action buttons
  • [49] NZD56PVB fix mouse selection
  • [50] D7A7MSIH allow to defer or abandon record, add buttons
  • [51] NRCUG4R2 load changed files src when selected
  • [52] ESMM3FEL test selection reindexing
  • [53] 4WO3ZJM2 show untracked files' contents
  • [54] I56UGW7U make record test, fix log update
  • [55] GOLHUD6R nav-scrollable: set skip-able sections
  • [56] UF5NJKAS test load repo
  • [57] FVA36HBV restart repo manager task if it crashes
  • [58] 3BK22XE5 add a test for hover btn and more refactors
  • [59] KM5PSZ4A watch repo once loaded
  • [60] EC3TVL4X add untracked files
  • [*] 6YZAVBWU Initial commit
  • [*] MJDGPSHG WIP contents diff
  • [*] WW36JYLR add iced_nav_scrollable widget crate

Change contents

  • edit in libflorescence/src/repo.rs at line 150
    [47.31]
    [2.466]
    LoadEntireLog,
  • edit in libflorescence/src/repo.rs at line 169
    [12.140]
    [5.723]
    LoadedEntireLog(Log),
  • edit in libflorescence/src/repo.rs at line 322
    [47.436]
    [47.436]
    }
    MsgIn::LoadEntireLog => {
    let log: Log;
    (internal_state, log) = spawn_blocking(move || {
    let log = get_log(&internal_state.repo, None, None);
    (internal_state, log)
    })
    .await
    .unwrap();
    let _ = msg_out_tx.send(MsgOut::LoadedEntireLog(log));
  • replacement in libflorescence/src/repo.rs at line 348
    [10.359][11.1891:1931]()
    let log = log(repo, offset, limit);
    [10.359]
    [11.1931]
    let log = get_log(repo, offset, limit);
  • replacement in libflorescence/src/repo.rs at line 883
    [10.416][21.238:257]()
    pub(crate) fn log(
    [10.416]
    [10.424]
    pub(crate) fn get_log(
  • edit in inflorescence_view/src/selection.rs at line 29
    [46.2808]
    [29.359]
    pub entire_log: Option<LogChange>,
  • replacement in inflorescence_view/src/selection.rs at line 50
    [18.3561][18.3561:3596](),[18.3596][40.952:984](),[40.984][18.3623:3648](),[18.3623][18.3623:3648](),[18.3951][18.3951:4004]()
    LogChange {
    ix: usize,
    hash: repo::ChangeHash,
    message: String,
    file: Option<LogChangeFileSelection>,
    },
    [18.3561]
    [18.4004]
    LogChange(LogChange),
  • replacement in inflorescence_view/src/selection.rs at line 81
    [46.2829][46.2829:2853]()
    #[derive(Debug, Clone)]
    [46.2829]
    [46.2853]
    #[derive(Debug)]
  • edit in inflorescence_view/src/selection.rs at line 86
    [46.2917]
    #[derive(Debug)]
    pub struct LogChange {
    pub ix: usize,
    pub hash: repo::ChangeHash,
    pub message: String,
    pub file: Option<LogChangeFileSelection>,
    }
  • edit in inflorescence_view/src/app.rs at line 34
    [46.3175]
    [16.12996]
    pub entire_log_selection: Option<EntireLogSelection<'a>>,
  • replacement in inflorescence_view/src/app.rs at line 41
    [37.1166][37.1166:1217]()
    /// changed files and most recent log changes.
    [37.1166]
    [37.1217]
    /// changed files and most recent log changes
  • replacement in inflorescence_view/src/app.rs at line 43
    [37.1252][47.2817:2877]()
    /// `true` when we're selecting a channel to switch to.
    [37.1252]
    [46.3236]
    /// `true` when we're selecting a channel to switch to
  • replacement in inflorescence_view/src/app.rs at line 45
    [46.3269][47.2878:2938]()
    /// `Some` when we're selecting a channel to switch to.
    [46.3269]
    [47.2938]
    /// `Some` when we're selecting a channel to switch to
  • edit in inflorescence_view/src/app.rs at line 47
    [47.2979]
    [40.1134]
    /// `Some` when looking at the entire log of changes
    pub entire_log: Option<EntireLog>,
  • edit in inflorescence_view/src/app.rs at line 88
    [40.1861]
    [16.12999]
    #[derive(Debug)]
    pub enum EntireLog {
    Loading,
    LoadingButNotViewing,
    Got {
    log: repo::Log,
    nav: Box<NavScrollable>,
    },
    NotViewing {
    log: repo::Log,
    nav_stored_offset: Option<f32>,
    },
    }
    #[derive(Debug)]
    pub struct EntireLogSelection<'a> {
    pub ix: usize,
    pub hash: repo::ChangeHash,
    pub message: &'a str,
    pub file: Option<LogChangeFileSelection<'a>>,
    pub nav: Option<&'a NavScrollable>,
    }
  • replacement in inflorescence_view/src/app.rs at line 118
    [37.1297][40.1862:1907]()
    LogNav {
    hash: repo::ChangeHash,
    [37.1297]
    [40.1907]
    LogChangeNav {
    change: repo::ChangeHash,
  • edit in inflorescence_view/src/app.rs at line 144
    [45.45]
    [16.15355]
    EntireLog,
    EntireLogNav(iced_nav_scrollable::Msg),
    EntireLogChangeNav {
    change: repo::ChangeHash,
    msg: iced_nav_scrollable::Msg,
    },
  • edit in inflorescence_view/src/app.rs at line 169
    [46.3477]
    [40.2300]
    entire_log_selection,
  • edit in inflorescence_view/src/app.rs at line 179
    [46.3648]
    [46.3648]
    entire_log_selection,
  • edit in inflorescence_view/src/app.rs at line 199
    [46.3837]
    [40.2661]
    entire_log_selection: Option<EntireLogSelection<'a>>,
  • edit in inflorescence_view/src/app.rs at line 214
    [47.3052]
    [37.1485]
    entire_log,
  • replacement in inflorescence_view/src/app.rs at line 219
    [37.1500][40.2886:2948](),[40.2948][46.3956:4153]()
    let view_repo_info = el(row([
    el(text(dir_name)),
    el(text(", channel: ")),
    el(button(text(channel))
    .on_press_maybe(can_switch_channel.then_some(Msg::SwitchChannel))),
    ])
    .align_y(alignment::Vertical::Center));
    [37.1500]
    [20.670]
    let view_repo_info = || {
    el(row([
    el(text(dir_name)),
    el(text(", channel: ")),
    el(button(text(channel)).on_press_maybe(
    can_switch_channel.then_some(Msg::SwitchChannel),
    )),
    ])
    .align_y(alignment::Vertical::Center))
    };
  • replacement in inflorescence_view/src/app.rs at line 269
    [16.17369][40.3362:3386]()
    let view_log = || {
    [16.17369]
    [40.3386]
    let view_status_log = || {
  • replacement in inflorescence_view/src/app.rs at line 271
    [20.943][16.17447:17641](),[37.1670][16.17447:17641](),[40.3422][16.17447:17641](),[16.17447][16.17447:17641]()
    |(ix, repo::LogEntry {
    hash,
    message,
    file_paths: _,
    })| {
    let short_hash = display_short_hash(hash);
    [40.3422]
    [46.4822]
    |(
    ix,
    entry,
    )| {
  • replacement in inflorescence_view/src/app.rs at line 278
    [16.17837][16.17837:17932](),[16.17932][46.4986:5163](),[46.5163][16.18100:18128](),[16.18100][16.18100:18128](),[16.18128][17.7899:7970](),[17.7970][36.137:209](),[36.209][16.18238:18292](),[16.18238][16.18238:18292]()
    el(row([
    el(button(text(short_hash).font(Font::MONOSPACE))
    .on_press(Msg::Selection(selection::Msg::Select(
    selection::Select::LogChange { ix, hash: *hash, message: message.clone() },
    )))
    .class(selectable_button_class(is_selected))),
    el(text(message).shaping(text::Shaping::Advanced)),
    ])
    .spacing(SPACING))
    [16.17837]
    [16.18292]
    view_log_change(ix, entry, is_selected)
  • replacement in inflorescence_view/src/app.rs at line 283
    [20.952][40.3494:3522]()
    let record_msg_editor =
    [20.952]
    [40.3522]
    let record_msg_editor = || {
  • replacement in inflorescence_view/src/app.rs at line 297
    [40.4105][40.4105:4116]()
    };
    [40.4105]
    [16.18330]
    }
    };
  • replacement in inflorescence_view/src/app.rs at line 300
    [16.18331][46.5164:5226]()
    let selection_details = match status_selection.as_ref() {
    [16.18331]
    [46.5226]
    let selection_details = || match status_selection.as_ref() {
  • edit in inflorescence_view/src/app.rs at line 356
    [40.5089]
    [40.5149]
    let change_selected = match file.as_ref() {
    Some(LogChangeFileSelection { diff, .. }) => !diff
    .as_ref()
    .map(|diff| diff.is_selected)
    .unwrap_or_default(),
    _ => false,
    };
  • replacement in inflorescence_view/src/app.rs at line 365
    [40.5236][40.5236:5372](),[40.5372][16.21803:21869](),[16.21803][16.21803:21869](),[16.21869][46.5381:5505](),[46.5505][17.7971:8039](),[16.21984][17.7971:8039](),[17.8039][16.22052:22072](),[16.22052][16.22052:22072]()
    let is_selected = matches!(file, Some(LogChangeFileSelection{ path: selected_path, .. }) if selected_path == path);
    el(button(text(path)).on_press_with(move || {
    Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))
    }).class(selectable_button_class(is_selected)))
    });
    [40.5236]
    [40.5373]
    let is_selected = matches!(file, Some(LogChangeFileSelection{ path: selected_path, .. }) if selected_path == path);
    el(button(text(path)).on_press_with(move || {
    Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))
    }).class(selectable_button_class(is_selected)))
    });
  • replacement in inflorescence_view/src/app.rs at line 372
    [42.309][42.309:359]()
    Msg::LogNav { hash, msg }
    [42.309]
    [42.359]
    Msg::LogChangeNav { change: hash, msg }
    })
    .class(if change_selected {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
  • edit in inflorescence_view/src/app.rs at line 407
    [23.1006]
    [46.5506]
    } else if let Some(EntireLogSelection { file, .. }) =
    entire_log_selection.as_ref()
    {
    if file.is_none() {
    1
    } else {
    2
    }
  • replacement in inflorescence_view/src/app.rs at line 434
    [23.1588][37.1735:1817](),[37.1817][40.6140:6179](),[40.6179][37.1851:1896](),[37.1851][37.1851:1896](),[37.1896][40.6180:6217](),[40.6217][37.1928:1974](),[37.1928][37.1928:1974](),[37.1974][40.6218:6246]()
    let status_nav_children = [el(text("Untracked files:"))]
    .into_iter()
    .chain(view_untracked_files())
    .chain([el(text("Changed files:"))])
    .chain(view_changed_files())
    .chain([el(text("Recent changes:"))])
    .chain(view_log());
    [23.1588]
    [37.2064]
    let status_nav_children = || {
    [el(text("Untracked files:"))]
    .into_iter()
    .chain(view_untracked_files())
    .chain([el(text("Changed files:"))])
    .chain(view_changed_files())
    .chain([el(text("Recent changes:"))])
    .chain(view_status_log())
    };
  • replacement in inflorescence_view/src/app.rs at line 444
    [37.2065][46.5793:5853]()
    let status_selected = match status_selection.as_ref() {
    [37.2065]
    [46.5853]
    let status_selected = || match status_selection.as_ref() {
  • edit in inflorescence_view/src/app.rs at line 456
    [37.2065][23.1588:1616](),[40.6780][23.1588:1616](),[23.1588][23.1588:1616](),[23.1616][40.6781:6805](),[40.6805][37.2066:2161](),[23.1635][37.2066:2161](),[37.2198][37.2198:2226](),[37.2226][40.6806:6960](),[35.281][23.1831:1891](),[37.2238][23.1831:1891](),[40.6960][23.1831:1891](),[23.1831][23.1831:1891]()
    let col_0 = el(column([
    view_repo_info,
    el(iced_nav_scrollable::view(
    status_nav,
    status_nav_children,
    Msg::StatusNav,
    )
    .class(if status_selected {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })),
    ])
    .width(Length::Fill)
    .height(Length::Fill));
  • replacement in inflorescence_view/src/app.rs at line 457
    [23.1892][23.1892:1978]()
    let col_1 = el(column([
    el(column([record_msg_editor, selection_details])
    [23.1892]
    [23.1978]
    let status_col_0 = || {
    el(column([
    view_repo_info(),
    el(iced_nav_scrollable::view(
    status_nav,
    status_nav_children(),
    Msg::StatusNav,
    )
    .class(if status_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
  • replacement in inflorescence_view/src/app.rs at line 472
    [23.2047][23.2047:2077](),[23.2077][44.1558:1674](),[44.1674][46.6055:6173](),[29.526][23.2268:2352](),[46.6173][23.2268:2352](),[23.2268][23.2268:2352](),[23.2352][24.28:78]()
    if hidden_cols == 1 {
    el(button(row([el(
    text("← Status").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Selection(selection::Msg::PressDir(
    selection::Dir::Left,
    ))))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING));
    [23.2047]
    [23.2380]
    ])
    .width(Length::Fill)
    .height(Length::Fill))
    };
  • replacement in inflorescence_view/src/app.rs at line 477
    [23.2381][46.6174:6224]()
    let col_2 = match status_selection.as_ref() {
    [23.2381]
    [46.6224]
    let status_col_1 = || {
    el(column([
    el(column([record_msg_editor(), selection_details()])
    .width(Length::Fill)
    .height(Length::Fill)),
    if hidden_cols == 1 {
    el(button(row([el(
    text("← Status").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Selection(
    selection::Msg::PressDir(selection::Dir::Left),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    };
    let status_col_2 = || match status_selection.as_ref() {
  • edit in inflorescence_view/src/app.rs at line 529
    [22.314][28.7338:7411]()
    // .width(Length::Fill)
    // .height(Length::Fill)
  • replacement in inflorescence_view/src/app.rs at line 533
    [27.1983][27.1983:2132]()
    el(button(row([
    el(text("← ").font(Font::MONOSPACE)),
    el(text("Log")),
    ]))
    [27.1983]
    [46.6261]
    el(button(row([el(
    text("← Files").shaping(text::Shaping::Advanced)
    )]))
  • edit in inflorescence_view/src/app.rs at line 551
    [27.2539]
    [27.2539]
    };
    let entire_log_selected = || match entire_log_selection.as_ref() {
    Some(EntireLogSelection { file, .. }) => file.is_none(),
    None => false,
    };
    let entire_log_change_selected = || match entire_log_selection.as_ref() {
    Some(EntireLogSelection {
    file: Some(LogChangeFileSelection { diff, .. }),
    ..
    }) => !diff
    .as_ref()
    .map(|diff| diff.is_selected)
    .unwrap_or_default(),
    _ => false,
    };
    let entire_log_col_0 = || {
    let Some(EntireLog::Got { log, nav }) = entire_log.as_ref() else {
    unreachable!()
    };
    let entries = log.iter().enumerate().map(|(ix, entry)| {
    let is_selected = matches!(entire_log_selection.as_ref(),
    Some(EntireLogSelection { ix: selected_ix, .. }) if &ix == selected_ix
    );
    view_log_change(ix, entry, is_selected)
    });
    let len = log.len();
    let selected_ix = entire_log_selection
    .as_ref()
    .map(|EntireLogSelection { ix, .. }| len - *ix);
    el(column([
    view_repo_info(),
    if let Some(selected_ix) = selected_ix {
    el(text(format!("Entire log ({selected_ix}/{len})")))
    } else {
    el(text(format!("Entire log ({len})")))
    },
    el(iced_nav_scrollable::view(nav, entries, Msg::EntireLogNav)
    .class(if entire_log_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill)),
    ])
    .width(Length::Fill)
    .height(Length::Fill))
  • edit in inflorescence_view/src/app.rs at line 603
    [27.2546]
    [16.24230]
    let entire_log_col_1 = || {
    let files_view = match entire_log_selection.as_ref() {
    Some(EntireLogSelection {
    ix,
    hash,
    message,
    file,
    nav,
    }) => {
    let short_hash = display_short_hash(hash);
    let view = match (nav.as_ref(), entire_log.as_ref()) {
    (Some(nav), Some(EntireLog::Got { log, nav: _ })) => {
    let entry = log.get(*ix).unwrap();
    let files = entry.file_paths.iter().enumerate().map(|(ix, path)| {
    let is_selected = matches!(file, Some(LogChangeFileSelection{ path: selected_path, .. }) if selected_path == path);
    el(button(text(path)).on_press_with(move || {
    Msg::Selection(selection::Msg::Select(selection::Select::LogChangeFile { ix, path: path.clone() }))
    }).class(selectable_button_class(is_selected)))
    });
    let hash = *hash;
    el(iced_nav_scrollable::view(nav, files, move |msg| {
    Msg::LogChangeNav { change: hash, msg }
    })
    .class(if entire_log_change_selected() {
    theme::Scrollable::Selected
    } else {
    theme::Scrollable::Normal
    })
    .width(Length::Fill)
    .height(Length::Fill))
    }
    _ => el(text("Loading...")),
    };
  • edit in inflorescence_view/src/app.rs at line 639
    [16.24231]
    [46.6521]
    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))
    }
    None => el(row([])),
    };
    el(column([
    files_view,
    if hidden_cols == 1 {
    el(button(row([el(
    text("← Log").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Selection(
    selection::Msg::PressDir(selection::Dir::Left),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))
    };
    let entire_log_col_2 = || match entire_log_selection.as_ref() {
    Some(EntireLogSelection {
    ix: _,
    hash,
    message: _,
    file: Some(LogChangeFileSelection { ix: _, path, diff }),
    nav: _,
    }) => Some(el(column([
    el(column([
    view_diff_header(format!(
    "{path} changes in {}:",
    display_short_hash(hash)
    )),
    match diff {
    Some(Diff {
    is_selected,
    file,
    state,
    nav,
    }) => {
    let id_hash = file::log_id_parts_hash(*hash, path);
    diff::view(state, nav, file, *is_selected).map(
    move |action| Msg::LogChangeFileDiff {
    id_hash,
    msg: action,
    },
    )
    }
    None => el(text("Loading diff..")),
    },
    ])
    .spacing(SPACING)),
    // NOTE: This is currently never true - there are only up to 3
    // cols
    if hidden_cols == 2 {
    el(button(row([el(
    text("← Files").shaping(text::Shaping::Advanced)
    )]))
    .on_press(Msg::Selection(
    selection::Msg::PressDir(selection::Dir::Left),
    )))
    } else {
    el(row([]))
    },
    ])
    .width(Length::Fill)
    .height(Length::Fill)
    .spacing(SPACING))),
    Some(EntireLogSelection { .. }) | None => None,
    };
  • replacement in inflorescence_view/src/app.rs at line 746
    [46.7272][46.7272:7312](),[44.1719][23.3887:3959](),[46.7312][23.3887:3959](),[23.3887][23.3887:3959]()
    } else if let Some(col_2) = col_2 {
    let cols = [col_0, col_1, col_2].into_iter().skip(hidden_cols);
    [46.7272]
    [44.1720]
    } else if let Some(EntireLog::Loading) = entire_log.as_ref() {
    el(column([
    view_repo_info(),
    el(text("Entire log")),
    el(text("Loading...")),
    ])
    .width(Length::Fill)
    .height(Length::Fill))
    } else if let Some(EntireLog::Got { .. }) = entire_log.as_ref() {
    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))
    }
    } else 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);
  • replacement in inflorescence_view/src/app.rs at line 780
    [23.4011][23.4011:4046]()
    let cols = [col_0, col_1];
    [23.4011]
    [44.1840]
    let cols = [status_col_0(), status_col_1()];
  • edit in inflorescence_view/src/app.rs at line 800
    [46.7451]
    [47.3692]
    entire_log_selection,
  • edit in inflorescence_view/src/app.rs at line 887
    [44.4039]
    [45.127]
    #[allow(clippy::let_and_return)]
  • replacement in inflorescence_view/src/app.rs at line 911
    [46.8287][47.4251:4304]()
    add_if(!can_record, switch_channel, row)
    [46.8287]
    [44.4979]
    let row = add_if(!can_record, switch_channel, row);
    row
  • replacement in inflorescence_view/src/app.rs at line 921
    [47.4426][47.4426:4479]()
    add_if(!can_record, switch_channel, row)
    [47.4426]
    [44.5256]
    let row = add_if(!can_record, switch_channel, row);
    row
  • replacement in inflorescence_view/src/app.rs at line 927
    [47.4541][47.4541:4594]()
    add_if(!can_record, switch_channel, row)
    [47.4541]
    [44.5445]
    let row = add_if(!can_record, switch_channel, row);
    row
  • replacement in inflorescence_view/src/app.rs at line 946
    [48.1499][47.5049:5080](),[47.5049][47.5049:5080]()
    row.push(cancel())
    [48.1499]
    [47.5080]
    let row = row.push(cancel());
    row
    }
    ActionState::EntireLog { can_select_right } => {
    let row = row([down(), up()]);
    let row = add_if(can_select_right, right, row);
    row
    }
    ActionState::EntireLogChange { can_select_right } => {
    let row = row([left(), down(), up()]);
    let row = add_if(can_select_right, right, row);
    row
    }
    ActionState::EntireLogChangeDiff => {
    let row = row([left(), down(), up(), down_no_skip(), up_no_skip()]);
    row
  • replacement in inflorescence_view/src/app.rs at line 998
    [44.5889][44.5889:5937]()
    /// Untracked, changed of log change's diff
    [44.5889]
    [46.9052]
    /// Untracked, changed or status log change's diff
  • edit in inflorescence_view/src/app.rs at line 1008
    [47.5463]
    [47.5463]
    },
    /// Viewing entire log
    EntireLog {
    can_select_right: bool,
  • edit in inflorescence_view/src/app.rs at line 1013
    [47.5470]
    [44.6028]
    /// Viewing entire log with some change selected
    EntireLogChange {
    can_select_right: bool,
    },
    /// Viewing entire log with some diff of a change selected
    EntireLogChangeDiff,
  • edit in inflorescence_view/src/app.rs at line 1039
    [46.9347]
    [44.6260]
    entire_log_selection: Option<EntireLogSelection<'a>>,
  • edit in inflorescence_view/src/app.rs at line 1064
    [47.5740]
    [44.6432]
    if let Some(EntireLogSelection { file, nav, .. }) = entire_log_selection {
    return match file {
    Some(LogChangeFileSelection {
    ix: _,
    path: _,
    diff,
    }) => {
    if let Some(diff) = diff {
    if diff.is_selected {
    ActionState::EntireLogChangeDiff
    } else {
    ActionState::EntireLogChange {
    can_select_right: matches!(
    diff.nav.ready,
    Some(iced_nav_scrollable::NeedsScrolling::Yes)
    ),
    }
    }
    } else {
    ActionState::EntireLogChange {
    can_select_right: false,
    }
    }
    }
    None => ActionState::EntireLog {
    can_select_right: nav.and_then(|nav| nav.ready).is_some(),
    },
    };
    }
  • edit in inflorescence_view/src/app.rs at line 1242
    [16.25268]
    [16.25268]
    }
    fn view_log_change(
    ix: usize,
    repo::LogEntry {
    hash,
    message,
    file_paths: _,
    }: &repo::LogEntry,
    is_selected: bool,
    ) -> Element<'_, Msg, Theme> {
    let short_hash = display_short_hash(hash);
    el(row([
    el(button(text(short_hash).font(Font::MONOSPACE))
    .on_press(Msg::Selection(selection::Msg::Select(
    selection::Select::LogChange {
    ix,
    hash: *hash,
    message: message.clone(),
    },
    )))
    .class(selectable_button_class(is_selected))),
    el(text(message).shaping(text::Shaping::Advanced)),
    ])
    .spacing(SPACING))
  • replacement in inflorescence/src/selection.rs at line 5
    [46.13124][46.13124:13188]()
    Channel, Dir, HeldKey, LogChangeFileSelection, Msg, Select,
    [46.13124]
    [46.13188]
    Channel, Dir, HeldKey, LogChange, LogChangeFileSelection, Msg, Select,
  • replacement in inflorescence/src/selection.rs at line 30
    [29.4309][40.20757:20796]()
    logs: &mut diff::LogFilesAndState,
    [29.4309]
    [38.108]
    status_logs: &mut diff::LogFilesAndState,
    entire_logs: &mut diff::LogFilesAndState,
  • replacement in inflorescence/src/selection.rs at line 44
    [30.2493][30.2493:2614]()
    // Iced is delayed 500
    // ms and that creates too much of a jump
    [30.2493]
    [30.2614]
    // Iced is delayed 500 ms and that creates too much
    // of a jump
  • replacement in inflorescence/src/selection.rs at line 60
    [29.5148][40.20822:20949](),[40.20949][29.5380:5409](),[29.5380][29.5380:5409](),[29.5409][40.20950:21026](),[40.21026][29.5490:5508](),[29.5490][29.5490:5508]()
    Dir::Down => {
    select_down(state, files, files_diffs, logs, repo, delta)
    }
    Dir::Up => {
    select_up(state, files, files_diffs, logs, repo, delta)
    }
    [29.5148]
    [38.143]
    Dir::Down => select_down(
    state,
    files,
    files_diffs,
    status_logs,
    entire_logs,
    repo,
    delta,
    ),
    Dir::Up => select_up(
    state,
    files,
    files_diffs,
    status_logs,
    entire_logs,
    repo,
    delta,
    ),
  • replacement in inflorescence/src/selection.rs at line 79
    [38.209][38.209:241](),[38.241][40.21027:21103](),[40.21103][38.322:340](),[38.322][38.322:340]()
    Dir::Right => {
    select_right(state, files_diffs, logs, repo.as_deref())
    }
    [38.209]
    [29.5644]
    Dir::Right => select_right(
    state,
    files_diffs,
    status_logs,
    entire_logs,
    repo.as_deref(),
    ),
  • replacement in inflorescence/src/selection.rs at line 88
    [29.5668][40.21104:21176]()
    Msg::ReleaseDir(dir) => release(dir, state, files_diffs, logs),
    [29.5668]
    [30.2886]
    Msg::ReleaseDir(dir) => release(dir, state, files_diffs, status_logs),
  • replacement in inflorescence/src/selection.rs at line 114
    [30.3802][40.21177:21331]()
    Dir::Down => alt_select_down(state, files_diffs, logs, delta),
    Dir::Up => alt_select_up(state, files_diffs, logs, delta),
    [30.3802]
    [30.4005]
    Dir::Down => {
    alt_select_down(state, files_diffs, status_logs, delta)
    }
    Dir::Up => {
    alt_select_up(state, files_diffs, status_logs, delta)
    }
  • replacement in inflorescence/src/selection.rs at line 132
    [38.498][40.21332:21350]()
    logs,
    [38.498]
    [38.521]
    status_logs,
    entire_logs,
  • replacement in inflorescence/src/selection.rs at line 142
    [29.5786][29.5786:5825]()
    logs: &mut diff::LogFilesAndState,
    [29.5786]
    [40.21368]
    status_logs: &mut diff::LogFilesAndState,
    entire_logs: &mut diff::LogFilesAndState,
  • edit in inflorescence/src/selection.rs at line 152
    [47.5778]
    [38.640]
    entire_log,
  • edit in inflorescence/src/selection.rs at line 172
    [46.13770]
    [46.13770]
    }
    if let Some(app::EntireLog::Got { log, nav }) = entire_log.as_ref() {
    let (selection, task) = if let Some(LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) = state.view.entire_log.take()
    {
    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,
    }),
    };
    let task = if let Some(nav) = entire_logs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    }) {
    iced_nav_scrollable::scroll_down(nav, delta)
    } else {
    Task::none()
    };
    (selection, task)
    } else {
    let log_entry = log.get(log_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(
    entire_logs,
    log_entry,
    hash,
    file_ix,
    );
    let scroll_task = if let Some((nav_changes_hash, nav)) =
    entire_logs.changes_nav.as_ref()
    && *nav_changes_hash == hash
    {
    iced_nav_scrollable::scroll_down_to_section(
    file_ix, nav,
    )
    } else {
    Task::none()
    };
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    };
    (selection, Task::batch([selection_task, scroll_task]))
    }
    }
    None => {
    if log.len().saturating_sub(1) == log_ix {
    let ix = 0;
    entire_log_selection(
    nav,
    entire_logs,
    log,
    ix,
    VertDir::Up,
    )
    } else {
    let ix = log_ix + 1;
    entire_log_selection(
    nav,
    entire_logs,
    log,
    ix,
    VertDir::Down,
    )
    }
    }
    }
    } else {
    let ix = 0;
    entire_log_selection(nav, entire_logs, log, ix, VertDir::Down)
    };
    state.view.entire_log = Some(selection);
    return task;
  • replacement in inflorescence/src/selection.rs at line 318
    [33.1304][40.21915:21950]()
    log_selection(
    [33.1304]
    [38.1658]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 320
    [38.1694][40.21951:21981]()
    logs,
    [38.1694]
    [40.21981]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 376
    [33.2553][40.22807:22842]()
    log_selection(
    [33.2553]
    [38.3120]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 378
    [38.3156][40.22843:22873]()
    logs,
    [38.3156]
    [40.22873]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 417
    [33.3113][46.14000:14033]()
    Some(Status::LogChange {
    [33.3113]
    [33.3149]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 422
    [33.3230][33.3230:3246]()
    }) => {
    [33.3230]
    [33.3246]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 431
    [33.3574][46.14034:14094]()
    let selection = Status::LogChange {
    [33.3574]
    [40.23749]
    let selection = Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 440
    [40.24086][40.24086:24172]()
    };
    let task = if let Some(nav) = logs
    [40.24086]
    [40.24172]
    });
    let task = if let Some(nav) = status_logs
  • replacement in inflorescence/src/selection.rs at line 464
    [40.24634][40.24634:24767]()
    let (file, selection_task) =
    log_file_selection(logs, log_entry, hash, file_ix);
    [40.24634]
    [14.7558]
    let (file, selection_task) = log_file_selection(
    status_logs,
    log_entry,
    hash,
    file_ix,
    );
  • replacement in inflorescence/src/selection.rs at line 472
    [40.24849][40.24849:24903]()
    logs.changes_nav.as_ref()
    [40.24849]
    [40.24903]
    status_logs.changes_nav.as_ref()
  • replacement in inflorescence/src/selection.rs at line 482
    [14.7679][46.14095:14155]()
    let selection = Status::LogChange {
    [14.7679]
    [40.25300]
    let selection = Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 487
    [40.25457][40.25457:25484]()
    };
    [40.25457]
    [40.25484]
    });
  • replacement in inflorescence/src/selection.rs at line 516
    [38.6405][40.26179:26222]()
    log_selection(
    [38.6405]
    [40.26222]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 518
    [40.26266][40.26266:26304]()
    logs,
    [40.26266]
    [40.26304]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 526
    [38.7022][40.26460:26499]()
    log_selection(
    [38.7022]
    [38.7316]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 528
    [38.7356][40.26500:26534]()
    logs,
    [38.7356]
    [40.26534]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 563
    [38.8573][40.27194:27249]()
    let (selection, task) = log_selection(
    [38.8573]
    [38.8787]
    let (selection, task) = status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 565
    [38.8819][40.27250:27276]()
    logs,
    [38.8819]
    [40.27276]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 584
    [29.6487][29.6487:6526]()
    logs: &mut diff::LogFilesAndState,
    [29.6487]
    [40.27383]
    status_logs: &mut diff::LogFilesAndState,
    entire_logs: &mut diff::LogFilesAndState,
  • edit in inflorescence/src/selection.rs at line 594
    [47.5807]
    [38.9001]
    entire_log,
  • edit in inflorescence/src/selection.rs at line 615
    [46.14764]
    [46.14764]
    if let Some(app::EntireLog::Got { log, nav }) = entire_log.as_ref() {
    let (selection, task) = if let Some(LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) = state.view.entire_log.take()
    {
    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,
    }),
    };
    let task = if let Some(nav) = entire_logs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    }) {
    iced_nav_scrollable::scroll_up(nav, delta)
    } else {
    Task::none()
    };
    (selection, task)
    } 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
    };
    let (file, selection_task) = entire_log_file_selection(
    entire_logs,
    log_entry,
    hash,
    file_ix,
    );
    let scroll_task = if let Some((nav_changes_hash, nav)) =
    entire_logs.changes_nav.as_ref()
    && *nav_changes_hash == hash
    {
    iced_nav_scrollable::scroll_up_to_section(
    file_ix, nav,
    )
    } else {
    Task::none()
    };
  • edit in inflorescence/src/selection.rs at line 680
    [46.14765]
    [46.14765]
    let selection = LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    };
    (selection, Task::batch([selection_task, scroll_task]))
    }
    }
    None => {
    if 0 == log_ix {
    let ix = log.len().saturating_sub(1);
    entire_log_selection(
    nav,
    entire_logs,
    log,
    ix,
    VertDir::Down,
    )
    } else {
    let ix = log_ix - 1;
    entire_log_selection(
    nav,
    entire_logs,
    log,
    ix,
    VertDir::Up,
    )
    }
    }
    }
    } else {
    let ix = 0;
    entire_log_selection(nav, entire_logs, log, ix, VertDir::Down)
    };
    state.view.entire_log = Some(selection);
    return task;
    }
  • replacement in inflorescence/src/selection.rs at line 747
    [38.9179][40.27691:27726]()
    log_selection(
    [38.9179]
    [38.9449]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 749
    [38.9485][40.27727:27757]()
    logs,
    [38.9485]
    [40.27757]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 825
    [38.11906][40.29061:29096]()
    log_selection(
    [38.11906]
    [38.12243]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 827
    [38.12279][40.29097:29127]()
    logs,
    [38.12279]
    [40.29127]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 856
    [33.10171][46.14988:15021]()
    Some(Status::LogChange {
    [33.10171]
    [33.10207]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 861
    [33.10288][33.10288:10304]()
    }) => {
    [33.10288]
    [33.10304]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 870
    [33.10632][46.15022:15082]()
    let selection = Status::LogChange {
    [33.10632]
    [40.29764]
    let selection = Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 879
    [40.30101][40.30101:30187]()
    };
    let task = if let Some(nav) = logs
    [40.30101]
    [40.30187]
    });
    let task = if let Some(nav) = status_logs
  • replacement in inflorescence/src/selection.rs at line 900
    [33.11792][40.30646:30779]()
    let (file, selection_task) =
    log_file_selection(logs, log_entry, hash, file_ix);
    [33.11792]
    [40.30779]
    let (file, selection_task) = log_file_selection(
    status_logs,
    log_entry,
    hash,
    file_ix,
    );
  • replacement in inflorescence/src/selection.rs at line 908
    [40.30861][40.30861:30915]()
    logs.changes_nav.as_ref()
    [40.30861]
    [40.30915]
    status_logs.changes_nav.as_ref()
  • replacement in inflorescence/src/selection.rs at line 918
    [40.31247][46.15083:15143]()
    let selection = Status::LogChange {
    [40.31247]
    [40.31310]
    let selection = Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 923
    [40.31467][40.31467:31494]()
    };
    [40.31467]
    [40.31494]
    });
  • replacement in inflorescence/src/selection.rs at line 952
    [38.15082][40.32249:32292]()
    log_selection(
    [38.15082]
    [40.32292]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 954
    [40.32336][40.32336:32374]()
    logs,
    [40.32336]
    [40.32374]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 962
    [33.12959][40.32532:32571]()
    log_selection(
    [33.12959]
    [38.16020]
    status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 964
    [38.16060][40.32572:32606]()
    logs,
    [38.16060]
    [40.32606]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 977
    [38.16247][40.32746:32801]()
    let (selection, task) = log_selection(
    [38.16247]
    [38.16459]
    let (selection, task) = status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 979
    [38.16491][40.32802:32828]()
    logs,
    [38.16491]
    [40.32828]
    status_logs,
  • replacement in inflorescence/src/selection.rs at line 1062
    [30.5352][46.15293:15326]()
    Some(Status::LogChange {
    [30.5352]
    [30.5388]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1072
    [30.5627][30.5627:5643]()
    }) => {
    [30.5627]
    [31.448]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 1086
    [46.15413][46.15413:15454]()
    | Some(Status::LogChange { .. })
    [46.15413]
    [30.6149]
    | Some(Status::LogChange(LogChange { .. }))
  • replacement in inflorescence/src/selection.rs at line 1136
    [30.7362][46.15568:15601]()
    Some(Status::LogChange {
    [30.7362]
    [30.7398]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1146
    [30.7637][30.7637:7653]()
    }) => {
    [30.7637]
    [31.665]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 1160
    [46.15688][46.15688:15729]()
    | Some(Status::LogChange { .. })
    [46.15688]
    [30.8157]
    | Some(Status::LogChange(LogChange { .. }))
  • edit in inflorescence/src/selection.rs at line 1174
    [47.5836]
    [40.34932]
    entire_log,
  • replacement in inflorescence/src/selection.rs at line 1179
    [33.14096][46.15761:15903]()
    let (selection, task): (Option<Status>, Task<crate::Msg>) =
    match state.view.status.take() {
    Some(Status::LogChange {
    [33.14096]
    [40.35113]
    if let Some(app::EntireLog::Got { log: _, nav }) = entire_log.as_ref() {
    let (selection, task) = match state.view.entire_log.take() {
    Some(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1195
    [40.35370][46.15904:15953]()
    Some(Status::LogChange {
    [40.35370]
    [40.35422]
    Some(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1208
    [40.35871][46.15954:16010]()
    let selection = Status::LogChange {
    [40.35871]
    [40.35930]
    let selection = LogChange {
  • edit in inflorescence/src/selection.rs at line 1214
    [40.36080]
    [40.36080]
    let task =
    iced_nav_scrollable::scroll_to_stored_offset(nav);
    (Some(selection), task)
    }
    }
    selection @ (Some(LogChange { file: None, .. }) | None) => {
    (selection, Task::none())
    }
    };
    state.view.entire_log = selection;
    return task;
    }
    let (selection, task): (Option<Status>, Task<crate::Msg>) =
    match state.view.status.take() {
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    })) => {
    if diff_selected {
    (
    Some(Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    })),
    Task::none(),
    )
    } else {
    let selection = Status::LogChange(LogChange {
    ix,
    hash,
    message,
    file: None,
    });
  • replacement in inflorescence/src/selection.rs at line 1293
    [46.16290][46.16290:16347]()
    | Some(Status::LogChange { file: None, .. })
    [46.16290]
    [40.37134]
    | Some(Status::LogChange(LogChange {
    file: None,
    ..
    }))
  • replacement in inflorescence/src/selection.rs at line 1306
    [28.40752][40.37224:37263]()
    logs: &mut diff::LogFilesAndState,
    [28.40752]
    [40.37263]
    status_logs: &mut diff::LogFilesAndState,
    entire_logs: &mut diff::LogFilesAndState,
  • edit in inflorescence/src/selection.rs at line 1315
    [47.5865]
    [38.17839]
    entire_log,
  • edit in inflorescence/src/selection.rs at line 1320
    [33.15706]
    [46.16415]
    if let Some(app::EntireLog::Got { log, nav: _ }) = entire_log.as_ref()
    && let Some(entire_log) = state.view.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 id_hash = file::log_id_parts_hash(log_entry.hash, path);
    let task = if let Some(log) =
    entire_logs.diffs.get(&id_hash)
    {
    // Init log diffs nav
    let contents_count = diff::contents_count(&log.file);
    let unchanged_sections =
    diff::unchanged_sections(&log.file);
    let (nav, tasks) = iced_nav_scrollable::init(
    contents_count,
    unchanged_sections,
    );
    entire_logs.diffs_nav = Some((id_hash, nav));
    tasks.map(move |msg| {
    crate::Msg::View(app::Msg::LogChangeFileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    })
    } else {
    // If the log is not loaded yet, the nav will be
    // initialized once it's loaded
    // (`repo::MsgOut::GotChangeDifs`)
    Task::none()
    };
    (
    Some(LogChangeFileSelection {
    ix: 0,
    path: path.clone(),
    diff_selected: false,
    }),
    task,
    )
    } else {
    (None, Task::none())
    };
    (
    Some(LogChange {
    ix,
    hash,
    message,
    file,
    }),
    task,
    )
    }
    LogChange {
    ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    } => {
    let id_hash = file::log_id_parts_hash(hash, &path);
    let is_diff_scrollable =
    diff::log_diff_needs_scrolling(entire_logs, id_hash);
    // If the selected file's diff is already loaded (it has an
    // attached state), scroll back to its last offset
    let task = if is_diff_scrollable
    && let Some(nav) = entire_logs.diffs_nav.as_ref().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    ) {
    iced_nav_scrollable::scroll_to_stored_offset(nav)
    } else {
    Task::none()
    };
    (
    Some(LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: is_diff_scrollable,
    }),
    }),
    task,
    )
    }
    selection @ LogChange { .. } => (Some(selection), Task::none()),
    };
    state.view.entire_log = selection;
    return task;
    }
  • replacement in inflorescence/src/selection.rs at line 1491
    [40.39532][46.16673:16706]()
    Some(Status::LogChange {
    [40.39532]
    [40.39568]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1496
    [40.39647][40.39647:39663]()
    }) => {
    [40.39647]
    [40.39663]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 1501
    [40.39895][40.39895:39968]()
    let task = if let Some(log) = logs.diffs.get(&id_hash) {
    [40.39895]
    [40.39968]
    let task = if let Some(log) = status_logs.diffs.get(&id_hash) {
  • replacement in inflorescence/src/selection.rs at line 1510
    [40.40363][40.40363:40575]()
    logs.diffs_nav = Some((id_hash, nav));
    tasks.map(move |msg| crate::Msg::LogDiffNav {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    [40.40363]
    [40.40575]
    status_logs.diffs_nav = Some((id_hash, nav));
    tasks.map(move |msg| {
    crate::Msg::View(app::Msg::LogChangeFileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
  • replacement in inflorescence/src/selection.rs at line 1535
    [40.41014][46.16707:16748]()
    Some(Status::LogChange {
    [40.41014]
    [40.41058]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1540
    [40.41163][40.41163:41183]()
    }),
    [40.41163]
    [40.41183]
    })),
  • replacement in inflorescence/src/selection.rs at line 1544
    [40.41229][46.16749:16782]()
    Some(Status::LogChange {
    [40.41229]
    [40.41265]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1554
    [40.41505][40.41505:41521]()
    }) => {
    [40.41505]
    [40.41521]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 1556
    [40.41585][40.41585:41664]()
    let diff_selected = diff::log_diff_needs_scrolling(logs, id_hash);
    [40.41585]
    [40.41664]
    let is_diff_scrollable =
    diff::log_diff_needs_scrolling(status_logs, id_hash);
  • replacement in inflorescence/src/selection.rs at line 1560
    [40.41799][40.41799:41950]()
    let task = if diff_selected
    && let Some(nav) =
    logs.diffs_nav.as_ref().and_then(|(nav_id_hash, nav)| {
    [40.41799]
    [40.41950]
    let task = if is_diff_scrollable
    && let Some(nav) = status_logs.diffs_nav.as_ref().and_then(
    |(nav_id_hash, nav)| {
  • replacement in inflorescence/src/selection.rs at line 1564
    [40.42015][40.42015:42040]()
    }) {
    [40.42015]
    [40.42040]
    },
    ) {
  • replacement in inflorescence/src/selection.rs at line 1571
    [40.42185][46.16783:16824]()
    Some(Status::LogChange {
    [40.42185]
    [40.42229]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1578
    [28.43289][28.43289:43328]()
    diff_selected,
    [28.43289]
    [28.43328]
    diff_selected: is_diff_scrollable,
  • replacement in inflorescence/src/selection.rs at line 1580
    [28.43352][40.42402:42422]()
    }),
    [28.43352]
    [40.42422]
    })),
  • replacement in inflorescence/src/selection.rs at line 1631
    [29.8562][46.16998:17039]()
    Some(Status::LogChange {
    [29.8562]
    [29.8606]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1641
    [29.8917][29.8917:8941]()
    }) => {
    [29.8917]
    [29.8941]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 1653
    [46.17142][46.17142:17191]()
    | Some(Status::LogChange { .. })
    [46.17142]
    [29.9471]
    | Some(Status::LogChange(LogChange { .. }))
  • replacement in inflorescence/src/selection.rs at line 1667
    [49.95][49.95:134]()
    logs: &mut diff::LogFilesAndState,
    [49.95]
    [49.134]
    status_logs: &mut diff::LogFilesAndState,
    entire_logs: &mut diff::LogFilesAndState,
  • edit in inflorescence/src/selection.rs at line 1675
    [47.5894]
    [38.18046]
    entire_log,
  • edit in inflorescence/src/selection.rs at line 1680
    [38.18107]
    [28.46273]
    if let Some(app::EntireLog::Got { log, nav }) = entire_log.as_ref() {
    let (selection, task) = match select {
    Select::LogChange {
    ix,
    hash: _,
    message: _,
    } => {
    let (selection, task) = entire_log_selection(
    nav,
    entire_logs,
    log,
    ix,
    VertDir::Down,
    );
    (Some(selection), task)
    }
    Select::LogChangeFile { ix: file_ix, path } => {
    match state.view.entire_log.take() {
    Some(LogChange {
    ix: log_ix,
    hash,
    message,
    file: _,
    }) => {
    let log_entry = log.get(log_ix).unwrap();
    let id_hash = file::log_id_parts_hash(hash, &path);
    let diff_selected = diff::log_diff_needs_scrolling(
    entire_logs,
    id_hash,
    );
    // If the selected file's diff is already loaded (it has
    // an attached state), scroll
    // back to its last offset
    let scroll_task = if diff_selected
    && let Some(nav) = entire_logs
    .diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    }) {
    iced_nav_scrollable::scroll_to_stored_offset(nav)
    } else {
    Task::none()
    };
    let (file, selection_task) = log_file_selection(
    entire_logs,
    log_entry,
    hash,
    file_ix,
    );
    let selection = Some(LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    });
    (selection, Task::batch([selection_task, scroll_task]))
    }
    selection => (selection, Task::none()),
    }
    }
    _ => {
    unreachable!()
    }
    };
    state.view.entire_log = selection;
    return task;
    }
  • replacement in inflorescence/src/selection.rs at line 1826
    [49.1040][49.1040:1156]()
    let (selection, task) =
    log_selection(status_nav, logs, repo_state, ix, VertDir::Down);
    [49.1040]
    [49.1156]
    let (selection, task) = status_log_selection(
    status_nav,
    status_logs,
    repo_state,
    ix,
    VertDir::Down,
    );
  • replacement in inflorescence/src/selection.rs at line 1837
    [46.17396][46.17396:17437]()
    Some(Status::LogChange {
    [46.17396]
    [49.1193]
    Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1842
    [28.49326][28.49326:49350]()
    }) => {
    [28.49326]
    [49.1226]
    })) => {
  • replacement in inflorescence/src/selection.rs at line 1847
    [28.49462][28.49462:49533]()
    diff::log_diff_needs_scrolling(logs, id_hash);
    [28.49462]
    [28.49533]
    diff::log_diff_needs_scrolling(status_logs, id_hash);
  • replacement in inflorescence/src/selection.rs at line 1851
    [49.1356][40.43757:43885](),[32.1124][40.43757:43885]()
    && let Some(nav) = logs.diffs_nav.as_ref().and_then(
    |(nav_id_hash, nav)| {
    [49.1356]
    [40.43885]
    && let Some(nav) = status_logs
    .diffs_nav
    .as_ref()
    .and_then(|(nav_id_hash, nav)| {
  • replacement in inflorescence/src/selection.rs at line 1856
    [40.43958][40.43958:44017]()
    },
    ) {
    [40.43958]
    [32.1195]
    }) {
  • replacement in inflorescence/src/selection.rs at line 1862
    [49.1358][49.1358:1483]()
    let (file, selection_task) =
    log_file_selection(logs, log_entry, hash, file_ix);
    [49.1358]
    [49.1483]
    let (file, selection_task) = log_file_selection(
    status_logs,
    log_entry,
    hash,
    file_ix,
    );
  • replacement in inflorescence/src/selection.rs at line 1869
    [49.1484][49.1484:1545]()
    let selection = Some(Status::LogChange {
    [49.1484]
    [49.1545]
    let selection = Some(Status::LogChange(LogChange {
  • replacement in inflorescence/src/selection.rs at line 1874
    [49.1686][49.1686:1710]()
    });
    [49.1686]
    [49.1710]
    }));
  • replacement in inflorescence/src/selection.rs at line 2030
    [40.48079][40.48079:48097]()
    fn log_selection(
    [40.48079]
    [40.48097]
    fn status_log_selection(
  • replacement in inflorescence/src/selection.rs at line 2047
    [40.48657][40.48657:48722]()
    crate::Msg::View(app::Msg::LogNav { hash, msg })
    [40.48657]
    [40.48722]
    crate::Msg::View(app::Msg::LogChangeNav { change: hash, msg })
  • edit in inflorescence/src/selection.rs at line 2069
    [40.49425]
    [40.49425]
    let selection = Status::LogChange(LogChange {
    ix,
    hash,
    message: entry.message.clone(),
    file: None,
    });
    (selection, Task::batch([nav_task, scroll_task]))
    }
    fn entire_log_selection(
    nav: &NavScrollable,
    logs: &mut diff::LogFilesAndState,
    log: &repo::Log,
    ix: usize,
    dir: VertDir,
    ) -> (LogChange, Task<crate::Msg>) {
    let entry = log.get(ix).unwrap();
    let hash = entry.hash;
  • replacement in inflorescence/src/selection.rs at line 2090
    [40.49426][46.17717:17757]()
    let selection = Status::LogChange {
    [40.49426]
    [40.49469]
    let nav_task = match logs.change_file_counts.get(&hash) {
    Some(contents_count) => {
    // Init log changes nav
    let (nav, tasks) =
    iced_nav_scrollable::init(*contents_count, HashSet::new());
    logs.changes_nav = Some((hash, nav));
    tasks.map(move |msg| {
    crate::Msg::View(app::Msg::EntireLogChangeNav {
    change: hash,
    msg,
    })
    })
    }
    None => {
    // If the log is not loaded yet, the nav will be initialized once
    // it's loaded (`repo::MsgOut::GotChangeDifs`)
    Task::done(crate::Msg::View(app::Msg::ToRepo(
    repo::MsgIn::GetChangeDiffs { hash },
    )))
    }
    };
    let scroll_task = match dir {
    VertDir::Up => iced_nav_scrollable::scroll_up_to_section(ix, nav),
    VertDir::Down => iced_nav_scrollable::scroll_down_to_section(ix, nav),
    };
    let selection = LogChange {
  • edit in inflorescence/src/selection.rs at line 2177
    [46.17761]
    [46.17761]
    fn entire_log_file_selection(
    logs: &mut diff::LogFilesAndState,
    log_entry: &repo::LogEntry,
    hash: repo::ChangeHash,
    file_ix: usize,
    ) -> (LogChangeFileSelection, Task<crate::Msg>) {
    let path = log_entry.file_paths.get(file_ix).unwrap().clone();
    let id_hash = file::log_id_parts_hash(hash, &path);
    let nav_task = match logs.diffs.get(&id_hash) {
    Some(diff) => {
    let needs_new_nav = logs.diffs_nav.is_none()
    || logs
    .diffs_nav
    .as_ref()
    .map(|(nav_id_hash, _nav)| *nav_id_hash != id_hash)
    .unwrap_or_default();
    if needs_new_nav {
    let contents_count = diff::contents_count(&diff.file);
    // Init log change diff nav
    let (nav, tasks) =
    iced_nav_scrollable::init(contents_count, HashSet::new());
    logs.diffs_nav = Some((id_hash, nav));
    tasks.map(move |msg| {
    crate::Msg::View(app::Msg::LogChangeFileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    })
    } else {
    Task::none()
    }
    }
    None => {
    // If the log is not loaded yet, the nav will be initialized once
    // it's loaded (`repo::MsgOut::GotChangeDifs`)
    Task::none()
    }
    };
    (
    LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    },
    nav_task,
    )
    }
  • replacement in inflorescence/src/main.rs at line 103
    [28.8871][28.8871:8924]()
    logs: diff::LogFilesAndState::default(),
    [28.8871]
    [4.1520]
    status_logs: diff::LogFilesAndState::default(),
    entire_logs: diff::LogFilesAndState::default(),
  • replacement in inflorescence/src/main.rs at line 122
    [15.189][26.3039:3085]()
    /// Diffs for untracked and changed files
    [15.189]
    [28.8925]
    /// Diffs for untracked and changed files shown in status view
  • replacement in inflorescence/src/main.rs at line 124
    [28.8960][26.3134:3200](),[26.3134][26.3134:3200](),[26.3200][28.8961:8995]()
    /// The diffs are loaded async and not present while loading.
    logs: diff::LogFilesAndState,
    [28.8960]
    [7.1025]
    /// Logs shown in the status view. The diffs are loaded async and not
    /// present while loading.
    status_logs: diff::LogFilesAndState,
    /// Logs for the entire log
    entire_logs: diff::LogFilesAndState,
  • edit in inflorescence/src/main.rs at line 140
    [25.2562][28.9042:9093](),[28.9093][25.2631:2662](),[25.2631][25.2631:2662]()
    LogDiffNav {
    id_hash: file::LogIdHash,
    msg: diff::Msg,
    },
  • edit in inflorescence/src/main.rs at line 192
    [25.3747][40.8406:8609](),[40.8609][25.4073:4087](),[28.9532][25.4073:4087](),[25.4073][25.4073:4087](),[25.4087][40.8610:8967](),[31.292][25.4531:4545](),[40.8967][25.4531:4545](),[28.9733][25.4531:4545](),[25.4531][25.4531:4545](),[25.4545][16.26257:26292](),[16.26257][16.26257:26292]()
    Msg::LogDiffNav { id_hash, msg } => {
    if let Some(diff::FileAndState {
    file: _,
    state: diff_state,
    }) = state.logs.diffs.get_mut(&id_hash)
    {
    let nav = state.logs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    );
    let task = diff::update(diff_state, nav, msg);
    return task.map(move |msg| Msg::LogDiffNav { id_hash, msg });
    }
    Task::none()
    }
  • edit in inflorescence/src/main.rs at line 272
    [47.7347]
    [47.7347]
    } else if matches!(
    repo.entire_log.as_ref(),
    Some(app::EntireLog::Got { .. }),
    ) {
    // Repeated match to take ownership of the log
    if let Some(app::EntireLog::Got { log, nav }) =
    repo.entire_log.take()
    {
    // Cache for later viewing
    repo.entire_log = Some(app::EntireLog::NotViewing {
    log,
    nav_stored_offset: nav.stored_offset,
    });
    } else {
    debug_assert!(false, "The outter match should have the same condition as the inner match)")
    }
  • replacement in inflorescence/src/main.rs at line 297
    [40.9131][40.9131:9160]()
    &mut state.logs,
    [40.9131]
    [40.9160]
    &mut state.status_logs,
    &mut state.entire_logs,
  • replacement in inflorescence/src/main.rs at line 315
    [40.9279][40.9279:9403]()
    app::Msg::LogNav { hash, msg } => {
    if let Some((selected_hash, nav)) = state.logs.changes_nav.as_mut()
    [40.9279]
    [40.9403]
    app::Msg::LogChangeNav { change: hash, msg } => {
    if let Some((selected_hash, nav)) =
    state.status_logs.changes_nav.as_mut()
  • replacement in inflorescence/src/main.rs at line 320
    [40.9459][40.9459:9592]()
    iced_nav_scrollable::update(nav, msg)
    .map(move |msg| Msg::View(app::Msg::LogNav { hash, msg }))
    [40.9459]
    [37.4908]
    iced_nav_scrollable::update(nav, msg).map(move |msg| {
    Msg::View(app::Msg::LogChangeNav { change: hash, msg })
    })
  • edit in inflorescence/src/main.rs at line 368
    [45.448]
    [19.850]
    app::Msg::EntireLog => {
    if let Some(repo) = state.repo.as_mut() {
    match repo.entire_log.as_ref() {
    None => {
    state
    .repo_tx_in
    .send(repo::MsgIn::LoadEntireLog)
    .unwrap();
    repo.entire_log = Some(app::EntireLog::Loading);
    }
    Some(app::EntireLog::LoadingButNotViewing) => {
    repo.entire_log = Some(app::EntireLog::Loading);
    }
    Some(app::EntireLog::NotViewing { .. }) => {
    // Repeated match to take ownership of the log
    if let Some(app::EntireLog::NotViewing {
    log,
    nav_stored_offset,
    }) = repo.entire_log.take()
    {
    let (mut nav, nav_task) = iced_nav_scrollable::init(
    log.len(),
    HashSet::new(),
    );
    // Scroll to last selection if any
    nav.stored_offset = nav_stored_offset;
    let scroll_task =
    iced_nav_scrollable::scroll_to_stored_offset(
    &nav,
    );
    repo.entire_log = Some(app::EntireLog::Got {
    log,
    nav: Box::new(nav),
    });
    return Task::batch([
    nav_task.map(|msg| {
    Msg::View(app::Msg::EntireLogNav(msg))
    }),
    scroll_task,
    ]);
    } else {
    debug_assert!(false, "The outter match should have the same condition as the inner match)")
    }
    }
    Some(
    app::EntireLog::Loading | app::EntireLog::Got { .. },
    ) => {}
    }
    }
    Task::none()
    }
    app::Msg::EntireLogNav(msg) => {
    if let Some(app::Repo {
    entire_log: Some(app::EntireLog::Got { log: _, nav }),
    ..
    }) = state.repo.as_mut()
    {
    return iced_nav_scrollable::update(nav, msg)
    .map(|msg| Msg::View(app::Msg::EntireLogNav(msg)));
    }
    Task::none()
    }
    app::Msg::EntireLogChangeNav { change, msg } => {
    if let Some((selected_change, nav)) =
    state.entire_logs.changes_nav.as_mut()
    && change == *selected_change
    {
    iced_nav_scrollable::update(nav, msg).map(move |msg| {
    Msg::View(app::Msg::EntireLogChangeNav { change, msg })
    })
    } else {
    Task::none()
    }
    }
  • edit in inflorescence/src/main.rs at line 456
    [19.1200]
    [19.1200]
    repo::MsgOut::LoadedEntireLog(log) => got_entire_log(state, log),
  • edit in inflorescence/src/main.rs at line 466
    [47.7843]
    [37.5058]
    entire_log: _,
  • edit in inflorescence/src/main.rs at line 530
    [47.7872]
    [37.6042]
    entire_log: _,
  • replacement in inflorescence/src/main.rs at line 650
    [46.20320][46.20320:20404]()
    state.logs.changes_nav = None;
    state.logs.diffs_nav = None;
    [46.20320]
    [46.20404]
    state.status_logs.changes_nav = None;
    state.status_logs.diffs_nav = None;
  • edit in inflorescence/src/main.rs at line 658
    [47.7909]
    [46.20534]
    entire_log: _,
  • replacement in inflorescence/src/main.rs at line 718
    [19.7374][46.21085:21132]()
    if let Some(selection::Status::LogChange {
    [19.7374]
    [19.7421]
    if let Some(selection::LogChange {
  • replacement in inflorescence/src/main.rs at line 728
    [19.7631][46.21187:21233]()
    }) = state.selection.view.status.as_mut()
    [19.7631]
    [19.7672]
    }) = state.selection.view.entire_log.as_mut()
  • replacement in inflorescence/src/main.rs at line 736
    [40.11861][40.11861:11913]()
    }) = state.logs.diffs.get_mut(&id_hash)
    [40.11861]
    [34.2275]
    }) = state.entire_logs.diffs.get_mut(&id_hash)
  • replacement in inflorescence/src/main.rs at line 738
    [34.2285][40.11914:12244](),[40.12244][34.2332:2399](),[34.2332][34.2332:2399]()
    let nav =
    state
    .logs
    .diffs_nav
    .as_mut()
    .and_then(|(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    });
    return diff::update(diff_state, nav, action)
    .map(move |msg| Msg::LogDiffNav { id_hash, msg });
    [34.2285]
    [13.874]
    let nav = state.entire_logs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav),
    );
    return diff::update(diff_state, nav, action).map(move |msg| {
    Msg::View(app::Msg::LogChangeFileDiff { id_hash, msg })
    });
    }
    } else if let Some(selection::Status::LogChange(selection::LogChange {
    ix: _,
    hash: selected_hash,
    message: _,
    file:
    Some(selection::LogChangeFileSelection {
    ix: _,
    path: selected_path,
    diff_selected: _,
    }),
    })) = state.selection.view.status.as_mut()
    {
    let selected_id_hash =
    file::log_id_parts_hash(*selected_hash, selected_path);
    if selected_id_hash == id_hash
    && let Some(diff::FileAndState {
    file: _,
    state: diff_state,
    }) = state.status_logs.diffs.get_mut(&id_hash)
    {
    let nav = state.status_logs.diffs_nav.as_mut().and_then(
    |(nav_id_hash, nav)| (*nav_id_hash == id_hash).then_some(nav),
    );
    return diff::update(diff_state, nav, action).map(move |msg| {
    Msg::View(app::Msg::LogChangeFileDiff { id_hash, msg })
    });
  • edit in inflorescence/src/main.rs at line 786
    [47.7941]
    [37.7370]
    entire_log: None,
  • edit in inflorescence/src/main.rs at line 874
    [47.8087]
    [37.7786]
    entire_log: None,
  • replacement in inflorescence/src/main.rs at line 952
    [19.11168][46.22149:22192]()
    selection::Status::LogChange {
    [19.11168]
    [19.11211]
    selection::Status::LogChange(selection::LogChange {
  • replacement in inflorescence/src/main.rs at line 957
    [19.11329][19.11329:11348]()
    } => {
    [19.11329]
    [19.11538]
    }) => {
  • replacement in inflorescence/src/main.rs at line 983
    [28.15178][46.22336:22391]()
    selection::Status::LogChange {
    [28.15178]
    [19.12353]
    selection::Status::LogChange(selection::LogChange {
  • replacement in inflorescence/src/main.rs at line 988
    [19.12543][8.2991:3017](),[9.15291][8.2991:3017](),[8.2991][8.2991:3017]()
    }
    [19.12543]
    [19.12544]
    })
  • replacement in inflorescence/src/main.rs at line 1019
    [40.12318][46.22440:22498](),[40.12376][19.12937:13001](),[46.22498][19.12937:13001](),[19.12937][19.12937:13001](),[19.13001][40.12377:12391](),[40.12391][46.22499:22545](),[41.561][34.2861:2895](),[46.22545][34.2861:2895](),[19.13098][34.2861:2895]()
    let task = if let Some(selection::Status::LogChange {
    ix: _,
    hash: selected_hash,
    message: _,
    file,
    }) = state.selection.view.status.as_mut()
    && *selected_hash == hash
    [40.12318]
    [19.13098]
    if let Some(app::EntireLog::Got { .. }) = state
    .repo
    .as_ref()
    .and_then(|repo| repo.entire_log.as_ref())
  • replacement in inflorescence/src/main.rs at line 1024
    [19.13104][40.12392:12436]()
    if let Some(file) = file.as_ref() {
    [19.13104]
    [40.12436]
    let Some(selection::LogChange {
    ix: _,
    hash: selected_hash,
    message: _,
    file,
    }) = state.selection.view.entire_log.as_mut()
    else {
    return Task::none();
    };
    if *selected_hash != hash {
    return Task::none();
    }
    let task = if let Some(file) = file.as_ref() {
  • replacement in inflorescence/src/main.rs at line 1046
    [40.12795][40.12795:12858]()
    state.logs.diffs_nav = Some((id_hash, diffs_nav));
    [40.12795]
    [40.12858]
    state.entire_logs.diffs_nav = Some((id_hash, diffs_nav));
  • replacement in inflorescence/src/main.rs at line 1059
    [40.13257][40.13257:13321]()
    state.logs.changes_nav = Some((hash, changes_nav));
    [40.13257]
    [40.13321]
    state.entire_logs.changes_nav = Some((hash, changes_nav));
    nav_task.map(move |msg| {
    Msg::View(app::Msg::EntireLogChangeNav { change: hash, msg })
    })
    };
    // Store the changes
    state
    .entire_logs
    .change_file_counts
    .insert(hash, changed_files_count);
    diffs.into_iter().for_each(|(path, diffs)| {
    // NOTE: using unknown encoding as we don't yet have the file
    // for past changes
    let file = diff::init_file(
    diff::FileContent::UnknownEncoding,
    Some(&diffs),
    );
    let id_hash = file::log_id_parts_hash(hash, &path);
    let log_file_diff = diff::FileAndState {
    file,
    // The nav is initialized only once a file is selected,
    // because its tasks need it to be visible to complete
    state: diff::State::default(),
    };
    state.entire_logs.diffs.insert(id_hash, log_file_diff);
    });
    task
    } else if let Some(selection::Status::LogChange(selection::LogChange {
    ix: _,
    hash: selected_hash,
    message: _,
    file,
    })) = state.selection.view.status.as_mut()
    {
    let task = if *selected_hash == hash {
    if let Some(file) = file.as_ref() {
    // If a file is selected, init the nav for its diff
    let diff = diffs.get(&file.path).unwrap();
    let diff_contents_count = diff.len();
    let (diffs_nav, nav_task) = iced_nav_scrollable::init(
    diff_contents_count,
    HashSet::new(),
    );
    let id_hash = file::log_id_parts_hash(hash, &file.path);
  • replacement in inflorescence/src/main.rs at line 1107
    [40.13322][40.13322:13452]()
    nav_task.map(move |msg| Msg::View(app::Msg::LogNav { hash, msg }))
    }
    } else {
    Task::none()
    };
    [40.13322]
    [40.13452]
    state.status_logs.diffs_nav = Some((id_hash, diffs_nav));
  • replacement in inflorescence/src/main.rs at line 1109
    [40.13453][40.13453:14124]()
    // Store the changes
    state
    .logs
    .change_file_counts
    .insert(hash, changed_files_count);
    diffs.into_iter().for_each(|(path, diffs)| {
    // NOTE: using unknown encoding as we don't yet have the file
    // for past changes
    let file =
    diff::init_file(diff::FileContent::UnknownEncoding, Some(&diffs));
    let id_hash = file::log_id_parts_hash(hash, &path);
    let log_file_diff = diff::FileAndState {
    file,
    // The nav is initialized only once a file is selected,
    // because its tasks need it to be visible to complete
    state: diff::State::default(),
    [40.13453]
    [40.14124]
    nav_task.map(move |msg| {
    Msg::View(app::Msg::LogChangeFileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    })
    } else {
    // Init scrollable nav for log changes
    let (changes_nav, nav_task) = iced_nav_scrollable::init(
    changed_files_count,
    HashSet::new(),
    );
    state.status_logs.changes_nav = Some((hash, changes_nav));
    nav_task.map(move |msg| {
    Msg::View(app::Msg::LogChangeNav { change: hash, msg })
    })
    }
    } else {
    Task::none()
  • edit in inflorescence/src/main.rs at line 1131
    [40.14135]
    [40.14135]
    // Store the changes
    state
    .status_logs
    .change_file_counts
    .insert(hash, changed_files_count);
    diffs.into_iter().for_each(|(path, diffs)| {
    // NOTE: using unknown encoding as we don't yet have the file
    // for past changes
    let file = diff::init_file(
    diff::FileContent::UnknownEncoding,
    Some(&diffs),
    );
    let id_hash = file::log_id_parts_hash(hash, &path);
    let log_file_diff = diff::FileAndState {
    file,
    // The nav is initialized only once a file is selected,
    // because its tasks need it to be visible to complete
    state: diff::State::default(),
    };
  • replacement in inflorescence/src/main.rs at line 1151
    [40.14136][40.14136:14201]()
    state.logs.diffs.insert(id_hash, log_file_diff);
    });
    [40.14136]
    [26.5852]
    state.status_logs.diffs.insert(id_hash, log_file_diff);
    });
    task
    } else {
    Task::none()
    }
    }
  • replacement in inflorescence/src/main.rs at line 1159
    [26.5853][40.14202:14211]()
    task
    [26.5853]
    [6.4296]
    fn got_entire_log(state: &mut State, log: repo::Log) -> Task<Msg> {
    if let Some(repo) = state.repo.as_mut() {
    match repo.entire_log.as_ref() {
    None
    | Some(app::EntireLog::Loading | app::EntireLog::Got { .. }) => {
    let (nav, task) =
    iced_nav_scrollable::init(log.len(), HashSet::new());
    repo.entire_log = Some(app::EntireLog::Got {
    log,
    nav: Box::new(nav),
    });
    return task.map(|msg| Msg::View(app::Msg::EntireLogNav(msg)));
    }
    Some(
    app::EntireLog::LoadingButNotViewing
    | app::EntireLog::NotViewing { .. },
    ) => {
    repo.entire_log = Some(app::EntireLog::NotViewing {
    log,
    nav_stored_offset: None,
    });
    }
    }
    }
    Task::none()
  • replacement in inflorescence/src/main.rs at line 1193
    [3.2903][44.13010:13082](),[44.13082][46.22546:22615](),[46.22615][47.8088:8155]()
    "a" => Some(Msg::View(app::Msg::AddUntrackedFile)),
    "c" => Some(Msg::View(app::Msg::SwitchChannel)),
    "f" => Some(Msg::View(app::Msg::ForkChannel)),
    [3.2903]
    [46.22615]
    // _________________________________________________________
    // Directions
  • edit in inflorescence/src/main.rs at line 1207
    [29.1535]
    [44.13083]
    // _________________________________________________________
    // Other keys (sort alphabetically)
    "a" => Some(Msg::View(app::Msg::AddUntrackedFile)),
    "c" => Some(Msg::View(app::Msg::SwitchChannel)),
    "e" => Some(Msg::View(app::Msg::EntireLog)),
    "f" => Some(Msg::View(app::Msg::ForkChannel)),
  • replacement in inflorescence/src/main.rs at line 1360
    [23.5720][37.7914:7965]()
    let status_nav_sub = if state.repo.is_some() {
    [23.5720]
    [37.7965]
    let status_nav_sub = if let Some(selection::LogChange { .. }) =
    state.selection.view.entire_log
    {
    iced_nav_scrollable::subs()
    .map(|msg| Msg::View(app::Msg::EntireLogNav(msg)))
    } else if state.repo.is_some() {
  • replacement in inflorescence/src/main.rs at line 1372
    [40.14213][40.14213:14542]()
    let log_nav_sub =
    if let Some((hash, _nav)) = state.logs.changes_nav.as_ref() {
    let hash = *hash;
    iced_nav_scrollable::subs()
    .with(hash)
    .map(|(hash, msg)| Msg::View(app::Msg::LogNav { hash, msg }))
    } else {
    Subscription::none()
    };
    [40.14213]
    [37.8110]
    let log_nav_sub = if let Some((hash, _nav)) =
    state.entire_logs.changes_nav.as_ref()
    {
    let change = *hash;
    iced_nav_scrollable::subs()
    .with(change)
    .map(|(change, msg)| {
    Msg::View(app::Msg::EntireLogChangeNav { change, msg })
    })
    } else if let Some((hash, _nav)) = state.status_logs.changes_nav.as_ref() {
    let hash = *hash;
    iced_nav_scrollable::subs().with(hash).map(|(hash, msg)| {
    Msg::View(app::Msg::LogChangeNav { change: hash, msg })
    })
    } else {
    Subscription::none()
    };
  • replacement in inflorescence/src/main.rs at line 1390
    [37.8111][46.26727:26844](),[46.26844][28.15853:16086](),[28.15853][28.15853:16086](),[28.16086][40.14543:14744](),[39.525][28.16224:16243](),[40.14744][28.16224:16243](),[28.16224][28.16224:16243]()
    let diff_nav_subs = match state.selection.view.status.as_ref() {
    Some(selection::Status::UntrackedFile {
    ix: _,
    path,
    diff_selected: true,
    }) => {
    let id_hash = file::id_parts_hash(path, file::Kind::Untracked);
    iced_nav_scrollable::subs()
    .with(id_hash)
    .map(|(id_hash, msg)| {
    Msg::View(app::Msg::FileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    })
    [37.8111]
    [28.16243]
    let diff_nav_subs = if let Some(selection) =
    state.selection.view.entire_log.as_ref()
    {
    match selection {
    selection::LogChange {
    ix: _,
    hash,
    message: _,
    file:
    Some(selection::LogChangeFileSelection {
    ix: _,
    path,
    diff_selected: true,
    }),
    } => {
    let id_hash = file::log_id_parts_hash(*hash, path);
    iced_nav_scrollable::subs().with(id_hash).map(
    |(id_hash, msg)| {
    Msg::View(app::Msg::LogChangeFileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    },
    )
    }
    _ => Subscription::none(),
  • replacement in inflorescence/src/main.rs at line 1417
    [28.16253][46.26845:26891](),[46.26891][28.16299:16530](),[28.16299][28.16299:16530](),[28.16530][40.14745:14946](),[39.576][28.16668:16697](),[40.14946][28.16668:16697](),[28.16668][28.16668:16697](),[28.16697][46.26892:26936](),[46.26936][28.16741:16820](),[28.16741][28.16741:16820](),[28.16820][46.26937:26994](),[46.26994][28.16874:17224](),[28.16874][28.16874:17224](),[28.17224][39.577:627](),[39.627][28.17280:17299](),[28.17280][28.17280:17299]()
    Some(selection::Status::ChangedFile {
    ix: _,
    path,
    diff_selected: true,
    }) => {
    let id_hash = file::id_parts_hash(path, file::Kind::Changed);
    iced_nav_scrollable::subs()
    .with(id_hash)
    .map(|(id_hash, msg)| {
    Msg::View(app::Msg::FileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    })
    }
    Some(selection::Status::LogChange {
    ix: _,
    hash,
    message: _,
    file:
    Some(selection::LogChangeFileSelection {
    ix: _,
    path,
    diff_selected: true,
    }),
    }) => {
    let id_hash = file::log_id_parts_hash(*hash, path);
    iced_nav_scrollable::subs()
    .with(id_hash)
    .map(|(id_hash, msg)| Msg::LogDiffNav {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    [28.16253]
    [28.17299]
    } else {
    match state.selection.view.status.as_ref() {
    Some(selection::Status::UntrackedFile {
    ix: _,
    path,
    diff_selected: true,
    }) => {
    let id_hash = file::id_parts_hash(path, file::Kind::Untracked);
    iced_nav_scrollable::subs().with(id_hash).map(
    |(id_hash, msg)| {
    Msg::View(app::Msg::FileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    },
    )
    }
    Some(selection::Status::ChangedFile {
    ix: _,
    path,
    diff_selected: true,
    }) => {
    let id_hash = file::id_parts_hash(path, file::Kind::Changed);
    iced_nav_scrollable::subs().with(id_hash).map(
    |(id_hash, msg)| {
    Msg::View(app::Msg::FileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    },
    )
    }
    Some(selection::Status::LogChange(selection::LogChange {
    ix: _,
    hash,
    message: _,
    file:
    Some(selection::LogChangeFileSelection {
    ix: _,
    path,
    diff_selected: true,
    }),
    })) => {
    let id_hash = file::log_id_parts_hash(*hash, path);
    iced_nav_scrollable::subs().with(id_hash).map(
    |(id_hash, msg)| {
    Msg::View(app::Msg::LogChangeFileDiff {
    id_hash,
    msg: diff::Msg::DiffNav(msg),
    })
    },
    )
    }
    Some(selection::Status::UntrackedFile { .. })
    | Some(selection::Status::ChangedFile { .. })
    | Some(selection::Status::LogChange { .. })
    | None => Subscription::none(),
  • edit in inflorescence/src/main.rs at line 1475
    [28.17309][46.26995:27155](),[46.27155][28.17469:17509](),[28.17469][28.17469:17509]()
    Some(selection::Status::UntrackedFile { .. })
    | Some(selection::Status::ChangedFile { .. })
    | Some(selection::Status::LogChange { .. })
    | None => Subscription::none(),
  • replacement in inflorescence/src/main.rs at line 1499
    [28.17598][40.14969:14983]()
    logs,
    [28.17598]
    [16.28717]
    status_logs,
    entire_logs,
  • replacement in inflorescence/src/main.rs at line 1576
    [26.6792][46.27448:27492]()
    Some(selection::Status::LogChange {
    [26.6792]
    [40.16714]
    Some(selection::Status::LogChange(selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    })) => {
    let file = file.as_ref().map(
    |selection::LogChangeFileSelection {
    ix: change_ix,
    path,
    diff_selected,
    }| {
    let id_hash = file::log_id_parts_hash(*hash, path);
    let nav = status_logs.diffs_nav.as_ref().and_then(
    |(nav_id_hash, nav)| {
    (*nav_id_hash == id_hash).then_some(nav)
    },
    );
    let diff = status_logs.diffs.get(&id_hash).zip(nav).map(
    |(diff::FileAndState { file, state }, nav)| app::Diff {
    is_selected: *diff_selected,
    file,
    state,
    nav,
    },
    );
    app::LogChangeFileSelection {
    ix: *change_ix,
    path,
    diff,
    }
    },
    );
    let nav = status_logs
    .changes_nav
    .as_ref()
    .and_then(|(nav_hash, nav)| (nav_hash == hash).then_some(nav));
    Some(app::StatusSelection::Log {
    ix: *log_ix,
    hash: *hash,
    message,
    file,
    nav,
    })
    }
    None => None,
    };
    let entire_log_selection = match selection.view.entire_log.as_ref() {
    Some(selection::LogChange {
  • replacement in inflorescence/src/main.rs at line 1638
    [40.17064][43.863:927]()
    let nav = logs.diffs_nav.as_ref().and_then(
    [40.17064]
    [43.927]
    let nav = entire_logs.diffs_nav.as_ref().and_then(
  • replacement in inflorescence/src/main.rs at line 1643
    [43.1093][43.1093:1163]()
    let diff = logs.diffs.get(&id_hash).zip(nav).map(
    [43.1093]
    [43.1163]
    let diff = entire_logs.diffs.get(&id_hash).zip(nav).map(
  • replacement in inflorescence/src/main.rs at line 1658
    [40.18037][40.18037:18064]()
    let nav = logs
    [40.18037]
    [40.18064]
    let nav = entire_logs
  • replacement in inflorescence/src/main.rs at line 1662
    [40.18199][46.27547:27592]()
    Some(app::StatusSelection::Log {
    [40.18199]
    [40.18238]
    Some(app::EntireLogSelection {
  • edit in inflorescence/src/main.rs at line 1680
    [46.27679]
    [40.18591]
    entire_log_selection,
  • replacement in inflorescence/src/diff.rs at line 39
    [28.19964][28.19964:19988]()
    /// `change_hashes`
    [28.19964]
    [28.19988]
    /// `change_file_counts`'s keys
  • replacement in iced_nav_scrollable/src/lib.rs at line 282
    [42.844][42.844:1150]()
    debug_assert_eq!(unmatched_sections, 0,"The `NavScrollable` was most likely initialized with a count different from the number of actual children given to the the view function. Actual number is {}, but got only {} children", nav.section_heights.len(), nav.section_heights.len() - unmatched_sections);
    [42.844]
    [42.1150]
    debug_assert_eq!(unmatched_sections, 0,"The `NavScrollable` was most likely initialized with a count different from the number of actual children given to the the view function. Initialized with {}, but viewing only {} children", nav.section_heights.len(), nav.section_heights.len() - unmatched_sections);