wip: Windows desktop app scaffold (WinUI 3/.NET 8) + NSIS installer + docs
Owner decision pending (STATE.md DC-100 tick): adopt/ship/park. Preserved from fragile git stash to named branch 2026-08-23. NOTE: requires a Windows build machine (WinUI XAML compiler + MSIX do not cross-build on Linux) — see WINDOWS_APP_BUILD.md in this tree. Secret-scanned clean 2026-08-23 (no keys/tokens/PEM in tree).
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace DashCaddy.Desktop;
|
||||
|
||||
public sealed partial class SettingsDialog : ContentDialog
|
||||
{
|
||||
public SettingsDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
var configPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"DashCaddy", "config.yaml");
|
||||
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
var lines = File.ReadAllLines(configPath);
|
||||
var dict = new Dictionary<string, string>();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.Contains(':'))
|
||||
{
|
||||
var parts = line.Split(':', 2);
|
||||
if (parts.Length == 2)
|
||||
dict[parts[0].Trim()] = parts[1].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.TryGetValue("domain", out var domain)) DomainBox.Text = domain;
|
||||
if (dict.TryGetValue("email", out var email)) EmailBox.Text = email;
|
||||
if (dict.TryGetValue("docker_data", out var dockerData)) DockerDataBox.Text = dockerData;
|
||||
if (dict.TryGetValue("dns_provider", out var dnsProvider))
|
||||
{
|
||||
foreach (ComboBoxItem item in DnsProviderCombo.Items)
|
||||
{
|
||||
if (item.Tag?.ToString() == dnsProvider)
|
||||
{
|
||||
DnsProviderCombo.SelectedItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DNS provider specific settings
|
||||
if (dict.TryGetValue("technitium_url", out var techUrl)) TechnitiumUrl.Text = techUrl;
|
||||
if (dict.TryGetValue("technitium_api_key", out var techKey)) TechnitiumApiKey.Text = techKey;
|
||||
if (dict.TryGetValue("technitium_zone", out var techZone)) TechnitiumZone.Text = techZone;
|
||||
if (dict.TryGetValue("coredns_api_url", out var coreUrl)) CoreDnsApiUrl.Text = coreUrl;
|
||||
if (dict.TryGetValue("coredns_zone", out var coreZone)) CoreDnsZone.Text = coreZone;
|
||||
if (dict.TryGetValue("cloudflare_api_token", out var cfToken)) CloudflareApiToken.Text = cfToken;
|
||||
if (dict.TryGetValue("cloudflare_zone_id", out var cfZone)) CloudflareZoneId.Text = cfZone;
|
||||
if (dict.TryGetValue("aws_access_key", out var awsKey)) AwsAccessKey.Text = awsKey;
|
||||
if (dict.TryGetValue("aws_secret_key", out var awsSecret)) AwsSecretKey.Text = awsSecret;
|
||||
if (dict.TryGetValue("aws_region", out var awsRegion)) AwsRegion.Text = awsRegion;
|
||||
if (dict.TryGetValue("route53_zone_id", out var r53Zone)) Route53ZoneId.Text = r53Zone;
|
||||
if (dict.TryGetValue("custom_dns_url", out var customUrl)) CustomDnsUrl.Text = customUrl;
|
||||
if (dict.TryGetValue("custom_dns_key", out var customKey)) CustomDnsKey.Text = customKey;
|
||||
|
||||
if (dict.TryGetValue("auto_start", out var autoStart) && bool.TryParse(autoStart, out var asBool))
|
||||
AutoStartCheck.IsChecked = asBool;
|
||||
if (dict.TryGetValue("auto_update", out var autoUpdate) && bool.TryParse(autoUpdate, out var auBool))
|
||||
AutoUpdateCheck.IsChecked = auBool;
|
||||
}
|
||||
}
|
||||
|
||||
private void DnsProvider_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (DnsProviderCombo.SelectedItem is ComboBoxItem item)
|
||||
{
|
||||
var provider = item.Tag?.ToString();
|
||||
|
||||
TechnitiumPanel.Visibility = provider == "Technitium" ? Visibility.Visible : Visibility.Collapsed;
|
||||
CoreDnsPanel.Visibility = provider == "CoreDNS" ? Visibility.Visible : Visibility.Collapsed;
|
||||
CloudflarePanel.Visibility = provider == "Cloudflare" ? Visibility.Visible : Visibility.Collapsed;
|
||||
Route53Panel.Visibility = provider == "Route53" ? Visibility.Visible : Visibility.Collapsed;
|
||||
CustomPanel.Visibility = provider == "Custom" ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
var configDir = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"DashCaddy");
|
||||
Directory.CreateDirectory(configDir);
|
||||
|
||||
var configPath = Path.Combine(configDir, "config.yaml");
|
||||
|
||||
var dnsProvider = (DnsProviderCombo.SelectedItem as ComboBoxItem)?.Tag?.ToString() ?? "Technitium";
|
||||
|
||||
var config = $@"domain: {DomainBox.Text}
|
||||
email: {EmailBox.Text}
|
||||
docker_data: {DockerDataBox.Text}
|
||||
dns_provider: {dnsProvider}
|
||||
technitium_url: {TechnitiumUrl.Text}
|
||||
technitium_api_key: {TechnitiumApiKey.Text}
|
||||
technitium_zone: {TechnitiumZone.Text}
|
||||
coredns_api_url: {CoreDnsApiUrl.Text}
|
||||
coredns_zone: {CoreDnsZone.Text}
|
||||
cloudflare_api_token: {CloudflareApiToken.Text}
|
||||
cloudflare_zone_id: {CloudflareZoneId.Text}
|
||||
aws_access_key: {AwsAccessKey.Text}
|
||||
aws_secret_key: {AwsSecretKey.Text}
|
||||
aws_region: {AwsRegion.Text}
|
||||
route53_zone_id: {Route53ZoneId.Text}
|
||||
custom_dns_url: {CustomDnsUrl.Text}
|
||||
custom_dns_key: {CustomDnsKey.Text}
|
||||
auto_start: {AutoStartCheck.IsChecked}
|
||||
auto_update: {AutoUpdateCheck.IsChecked}
|
||||
";
|
||||
File.WriteAllText(configPath, config);
|
||||
}
|
||||
|
||||
private void OpenConfigFolder_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var configDir = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"DashCaddy");
|
||||
Directory.CreateDirectory(configDir);
|
||||
Process.Start(new ProcessStartInfo("explorer.exe", configDir) { UseShellExecute = true });
|
||||
}
|
||||
|
||||
private void ViewLogs_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var logDir = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"DashCaddy", "logs");
|
||||
Directory.CreateDirectory(logDir);
|
||||
Process.Start(new ProcessStartInfo("explorer.exe", logDir) { UseShellExecute = true });
|
||||
}
|
||||
|
||||
private async void ResetData_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var confirm = new ContentDialog
|
||||
{
|
||||
Title = "Reset All Data",
|
||||
Content = "This will delete ALL DashCaddy data including services, configs, and Docker volumes. This cannot be undone.",
|
||||
PrimaryButtonText = "Delete Everything",
|
||||
CloseButtonText = "Cancel",
|
||||
DefaultButton = ContentDialogButton.Close,
|
||||
XamlRoot = this.XamlRoot
|
||||
};
|
||||
var result = await confirm.ShowAsync();
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
// TODO: Implement full reset
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user