From 0383f9517b433f65e705c41b1ce91cb499ae0473 Mon Sep 17 00:00:00 2001 From: Alexandru Macovei Date: Mon, 3 Oct 2022 13:01:39 +0300 Subject: (refactor) shorten component creation by grouping common items in an Environment --- src/app.rs | 280 +++++++---------------- src/components/blame_file.rs | 23 +- src/components/branchlist.rs | 16 +- src/components/changes.rs | 24 +- src/components/commit.rs | 27 +-- src/components/commit_details/compare_details.rs | 11 +- src/components/commit_details/details.rs | 14 +- src/components/commit_details/mod.rs | 42 +--- src/components/commitlist.rs | 17 +- src/components/compare_commits.rs | 42 +--- src/components/create_branch.rs | 23 +- src/components/cred.rs | 14 +- src/components/diff.rs | 20 +- src/components/externaleditor.rs | 10 +- src/components/fetch.rs | 26 +-- src/components/file_revlog.rs | 35 +-- src/components/fuzzy_find_popup.rs | 22 +- src/components/help.rs | 10 +- src/components/inspect_commit.rs | 42 +--- src/components/log_search_popup.rs | 25 +- src/components/msg.rs | 10 +- src/components/options_popup.rs | 16 +- src/components/pull.rs | 29 +-- src/components/push.rs | 28 +-- src/components/push_tags.rs | 27 +-- src/components/rename_branch.rs | 22 +- src/components/reset.rs | 13 +- src/components/reset_popup.rs | 22 +- src/components/revision_files.rs | 32 +-- src/components/revision_files_popup.rs | 32 +-- src/components/stashmsg.rs | 22 +- src/components/status_tree.rs | 83 +++---- src/components/submodules.rs | 16 +- src/components/syntax_text.rs | 19 +- src/components/tag_commit.rs | 18 +- src/components/taglist.rs | 23 +- src/components/textinput.rs | 32 +-- src/main.rs | 4 +- src/options.rs | 11 + src/tabs/files.rs | 32 +-- src/tabs/revlog.rs | 51 ++--- src/tabs/stashing.rs | 29 +-- src/tabs/stashlist.rs | 22 +- src/tabs/status.rs | 62 ++--- 44 files changed, 467 insertions(+), 911 deletions(-) (limited to 'src') diff --git a/src/app.rs b/src/app.rs index 2bdb2754..3278d0bf 100644 --- a/src/app.rs +++ b/src/app.rs @@ -113,14 +113,41 @@ pub struct App { file_to_open: Option, } +pub struct Environment { + pub queue: Queue, + pub theme: SharedTheme, + pub key_config: SharedKeyConfig, + pub repo: RepoPathRef, + pub options: SharedOptions, + pub sender_git: Sender, + pub sender_app: Sender, +} + +/// The need to construct a "whatever" environment only arises in testing right now +#[cfg(test)] +impl Default for Environment { + fn default() -> Self { + use crossbeam_channel::unbounded; + Self { + queue: Queue::new(), + theme: Default::default(), + key_config: Default::default(), + repo: RefCell::new(RepoPath::Path(Default::default())), + options: Default::default(), + sender_git: unbounded().0, + sender_app: unbounded().0, + } + } +} + // public interface impl App { /// #[allow(clippy::too_many_lines)] pub fn new( repo: RepoPathRef, - sender: &Sender, - sender_app: &Sender, + sender_git: Sender, + sender_app: Sender, input: Input, theme: Theme, key_config: KeyConfig, @@ -130,219 +157,66 @@ impl App { let repo_path_text = repo_work_dir(&repo.borrow()).unwrap_or_default(); - let queue = Queue::new(); - let theme = Rc::new(theme); - let key_config = Rc::new(key_config); - let options = Options::new(repo.clone()); + let env = Environment { + queue: Queue::new(), + theme: Rc::new(theme), + key_config: Rc::new(key_config), + options: Options::new(repo.clone()), + repo, + sender_git, + sender_app, + }; - let tab = options.borrow().current_tab(); + let tab = env.options.borrow().current_tab(); let mut app = Self { input, - reset: ConfirmComponent::new( - queue.clone(), - theme.clone(), - key_config.clone(), - ), - commit: CommitComponent::new( - repo.clone(), - queue.clone(), - theme.clone(), - key_config.clone(), - options.clone(), - ), + reset: ConfirmComponent::new(&env), + commit: CommitComponent::new(&env), blame_file_popup: BlameFileComponent::new( - &repo, - &queue, - sender, - &strings::blame_title(&key_config), - theme.clone(), - key_config.clone(), - ), - file_revlog_popup: FileRevlogComponent::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - options.clone(), - ), - revision_files_popup: RevisionFilesPopup::new( - repo.clone(), - &queue, - sender_app, - sender.clone(), - theme.clone(), - key_config.clone(), - ), - stashmsg_popup: StashMsgComponent::new( - repo.clone(), - queue.clone(), - theme.clone(), - key_config.clone(), - ), - inspect_commit_popup: InspectCommitComponent::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - options.clone(), - ), - compare_commits_popup: CompareCommitsComponent::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - options.clone(), - ), - external_editor_popup: ExternalEditorComponent::new( - theme.clone(), - key_config.clone(), - ), - push_popup: PushComponent::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - ), - push_tags_popup: PushTagsComponent::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - ), - reset_popup: ResetPopupComponent::new( - &queue, - &repo, - theme.clone(), - key_config.clone(), - ), - pull_popup: PullComponent::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - ), - fetch_popup: FetchComponent::new( - repo.clone(), - &queue, - sender, - theme.clone(), - key_config.clone(), - ), - tag_commit_popup: TagCommitComponent::new( - repo.clone(), - queue.clone(), - theme.clone(), - key_config.clone(), - ), - create_branch_popup: CreateBranchComponent::new( - repo.clone(), - queue.clone(), - theme.clone(), - key_config.clone(), - ), - rename_branch_popup: RenameBranchComponent::new( - repo.clone(), - queue.clone(), - theme.clone(), - key_config.clone(), - ), - select_branch_popup: BranchListComponent::new( - repo.clone(), - queue.clone(), - theme.clone(), - key_config.clone(), - ), - tags_popup: TagListComponent::new( - repo.clone(), - &queue, - sender, - theme.clone(), - key_config.clone(), - ), - options_popup: OptionsPopupComponent::new( - &queue, - theme.clone(), - key_config.clone(), - options.clone(), - ), - submodule_popup: SubmodulesListComponent::new( - repo.clone(), - &queue, - theme.clone(), - key_config.clone(), - ), - log_search_popup: LogSearchPopupComponent::new( - repo.clone(), - &queue, - theme.clone(), - key_config.clone(), - ), - fuzzy_find_popup: FuzzyFindPopup::new( - &queue, - theme.clone(), - key_config.clone(), + &env, + &strings::blame_title(&env.key_config), ), + file_revlog_popup: FileRevlogComponent::new(&env), + revision_files_popup: RevisionFilesPopup::new(&env), + stashmsg_popup: StashMsgComponent::new(&env), + inspect_commit_popup: InspectCommitComponent::new(&env), + compare_commits_popup: CompareCommitsComponent::new(&env), + external_editor_popup: ExternalEditorComponent::new(&env), + push_popup: PushComponent::new(&env), + push_tags_popup: PushTagsComponent::new(&env), + reset_popup: ResetPopupComponent::new(&env), + pull_popup: PullComponent::new(&env), + fetch_popup: FetchComponent::new(&env), + tag_commit_popup: TagCommitComponent::new(&env), + create_branch_popup: CreateBranchComponent::new(&env), + rename_branch_popup: RenameBranchComponent::new(&env), + select_branch_popup: BranchListComponent::new(&env), + tags_popup: TagListComponent::new(&env), + options_popup: OptionsPopupComponent::new(&env), + submodule_popup: SubmodulesListComponent::new(&env), + log_search_popup: LogSearchPopupComponent::new(&env), + fuzzy_find_popup: FuzzyFindPopup::new(&env), do_quit: QuitState::None, cmdbar: RefCell::new(CommandBar::new( - theme.clone(), - key_config.clone(), + env.theme.clone(), + env.key_config.clone(), )), - help: HelpComponent::new( - theme.clone(), - key_config.clone(), - ), - msg: MsgComponent::new(theme.clone(), key_config.clone()), - revlog: Revlog::new( - &repo, - &queue, - sender, - theme.clone(), - key_config.clone(), - ), - status_tab: Status::new( - repo.clone(), - &queue, - sender, - theme.clone(), - key_config.clone(), - options.clone(), - ), - stashing_tab: Stashing::new( - &repo, - sender, - &queue, - theme.clone(), - key_config.clone(), - ), - stashlist_tab: StashList::new( - repo.clone(), - &queue, - theme.clone(), - key_config.clone(), - ), - files_tab: FilesTab::new( - repo.clone(), - sender_app, - sender.clone(), - &queue, - theme.clone(), - key_config.clone(), - ), + help: HelpComponent::new(&env), + msg: MsgComponent::new(&env), + revlog: Revlog::new(&env), + status_tab: Status::new(&env), + stashing_tab: Stashing::new(&env), + stashlist_tab: StashList::new(&env), + files_tab: FilesTab::new(&env), tab: 0, - queue, - theme, - options, - key_config, + queue: env.queue, + theme: env.theme, + options: env.options, + key_config: env.key_config, requires_redraw: Cell::new(false), file_to_open: None, - repo, + repo: env.repo, repo_path_text, popup_stack: PopupStack::default(), }; diff --git a/src/components/blame_file.rs b/src/components/blame_file.rs index 632006fa..2a86aba5 100644 --- a/src/components/blame_file.rs +++ b/src/components/blame_file.rs @@ -4,6 +4,7 @@ use super::{ InspectCommitOpen, }; use crate::{ + app::Environment, components::{utils::string_width_align, ScrollType}, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, @@ -13,10 +14,9 @@ use crate::{ }; use anyhow::Result; use asyncgit::{ - sync::{BlameHunk, CommitId, FileBlame, RepoPathRef}, + sync::{BlameHunk, CommitId, FileBlame}, AsyncBlame, AsyncGitNotification, BlameParams, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -272,28 +272,21 @@ impl Component for BlameFileComponent { impl BlameFileComponent { /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - title: &str, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment, title: &str) -> Self { Self { title: String::from(title), - theme, + theme: env.theme.clone(), async_blame: AsyncBlame::new( - repo.borrow().clone(), - sender, + env.repo.borrow().clone(), + &env.sender_git, ), - queue: queue.clone(), + queue: env.queue.clone(), visible: false, params: None, file_blame: None, open_request: None, table_state: std::cell::Cell::new(TableState::default()), - key_config, + key_config: env.key_config.clone(), current_height: std::cell::Cell::new(0), } } diff --git a/src/components/branchlist.rs b/src/components/branchlist.rs index b097ce6d..d3cc147a 100644 --- a/src/components/branchlist.rs +++ b/src/components/branchlist.rs @@ -4,6 +4,7 @@ use super::{ EventState, FuzzyFinderTarget, InspectCommitOpen, }; use crate::{ + app::Environment, components::ScrollType, keys::{key_match, SharedKeyConfig}, queue::{ @@ -329,12 +330,7 @@ impl Component for BranchListComponent { } impl BranchListComponent { - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { branches: Vec::new(), local: true, @@ -342,11 +338,11 @@ impl BranchListComponent { visible: false, selection: 0, scroll: VerticalScroll::new(), - queue, - theme, - key_config, + queue: env.queue.clone(), + theme: env.theme.clone(), + key_config: env.key_config.clone(), current_height: Cell::new(0), - repo, + repo: env.repo.clone(), } } diff --git a/src/components/changes.rs b/src/components/changes.rs index 3b573a99..af8d68f0 100644 --- a/src/components/changes.rs +++ b/src/components/changes.rs @@ -4,12 +4,12 @@ use super::{ CommandBlocking, DrawableComponent, }; use crate::{ + app::Environment, components::{CommandInfo, Component, EventState}, keys::{key_match, SharedKeyConfig}, options::SharedOptions, queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem}, strings, try_or_popup, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::{ @@ -35,28 +35,18 @@ impl ChangesComponent { //TODO: fix #[allow(clippy::too_many_arguments)] pub fn new( - repo: RepoPathRef, + env: &Environment, title: &str, focus: bool, is_working_dir: bool, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - options: SharedOptions, ) -> Self { Self { - files: StatusTreeComponent::new( - title, - focus, - Some(queue.clone()), - theme, - key_config.clone(), - ), + files: StatusTreeComponent::new(env, title, focus), is_working_dir, - queue, - key_config, - options, - repo, + queue: env.queue.clone(), + key_config: env.key_config.clone(), + options: env.options.clone(), + repo: env.repo.clone(), } } diff --git a/src/components/commit.rs b/src/components/commit.rs index bd762878..8a26ecd3 100644 --- a/src/components/commit.rs +++ b/src/components/commit.rs @@ -65,30 +65,25 @@ const FIRST_LINE_LIMIT: usize = 50; impl CommitComponent { /// - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - options: SharedOptions, - ) -> Self { + pub fn new(env: &crate::app::Environment) -> Self { Self { - queue, + queue: env.queue.clone(), mode: Mode::Normal, input: TextInputComponent::new( - theme.clone(), - key_config.clone(), + env, "", - &strings::commit_msg(&key_config), + &strings::commit_msg(&env.key_config), true, ), - key_config, - git_branch_name: cached::BranchName::new(repo.clone()), + key_config: env.key_config.clone(), + git_branch_name: cached::BranchName::new( + env.repo.clone(), + ), commit_template: None, - theme, - repo, + theme: env.theme.clone(), + repo: env.repo.clone(), commit_msg_history_idx: 0, - options, + options: env.options.clone(), verify: true, } } diff --git a/src/components/commit_details/compare_details.rs b/src/components/commit_details/compare_details.rs index 015e3ff3..2f184a25 100644 --- a/src/components/commit_details/compare_details.rs +++ b/src/components/commit_details/compare_details.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use crate::{ + app::Environment, components::{ commit_details::style::{style_detail, Detail}, dialog_paragraph, @@ -30,16 +31,12 @@ pub struct CompareDetailsComponent { impl CompareDetailsComponent { /// - pub const fn new( - repo: RepoPathRef, - theme: SharedTheme, - focused: bool, - ) -> Self { + pub fn new(env: &Environment, focused: bool) -> Self { Self { data: None, - theme, + theme: env.theme.clone(), focused, - repo, + repo: env.repo.clone(), } } diff --git a/src/components/commit_details/details.rs b/src/components/commit_details/details.rs index 6c1a86c7..e1bce3fd 100644 --- a/src/components/commit_details/details.rs +++ b/src/components/commit_details/details.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ commit_details::style::style_detail, dialog_paragraph, @@ -45,22 +46,17 @@ type WrappedCommitMessage<'a> = impl DetailsComponent { /// - pub const fn new( - repo: RepoPathRef, - theme: SharedTheme, - key_config: SharedKeyConfig, - focused: bool, - ) -> Self { + pub fn new(env: &Environment, focused: bool) -> Self { Self { - repo, + repo: env.repo.clone(), data: None, tags: Vec::new(), - theme, + theme: env.theme.clone(), focused, scroll_to_bottom_next_draw: Cell::new(false), current_width: Cell::new(0), scroll: VerticalScroll::new(), - key_config, + key_config: env.key_config.clone(), } } diff --git a/src/components/commit_details/mod.rs b/src/components/commit_details/mod.rs index 35317670..2e14aeca 100644 --- a/src/components/commit_details/mod.rs +++ b/src/components/commit_details/mod.rs @@ -8,18 +8,15 @@ use super::{ }; use crate::{ accessors, + app::Environment, keys::{key_match, SharedKeyConfig}, - queue::Queue, strings, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::{ - sync::{CommitTags, RepoPathRef}, - AsyncCommitFiles, AsyncGitNotification, CommitFilesParams, + sync::CommitTags, AsyncCommitFiles, CommitFilesParams, }; use compare_details::CompareDetailsComponent; -use crossbeam_channel::Sender; use crossterm::event::Event; use details::DetailsComponent; use ratatui::{ @@ -42,39 +39,18 @@ impl CommitDetailsComponent { accessors!(self, [single_details, compare_details, file_tree]); /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - single_details: DetailsComponent::new( - repo.clone(), - theme.clone(), - key_config.clone(), - false, - ), - compare_details: CompareDetailsComponent::new( - repo.clone(), - theme.clone(), - false, - ), + single_details: DetailsComponent::new(env, false), + compare_details: CompareDetailsComponent::new(env, false), git_commit_files: AsyncCommitFiles::new( - repo.borrow().clone(), - sender, - ), - file_tree: StatusTreeComponent::new( - "", - false, - Some(queue.clone()), - theme, - key_config.clone(), + env.repo.borrow().clone(), + &env.sender_git, ), + file_tree: StatusTreeComponent::new(env, "", false), visible: false, commit: None, - key_config, + key_config: env.key_config.clone(), } } diff --git a/src/components/commitlist.rs b/src/components/commitlist.rs index 7f9cef3a..9f2956b7 100644 --- a/src/components/commitlist.rs +++ b/src/components/commitlist.rs @@ -1,5 +1,6 @@ use super::utils::logitems::{ItemBatch, LogEntry}; use crate::{ + app::Environment, components::{ utils::string_width_align, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, ScrollType, @@ -59,15 +60,9 @@ pub struct CommitList { impl CommitList { /// - pub fn new( - repo: RepoPathRef, - title: &str, - theme: SharedTheme, - queue: Queue, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment, title: &str) -> Self { Self { - repo, + repo: env.repo.clone(), items: ItemBatch::default(), marked: Vec::with_capacity(2), selection: 0, @@ -80,9 +75,9 @@ impl CommitList { remote_branches: BTreeMap::default(), current_size: Cell::new(None), scroll_top: Cell::new(0), - theme, - queue, - key_config, + theme: env.theme.clone(), + queue: env.queue.clone(), + key_config: env.key_config.clone(), title: title.into(), } } diff --git a/src/components/compare_commits.rs b/src/components/compare_commits.rs index db5ea23c..49937c58 100644 --- a/src/components/compare_commits.rs +++ b/src/components/compare_commits.rs @@ -5,11 +5,11 @@ use super::{ }; use crate::{ accessors, + app::Environment, keys::{key_match, SharedKeyConfig}, options::SharedOptions, queue::{InternalEvent, Queue, StackablePopupOpen}, strings, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::{ @@ -17,7 +17,6 @@ use asyncgit::{ AsyncDiff, AsyncGitNotification, CommitFilesParams, DiffParams, DiffType, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -168,37 +167,20 @@ impl CompareCommitsComponent { accessors!(self, [diff, details]); /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - options: SharedOptions, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - repo: repo.clone(), - details: CommitDetailsComponent::new( - repo, - queue, - sender, - theme.clone(), - key_config.clone(), - ), - diff: DiffComponent::new( - repo.clone(), - queue.clone(), - theme, - key_config.clone(), - true, - options.clone(), - ), + repo: env.repo.clone(), + details: CommitDetailsComponent::new(env), + diff: DiffComponent::new(env, true), open_request: None, - git_diff: AsyncDiff::new(repo.borrow().clone(), sender), + git_diff: AsyncDiff::new( + env.repo.borrow().clone(), + &env.sender_git, + ), visible: false, - key_config, - queue: queue.clone(), - options, + key_config: env.key_config.clone(), + queue: env.queue.clone(), + options: env.options.clone(), } } diff --git a/src/components/create_branch.rs b/src/components/create_branch.rs index c81a45b6..c1a30b81 100644 --- a/src/components/create_branch.rs +++ b/src/components/create_branch.rs @@ -4,6 +4,7 @@ use super::{ EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, @@ -95,24 +96,18 @@ impl Component for CreateBranchComponent { impl CreateBranchComponent { /// - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - queue, + queue: env.queue.clone(), input: TextInputComponent::new( - theme.clone(), - key_config.clone(), - &strings::create_branch_popup_title(&key_config), - &strings::create_branch_popup_msg(&key_config), + env, + &strings::create_branch_popup_title(&env.key_config), + &strings::create_branch_popup_msg(&env.key_config), true, ), - theme, - key_config, - repo, + theme: env.theme.clone(), + key_config: env.key_config.clone(), + repo: env.repo.clone(), } } diff --git a/src/components/cred.rs b/src/components/cred.rs index 7cecc85a..f801a550 100644 --- a/src/components/cred.rs +++ b/src/components/cred.rs @@ -4,6 +4,7 @@ use ratatui::{backend::Backend, layout::Rect, Frame}; use asyncgit::sync::cred::BasicAuthCredential; +use crate::app::Environment; use crate::components::{EventState, InputType, TextInputComponent}; use crate::keys::key_match; use crate::{ @@ -13,7 +14,6 @@ use crate::{ }, keys::SharedKeyConfig, strings, - ui::style::SharedTheme, }; /// @@ -27,23 +27,19 @@ pub struct CredComponent { impl CredComponent { /// - pub fn new( - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { + let key_config = env.key_config.clone(); Self { visible: false, input_username: TextInputComponent::new( - theme.clone(), - key_config.clone(), + env, &strings::username_popup_title(&key_config), &strings::username_popup_msg(&key_config), false, ) .with_input_type(InputType::Singleline), input_password: TextInputComponent::new( - theme, - key_config.clone(), + env, &strings::password_popup_title(&key_config), &strings::password_popup_msg(&key_config), false, diff --git a/src/components/diff.rs b/src/components/diff.rs index 6a2d433a..557ce9d8 100644 --- a/src/components/diff.rs +++ b/src/components/diff.rs @@ -4,6 +4,7 @@ use super::{ Direction, DrawableComponent, HorizontalScrollType, ScrollType, }; use crate::{ + app::Environment, components::{CommandInfo, Component, EventState}, keys::{key_match, SharedKeyConfig}, options::SharedOptions, @@ -123,17 +124,10 @@ pub struct DiffComponent { impl DiffComponent { /// - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - is_immutable: bool, - options: SharedOptions, - ) -> Self { + pub fn new(env: &Environment, is_immutable: bool) -> Self { Self { focused: false, - queue, + queue: env.queue.clone(), current: Current::default(), pending: false, selected_hunk: None, @@ -143,11 +137,11 @@ impl DiffComponent { selection: Selection::Single(0), vertical_scroll: VerticalScroll::new(), horizontal_scroll: HorizontalScroll::new(), - theme, - key_config, + theme: env.theme.clone(), + key_config: env.key_config.clone(), is_immutable, - repo, - options, + repo: env.repo.clone(), + options: env.options.clone(), } } /// diff --git a/src/components/externaleditor.rs b/src/components/externaleditor.rs index 61d41e85..b343a9b7 100644 --- a/src/components/externaleditor.rs +++ b/src/components/externaleditor.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -36,14 +37,11 @@ pub struct ExternalEditorComponent { impl ExternalEditorComponent { /// - pub fn new( - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { visible: false, - theme, - key_config, + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } diff --git a/src/components/fetch.rs b/src/components/fetch.rs index 80edaf64..d8a154ab 100644 --- a/src/components/fetch.rs +++ b/src/components/fetch.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ cred::CredComponent, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -20,7 +21,7 @@ use asyncgit::{ }, AsyncFetchJob, AsyncGitNotification, ProgressPercent, }; -use crossbeam_channel::Sender; + use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -45,26 +46,17 @@ pub struct FetchComponent { impl FetchComponent { /// - pub fn new( - repo: RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - queue: queue.clone(), + queue: env.queue.clone(), pending: false, visible: false, - async_fetch: AsyncSingleJob::new(sender.clone()), + async_fetch: AsyncSingleJob::new(env.sender_git.clone()), progress: None, - input_cred: CredComponent::new( - theme.clone(), - key_config.clone(), - ), - theme, - key_config, - repo, + input_cred: CredComponent::new(env), + theme: env.theme.clone(), + key_config: env.key_config.clone(), + repo: env.repo.clone(), } } diff --git a/src/components/file_revlog.rs b/src/components/file_revlog.rs index 6ce4eeac..2366ebda 100644 --- a/src/components/file_revlog.rs +++ b/src/components/file_revlog.rs @@ -1,5 +1,6 @@ use super::utils::logitems::ItemBatch; use super::{visibility_blocking, BlameFileOpen, InspectCommitOpen}; +use crate::app::Environment; use crate::keys::key_match; use crate::options::SharedOptions; use crate::queue::StackablePopupOpen; @@ -70,41 +71,27 @@ pub struct FileRevlogComponent { impl FileRevlogComponent { /// - pub fn new( - repo_path: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - options: SharedOptions, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - theme: theme.clone(), - queue: queue.clone(), - sender: sender.clone(), - diff: DiffComponent::new( - repo_path.clone(), - queue.clone(), - theme, - key_config.clone(), - true, - options.clone(), - ), + theme: env.theme.clone(), + queue: env.queue.clone(), + sender: env.sender_git.clone(), + diff: DiffComponent::new(env, true), git_log: None, git_diff: AsyncDiff::new( - repo_path.borrow().clone(), - sender, + env.repo.borrow().clone(), + &env.sender_git, ), visible: false, - repo_path: repo_path.clone(), + repo_path: env.repo.clone(), open_request: None, table_state: std::cell::Cell::new(TableState::default()), items: ItemBatch::default(), count_total: 0, - key_config, + key_config: env.key_config.clone(), current_width: std::cell::Cell::new(0), current_height: std::cell::Cell::new(0), - options, + options: env.options.clone(), } } diff --git a/src/components/fuzzy_find_popup.rs b/src/components/fuzzy_find_popup.rs index cb9bfd8a..1bc9b052 100644 --- a/src/components/fuzzy_find_popup.rs +++ b/src/components/fuzzy_find_popup.rs @@ -4,6 +4,7 @@ use super::{ TextInputComponent, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, string_utils::trim_length_left, @@ -39,30 +40,21 @@ pub struct FuzzyFindPopup { impl FuzzyFindPopup { /// - pub fn new( - queue: &Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { - let mut find_text = TextInputComponent::new( - theme.clone(), - key_config.clone(), - "", - "start typing..", - false, - ); + pub fn new(env: &Environment) -> Self { + let mut find_text = + TextInputComponent::new(env, "", "start typing..", false); find_text.embed(); Self { - queue: queue.clone(), + queue: env.queue.clone(), visible: false, query: None, find_text, - theme, + theme: env.theme.clone(), contents: Vec::new(), filtered: Vec::new(), selected_index: None, - key_config, + key_config: env.key_config.clone(), selection: 0, target: None, } diff --git a/src/components/help.rs b/src/components/help.rs index 6fd6eee6..314e1a9d 100644 --- a/src/components/help.rs +++ b/src/components/help.rs @@ -3,6 +3,7 @@ use super::{ DrawableComponent, EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, strings, ui, version::Version, @@ -167,16 +168,13 @@ impl Component for HelpComponent { } impl HelpComponent { - pub const fn new( - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { cmds: vec![], visible: false, selection: 0, - theme, - key_config, + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } /// diff --git a/src/components/inspect_commit.rs b/src/components/inspect_commit.rs index 664e6c2d..1d737e69 100644 --- a/src/components/inspect_commit.rs +++ b/src/components/inspect_commit.rs @@ -5,18 +5,17 @@ use super::{ }; use crate::{ accessors, + app::Environment, keys::{key_match, SharedKeyConfig}, options::SharedOptions, queue::{InternalEvent, Queue, StackablePopupOpen}, strings, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::{ - sync::{CommitId, CommitTags, RepoPathRef}, + sync::{CommitId, CommitTags}, AsyncDiff, AsyncGitNotification, DiffParams, DiffType, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -204,36 +203,19 @@ impl InspectCommitComponent { accessors!(self, [diff, details]); /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - options: SharedOptions, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - queue: queue.clone(), - details: CommitDetailsComponent::new( - repo, - queue, - sender, - theme.clone(), - key_config.clone(), - ), - diff: DiffComponent::new( - repo.clone(), - queue.clone(), - theme, - key_config.clone(), - true, - options.clone(), - ), + queue: env.queue.clone(), + details: CommitDetailsComponent::new(env), + diff: DiffComponent::new(env, true), open_request: None, - git_diff: AsyncDiff::new(repo.borrow().clone(), sender), + git_diff: AsyncDiff::new( + env.repo.borrow().clone(), + &env.sender_git, + ), visible: false, - key_config, - options, + key_config: env.key_config.clone(), + options: env.options.clone(), } } diff --git a/src/components/log_search_popup.rs b/src/components/log_search_popup.rs index 3f90a0d0..f8f29ec8 100644 --- a/src/components/log_search_popup.rs +++ b/src/components/log_search_popup.rs @@ -3,6 +3,7 @@ use super::{ DrawableComponent, EventState, TextInputComponent, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, strings::{self, POPUP_COMMIT_SHA_INVALID}, @@ -55,33 +56,23 @@ pub struct LogSearchPopupComponent { impl LogSearchPopupComponent { /// - pub fn new( - repo: RepoPathRef, - queue: &Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { - let mut find_text = TextInputComponent::new( - theme.clone(), - key_config.clone(), - "", - "search text", - false, - ); + pub fn new(env: &Environment) -> Self { + let mut find_text = + TextInputComponent::new(env, "", "search text", false); find_text.embed(); find_text.enabled(true); Self { - repo, - queue: queue.clone(), + repo: env.repo.clone(), + queue: env.queue.clone(), visible: false, mode: PopupMode::Search, - key_config, + key_config: env.key_config.clone(), options: ( SearchFields::default(), SearchOptions::default(), ), - theme, + theme: env.theme.clone(), find_text, selection: Selection::EnterText, jump_commit_id: None, diff --git a/src/components/msg.rs b/src/components/msg.rs index 31cb5c37..e7876505 100644 --- a/src/components/msg.rs +++ b/src/components/msg.rs @@ -3,6 +3,7 @@ use super::{ DrawableComponent, EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, strings, ui, }; @@ -121,16 +122,13 @@ impl Component for MsgComponent { } impl MsgComponent { - pub const fn new( - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { title: String::new(), msg: String::new(), visible: false, - theme, - key_config, + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } diff --git a/src/components/options_popup.rs b/src/components/options_popup.rs index 73b4e5c2..c654ad1a 100644 --- a/src/components/options_popup.rs +++ b/src/components/options_popup.rs @@ -3,6 +3,7 @@ use super::{ DrawableComponent, EventState, }; use crate::{ + app::Environment, components::utils::string_width_align, keys::{key_match, SharedKeyConfig}, options::SharedOptions, @@ -41,19 +42,14 @@ pub struct OptionsPopupComponent { impl OptionsPopupComponent { /// - pub fn new( - queue: &Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - options: SharedOptions, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { selection: AppOption::StatusShowUntracked, - queue: queue.clone(), + queue: env.queue.clone(), visible: false, - key_config, - options, - theme, + key_config: env.key_config.clone(), + options: env.options.clone(), + theme: env.theme.clone(), } } diff --git a/src/components/pull.rs b/src/components/pull.rs index 76c91414..e9f42e68 100644 --- a/src/components/pull.rs +++ b/src/components/pull.rs @@ -1,5 +1,6 @@ use super::PushComponent; use crate::{ + app::Environment, components::{ cred::CredComponent, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -21,7 +22,7 @@ use asyncgit::{ }, AsyncGitNotification, AsyncPull, FetchRequest, RemoteProgress, }; -use crossbeam_channel::Sender; + use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -47,27 +48,21 @@ pub struct PullComponent { impl PullComponent { /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - repo: repo.clone(), - queue: queue.clone(), + repo: env.repo.clone(), + queue: env.queue.clone(), pending: false, visible: false, branch: String::new(), - git_fetch: AsyncPull::new(repo.borrow().clone(), sender), - progress: None, - input_cred: CredComponent::new( - theme.clone(), - key_config.clone(), + git_fetch: AsyncPull::new( + env.repo.borrow().clone(), + &env.sender_git, ), - theme, - key_config, + progress: None, + input_cred: CredComponent::new(env), + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } diff --git a/src/components/push.rs b/src/components/push.rs index e272cefe..33f44585 100644 --- a/src/components/push.rs +++ b/src/components/push.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ cred::CredComponent, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -20,7 +21,6 @@ use asyncgit::{ AsyncGitNotification, AsyncPush, PushRequest, PushType, RemoteProgress, RemoteProgressState, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -66,29 +66,23 @@ pub struct PushComponent { impl PushComponent { /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - repo: repo.clone(), - queue: queue.clone(), + repo: env.repo.clone(), + queue: env.queue.clone(), modifier: PushComponentModifier::None, pending: false, visible: false, branch: String::new(), push_type: PushType::Branch, - git_push: AsyncPush::new(repo.borrow().clone(), sender), - progress: None, - input_cred: CredComponent::new( - theme.clone(), - key_config.clone(), + git_push: AsyncPush::new( + env.repo.borrow().clone(), + &env.sender_git, ), - theme, - key_config, + progress: None, + input_cred: CredComponent::new(env), + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } diff --git a/src/components/push_tags.rs b/src/components/push_tags.rs index 89668c80..d2a8f996 100644 --- a/src/components/push_tags.rs +++ b/src/components/push_tags.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ cred::CredComponent, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -20,7 +21,6 @@ use asyncgit::{ }, AsyncGitNotification, AsyncPushTags, PushTagsRequest, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -45,29 +45,20 @@ pub struct PushTagsComponent { impl PushTagsComponent { /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - repo: repo.clone(), - queue: queue.clone(), + repo: env.repo.clone(), + queue: env.queue.clone(), pending: false, visible: false, git_push: AsyncPushTags::new( - repo.borrow().clone(), - sender, + env.repo.borrow().clone(), + &env.sender_git, ), progress: None, - input_cred: CredComponent::new( - theme.clone(), - key_config.clone(), - ), - theme, - key_config, + input_cred: CredComponent::new(env), + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } diff --git a/src/components/rename_branch.rs b/src/components/rename_branch.rs index a9963091..e4398888 100644 --- a/src/components/rename_branch.rs +++ b/src/components/rename_branch.rs @@ -4,10 +4,10 @@ use super::{ EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::sync::{self, RepoPathRef}; @@ -89,24 +89,18 @@ impl Component for RenameBranchComponent { impl RenameBranchComponent { /// - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - repo, - queue, + repo: env.repo.clone(), + queue: env.queue.clone(), input: TextInputComponent::new( - theme, - key_config.clone(), - &strings::rename_branch_popup_title(&key_config), - &strings::rename_branch_popup_msg(&key_config), + env, + &strings::rename_branch_popup_title(&env.key_config), + &strings::rename_branch_popup_msg(&env.key_config), true, ), branch_ref: None, - key_config, + key_config: env.key_config.clone(), } } diff --git a/src/components/reset.rs b/src/components/reset.rs index aa8cd1dd..51d4781a 100644 --- a/src/components/reset.rs +++ b/src/components/reset.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ popup_paragraph, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -103,17 +104,13 @@ impl Component for ConfirmComponent { impl ConfirmComponent { /// - pub fn new( - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { target: None, visible: false, - queue, - theme, - key_config, + queue: env.queue.clone(), + theme: env.theme.clone(), + key_config: env.key_config.clone(), } } /// diff --git a/src/components/reset_popup.rs b/src/components/reset_popup.rs index a3b48428..f384a418 100644 --- a/src/components/reset_popup.rs +++ b/src/components/reset_popup.rs @@ -3,6 +3,7 @@ use super::{ DrawableComponent, EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::Queue, strings, try_or_popup, @@ -11,7 +12,7 @@ use crate::{ use anyhow::Result; use asyncgit::{ cached, - sync::{CommitId, RepoPath, RepoPathRef, ResetType}, + sync::{CommitId, RepoPath, ResetType}, }; use crossterm::event::Event; use ratatui::{ @@ -52,21 +53,18 @@ pub struct ResetPopupComponent { impl ResetPopupComponent { /// - pub fn new( - queue: &Queue, - repo: &RepoPathRef, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - queue: queue.clone(), - repo: repo.borrow().clone(), + queue: env.queue.clone(), + repo: env.repo.borrow().clone(), commit: None, kind: ResetType::Soft, - git_branch_name: cached::BranchName::new(repo.clone()), + git_branch_name: cached::BranchName::new( + env.repo.clone(), + ), visible: false, - key_config, - theme, + key_config: env.key_config.clone(), + theme: env.theme.clone(), } } diff --git a/src/components/revision_files.rs b/src/components/revision_files.rs index ee28cb24..ef1b0297 100644 --- a/src/components/revision_files.rs +++ b/src/components/revision_files.rs @@ -4,12 +4,13 @@ use super::{ EventState, FileRevOpen, FuzzyFinderTarget, SyntaxTextComponent, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings::{self, order, symbol}, try_or_popup, ui::{self, common_nav, style::SharedTheme}, - AsyncAppNotification, AsyncNotification, + AsyncNotification, }; use anyhow::Result; use asyncgit::{ @@ -19,7 +20,6 @@ use asyncgit::{ }, AsyncGitNotification, AsyncTreeFilesJob, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use filetreelist::{FileTree, FileTreeItem}; use ratatui::{ @@ -57,31 +57,21 @@ pub struct RevisionFilesComponent { impl RevisionFilesComponent { /// - pub fn new( - repo: RepoPathRef, - queue: &Queue, - sender: &Sender, - sender_git: Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - queue: queue.clone(), + queue: env.queue.clone(), tree: FileTree::default(), scroll: VerticalScroll::new(), - current_file: SyntaxTextComponent::new( - repo.clone(), - sender, - key_config.clone(), - theme.clone(), - ), - async_treefiles: AsyncSingleJob::new(sender_git), - theme, + current_file: SyntaxTextComponent::new(env), + theme: env.theme.clone(), files: None, + async_treefiles: AsyncSingleJob::new( + env.sender_git.clone(), + ), revision: None, focus: Focus::Tree, - key_config, - repo, + key_config: env.key_config.clone(), + repo: env.repo.clone(), visible: false, } } diff --git a/src/components/revision_files_popup.rs b/src/components/revision_files_popup.rs index 19b762d2..809c960a 100644 --- a/src/components/revision_files_popup.rs +++ b/src/components/revision_files_popup.rs @@ -6,18 +6,14 @@ use super::{ EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings::{self}, - ui::style::SharedTheme, - AsyncAppNotification, AsyncNotification, + AsyncNotification, }; use anyhow::Result; -use asyncgit::{ - sync::{CommitId, RepoPathRef}, - AsyncGitNotification, -}; -use crossbeam_channel::Sender; +use asyncgit::sync::CommitId; use crossterm::event::Event; use ratatui::{ backend::Backend, layout::Rect, widgets::Clear, Frame, @@ -48,27 +44,13 @@ pub struct RevisionFilesPopup { impl RevisionFilesPopup { /// - pub fn new( - repo: RepoPathRef, - queue: &Queue, - sender: &Sender, - sender_git: Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - files: RevisionFilesComponent::new( - repo, - queue, - sender, - sender_git, - theme, - key_config.clone(), - ), + files: RevisionFilesComponent::new(env), visible: false, - key_config, + key_config: env.key_config.clone(), open_request: None, - queue: queue.clone(), + queue: env.queue.clone(), } } diff --git a/src/components/stashmsg.rs b/src/components/stashmsg.rs index d30f68fc..86c34441 100644 --- a/src/components/stashmsg.rs +++ b/src/components/stashmsg.rs @@ -4,11 +4,11 @@ use super::{ EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{AppTabs, InternalEvent, Queue}, strings, tabs::StashingOptions, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::sync::{self, RepoPathRef}; @@ -126,24 +126,18 @@ impl Component for StashMsgComponent { impl StashMsgComponent { /// - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { options: StashingOptions::default(), - queue, + queue: env.queue.clone(), input: TextInputComponent::new( - theme, - key_config.clone(), - &strings::stash_popup_title(&key_config), - &strings::stash_popup_msg(&key_config), + env, + &strings::stash_popup_title(&env.key_config), + &strings::stash_popup_msg(&env.key_config), true, ), - key_config, - repo, + key_config: env.key_config.clone(), + repo: env.repo.clone(), } } diff --git a/src/components/status_tree.rs b/src/components/status_tree.rs index 3c303125..2cbd29b6 100644 --- a/src/components/status_tree.rs +++ b/src/components/status_tree.rs @@ -6,6 +6,7 @@ use super::{ BlameFileOpen, CommandBlocking, DrawableComponent, FileRevOpen, }; use crate::{ + app::Environment, components::{CommandInfo, Component, EventState}, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue, StackablePopupOpen}, @@ -30,7 +31,7 @@ pub struct StatusTreeComponent { current_hash: u64, focused: bool, show_selection: bool, - queue: Option, + queue: Queue, theme: SharedTheme, key_config: SharedKeyConfig, scroll_top: Cell, @@ -40,22 +41,16 @@ pub struct StatusTreeComponent { impl StatusTreeComponent { /// - pub fn new( - title: &str, - focus: bool, - queue: Option, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment, title: &str, focus: bool) -> Self { Self { title: title.to_string(), tree: StatusTree::default(), current_hash: 0, focused: focus, show_selection: focus, - queue, - theme, - key_config, + queue: env.queue.clone(), + theme: env.theme.clone(), + key_config: env.key_config.clone(), scroll_top: Cell::new(0), pending: true, visible: false, @@ -137,9 +132,7 @@ impl StatusTreeComponent { let changed = self.tree.move_selection(dir); if changed { - if let Some(ref queue) = self.queue { - queue.push(InternalEvent::Update(NeedsUpdate::DIFF)); - } + self.queue.push(InternalEvent::Update(NeedsUpdate::DIFF)); } changed @@ -309,11 +302,9 @@ impl StatusTreeComponent { if crate::clipboard::copy_string(&item.info.full_path) .is_err() { - if let Some(queue) = &self.queue { - queue.push(InternalEvent::ShowErrorMsg( - strings::POPUP_FAIL_COPY.to_string(), - )); - } + self.queue.push(InternalEvent::ShowErrorMsg( + strings::POPUP_FAIL_COPY.to_string(), + )); } } } @@ -463,17 +454,15 @@ impl Component for StatusTreeComponent { return if key_match(e, self.key_config.keys.blame) { if let Some(status_item) = self.selection_file() { self.hide(); - if let Some(queue) = &self.queue { - queue.push(InternalEvent::OpenPopup( - StackablePopupOpen::BlameFile( - BlameFileOpen { - file_path: status_item.path, - commit_id: self.revision, - selection: None, - }, - ), - )); - } + self.queue.push(InternalEvent::OpenPopup( + StackablePopupOpen::BlameFile( + BlameFileOpen { + file_path: status_item.path, + commit_id: self.revision, + selection: None, + }, + ), + )); } Ok(EventState::Consumed) } else if key_match( @@ -482,27 +471,21 @@ impl Component for StatusTreeComponent { ) { if let Some(status_item) = self.selection_file() { self.hide(); - if let Some(queue) = &self.queue { - queue.push(InternalEvent::OpenPopup( - StackablePopupOpen::FileRevlog( - FileRevOpen::new( - status_item.path, - ), - ), - )); - } + self.queue.push(InternalEvent::OpenPopup( + StackablePopupOpen::FileRevlog( + FileRevOpen::new(status_item.path), + ), + )); } Ok(EventState::Consumed) } else if key_match(e, self.key_config.keys.edit_file) { if let Some(status_item) = self.selection_file() { - if let Some(queue) = &self.queue { - queue.push( - InternalEvent::OpenExternalEditor( - Some(status_item.path), - ), - ); - } + self.queue.push( + InternalEvent::OpenExternalEditor(Some( + status_item.path, + )), + ); } Ok(EventState::Consumed) } else if key_match(e, self.key_config.keys.copy) { @@ -607,11 +590,9 @@ mod tests { // set up file tree let mut ftc = StatusTreeComponent::new( + &Default::default(), "title", true, - None, - SharedTheme::default(), - SharedKeyConfig::default(), ); ftc.update(&items) .expect("Updating FileTreeComponent failed"); @@ -649,11 +630,9 @@ mod tests { // set up file tree let mut ftc = StatusTreeComponent::new( + &Default::default(), "title", true, - None, - SharedTheme::default(), - SharedKeyConfig::default(), ); ftc.update(&items) .expect("Updating FileTreeComponent failed"); diff --git a/src/components/submodules.rs b/src/components/submodules.rs index e8cdac85..f92d800a 100644 --- a/src/components/submodules.rs +++ b/src/components/submodules.rs @@ -4,6 +4,7 @@ use super::{ EventState, ScrollType, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, try_or_popup, @@ -245,23 +246,18 @@ impl Component for SubmodulesListComponent { } impl SubmodulesListComponent { - pub fn new( - repo: RepoPathRef, - queue: &Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { submodules: Vec::new(), submodule_parent: None, scroll: VerticalScroll::new(), - queue: queue.clone(), + queue: env.queue.clone(), selection: 0, visible: false, - theme, - key_config, + theme: env.theme.clone(), + key_config: env.key_config.clone(), current_height: Cell::new(0), - repo, + repo: env.repo.clone(), repo_path: String::new(), } } diff --git a/src/components/syntax_text.rs b/src/components/syntax_text.rs index d96705d7..c1d908bb 100644 --- a/src/components/syntax_text.rs +++ b/src/components/syntax_text.rs @@ -3,6 +3,7 @@ use super::{ EventState, }; use crate::{ + app::Environment, keys::SharedKeyConfig, string_utils::tabs_to_spaces, strings, @@ -18,7 +19,6 @@ use asyncgit::{ sync::{self, RepoPathRef, TreeFile}, ProgressPercent, }; -use crossbeam_channel::Sender; use crossterm::event::Event; use filetreelist::MoveSelection; use itertools::Either; @@ -44,21 +44,18 @@ pub struct SyntaxTextComponent { impl SyntaxTextComponent { /// - pub fn new( - repo: RepoPathRef, - sender: &Sender, - key_config: SharedKeyConfig, - theme: SharedTheme, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - async_highlighting: AsyncSingleJob::new(sender.clone()), + async_highlighting: AsyncSingleJob::new( + env.sender_app.clone(), + ), syntax_progress: None, current_file: None, paragraph_state: Cell::new(ParagraphState::default()), focused: false, - key_config, - theme, - repo, + key_config: env.key_config.clone(), + theme: env.theme.clone(), + repo: env.repo.clone(), } } diff --git a/src/components/tag_commit.rs b/src/components/tag_commit.rs index 3919141f..79f506c4 100644 --- a/src/components/tag_commit.rs +++ b/src/components/tag_commit.rs @@ -4,10 +4,10 @@ use super::{ EventState, }; use crate::{ + app::Environment, keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, try_or_popup, - ui::style::SharedTheme, }; use anyhow::Result; use asyncgit::sync::{ @@ -126,24 +126,18 @@ impl Component for TagCommitComponent { impl TagCommitComponent { /// - pub fn new( - repo: RepoPathRef, - queue: Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - queue, + queue: env.queue.clone(), input: TextInputComponent::new( - theme, - key_config.clone(), + env, &strings::tag_popup_name_title(), &strings::tag_popup_name_msg(), true, ), commit_id: None, - key_config, - repo, + key_config: env.key_config.clone(), + repo: env.repo.clone(), mode: Mode::Name, } } diff --git a/src/components/taglist.rs b/src/components/taglist.rs index eba6a032..18e83dab 100644 --- a/src/components/taglist.rs +++ b/src/components/taglist.rs @@ -3,6 +3,7 @@ use super::{ Component, DrawableComponent, EventState, }; use crate::{ + app::Environment, components::ScrollType, keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, Queue}, @@ -23,7 +24,7 @@ use asyncgit::{ }, AsyncGitNotification, }; -use crossbeam_channel::Sender; + use crossterm::event::Event; use ratatui::{ backend::Backend, @@ -292,16 +293,10 @@ impl Component for TagListComponent { } impl TagListComponent { - pub fn new( - repo: RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - theme, - queue: queue.clone(), + theme: env.theme.clone(), + queue: env.queue.clone(), tags: None, visible: false, has_remotes: false, @@ -309,9 +304,11 @@ impl TagListComponent { current_height: std::cell::Cell::new(0), basic_credential: None, missing_remote_tags: None, - async_remote_tags: AsyncSingleJob::new(sender.clone()), - key_config, - repo, + async_remote_tags: AsyncSingleJob::new( + env.sender_git.clone(), + ), + key_config: env.key_config.clone(), + repo: env.repo.clone(), } } diff --git a/src/components/textinput.rs b/src/components/textinput.rs index 1c8bd73d..b9c98a23 100644 --- a/src/components/textinput.rs +++ b/src/components/textinput.rs @@ -1,3 +1,4 @@ +use crate::app::Environment; use crate::keys::key_match; use crate::strings::symbol; use crate::ui::Size; @@ -51,8 +52,7 @@ pub struct TextInputComponent { impl TextInputComponent { /// pub fn new( - theme: SharedTheme, - key_config: SharedKeyConfig, + env: &Environment, title: &str, default_msg: &str, show_char_count: bool, @@ -60,8 +60,8 @@ impl TextInputComponent { Self { msg: String::new(), visible: false, - theme, - key_config, + theme: env.theme.clone(), + key_config: env.key_config.clone(), show_char_count, title: title.to_string(), default_msg: default_msg.to_string(), @@ -555,8 +555,7 @@ mod tests { #[test] fn test_smoke() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -576,8 +575,7 @@ mod tests { #[test] fn text_cursor_initial_position() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -602,8 +600,7 @@ mod tests { #[test] fn test_cursor_second_position() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -639,8 +636,7 @@ mod tests { #[test] fn test_visualize_newline() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -675,8 +671,7 @@ mod tests { #[test] fn test_invisible_newline() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -706,8 +701,7 @@ mod tests { #[test] fn test_next_word_position() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -731,8 +725,7 @@ mod tests { #[test] fn test_previous_word_position() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, @@ -759,8 +752,7 @@ mod tests { #[test] fn test_next_word_multibyte() { let mut comp = TextInputComponent::new( - SharedTheme::default(), - SharedKeyConfig::default(), + &Environment::default(), "", "", false, diff --git a/src/main.rs b/src/main.rs index c0f41a27..0fb61391 100644 --- a/src/main.rs +++ b/src/main.rs @@ -203,8 +203,8 @@ fn run_app( let mut app = App::new( RefCell::new(repo), - &tx_git, - &tx_app, + tx_git, + tx_app, input.clone(), theme, key_config, diff --git a/src/options.rs b/src/options.rs index 68cebd0a..017f4144 100644 --- a/src/options.rs +++ b/src/options.rs @@ -32,6 +32,17 @@ pub struct Options { data: OptionsData, } +#[cfg(test)] +impl Default for Options { + fn default() -> Self { + use asyncgit::sync::RepoPath; + Self { + repo: RefCell::new(RepoPath::Path(Default::default())), + data: Default::default(), + } + } +} + pub type SharedOptions = Rc>; impl Options { diff --git a/src/tabs/files.rs b/src/tabs/files.rs index 9c4c3304..81da2618 100644 --- a/src/tabs/files.rs +++ b/src/tabs/files.rs @@ -1,21 +1,15 @@ use std::path::Path; use crate::{ + app::Environment, components::{ visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, RevisionFilesComponent, }, - keys::SharedKeyConfig, - queue::Queue, - ui::style::SharedTheme, - AsyncAppNotification, AsyncNotification, + AsyncNotification, }; use anyhow::Result; -use asyncgit::{ - sync::{self, RepoPathRef}, - AsyncGitNotification, -}; -use crossbeam_channel::Sender; +use asyncgit::sync::{self, RepoPathRef}; pub struct FilesTab { repo: RepoPathRef, @@ -25,25 +19,11 @@ pub struct FilesTab { impl FilesTab { /// - pub fn new( - repo: RepoPathRef, - sender: &Sender, - sender_git: Sender, - queue: &Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { visible: false, - files: RevisionFilesComponent::new( - repo.clone(), - queue, - sender, - sender_git, - theme, - key_config, - ), - repo, + files: RevisionFilesComponent::new(env), + repo: env.repo.clone(), } } diff --git a/src/tabs/revlog.rs b/src/tabs/revlog.rs index c208b868..a9cff547 100644 --- a/src/tabs/revlog.rs +++ b/src/tabs/revlog.rs @@ -1,4 +1,5 @@ use crate::{ + app::Environment, components::{ visibility_blocking, CommandBlocking, CommandInfo, CommitDetailsComponent, CommitList, Component, @@ -70,43 +71,35 @@ pub struct Revlog { impl Revlog { /// - pub fn new( - repo: &RepoPathRef, - queue: &Queue, - sender: &Sender, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { + pub fn new(env: &Environment) -> Self { Self { - repo: repo.clone(), - queue: queue.clone(), - commit_details: CommitDetailsComponent::new( - repo, - queue, - sender, - theme.clone(), - key_config.clone(), - ), + repo: env.repo.clone(), + queue: env.queue.clone(), + commit_details: CommitDetailsComponent::new(env), list: CommitList::new( - repo.clone(), - &strings::log_title(&key_config), - theme.clone(), - queue.clone(), - key_config.clone(), + env, + &strings::log_title(&env.key_config), ), git_log: AsyncLog::new( - repo.borrow().clone(), - sender, + env.repo.borrow().clone(), + &env.sender_git, None, ), search: LogSearch::Off, - git_tags: AsyncTags::new(repo.borrow().clone(), sender), - git_local_branches: AsyncSingleJob::new(sender.clone()), - git_remote_branches: AsyncSingleJob::new(sender.clone()), + git_tags: AsyncTags::new( + env.repo.borrow().clone(), + &env.sender_git, + ), + git_local_branches: AsyncSingleJob::new( + env.sender_git.clone(), + ), + git_remote_branches: AsyncSingleJob::new( + env.sender_git.clone(), + ), visible: false, - key_config, - sender: sender.clone(), - theme, + key_config: env.key_config.clone(), + sender: env.sender_git.clone(), + theme: env.theme.clone(), } } diff --git a/src/tabs/stashing.rs b/src/tabs/stashing.rs index 6df47495..2489f949 100644 --- a/src/tabs/stashing.rs +++ b/src/tabs/stashing.rs @@ -1,5 +1,6 @@ use crate::{ accessors, + app::Environment, components::{ command_pump, event_pump, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, @@ -15,7 +16,7 @@ use asyncgit::{ sync::{self, status::StatusType, RepoPathRef}, AsyncGitNotification, AsyncStatus, StatusParams, }; -use crossbeam_channel::Sender; + use crossterm::event::Event; use ratatui::{