Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita6f7bb6

Browse files
authored
feat: add workspace app icons to tray window (#86)
Closes#50
1 parent9e4ebf2 commita6f7bb6

File tree

38 files changed

+2057
-242
lines changed

38 files changed

+2057
-242
lines changed

‎App/App.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<ProjectSdk="Microsoft.NET.Sdk">
1+
<ProjectSdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>WinExe</OutputType>
44
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
@@ -16,7 +16,7 @@
1616
<!-- To use CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute:-->
1717
<LangVersion>preview</LangVersion>
1818
<!-- We have our own implementation of main with exception handling-->
19-
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
19+
<DefineConstants>DISABLE_XAML_GENERATED_MAIN;DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION</DefineConstants>
2020

2121
<AssemblyName>Coder Desktop</AssemblyName>
2222
<ApplicationIcon>coder.ico</ApplicationIcon>
@@ -57,6 +57,7 @@
5757
<ItemGroup>
5858
<PackageReferenceInclude="CommunityToolkit.Mvvm"Version="8.4.0" />
5959
<PackageReferenceInclude="CommunityToolkit.WinUI.Controls.Primitives"Version="8.2.250402" />
60+
<PackageReferenceInclude="CommunityToolkit.WinUI.Extensions"Version="8.2.250402" />
6061
<PackageReferenceInclude="DependencyPropertyGenerator"Version="1.5.0">
6162
<PrivateAssets>all</PrivateAssets>
6263
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

‎App/App.xaml.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
usingCoder.Desktop.App.Views;
1212
usingCoder.Desktop.App.Views.Pages;
1313
usingCoder.Desktop.CoderSdk.Agent;
14+
usingCoder.Desktop.CoderSdk.Coder;
1415
usingCoder.Desktop.Vpn;
1516
usingMicrosoft.Extensions.Configuration;
1617
usingMicrosoft.Extensions.DependencyInjection;
@@ -19,9 +20,9 @@
1920
usingMicrosoft.UI.Xaml;
2021
usingMicrosoft.Win32;
2122
usingMicrosoft.Windows.AppLifecycle;
23+
usingMicrosoft.Windows.AppNotifications;
2224
usingSerilog;
2325
usingLaunchActivatedEventArgs=Microsoft.UI.Xaml.LaunchActivatedEventArgs;
24-
usingMicrosoft.Windows.AppNotifications;
2526

2627
namespaceCoder.Desktop.App;
2728

@@ -64,8 +65,11 @@ public App()
6465
loggerConfig.ReadFrom.Configuration(builder.Configuration);
6566
});
6667

68+
services.AddSingleton<ICoderApiClientFactory,CoderApiClientFactory>();
6769
services.AddSingleton<IAgentApiClientFactory,AgentApiClientFactory>();
6870

71+
services.AddSingleton<ICredentialBackend>(_=>
72+
newWindowsCredentialBackend(WindowsCredentialBackend.CoderCredentialsTargetName));
6973
services.AddSingleton<ICredentialManager,CredentialManager>();
7074
services.AddSingleton<IRpcController,RpcController>();
7175

@@ -95,6 +99,8 @@ public App()
9599
services.AddTransient<TrayWindowLoginRequiredPage>();
96100
services.AddTransient<TrayWindowLoginRequiredViewModel>();
97101
services.AddTransient<TrayWindowLoginRequiredPage>();
102+
services.AddSingleton<IAgentAppViewModelFactory,AgentAppViewModelFactory>();
103+
services.AddSingleton<IAgentViewModelFactory,AgentViewModelFactory>();
98104
services.AddTransient<TrayWindowViewModel>();
99105
services.AddTransient<TrayWindowMainPage>();
100106
services.AddTransient<TrayWindow>();

