Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

State rewrite #1

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

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

14 changes: 10 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cargo-features = ["strip"]
name = "rshub"
version = "0.1.4"
authors = ["Fogapod <[email protected]>"]
edition = "2018"
edition = "2021"
description = "Unofficial game launcher for UnityStation"
homepage = "https://github.com/Fogapod/rshub"
repository = "https://github.com/Fogapod/rshub"
Expand All @@ -13,7 +13,6 @@ keywords = ["ss13", "unitystation", "ui", "cli", "terminal"]
categories = ["command-line-utilities", "games"]
exclude = [".github/*", ".assets/*"]


[features]
default = ["rustls"]

Expand All @@ -25,13 +24,20 @@ geolocation = []

[dependencies]
serde_json = "1"
crossterm = "0.21"
better-panic = "0.2.0"
dirs-next = "2.0.0"
async-trait = "0.1.51"
bytesize = "1.1.0"
anyhow = "1.0.43"

[dependencies.crossterm]
version = "0.21.0"
features = ["event-stream"]

[dependencies.parking_lot]
version = "0.11.2"
features = ["send_guard"]

[dependencies.zip]
version = "0.5.13"
default-features = false
Expand All @@ -40,7 +46,7 @@ features = ["deflate"]
[dependencies.tokio]
version = "1"
default-features = false
features = ["rt-multi-thread", "sync", "fs", "process", "macros", "time"]
features = ["rt-multi-thread", "fs", "process", "macros", "time"]

[dependencies.futures]
version = "0.3.16"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ RSHub requires nightly rust toolchain to build (unstable strip feature).
If you do not have nightly toolchain, you can prefix cargo commands with `RUSTC_BOOTSTRAP=1 cargo ...` as a workaround.

