Skip to content

Commit c2c3d51

Browse files
committed
WIP
1 parent 45e506f commit c2c3d51

File tree

7 files changed

+135
-40
lines changed

7 files changed

+135
-40
lines changed

App/App.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
<ItemGroup>
5858
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
5959
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
60+
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250402" />
6061
<PackageReference Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
6162
<PackageReference Include="DependencyPropertyGenerator" Version="1.5.0">
6263
<PrivateAssets>all</PrivateAssets>

App/App.xaml.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public partial class App : Application
4444
private readonly ILogger<App> _logger;
4545
private readonly IUriHandler _uriHandler;
4646

47+
private readonly ISettingsManager _settingsManager;
48+
4749
public App()
4850
{
4951
var builder = Host.CreateApplicationBuilder();
@@ -115,6 +117,7 @@ public App()
115117
_services = services.BuildServiceProvider();
116118
_logger = (ILogger<App>)_services.GetService(typeof(ILogger<App>))!;
117119
_uriHandler = (IUriHandler)_services.GetService(typeof(IUriHandler))!;
120+
_settingsManager = (ISettingsManager)_services.GetService(typeof(ISettingsManager))!;
118121

119122
InitializeComponent();
120123
}
@@ -150,6 +153,22 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
150153
Debug.WriteLine(t.Exception);
151154
Debugger.Break();
152155
#endif
156+
} else
157+
{
158+
if (rpcController.GetState().RpcLifecycle == RpcLifecycle.Disconnected)
159+
{
160+
if (_settingsManager.Read(SettingsManager.ConnectOnLaunchKey, false))
161+
{
162+
_logger.LogInformation("RPC lifecycle is disconnected, but ConnectOnLaunch is enabled; attempting to connect");
163+
_ = rpcController.StartVpn(CancellationToken.None).ContinueWith(connectTask =>
164+
{
165+
if (connectTask.Exception != null)
166+
{
167+
_logger.LogError(connectTask.Exception, "failed to connect on launch");
168+
}
169+
});
170+
}
171+
}
153172
}
154173
});
155174

@@ -178,9 +197,6 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
178197
if (t.IsCanceled || t.Exception != null)
179198
{
180199
_logger.LogError(t.Exception, "failed to refresh sync state (canceled = {canceled})", t.IsCanceled);
181-
#if DEBUG
182-
Debugger.Break();
183-
#endif
184200
}
185201

186202
syncSessionCts.Dispose();

App/Services/SettingsManager.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ public sealed class SettingsManager : ISettingsManager
3232
private readonly object _lock = new();
3333
private Dictionary<string, JsonElement> _cache;
3434

35+
public static readonly string ConnectOnLaunchKey = "ConnectOnLaunch";
36+
public static readonly string StartOnLoginKey = "StartOnLogin";
37+
3538
/// <param name="appName">
36-
/// Sub‑folder under %LOCALAPPDATA% (e.g. "coder-desktop").
39+
/// Sub‑folder under %LOCALAPPDATA% (e.g. "CoderDesktop").
3740
/// If <c>null</c> the folder name defaults to the executable name.
3841
/// For unit‑tests you can pass an absolute path that already exists.
3942
/// </param>

App/ViewModels/SettingsViewModel.cs

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
using System;
21
using Coder.Desktop.App.Services;
32
using CommunityToolkit.Mvvm.ComponentModel;
43
using CommunityToolkit.Mvvm.Input;
4+
using Microsoft.Extensions.Logging;
55
using Microsoft.UI.Dispatching;
66
using Microsoft.UI.Xaml;
77
using Microsoft.UI.Xaml.Controls;
8+
using System;
89

910
namespace Coder.Desktop.App.ViewModels;
1011

@@ -13,11 +14,48 @@ public partial class SettingsViewModel : ObservableObject
1314
private Window? _window;
1415
private DispatcherQueue? _dispatcherQueue;
1516

17+
private readonly ILogger<SettingsViewModel> _logger;
18+
19+
[ObservableProperty]
20+
public partial bool ConnectOnLaunch { get; set; } = false;
21+
22+
[ObservableProperty]
23+
public partial bool StartOnLogin { get; set; } = false;
24+
1625
private ISettingsManager _settingsManager;
1726

