diff --git a/style/main.scss b/style/main.scss index 3872b25..5b1fb85 100644 --- a/style/main.scss +++ b/style/main.scss @@ -732,3 +732,16 @@ dialog .tab-content { } } + +.dialog-modal:has(.cancel-game-button) { + display: flex; + flex-direction: row; + justify-content: flex-end; + margin-top: 1ch; +} + +.scary { + color: red; + border: 1px solid red; + background-color: black; +} diff --git a/werewolves-proto/src/error.rs b/werewolves-proto/src/error.rs index 8be8bd9..6a48fab 100644 --- a/werewolves-proto/src/error.rs +++ b/werewolves-proto/src/error.rs @@ -149,6 +149,10 @@ pub enum ServerError { InvalidRequest(String), #[error("you're already in an active game: {0}")] AlreadyInActiveGame(GameId), + #[error("not your game")] + NotYourGame, + #[error("this game is already over")] + GameAlreadyOver, #[error("{0}")] GameError(#[from] GameError), } @@ -236,11 +240,11 @@ impl axum::response::IntoResponse for ServerError { fn into_response(self) -> axum::response::Response { use axum::{Json, http::StatusCode}; - - ( match self { - ServerError::AlreadyInActiveGame(_) + ServerError::NotYourGame + | ServerError::GameAlreadyOver + | ServerError::AlreadyInActiveGame(_) | ServerError::GameError(_) | ServerError::InvalidCredentials | ServerError::InvalidRequest(_) diff --git a/werewolves-proto/src/message/host.rs b/werewolves-proto/src/message/host.rs index 5b0259d..b26d063 100644 --- a/werewolves-proto/src/message/host.rs +++ b/werewolves-proto/src/message/host.rs @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize}; use crate::{ character::CharacterId, - error::GameError, + error::{GameError, ServerError}, game::{GameOver, GameSettings, story::GameStory}, message::{ CharacterIdentity, @@ -39,6 +39,7 @@ pub enum HostMessage { ForceRoleAckFor(CharacterId), PostGame(PostGameMessage), Echo(ServerToHostMessage), + CancelGame, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -107,7 +108,7 @@ pub enum ServerToHostMessage { settings: GameSettings, qr_mode: bool, }, - Error(GameError), + Error(ServerError), GameOver(GameOver), WaitingForRoleRevealAcks { ackd: Box<[CharacterIdentity]>, diff --git a/werewolves/src/app.rs b/werewolves/src/app.rs index a2d7e3d..aa65cf1 100644 --- a/werewolves/src/app.rs +++ b/werewolves/src/app.rs @@ -56,18 +56,22 @@ pub fn shell(options: LeptosOptions) -> impl IntoView { } #[derive(Debug, Clone, Serialize, PartialEq, Eq, Deserialize)] -pub struct TutorialSettings { - pub enabled: bool, +pub struct Preferences { + pub tutorials_enabled: bool, + pub show_cancel_game: bool, } -impl Default for TutorialSettings { +impl Default for Preferences { fn default() -> Self { - Self { enabled: true } + Self { + tutorials_enabled: true, + show_cancel_game: true, + } } } -impl Stored for TutorialSettings { - const STORAGE_KEY: &str = "tutorial-settings"; +impl Stored for Preferences { + const STORAGE_KEY: &str = "preferences"; } #[component] @@ -81,9 +85,9 @@ pub fn App() -> impl IntoView { Effect::new(move || auth_store.init_or_update()); Effect::new(move || session_store.init_or_update()); - let (tut_read, tut_write, _) = - use_local_storage::(TutorialSettings::STORAGE_KEY); - provide_context((tut_read, tut_write)); + let (pref_read, pref_write, _) = + use_local_storage::(Preferences::STORAGE_KEY); + provide_context((pref_read, pref_write)); let is_logged_in = move || { auth_store diff --git a/werewolves/src/app/components/sample.rs b/werewolves/src/app/components/sample.rs index 60c214f..fe7d8ec 100644 --- a/werewolves/src/app/components/sample.rs +++ b/werewolves/src/app/components/sample.rs @@ -6,7 +6,7 @@ use werewolves_proto::{ player::PlayerId, }; -use crate::app::TutorialSettings; +use crate::app::Preferences; pub trait Sample { fn sample() -> Self; @@ -51,11 +51,10 @@ impl Sample for Identification { #[component] pub fn TutorialBox(children: Children) -> impl IntoView { let sample_hidden = RwSignal::new(false); - let (tut_read, _) = - expect_context::<(Signal, WriteSignal)>(); + let (tut_read, _) = expect_context::<(Signal, WriteSignal)>(); view! { -