pub use indexmap::IndexSet;
use crate::{action, diff, log, selection, to_record};
use inflorescence_iced_widget::{dir_picker, nav_scrollable, report};
use libflorescence::identity::Id;
use libflorescence::{repo, store};
use iced::widget::text_editor;
use std::collections::HashMap;
use std::path::PathBuf;
pub fn is_ready(state: &ManagingRepo) -> Option<&ReadyState> {
if let ManagingRepoSubState::Ready(state) = &state.sub {
return Some(state);
}
None
}
pub fn is_ready_mut(state: &mut ManagingRepo) -> Option<&mut ReadyState> {
if let ManagingRepoSubState::Ready(state) = &mut state.sub {
return Some(state);
}
None
}
#[derive(Debug)]
pub struct State {
pub sub: SubState,
pub window_size: iced::Size,
pub window_scale: f32,
pub allowed_actions: Vec<action::Binding>,
pub sub_menu: Option<SubMenu>,
pub report: report::Container,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum SubState {
PickingProject(PickingProject),
PickingRepoDir(PickingRepoDir),
ManagingRepo(ManagingRepo),
}
#[derive(Debug)]
pub struct PickingProject {
pub is_blocking: bool,
pub projects: Option<store::Projects>,
pub selection: PickingProjectSelection,
pub projects_nav: nav_scrollable::State,
}
#[derive(Debug, Clone, Copy, Default)]
pub enum PickingProjectSelection {
#[default]
FindOrCreate,
Existing {
ix: usize,
},
}
#[derive(Debug)]
pub struct PickingRepoDir {
pub picker: dir_picker::State,
pub waiting_to_init: Option<ProjectInitKind>,
}
#[derive(Debug, Clone, Copy)]
pub enum ProjectInitKind {
New,
ImportFromGit,
}
#[derive(Debug)]
pub struct ManagingRepo {
pub repo_path: PathBuf,
pub sub: ManagingRepoSubState,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum SubMenu {
Push {
remote: Option<String>,
opt: Option<PushOption>,
},
Pull {
remote: Option<String>,
opt: Option<PullOption>,
},
ResetChange,
InitRepo {
path: PathBuf,
},
ImportFromGit {
path: PathBuf,
},
Add {
recursive: bool,
},
CompareRemote {
remote: Option<String>,
remote_channel: Option<String>,
opt: Option<CompareRemoteOption>,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum PushOption {
SelectingRemote {
remote: Option<String>,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum PullOption {
SelectingRemote {
remote: Option<String>,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum CompareRemoteOption {
SelectingRemote {
remote: Option<String>,
},
InputingRemoteChannel {
channel: Option<String>,
},
}
#[allow(
clippy::large_enum_variant,
reason = "There's only ever 1 instance and the small sized cases are expected to always turn into the largest `Ready` case"
)]
#[derive(Debug)]
pub enum ManagingRepoSubState {
Loading {
user_ids: Option<Vec<Id>>,
repo: Option<repo::State>,
},
SelectingIdentity {
ids: Vec<Id>,
selection_ix: usize,
selection_nav: nav_scrollable::State,
confirmed_selection_ix: Option<usize>,
repo: Option<repo::State>,
},
NoIdFound {
repo: Option<repo::State>,
},
Ready(ReadyState),
}
#[derive(Debug)]
pub struct ReadyState {
pub user_id: Id,
pub repo: repo::State,
pub selection: selection::State,
pub navigation: Navigation,
pub record_changes: Option<RecordChanges>,
pub forking_channel_name: Option<String>,
pub logs: Logs,
pub to_record: to_record::State,
pub jobs: IndexSet<Job>,
pub record_dichotomy:
HashMap<String, HashMap<String, repo::RecordDichotomy>>,
}
pub fn get_record_dichotomy<'a>(
record_dichotomy: &'a HashMap<
String,
HashMap<String, repo::RecordDichotomy>,
>,
remote: &str,
remote_channel: &str,
) -> Option<&'a repo::RecordDichotomy> {
record_dichotomy
.get(remote)
.and_then(|map| map.get(remote_channel))
}
pub fn get_record_dichotomy_mut<'a>(
record_dichotomy: &'a mut HashMap<
String,
HashMap<String, repo::RecordDichotomy>,
>,
remote: &str,
channel: &str,
) -> Option<&'a mut repo::RecordDichotomy> {
record_dichotomy
.get_mut(remote)
.and_then(|map| map.get_mut(channel))
}
#[derive(Debug)]
pub enum RecordChanges {
Typing {
msg: String,
desc: text_editor::Content,
},
Canceled {
old_msg: String,
old_desc: String,
},
}
#[derive(Debug, Default)]
pub struct Navigation {
pub status_nav: nav_scrollable::State,
pub status_logs_navs: log::Navs,
pub other_channels_nav: nav_scrollable::State,
pub other_channel_log_nav: nav_scrollable::State,
#[cfg(debug_assertions)]
pub other_channel_name: Option<String>,
pub other_channel_logs_navs: log::Navs,
pub entire_log_nav: nav_scrollable::State,
pub entire_logs_navs: log::Navs,
pub compare_remote_nav: nav_scrollable::State,
pub compare_remote_navs: log::Navs,
pub files_diffs: diff::FilesState,
pub log_diffs: log::FilesAndState,
}
#[derive(Debug, Default)]
pub struct Logs {
pub entire_log: Option<Log>,
pub other_channels_logs: HashMap<String, Log>,
}
#[derive(Debug)]
pub enum Log {
Loading,
Loaded { log: repo::Log },
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum Job {
Pull {
remote: String,
channel: String,
},
Push {
remote: String,
channel: String,
},
CompareRemote {
remote: String,
remote_channel: String,
},
}
pub fn init_channel_nav(
navigation: &mut Navigation,
#[cfg(debug_assertions)] name: String,
) {
navigation.other_channel_log_nav = nav_scrollable::State::default();
navigation.other_channel_logs_navs = log::Navs::default();
#[cfg(debug_assertions)]
{
navigation.other_channel_name = Some(name);
}
}