Skip to content

Commit 011bccf

Browse files
committed
Introduce AppData to manage app wide state
1 parent 5f1b3b9 commit 011bccf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1067
-771
lines changed

src/application.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
mod app_data;
2+
13
use std::sync::Arc;
24

35
use anyhow::Result;
46
use parking_lot::Mutex;
57

8+
pub(crate) use crate::application::app_data::AppData;
69
use crate::{
710
Args,
811
Exit,
@@ -11,7 +14,7 @@ use crate::{
1114
git::Repository,
1215
help::build_help,
1316
input::{Event, EventHandler, EventReaderFn, KeyBindings, StandardEvent},
14-
module::{self, ExitStatus, ModuleHandler},
17+
module::{self, ExitStatus, ModuleHandler, State},
1518
process::{self, Process},
1619
runtime::{Runtime, ThreadStatuses, Threadable},
1720
search,
@@ -22,7 +25,6 @@ use crate::{
2225
pub(crate) struct Application<ModuleProvider>
2326
where ModuleProvider: module::ModuleProvider + Send + 'static
2427
{
25-
_config: Config,
2628
process: Process<ModuleProvider>,
2729
threads: Option<Vec<Box<dyn Threadable>>>,
2830
thread_statuses: ThreadStatuses,
@@ -38,14 +40,9 @@ where ModuleProvider: module::ModuleProvider + Send + 'static
3840
{
3941
let filepath = Self::filepath_from_args(args)?;
4042
let repository = Self::open_repository()?;
41-
let config = Self::load_config(&repository)?;
43+
let config = Arc::new(Self::load_config(&repository)?);
4244
let todo_file = Arc::new(Mutex::new(Self::load_todo_file(filepath.as_str(), &config)?));
4345

44-
let module_handler = ModuleHandler::new(
45-
EventHandler::new(KeyBindings::new(&config.key_bindings)),
46-
ModuleProvider::new(&config, repository, &todo_file),
47-
);
48-
4946
let display = Display::new(tui, &config.theme);
5047
let initial_display_size = display.get_window_size();
5148
let view = View::new(
@@ -75,20 +72,24 @@ where ModuleProvider: module::ModuleProvider + Send + 'static
7572
let search_state = search_threads.state();
7673
threads.push(Box::new(search_threads));
7774

78-
let process = Process::new(
79-
initial_display_size,
80-
todo_file,
81-
module_handler,
82-
input_state,
83-
view_state,
84-
search_state,
85-
thread_statuses.clone(),
75+
let app_data = AppData::new(
76+
Arc::clone(&config),
77+
State::WindowSizeError,
78+
Arc::clone(&todo_file),
79+
view_state.clone(),
80+
input_state.clone(),
81+
search_state.clone(),
82+
);
83+
84+
let module_handler = ModuleHandler::new(
85+
EventHandler::new(KeyBindings::new(&config.key_bindings)),
86+
ModuleProvider::new(repository, &app_data),
8687
);
88+
let process = Process::new(&app_data, initial_display_size, module_handler, thread_statuses.clone());
8789
let process_threads = process::Thread::new(process.clone());
8890
threads.push(Box::new(process_threads));
8991

9092
Ok(Self {
91-
_config: config,
9293
process,
9394
threads: Some(threads),
9495
thread_statuses,

src/application/app_data.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use std::sync::Arc;
2+
3+
use parking_lot::Mutex;
4+
5+
use crate::{config::Config, input, module, search, todo_file::TodoFile, view};
6+
7+
#[derive(Clone, Debug)]
8+
pub(crate) struct AppData {
9+
config: Arc<Config>,
10+
active_module: Arc<Mutex<module::State>>,
11+
todo_file: Arc<Mutex<TodoFile>>,
12+
view_state: view::State,
13+
input_state: input::State,
14+
search_state: search::State,
15+
}
16+
17+
impl AppData {
18+
pub(crate) fn new(
19+
config: Arc<Config>,
20+
active_module: module::State,
21+
todo_file: Arc<Mutex<TodoFile>>,
22+
view_state: view::State,
23+
input_state: input::State,
24+
search_state: search::State,
25+
) -> Self {
26+
Self {
27+
config,
28+
active_module: Arc::new(Mutex::new(active_module)),
29+
todo_file,
30+
view_state,
31+
input_state,
32+
search_state,
33+
}
34+
}
35+
36+
pub(crate) fn config(&self) -> Arc<Config> {
37+
Arc::clone(&self.config)
38+
}
39+
40+
pub(crate) fn active_module(&self) -> Arc<Mutex<module::State>> {
41+
Arc::clone(&self.active_module)
42+
}
43+
44+
pub(crate) fn todo_file(&self) -> Arc<Mutex<TodoFile>> {
45+
Arc::clone(&self.todo_file)
46+
}
47+
48+
pub(crate) fn view_state(&self) -> view::State {
49+
self.view_state.clone()
50+
}
51+
52+
pub(crate) fn input_state(&self) -> input::State {
53+
self.input_state.clone()
54+
}
55+
56+
pub(crate) fn search_state(&self) -> search::State {
57+
self.search_state.clone()
58+
}
59+
}

src/components/choice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
display::DisplayColor,
88
input::{Event, InputOptions, KeyCode},
99
util::handle_view_data_scroll,
10-
view::{LineSegment, ViewData, ViewLine, ViewLines},
10+
view::{self, LineSegment, ViewData, ViewLine, ViewLines},
1111
};
1212

1313
pub(crate) static INPUT_OPTIONS: LazyLock<InputOptions> =
@@ -80,7 +80,7 @@ where T: Clone
8080
&self.view_data
8181
}
8282

83-
pub(crate) fn handle_event(&mut self, event: Event, view_state: &crate::view::State) -> Option<&T> {
83+
pub(crate) fn handle_event(&mut self, event: Event, view_state: &view::State) -> Option<&T> {
8484
if handle_view_data_scroll(event, view_state).is_none() {
8585
if let Event::Key(key_event) = event {
8686
if let KeyCode::Char(c) = key_event.code {

src/components/help.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
process::Results,
1010
select,
1111
util::handle_view_data_scroll,
12-
view::{LineSegment, LineSegmentOptions, ViewData, ViewLine},
12+
view::{self, LineSegment, LineSegmentOptions, ViewData, ViewLine},
1313
};
1414

1515
const INPUT_OPTIONS: InputOptions = InputOptions::RESIZE
@@ -86,7 +86,7 @@ impl Help {
8686
(self.is_active() || event == Event::Standard(StandardEvent::Help)).then_some(event)
8787
}
8888

89-
pub(crate) fn handle_event(&mut self, event: Event, view_state: &crate::view::State) -> Option<Results> {
89+
pub(crate) fn handle_event(&mut self, event: Event, view_state: &view::State) -> Option<Results> {
9090
self.is_active().then(|| {
9191
select!(
9292
default {

src/module.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) trait Module: Send {
4747
event
4848
}
4949

50-
fn handle_event(&mut self, _event: Event, _view_state: &crate::view::State) -> Results {
50+
fn handle_event(&mut self, _event: Event) -> Results {
5151
Results::new()
5252
}
5353

src/module/module_handler.rs

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,18 @@ impl<ModuleProvider: crate::module::ModuleProvider> ModuleHandler<ModuleProvider
3232
.build_view_data(render_context)
3333
}
3434

35-
pub(crate) fn handle_event(
36-
&mut self,
37-
state: State,
38-
input_state: &crate::input::State,
39-
view_state: &crate::view::State,
40-
) -> Option<Results> {
35+
pub(crate) fn handle_event(&mut self, state: State, event: Event) -> Option<Results> {
4136
let module = self.module_provider.get_module(state);
4237
let input_options = module.input_options();
43-
let event = self
38+
let evt = self
4439
.event_handler
45-
.read_event(input_state.read_event(), input_options, |event, key_bindings| {
46-
module.read_event(event, key_bindings)
40+
.read_event(event, input_options, |evt, key_bindings| {
41+
module.read_event(evt, key_bindings)
4742
});
48-
(event != Event::None).then(|| {
43+
(evt != Event::None).then(|| {
4944
let mut results = Results::new();
50-
results.event(event);
51-
results.append(
52-
self.module_provider
53-
.get_mut_module(state)
54-
.handle_event(event, view_state),
55-
);
45+
results.event(evt);
46+
results.append(self.module_provider.get_mut_module(state).handle_event(evt));
5647
results
5748
})
5849
}
@@ -111,7 +102,7 @@ mod tests {
111102
&self.view_data
112103
}
113104

114-
fn handle_event(&mut self, _: Event, _: &crate::view::State) -> Results {
105+
fn handle_event(&mut self, _: Event) -> Results {
115106
self.trace.lock().push(String::from("Handle Events"));
116107
Results::new()
117108
}
@@ -124,43 +115,31 @@ mod tests {
124115

125116
#[test]
126117
fn module_lifecycle() {
127-
testers::module(
128-
&["pick aaa comment"],
129-
&[Event::Standard(StandardEvent::Exit)],
130-
|context| {
131-
let test_module = TestModule::new();
132-
let mut module_handler = ModuleHandler::new(
133-
context.event_handler_context.event_handler,
134-
TestModuleProvider::from(test_module.clone()),
135-
);
136-
_ = module_handler.activate(State::List, State::Insert);
137-
_ = module_handler.handle_event(
138-
State::List,
139-
&context.event_handler_context.state,
140-
&context.view_context.state,
141-
);
142-
143-
_ = module_handler.build_view_data(State::List, &RenderContext::new(100, 100));
144-
_ = module_handler.deactivate(State::List);
145-
assert_eq!(test_module.trace(), "Activate,Handle Events,Build View Data,Deactivate");
146-
},
147-
);
118+
testers::module(&["pick aaa comment"], &[], None, |context| {
119+
let test_module = TestModule::new();
120+
let mut module_handler = ModuleHandler::new(
121+
context.event_handler_context.event_handler,
122+
TestModuleProvider::from(test_module.clone()),
123+
);
124+
_ = module_handler.activate(State::List, State::Insert);
125+
_ = module_handler.handle_event(State::List, Event::Standard(StandardEvent::Yes));
126+
127+
_ = module_handler.build_view_data(State::List, &RenderContext::new(100, 100));
128+
_ = module_handler.deactivate(State::List);
129+
assert_eq!(test_module.trace(), "Activate,Handle Events,Build View Data,Deactivate");
130+
});
148131
}
149132

150133
#[test]
151134
fn error() {
152-
testers::module(
153-
&["pick aaa comment"],
154-
&[Event::Standard(StandardEvent::Exit)],
155-
|context| {
156-
let test_module = TestModule::new();
157-
let mut module_handler = ModuleHandler::new(
158-
context.event_handler_context.event_handler,
159-
TestModuleProvider::from(test_module.clone()),
160-
);
161-
_ = module_handler.error(State::Error, &anyhow!("Test Error"));
162-
assert_eq!(test_module.trace(), "Test Error");
163-
},
164-
);
135+
testers::module(&["pick aaa comment"], &[], None, |context| {
136+
let test_module = TestModule::new();
137+
let mut module_handler = ModuleHandler::new(
138+
context.event_handler_context.event_handler,
139+
TestModuleProvider::from(test_module.clone()),
140+
);
141+
_ = module_handler.error(State::Error, &anyhow!("Test Error"));
142+
assert_eq!(test_module.trace(), "Test Error");
143+
});
165144
}
166145
}

src/module/module_provider.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
use std::sync::Arc;
2-
3-
use parking_lot::Mutex;
4-
51
use crate::{
6-
config::Config,
2+
application::AppData,
73
git::Repository,
84
module::{Module, State},
9-
todo_file::TodoFile,
105
};
116

127
pub(crate) trait ModuleProvider {
13-
fn new(config: &Config, repository: Repository, todo_file: &Arc<Mutex<TodoFile>>) -> Self;
8+
fn new(repository: Repository, app_data: &AppData) -> Self;
149

1510
fn get_mut_module(&mut self, _state: State) -> &mut dyn Module;
1611

src/module/modules.rs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
use std::sync::Arc;
2-
3-
use parking_lot::Mutex;
4-
51
use crate::{
6-
config::Config,
2+
application::AppData,
73
git::Repository,
84
module::{Module, ModuleProvider, State},
95
modules::{ConfirmAbort, ConfirmRebase, Error, ExternalEditor, Insert, List, ShowCommit, WindowSizeError},
10-
todo_file::TodoFile,
116
};
127

138
pub(crate) struct Modules {
@@ -22,20 +17,16 @@ pub(crate) struct Modules {
2217
}
2318

2419
impl ModuleProvider for Modules {
25-
fn new(config: &Config, repository: Repository, todo_file: &Arc<Mutex<TodoFile>>) -> Self {
20+
fn new(repository: Repository, app_data: &AppData) -> Self {
2621
Self {
27-
error: Error::new(),
28-
list: List::new(config, Arc::clone(todo_file)),
29-
show_commit: ShowCommit::new(config, repository, Arc::clone(todo_file)),
22+
error: Error::new(app_data),
23+
list: List::new(app_data),
24+
show_commit: ShowCommit::new(app_data, repository),
3025
window_size_error: WindowSizeError::new(),
31-
confirm_abort: ConfirmAbort::new(
32-
&config.key_bindings.confirm_yes,
33-
&config.key_bindings.confirm_no,
34-
Arc::clone(todo_file),
35-
),
36-
confirm_rebase: ConfirmRebase::new(&config.key_bindings.confirm_yes, &config.key_bindings.confirm_no),
37-
external_editor: ExternalEditor::new(config.git.editor.as_str(), Arc::clone(todo_file)),
38-
insert: Insert::new(Arc::clone(todo_file)),
26+
confirm_abort: ConfirmAbort::new(app_data),
27+
confirm_rebase: ConfirmRebase::new(app_data),
28+
external_editor: ExternalEditor::new(app_data),
29+
insert: Insert::new(app_data),
3930
}
4031
}
4132

@@ -68,16 +59,33 @@ impl ModuleProvider for Modules {
6859

6960
#[cfg(test)]
7061
mod tests {
62+
use std::sync::Arc;
63+
64+
use parking_lot::Mutex;
65+
7166
use super::*;
72-
use crate::test_helpers::{create_config, with_temp_repository, with_todo_file};
67+
use crate::{
68+
input,
69+
search,
70+
test_helpers::{create_config, with_temp_repository, with_todo_file},
71+
view,
72+
};
7373

7474
pub(crate) fn modules_test<C>(callback: C)
7575
where C: FnOnce(Modules) {
7676
with_temp_repository(|repository| {
7777
with_todo_file(&[], |todo_file_context| {
7878
let (_todo_file_path, todo_file) = todo_file_context.to_owned();
7979
let config = create_config();
80-
let modules = Modules::new(&config, repository, &Arc::new(Mutex::new(todo_file)));
80+
let app_data = AppData::new(
81+
Arc::new(config),
82+
State::WindowSizeError,
83+
Arc::new(Mutex::new(todo_file)),
84+
view::State::new(),
85+
input::State::new(),
86+
search::State::new(),
87+
);
88+
let modules = Modules::new(repository, &app_data);
8189
callback(modules);
8290
});
8391
});

0 commit comments

Comments
 (0)