selection.rs
use libflorescence::file::Path;
use libflorescence::repo;
use iced::time::Instant;
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum Msg {
/// Directional key press
PressDir(Dir),
/// Directional key press with a modifier
AltPressDir(Dir),
}
/// Msgs that do not need to be explicitly allowed (see
/// [`crate::action::is_allowed`])
#[derive(Debug, Clone, PartialEq)]
pub enum UnfilteredMsg {
/// Directional key release
ReleaseDir(Dir),
/// Mouse select
Select(Select),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dir {
Down,
Up,
Right,
Left,
}
#[derive(Debug, Default)]
pub struct State {
/// Primary selection state. This is distinct from `status`, `channel`,
/// `entire_log` sub-states fields to which each case corresponds, because
/// they are preserved in different primary selection states.
pub primary: Primary,
/// Sub-selection in [`Primary::Status`] state
pub status: Option<Status>,
/// Sub-selection in [`Primary::Channel`] state
pub channel: Option<Channel>,
/// Sub-selection in [`Primary::EntireLog`] state
pub entire_log: Option<LogChange>,
/// Sub-selection in [`Primary::CompareRemote`] state
pub compare_remote: Option<CompareRemote>,
/// Last directional key down that's not yet been released
pub held_key: Option<HeldKey>,
}
#[derive(Debug)]
pub enum Unified<'a> {
Status(Option<&'a Status>),
Channel(Option<&'a Channel>),
EntireLog(Option<&'a LogChange>),
CompareRemote(Option<&'a CompareRemote>),
}
#[derive(Debug, Default, Clone, Copy)]
pub enum Primary {
#[default]
Status,
Channel,
EntireLog,
CompareRemote,
}
#[derive(Debug)]
pub struct HeldKey {
pub dir: Dir,
pub last_tick: Instant,
}
#[derive(Debug)]
pub enum Status {
UntrackedFile {
ix: usize,
path: Path,
diff_selected: bool,
},
ChangedFile {
ix: usize,
path: Path,
diff_selected: bool,
},
LogChange(LogChange),
}
#[derive(Debug)]
pub struct LogChangeFileSelection {
pub ix: usize,
pub path: String,
pub diff_selected: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Select {
UntrackedFile {
ix: usize,
path: Path,
},
ChangedFile {
ix: usize,
path: Path,
},
LogChange {
ix: usize,
hash: repo::ChangeHash,
message: String,
},
LogChangeFile {
ix: usize,
path: String,
},
Channel {
ix: usize,
name: String,
},
CompareRemote {
ix: usize,
},
CompareRemoteFile {
ix: usize,
path: String,
},
}
#[derive(Debug)]
pub struct Channel {
pub ix: usize,
pub name: String,
pub log: Option<LogChange>,
}
#[derive(Debug)]
pub struct LogChange {
pub ix: usize,
pub hash: repo::ChangeHash,
pub message: String,
pub file: Option<LogChangeFileSelection>,
}
#[derive(Debug)]
pub struct CompareRemote {
pub ix: Option<usize>,
pub hash: Option<repo::ChangeHash>,
pub file: Option<LogChangeFileSelection>,
pub remote: String,
pub remote_channel: String,
}
pub fn unify(state: &State) -> Unified<'_> {
let State {
primary,
status,
channel,
entire_log,
compare_remote,
held_key: _,
} = state;
match primary {
Primary::Status => Unified::Status(status.as_ref()),
Primary::Channel => Unified::Channel(channel.as_ref()),
Primary::EntireLog => Unified::EntireLog(entire_log.as_ref()),
Primary::CompareRemote => {
Unified::CompareRemote(compare_remote.as_ref())
}
}
}