‎App/Controls/ExpandChevron.xaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<UserControl
4+
x:Class="Coder.Desktop.App.Controls.ExpandChevron"
5+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
6+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
10+
mc:Ignorable="d">
11+
12+
<Grid>
13+
<AnimatedIcon
14+
Grid.Column="0"
15+
x:Name="ChevronIcon"
16+
Width="16"
17+
Height="16"
18+
Margin="0,0,8,0"
19+
RenderTransformOrigin="0.5, 0.5"
20+
Foreground="{x:Bind Foreground, Mode=OneWay}"
21+
HorizontalAlignment="Center"
22+
VerticalAlignment="Center"
23+
AnimatedIcon.State="NormalOff">
24+
25+
<animatedVisuals:AnimatedChevronRightDownSmallVisualSource />
26+
<AnimatedIcon.FallbackIconSource>
27+
<FontIconSourceGlyph="&#xE76C;" />
28+
</AnimatedIcon.FallbackIconSource>
29+
</AnimatedIcon>
30+
</Grid>
31+
</UserControl>

‎App/Controls/ExpandChevron.xaml.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
usingDependencyPropertyGenerator;
2+
usingMicrosoft.UI.Xaml.Controls;
3+
4+
namespaceCoder.Desktop.App.Controls;
5+
6+
[DependencyProperty<bool>("IsOpen",DefaultValue=false)]
7+
publicsealedpartialclassExpandChevron:UserControl
8+
{
9+
publicExpandChevron()
10+
{
11+
InitializeComponent();
12+
}
13+
14+
partialvoidOnIsOpenChanged(boololdValue,boolnewValue)
15+
{
16+
varnewState=newValue?"NormalOn":"NormalOff";
17+
AnimatedIcon.SetState(ChevronIcon,newState);
18+
}
19+
}

‎App/Controls/ExpandContent.xaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<UserControl
4+
x:Class="Coder.Desktop.App.Controls.ExpandContent"
5+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
6+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
xmlns:toolkit="using:CommunityToolkit.WinUI"
10+
mc:Ignorable="d">
11+
12+
<Gridx:Name="CollapsiblePanel"Opacity="0"Visibility="Collapsed" toolkit:UIElementExtensions.ClipToBounds="True">
13+
<Grid.RenderTransform>
14+
<TranslateTransformx:Name="SlideTransform"Y="-10" />
15+
</Grid.RenderTransform>
16+
17+
<VisualStateManager.VisualStateGroups>
18+
<VisualStateGroup>
19+
<VisualStatex:Name="ExpandedState">
20+
<Storyboard>
21+
<DoubleAnimation
22+
Storyboard.TargetName="CollapsiblePanel"
23+
Storyboard.TargetProperty="Opacity"
24+
To="1"
25+
Duration="0:0:0.2" />
26+
<DoubleAnimation
27+
Storyboard.TargetName="SlideTransform"
28+
Storyboard.TargetProperty="Y"
29+
To="0"
30+
Duration="0:0:0.2" />
31+
</Storyboard>
32+
</VisualState>
33+
34+
<VisualStatex:Name="CollapsedState">
35+
<StoryboardCompleted="{x:Bind CollapseAnimation_Completed}">
36+
<DoubleAnimation
37+
Storyboard.TargetName="CollapsiblePanel"
38+
Storyboard.TargetProperty="Opacity"
39+
To="0"
40+
Duration="0:0:0.2" />
41+
<DoubleAnimation
42+
Storyboard.TargetName="SlideTransform"
43+
Storyboard.TargetProperty="Y"
44+
To="-10"
45+
Duration="0:0:0.2" />
46+
</Storyboard>
47+
</VisualState>
48+
</VisualStateGroup>
49+
</VisualStateManager.VisualStateGroups>
50+
</Grid>
51+
</UserControl>

‎App/Controls/ExpandContent.xaml.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
usingDependencyPropertyGenerator;
2+
usingMicrosoft.UI.Xaml;
3+
usingMicrosoft.UI.Xaml.Controls;
4+
usingMicrosoft.UI.Xaml.Markup;
5+
6+
namespaceCoder.Desktop.App.Controls;
7+
8+
[ContentProperty(Name=nameof(Children))]
9+
[DependencyProperty<bool>("IsOpen",DefaultValue=false)]
10+
publicsealedpartialclassExpandContent:UserControl
11+
{
12+
publicUIElementCollectionChildren=>CollapsiblePanel.Children;
13+
14+
publicExpandContent()
15+
{
16+
InitializeComponent();
17+
}
18+
19+
publicvoidCollapseAnimation_Completed(object?sender,objectargs)
20+
{
21+
// Hide the panel completely when the collapse animation is done. This
22+
// cannot be done with keyframes for some reason.
23+
//
24+
// Without this, the space will still be reserved for the panel.
25+
CollapsiblePanel.Visibility=Visibility.Collapsed;
26+
}
27+
28+
partialvoidOnIsOpenChanged(boololdValue,boolnewValue)
29+
{
30+
varnewState=newValue?"ExpandedState":"CollapsedState";
31+
32+
// The animation can't set visibility when starting or ending the
33+
// animation.
34+
if(newValue)
35+
CollapsiblePanel.Visibility=Visibility.Visible;
36+
37+
VisualStateManager.GoToState(this,newState,true);
38+
}
39+
}

‎App/Converters/DependencyObjectSelector.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,15 @@ private void UpdateSelectedObject()
156156
ClearValue(SelectedObjectProperty);
157157
}
158158

159+
privatestaticvoidVerifyReferencesProperty(IObservableVector<DependencyObject>references)
160+
{
161+
// Ensure unique keys and that the values are DependencyObjectSelectorItem<K, V>.
162+
varitems=references.OfType<DependencyObjectSelectorItem<TK,TV>>().ToArray();
163+
varkeys=items.Select(i=>i.Key).Distinct().ToArray();
164+
if(keys.Length!=references.Count)
165+
thrownewArgumentException("ObservableCollection Keys must be unique.");
166+
}
167+
159168
// Called when the References property is replaced.
160169
privatestaticvoidReferencesPropertyChanged(DependencyObjectobj,DependencyPropertyChangedEventArgsargs)
161170
{
@@ -166,12 +175,16 @@ private static void ReferencesPropertyChanged(DependencyObject obj, DependencyPr
166175
oldValue.VectorChanged-=self.OnVectorChangedReferences;
167176
varnewValue=args.NewValueasDependencyObjectCollection;
168177
if(newValue!=null)
178+
{
179+
VerifyReferencesProperty(newValue);
169180
newValue.VectorChanged+=self.OnVectorChangedReferences;
181+
}
170182
}
171183

172184
// Called when the References collection changes without being replaced.
173185
privatevoidOnVectorChangedReferences(IObservableVector<DependencyObject>sender,IVectorChangedEventArgsargs)
174186
{
187+
VerifyReferencesProperty(sender);
175188
UpdateSelectedObject();
176189
}
177190

‎App/Models/CredentialModel.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1+
usingSystem;
2+
13
namespaceCoder.Desktop.App.Models;
24

35
publicenumCredentialState
46
{
57
// Unknown means "we haven't checked yet"
68
Unknown,
79

8-
// Invalid means "we checked and there's either no saved credentials or they are not valid"
10+
// Invalid means "we checked and there's either no saved credentials, or they are not valid"
911
Invalid,
1012

11-
// Valid means "we checked and there are saved credentials and they are valid"
13+
// Valid means "we checked and there are saved credentials, and they are valid"
1214
Valid,
1315
}
1416

1517
publicclassCredentialModel
1618
{
1719
publicCredentialStateState{get;init;}=CredentialState.Unknown;
1820

19-
publicstring?CoderUrl{get;init;}
21+
publicUri?CoderUrl{get;init;}
2022
publicstring?ApiToken{get;init;}
2123

2224
publicstring?Username{get;init;}

‎App/Program.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,9 @@ private static void Main(string[] args)
6363
notificationManager.NotificationInvoked+=app.HandleNotification;
6464
notificationManager.Register();
6565
if(activationArgs.Kind!=ExtendedActivationKind.Launch)
66-
{
6766
// this means we were activated without having already launched, so handle
6867
// the activation as well.
6968
app.OnActivated(null,activationArgs);
70-
}
7169
});
7270
}
7371
catch(Exceptione)

‎App/Services/CredentialManager.cs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class RawCredentials
2121
[JsonSerializable(typeof(RawCredentials))]
2222
publicpartialclassRawCredentialsJsonContext:JsonSerializerContext;
2323

24-
publicinterface ICredentialManager
24+
publicinterface ICredentialManager:ICoderApiClientCredentialProvider
2525
{
2626
publiceventEventHandler<CredentialModel>CredentialsChanged;
2727

@@ -59,7 +59,8 @@ public interface ICredentialBackend
5959
/// </summary>
6060
publicclassCredentialManager:ICredentialManager
6161
{
62-
privateconststringCredentialsTargetName="Coder.Desktop.App.Credentials";
62+
privatereadonlyICredentialBackendBackend;
63+
privatereadonlyICoderApiClientFactoryCoderApiClientFactory;
6364

6465
// _opLock is held for the full duration of SetCredentials, and partially
6566
// during LoadCredentials. _opLock protects _inFlightLoad, _loadCts, and
@@ -79,14 +80,6 @@ public class CredentialManager : ICredentialManager
7980
// immediate).
8081
privatevolatileCredentialModel?_latestCredentials;
8182

82-
privateICredentialBackendBackend{get;}=newWindowsCredentialBackend(CredentialsTargetName);
83-
84-
privateICoderApiClientFactoryCoderApiClientFactory{get;}=newCoderApiClientFactory();
85-
86-
publicCredentialManager()
87-
{
88-
}
89-
9083
publicCredentialManager(ICredentialBackendbackend,ICoderApiClientFactorycoderApiClientFactory)
9184
{
9285
Backend=backend;
@@ -108,6 +101,20 @@ public CredentialModel GetCachedCredentials()
108101
};
109102
}
110103

104+
// Implements ICoderApiClientCredentialProvider
105+
publicCoderApiClientCredential?GetCoderApiClientCredential()
106+
{
107+
varlatestCreds=_latestCredentials;
108+
if(latestCredsis not{State:CredentialState.Valid}||latestCreds.CoderUrlisnull)
109+
returnnull;
110+
111+
returnnewCoderApiClientCredential
112+
{
113+
CoderUrl=latestCreds.CoderUrl,
114+
ApiToken=latestCreds.ApiToken??"",
115+
};
116+
}
117+
111118
publicasyncTask<string?>GetSignInUri()
112119
{
113120
try
@@ -253,6 +260,12 @@ private async Task<CredentialModel> PopulateModel(RawCredentials? credentials, C
253260
State=CredentialState.Invalid,
254261
};
255262

263+
if(!Uri.TryCreate(credentials.CoderUrl,UriKind.Absolute,outvaruri))
264+
returnnewCredentialModel
265+
{
266+
State=CredentialState.Invalid,
267+
};
268+
256269
BuildInfobuildInfo;
257270
Userme;
258271
try
@@ -279,7 +292,7 @@ private async Task<CredentialModel> PopulateModel(RawCredentials? credentials, C
279292
returnnewCredentialModel
280293
{
281294
State=CredentialState.Valid,
282-
CoderUrl=credentials.CoderUrl,
295+
CoderUrl=uri,
283296
ApiToken=credentials.ApiToken,
284297
Username=me.Username,
285298
};
@@ -298,6 +311,8 @@ private void UpdateState(CredentialModel newModel)
298311

299312
publicclassWindowsCredentialBackend:ICredentialBackend
300313
{
314+
publicconststringCoderCredentialsTargetName="Coder.Desktop.App.Credentials";
315+
301316
privatereadonlystring_credentialsTargetName;
302317

303318
publicWindowsCredentialBackend(stringcredentialsTargetName)

‎App/Services/RpcController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public async Task StartVpn(CancellationToken ct = default)
170170
{
171171
Start=newStartRequest
172172
{
173-
CoderUrl=credentials.CoderUrl,
173+
CoderUrl=credentials.CoderUrl?.ToString(),
174174
ApiToken=credentials.ApiToken,
175175
},
176176
},ct);

‎App/Services/UserNotifier.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,3 @@ public Task ShowErrorNotification(string title, string message, CancellationToke
2727
returnTask.CompletedTask;
2828
}
2929
}
30-

‎App/DisplayScale.csrenamed to‎App/Utils/DisplayScale.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
usingMicrosoft.UI.Xaml;
44
usingWinRT.Interop;
55

6-
namespaceCoder.Desktop.App;
6+
namespaceCoder.Desktop.App.Utils;
77

88
/// <summary>
99
/// A static utility class to house methods related to the visual scale of the display monitor.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp