From 077e39fa8a52e15aa559691fea265cfeee0871a8 Mon Sep 17 00:00:00 2001 From: MrMaho Date: Wed, 28 Oct 2026 17:48:47 +0100 Subject: [PATCH] Startoption -dev: lokale Test-Website (localhost:5080) Eigene Anmeldung (settings.dev.json), bleibt bei Selbst-Installation und Update erhalten, DEV-Schild in der Oberflaeche. Co-Authored-By: Claude Opus 5.5 --- BSO.Launcher.csproj | 2 +- MainForm.cs | 6 ++++-- README.md | 15 +++++++++++++-- Services/Api.cs | 11 +++++++++-- Services/Installer.cs | 5 ++++- Services/SelfUpdate.cs | 1 + Services/Settings.cs | 3 ++- ui/app.css | 2 ++ ui/app.js | 8 ++++++++ ui/index.html | 2 ++ 10 files changed, 46 insertions(+), 9 deletions(-) diff --git a/BSO.Launcher.csproj b/BSO.Launcher.csproj index 3200ccd..b6639a2 100644 --- a/BSO.Launcher.csproj +++ b/BSO.Launcher.csproj @@ -8,7 +8,7 @@ enable BSO.Launcher BSO-Launcher - 0.1.0 + 0.1.1 MBM.wtf BSO Launcher BSO Launcher - Bus Simulator Online diff --git a/MainForm.cs b/MainForm.cs index 3535c79..27124e6 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -32,7 +32,8 @@ public sealed class MainForm : Form ClientSize = new Size(1120, 700); MinimumSize = new Size(900, 600); StartPosition = FormStartPosition.CenterScreen; - LauncherLog.Info("BSO Launcher " + SelfUpdate.CurrentVersion + " gestartet"); + LauncherLog.Info("BSO Launcher " + SelfUpdate.CurrentVersion + " gestartet" + (Api.Dev ? " (-dev)" : "") + ", Website " + Api.Base); + if (Api.Base != Api.BaseUrl) Text += " (DEV)"; try { Icon = Icon.ExtractAssociatedIcon(Environment.ProcessPath ?? Application.ExecutablePath); } catch { } Controls.Add(web); Load += async (_, _) => await InitWeb(); @@ -244,7 +245,8 @@ public sealed class MainForm : Form version = SelfUpdate.CurrentVersion, username = settings.Username, loggedIn = settings.Token != null, - master = Api.Base + master = Api.Base, + dev = Api.Dev || Api.Base != Api.BaseUrl }; // --- Konto diff --git a/README.md b/README.md index 784ba04..06bcd79 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,19 @@ dotnet publish -c Release -o publish # eine .exe, ohne vorinstalliertes .\release.ps1 -Product launcher -Version 0.1.0 -File publish\BSO-Launcher.exe -Changelog "..." ``` -Zum Testen gegen eine lokale Website: `$env:BSO_LAUNCHER_API = "http://localhost:5080"`, dann -`publish\BSO-Launcher.exe --portable`. +## Gegen die lokale Test-Website (`-dev`) + +```powershell +BSO-Launcher.exe -dev # nimmt http://localhost:5080 statt https://bso.mbm.wtf +``` + +- `-dev` bleibt beim Selbst-Installieren und beim Selbst-Update erhalten; die installierte Kopie startet man genauso: + `"%LocalAppData%\Programs\BSO Launcher\BSO-Launcher.exe" -dev`. +- Eigene Anmeldung (`settings.dev.json`) – Test- und echtes Konto kommen sich nicht in die Quere. +- Gelbes **DEV**-Schild in der Titelleiste, im Fenstertitel und unter dem Anmelden-Formular steht die Adresse. +- Beliebiger anderer Server: Umgebungsvariable `BSO_LAUNCHER_API` (geht vor `-dev`). + +Lokale Website starten: im BSO-Website-Repo `dotnet run --urls http://localhost:5080`. ## Release-Schlüssel diff --git a/Services/Api.cs b/Services/Api.cs index 7989a84..748b934 100644 --- a/Services/Api.cs +++ b/Services/Api.cs @@ -8,8 +8,15 @@ namespace BSO.Launcher; public static class Api { public const string BaseUrl = "https://bso.mbm.wtf"; - /// Zum Testen umstellbar: BSO_LAUNCHER_API=http://localhost:5080 - public static string Base => (Environment.GetEnvironmentVariable("BSO_LAUNCHER_API") ?? BaseUrl).TrimEnd('/'); + /// Lokale Test-Website (BSO-Website mit "dotnet run --urls http://localhost:5080"). + public const string DevUrl = "http://localhost:5080"; + public const string DevArg = "-dev"; + + /// Mit -dev (oder --dev) gestartet: gegen die lokale Test-Website statt bso.mbm.wtf. + public static readonly bool Dev = Environment.GetCommandLineArgs().Skip(1).Any(a => a is "-dev" or "--dev"); + + /// Adresse der Website. BSO_LAUNCHER_API geht vor (beliebiger Test-Server), dann -dev, sonst bso.mbm.wtf. + public static string Base => (Environment.GetEnvironmentVariable("BSO_LAUNCHER_API") ?? (Dev ? DevUrl : BaseUrl)).TrimEnd('/'); public static readonly HttpClient Http = CreateHttp(); diff --git a/Services/Installer.cs b/Services/Installer.cs index 52fc0be..ca5f3fb 100644 --- a/Services/Installer.cs +++ b/Services/Installer.cs @@ -111,9 +111,12 @@ public static class Installer catch { /* ohne Verknuepfung geht es auch */ } } + /// Installierte Kopie starten - mit -dev, wenn diese hier mit -dev lief. public static void StartInstalled() { - Process.Start(new ProcessStartInfo(InstalledExe) { UseShellExecute = true, WorkingDirectory = InstallDir }); + var start = new ProcessStartInfo(InstalledExe) { UseShellExecute = true, WorkingDirectory = InstallDir }; + if (Api.Dev) start.ArgumentList.Add(Api.DevArg); + Process.Start(start); } /// Ordner/Dateien loeschen, sobald dieser Prozess beendet ist (seine .exe ist bis dahin gesperrt). diff --git a/Services/SelfUpdate.cs b/Services/SelfUpdate.cs index af99bca..790ec6d 100644 --- a/Services/SelfUpdate.cs +++ b/Services/SelfUpdate.cs @@ -45,6 +45,7 @@ public static class SelfUpdate var start = new ProcessStartInfo(exe) { UseShellExecute = true }; start.ArgumentList.Add(AfterUpdateArg); if (!Installer.RunningInstalled) start.ArgumentList.Add("--portable"); + if (Api.Dev) start.ArgumentList.Add(Api.DevArg); Process.Start(start); return release.version; } diff --git a/Services/Settings.cs b/Services/Settings.cs index 13902ee..2cc2ce4 100644 --- a/Services/Settings.cs +++ b/Services/Settings.cs @@ -11,7 +11,8 @@ namespace BSO.Launcher; public sealed class Settings { public static string Folder => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "BSO Launcher"); - static string FilePath => Path.Combine(Folder, "settings.json"); + /// Mit -dev eigene Datei: die Anmeldung gilt nur fuer die Website, bei der sie gemacht wurde. + static string FilePath => Path.Combine(Folder, Api.Dev ? "settings.dev.json" : "settings.json"); static readonly JsonSerializerOptions Options = new() { WriteIndented = true }; public string? Username { get; set; } diff --git a/ui/app.css b/ui/app.css index c105113..7506d94 100644 --- a/ui/app.css +++ b/ui/app.css @@ -42,6 +42,8 @@ code, .mono { font-family: "Cascadia Mono", Consolas, monospace; font-size: 12.5 background: var(--sidebar); border-bottom: 1px solid #151922; } .titlebar-drag { flex: 1; display: flex; align-items: center; gap: 8px; padding: 0 12px; color: var(--muted); font-size: 12px; font-weight: 600; } .titlebar-drag img { width: 18px; height: 18px; } +.dev-badge { font-size: 10.5px; font-weight: 800; letter-spacing: .06em; padding: 1px 7px; border-radius: 6px; + color: #1a1400; background: var(--pending); } .window-buttons { display: flex; } .window-buttons button { width: 46px; border: 0; background: transparent; color: #c4ccd8; font: 10px var(--icons); cursor: default; } .window-buttons button:hover { background: #1c212c; } diff --git a/ui/app.js b/ui/app.js index a6d0661..8428a11 100644 --- a/ui/app.js +++ b/ui/app.js @@ -287,6 +287,14 @@ async function renderSettings(root) { (async () => { const init = await call("init"); $("meVersion").textContent = "Launcher " + init.version; + if (init.dev) { + // -dev: gegen die lokale Test-Website - gut sichtbar, damit niemand das verwechselt + const host = init.master.replace(/^https?:\/\//, ""); + $("devBadge").textContent = "DEV · " + host; + $("devBadge").classList.remove("hidden"); + $("meVersion").textContent += " · DEV"; + } + $("authServer").textContent = "Server: " + init.master.replace(/^https?:\/\//, ""); if (!init.loggedIn) { showAuth(); return; } const me = await call("me"); if (me.loggedIn) showApp(me.username); diff --git a/ui/index.html b/ui/index.html index 9ceead9..cb961d4 100644 --- a/ui/index.html +++ b/ui/index.html @@ -13,6 +13,7 @@
BSO Launcher +
@@ -50,6 +51,7 @@

Dein Benutzername ist auch dein Name im Spiel. Passwoerter liegen nur verschluesselt auf dem BSO-Server.

+