mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Use terminal window focus to determine when a message has actually been seen (#94)
This commit is contained in:
parent
430c601ff2
commit
885b56038f
5 changed files with 51 additions and 13 deletions
41
src/main.rs
41
src/main.rs
|
@ -22,7 +22,15 @@ use matrix_sdk::ruma::OwnedUserId;
|
|||
use modalkit::crossterm::{
|
||||
self,
|
||||
cursor::Show as CursorShow,
|
||||
event::{poll, read, DisableBracketedPaste, EnableBracketedPaste, Event},
|
||||
event::{
|
||||
poll,
|
||||
read,
|
||||
DisableBracketedPaste,
|
||||
DisableFocusChange,
|
||||
EnableBracketedPaste,
|
||||
EnableFocusChange,
|
||||
Event,
|
||||
},
|
||||
execute,
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, SetTitle},
|
||||
};
|
||||
|
@ -109,6 +117,7 @@ struct Application {
|
|||
bindings: KeyManager<TerminalKey, ProgramAction, RepeatType, ProgramContext>,
|
||||
actstack: VecDeque<(ProgramAction, ProgramContext)>,
|
||||
screen: ScreenState<IambWindow, IambInfo>,
|
||||
focused: bool,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
|
@ -120,6 +129,7 @@ impl Application {
|
|||
crossterm::terminal::enable_raw_mode()?;
|
||||
crossterm::execute!(stdout, EnterAlternateScreen)?;
|
||||
crossterm::execute!(stdout, EnableBracketedPaste)?;
|
||||
crossterm::execute!(stdout, EnableFocusChange)?;
|
||||
|
||||
let title = format!("iamb ({})", settings.profile.user_id);
|
||||
crossterm::execute!(stdout, SetTitle(title))?;
|
||||
|
@ -154,11 +164,13 @@ impl Application {
|
|||
bindings,
|
||||
actstack,
|
||||
screen,
|
||||
focused: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn redraw(&mut self, full: bool, store: &mut ProgramStore) -> Result<(), std::io::Error> {
|
||||
let bindings = &mut self.bindings;
|
||||
let focused = self.focused;
|
||||
let sstate = &mut self.screen;
|
||||
let term = &mut self.terminal;
|
||||
|
||||
|
@ -176,7 +188,11 @@ impl Application {
|
|||
// Don't show terminal cursor when we show a dialog.
|
||||
let hide_cursor = !dialogstr.is_empty();
|
||||
|
||||
let screen = Screen::new(store).show_dialog(dialogstr).show_mode(modestr).borders(true);
|
||||
let screen = Screen::new(store)
|
||||
.show_dialog(dialogstr)
|
||||
.show_mode(modestr)
|
||||
.borders(true)
|
||||
.focus(focused);
|
||||
f.render_stateful_widget(screen, area, sstate);
|
||||
|
||||
if hide_cursor {
|
||||
|
@ -212,8 +228,11 @@ impl Application {
|
|||
Event::Mouse(_) => {
|
||||
// Do nothing for now.
|
||||
},
|
||||
Event::FocusGained | Event::FocusLost => {
|
||||
// Do nothing for now.
|
||||
Event::FocusGained => {
|
||||
self.focused = true;
|
||||
},
|
||||
Event::FocusLost => {
|
||||
self.focused = false;
|
||||
},
|
||||
Event::Resize(_, _) => {
|
||||
// We'll redraw for the new size next time step() is called.
|
||||
|
@ -532,13 +551,18 @@ async fn run(settings: ApplicationSettings) -> IambResult<()> {
|
|||
|
||||
login(worker, &settings).await.unwrap_or_else(print_exit);
|
||||
|
||||
fn restore_tty() {
|
||||
let _ = crossterm::terminal::disable_raw_mode();
|
||||
let _ = crossterm::execute!(stdout(), DisableBracketedPaste);
|
||||
let _ = crossterm::execute!(stdout(), DisableFocusChange);
|
||||
let _ = crossterm::execute!(stdout(), LeaveAlternateScreen);
|
||||
let _ = crossterm::execute!(stdout(), CursorShow);
|
||||
}
|
||||
|
||||
// Make sure panics clean up the terminal properly.
|
||||
let orig_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |panic_info| {
|
||||
let _ = crossterm::terminal::disable_raw_mode();
|
||||
let _ = crossterm::execute!(stdout(), DisableBracketedPaste);
|
||||
let _ = crossterm::execute!(stdout(), LeaveAlternateScreen);
|
||||
let _ = crossterm::execute!(stdout(), CursorShow);
|
||||
restore_tty();
|
||||
orig_hook(panic_info);
|
||||
process::exit(1);
|
||||
}));
|
||||
|
@ -547,6 +571,7 @@ async fn run(settings: ApplicationSettings) -> IambResult<()> {
|
|||
|
||||
// We can now run the application.
|
||||
application.run().await?;
|
||||
restore_tty();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -848,7 +848,9 @@ impl<'a> StatefulWidget for Chat<'a> {
|
|||
|
||||
// Render the message scrollback.
|
||||
let scrollback_focused = state.focus.is_scrollback() && self.focused;
|
||||
let scrollback = Scrollback::new(self.store).focus(scrollback_focused);
|
||||
let scrollback = Scrollback::new(self.store)
|
||||
.focus(scrollback_focused)
|
||||
.room_focus(self.focused);
|
||||
scrollback.render(scrollarea, buf, &mut state.scrollback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1206,13 +1206,21 @@ impl TerminalCursor for ScrollbackState {
|
|||
}
|
||||
|
||||
pub struct Scrollback<'a> {
|
||||
room_focused: bool,
|
||||
focused: bool,
|
||||
store: &'a mut ProgramStore,
|
||||
}
|
||||
|
||||
impl<'a> Scrollback<'a> {
|
||||
pub fn new(store: &'a mut ProgramStore) -> Self {
|
||||
Scrollback { focused: false, store }
|
||||
Scrollback { room_focused: false, focused: false, store }
|
||||
}
|
||||
|
||||
/// Indicate whether the room window is currently focused, regardless of whether the scrollback
|
||||
/// also is.
|
||||
pub fn room_focus(mut self, focused: bool) -> Self {
|
||||
self.room_focused = focused;
|
||||
self
|
||||
}
|
||||
|
||||
/// Indicate whether the scrollback is currently focused.
|
||||
|
@ -1307,7 +1315,10 @@ impl<'a> StatefulWidget for Scrollback<'a> {
|
|||
y += 1;
|
||||
}
|
||||
|
||||
if settings.tunables.read_receipt_send && state.cursor.timestamp.is_none() {
|
||||
if self.room_focused &&
|
||||
settings.tunables.read_receipt_send &&
|
||||
state.cursor.timestamp.is_none()
|
||||
{
|
||||
// If the cursor is at the last message, then update the read marker.
|
||||
info.read_till = info.messages.last_key_value().map(|(k, _)| k.1.clone());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue