Skip to content

Commit 6f1e3ad

Browse files
authored
Added update button to the toolbar (#8054)
1 parent 1acf452 commit 6f1e3ad

File tree

9 files changed

+222
-2
lines changed

9 files changed

+222
-2
lines changed

src/Files/App.xaml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ private IServiceProvider ConfigureServices()
106106
// Settings not related to IUserSettingsService:
107107
.AddSingleton<IFileTagsSettingsService, FileTagsSettingsService>()
108108
.AddSingleton<IBundlesSettingsService, BundlesSettingsService>()
109+
.AddSingleton<IUpdateSettingsService, UpdateSettingsService>()
109110

110111
// TODO: Dialogs:
111112

@@ -184,7 +185,9 @@ await Task.WhenAll(
184185
});
185186

186187
// Check for required updates
187-
new AppUpdater().CheckForUpdatesAsync();
188+
var updateService = Ioc.Default.GetRequiredService<IUpdateSettingsService>();
189+
await updateService.CheckForUpdates();
190+
await updateService.DownloadMandatoryUpdates();
188191
}
189192

190193
private void OnLeavingBackground(object sender, LeavingBackgroundEventArgs e)

src/Files/Files.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,10 @@
265265
<Compile Include="Services\IMultitaskingSettingsService.cs" />
266266
<Compile Include="Services\IPreferencesSettingsService.cs" />
267267
<Compile Include="Services\IPreviewPaneSettingsService.cs" />
268+
<Compile Include="Services\IUpdateSettingsService.cs" />
268269
<Compile Include="Services\IUserSettingsService.cs" />
269270
<Compile Include="Services\IWidgetsSettingsService.cs" />
271+
<Compile Include="Services\Implementation\UpdateSettingsService.cs" />
270272
<Compile Include="UserControls\ColoredIcon.xaml.cs">
271273
<DependentUpon>ColoredIcon.xaml</DependentUpon>
272274
</Compile>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Threading.Tasks;
4+
5+
namespace Files.Services
6+
{
7+
public interface IUpdateSettingsService : IBaseSettingsService, INotifyPropertyChanged
8+
{
9+
/// <summary>
10+
/// Gets a value indicating whether updates are available.
11+
/// </summary>
12+
bool IsUpdateAvailable { get; }
13+
14+
/// <summary>
15+
/// Gets a value indicating if an update is in progress.
16+
/// </summary>
17+
bool IsUpdating { get; }
18+
19+
Task DownloadUpdates();
20+
21+
Task DownloadMandatoryUpdates();
22+
23+
Task CheckForUpdates();
24+
}
25+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using Files.Models.JsonSettings;
7+
using Microsoft.Toolkit.Uwp;
8+
using Windows.Services.Store;
9+
using Windows.UI.Xaml.Controls;
10+
11+
namespace Files.Services.Implementation
12+
{
13+
public class UpdateSettingsService : BaseObservableJsonSettingsModel, IUpdateSettingsService
14+
{
15+
private StoreContext _storeContext;
16+
private IList<StorePackageUpdate> _updatePackages;
17+
18+
private bool IsMandatory => _updatePackages?.Where(e => e.Mandatory).ToList().Count >= 1;
19+
20+
private bool _isUpdateAvailable;
21+
22+
public bool IsUpdateAvailable
23+
{
24+
get => _isUpdateAvailable;
25+
set
26+
{
27+
_isUpdateAvailable = value;
28+
OnPropertyChanged(nameof(IsUpdateAvailable));
29+
}
30+
}
31+
32+
private bool _isUpdating;
33+
34+
public bool IsUpdating
35+
{
36+
get => _isUpdating;
37+
private set
38+
{
39+
_isUpdating = value;
40+
OnPropertyChanged(nameof(IsUpdating));
41+
}
42+
}
43+
44+
public UpdateSettingsService()
45+
{
46+
_updatePackages = new List<StorePackageUpdate>();
47+
}
48+
49+
public void ReportToAppCenter() {}
50+
51+
public async Task DownloadUpdates()
52+
{
53+
OnUpdateInProgress();
54+
55+
if (!HasUpdates())
56+
{
57+
return;
58+
}
59+
60+
// double check for Mandatory
61+
if (IsMandatory)
62+
{
63+
// Show dialog
64+
var dialog = await ShowDialogAsync();
65+
if (!dialog)
66+
{
67+
// User rejected mandatory update.
68+
OnUpdateCancelled();
69+
return;
70+
}
71+
}
72+
73+
await DownloadAndInstall();
74+
OnUpdateCompleted();
75+
}
76+
77+
public async Task DownloadMandatoryUpdates()
78+
{
79+
// Prompt the user to download if the package list
80+
// contains mandatory updates.
81+
if (IsMandatory && HasUpdates())
82+
{
83+
if (await ShowDialogAsync())
84+
{
85+
OnUpdateInProgress();
86+
await DownloadAndInstall();
87+
OnUpdateCompleted();
88+
}
89+
}
90+
}
91+
92+
public async Task CheckForUpdates()
93+
{
94+
await GetUpdatePackages();
95+
96+
if (_updatePackages is not null && _updatePackages.Count > 0)
97+
{
98+
IsUpdateAvailable = true;
99+
}
100+
}
101+
102+
private async Task DownloadAndInstall()
103+
{
104+
App.SaveSessionTabs();
105+
var downloadOperation = _storeContext.RequestDownloadAndInstallStorePackageUpdatesAsync(_updatePackages);
106+
await downloadOperation.AsTask();
107+
}
108+
109+
private async Task GetUpdatePackages()
110+
{
111+
try
112+
{
113+
_storeContext ??= await Task.Run(StoreContext.GetDefault);
114+
var updateList = await _storeContext.GetAppAndOptionalStorePackageUpdatesAsync();
115+
_updatePackages = updateList?.ToList();
116+
}
117+
catch (FileNotFoundException)
118+
{
119+
// Suppress the FileNotFoundException.
120+
// GetAppAndOptionalStorePackageUpdatesAsync throws for unknown reasons.
121+
}
122+
}
123+
124+
private static async Task<bool> ShowDialogAsync()
125+
{
126+
//TODO: Use IDialogService in future.
127+
ContentDialog dialog = new()
128+
{
129+
Title = "ConsentDialogTitle".GetLocalized(),
130+
Content = "ConsentDialogContent".GetLocalized(),
131+
CloseButtonText = "Close".GetLocalized(),
132+
PrimaryButtonText = "ConsentDialogPrimaryButtonText".GetLocalized()
133+
};
134+
ContentDialogResult result = await dialog.ShowAsync();
135+
136+
return result == ContentDialogResult.Primary;
137+
}
138+
139+
private bool HasUpdates()
140+
{
141+
return _updatePackages is not null && _updatePackages.Count >= 1;
142+
}
143+
144+
protected virtual void OnUpdateInProgress()
145+
{
146+
IsUpdating = true;
147+
}
148+
149+
protected virtual void OnUpdateCompleted()
150+
{
151+
IsUpdating = false;
152+
IsUpdateAvailable = false;
153+
_updatePackages.Clear();
154+
}
155+
156+
protected virtual void OnUpdateCancelled()
157+
{
158+
IsUpdating = false;
159+
}
160+
}
161+
}

src/Files/Strings/en-US/Resources.resw

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2744,4 +2744,7 @@ We use App Center to track which settings are being used, find bugs, and fix cra
27442744
<data name="CloseOtherTabs" xml:space="preserve">
27452745
<value>Close other tabs</value>
27462746
</data>
2747-
</root>
2747+
<data name="UpdateFiles" xml:space="preserve">
2748+
<value>Update Files</value>
2749+
</data>
2750+
</root>

src/Files/UserControls/NavigationToolbar.xaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,22 @@
562562
Value="{x:Bind OngoingTasksViewModel.InfoBadgeValue, Mode=OneWay}" />
563563
</Grid>
564564

565+
<Button
566+
x:Name="UpdateButton"
567+
x:Load="{x:Bind ViewModel.UpdateSettingsService.IsUpdateAvailable, Mode=OneWay}"
568+
Width="36"
569+
Height="32"
570+
AccessKey="1"
571+
AutomationProperties.Name="{helpers:ResourceString Name=UpdateFiles}"
572+
Background="Transparent"
573+
Command="{x:Bind ViewModel.UpdateCommand, Mode=OneWay}"
574+
IsEnabled="{x:Bind ViewModel.UpdateSettingsService.IsUpdating, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
575+
Style="{StaticResource ToolBarButtonStyle}"
576+
ToolTipService.ToolTip="{helpers:ResourceString Name=UpdateFiles}"
577+
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
578+
<FontIcon FontSize="14" Glyph="&#xE896;" />
579+
</Button>
580+
565581
<Button
566582
x:Name="SettingsButton"
567583
Width="36"

src/Files/ViewModels/NavToolbarViewModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class NavToolbarViewModel : ObservableObject, INavigationToolbar, IDispos
3737
{
3838
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService<IUserSettingsService>();
3939

40+
public IUpdateSettingsService UpdateSettingsService { get; } = Ioc.Default.GetService<IUpdateSettingsService>();
41+
4042
public delegate void ToolbarPathItemInvokedEventHandler(object sender, PathNavigationEventArgs e);
4143

4244
public delegate void ToolbarFlyoutOpenedEventHandler(object sender, ToolbarFlyoutOpenedEventArgs e);
@@ -816,6 +818,8 @@ public void SearchRegion_LostFocus(object sender, RoutedEventArgs e)
816818

817819
public ICommand InstallFontCommand { get; set; }
818820

821+
public ICommand UpdateCommand { get; set; }
822+
819823
public async Task SetPathBoxDropDownFlyoutAsync(MenuFlyout flyout, PathBoxItem pathItem, IShellPage shellPage)
820824
{
821825
var nextPathItemTitle = PathComponents[PathComponents.IndexOf(pathItem) + 1].Title;

src/Files/Views/ColumnShellPage.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public sealed partial class ColumnShellPage : Page, IShellPage, INotifyPropertyC
6262

6363
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService<IUserSettingsService>();
6464

65+
private IUpdateSettingsService UpdateSettingsService { get; } = Ioc.Default.GetService<IUpdateSettingsService>();
66+
6567
public bool IsCurrentInstance
6668
{
6769
get
@@ -228,6 +230,7 @@ private void InitToolbarCommands()
228230
NavToolbarViewModel.RotateImageLeftCommand = new RelayCommand(async () => SlimContentPage?.CommandsViewModel.RotateImageLeftCommand.Execute(null));
229231
NavToolbarViewModel.RotateImageRightCommand = new RelayCommand(async () => SlimContentPage?.CommandsViewModel.RotateImageRightCommand.Execute(null));
230232
NavToolbarViewModel.InstallFontCommand = new RelayCommand(() => SlimContentPage?.CommandsViewModel.InstallFontCommand.Execute(null));
233+
NavToolbarViewModel.UpdateCommand = new AsyncRelayCommand(async () => await UpdateSettingsService.DownloadUpdates());
231234
}
232235

233236
private void FolderSettings_LayoutPreferencesUpdateRequired(object sender, LayoutPreferenceEventArgs e)

src/Files/Views/ModernShellPage.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public sealed partial class ModernShellPage : Page, IShellPage, INotifyPropertyC
5151

5252
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService<IUserSettingsService>();
5353

54+
private IUpdateSettingsService UpdateSettingsService { get; } = Ioc.Default.GetService<IUpdateSettingsService>();
55+
5456
public bool IsCurrentInstance
5557
{
5658
get
@@ -213,6 +215,7 @@ private void InitToolbarCommands()
213215
NavToolbarViewModel.RotateImageLeftCommand = new RelayCommand(async () => SlimContentPage?.CommandsViewModel.RotateImageLeftCommand.Execute(null));
214216
NavToolbarViewModel.RotateImageRightCommand = new RelayCommand(async () => SlimContentPage?.CommandsViewModel.RotateImageRightCommand.Execute(null));
215217
NavToolbarViewModel.InstallFontCommand = new RelayCommand(() => SlimContentPage?.CommandsViewModel.InstallFontCommand.Execute(null));
218+
NavToolbarViewModel.UpdateCommand = new AsyncRelayCommand(async () => await UpdateSettingsService.DownloadUpdates());
216219
}
217220

218221
private void ModernShellPage_RefreshWidgetsRequested(object sender, EventArgs e)

0 commit comments

Comments
 (0)