Install from crates.io (stable version): `cargo install rshub`
Or with [geolocation](#geolocation) feature: `cargo install rshub --feature geolocation`
Or with [geolocation](#geolocation) feature: `cargo install rshub --features geolocation`

Run from source (latest version):
`cargo run` or `cargo run --release` (slow)
Expand Down
103 changes: 81 additions & 22 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
use std::collections::HashMap;
use std::convert::TryFrom;
use std::io;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use std::time::Duration;

use tui::backend::CrosstermBackend;
use tui::terminal::Frame;
use tui::terminal::{Frame, Terminal};

use crossterm::event::EventStream;

use futures::StreamExt;

use tokio::sync::mpsc;

use crate::config::AppConfig;
use crate::datatypes::game_version::GameVersion;
Expand All @@ -13,7 +20,13 @@ use crate::input::UserInput;
use crate::states::app::AppState;
#[cfg(feature = "geolocation")]
use crate::views::world::World;
use crate::views::{events::EventsView, help::Help, tabs::TabView, AppView, Drawable, ViewType};
use crate::views::{events::EventsView, help::Help, tabs::Tabs, AppView, Draw, ViewType};

#[derive(Debug)]
pub enum StopSignal {
UserExit,
Panic,
}

#[derive(Debug)]
pub enum AppAction {
Expand All @@ -39,14 +52,14 @@ pub struct App {

events_view: EventsView,

pub stopped: bool,
pub panicked: Arc<AtomicBool>,
pub kill_switch: mpsc::Sender<StopSignal>,
kill_switch_recv: mpsc::Receiver<StopSignal>,
}

impl App {
pub async fn new(config: AppConfig) -> Self {
let panic_bool = Arc::new(AtomicBool::new(false));
let state = AppState::new(config, panic_bool.clone()).await;
pub fn new(config: AppConfig) -> Self {
let (kill_switch, kill_switch_recv) = mpsc::channel(1);
let state = Arc::new(AppState::new(config, kill_switch.clone()));

let mut instance = Self {
state,
Expand All @@ -56,11 +69,11 @@ impl App {

events_view: EventsView {},

stopped: false,
panicked: panic_bool,
kill_switch,
kill_switch_recv,
};

instance.register_view(ViewType::Tab, Box::new(TabView::new()));
instance.register_view(ViewType::Tab, Box::new(Tabs::new()));
#[cfg(feature = "geolocation")]
instance.register_view(ViewType::World, Box::new(World {}));
instance.register_view(ViewType::Help, Box::new(Help {}));
Expand All @@ -72,27 +85,75 @@ impl App {
self.views.insert(tp, view);
}

pub async fn draw(&mut self, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) {
pub async fn run(&mut self, terminal: &mut Terminal<CrosstermBackend<io::Stdout>>) {
self.state.run(Arc::clone(&self.state)).await;

let interval = Duration::from_millis(200);
let mut delay = tokio::time::interval(interval);
let mut reader = EventStream::new();

loop {
tokio::select! {
_ = delay.tick() => {
terminal.draw(|f| self.draw(f)).unwrap();
},
maybe_event = reader.next() => {
match maybe_event {
Some(Ok(event)) => {
if let Ok(valid_input) = UserInput::try_from(&event) {
self.on_input(&valid_input).await;
}
},
Some(Err(err)) => {
log::error!("Error reading input: {}", err);
break;
}
None => {
log::error!("Input channel closed somehow");
break
},
}
},
stop = self.kill_switch_recv.recv() => {
if let Some(stop) = stop {
match stop {
StopSignal::UserExit => {
log::info!("app stopped, cleaning up");
break;
}
StopSignal::Panic => {
log::error!("app panicked, cleaning up");
break;
}
}
} else {
log::error!("kill_switch channel closed somehow");
break;
}
}
}
}
}

pub fn draw(&mut self, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) {
if let Some(tp) = self.view_stack.last() {
if let Some(widget) = self.views.get_mut(tp) {
use tui::layout::{Constraint, Direction, Layout};

let area = if self.state.events.read().await.current_event.is_some() {
let area = if self.state.events.read().current_event.is_some() {
let chunks = Layout::default()
.constraints(vec![Constraint::Min(0), Constraint::Length(1)])
.direction(Direction::Vertical)
.split(f.size());

self.events_view
.draw(f, chunks[1], Arc::clone(&self.state))
.await;
self.events_view.draw(f, chunks[1], Arc::clone(&self.state));

chunks[0]
} else {
f.size()
};

widget.draw(f, area, Arc::clone(&self.state)).await;
widget.draw(f, area, Arc::clone(&self.state));
}
}
}
Expand All @@ -101,7 +162,9 @@ impl App {
log::debug!("input: {:?}", input);

match input {
UserInput::Quit => self.stop(),
UserInput::Quit => {
self.kill_switch.send(StopSignal::UserExit).await.unwrap();
}
UserInput::Help => {
if let Some(top_view_type) = self.view_stack.last() {
if top_view_type == &ViewType::Help {
Expand Down Expand Up @@ -134,8 +197,4 @@ impl App {
}
}
}

fn stop(&mut self) {
self.stopped = true;
}
}
43 changes: 43 additions & 0 deletions src/datatypes/hotkey.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::fmt;

use crossterm::event::{KeyCode, KeyModifiers};

// TODO: less code duplication by associating this with inputs.rs somehow
#[derive(Debug, Clone)]
pub struct HotKey {
pub description: &'static str,
pub key: KeyCode,
pub modifiers: Option<KeyModifiers>,
}

impl fmt::Display for HotKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(modifiers) = self.modifiers {
write!(f, "{:?}+", modifiers)?;
}
write!(
f,
"{}",
match self.key {
KeyCode::Backspace => "Backspace".to_owned(),
KeyCode::Enter => "Enter".to_owned(),
KeyCode::Left => "Left".to_owned(),
KeyCode::Right => "Right".to_owned(),
KeyCode::Up => "Up".to_owned(),
KeyCode::Down => "Down".to_owned(),
KeyCode::Home => "Home".to_owned(),
KeyCode::End => "End".to_owned(),
KeyCode::PageUp => "PageUp".to_owned(),
KeyCode::PageDown => "PageDown".to_owned(),
KeyCode::Tab => "Tab".to_owned(),
KeyCode::BackTab => "BackTab".to_owned(),
KeyCode::Delete => "Delete".to_owned(),
KeyCode::Insert => "Insert".to_owned(),
KeyCode::F(i) => format!("F{}", i),
KeyCode::Char(c) => c.to_uppercase().to_string(),
KeyCode::Null => "Null".to_owned(),
KeyCode::Esc => "Esc".to_owned(),
}
)
}
}
1 change: 1 addition & 0 deletions src/datatypes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod commit;
pub mod game_version;
pub mod geolocation;
pub mod hotkey;
pub mod installation;
pub mod server;
pub mod value_sorted_map;
5 changes: 1 addition & 4 deletions src/datatypes/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ pub struct Server {
pub gamemode: String,
pub time: String,
pub fps: u32,
// ui update skip optimization
// pub updated: bool,
pub offline: bool,
}

Expand All @@ -145,8 +143,7 @@ impl Server {
players,
fps,
version,
address: address.clone(),
// updated: true,
address,
offline: false,
}
}
Expand Down
Loading