mirror of
https://github.com/extrawurst/gitui.git
synced 2024-12-27 11:03:03 +03:00
app has its own async notifications now (#813)
* app has its own async notifications now
This commit is contained in:
parent
aacc7a3211
commit
19f2fd03cf
@ -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 `./`
|
||||
|
35
src/app.rs
35
src/app.rs
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)?;
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
51
src/main.rs
51
src/main.rs
@ -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"),
|
||||
}?;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user