diff --git a/Cargo.lock b/Cargo.lock index de6765c..434407c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -189,7 +189,7 @@ dependencies = [ [[package]] name = "backbone-lib" -version = "0.2.11" +version = "0.1.0" dependencies = [ "bytes", "ewebsock", @@ -2649,7 +2649,7 @@ dependencies = [ [[package]] name = "protocol" -version = "0.2.11" +version = "0.1.0" dependencies = [ "serde", ] @@ -2883,7 +2883,7 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "relay-server" -version = "0.2.11" +version = "0.1.0" dependencies = [ "argon2", "axum", @@ -3893,7 +3893,7 @@ dependencies = [ [[package]] name = "trictrac-store" -version = "0.2.11" +version = "0.1.0" dependencies = [ "anyhow", "base64 0.21.7", @@ -3906,7 +3906,7 @@ dependencies = [ [[package]] name = "trictrac-web" -version = "0.2.11" +version = "0.1.0" dependencies = [ "backbone-lib", "futures", diff --git a/Cargo.toml b/Cargo.toml index 9db1a73..e78d862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,3 @@ -[workspace.package] -version = "0.2.11" - [workspace] resolver = "2" diff --git a/clients/backbone-lib/Cargo.toml b/clients/backbone-lib/Cargo.toml index d6ae5c9..1e57d93 100644 --- a/clients/backbone-lib/Cargo.toml +++ b/clients/backbone-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "backbone-lib" -version.workspace = true +version = "0.1.0" edition = "2024" [dependencies] diff --git a/clients/web/Cargo.toml b/clients/web/Cargo.toml index 1edb9eb..4849bec 100644 --- a/clients/web/Cargo.toml +++ b/clients/web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trictrac-web" -version.workspace = true +version = "0.1.0" edition = "2021" [package.metadata.leptos-i18n] diff --git a/clients/web/assets/style.css b/clients/web/assets/style.css index 09b21e9..428d693 100644 --- a/clients/web/assets/style.css +++ b/clients/web/assets/style.css @@ -161,7 +161,7 @@ body { /* ── Stats grid ──────────────────────────────────────────────────── */ .stats-grid { display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem; } @@ -2076,19 +2076,3 @@ a:hover { text-decoration: underline; } max-width: 200px; margin: 0 auto; } - -/* Push the version wrapper to the bottom of the sidebar flex column */ -.game-sidebar > div:has(.site-nav-version) { - margin-top: auto; - padding: 0.75rem 1rem; - border-top: 1px solid rgba(200,164,72,0.12); -} - -.site-nav-version { - display: block; - text-align: center; - font-family: var(--font-ui); - font-size: 0.7rem; - letter-spacing: 0.06em; - color: rgba(200,164,72,0.4); -} diff --git a/clients/web/locales/fr.json b/clients/web/locales/fr.json index 569d66b..b3a05f0 100644 --- a/clients/web/locales/fr.json +++ b/clients/web/locales/fr.json @@ -99,7 +99,7 @@ "resend_verification": "Renvoyer l'email de vérification", "verification_email_resent": "Email de vérification envoyé.", "loading": "Chargement…", - "member_since": "Membre depuis le", + "member_since": "Membre depuis", "stat_games": "Parties", "stat_wins": "Victoires", "stat_losses": "Défaites", diff --git a/clients/web/src/api.rs b/clients/web/src/api.rs index d826165..9e0f57c 100644 --- a/clients/web/src/api.rs +++ b/clients/web/src/api.rs @@ -244,53 +244,10 @@ pub async fn post_reset_password(token: &str, new_password: &str) -> Result<(), // ── Utilities ───────────────────────────────────────────────────────────────── -/// Maps to the `Intl.DateTimeFormat` options object accepted by `Date.toLocaleString`. -/// `Default` passes no options (browser default: full date + time). -pub struct DateFormatOptions { - /// "full" | "long" | "medium" | "short" — omit to suppress date part - pub date_style: Option<&'static str>, - /// "full" | "long" | "medium" | "short" — omit to suppress time part - pub time_style: Option<&'static str>, -} - -impl Default for DateFormatOptions { - fn default() -> Self { - Self { date_style: None, time_style: None } - } -} - -impl DateFormatOptions { - pub fn date_only() -> Self { - Self { date_style: Some("short"), time_style: None } - } - - pub fn time_only() -> Self { - Self { date_style: None, time_style: Some("short") } - } - - pub fn date_time() -> Self { - Self { date_style: Some("short"), time_style: Some("short") } - } - - fn to_js_value(&self) -> wasm_bindgen::JsValue { - if self.date_style.is_none() && self.time_style.is_none() { - return wasm_bindgen::JsValue::UNDEFINED; - } - let obj = js_sys::Object::new(); - if let Some(v) = self.date_style { - let _ = js_sys::Reflect::set(&obj, &"dateStyle".into(), &v.into()); - } - if let Some(v) = self.time_style { - let _ = js_sys::Reflect::set(&obj, &"timeStyle".into(), &v.into()); - } - obj.into() - } -} - -pub fn format_ts(ts: i64, locale: &str, opts: &DateFormatOptions) -> String { +pub fn format_ts(ts: i64) -> String { let ms = (ts * 1000) as f64; let date = js_sys::Date::new(&wasm_bindgen::JsValue::from_f64(ms)); - date.to_locale_string(locale, &opts.to_js_value()) + date.to_locale_string("en-GB", &wasm_bindgen::JsValue::UNDEFINED) .as_string() .unwrap_or_default() } diff --git a/clients/web/src/app.rs b/clients/web/src/app.rs index 5c38d33..3819b61 100644 --- a/clients/web/src/app.rs +++ b/clients/web/src/app.rs @@ -32,7 +32,6 @@ use std::collections::VecDeque; const RELAY_URL: &str = "ws://localhost:8080/ws"; const GAME_ID: &str = "trictrac"; const STORAGE_KEY: &str = "trictrac_session"; -const VERSION: &str = env!("CARGO_PKG_VERSION"); /// The state the UI needs to render the game screen. #[derive(Clone, PartialEq)] @@ -622,9 +621,6 @@ fn SiteHamburger() -> impl IntoView { sidebar_open.set(false); }>{t!(i18n, replay_snapshot)} -
- "v" {VERSION} -
// ── Replay snapshot modal ───────────────────────────────────────────── diff --git a/clients/web/src/nav.rs b/clients/web/src/nav.rs new file mode 100644 index 0000000..10ecc36 --- /dev/null +++ b/clients/web/src/nav.rs @@ -0,0 +1,46 @@ +use leptos::prelude::*; +use leptos::task::spawn_local; +use leptos_router::components::A; + +use crate::api; +use crate::i18n::*; + +#[component] +pub fn SiteNav() -> impl IntoView { + let i18n = use_i18n(); + let auth_username = + use_context::>>().expect("auth_username context not found"); + + let logout = move |_| { + spawn_local(async move { + let _ = api::post_logout().await; + auth_username.set(None); + }); + }; + + view! { + + } +} diff --git a/clients/web/src/portal/game_detail.rs b/clients/web/src/portal/game_detail.rs index d0d17d4..adc3643 100644 --- a/clients/web/src/portal/game_detail.rs +++ b/clients/web/src/portal/game_detail.rs @@ -32,12 +32,8 @@ pub fn GameDetailPage() -> impl IntoView { #[component] fn GameDetailView(game: GameDetail) -> impl IntoView { let i18n = use_i18n(); - let locale_tag = match i18n.get_locale() { - Locale::en => "en-GB", - Locale::fr => "fr-FR", - }; - let started = api::format_ts(game.started_at, locale_tag, &api::DateFormatOptions::date_only()); - let ended = game.ended_at.map(|ts| api::format_ts(ts, locale_tag, &api::DateFormatOptions::date_only())) + let started = api::format_ts(game.started_at); + let ended = game.ended_at.map(api::format_ts) .unwrap_or_else(|| t_string!(i18n, game_ongoing).to_string()); view! { diff --git a/clients/web/src/portal/profile.rs b/clients/web/src/portal/profile.rs index c727bbd..9a94b3f 100644 --- a/clients/web/src/portal/profile.rs +++ b/clients/web/src/portal/profile.rs @@ -37,16 +37,7 @@ fn ProfileContent(profile: UserProfile, username: String) -> impl IntoView { async move { api::get_user_games(&u, p).await } }); - let locale_tag = match i18n.get_locale() { - Locale::en => "en-GB", - Locale::fr => "fr-FR", - }; - let date_format = api::DateFormatOptions { - date_style: Some("long"), - time_style: None, - }; - let joined = api::format_ts(profile.created_at, locale_tag, &date_format); - // let joined = api::format_ts(profile.created_at, locale_tag, &api::DateFormatOptions::date_only()); + let joined = api::format_ts(profile.created_at); view! {
@@ -66,6 +57,10 @@ fn ProfileContent(profile: UserProfile, username: String) -> impl IntoView {
{ profile.losses }
{t!(i18n, stat_losses)}
+
+
{ profile.draws }
+
{t!(i18n, stat_draws)}
+
@@ -89,10 +84,6 @@ fn ProfileContent(profile: UserProfile, username: String) -> impl IntoView { #[component] fn GamesTable(games: Vec, page: RwSignal) -> impl IntoView { let i18n = use_i18n(); - let locale_tag = match i18n.get_locale() { - Locale::en => "en-GB", - Locale::fr => "fr-FR", - }; let rows = games.clone(); let has_next = games.len() == 20; @@ -109,8 +100,8 @@ fn GamesTable(games: Vec, page: RwSignal) -> impl IntoView { {rows.into_iter().map(|g| { - let started = api::format_ts(g.started_at, locale_tag, &api::DateFormatOptions::date_only()); - let ended = g.ended_at.map(|ts| api::format_ts(ts, locale_tag, &api::DateFormatOptions::date_only())).unwrap_or_else(|| "—".into()); + let started = api::format_ts(g.started_at); + let ended = g.ended_at.map(api::format_ts).unwrap_or_else(|| "—".into()); let outcome_class = match g.outcome.as_deref() { Some("win") => "outcome-win", Some("loss") => "outcome-loss", diff --git a/flake.nix b/flake.nix index cde292d..54da2ed 100644 --- a/flake.nix +++ b/flake.nix @@ -103,7 +103,7 @@ trictrac = with final; rustPlatform.buildRustPackage { pname = "trictrac"; - version = "0.2.11"; # trictrac-version + version = "0.2.1"; src = ./.; nativeBuildInputs = [ pkg-config ]; diff --git a/justfile b/justfile index fe4e52e..fe80391 100644 --- a/justfile +++ b/justfile @@ -2,17 +2,6 @@ # ^ A shebang isn't required, but allows a justfile to be executed # like a script, with `./justfile test`, for example. -# Bump the project version and start a git-flow release. -# Usage: just bump 0.2.12 -# After running, finish with: git flow release finish -bump version: - sed -i '/^\[workspace\.package\]/,/^\[/{s/^version = ".*"/version = "{{version}}"/}' Cargo.toml - sed -i 's/version = "[0-9.]*"; # trictrac-version/version = "{{version}}"; # trictrac-version/' flake.nix - git flow release start {{version}} - git add Cargo.toml flake.nix - git commit -m "chore: bump version to {{version}}" - @echo "Done. Finish with: git flow release finish {{version}}" - doc: cargo doc --no-deps shell: diff --git a/module.nix b/module.nix index 53f77c6..68b2833 100644 --- a/module.nix +++ b/module.nix @@ -123,7 +123,6 @@ in proxy_read_timeout 3600s; ''; withSSL = cfg.protocol == "https"; - listenPort = if withSSL then 443 else 80; in { "${cfg.hostname}" = { @@ -131,19 +130,18 @@ in forceSSL = withSSL; # Explicit listen so this vhost isn't shadowed by a default_server # created by other virtual hosts with forceSSL = true. - listen = [ - { addr = "0.0.0.0"; port = listenPort; ssl = withSSL; } - { addr = "[::]"; port = listenPort; ssl = withSSL; } + listen = + if withSSL then [ + { addr = "0.0.0.0"; port = 443; ssl = true; } + { addr = "[::]"; port = 443; ssl = true; } + ] else [ + { addr = "0.0.0.0"; port = 80; ssl = false; } + { addr = "[::]"; port = 80; ssl = false; } ]; locations."/" = { extraConfig = proxyConfig; proxyPass = "http://trictrac-api/"; }; - - extraConfig = '' - error_log /var/log/nginx/trictrac_error.log; - access_log /var/log/nginx/trictrac_access.log; - ''; }; }; }; diff --git a/server/protocol/Cargo.toml b/server/protocol/Cargo.toml index 70f4e68..2630fc1 100644 --- a/server/protocol/Cargo.toml +++ b/server/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "protocol" -version.workspace = true +version = "0.1.0" edition = "2024" [dependencies] diff --git a/server/relay-server/Cargo.toml b/server/relay-server/Cargo.toml index 1c0112b..ccb97fa 100644 --- a/server/relay-server/Cargo.toml +++ b/server/relay-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "relay-server" -version.workspace = true +version = "0.1.0" edition = "2024" [dependencies] diff --git a/server/relay-server/src/main.rs b/server/relay-server/src/main.rs index 32baf70..0dfea0c 100644 --- a/server/relay-server/src/main.rs +++ b/server/relay-server/src/main.rs @@ -99,9 +99,9 @@ async fn main() { .route("/ws", get(websocket_handler)) .merge(http::router()) .with_state(app_state) - .fallback_service(ServeDir::new(".").not_found_service(ServeFile::new("index.html"))) .layer(auth_layer) - .layer(cors); + .layer(cors) + .fallback_service(ServeDir::new(".").not_found_service(ServeFile::new("index.html"))); let listener = tokio::net::TcpListener::bind("127.0.0.1:8080") .await diff --git a/store/Cargo.toml b/store/Cargo.toml index 92b1b84..d8a594c 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trictrac-store" -version.workspace = true +version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html