18-
public SettingsViewModel(ISettingsManager settingsManager)
27+
public SettingsViewModel(ILogger<SettingsViewModel> logger, ISettingsManager settingsManager)
1928
{
2029
_settingsManager = settingsManager;
30+
_logger = logger;
31+
ConnectOnLaunch = _settingsManager.Read(SettingsManager.ConnectOnLaunchKey, false);
32+
StartOnLogin = _settingsManager.Read(SettingsManager.StartOnLoginKey, false);
33+
34+
this.PropertyChanged += (_, args) =>
35+
{
36+
if (args.PropertyName == nameof(ConnectOnLaunch))
37+
{
38+
try
39+
{
40+
_settingsManager.Save(SettingsManager.ConnectOnLaunchKey, ConnectOnLaunch);
41+
}
42+
catch (Exception ex)
43+
{
44+
Console.WriteLine($"Error saving {SettingsManager.ConnectOnLaunchKey} setting: {ex.Message}");
45+
}
46+
}
47+
else if (args.PropertyName == nameof(StartOnLogin))
48+
{
49+
try
50+
{
51+
_settingsManager.Save(SettingsManager.StartOnLoginKey, StartOnLogin);
52+
}
53+
catch (Exception ex)
54+
{
55+
Console.WriteLine($"Error saving {SettingsManager.StartOnLoginKey} setting: {ex.Message}");
56+
}
57+
}
58+
};
2159
}
2260

2361
public void Initialize(Window window, DispatcherQueue dispatcherQueue)
@@ -27,28 +65,4 @@ public void Initialize(Window window, DispatcherQueue dispatcherQueue)
2765
if (!_dispatcherQueue.HasThreadAccess)
2866
throw new InvalidOperationException("Initialize must be called from the UI thread");
2967
}
30-
31-
[RelayCommand]
32-
private void SaveSetting()
33-
{
34-
//_settingsManager.Save();
35-
}
36-
37-
[RelayCommand]
38-
private void ShowSettingsDialog()
39-
{
40-
if (_window is null || _dispatcherQueue is null)
41-
throw new InvalidOperationException("Initialize must be called before showing the settings dialog.");
42-
// Here you would typically open a settings dialog or page.
43-
// For example, you could navigate to a SettingsPage in your app.
44-
// This is just a placeholder for demonstration purposes.
45-
// Display MessageBox and show a message
46-
var message = $"Settings dialog opened. Current setting: {_settingsManager.Read("SomeSetting", false)}\n" +
47-
"You can implement your settings dialog here.";
48-
var dialog = new ContentDialog();
49-
dialog.Title = "Settings";
50-
dialog.Content = message;
51-
dialog.XamlRoot = _window.Content.XamlRoot;
52-
_ = dialog.ShowAsync();
53-
}
5468
}

App/Views/Pages/SettingsMainPage.xaml

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,49 @@
88
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
99
xmlns:viewmodels="using:Coder.Desktop.App.ViewModels"
1010
xmlns:converters="using:Coder.Desktop.App.Converters"
11+
xmlns:ui="using:CommunityToolkit.WinUI"
12+
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
13+
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
1114
mc:Ignorable="d"
1215
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
1316

