Skip to content

Instantly share code, notes, and snippets.

@sigmaSd
Created November 1, 2020 09:59
Show Gist options
  • Save sigmaSd/393b475e3ed3ebec48fedcaabd150e19 to your computer and use it in GitHub Desktop.
Save sigmaSd/393b475e3ed3ebec48fedcaabd150e19 to your computer and use it in GitHub Desktop.
channel
use super::Event;
use super::{stringify_sendall_errors, Application, NetMessage};
use crate::state::{ApplicationState, TermchatMessageType};
use crate::ui;
use crate::util::{termchat_message, Result};
use crossterm::event::{Event as TermEvent, KeyCode, KeyEvent, KeyModifiers};
impl Application {
pub fn parse_input(&mut self, input: &str, state: &mut ApplicationState) -> Result<()> {
const SEND_COMMAND: &str = "?send";
if input.starts_with(SEND_COMMAND) {
let events = self.handle_send_command(input, state)?;
let tmp_sender = self.event_queue.sender();
for ev in events.into_iter().rev() {
tmp_sender.send(ev);
}
}
Ok(())
}
fn handle_send_command(
&mut self,
input: &str,
state: &mut ApplicationState,
) -> Result<Vec<Event>> {
use std::io::Read;
const READ_FILENAME_ERROR: &str = "Unable to read file name";
let path =
std::path::Path::new(input.split_whitespace().nth(1).ok_or("No file specified")?);
let file_name = path
.file_name()
.ok_or(READ_FILENAME_ERROR)?
.to_str()
.ok_or(READ_FILENAME_ERROR)?
.to_string();
use std::convert::TryInto;
let file_size = std::fs::metadata(path)?.len().try_into()?;
state.progress.start(file_size);
let mut file = std::fs::File::open(path)?;
const BLOCK: usize = 65536;
let mut data = [0; BLOCK];
let (local_tx, local_rx) = std::sync::mpsc::channel();
let event_queue = self.event_queue.clone();
std::thread::spawn(move || loop {
let mut v = vec![];
let ev = event_queue.receive();
if let Some(Event::Terminal(TermEvent::Key(KeyEvent {
code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL,
}))) = ev
{
local_tx.send(v);
break;
} else {
v.push(ev);
}
});
let mut leftover = vec![];
loop {
match file.read(&mut data) {
Ok(bytes_read) => {
state.progress.advance(bytes_read);
let data_to_send = data[..bytes_read].to_vec();
self.network
.send_all(
state.all_user_endpoints(),
NetMessage::UserData(
file_name.clone(),
Some((data_to_send, bytes_read)),
None,
),
)
.map_err(stringify_sendall_errors)?;
// done
if bytes_read == 0 {
let msg = format!("Successfully sent file {} !", file_name);
let msg = termchat_message(msg, TermchatMessageType::Notification);
state.add_message(msg);
break;
}
}
Err(e) => {
state.progress.done();
self.network
.send_all(
state.all_user_endpoints(),
NetMessage::UserData(file_name, None, Some(e.to_string())),
)
.map_err(stringify_sendall_errors)?;
return Err(e.into());
}
}
ui::draw(&mut self.terminal, &state)?;
// check for ctrl_c
if let Ok(Some(events)) = local_rx.try_recv() {
leftover = events;
let message =
termchat_message("File not sent.".into(), TermchatMessageType::Notification);
state.add_message(message);
self.network
.send_all(
state.all_user_endpoints(),
NetMessage::UserData(file_name, None, Some("User aborted.".into())),
)
.map_err(stringify_sendall_errors)?;
break;
}
}
state.progress.done();
ui::draw(&mut self.terminal, &state)?;
Ok(leftover)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment