2026-04-23 19:04:39 +08:00
|
|
|
namespace LanMountainDesktop.Launcher.Services;
|
|
|
|
|
|
|
|
|
|
internal sealed record LauncherDebugSettings(bool DevModeEnabled, string? CustomHostPath);
|
|
|
|
|
|
|
|
|
|
internal static class LauncherDebugSettingsStore
|
|
|
|
|
{
|
|
|
|
|
private const string DevModeFileName = "dev-mode.flag";
|
|
|
|
|
private const string CustomHostPathFileName = "custom-host-path.txt";
|
|
|
|
|
private const string LegacyDevModeFileName = "devmode.config";
|
|
|
|
|
private const string LegacyCustomHostPathFileName = "custom-host-path.config";
|
|
|
|
|
|
|
|
|
|
internal static string? ConfigBaseDirectoryOverride { get; set; }
|
|
|
|
|
|
|
|
|
|
public static string ConfigBaseDirectory => ConfigBaseDirectoryOverride ?? ResolveConfigBaseDirectory();
|
|
|
|
|
|
|
|
|
|
public static LauncherDebugSettings Load()
|
|
|
|
|
{
|
|
|
|
|
return new LauncherDebugSettings(
|
|
|
|
|
LoadDevModeState(),
|
|
|
|
|
LoadCustomHostPath());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool IsDevModeEnabled() => Load().DevModeEnabled;
|
|
|
|
|
|
|
|
|
|
public static string? GetSavedCustomHostPath() => Load().CustomHostPath;
|
|
|
|
|
|
|
|
|
|
public static void Save(LauncherDebugSettings settings)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(ConfigBaseDirectory);
|
|
|
|
|
File.WriteAllText(GetPath(DevModeFileName), settings.DevModeEnabled.ToString());
|
|
|
|
|
File.WriteAllText(GetPath(CustomHostPathFileName), settings.CustomHostPath ?? string.Empty);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warn($"Failed to save launcher debug settings: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void SaveDevModeState(bool enabled)
|
|
|
|
|
{
|
|
|
|
|
var current = Load();
|
|
|
|
|
Save(current with { DevModeEnabled = enabled });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void SaveCustomHostPath(string? customHostPath)
|
|
|
|
|
{
|
|
|
|
|
var current = Load();
|
|
|
|
|
Save(current with { CustomHostPath = customHostPath });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool LoadDevModeState()
|
|
|
|
|
{
|
|
|
|
|
var newValue = TryReadText(GetPath(DevModeFileName));
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(newValue))
|
|
|
|
|
{
|
|
|
|
|
return TryParseDevMode(newValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var legacyValue = TryReadText(GetPath(LegacyDevModeFileName));
|
|
|
|
|
return !string.IsNullOrWhiteSpace(legacyValue) && TryParseDevMode(legacyValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string? LoadCustomHostPath()
|
|
|
|
|
{
|
|
|
|
|
var newValue = TryReadText(GetPath(CustomHostPathFileName));
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(newValue))
|
|
|
|
|
{
|
|
|
|
|
return newValue.Trim();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var legacyValue = TryReadText(GetPath(LegacyCustomHostPathFileName));
|
|
|
|
|
return string.IsNullOrWhiteSpace(legacyValue) ? null : legacyValue.Trim();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool TryParseDevMode(string value)
|
|
|
|
|
{
|
|
|
|
|
var normalized = value.Trim();
|
|
|
|
|
return normalized == "1" ||
|
|
|
|
|
normalized.Equals("true", StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
|
normalized.Equals("yes", StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
|
normalized.Equals("on", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string? TryReadText(string path)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return File.Exists(path) ? File.ReadAllText(path) : null;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Warn($"Failed to read launcher debug setting '{path}': {ex.Message}");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GetPath(string fileName) => Path.Combine(ConfigBaseDirectory, fileName);
|
|
|
|
|
|
|
|
|
|
private static string ResolveConfigBaseDirectory()
|
|
|
|
|
{
|
Add configurable data location (portable/system)
Introduce support for choosing and resolving the application's data root (system user dir vs. portable app folder). Adds DataLocationConfig model, DataLocationResolver (load/save/resolve/migrate), a UI prompt (DataLocationPromptWindow) and an OOBE step (DataLocationOobeStep) to let users pick and optionally migrate existing data. Wire the chosen data root into the launcher flow and host launch plan (forwarded via --data-root and LMD_DATA_ROOT), and add AppDataPathProvider to let runtime services read the effective data root (initialized in Program.Main). Update various services (logging, settings, DB, plugin/market, startup registry, etc.) to use the new provider/resolver and register the config type in the JSON context. This enables portable installs, safe migration, and runtime overrides via CLI or environment variable.
2026-04-24 12:30:05 +08:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var appRoot = Commands.ResolveAppRoot(CommandContext.FromArgs([]));
|
|
|
|
|
var resolver = new DataLocationResolver(appRoot);
|
Refactor data location paths and add background service
Refactor DataLocationResolver to centralize data path resolution (ResolveLauncherDataPath, ResolveDesktopDataPath, ResolveConfigPath, ResolveLauncherLogsPath, ResolveLauncherStatePath) and replace usages of the previous ".launcher" layout with a "Launcher" folder. Update API: LoadConfig/SaveConfig reorganized and ApplyLocationChoice now accepts an optional custom path and migration flag; migration logic updated accordingly. Update dependent services and views (Logger, DeploymentLocator, UpdateEngineService, OobeStateService, StartupAttemptRegistry, LauncherDebugSettingsStore, OobeWindow) to use the new resolver APIs and paths. Add LauncherBackgroundService to load/validate/cache a custom splash background image and wire it into SplashWindow (AXAML/Axaml.cs) with UI placeholders and overlay. Misc: minor cleanup of Oobe/Splash XAML and related code adjustments and logging improvements.
2026-04-25 18:14:29 +08:00
|
|
|
return resolver.ResolveLauncherDataPath();
|
Add configurable data location (portable/system)
Introduce support for choosing and resolving the application's data root (system user dir vs. portable app folder). Adds DataLocationConfig model, DataLocationResolver (load/save/resolve/migrate), a UI prompt (DataLocationPromptWindow) and an OOBE step (DataLocationOobeStep) to let users pick and optionally migrate existing data. Wire the chosen data root into the launcher flow and host launch plan (forwarded via --data-root and LMD_DATA_ROOT), and add AppDataPathProvider to let runtime services read the effective data root (initialized in Program.Main). Update various services (logging, settings, DB, plugin/market, startup registry, etc.) to use the new provider/resolver and register the config type in the JSON context. This enables portable installs, safe migration, and runtime overrides via CLI or environment variable.
2026-04-24 12:30:05 +08:00
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-23 19:04:39 +08:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(appData))
|
|
|
|
|
{
|
Refactor data location paths and add background service
Refactor DataLocationResolver to centralize data path resolution (ResolveLauncherDataPath, ResolveDesktopDataPath, ResolveConfigPath, ResolveLauncherLogsPath, ResolveLauncherStatePath) and replace usages of the previous ".launcher" layout with a "Launcher" folder. Update API: LoadConfig/SaveConfig reorganized and ApplyLocationChoice now accepts an optional custom path and migration flag; migration logic updated accordingly. Update dependent services and views (Logger, DeploymentLocator, UpdateEngineService, OobeStateService, StartupAttemptRegistry, LauncherDebugSettingsStore, OobeWindow) to use the new resolver APIs and paths. Add LauncherBackgroundService to load/validate/cache a custom splash background image and wire it into SplashWindow (AXAML/Axaml.cs) with UI placeholders and overlay. Misc: minor cleanup of Oobe/Splash XAML and related code adjustments and logging improvements.
2026-04-25 18:14:29 +08:00
|
|
|
return Path.Combine(appData, "LanMountainDesktop", "Launcher");
|
2026-04-23 19:04:39 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
Refactor data location paths and add background service
Refactor DataLocationResolver to centralize data path resolution (ResolveLauncherDataPath, ResolveDesktopDataPath, ResolveConfigPath, ResolveLauncherLogsPath, ResolveLauncherStatePath) and replace usages of the previous ".launcher" layout with a "Launcher" folder. Update API: LoadConfig/SaveConfig reorganized and ApplyLocationChoice now accepts an optional custom path and migration flag; migration logic updated accordingly. Update dependent services and views (Logger, DeploymentLocator, UpdateEngineService, OobeStateService, StartupAttemptRegistry, LauncherDebugSettingsStore, OobeWindow) to use the new resolver APIs and paths. Add LauncherBackgroundService to load/validate/cache a custom splash background image and wire it into SplashWindow (AXAML/Axaml.cs) with UI placeholders and overlay. Misc: minor cleanup of Oobe/Splash XAML and related code adjustments and logging improvements.
2026-04-25 18:14:29 +08:00
|
|
|
return Path.Combine(AppContext.BaseDirectory, "Launcher");
|
2026-04-23 19:04:39 +08:00
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
Refactor data location paths and add background service
Refactor DataLocationResolver to centralize data path resolution (ResolveLauncherDataPath, ResolveDesktopDataPath, ResolveConfigPath, ResolveLauncherLogsPath, ResolveLauncherStatePath) and replace usages of the previous ".launcher" layout with a "Launcher" folder. Update API: LoadConfig/SaveConfig reorganized and ApplyLocationChoice now accepts an optional custom path and migration flag; migration logic updated accordingly. Update dependent services and views (Logger, DeploymentLocator, UpdateEngineService, OobeStateService, StartupAttemptRegistry, LauncherDebugSettingsStore, OobeWindow) to use the new resolver APIs and paths. Add LauncherBackgroundService to load/validate/cache a custom splash background image and wire it into SplashWindow (AXAML/Axaml.cs) with UI placeholders and overlay. Misc: minor cleanup of Oobe/Splash XAML and related code adjustments and logging improvements.
2026-04-25 18:14:29 +08:00
|
|
|
return Path.Combine(Directory.GetCurrentDirectory(), "Launcher");
|
2026-04-23 19:04:39 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|