lobby list skeleton

This commit is contained in:
clizia 2025-04-18 14:22:23 +02:00
parent ed77971e41
commit b37ab4a37d
8 changed files with 477 additions and 368 deletions

593
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -18,8 +18,11 @@ RUSTFLAGS="--cfg tokio_unstable" cargo run --bin server
- [x] move player creation on the server - [x] move player creation on the server
- [x] move lobby creation on the server - [x] move lobby creation on the server
- [ ] add clap configuration
- [ ] delete player - [ ] delete player
- [ ] delete lobby - [ ] delete lobby
- [ ] join existing lobbies - [ ] join existing lobbies
- [ ] actually do the game - [ ] actually do the game
- [ ] fixing ui (perpetual) - [ ] fixing ui (perpetual)
- [ ] add unit testing
- [ ] reorganize modules

View file

@ -1,12 +1,13 @@
use anyhow::Result; use anyhow::Result;
use ratatui::DefaultTerminal; use ratatui::DefaultTerminal;
use crate::{message::{Message, MessageKind}, player::Player, ui::ui}; use crate::{message::{Message, MessageKind}, player::Player, ui::{ui, CurrentScreen}};
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Client { pub struct Client {
pub addr: String, pub addr: String,
pub client: reqwest::Client, pub client: reqwest::Client,
pub current_screen: CurrentScreen,
pub user: Option<String>, pub user: Option<String>,
pub user_name: String, pub user_name: String,
pub exit: bool, pub exit: bool,

10
src/entity.rs Normal file
View file

@ -0,0 +1,10 @@
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Entity<T: Serialize>(T);
impl<T: Serialize> Entity<T> {
pub fn encode(&self) -> anyhow::Result<String, serde_json::Error> {
serde_json::to_string(&self)
}
}

View file

@ -17,6 +17,8 @@ pub enum MessageKind {
CreateLobby, CreateLobby,
DeletePlayer, DeletePlayer,
DeleteLobby, DeleteLobby,
JoinLobby,
QuitLobby,
} }
impl Message { impl Message {

View file

@ -126,4 +126,11 @@ impl App {
} }
} }
pub async fn join_lobby(
State(db): State<AppState>,
Path(lobby_id): Path<String>
) -> Result<axum::response::Json<Message>, StatusCode> {
todo!()
}
} }

View file

