Compare commits

...

3 commits

Author SHA1 Message Date
clizia
16acd8c00e another time 2025-05-14 22:18:31 +02:00
clizia
d1ea7eb2c0 textarea shows but doesnt update 2025-05-14 17:57:05 +02:00
clizia
72bd4ce74c second try at joining lobby 2025-05-14 16:55:48 +02:00
3 changed files with 136 additions and 68 deletions

View file

@ -1,24 +1,32 @@
use anyhow::Result; use anyhow::Result;
use ratatui::{widgets::ListState, DefaultTerminal}; use ratatui::{widgets::ListState, DefaultTerminal};
use tui_textarea::TextArea;
use crate::{lobby::Lobby, message::{Message, MessageKind}, player::Player, ui::{ui, CurrentScreen}}; use crate::{
lobby::Lobby,
message::{Message, MessageKind},
player::Player,
ui::ui,
};
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Client { pub struct Client<'a> {
pub addr: String, pub addr: String,
pub client: reqwest::Client, pub client: reqwest::Client,
pub user: Option<String>, pub user: Option<String>,
pub user_name: String, pub user_name: String,
pub exit: bool, pub exit: bool,
pub popup_user_input: bool,
pub popup: bool, pub popup: bool,
pub popup_title: String, pub popup_title: String,
pub popup_content: String, pub popup_content: String,
pub response: String, pub response: String,
pub lobby: Option<String>, pub lobby: Option<String>,
pub lobby_id: String, pub lobby_id: String,
pub textarea: TextArea<'a>,
} }
impl Client { impl Client<'_> {
pub async fn run(&mut self, terminal: &mut DefaultTerminal) -> anyhow::Result<()> { pub async fn run(&mut self, terminal: &mut DefaultTerminal) -> anyhow::Result<()> {
self.addr = "http://127.0.0.1:8080".to_string(); self.addr = "http://127.0.0.1:8080".to_string();
self.client = reqwest::Client::new(); self.client = reqwest::Client::new();

View file

@ -114,7 +114,7 @@ impl App {
true => { true => {
players.remove(&player_id); players.remove(&player_id);
println!("{:?}", players); println!("{:?}", players);
Ok(Json(Message::new("server", MessageKind::DeletePlayer, "user deleted").expect("a"))) Ok(Json(Message::new("server", MessageKind::DeletePlayer, "user deleted").expect("failed to create message")))
}, },
false => Err(String::from("player not found")), false => Err(String::from("player not found")),
} }

188
src/ui.rs
View file

@ -8,12 +8,29 @@ use ratatui::{
}, },
style::{Color, Style, Stylize}, style::{Color, Style, Stylize},
text::{Line, Span, Text}, text::{Line, Span, Text},
widgets::{Block, Borders, Clear, List, ListItem, ListState, Paragraph, Widget, Wrap}, widgets::{
Block,
Borders,
Clear,
List,
ListItem,
ListState,
Paragraph,
Widget,
Wrap
},
Frame, Frame,
crossterm::event::{
self,
Event,
KeyCode,
KeyEvent,
KeyEventKind
}
}; };
use ratatui::crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind}; use tui_textarea::{Key, Input, TextArea};
use crate::{client::Client, message::{Message, MessageKind}, player::Player}; use crate::{client::Client, db::AppState, message::{Message, MessageKind}, player::Player};
const HELP: &str = r#"bindings: const HELP: &str = r#"bindings:
h - show help h - show help
@ -23,6 +40,7 @@ q - quit
3 - send player to server 3 - send player to server
4 - send lobby to server"#; 4 - send lobby to server"#;
// popup things
#[derive(Debug, Default, Setters)] #[derive(Debug, Default, Setters)]
struct Popup<'a> { struct Popup<'a> {
#[setters(into)] #[setters(into)]
@ -34,6 +52,7 @@ struct Popup<'a> {
style: Style, style: Style,
} }
// popup things
impl Widget for Popup<'_> { impl Widget for Popup<'_> {
fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer) fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer)
where where
@ -54,81 +73,95 @@ impl Widget for Popup<'_> {
} }
} }
#[derive(Debug, Default)] async fn handle_key_event(mut client: &mut Client<'_>, key_event: KeyEvent) {
pub enum CurrentScreen { match client.popup_user_input {
#[default] Menu,
Lobbies,
}
async fn handle_key_event(mut client: &mut Client, key_event: KeyEvent) {
match &client.popup {
false => {
match key_event.code {
KeyCode::Char('q') => Client::exit(client),
KeyCode::Char('h') => {
client.popup_title = "help".to_string();
client.popup_content = HELP.to_string();
client.popup = true;
},
KeyCode::Char('1') => {
if client.user != None {
client.popup_title = "Error".to_string();
client.popup_content = "user already_created".to_string();
client.popup = true;
} else {
let addr = client.addr.clone();
let path = "/create/player";
let message = Message::new(
"",
MessageKind::CreatePlayer,
""
).unwrap();
Client::send(&mut client, message, &addr, &path).await.unwrap();
client.user_name = client.user.clone().unwrap();
}
},
KeyCode::Char('2') => {
if client.lobby != None || client.user == None {
client.popup_title = "Error".to_string();
client.popup_content = "lobby already_created or player not yet created".to_string();
client.popup = true;
} else {
let addr = client.addr.clone();
let path = "/create/lobby";
let message = Message::new(
"",
MessageKind::CreateLobby,
&client.user_name,
).unwrap();
Client::send(&mut client, message, &addr, &path).await.unwrap();
client.lobby_id = client.lobby.clone().unwrap();
}
},
_ => (),
}
}
true => { true => {
match key_event.code { match key_event.into() {
_ => client.popup = false, Input {key: Key::Esc, ..} => client.popup_user_input = false,
input => {
client.textarea.input(input);
},
}
},
false => {
match &client.popup {
false => {
match key_event.code {
// quit
KeyCode::Char('q') => Client::exit(client),
KeyCode::Char('h') => {
client.popup_title = "help".to_string();
client.popup_content = HELP.to_string();
client.popup = true;
},
// player creation
KeyCode::Char('1') => {
if client.user != None {
client.popup_title = "Error".to_string();
client.popup_content = "user already_created".to_string();
client.popup = true;
} else {
let addr = client.addr.clone();
let path = "/create/player";
let message = Message::new(
"",
MessageKind::CreatePlayer,
""
).unwrap();
Client::send(&mut client, message, &addr, &path).await.unwrap();
client.user_name = client.user.clone().unwrap();
}
},
// lobby creation
KeyCode::Char('2') => {
if client.lobby != None || client.user == None {
client.popup_title = "Error".to_string();
client.popup_content = "lobby already_created or player not yet created".to_string();
client.popup = true;
} else {
let addr = client.addr.clone();
let path = "/create/lobby";
let message = Message::new(
"",
MessageKind::CreateLobby,
&client.user_name,
).unwrap();
Client::send(&mut client, message, &addr, &path).await.unwrap();
client.lobby_id = client.lobby.clone().unwrap();
}
},
// popup for lobby search
KeyCode::Char('3') => {
client.popup_user_input = true;
}
_ => (),
}
}
true => {
match key_event.code {
_ => client.popup = false,
}
}
} }
} }
} }
} }
pub async fn handle_events(client: &mut Client) -> anyhow::Result<()> { pub async fn handle_events(app: &mut Client<'_>) -> anyhow::Result<()> {
match event::read()? { match event::read()? {
Event::Key(key) if key.kind == KeyEventKind::Press => { Event::Key(key) if key.kind == KeyEventKind::Press => {
handle_key_event(client, key).await handle_key_event(app, key).await
} }
_ => {} _ => ()
} }
Ok(()) Ok(())
} }
pub fn ui(frame: &mut Frame, app: &Client) { pub fn ui(frame: &mut Frame, app: &mut Client) {
// main ui
let chunks = Layout::default() let chunks = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints([ .constraints([
@ -142,6 +175,8 @@ pub fn ui(frame: &mut Frame, app: &Client) {
" create player ".into(), " create player ".into(),
"2".blue().bold(), "2".blue().bold(),
" create lobby ".into(), " create lobby ".into(),
"3".blue().bold(),
" search lobby ".into(),
"<Q>".blue().bold(), "<Q>".blue().bold(),
" quit ".into(), " quit ".into(),
]); ]);
@ -188,6 +223,7 @@ pub fn ui(frame: &mut Frame, app: &Client) {
chunks[1], chunks[1],
); );
// popup things
let popup_area = Rect { let popup_area = Rect {
x: frame.area().width / 4, x: frame.area().width / 4,
y: frame.area().height / 3, y: frame.area().height / 3,
@ -204,4 +240,28 @@ pub fn ui(frame: &mut Frame, app: &Client) {
.border_style(Style::new().red()); .border_style(Style::new().red());
frame.render_widget(popup, popup_area); frame.render_widget(popup, popup_area);
} }
let mut textarea = TextArea::default();
textarea.set_block(
Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(Color::LightBlue))
.title("Crossterm Popup Example"),
);
let area = Rect {
width: 40,
height: 5,
x: 5,
y: 5,
};
textarea.set_style(Style::default().fg(Color::Yellow));
textarea.set_placeholder_style(Style::default());
app.textarea = textarea;
if app.popup_user_input == true {
frame.render_widget(&app.textarea, area);
}
} }