Skip to content

Commit 7d318d2

Browse files
refactor focus and popups (#162)
* refactor focus and popups * autofocus editor on preview
1 parent 994a980 commit 7d318d2

File tree

2 files changed

+140
-151
lines changed

2 files changed

+140
-151
lines changed

src/app.rs

Lines changed: 137 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,42 @@ where
167167
self.state.history = vec![];
168168
}
169169

170+
fn set_focus(&mut self, focus: Focus) {
171+
self.state.focus = focus;
172+
if focus != Focus::PopUp {
173+
self.popup = None;
174+
self.last_focused_component = focus;
175+
}
176+
if focus == Focus::Editor || focus == Focus::History || focus == Focus::Favorites {
177+
self.last_focused_tab = focus;
178+
}
179+
}
180+
181+
fn set_popup(&mut self, popup: Box<dyn PopUp<DB>>) {
182+
self.popup = Some(popup);
183+
self.set_focus(Focus::PopUp);
184+
}
185+
186+
fn last_focused_tab(&mut self) {
187+
match self.last_focused_tab {
188+
Focus::Editor => self.set_focus(Focus::Editor),
189+
Focus::History => self.set_focus(Focus::History),
190+
Focus::Favorites => self.set_focus(Focus::Favorites),
191+
_ => {},
192+
}
193+
}
194+
195+
fn last_focused_component(&mut self) {
196+
match self.last_focused_component {
197+
Focus::Menu => self.set_focus(Focus::Menu),
198+
Focus::Editor => self.set_focus(Focus::Editor),
199+
Focus::Data => self.set_focus(Focus::Data),
200+
Focus::History => self.set_focus(Focus::History),
201+
Focus::Favorites => self.set_focus(Focus::Favorites),
202+
Focus::PopUp => {},
203+
}
204+
}
205+
170206
pub async fn run(&mut self) -> Result<()> {
171207
let (action_tx, mut action_rx) = mpsc::unbounded_channel();
172208
let connection_opts = self.state.connection_opts.clone();
@@ -204,7 +240,7 @@ where
204240

205241
loop {
206242
if let Some(popup) = &mut self.popup {
207-
self.state.focus = Focus::PopUp;
243+
self.set_focus(Focus::PopUp);
208244
}
209245
match &mut self.state.query_task {
210246
Some(DbTask::Query(task)) => {
@@ -221,8 +257,7 @@ where
221257
match results.results {
222258
Ok(_) => {
223259
self.state.query_task = Some(DbTask::TxPending(tx, results));
224-
self.popup = Some(Box::new(ConfirmTx::<DB>::new()));
225-
self.state.focus = Focus::PopUp;
260+
self.set_popup(Box::new(ConfirmTx::<DB>::new()));
226261
},
227262
Err(_) => {
228263
self.state.query_task = None;
@@ -256,31 +291,26 @@ where
256291
match payload {
257292
Some(PopUpPayload::SetDataTable(result, statement)) => {
258293
self.components.data.set_data_state(result, statement);
259-
self.popup = None;
260-
action_tx.send(Action::FocusEditor)?;
294+
self.set_focus(Focus::Editor);
261295
},
262296
Some(PopUpPayload::ConfirmQuery(query)) => {
263297
action_tx.send(Action::Query(vec![query], true))?;
264-
self.popup = None;
265-
action_tx.send(Action::FocusEditor)?;
298+
self.set_focus(Focus::Editor);
266299
},
267300
Some(PopUpPayload::ConfirmExport(confirmed)) => {
268301
if confirmed {
269302
action_tx.send(Action::ExportData(ExportFormat::CSV))?;
270-
self.popup = Some(Box::new(Exporting::new()));
303+
self.set_popup(Box::new(Exporting::new()));
271304
} else {
272-
self.popup = None;
273-
action_tx.send(Action::FocusData)?;
305+
self.set_focus(Focus::Data);
274306
}
275307
},
276308
Some(PopUpPayload::Cancel) => {
277-
self.popup = None;
278-
self.last_focused_component(action_tx.clone())?;
309+
self.last_focused_component();
279310
},
280311
Some(PopUpPayload::NamedFavorite(name, query_lines)) => {
281312
self.state.favorites.add_entry(name, query_lines);
282-
self.popup = None;
283-
action_tx.send(Action::FocusEditor)?;
313+
self.set_focus(Focus::Editor);
284314
},
285315
None => {},
286316
}
@@ -357,46 +387,28 @@ where
357387
})?;
358388
self.last_frame_mouse_event = None;
359389
},
360-
Action::FocusMenu => {
361-
self.state.focus = Focus::Menu;
362-
self.last_focused_component = Focus::Menu;
363-
},
364-
Action::FocusEditor => {
365-
self.state.focus = Focus::Editor;
366-
self.last_focused_tab = Focus::Editor;
367-
self.last_focused_component = Focus::Editor;
368-
},
369-
Action::FocusData => {
370-
self.state.focus = Focus::Data;
371-
self.last_focused_component = Focus::Data;
372-
},
373-
Action::FocusHistory => {
374-
self.state.focus = Focus::History;
375-
self.last_focused_tab = Focus::History;
376-
self.last_focused_component = Focus::History;
377-
},
378-
Action::FocusFavorites => {
379-
self.state.focus = Focus::Favorites;
380-
self.last_focused_tab = Focus::Favorites;
381-
self.last_focused_component = Focus::Favorites;
382-
},
390+
Action::FocusMenu => self.set_focus(Focus::Menu),
391+
Action::FocusEditor => self.set_focus(Focus::Editor),
392+
Action::FocusData => self.set_focus(Focus::Data),
393+
Action::FocusHistory => self.set_focus(Focus::History),
394+
Action::FocusFavorites => self.set_focus(Focus::Favorites),
383395
Action::CycleFocusForwards => {
384396
match self.state.focus {
385-
Focus::Menu => action_tx.send(Action::FocusEditor)?,
386-
Focus::Editor => action_tx.send(Action::FocusData)?,
387-
Focus::Data => action_tx.send(Action::FocusHistory)?,
388-
Focus::History => action_tx.send(Action::FocusFavorites)?,
389-
Focus::Favorites => action_tx.send(Action::FocusMenu)?,
397+
Focus::Menu => self.set_focus(Focus::Editor),
398+
Focus::Editor => self.set_focus(Focus::Data),
399+
Focus::Data => self.set_focus(Focus::History),
400+
Focus::History => self.set_focus(Focus::Favorites),
401+
Focus::Favorites => self.set_focus(Focus::Menu),
390402
Focus::PopUp => {},
391403
}
392404
},
393405
Action::CycleFocusBackwards => {
394406
match self.state.focus {
395-
Focus::History => action_tx.send(Action::FocusData)?,
396-
Focus::Data => action_tx.send(Action::FocusEditor)?,
397-
Focus::Editor => action_tx.send(Action::FocusMenu)?,
398-
Focus::Menu => action_tx.send(Action::FocusFavorites)?,
399-
Focus::Favorites => action_tx.send(Action::FocusHistory)?,
407+
Focus::History => self.set_focus(Focus::Data),
408+
Focus::Data => self.set_focus(Focus::Editor),
409+
Focus::Editor => self.set_focus(Focus::Menu),
410+
Focus::Menu => self.set_focus(Focus::Favorites),
411+
Focus::Favorites => self.set_focus(Focus::History),
400412
Focus::PopUp => {},
401413
}
402414
},
@@ -407,78 +419,77 @@ where
407419
self.components.menu.set_table_list(Some(results));
408420
}
409421
},
410-
Action::Query(query_lines, confirmed) => {
422+
Action::Query(query_lines, confirmed) => 'query_action: {
411423
let query_string = query_lines.clone().join(" \n");
412-
if !query_string.is_empty() {
413-
self.add_to_history(query_lines.clone());
414-
let first_query = database::get_first_query(query_string.clone(), self.state.dialect.as_ref());
415-
let execution_type = first_query.map(|(_, statement_type)| {
416-
(database::get_execution_type(statement_type.clone(), *confirmed), statement_type)
417-
});
418-
let action_tx = action_tx.clone();
419-
if let Some(pool) = &self.pool {
420-
let pool = pool.clone();
421-
let dialect = self.state.dialect.clone();
422-
match execution_type {
423-
Ok((ExecutionType::Transaction, statement_type)) => {
424-
self.components.data.set_loading();
425-
let tx = pool.begin().await?;
426-
self.state.query_task = Some(DbTask::TxStart(tokio::spawn(async move {
427-
let (results, tx) =
428-
database::query_with_tx::<DB>(tx, dialect.as_ref(), query_string.clone()).await;
429-
match results {
430-
Ok(Either::Left(rows_affected)) => {
431-
log::info!("{:?} rows affected", rows_affected);
432-
(
433-
QueryResultsWithMetadata {
434-
results: Ok(Rows { headers: vec![], rows: vec![], rows_affected: Some(rows_affected) }),
435-
statement_type,
436-
},
437-
tx,
438-
)
439-
},
440-
Ok(Either::Right(rows)) => {
441-
log::info!("{:?} rows affected", rows.rows_affected);
442-
(QueryResultsWithMetadata { results: Ok(rows), statement_type }, tx)
443-
},
444-
Err(e) => {
445-
log::error!("{e:?}");
446-
(QueryResultsWithMetadata { results: Err(e), statement_type }, tx)
447-
},
448-
}
449-
})));
450-
self.state.last_query_start = Some(chrono::Utc::now());
451-
self.state.last_query_end = None;
452-
},
453-
Ok((ExecutionType::Confirm, statement_type)) => {
454-
self.popup = Some(Box::new(ConfirmQuery::<DB>::new(query_string.clone(), statement_type)));
455-
self.state.focus = Focus::PopUp;
456-
},
457-
Ok((ExecutionType::Normal, statement_type)) => {
458-
self.components.data.set_loading();
459-
let dialect = self.state.dialect.clone();
460-
self.state.query_task = Some(DbTask::Query(tokio::spawn(async move {
461-
let results = database::query(query_string.clone(), dialect.as_ref(), &pool).await;
462-
match &results {
463-
Ok(rows) => {
464-
log::info!("{:?} rows, {:?} affected", rows.rows.len(), rows.rows_affected);
465-
},
466-
Err(e) => {
467-
log::error!("{e:?}");
468-
},
469-
};
470-
471-
QueryResultsWithMetadata { results, statement_type }
472-
})));
473-
self.state.last_query_start = Some(chrono::Utc::now());
474-
self.state.last_query_end = None;
475-
},
476-
Err(e) => self.components.data.set_data_state(Some(Err(e)), None),
477-
}
478-
} else {
479-
log::error!("No connection pool");
480-
self.components.data.set_data_state(Some(Err(DbError::Left(sqlx::Error::PoolTimedOut))), None)
424+
if query_string.is_empty() {
425+
break 'query_action;
426+
}
427+
self.add_to_history(query_lines.clone());
428+
let first_query = database::get_first_query(query_string.clone(), self.state.dialect.as_ref());
429+
let execution_type = first_query.map(|(_, statement_type)| {
430+
(database::get_execution_type(statement_type.clone(), *confirmed), statement_type)
431+
});
432+
let action_tx = action_tx.clone();
433+
if let Some(pool) = &self.pool {
434+
let pool = pool.clone();
435+
let dialect = self.state.dialect.clone();
436+
match execution_type {
437+
Ok((ExecutionType::Transaction, statement_type)) => {
438+
self.components.data.set_loading();
439+
let tx = pool.begin().await?;
440+
self.state.query_task = Some(DbTask::TxStart(tokio::spawn(async move {
441+
let (results, tx) = database::query_with_tx::<DB>(tx, dialect.as_ref(), query_string.clone()).await;
442+
match results {
443+
Ok(Either::Left(rows_affected)) => {
444+
log::info!("{:?} rows affected", rows_affected);
445+
(
446+
QueryResultsWithMetadata {
447+
results: Ok(Rows { headers: vec![], rows: vec![], rows_affected: Some(rows_affected) }),
448+
statement_type,
449+
},
450+
tx,
451+
)
452+
},
453+
Ok(Either::Right(rows)) => {
454+
log::info!("{:?} rows affected", rows.rows_affected);
455+
(QueryResultsWithMetadata { results: Ok(rows), statement_type }, tx)
456+
},
457+
Err(e) => {
458+
log::error!("{e:?}");
459+
(QueryResultsWithMetadata { results: Err(e), statement_type }, tx)
460+
},
461+
}
462+
})));
463+
self.state.last_query_start = Some(chrono::Utc::now());
464+
self.state.last_query_end = None;
465+
},
466+
Ok((ExecutionType::Confirm, statement_type)) => {
467+
self.set_popup(Box::new(ConfirmQuery::<DB>::new(query_string.clone(), statement_type)));
468+
},
469+
Ok((ExecutionType::Normal, statement_type)) => {
470+
self.components.data.set_loading();
471+
let dialect = self.state.dialect.clone();
472+
self.state.query_task = Some(DbTask::Query(tokio::spawn(async move {
473+
let results = database::query(query_string.clone(), dialect.as_ref(), &pool).await;
474+
match &results {
475+
Ok(rows) => {
476+
log::info!("{:?} rows, {:?} affected", rows.rows.len(), rows.rows_affected);
477+
},
478+
Err(e) => {
479+
log::error!("{e:?}");
480+
},
481+
};
482+
483+
QueryResultsWithMetadata { results, statement_type }
484+
})));
485+
self.state.last_query_start = Some(chrono::Utc::now());
486+
self.state.last_query_end = None;
487+
},
488+
Err(e) => self.components.data.set_data_state(Some(Err(e)), None),
481489
}
490+
} else {
491+
log::error!("No connection pool");
492+
self.components.data.set_data_state(Some(Err(DbError::Left(sqlx::Error::PoolTimedOut))), None)
482493
}
483494
},
484495
Action::AbortQuery => {
@@ -499,11 +510,10 @@ where
499510
}
500511
},
501512
Action::RequestSaveFavorite(query_lines) => {
502-
self.popup = Some(Box::new(NameFavorite::<DB>::new(
513+
self.set_popup(Box::new(NameFavorite::<DB>::new(
503514
self.state.favorites.iter().map(|f| f.get_name().to_string()).collect(),
504515
query_lines.clone(),
505516
)));
506-
self.state.focus = Focus::PopUp;
507517
},
508518
Action::DeleteFavorite(name) => {
509519
self.state.favorites.delete_entry(name.clone());
@@ -527,12 +537,10 @@ where
527537
}
528538
},
529539
Action::RequestExportData(row_count) => {
530-
self.popup = Some(Box::new(ConfirmExport::<DB>::new(*row_count)));
531-
self.state.focus = Focus::PopUp;
540+
self.set_popup(Box::new(ConfirmExport::<DB>::new(*row_count)));
532541
},
533542
Action::ExportDataFinished => {
534-
self.popup = None;
535-
action_tx.send(Action::FocusData)?;
543+
self.set_focus(Focus::Data);
536544
},
537545
_ => {},
538546
}
@@ -613,26 +621,26 @@ where
613621
let tab_content_target = tabs_layout[1];
614622
let data_target = right_layout[1];
615623
if menu_target.contains(position) {
616-
action_tx.send(Action::FocusMenu)?;
624+
self.set_focus(Focus::Menu);
617625
} else if data_target.contains(position) {
618-
action_tx.send(Action::FocusData)?;
626+
self.set_focus(Focus::Data);
619627
} else if tab_content_target.contains(position) {
620-
self.last_focused_tab(action_tx.clone())?;
628+
self.last_focused_tab();
621629
} else if tabs_target.contains(position) {
622630
match self.state.focus {
623631
Focus::Editor => {
624632
if matches!(event.kind, MouseEventKind::Up(_)) {
625-
action_tx.send(Action::FocusHistory)?;
633+
self.set_focus(Focus::History);
626634
}
627635
},
628636
Focus::History => {
629637
if matches!(event.kind, MouseEventKind::Up(_)) {
630-
action_tx.send(Action::FocusFavorites)?;
638+
self.set_focus(Focus::Favorites);
631639
}
632640
},
633641
Focus::Favorites => {
634642
if matches!(event.kind, MouseEventKind::Up(_)) {
635-
action_tx.send(Action::FocusEditor)?;
643+
self.set_focus(Focus::Editor);
636644
}
637645
},
638646
Focus::PopUp => {},
@@ -721,26 +729,4 @@ where
721729
frame.render_widget(popup_cta, layout[0]);
722730
frame.render_widget(popup_actions, center(layout[1], Constraint::Fill(1), Constraint::Percentage(50)));
723731
}
724-
725-
fn last_focused_tab(&self, action_tx: mpsc::UnboundedSender<Action>) -> Result<()> {
726-
match self.last_focused_tab {
727-
Focus::Editor => action_tx.send(Action::FocusEditor)?,
728-
Focus::History => action_tx.send(Action::FocusHistory)?,
729-
Focus::Favorites => action_tx.send(Action::FocusFavorites)?,
730-
_ => {},
731-
};
732-
Ok(())
733-
}
734-
735-
fn last_focused_component(&self, action_tx: mpsc::UnboundedSender<Action>) -> Result<()> {
736-
match self.last_focused_component {
737-
Focus::Menu => action_tx.send(Action::FocusMenu)?,
738-
Focus::Editor => action_tx.send(Action::FocusEditor)?,
739-
Focus::Data => action_tx.send(Action::FocusData)?,
740-
Focus::History => action_tx.send(Action::FocusHistory)?,
741-
Focus::Favorites => action_tx.send(Action::FocusFavorites)?,
742-
Focus::PopUp => {},
743-
};
744-
Ok(())
745-
}
746732
}

0 commit comments

Comments
 (0)