Skip to content

Commit d6cbf71

Browse files
feat: enabled sign out and animated window resize (#109)
Closes: #96 --------- Co-authored-by: Dean Sheather <[email protected]>
1 parent 2301c75 commit d6cbf71

File tree

10 files changed

+188
-70
lines changed

10 files changed

+188
-70
lines changed

‎App/Controls/ExpandContent.xaml‎

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,43 @@
99
xmlns:toolkit="using:CommunityToolkit.WinUI"
1010
mc:Ignorable="d">
1111

12-
<Gridx:Name="CollapsiblePanel"Opacity="0"Visibility="Collapsed" toolkit:UIElementExtensions.ClipToBounds="True">
12+
<Gridx:Name="CollapsiblePanel"Opacity="0"Visibility="Collapsed"MaxHeight="0"toolkit:UIElementExtensions.ClipToBounds="True">
1313
<Grid.RenderTransform>
14-
<TranslateTransformx:Name="SlideTransform"Y="-10"/>
14+
<TranslateTransformx:Name="SlideTransform"Y="-16"/>
1515
</Grid.RenderTransform>
1616

1717
<VisualStateManager.VisualStateGroups>
1818
<VisualStateGroup>
1919
<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"/>
20+
<Storyboardx:Name="ExpandSb">
21+
<DoubleAnimation Storyboard.TargetName="CollapsiblePanel"
22+
Storyboard.TargetProperty="MaxHeight"
23+
To="10000"Duration="0:0:0.16"BeginTime="0:0:0.16"
24+
EnableDependentAnimation="True"/>
25+
<DoubleAnimation Storyboard.TargetName="CollapsiblePanel"
26+
Storyboard.TargetProperty="Opacity"BeginTime="0:0:0.16"
27+
To="1"Duration="0:0:0.16"/>
28+
<DoubleAnimationStoryboard.TargetName="SlideTransform"
29+
Storyboard.TargetProperty="Y"BeginTime="0:0:0.16"
30+
To="0"Duration="0:0:0.16"/>
3131
</Storyboard>
3232
</VisualState>
33-
3433
<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" />
34+
<Storyboardx:Name="CollapseSb"
35+
Completed="{x:Bind CollapseStoryboard_Completed}">
36+
<DoubleAnimation Storyboard.TargetName="CollapsiblePanel"
37+
Storyboard.TargetProperty="MaxHeight"
38+
To="0"Duration="0:0:0.16"
39+
EnableDependentAnimation="True"/>
40+
<DoubleAnimation Storyboard.TargetName="CollapsiblePanel"
41+
Storyboard.TargetProperty="Opacity"
42+
To="0"Duration="0:0:0.16"/>
43+
<DoubleAnimation Storyboard.TargetName="SlideTransform"
44+
Storyboard.TargetProperty="Y"
45+
To="-16"Duration="0:0:0.16"/>
4646
</Storyboard>
4747
</VisualState>
48+
4849
</VisualStateGroup>
4950
</VisualStateManager.VisualStateGroups>
5051
</Grid>

‎App/Controls/ExpandContent.xaml.cs‎

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,60 @@
22
usingMicrosoft.UI.Xaml;
33
usingMicrosoft.UI.Xaml.Controls;
44
usingMicrosoft.UI.Xaml.Markup;
5+
usingSystem;
6+
usingSystem.Threading.Tasks;
57

68
namespaceCoder.Desktop.App.Controls;
79

10+
811
[ContentProperty(Name=nameof(Children))]
912
[DependencyProperty<bool>("IsOpen",DefaultValue=false)]
1013
publicsealedpartialclassExpandContent:UserControl
1114
{
1215
publicUIElementCollectionChildren=>CollapsiblePanel.Children;
1316

17+
privatereadonlystring_expandedState="ExpandedState";
18+
privatereadonlystring_collapsedState="CollapsedState";
19+
1420
publicExpandContent()
1521
{
1622
InitializeComponent();
17-
}
23+
Loaded+=(_,__)=>
24+
{
25+
// When we load the control for the first time (after panel swapping)
26+
// we need to set the initial state based on IsOpen.
27+
VisualStateManager.GoToState(
28+
this,
29+
IsOpen?_expandedState:_collapsedState,
30+
useTransitions:false);// NO animation yet
1831

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;
32+
// If IsOpen was already true we must also show the panel
33+
if(IsOpen)
34+
{
35+
CollapsiblePanel.Visibility=Visibility.Visible;
36+
// This makes the panel expand to its full height
37+
CollapsiblePanel.ClearValue(FrameworkElement.MaxHeightProperty);
38+
}
39+
};
2640
}
2741

2842
partialvoidOnIsOpenChanged(boololdValue,boolnewValue)
2943
{
30-
varnewState=newValue?"ExpandedState":"CollapsedState";
31-
32-
// The animation can't set visibility when starting or ending the
33-
// animation.
44+
varnewState=newValue?_expandedState:_collapsedState;
3445
if(newValue)
46+
{
3547
CollapsiblePanel.Visibility=Visibility.Visible;
48+
// We use BeginTime to ensure other panels are collapsed first.
49+
// If the user clicks the expand button quickly, we want to avoid
50+
// the panel expanding to its full height before the collapse animation completes.
51+
CollapseSb.SkipToFill();
52+
}
3653

3754
VisualStateManager.GoToState(this,newState,true);
3855
}
56+
57+
privatevoidCollapseStoryboard_Completed(objectsender,objecte)
58+
{
59+
CollapsiblePanel.Visibility=Visibility.Collapsed;
60+
}
3961
}

‎App/Services/RpcController.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ public async Task StopVpn(CancellationToken ct = default)
234234
MutateState(state =>{state.VpnLifecycle=VpnLifecycle.Unknown;});
235235
thrownewVpnLifecycleException($"Failed to stop VPN. Service reported failure: {reply.Stop.ErrorMessage}");
236236
}
237+
238+
MutateState(state =>{state.VpnLifecycle=VpnLifecycle.Stopped;});
237239
}
238240

239241
publicasyncValueTaskDisposeAsync()

‎App/ViewModels/AgentViewModel.cs‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,20 @@ public AgentViewModel(ILogger<AgentViewModel> logger, ICoderApiClientFactory cod
237237

238238
Id=id;
239239

240-
PropertyChanged+=(_,args)=>
240+
PropertyChanging+=(x,args)=>
241241
{
242242
if(args.PropertyName==nameof(IsExpanded))
243243
{
244-
_expanderHost.HandleAgentExpanded(Id,IsExpanded);
244+
varvalue=!IsExpanded;
245+
if(value)
246+
_expanderHost.HandleAgentExpanded(Id,value);
247+
}
248+
};
245249

250+
PropertyChanged+=(x,args)=>
251+
{
252+
if(args.PropertyName==nameof(IsExpanded))
253+
{
246254
// Every time the drawer is expanded, re-fetch all apps.
247255
if(IsExpanded&&!FetchingApps)
248256
FetchApps();

‎App/ViewModels/TrayWindowLoginRequiredViewModel.cs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
usingCoder.Desktop.App.Views;
33
usingCommunityToolkit.Mvvm.Input;
44
usingMicrosoft.Extensions.DependencyInjection;
5+
usingMicrosoft.UI.Xaml;
56

67
namespaceCoder.Desktop.App.ViewModels;
78

@@ -31,4 +32,10 @@ public void Login()
3132
_signInWindow.Closed+=(_,_)=>_signInWindow=null;
3233
_signInWindow.Activate();
3334
}
35+
36+
[RelayCommand]
37+
publicvoidExit()
38+
{
39+
_=((App)Application.Current).ExitApplication();
40+
}
3441
}

‎App/ViewModels/TrayWindowViewModel.cs‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public void HandleAgentExpanded(Uuid id, bool expanded)
126126
if(!expanded)return;
127127
_hasExpandedAgent=true;
128128
// Collapse every other agent.
129-
foreach(varotherAgentinAgents.Where(a =>a.Id!=id))
129+
foreach(varotherAgentinAgents.Where(a =>a.Id!=id&&a.IsExpanded==true))
130130
otherAgent.SetExpanded(false);
131131
}
132132

@@ -360,11 +360,10 @@ private void ShowFileSyncListWindow()
360360
}
361361

362362
[RelayCommand]
363-
privatevoidSignOut()
363+
privateasyncTaskSignOut()
364364
{
365-
if(VpnLifecycleis not VpnLifecycle.Stopped)
366-
return;
367-
_credentialManager.ClearCredentials();
365+
await_rpcController.StopVpn();
366+
await_credentialManager.ClearCredentials();
368367
}
369368

370369
[RelayCommand]

‎App/Views/Pages/TrayWindowLoginRequiredPage.xaml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,14 @@
3434

3535
<TextBlockText="Sign in"Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
3636
</HyperlinkButton>
37+
38+
<HyperlinkButton
39+
Command="{x:Bind ViewModel.ExitCommand, Mode=OneWay}"
40+
Margin="-12,-8,-12,-5"
41+
HorizontalAlignment="Stretch"
42+
HorizontalContentAlignment="Left">
43+
44+
<TextBlockText="Exit"Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
45+
</HyperlinkButton>
3746
</StackPanel>
3847
</Page>

‎App/Views/Pages/TrayWindowMainPage.xaml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@
333333

334334
<HyperlinkButton
335335
Command="{x:Bind ViewModel.SignOutCommand, Mode=OneWay}"
336-
IsEnabled="{x:Bind ViewModel.VpnLifecycle, Converter={StaticResource StoppedBoolConverter}, Mode=OneWay}"
337336
Margin="-12,0"
338337
HorizontalAlignment="Stretch"
339338
HorizontalContentAlignment="Left">

‎App/Views/TrayWindow.xaml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,12 @@
2020

2121
<!-- This is where the current Page is displayed -->
2222
<controls:SizedFramex:Name="RootFrame" />
23+
24+
<!-- proxy for animating resize -->
25+
<Borderx:Name="SizeProxy"
26+
Width="0"
27+
Height="0"
28+
IsHitTestVisible="False"
29+
Opacity="0" />
2330
</Grid>
2431
</Window>

0 commit comments

Comments
(0)