allow to init new repo in existing dir and improve dir picker view

tzemanovic
Feb 11, 2026, 12:07 PM
I7EWMAHYKQWG7RJS3WERQHF5Z7IKGYW76TGVZFOBMSX23AA4MAKQC

Dependencies

  • [2] PKJCFSBM theme improvements
  • [3] YRGDFHAB project dir picker
  • [4] LPSUBGUB add projects picker
  • [5] MORKDJUE use allowed actions binding for key subs
  • [6] 5BAPU7K6 dir picker key navigation
  • [7] TMDH7GPV dir picker scrollables handling + confirmation
  • [8] J3AD2D2J improve push and pull keys
  • [9] IOXNOVX2 allow to initiate a new repo
  • [10] LA45PKNR improve hierachical selection highlighting
  • [11] MYGIBRRH wip custom theme
  • [*] 23SFYK4Q big view refactor into a new crate
  • [*] EJPSD5XO shared allowed actions conditions between update and view
  • [*] 6YZAVBWU Initial commit

Change contents

  • replacement in inflorescence_view/src/view.rs at line 165
    [6.72][6.72:112]()
    theme::Container::Bordered,
    [6.72]
    [6.112]
    theme::Container::FadedBorder,
  • edit in inflorescence_view/src/view.rs at line 171
    [6.314]
    [6.314]
    theme::Text::SlightlyFaded,
  • replacement in inflorescence_view/src/theme.rs at line 102
    [2.1352][3.23477:23491]()
    Bordered,
    [2.1352]
    [2.1352]
    FadedBorder,
  • replacement in inflorescence_view/src/theme.rs at line 265
    [2.2255][3.23492:23546]()
    Container::Bordered => container::Style {
    [2.2255]
    [3.23546]
    Container::FadedBorder => container::Style {
  • replacement in inflorescence_view/src/theme.rs at line 267
    [3.23579][3.23579:23636]()
    color: Color { a: 0.3, ..TURQOISE },
    [3.23579]
    [3.23636]
    color: TEXT_COLOR_FADED,
  • edit in inflorescence_model/src/action.rs at line 310
    [6.1972]
    [6.1972]
    current_kind,
  • replacement in inflorescence_model/src/action.rs at line 404
    [5.172698][7.56:128](),[7.128][8.45299:45336](),[8.45336][7.165:260](),[7.165][7.165:260](),[7.260][8.45337:45382](),[8.45382][7.305:495](),[7.305][7.305:495](),[7.495][8.45383:45432]()
    push_if(
    matches!(selection, dir_picker::Selection::Input),
    || confirm("confirm input"),
    ma,
    );
    push_if(
    matches!(selection, dir_picker::Selection::SubDir(_)),
    || confirm("confirm dir selection"),
    ma,
    );
    push_if(
    matches!(
    selection,
    dir_picker::Selection::ProjectPijul(_)
    | dir_picker::Selection::ProjectGit(_)
    ),
    || confirm("confirm project selection"),
    [5.172698]
    [7.544]
    push(
    || {
    confirm(match current_kind {
    Some(dir_picker::RepoKind::Pijul) => "open Pijul repository",
    Some(dir_picker::RepoKind::Git) => "import from Git",
    None => "initialize new repository",
    })
    },
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 14
    [3.415][3.415:447]()
    use std::collections::VecDeque;
    [3.415]
    [3.447]
    use std::collections::{BTreeSet, VecDeque};
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 25
    [6.6003]
    [6.6003]
    pub current_kind: Option<RepoKind>,
    /// Absolute paths with the child directories of the `current_dir`
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 28
    [6.6037]
    [6.6037]
    /// Relative paths with the child directories of the `current_dir` matching
    /// current `input`
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 63
    [3.1403]
    [3.1403]
    FindReposDirsDone,
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 93
    [3.2430]
    [3.2430]
    let mut state = State {
    left_nav: nav_scrollable::State::default(),
    right_nav: nav_scrollable::State::default(),
    input: String::default(),
    current_dir,
    current_kind: None,
    child_dirs: vec![],
    matched_child_dirs: vec![],
    found_repos_dirs_pijul: vec![],
    found_repos_dirs_git: vec![],
    find_child_dirs_handle,
    find_repos_handle,
    matcher: Matcher::default(),
    selection: Selection::default(),
    };
    update_current_kind(&mut state);
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 110
    [3.2436][3.2436:2894](),[3.2894][6.6472:6517](),[6.6517][3.2894:2905](),[3.2894][3.2894:2905]()
    State {
    left_nav: nav_scrollable::State::default(),
    right_nav: nav_scrollable::State::default(),
    input: String::default(),
    current_dir,
    child_dirs: vec![],
    matched_child_dirs: vec![],
    found_repos_dirs_pijul: vec![],
    found_repos_dirs_git: vec![],
    find_child_dirs_handle,
    find_repos_handle,
    matcher: Matcher::default(),
    selection: Selection::default(),
    },
    [3.2436]
    [3.2905]
    state,
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 185
    [3.6287][7.1626:1627]()
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 218
    [3.7649]
    [3.7649]
    state.find_child_dirs_handle = None;
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 233
    [3.8101]
    [3.8101]
    Msg::FindReposDirsDone => {
    state.find_repos_handle = None;
    Task::none()
    }
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 243
    [3.8226]
    [3.8226]
    update_current_kind(state);
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 552
    [6.13997]
    [3.8245]
    update_current_kind(state);
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 641
    [6.14423]
    [3.8376]
    text_class_decorative: <Theme as text::Catalog>::Class<'a>,
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 652
    [6.14530]
    [3.8579]
    <Theme as text::Catalog>::Class<'a>: Copy,
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 669
    [6.14550]
    [3.9009]
    current_kind: _,
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 741
    [3.11593][3.11593:11656]()
    .shaping(text::Shaping::Advanced),
    [3.11593]
    [3.11656]
    .shaping(text::Shaping::Advanced)
    .class(text_class_decorative),
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 779
    [3.12660][3.12660:12719]()
    .shaping(text::Shaping::Advanced),
    [3.12660]
    [3.12719]
    .shaping(text::Shaping::Advanced)
    .class(text_class_decorative),
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 927
    [3.15713][3.15713:15754]()
    let mut child_dirs = vec![];
    [3.15713]
    [3.15754]
    let mut child_dirs = BTreeSet::new();
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 932
    [3.15990][3.15990:16033]()
    child_dirs.push(path);
    [3.15990]
    [3.16033]
    child_dirs.insert(path);
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 935
    [3.16065][3.16065:16092]()
    Ok(child_dirs)
    [3.16065]
    [3.16092]
    Ok(child_dirs.into_iter().collect())
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 963
    [4.15831][3.17198:17253](),[3.17198][3.17198:17253]()
    yield (path, RepoKind::Pijul);
    [4.15831]
    [3.17253]
    yield Some((path, RepoKind::Pijul));
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 966
    [4.15876][3.17361:17414](),[3.17361][3.17361:17414]()
    yield (path, RepoKind::Git);
    [4.15876]
    [3.17414]
    yield Some((path, RepoKind::Git));
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 973
    [3.17555]
    [3.17555]
    yield None
  • replacement in inflorescence_iced_widget/src/dir_picker.rs at line 978
    [3.17657][3.17657:17728]()
    Ok((dir, kind)) => Msg::FindReposDirsSuccess((dir, kind)),
    [3.17657]
    [3.17728]
    Ok(Some((dir, kind))) => Msg::FindReposDirsSuccess((dir, kind)),
    Ok(None) => Msg::FindReposDirsDone,
  • edit in inflorescence_iced_widget/src/dir_picker.rs at line 1010
    [3.18535]
    [4.15877]
    fn update_current_kind(state: &mut State) {
    let path_to_check = match &state.selection {
    Selection::Input => {
    Some(state.current_dir.join(&state.input).into_path_buf())
    }
    Selection::SubDir(ix) => {
    Some(if !state.matched_child_dirs.is_empty() {
    let subdir = state.matched_child_dirs.get(*ix).unwrap();
    state.current_dir.join(subdir).into_path_buf()
    } else {
    state.child_dirs.get(*ix).unwrap().clone()
    })
    }
    Selection::ProjectPijul(_) => {
    state.current_kind = Some(RepoKind::Pijul);
    None
    }
    Selection::ProjectGit(_) => {
    state.current_kind = Some(RepoKind::Git);
    None
    }
    };
    if let Some(path) = path_to_check {
    if is_pijul(path.as_path()) {
    state.current_kind = Some(RepoKind::Pijul);
    } else if is_git(path.as_path()) {
    state.current_kind = Some(RepoKind::Git);
    } else {
    state.current_kind = None;
    }
    }
    }
  • replacement in inflorescence/src/main.rs at line 784
    [9.3066][9.3066:3991]()
    // If it contains Pijul repo, init ManagingRepo state
    // TODO: If it contains Git, offer to migrate it
    // TODO: Otherwise, offer to init Pijul from scratch
    let project = store::Project {
    last_closed_time: cmp::Reverse(None),
    path: dir.clone(),
    };
    let store_project_task =
    if repo::is_pijul(&project.path) {
    Task::perform(
    async move {
    store::upsert_project(project).await
    },
    Msg::UpsertProjectResult,
    )
    } else {
    Task::none()
    [9.3066]
    [9.3991]
    if repo::is_pijul(&dir) {
    // If it contains Pijul repo, init ManagingRepo
    // state
    let project = store::Project {
    last_closed_time: cmp::Reverse(None),
    path: dir.clone(),
  • replacement in inflorescence/src/main.rs at line 791
    [9.4022][9.4022:4296]()
    let (sub, managing_repo, managing_repo_task) =
    init_managing_repo(dir, report);
    new_state = Some((sub, managing_repo));
    Task::batch([managing_repo_task, store_project_task])
    [9.4022]
    [9.4296]
    let store_project_task = Task::perform(
    async move { store::upsert_project(project).await },
    Msg::UpsertProjectResult,
    );
    let (sub, managing_repo, managing_repo_task) =
    init_managing_repo(dir, report);
    new_state = Some((sub, managing_repo));
    Task::batch([
    managing_repo_task,
    store_project_task,
    ])
    } else {
    if repo::is_git(&dir) {
    // Allow to import from Git or init new Pijul
    // history TODO
    // *sub_menu = Some(model::SubMenu::InitRepo {
    // path: dir.clone(),
    // });
    } else {
    // If it's not Git repo either, allow to
    // initialize Pijul
    *sub_menu = Some(model::SubMenu::InitRepo {
    path: dir.clone(),
    });
    }
    Task::none()
    }