app has its own async notifications now (#813)

* app has its own async notifications now
This commit is contained in:
Stephan Dilly 2021-07-11 13:24:19 +02:00 committed by GitHub
parent aacc7a3211
commit 19f2fd03cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 63 deletions

View File

@ -83,12 +83,6 @@ pub enum AsyncGitNotification {
Fetch,
///
Blame,
///
//TODO: this does not belong here
SyntaxHighlighting,
///
//TODO: this does not belong here
RemoteTags,
}
/// current working directory `./`

View File

@ -18,6 +18,7 @@ use crate::{
strings::{self, order},
tabs::{FilesTab, Revlog, StashList, Stashing, Status},
ui::style::{SharedTheme, Theme},
AsyncAppNotification, AsyncNotification,
};
use anyhow::{bail, Result};
use asyncgit::{sync, AsyncGitNotification, CWD};
@ -79,6 +80,7 @@ impl App {
#[allow(clippy::too_many_lines)]
pub fn new(
sender: &Sender<AsyncGitNotification>,
sender_app: &Sender<AsyncAppNotification>,
input: Input,
theme: Theme,
key_config: KeyConfig,
@ -108,7 +110,7 @@ impl App {
),
revision_files_popup: RevisionFilesPopup::new(
&queue,
sender,
sender_app,
theme.clone(),
key_config.clone(),
),
@ -167,7 +169,7 @@ impl App {
),
tags_popup: TagListComponent::new(
&queue,
sender,
sender_app,
theme.clone(),
key_config.clone(),
),
@ -206,7 +208,7 @@ impl App {
key_config.clone(),
),
files_tab: FilesTab::new(
sender,
sender_app,
&queue,
theme.clone(),
key_config.clone(),
@ -342,21 +344,24 @@ impl App {
}
///
pub fn update_git(
pub fn update_async(
&mut self,
ev: AsyncGitNotification,
ev: AsyncNotification,
) -> Result<()> {
log::trace!("update_git: {:?}", ev);
log::trace!("update_async: {:?}", ev);
self.status_tab.update_git(ev)?;
self.stashing_tab.update_git(ev)?;
self.files_tab.update_git(ev);
self.revlog.update_git(ev)?;
self.blame_file_popup.update_git(ev)?;
self.inspect_commit_popup.update_git(ev)?;
self.push_popup.update_git(ev)?;
self.push_tags_popup.update_git(ev)?;
self.pull_popup.update_git(ev)?;
if let AsyncNotification::Git(ev) = ev {
self.status_tab.update_git(ev)?;
self.stashing_tab.update_git(ev)?;
self.revlog.update_git(ev)?;
self.blame_file_popup.update_git(ev)?;
self.inspect_commit_popup.update_git(ev)?;
self.push_popup.update_git(ev)?;
self.push_tags_popup.update_git(ev)?;
self.pull_popup.update_git(ev)?;
}
self.files_tab.update_async(ev);
self.revision_files_popup.update(ev);
self.tags_popup.update(ev);

View File

@ -8,11 +8,12 @@ use crate::{
queue::{InternalEvent, Queue},
strings::{self, order},
ui::{self, common_nav, style::SharedTheme},
AsyncAppNotification, AsyncNotification,
};
use anyhow::Result;
use asyncgit::{
sync::{self, CommitId, TreeFile},
AsyncGitNotification, CWD,
CWD,
};
use crossbeam_channel::Sender;
use crossterm::event::Event;
@ -52,7 +53,7 @@ impl RevisionFilesComponent {
///
pub fn new(
queue: &Queue,
sender: &Sender<AsyncGitNotification>,
sender: &Sender<AsyncAppNotification>,
theme: SharedTheme,
key_config: SharedKeyConfig,
) -> Self {
@ -90,7 +91,7 @@ impl RevisionFilesComponent {
}
///
pub fn update(&mut self, ev: AsyncGitNotification) {
pub fn update(&mut self, ev: AsyncNotification) {
self.current_file.update(ev);
}

View File

@ -8,9 +8,10 @@ use crate::{
queue::Queue,
strings::{self},
ui::style::SharedTheme,
AsyncAppNotification, AsyncNotification,
};
use anyhow::Result;
use asyncgit::{sync::CommitId, AsyncGitNotification};
use asyncgit::sync::CommitId;
use crossbeam_channel::Sender;
use crossterm::event::Event;
use tui::{backend::Backend, layout::Rect, widgets::Clear, Frame};
@ -25,7 +26,7 @@ impl RevisionFilesPopup {
///
pub fn new(
queue: &Queue,
sender: &Sender<AsyncGitNotification>,
sender: &Sender<AsyncAppNotification>,
theme: SharedTheme,
key_config: SharedKeyConfig,
) -> Self {
@ -50,7 +51,7 @@ impl RevisionFilesPopup {
}
///
pub fn update(&mut self, ev: AsyncGitNotification) {
pub fn update(&mut self, ev: AsyncNotification) {
self.files.update(ev);
}
@ -68,16 +69,6 @@ impl DrawableComponent for RevisionFilesPopup {
) -> Result<()> {
if self.is_visible() {
f.render_widget(Clear, area);
// f.render_widget(
// Block::default()
// .borders(Borders::TOP)
// .title(Span::styled(
// format!(" {}", self.title),
// self.theme.title(true),
// ))
// .border_style(self.theme.block(true)),
// area,
// );
self.files.draw(f, area)?;
}

View File

@ -9,12 +9,13 @@ use crate::{
self, common_nav, style::SharedTheme, AsyncSyntaxJob,
ParagraphState, ScrollPos, StatefulParagraph,
},
AsyncAppNotification, AsyncNotification,
};
use anyhow::Result;
use asyncgit::{
asyncjob::AsyncSingleJob,
sync::{self, TreeFile},
AsyncGitNotification, CWD,
CWD,
};
use crossbeam_channel::Sender;
use crossterm::event::Event;
@ -32,7 +33,7 @@ use tui::{
pub struct SyntaxTextComponent {
current_file: Option<(String, Either<ui::SyntaxText, String>)>,
async_highlighting:
AsyncSingleJob<AsyncSyntaxJob, AsyncGitNotification>,
AsyncSingleJob<AsyncSyntaxJob, AsyncAppNotification>,
key_config: SharedKeyConfig,
paragraph_state: Cell<ParagraphState>,
focused: bool,
@ -42,14 +43,14 @@ pub struct SyntaxTextComponent {
impl SyntaxTextComponent {
///
pub fn new(
sender: &Sender<AsyncGitNotification>,
sender: &Sender<AsyncAppNotification>,
key_config: SharedKeyConfig,
theme: SharedTheme,
) -> Self {
Self {
async_highlighting: AsyncSingleJob::new(
sender.clone(),
AsyncGitNotification::SyntaxHighlighting,
AsyncAppNotification::SyntaxHighlighting,
),
current_file: None,
paragraph_state: Cell::new(ParagraphState::default()),
@ -60,8 +61,13 @@ impl SyntaxTextComponent {
}
///
pub fn update(&mut self, ev: AsyncGitNotification) {
if ev == AsyncGitNotification::SyntaxHighlighting {
pub fn update(&mut self, ev: AsyncNotification) {
if matches!(
ev,
AsyncNotification::App(
AsyncAppNotification::SyntaxHighlighting
)
) {
if let Some(job) = self.async_highlighting.take_last() {
if let Some((path, content)) =
self.current_file.as_mut()

View File

@ -8,6 +8,7 @@ use crate::{
queue::{Action, InternalEvent, Queue},
strings,
ui::{self, Size},
AsyncAppNotification, AsyncNotification,
};
use anyhow::Result;
use asyncgit::{
@ -46,7 +47,7 @@ pub struct TagListComponent {
missing_remote_tags: Option<Vec<String>>,
basic_credential: Option<BasicAuthCredential>,
async_remote_tags:
AsyncSingleJob<AsyncRemoteTagsJob, AsyncGitNotification>,
AsyncSingleJob<AsyncRemoteTagsJob, AsyncAppNotification>,
key_config: SharedKeyConfig,
}
@ -250,7 +251,7 @@ impl Component for TagListComponent {
impl TagListComponent {
pub fn new(
queue: &Queue,
sender: &Sender<AsyncGitNotification>,
sender: &Sender<AsyncAppNotification>,
theme: SharedTheme,
key_config: SharedKeyConfig,
) -> Self {
@ -265,7 +266,7 @@ impl TagListComponent {
missing_remote_tags: None,
async_remote_tags: AsyncSingleJob::new(
sender.clone(),
AsyncGitNotification::RemoteTags,
AsyncAppNotification::RemoteTags,
),
key_config,
}
@ -297,15 +298,21 @@ impl TagListComponent {
}
///
pub fn update(&mut self, event: AsyncGitNotification) {
if event == AsyncGitNotification::RemoteTags {
pub fn update(&mut self, ev: AsyncNotification) {
if matches!(
ev,
AsyncNotification::App(AsyncAppNotification::RemoteTags)
) {
if let Some(job) = self.async_remote_tags.take_last() {
if let Some(Ok(missing_remote_tags)) = job.result() {
self.missing_remote_tags =
Some(missing_remote_tags);
}
}
} else if event == AsyncGitNotification::PushTags {
} else if matches!(
ev,
AsyncNotification::Git(AsyncGitNotification::PushTags)
) {
self.update_missing_remote_tags();
}
}

View File

@ -72,10 +72,26 @@ static SPINNER_INTERVAL: Duration = Duration::from_millis(80);
pub enum QueueEvent {
Tick,
SpinnerUpdate,
GitEvent(AsyncGitNotification),
AsyncEvent(AsyncNotification),
InputEvent(InputEvent),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AsyncAppNotification {
///
SyntaxHighlighting,
///
RemoteTags,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AsyncNotification {
///
App(AsyncAppNotification),
///
Git(AsyncGitNotification),
}
fn main() -> Result<()> {
let cliargs = process_cmdline()?;
@ -103,6 +119,7 @@ fn main() -> Result<()> {
let mut terminal = start_terminal(io::stdout())?;
let (tx_git, rx_git) = unbounded();
let (tx_app, rx_app) = unbounded();
let input = Input::new();
@ -110,7 +127,8 @@ fn main() -> Result<()> {
let ticker = tick(TICK_INTERVAL);
let spinner_ticker = tick(SPINNER_INTERVAL);
let mut app = App::new(&tx_git, input, theme, key_config);
let mut app =
App::new(&tx_git, &tx_app, input, theme, key_config);
let mut spinner = Spinner::default();
let mut first_update = true;
@ -123,6 +141,7 @@ fn main() -> Result<()> {
select_event(
&rx_input,
&rx_git,
&rx_app,
&ticker,
&spinner_ticker,
)?
@ -147,13 +166,16 @@ fn main() -> Result<()> {
app.event(ev)?;
}
QueueEvent::Tick => app.update()?,
QueueEvent::GitEvent(ev)
if ev
!= AsyncGitNotification::FinishUnchanged =>
{
app.update_git(ev)?;
QueueEvent::AsyncEvent(ev) => {
if !matches!(
ev,
AsyncNotification::Git(
AsyncGitNotification::FinishUnchanged
)
) {
app.update_async(ev)?;
}
}
QueueEvent::GitEvent(..) => (),
QueueEvent::SpinnerUpdate => unreachable!(),
}
@ -217,6 +239,7 @@ fn valid_path() -> Result<bool> {
fn select_event(
rx_input: &Receiver<InputEvent>,
rx_git: &Receiver<AsyncGitNotification>,
rx_app: &Receiver<AsyncAppNotification>,
rx_ticker: &Receiver<Instant>,
rx_spinner: &Receiver<Instant>,
) -> Result<QueueEvent> {
@ -224,6 +247,7 @@ fn select_event(
sel.recv(rx_input);
sel.recv(rx_git);
sel.recv(rx_app);
sel.recv(rx_ticker);
sel.recv(rx_spinner);
@ -232,9 +256,14 @@ fn select_event(
let ev = match index {
0 => oper.recv(rx_input).map(QueueEvent::InputEvent),
1 => oper.recv(rx_git).map(QueueEvent::GitEvent),
2 => oper.recv(rx_ticker).map(|_| QueueEvent::Tick),
3 => oper.recv(rx_spinner).map(|_| QueueEvent::SpinnerUpdate),
1 => oper.recv(rx_git).map(|e| {
QueueEvent::AsyncEvent(AsyncNotification::Git(e))
}),
2 => oper.recv(rx_app).map(|e| {
QueueEvent::AsyncEvent(AsyncNotification::App(e))
}),
3 => oper.recv(rx_ticker).map(|_| QueueEvent::Tick),
4 => oper.recv(rx_spinner).map(|_| QueueEvent::SpinnerUpdate),
_ => bail!("unknown select source"),
}?;

View File

@ -12,9 +12,10 @@ use crate::{
keys::SharedKeyConfig,
queue::Queue,
ui::style::SharedTheme,
AsyncAppNotification, AsyncNotification,
};
use anyhow::Result;
use asyncgit::{sync, AsyncGitNotification, CWD};
use asyncgit::{sync, CWD};
use crossbeam_channel::Sender;
pub struct FilesTab {
@ -27,7 +28,7 @@ pub struct FilesTab {
impl FilesTab {
///
pub fn new(
sender: &Sender<AsyncGitNotification>,
sender: &Sender<AsyncAppNotification>,
queue: &Queue,
theme: SharedTheme,
key_config: SharedKeyConfig,
@ -60,7 +61,7 @@ impl FilesTab {
}
///
pub fn update_git(&mut self, ev: AsyncGitNotification) {
pub fn update_async(&mut self, ev: AsyncNotification) {
if self.is_visible() {
self.files.update(ev);
}