fix connection channel getting lagged
This commit is contained in:
parent
5ad2831688
commit
48828cac8a
|
|
@ -0,0 +1,60 @@
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use werewolves_proto::player::PlayerId;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ConnectUpdate {
|
||||||
|
updated: Arc<AtomicBool>,
|
||||||
|
connected: Arc<Mutex<Vec<PlayerId>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnectUpdate {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
updated: Arc::new(AtomicBool::new(false)),
|
||||||
|
connected: Arc::new(Mutex::new(Vec::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connect(&self, pid: PlayerId) {
|
||||||
|
let mut connected = self.connected.lock().await;
|
||||||
|
if connected.iter().any(|c| c == &pid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
connected.push(pid);
|
||||||
|
self.updated.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn disconnect(&self, pid: PlayerId) {
|
||||||
|
let mut connected = self.connected.lock().await;
|
||||||
|
if let Some(idx) = connected
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(idx, c)| (c == &pid).then_some(idx))
|
||||||
|
{
|
||||||
|
connected.swap_remove(idx);
|
||||||
|
self.updated.store(true, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Future for ConnectUpdate {
|
||||||
|
type Output = Arc<[PlayerId]>;
|
||||||
|
|
||||||
|
fn poll(
|
||||||
|
self: std::pin::Pin<&mut Self>,
|
||||||
|
cx: &mut std::task::Context<'_>,
|
||||||
|
) -> std::task::Poll<Self::Output> {
|
||||||
|
if self.updated.load(Ordering::SeqCst)
|
||||||
|
&& let Ok(connected) = self.connected.try_lock()
|
||||||
|
{
|
||||||
|
self.updated.store(false, Ordering::SeqCst);
|
||||||
|
std::task::Poll::Ready(connected.clone().into())
|
||||||
|
} else {
|
||||||
|
cx.waker().wake_by_ref();
|
||||||
|
std::task::Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,28 @@
|
||||||
use tokio::sync::broadcast::Receiver;
|
use tokio::sync::broadcast::Receiver;
|
||||||
use werewolves_proto::{error::GameError, player::PlayerId};
|
use werewolves_proto::{error::GameError, player::PlayerId};
|
||||||
|
|
||||||
use crate::{communication::Comms, runner::Message};
|
use crate::{
|
||||||
|
communication::{Comms, connect::ConnectUpdate},
|
||||||
|
runner::Message,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{HostComms, player::PlayerIdComms};
|
use super::{HostComms, player::PlayerIdComms};
|
||||||
|
|
||||||
pub struct LobbyComms {
|
pub struct LobbyComms {
|
||||||
comms: Comms,
|
comms: Comms,
|
||||||
// TODO: move this to not use a receiver
|
// TODO: move this to not use a receiver
|
||||||
connect_recv: Receiver<(PlayerId, bool)>,
|
connect_recv: ConnectUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LobbyComms {
|
impl LobbyComms {
|
||||||
pub fn new(comms: Comms, connect_recv: Receiver<(PlayerId, bool)>) -> Self {
|
pub fn new(comms: Comms, connect_recv: ConnectUpdate) -> Self {
|
||||||
Self {
|
Self {
|
||||||
comms,
|
comms,
|
||||||
connect_recv,
|
connect_recv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_inner(self) -> (Comms, Receiver<(PlayerId, bool)>) {
|
pub fn into_inner(self) -> (Comms, ConnectUpdate) {
|
||||||
(self.comms, self.connect_recv)
|
(self.comms, self.connect_recv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,12 +44,8 @@ impl LobbyComms {
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = self.connect_recv.recv() => {
|
r = self.connect_recv.clone() => {
|
||||||
match r {
|
Ok(Message::ConnectedList(r))
|
||||||
Ok((player_id, true)) => Ok(Message::Connect(player_id)),
|
|
||||||
Ok((player_id, false)) => Ok(Message::Disconnect(player_id)),
|
|
||||||
Err(err) => Err(GameError::GenericError(format!("connect recv: {err}"))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
runner::Message,
|
runner::Message,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod connect;
|
||||||
pub mod host;
|
pub mod host;
|
||||||
pub mod lobby;
|
pub mod lobby;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use werewolves_proto::{
|
||||||
player::PlayerId,
|
player::PlayerId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::LogError;
|
use crate::{LogError, communication::connect::ConnectUpdate};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ConnectionId(PlayerId, Instant);
|
pub struct ConnectionId(PlayerId, Instant);
|
||||||
|
|
@ -66,13 +66,13 @@ impl JoinedPlayer {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct JoinedPlayers {
|
pub struct JoinedPlayers {
|
||||||
players: Arc<Mutex<HashMap<PlayerId, JoinedPlayer>>>,
|
players: Arc<Mutex<HashMap<PlayerId, JoinedPlayer>>>,
|
||||||
connect_state_sender: Sender<(PlayerId, bool)>,
|
connect_state: ConnectUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JoinedPlayers {
|
impl JoinedPlayers {
|
||||||
pub fn new(connect_state_sender: Sender<(PlayerId, bool)>) -> Self {
|
pub fn new(connect_state: ConnectUpdate) -> Self {
|
||||||
Self {
|
Self {
|
||||||
connect_state_sender,
|
connect_state,
|
||||||
players: Arc::new(Mutex::new(HashMap::new())),
|
players: Arc::new(Mutex::new(HashMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,9 +126,7 @@ impl JoinedPlayers {
|
||||||
pub async fn disconnect(&self, connection: &ConnectionId) -> Option<JoinedPlayer> {
|
pub async fn disconnect(&self, connection: &ConnectionId) -> Option<JoinedPlayer> {
|
||||||
let mut map = self.players.lock().await;
|
let mut map = self.players.lock().await;
|
||||||
|
|
||||||
self.connect_state_sender
|
self.connect_state.disconnect(connection.0.clone()).await;
|
||||||
.send((connection.0.clone(), false))
|
|
||||||
.log_warn();
|
|
||||||
|
|
||||||
if map
|
if map
|
||||||
.get(connection.player_id())
|
.get(connection.player_id())
|
||||||
|
|
@ -162,9 +160,8 @@ impl JoinedPlayers {
|
||||||
|
|
||||||
old.receiver
|
old.receiver
|
||||||
} else {
|
} else {
|
||||||
self.connect_state_sender
|
self.connect_state.connect(player_id.clone()).await;
|
||||||
.send((player_id.clone(), true))
|
|
||||||
.log_warn();
|
|
||||||
unsafe { map.get(&player_id).unwrap_unchecked() }
|
unsafe { map.get(&player_id).unwrap_unchecked() }
|
||||||
.receiver
|
.receiver
|
||||||
.resubscribe()
|
.resubscribe()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use core::ops::Not;
|
use core::ops::Not;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
LogError,
|
LogError,
|
||||||
communication::{Comms, lobby::LobbyComms},
|
communication::{Comms, connect::ConnectUpdate, lobby::LobbyComms},
|
||||||
connection::JoinedPlayers,
|
connection::JoinedPlayers,
|
||||||
lobby::{Lobby, LobbyPlayers},
|
lobby::{Lobby, LobbyPlayers},
|
||||||
runner::{IdentifiedClientMessage, Message},
|
runner::{IdentifiedClientMessage, Message},
|
||||||
|
|
@ -23,7 +24,7 @@ type Result<T> = core::result::Result<T, GameError>;
|
||||||
pub struct GameRunner {
|
pub struct GameRunner {
|
||||||
game: Game,
|
game: Game,
|
||||||
comms: Comms,
|
comms: Comms,
|
||||||
connect_recv: Receiver<(PlayerId, bool)>,
|
connect_recv: ConnectUpdate,
|
||||||
player_sender: LobbyPlayers,
|
player_sender: LobbyPlayers,
|
||||||
roles_revealed: bool,
|
roles_revealed: bool,
|
||||||
joined_players: JoinedPlayers,
|
joined_players: JoinedPlayers,
|
||||||
|
|
@ -34,7 +35,7 @@ impl GameRunner {
|
||||||
game: Game,
|
game: Game,
|
||||||
comms: Comms,
|
comms: Comms,
|
||||||
player_sender: LobbyPlayers,
|
player_sender: LobbyPlayers,
|
||||||
connect_recv: Receiver<(PlayerId, bool)>,
|
connect_recv: ConnectUpdate,
|
||||||
joined_players: JoinedPlayers,
|
joined_players: JoinedPlayers,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -117,6 +118,7 @@ impl GameRunner {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut last_err_log = tokio::time::Instant::now() - tokio::time::Duration::from_secs(60);
|
let mut last_err_log = tokio::time::Instant::now() - tokio::time::Duration::from_secs(60);
|
||||||
|
let mut connect_list: Arc<[PlayerId]> = Arc::new([]);
|
||||||
while acks.iter().any(|(_, ackd)| !*ackd) {
|
while acks.iter().any(|(_, ackd)| !*ackd) {
|
||||||
let msg = match self.comms.message().await {
|
let msg = match self.comms.message().await {
|
||||||
Ok(msg) => msg,
|
Ok(msg) => msg,
|
||||||
|
|
@ -204,11 +206,14 @@ impl GameRunner {
|
||||||
public: _,
|
public: _,
|
||||||
},
|
},
|
||||||
message: _,
|
message: _,
|
||||||
})
|
}) => (notify_of_role)(&player_id, self.game.village(), &self.player_sender),
|
||||||
| Message::Connect(player_id) => {
|
Message::ConnectedList(c) => {
|
||||||
(notify_of_role)(&player_id, self.game.village(), &self.player_sender)
|
let newly_connected = c.iter().filter(|c| connect_list.contains(*c));
|
||||||
|
for connected in newly_connected {
|
||||||
|
(notify_of_role)(connected, self.game.village(), &self.player_sender)
|
||||||
|
}
|
||||||
|
connect_list = c;
|
||||||
}
|
}
|
||||||
Message::Disconnect(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,7 +335,7 @@ impl GameEnd {
|
||||||
.send_if_present(&identity.player_id, ServerMessage::GameOver(result))
|
.send_if_present(&identity.player_id, ServerMessage::GameOver(result))
|
||||||
.log_debug();
|
.log_debug();
|
||||||
}
|
}
|
||||||
Message::Connect(_) | Message::Disconnect(_) => {}
|
Message::ConnectedList(_) => {}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ impl Lobby {
|
||||||
.players_in_lobby
|
.players_in_lobby
|
||||||
.send_if_present(&player_id, ServerMessage::Reset);
|
.send_if_present(&player_id, ServerMessage::Reset);
|
||||||
}
|
}
|
||||||
Err((Message::Connect(_), _)) | Err((Message::Disconnect(_), _)) => {}
|
Err((Message::ConnectedList(_), _)) => {}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -299,7 +299,7 @@ impl Lobby {
|
||||||
self.send_lobby_info_to_clients().await;
|
self.send_lobby_info_to_clients().await;
|
||||||
self.send_lobby_info_to_host().await.log_debug();
|
self.send_lobby_info_to_host().await.log_debug();
|
||||||
}
|
}
|
||||||
Message::Connect(_) | Message::Disconnect(_) => self.send_lobby_info_to_host().await?,
|
Message::ConnectedList(_) => self.send_lobby_info_to_host().await?,
|
||||||
Message::Host(HostMessage::Echo(msg)) => {
|
Message::Host(HostMessage::Echo(msg)) => {
|
||||||
self.comms()?.host().send(msg).log_warn();
|
self.comms()?.host().send(msg).log_warn();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use std::{env, io::Write, path::Path};
|
||||||
use tokio::sync::{broadcast, mpsc};
|
use tokio::sync::{broadcast, mpsc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
communication::{Comms, host::HostComms, player::PlayerIdComms},
|
communication::{Comms, connect::ConnectUpdate, host::HostComms, player::PlayerIdComms},
|
||||||
saver::FileSaver,
|
saver::FileSaver,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -92,18 +92,14 @@ async fn main() {
|
||||||
let (send, recv) = broadcast::channel(100);
|
let (send, recv) = broadcast::channel(100);
|
||||||
let (server_send, host_recv) = broadcast::channel(100);
|
let (server_send, host_recv) = broadcast::channel(100);
|
||||||
let (host_send, server_recv) = mpsc::channel(100);
|
let (host_send, server_recv) = mpsc::channel(100);
|
||||||
let (connect_send, connect_recv) = broadcast::channel(100);
|
let conn_update = ConnectUpdate::new();
|
||||||
let joined_players = JoinedPlayers::new(connect_send);
|
let joined_players = JoinedPlayers::new(conn_update.clone());
|
||||||
let lobby_comms = LobbyComms::new(
|
let lobby_comms = LobbyComms::new(
|
||||||
Comms::new(
|
Comms::new(
|
||||||
HostComms::new(server_send, server_recv),
|
HostComms::new(server_send, server_recv),
|
||||||
PlayerIdComms::new(
|
PlayerIdComms::new(recv),
|
||||||
//joined_players.clone(),
|
|
||||||
recv,
|
|
||||||
// connect_recv.resubscribe()
|
|
||||||
),
|
),
|
||||||
),
|
conn_update,
|
||||||
connect_recv,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let jp_clone = joined_players.clone();
|
let jp_clone = joined_players.clone();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use werewolves_proto::{
|
use werewolves_proto::{
|
||||||
message::{ClientMessage, Identification, host::HostMessage},
|
message::{ClientMessage, Identification, host::HostMessage},
|
||||||
|
|
@ -79,8 +80,7 @@ pub async fn run_game(joined_players: JoinedPlayers, comms: LobbyComms, mut save
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
Host(HostMessage),
|
Host(HostMessage),
|
||||||
Client(IdentifiedClientMessage),
|
Client(IdentifiedClientMessage),
|
||||||
Connect(PlayerId),
|
ConnectedList(Arc<[PlayerId]>),
|
||||||
Disconnect(PlayerId),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RunningState {
|
pub enum RunningState {
|
||||||
|
|
|
||||||
|
|
@ -105,12 +105,24 @@ nav.debug-nav {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.player-list {
|
||||||
|
padding-bottom: 80px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.player {
|
.player {
|
||||||
|
flex-grow: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
max-width: 10vw;
|
max-width: 10vw;
|
||||||
max-height: 4rem;
|
height: 4rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -120,12 +132,34 @@ nav.debug-nav {
|
||||||
filter: hue-rotate(90deg);
|
filter: hue-rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.connected {}
|
block-size: max-content;
|
||||||
|
|
||||||
&.disconnected {
|
&>button {
|
||||||
// background-color: $disconnected_color;
|
width: 100%;
|
||||||
// border: 3px solid darken($disconnected_color, 20%);
|
height: 100%;
|
||||||
|
border: 1px solid $disconnected_color;
|
||||||
|
background-color: color.change($disconnected_color, $alpha: 0.15);
|
||||||
|
color: $disconnected_color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(150%);
|
||||||
|
background-color: color.change($disconnected_color, $alpha: 0.15);
|
||||||
|
color: $disconnected_color;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.connected {
|
||||||
|
&>button {
|
||||||
|
background-color: color.change($connected_color, $alpha: 0.15);
|
||||||
|
border: 1px solid $connected_color;
|
||||||
|
color: $connected_color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(150%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
&.dead {
|
&.dead {
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
|
|
@ -228,7 +262,7 @@ button {
|
||||||
content: attr(reason);
|
content: attr(reason);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
// top: 90%;
|
top: 90%;
|
||||||
// left: 0;
|
// left: 0;
|
||||||
font: 'Cute Font';
|
font: 'Cute Font';
|
||||||
// color: #000;
|
// color: #000;
|
||||||
|
|
@ -464,18 +498,6 @@ bool_role {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
player {
|
|
||||||
background-color: rgba(255, 107, 255, 0.7);
|
|
||||||
width: fit-content;
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-right: 10px;
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
margin: 10px;
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
client {
|
client {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
||||||
|
|
@ -738,16 +760,6 @@ error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-list {
|
|
||||||
padding-bottom: 80px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 10px;
|
|
||||||
// align-items: center;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
|
|
||||||
.binary {
|
.binary {
|
||||||
.button-container {
|
.button-container {
|
||||||
background-color: $village_color;
|
background-color: $village_color;
|
||||||
|
|
@ -911,3 +923,11 @@ input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.big-screen {
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -580,10 +580,9 @@ impl Component for Host {
|
||||||
HostEvent::SetBigScreenState(state) => {
|
HostEvent::SetBigScreenState(state) => {
|
||||||
self.big_screen = state;
|
self.big_screen = state;
|
||||||
if self.big_screen
|
if self.big_screen
|
||||||
&& let Some(root) = gloo::utils::document().document_element()
|
&& let Ok(Some(root)) = gloo::utils::document().query_selector(".content")
|
||||||
&& let Err(err) = root.set_attribute("style", "font-size: 3rem;")
|
|
||||||
{
|
{
|
||||||
log::error!("setting zoom: {err:?}");
|
root.set_class_name("content big-screen")
|
||||||
}
|
}
|
||||||
|
|
||||||
if state {
|
if state {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use core::num::NonZeroU8;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use werewolves_proto::{message::PlayerState, player::PlayerId};
|
use werewolves_proto::{message::PlayerState, player::PlayerId};
|
||||||
|
|
@ -21,7 +20,7 @@ pub fn Lobby(LobbyProps { players, on_action }: &LobbyProps) -> Html {
|
||||||
<div class="player-list">
|
<div class="player-list">
|
||||||
{
|
{
|
||||||
players
|
players
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|p| html! {<LobbyPlayer on_action={on_action} player={p.clone()} />})
|
.map(|p| html! {<LobbyPlayer on_action={on_action} player={p.clone()} />})
|
||||||
.collect::<Html>()
|
.collect::<Html>()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,22 +21,24 @@ pub enum LobbyPlayerAction {
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
pub fn LobbyPlayer(LobbyPlayerProps { player, on_action }: &LobbyPlayerProps) -> Html {
|
pub fn LobbyPlayer(LobbyPlayerProps { player, on_action }: &LobbyPlayerProps) -> Html {
|
||||||
let class = if player.connected {
|
let open = use_state(|| false);
|
||||||
"connected"
|
let class = player.connected.then_some("connected");
|
||||||
} else {
|
|
||||||
"disconnected"
|
|
||||||
};
|
|
||||||
let pid = player.identification.player_id.clone();
|
let pid = player.identification.player_id.clone();
|
||||||
|
let action_open = open.clone();
|
||||||
let action = |action: LobbyPlayerAction| {
|
let action = |action: LobbyPlayerAction| {
|
||||||
let pid = pid.clone();
|
let pid = pid.clone();
|
||||||
on_action
|
on_action
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|on_action| Callback::from(move |_| on_action.emit((pid.clone(), action))))
|
.map(|on_action| {
|
||||||
|
Callback::from(move |_| {
|
||||||
|
on_action.emit((pid.clone(), action));
|
||||||
|
action_open.set(false);
|
||||||
|
})
|
||||||
|
})
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
};
|
};
|
||||||
let number = use_state(String::new);
|
let number = use_state(String::new);
|
||||||
let open = use_state(|| false);
|
|
||||||
let number_open = use_state(|| false);
|
let number_open = use_state(|| false);
|
||||||
let submenu_open = open.clone();
|
let submenu_open = open.clone();
|
||||||
let submenu = on_action.clone().map(|on_action| {
|
let submenu = on_action.clone().map(|on_action| {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
use yew::prelude::*;
|
|
||||||
|
|
||||||
// #[derive(Debug, PartialEq, Properties)]
|
|
||||||
// pub struct NotificationProps {
|
|
||||||
// pub text: String,
|
|
||||||
// pub callback: Callback<()>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[function_component]
|
|
||||||
// pub fn Notification(props: &NotificationProps) -> Html {
|
|
||||||
// let cb = props.callback.clone();
|
|
||||||
// let on_click = Callback::from(move |_| cb.clone().emit(()));
|
|
||||||
// html! {
|
|
||||||
// <stack>
|
|
||||||
// <h2>{props.text.clone()}</h2>
|
|
||||||
// <button class="confirm" onclick={on_click}>{"Ok"}</button>
|
|
||||||
// </stack>
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
Loading…
Reference in New Issue