14-
<Grid>
15-
<HyperlinkButton
16-
Command="{x:Bind ViewModel.ShowSettingsDialogCommand, Mode=OneWay}"
17-
HorizontalAlignment="Stretch"
18-
HorizontalContentAlignment="Left">
17+
<Page.Resources>
18+
<!-- These styles can be referenced to create a consistent SettingsPage layout -->
19+
20+
<!-- Spacing between cards -->
21+
<x:Double x:Key="SettingsCardSpacing">4</x:Double>
22+
23+
<!-- Style (inc. the correct spacing) of a section header -->
24+
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
25+
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
26+
TargetType="TextBlock">
27+
<Style.Setters>
28+
<Setter Property="Margin" Value="1,30,0,6" />
29+
</Style.Setters>
30+
</Style>
31+
</Page.Resources>
32+
<ScrollViewer>
33+
<Grid Padding="20, 0, 20, 0">
34+
<StackPanel MaxWidth="1000"
35+
HorizontalAlignment="Stretch"
36+
Spacing="{StaticResource SettingsCardSpacing}">
37+
38+
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="Coder Desktop" />
39+
40+
<controls:SettingsCard Description="This setting controls whether the Coder Desktop app starts on Windows startup."
41+
Header="Start on login"
42+
HeaderIcon="{ui:FontIcon Glyph=&#xE819;}">
43+
<ToggleSwitch IsOn="{x:Bind ViewModel.StartOnLogin, Mode=TwoWay}" />
44+
</controls:SettingsCard>
45+
46+
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="Coder Connect" />
47+
<controls:SettingsCard Description="This setting controls whether Coder Connect automatically starts with Coder Desktop "
48+
Header="Connect on launch"
49+
HeaderIcon="{ui:FontIcon Glyph=&#xE8AF;}">
50+
<ToggleSwitch IsOn="{x:Bind ViewModel.ConnectOnLaunch, Mode=TwoWay}" />
51+
</controls:SettingsCard>
52+
</StackPanel>
53+
</Grid>
54+
</ScrollViewer>
1955

20-
<TextBlock Text="Show settings" Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
21-
</HyperlinkButton>
22-
</Grid>
2356
</Page>

App/Views/SettingsWindow.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
xmlns:winuiex="using:WinUIEx"
1010
mc:Ignorable="d"
1111
Title="Coder Settings"
12-
Width="1000" Height="300"
13-
MinWidth="1000" MinHeight="300">
12+
Width="600" Height="350"
13+
MinWidth="600" MinHeight="350">
1414

1515
<Window.SystemBackdrop>
1616
<DesktopAcrylicBackdrop />

App/packages.lock.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
"Microsoft.WindowsAppSDK": "1.6.250108002"
1919
}
2020
},
21+
"CommunityToolkit.WinUI.Controls.SettingsControls": {
22+
"type": "Direct",
23+
"requested": "[8.2.250402, )",
24+
"resolved": "8.2.250402",
25+
"contentHash": "whJNIyxVwwLmmCS63m91r0aL13EYgdKDE0ERh2e0G2U5TUeYQQe2XRODGGr/ceBRvqu6SIvq1sXxVwglSMiJMg==",
26+
"dependencies": {
27+
"CommunityToolkit.WinUI.Triggers": "8.2.250402",
28+
"Microsoft.WindowsAppSDK": "1.6.250108002"
29+
}
30+
},
2131
"CommunityToolkit.WinUI.Extensions": {
2232
"type": "Direct",
2333
"requested": "[8.2.250402, )",
@@ -152,6 +162,24 @@
152162
"resolved": "8.2.1",
153163
"contentHash": "LWuhy8cQKJ/MYcy3XafJ916U3gPH/YDvYoNGWyQWN11aiEKCZszzPOTJAOvBjP9yG8vHmIcCyPUt4L82OK47Iw=="
154164
},
165+
"CommunityToolkit.WinUI.Helpers": {
166+
"type": "Transitive",
167+
"resolved": "8.2.250402",
168+
"contentHash": "DThBXB4hT3/aJ7xFKQJw/C0ZEs1QhZL7QG6AFOYcpnGWNlv3tkF761PFtTyhpNQrR1AFfzml5zG+zWfFbKs6Mw==",
169+
"dependencies": {
170+
"CommunityToolkit.WinUI.Extensions": "8.2.250402",
171+
"Microsoft.WindowsAppSDK": "1.6.250108002"
172+
}
173+
},
174+
"CommunityToolkit.WinUI.Triggers": {
175+
"type": "Transitive",
176+
"resolved": "8.2.250402",
177+
"contentHash": "laHIrBQkwQCurTNSQdGdEXUyoCpqY8QFXSybDM/Q1Ti/23xL+sRX/gHe3pP8uMM59bcwYbYlMRCbIaLnxnrdjw==",
178+
"dependencies": {
179+
"CommunityToolkit.WinUI.Helpers": "8.2.250402",
180+
"Microsoft.WindowsAppSDK": "1.6.250108002"
181+
}
182+
},
155183
"Google.Protobuf": {
156184
"type": "Transitive",
157185
"resolved": "3.29.3",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy