Skip to content

Commit

Permalink
Sending a message is a nice feature to have.
Browse files Browse the repository at this point in the history
  • Loading branch information
pkulak committed Apr 6, 2023
1 parent 0a66295 commit 7144a3b
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 36 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ once_cell = "1.17"
rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] }
simple-logging = "2.0"
tempfile = "3"
textwrap = "0.16"
tokio = { version = "1.24.2", features = ["rt-multi-thread"] }
tui = "0.19.0"
Expand Down
19 changes: 11 additions & 8 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use matrix_sdk::encryption::verification::SasVerification;
use std::sync::mpsc::Sender;
use std::sync::Mutex;

use crate::event::Event;
use crate::event::{Event, EventHandler};
use crate::matrix::matrix::Matrix;
use crate::widgets::chat::Chat;
use crate::widgets::confirm::Confirm;
Expand All @@ -17,6 +17,8 @@ static mut SENDER: Mutex<Option<Sender<Event>>> = Mutex::new(None);

/// Application.
pub struct App {
pub events: EventHandler,

/// Is the application running?
pub running: bool,

Expand All @@ -33,21 +35,22 @@ pub struct App {

/// And our single Matrix client and channel
pub matrix: Matrix,
pub send: Sender<Event>,
pub sender: Sender<Event>,

/// We'll hold on to any in-progress verifications here
pub sas: Option<SasVerification>,
}

impl App {
pub fn new(send: Sender<Event>) -> Self {
pub fn new(send: Sender<Event>, events: EventHandler) -> Self {
let matrix = Matrix::new(send.clone());

// Save the sender for future threads.
// Safety: let's make sure to only have one App
unsafe { SENDER = Mutex::new(Some(send.clone())) }

Self {
events,
running: true,
timestamp: 0,
progress: None,
Expand All @@ -57,7 +60,7 @@ impl App {
rooms: None,
chat: None,
matrix,
send,
sender: send,
sas: None,
}
}
Expand Down Expand Up @@ -100,6 +103,10 @@ impl App {

/// Renders the user interface widgets.
pub fn render<B: Backend>(&mut self, frame: &mut Frame<'_, B>) {
if let Some(c) = &self.chat {
frame.render_widget(c.widget(), frame.size())
}

if let Some(w) = &self.error {
frame.render_widget(w.widget(), frame.size());
return;
Expand All @@ -120,10 +127,6 @@ impl App {
return;
}

if let Some(c) = &self.chat {
frame.render_widget(c.widget(), frame.size())
}

if let Some(r) = &self.rooms {
frame.render_widget(r.widget(), frame.size())
}
Expand Down
54 changes: 43 additions & 11 deletions src/event.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::handler::MatuiEvent;
use crossterm::event::{self, Event as CrosstermEvent, KeyEvent, MouseEvent};
use std::sync::mpsc;
use std::sync::mpsc::Sender;
use std::ops::Sub;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::time::{Duration, Instant};

Expand All @@ -10,6 +10,8 @@ use std::time::{Duration, Instant};
pub enum Event {
/// Terminal tick.
Tick,
/// Force a clear and full re-draw.
Redraw,
/// Key press.
Key(KeyEvent),
/// Mouse click/scroll.
Expand All @@ -25,35 +27,64 @@ pub enum Event {
#[derive(Debug)]
pub struct EventHandler {
/// Event sender channel.
sender: mpsc::Sender<Event>,
sender: Sender<Event>,
/// Event receiver channel.
receiver: mpsc::Receiver<Event>,
receiver: Receiver<Event>,
/// Park sender.
pk_sender: Sender<bool>,
/// Event handler thread.
handler: thread::JoinHandle<()>,
}

impl EventHandler {
pub fn park(&self) {
self.pk_sender.send(true).expect("could send park event");
}

pub fn unpark(&self) {
self.handler.thread().unpark();
}

/// Constructs a new instance of [`EventHandler`].
pub fn new(tick_rate: u64) -> Self {
let tick_rate = Duration::from_millis(tick_rate);
let (sender, receiver) = mpsc::channel();
let (sender, receiver) = channel();
let (pk_sender, pk_receiver) = channel();
let handler = {
let sender = sender.clone();
thread::spawn(move || {
let mut last_tick = Instant::now();
let mut last_park = Instant::now().sub(Duration::from_secs(10));

loop {
let timeout = tick_rate
.checked_sub(last_tick.elapsed())
.unwrap_or(tick_rate);

if let Ok(_) = pk_receiver.try_recv() {
thread::park();
last_park = Instant::now()
}

if event::poll(timeout).expect("no events available") {
match event::read().expect("unable to read event") {
CrosstermEvent::Key(e) => sender.send(Event::Key(e)),
CrosstermEvent::Mouse(e) => sender.send(Event::Mouse(e)),
CrosstermEvent::Resize(w, h) => sender.send(Event::Resize(w, h)),
_ => unimplemented!(),
let event = event::read().expect("unable to read event");

if let Ok(_) = pk_receiver.try_recv() {
thread::park();
last_park = Instant::now()
}

// right after we unpark, we can get a stream of
// garbage events
if last_park.elapsed() > Duration::from_millis(250) {
match event {
CrosstermEvent::Key(e) => sender.send(Event::Key(e)),
CrosstermEvent::Mouse(e) => sender.send(Event::Mouse(e)),
CrosstermEvent::Resize(w, h) => sender.send(Event::Resize(w, h)),
_ => unimplemented!(),
}
.expect("failed to send terminal event")
}
.expect("failed to send terminal event")
}

if last_tick.elapsed() >= tick_rate {
Expand All @@ -66,6 +97,7 @@ impl EventHandler {
Self {
sender,
receiver,
pk_sender,
handler,
}
}
Expand Down
30 changes: 28 additions & 2 deletions src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::widgets::signin::Signin;
use crate::widgets::Action::{ButtonNo, ButtonYes, SelectRoom};
use crate::widgets::EventResult::Consumed;
use crossterm::event::{KeyCode, KeyEvent};

use matrix_sdk::encryption::verification::{Emoji, SasVerification};
use matrix_sdk::room::RoomMember;
use ruma::events::AnyTimelineEvent;
Expand All @@ -20,6 +21,8 @@ pub enum MatuiEvent {
LoginRequired,
LoginStarted,
Member(RoomMember),
ProgressStarted(String),
ProgressComplete,
SyncComplete,
SyncStarted(SyncType),
Timeline(AnyTimelineEvent),
Expand Down Expand Up @@ -57,6 +60,8 @@ pub fn handle_app_event(event: MatuiEvent, app: &mut App) {
c.room_member_event(rm);
}
}
MatuiEvent::ProgressStarted(msg) => app.progress = Some(Progress::new(&msg)),
MatuiEvent::ProgressComplete => app.progress = None,
MatuiEvent::SyncStarted(st) => {
app.error = None;
match st {
Expand Down Expand Up @@ -120,6 +125,7 @@ pub fn handle_key_event(key_event: KeyEvent, app: &mut App) -> anyhow::Result<()
if let Consumed(ButtonYes) = w.input(&key_event) {
app.matrix
.login(w.id.value().as_str(), w.password.value().as_str());
return Ok(());
}
}

Expand All @@ -131,6 +137,8 @@ pub fn handle_key_event(key_event: KeyEvent, app: &mut App) -> anyhow::Result<()
room.set_room(joined);

app.chat = Some(room);

return Ok(());
}
}

Expand All @@ -142,18 +150,36 @@ pub fn handle_key_event(key_event: KeyEvent, app: &mut App) -> anyhow::Result<()
app.confirm = None;
app.progress =
Some(Progress::new("Waiting for your other device to confirm."));
return Ok(());
}
Consumed(ButtonNo) => {
app.matrix.mismatched_verification(sas);
app.confirm = None;
return Ok(());
}
_ => {}
}
}
}

if app.signin.is_none() && app.rooms.is_none() && key_event.code == KeyCode::Char('k') {
app.rooms = Some(Rooms::new(app.matrix.clone()));
// there's probably a more elegant way to do this...
if app.signin.is_none()
&& app.rooms.is_none()
&& app.confirm.is_none()
&& app.progress.is_none()
&& app.error.is_none()
{
if let Some(chat) = &app.chat {
match chat.input(&app, &key_event) {
Err(err) => app.error = Some(Error::new(err.to_string())),
_ => {}
}
}

match key_event.code {
KeyCode::Char('k') => app.rooms = Some(Rooms::new(app.matrix.clone())),
_ => {}
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ pub mod widgets;

/// Matrix
pub mod matrix;

/// Using external apps to do our bidding
pub mod spawn;
11 changes: 6 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,24 @@ fn main() -> anyhow::Result<()> {
let terminal = Terminal::new(backend)?;
let events = EventHandler::new(250);
let sender = events.sender();
let mut tui = Tui::new(terminal, events);
let mut tui = Tui::new(terminal);
tui.init()?;

// Create an application.
let mut app = App::new(sender);
let mut app = App::new(sender, events);

// Start the main loop.
while app.running {
// Handle events.
match tui.events.next()? {
match app.events.next()? {
Event::Tick => {
app.tick();
tui.draw(&mut app)?;
tui.draw(&mut app, false)?;
}
Event::Redraw => tui.draw(&mut app, true)?,
Event::Key(key_event) => {
handle_key_event(key_event, &mut app)?;
tui.draw(&mut app)?;
tui.draw(&mut app, false)?;
}
Event::Mouse(_) => {}
Event::Resize(_, _) => {}
Expand Down
25 changes: 22 additions & 3 deletions src/matrix/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use std::sync::Arc;
use crate::app::App;
use crate::event::Event;
use crate::event::Event::{Matui, Tick};
use crate::handler::MatuiEvent::{Error, VerificationCompleted, VerificationStarted};
use crate::handler::MatuiEvent::{
Error, ProgressComplete, ProgressStarted, VerificationCompleted, VerificationStarted,
};
use crate::handler::{MatuiEvent, SyncType};
use crate::matrix::roomcache::{DecoratedRoom, RoomCache};
use anyhow::{bail, Context};
Expand All @@ -30,6 +32,7 @@ use matrix_sdk::{Client, LoopCtrl, ServerName, Session};
use once_cell::sync::OnceCell;
use rand::rngs::OsRng;
use rand::{distributions::Alphanumeric, Rng};
use ruma::events::room::message::RoomMessageEventContent;
use ruma::events::{AnySyncTimelineEvent, AnyTimelineEvent};
use ruma::UInt;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -112,8 +115,6 @@ impl Matrix {
.set(client.clone())
.expect("could not set client");

add_default_handlers(client.clone());

if let Err(err) = sync_once(client.clone(), token, &session_file).await {
matrix.send(Error(err.to_string()));
return;
Expand Down Expand Up @@ -162,6 +163,7 @@ impl Matrix {
}

pub fn sync(&self) {
add_default_handlers(self.client());
add_verification_handlers(self.client());

let client = self.client();
Expand Down Expand Up @@ -279,6 +281,23 @@ impl Matrix {
});
}

pub fn send_text_message(&self, room: Joined, message: String) {
let matrix = self.clone();

self.rt.spawn(async move {
matrix.send(ProgressStarted("Sending message.".to_string()));

if let Err(err) = room
.send(RoomMessageEventContent::text_plain(message), None)
.await
{
matrix.send(Error(err.to_string()));
}

matrix.send(ProgressComplete);
});
}

pub fn timeline_event(&self, event: &AnyTimelineEvent) {
let matrix = self.clone();
let event = event.clone();
Expand Down
Loading

0 comments on commit 7144a3b

Please sign in to comment.