move stuff around a little

This commit is contained in:
Joe Ardent 2025-08-02 11:28:57 -07:00
parent d73076f197
commit 34e64f5e51
3 changed files with 95 additions and 99 deletions

View file

@ -2,17 +2,11 @@ use std::{collections::BTreeMap, net::SocketAddr, time::Duration};
use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, KeyEventKind};
use futures::{FutureExt, StreamExt};
use joecalsend::{
Config, JoecalService, JoecalUploadRequest, Listeners, TransferEvent, UploadDialog,
error::Result, models::Device,
};
use joecalsend::{JoecalService, JoecalUploadRequest, TransferEvent, UploadDialog, error::Result};
use julid::Julid;
use log::{LevelFilter, debug, error, info, warn};
use ratatui::{DefaultTerminal, Frame, widgets::TableState};
use tokio::{
sync::mpsc::{UnboundedReceiver, unbounded_channel},
task::JoinSet,
};
use log::{LevelFilter, debug, error, warn};
use ratatui::{Frame, widgets::TableState};
use tokio::sync::mpsc::UnboundedReceiver;
pub mod widgets;
@ -40,58 +34,6 @@ pub enum CurrentScreen {
Logging,
}
#[tokio::main]
pub async fn start_and_run(
terminal: &mut DefaultTerminal,
config: Config,
device: Device,
) -> Result<()> {
let (event_tx, event_listener) = unbounded_channel();
let service = JoecalService::new(device, event_tx)
.await
.expect("Could not create JoecalService");
let mut app = App::new(service, event_listener);
let mut handles = JoinSet::new();
app.service.start(&config, &mut handles).await;
loop {
terminal.draw(|frame| app.draw(frame))?;
app.handle_events().await?;
if let Some(&top) = app.screen.last()
&& top == CurrentScreen::Stopping
{
app.service.stop().await;
break;
}
let peers = app.service.peers.lock().await;
app.peers.clear();
peers.iter().for_each(|(fingerprint, (addr, device))| {
let alias = device.alias.clone();
app.peers
.insert(addr.to_owned(), (alias, fingerprint.to_owned()));
});
let mut stale_uploads = Vec::new();
let now = chrono::Utc::now().timestamp_millis() as u64;
for (id, request) in app.uploads.iter() {
if request.tx.is_closed() || (now - id.timestamp()) > 60_000 {
stale_uploads.push(*id);
}
}
for id in stale_uploads {
app.uploads.remove(&id);
}
}
shutdown(&mut handles).await;
Ok(())
}
impl App {
pub fn new(service: JoecalService, event_listener: UnboundedReceiver<TransferEvent>) -> Self {
App {
@ -105,7 +47,7 @@ impl App {
}
}
async fn handle_events(&mut self) -> Result<()> {
pub async fn handle_events(&mut self) -> Result<()> {
tokio::select! {
event = self.events.next().fuse() => {
if let Some(Ok(evt)) = event {
@ -138,7 +80,7 @@ impl App {
Ok(())
}
fn handle_key_event(&mut self, key_event: KeyEvent) {
pub fn handle_key_event(&mut self, key_event: KeyEvent) {
match self.screen.last().unwrap() {
CurrentScreen::Logging => match key_event.code {
KeyCode::Esc => self.pop(),
@ -167,7 +109,7 @@ impl App {
}
}
fn accept(&mut self) {
pub fn accept(&mut self) {
let Some(idx) = self.upload_state.selected() else {
return;
};
@ -185,7 +127,7 @@ impl App {
};
}
fn deny(&mut self) {
pub fn deny(&mut self) {
let Some(idx) = self.upload_state.selected() else {
return;
};
@ -204,15 +146,15 @@ impl App {
self.uploads.remove(key);
}
fn draw(&mut self, frame: &mut Frame) {
pub fn draw(&mut self, frame: &mut Frame) {
frame.render_widget(self, frame.area());
}
fn exit(&mut self) {
pub fn exit(&mut self) {
self.screen.push(CurrentScreen::Stopping);
}
fn send(&mut self) {
pub fn send(&mut self) {
let last = self.screen.last();
match last {
Some(CurrentScreen::Sending) => {}
@ -220,7 +162,7 @@ impl App {
}
}
fn recv(&mut self) {
pub fn recv(&mut self) {
let last = self.screen.last();
match last {
Some(CurrentScreen::Receiving) => {}
@ -228,7 +170,7 @@ impl App {
}
}
fn logs(&mut self) {
pub fn logs(&mut self) {
let last = self.screen.last();
match last {
Some(CurrentScreen::Logging) => {}
@ -236,7 +178,7 @@ impl App {
}
}
fn pop(&mut self) {
pub fn pop(&mut self) {
self.screen.pop();
if self.screen.last().is_none() {
self.screen.push(CurrentScreen::Main);
@ -253,26 +195,3 @@ fn change_log_level(delta: isize) {
log::set_max_level(level);
}
async fn shutdown(handles: &mut JoinSet<Listeners>) {
let mut alarm = tokio::time::interval(tokio::time::Duration::from_secs(5));
alarm.tick().await;
loop {
tokio::select! {
join_result = handles.join_next() => {
match join_result {
Some(handle) => match handle {
Ok(h) => info!("Stopped {h:?}"),
Err(e) => error!("Got error {e:?}"),
}
None => break,
}
}
_ = alarm.tick() => {
info!("Exit timeout reached, aborting all unjoined tasks");
handles.abort_all();
break;
},
}
}
}

View file

@ -9,7 +9,6 @@ use axum::{
extract::{ConnectInfo, State},
};
use log::{debug, error, trace, warn};
use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig, V4IfAddr};
use tokio::net::UdpSocket;
use crate::{Config, JoecalService, RunningState, models::Device};

View file

@ -1,8 +1,11 @@
use joecalsend::{Config, error, models::Device};
use local_ip_address::local_ip;
use joecalsend::{Config, JoecalService, Listeners, error, models::Device};
use log::{error, info};
use ratatui::DefaultTerminal;
use tokio::{sync::mpsc::unbounded_channel, task::JoinSet};
use tui_logger::{LevelFilter, init_logger, set_env_filter_from_env};
mod app;
use app::{App, CurrentScreen};
fn main() -> error::Result<()> {
let device = Device::default();
@ -18,8 +21,83 @@ fn main() -> error::Result<()> {
let config = Config::default();
let mut terminal = ratatui::init();
let result = app::start_and_run(&mut terminal, config, device);
let result = start_and_run(&mut terminal, config, device);
ratatui::restore();
result
}
#[tokio::main]
async fn start_and_run(
terminal: &mut DefaultTerminal,
config: Config,
device: Device,
) -> error::Result<()> {
let (event_tx, event_listener) = unbounded_channel();
let service = JoecalService::new(device, event_tx)
.await
.expect("Could not create JoecalService");
let mut app = App::new(service, event_listener);
let mut handles = JoinSet::new();
app.service.start(&config, &mut handles).await;
loop {
terminal.draw(|frame| app.draw(frame))?;
app.handle_events().await?;
if let Some(&top) = app.screen.last()
&& top == CurrentScreen::Stopping
{
app.service.stop().await;
break;
}
let peers = app.service.peers.lock().await;
app.peers.clear();
peers.iter().for_each(|(fingerprint, (addr, device))| {
let alias = device.alias.clone();
app.peers
.insert(addr.to_owned(), (alias, fingerprint.to_owned()));
});
let mut stale_uploads = Vec::with_capacity(app.uploads.len());
let now = chrono::Utc::now().timestamp_millis() as u64;
for (id, request) in app.uploads.iter() {
if request.tx.is_closed() || (now - id.timestamp()) > 60_000 {
stale_uploads.push(*id);
}
}
for id in stale_uploads {
app.uploads.remove(&id);
}
}
shutdown(&mut handles).await;
Ok(())
}
async fn shutdown(handles: &mut JoinSet<Listeners>) {
let mut alarm = tokio::time::interval(tokio::time::Duration::from_secs(5));
alarm.tick().await;
loop {
tokio::select! {
join_result = handles.join_next() => {
match join_result {
Some(handle) => match handle {
Ok(h) => info!("Stopped {h:?}"),
Err(e) => error!("Got error {e:?}"),
}
None => break,
}
}
_ = alarm.tick() => {
info!("Exit timeout reached, aborting all unjoined tasks");
handles.abort_all();
break;
},
}
}
}