@ -33,6 +33,7 @@ impl Server {
.route("/create/lobby", post(App::create_lobby)) .route("/create/lobby", post(App::create_lobby))
.route("/delete/player/{player_id}", get(App::delete_player)) .route("/delete/player/{player_id}", get(App::delete_player))
.route("/delete/lobby/{lobby_id}", get(App::delete_lobby)) .route("/delete/lobby/{lobby_id}", get(App::delete_lobby))
.route("/join/{lobby_id}", post(App::join_lobby))
.with_state(app.db); .with_state(app.db);
axum::serve(listener, router).await.unwrap(); axum::serve(listener, router).await.unwrap();

226
src/ui.rs
View file

@ -54,53 +54,64 @@ impl Widget for Popup<'_> {
} }
} }
#[derive(Debug, Default)]
pub enum CurrentScreen {
#[default] Menu,
LobbyList,
}
async fn handle_key_event(mut client: &mut Client, key_event: KeyEvent) { async fn handle_key_event(mut client: &mut Client, key_event: KeyEvent) {
match &client.popup { match &client.popup {
false => { false => {
match key_event.code { match client.current_screen {
KeyCode::Char('q') => Client::exit(client), CurrentScreen::Menu => {
KeyCode::Char('h') => { match key_event.code {
client.popup_title = "help".to_string(); KeyCode::Char('q') => Client::exit(client),
client.popup_content = HELP.to_string(); KeyCode::Char('h') => {
client.popup = true; client.popup_title = "help".to_string();
}, client.popup_content = HELP.to_string();
KeyCode::Char('1') => { client.popup = true;
if client.user != None { },
client.popup_title = "Error".to_string(); KeyCode::Char('1') => {
client.popup_content = "user already_created".to_string(); if client.user != None {
client.popup = true; client.popup_title = "Error".to_string();
} else { client.popup_content = "user already_created".to_string();
let addr = client.addr.clone(); client.popup = true;
let path = "/create/player"; } else {
let message = Message::new( let addr = client.addr.clone();
"", let path = "/create/player";
MessageKind::CreatePlayer, let message = Message::new(
"" "",
).unwrap(); MessageKind::CreatePlayer,
""
).unwrap();
Client::send(&mut client, message, &addr, &path).await.unwrap(); Client::send(&mut client, message, &addr, &path).await.unwrap();
client.user_name = client.user.clone().unwrap(); client.user_name = client.user.clone().unwrap();
} }
}, },
KeyCode::Char('2') => { KeyCode::Char('2') => {
if client.lobby != None { if client.lobby != None {
client.popup_title = "Error".to_string(); client.popup_title = "Error".to_string();
client.popup_content = "lobby already_created".to_string(); client.popup_content = "lobby already_created".to_string();
client.popup = true; client.popup = true;
} else { } else {
let addr = client.addr.clone(); let addr = client.addr.clone();
let path = "/create/lobby"; let path = "/create/lobby";
let message = Message::new( let message = Message::new(
"", "",
MessageKind::CreateLobby, MessageKind::CreateLobby,
"" ""
).unwrap(); ).unwrap();
Client::send(&mut client, message, &addr, &path).await.unwrap(); Client::send(&mut client, message, &addr, &path).await.unwrap();
client.lobby_id = client.lobby.clone().unwrap(); client.lobby_id = client.lobby.clone().unwrap();
}
},
_ => (),
} }
}, }
_ => (), CurrentScreen::LobbyList => todo!(),
} }
} }
true => { true => {
@ -123,66 +134,70 @@ pub async fn handle_events(client: &mut Client) -> anyhow::Result<()> {
} }
pub fn ui(frame: &mut Frame, app: &Client) { pub fn ui(frame: &mut Frame, app: &Client) {
let chunks = Layout::default() match app.current_screen {
.direction(Direction::Vertical) CurrentScreen::Menu => {
.constraints([
Constraint::Min(3),
Constraint::Min(1),
])
.split(frame.area());
let instructions = Line::from(vec![ let chunks = Layout::default()
" 1".blue().bold(), .direction(Direction::Vertical)
" create player ".into(), .constraints([
"2".blue().bold(), Constraint::Min(3),
" create lobby ".into(), Constraint::Min(1),
"3".blue().bold(), ])
" send player ".into(), .split(frame.area());
"<Q>".blue().bold(),
" quit ".into(),
]);
let infos = Text::from(vec![ let instructions = Line::from(vec![
Line::from(vec![ " 1".blue().bold(),
"connected to: ".into(), " create player ".into(),
app.addr.clone().yellow(), "2".blue().bold(),
]), " create lobby ".into(),
Line::from(vec![ "<Q>".blue().bold(),
"username: ".into(), " quit ".into(),
app.user_name.clone().yellow(), ]);
]),
Line::from(vec![
"lobby: ".into(),
app.lobby_id.clone().yellow(),
]),
]);
let top_block_title = Line::from(" durak tui test fre ".bold()); let infos = Text::from(vec![
let top_block = Block::default() Line::from(vec![
.title(top_block_title.centered()) "connected to: ".into(),
.borders(Borders::ALL) app.addr.clone().yellow(),
.style(Style::default()); ]),
frame.render_widget(Paragraph::new(infos).block(top_block), chunks[0]); Line::from(vec![
"username: ".into(),
app.user_name.clone().yellow(),
]),
Line::from(vec![
"lobby: ".into(),
app.lobby_id.clone().yellow(),
]),
]);
let server_message = Text::from(vec![ let top_block_title = Line::from(" durak tui test fre ".bold());
Line::from(vec![ let top_block = Block::default()
"message: ".into(), .title(top_block_title.centered())
app.response.clone().blue(), .borders(Borders::ALL)
]) .style(Style::default());
]); frame.render_widget(Paragraph::new(infos).block(top_block), chunks[0]);
let btm_block_title = Line::from(" messaggini carini :3 ".bold()); let server_message = Text::from(vec![
let btm_block = Block::default() Line::from(vec![
.title(btm_block_title.centered()) "message: ".into(),
.title_bottom(instructions.centered()) app.response.clone().blue(),
.borders(Borders::ALL) ])
.style(Style::default()); ]);
frame.render_widget(
Paragraph::new(server_message) let btm_block_title = Line::from(" messaggini carini :3 ".bold());
.wrap(Wrap { trim: true, }) let btm_block = Block::default()
.block(btm_block), .title(btm_block_title.centered())
chunks[1], .title_bottom(instructions.centered())
); .borders(Borders::ALL)
.style(Style::default());
frame.render_widget(
Paragraph::new(server_message)
.wrap(Wrap { trim: true, })
.block(btm_block),
chunks[1],
);
}
CurrentScreen::LobbyList => todo!(),
}
let popup_area = Rect { let popup_area = Rect {
x: frame.area().width / 4, x: frame.area().width / 4,
@ -191,16 +206,13 @@ pub fn ui(frame: &mut Frame, app: &Client) {
height: frame.area().height / 3, height: frame.area().height / 3,
}; };
match &app.popup { if app.popup == true {
true => { let popup = Popup::default()
let popup = Popup::default() .title(app.popup_title.clone())
.title(app.popup_title.clone()) .content(app.popup_content.clone())
.content(app.popup_content.clone()) .style(Style::new().yellow())
.style(Style::new().yellow()) .title_style(Style::new().white().bold())
.title_style(Style::new().white().bold()) .border_style(Style::new().red());
.border_style(Style::new().red()); frame.render_widget(popup, popup_area);
frame.render_widget(popup, popup_area);
},
_ => ()
} }
} }