Skip to content

Commit

Permalink
Check for updates automatically (but don't install) (#13437)
Browse files Browse the repository at this point in the history
This PR adds support to the About Dialog for checking the store to see
if there's a new version of the Terminal package available. We'll only
do this once per day, per terminal window.

In dev mode, we'll always fake it and say there's an update to `x.y.z`
available.

This also involved pulling all of the About dialog code out into its own
class. All that is goodness.

We don't currently provide a button for _installing_ the update. We just
check. Incremental progress is better than none.

Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
  • Loading branch information
3 people authored Apr 6, 2023
1 parent 7fbd3be commit ea44375
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2283,6 +2283,8 @@ xunit
xutr
XVIRTUALSCREEN
XWalk
xwwyzz
xxyyzz
yact
YCast
YCENTER
Expand Down
128 changes: 128 additions & 0 deletions src/cascadia/TerminalApp/AboutDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#include "pch.h"
#include "AboutDialog.h"
#include "AboutDialog.g.cpp"

#include <LibraryResources.h>
#include <WtExeUtils.h>

#include "../../types/inc/utils.hpp"
#include "Utils.h"

using namespace winrt;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal;
using namespace ::TerminalApp;
using namespace std::chrono_literals;

namespace winrt
{
namespace WUX = Windows::UI::Xaml;
using IInspectable = Windows::Foundation::IInspectable;
}

namespace winrt::TerminalApp::implementation
{
AboutDialog::AboutDialog()
{
InitializeComponent();
}

winrt::hstring AboutDialog::ApplicationDisplayName()
{
return CascadiaSettings::ApplicationDisplayName();
}

winrt::hstring AboutDialog::ApplicationVersion()
{
return CascadiaSettings::ApplicationVersion();
}

void AboutDialog::_SendFeedbackOnClick(const IInspectable& /*sender*/, const Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs& /*eventArgs*/)
{
#if defined(WT_BRANDING_RELEASE)
ShellExecute(nullptr, nullptr, L"https://go.microsoft.com/fwlink/?linkid=2125419", nullptr, nullptr, SW_SHOW);
#else
ShellExecute(nullptr, nullptr, L"https://go.microsoft.com/fwlink/?linkid=2204904", nullptr, nullptr, SW_SHOW);
#endif
}

void AboutDialog::_ThirdPartyNoticesOnClick(const IInspectable& /*sender*/, const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
{
std::filesystem::path currentPath{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
currentPath.replace_filename(L"NOTICE.html");
ShellExecute(nullptr, nullptr, currentPath.c_str(), nullptr, nullptr, SW_SHOW);
}

bool AboutDialog::UpdatesAvailable() const
{
return !_pendingUpdateVersion.empty();
}

winrt::hstring AboutDialog::PendingUpdateVersion() const
{
return _pendingUpdateVersion;
}

void AboutDialog::_SetPendingUpdateVersion(const winrt::hstring& version)
{
_pendingUpdateVersion = version;
_PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"PendingUpdateVersion" });
_PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"UpdatesAvailable" });
}

winrt::fire_and_forget AboutDialog::QueueUpdateCheck()
{
auto strongThis = get_strong();
auto now{ std::chrono::system_clock::now() };
if (now - _lastUpdateCheck < std::chrono::days{ 1 })
{
co_return;
}
_lastUpdateCheck = now;

if (!IsPackaged())
{
co_return;
}

co_await wil::resume_foreground(strongThis->Dispatcher());
_SetPendingUpdateVersion({});
CheckingForUpdates(true);

try
{
#ifdef WT_BRANDING_DEV
// **DEV BRANDING**: Always sleep for three seconds and then report that
// there is an update available. This lets us test the system.
co_await winrt::resume_after(std::chrono::seconds{ 3 });
co_await wil::resume_foreground(strongThis->Dispatcher());
_SetPendingUpdateVersion(L"X.Y.Z");
#else // release build, likely has a store context
if (auto storeContext{ winrt::Windows::Services::Store::StoreContext::GetDefault() })
{
const auto updates = co_await storeContext.GetAppAndOptionalStorePackageUpdatesAsync();
co_await wil::resume_foreground(strongThis->Dispatcher());
const auto numUpdates = updates.Size();
if (numUpdates > 0)
{
const auto update = updates.GetAt(0);
const auto version = update.Package().Id().Version();
const auto str = fmt::format(FMT_COMPILE(L"{}.{}.{}"), version.Major, version.Minor, version.Build);
_SetPendingUpdateVersion(winrt::hstring{ str });
}
}
#endif
}
catch (...)
{
// do nothing on failure
}

co_await wil::resume_foreground(strongThis->Dispatcher());
CheckingForUpdates(false);
}
}
40 changes: 40 additions & 0 deletions src/cascadia/TerminalApp/AboutDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once

#include "AboutDialog.g.h"

namespace winrt::TerminalApp::implementation
{
struct AboutDialog : AboutDialogT<AboutDialog>
{
public:
AboutDialog();

winrt::hstring ApplicationDisplayName();
winrt::hstring ApplicationVersion();
bool UpdatesAvailable() const;
winrt::hstring PendingUpdateVersion() const;
winrt::fire_and_forget QueueUpdateCheck();

WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(bool, CheckingForUpdates, _PropertyChangedHandlers, false);

private:
friend struct AboutDialogT<AboutDialog>; // for Xaml to bind events

void _SetPendingUpdateVersion(const winrt::hstring& pendingUpdateVersion);

std::chrono::system_clock::time_point _lastUpdateCheck{};
winrt::hstring _pendingUpdateVersion;

void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _SendFeedbackOnClick(const IInspectable& sender, const Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs& eventArgs);
};
}

namespace winrt::TerminalApp::factory_implementation
{
BASIC_FACTORY(AboutDialog);
}
19 changes: 19 additions & 0 deletions src/cascadia/TerminalApp/AboutDialog.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

namespace TerminalApp
{
[default_interface] runtimeclass AboutDialog : Windows.UI.Xaml.Controls.ContentDialog, Windows.UI.Xaml.Data.INotifyPropertyChanged
{
AboutDialog();

String ApplicationDisplayName { get; };
String ApplicationVersion { get; };

Boolean CheckingForUpdates { get; };
Boolean UpdatesAvailable { get; };
String PendingUpdateVersion { get; };

void QueueUpdateCheck();
}
}
63 changes: 63 additions & 0 deletions src/cascadia/TerminalApp/AboutDialog.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<ContentDialog x:Class="TerminalApp.AboutDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
x:Uid="AboutDialog"
DefaultButton="Close"
PrimaryButtonClick="_SendFeedbackOnClick"
Style="{StaticResource DefaultContentDialogStyle}"
mc:Ignorable="d">

<StackPanel Orientation="Vertical">
<TextBlock IsTextSelectionEnabled="True">
<Run Text="{x:Bind ApplicationDisplayName}" /> <LineBreak />
<Run x:Uid="AboutDialog_VersionLabel" />
<Run Text="{x:Bind ApplicationVersion}" />
</TextBlock>

<StackPanel Orientation="Vertical">
<StackPanel Padding="0,4,0,4"
VerticalAlignment="Center"
Orientation="Horizontal"
Visibility="{x:Bind CheckingForUpdates, Mode=OneWay}">
<mux:ProgressRing Width="16"
Height="16"
IsActive="True"
IsIndeterminate="True" />
<TextBlock x:Uid="AboutDialog_CheckingForUpdatesLabel"
Padding="4,0,0,0" />
</StackPanel>
<StackPanel Padding="0,4,0,4"
VerticalAlignment="Center"
Orientation="Vertical"
Visibility="{x:Bind UpdatesAvailable, Mode=OneWay}">
<TextBlock IsTextSelectionEnabled="False">
<Run x:Uid="AboutDialog_UpdateAvailableLabel" /> <LineBreak />
<Run x:Uid="AboutDialog_VersionLabel" />
<Run Text="{x:Bind PendingUpdateVersion, Mode=OneWay}" />
</TextBlock>
<!-- <Button x:Uid="AboutDialog_InstallUpdateButton"
Margin="0" />-->
</StackPanel>
</StackPanel>

<HyperlinkButton x:Uid="AboutDialog_SourceCodeLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2203152" />
<HyperlinkButton x:Uid="AboutDialog_DocumentationLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125416" />
<HyperlinkButton x:Uid="AboutDialog_ReleaseNotesLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125417" />
<HyperlinkButton x:Uid="AboutDialog_PrivacyPolicyLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125418" />
<HyperlinkButton x:Uid="AboutDialog_ThirdPartyNoticesLink"
Click="_ThirdPartyNoticesOnClick" />
</StackPanel>
</ContentDialog>

12 changes: 12 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,18 @@
<value>Suggestions found: {0}</value>
<comment>{0} will be replaced with a number.</comment>
</data>
<data name="AboutDialog_CheckingForUpdatesLabel.Text" xml:space="preserve">
<value>Checking for updates...</value>
<comment></comment>
</data>
<data name="AboutDialog_UpdateAvailableLabel.Text" xml:space="preserve">
<value>An update is available.</value>
<comment></comment>
</data>
<data name="AboutDialog_InstallUpdateButton.Content" xml:space="preserve">
<value>Install now</value>
<comment></comment>
</data>
<data name="DuplicateRemainingProfilesEntry" xml:space="preserve">
<value>The "newTabMenu" field contains more than one entry of type "remainingProfiles". Only the first one will be considered.</value>
<comment>{Locked="newTabMenu"} {Locked="remainingProfiles"}</comment>
Expand Down
12 changes: 12 additions & 0 deletions src/cascadia/TerminalApp/TerminalAppLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
</ItemGroup>
<!-- When we add other user controls, they should go in here as so: -->
<ItemGroup>
<Page Include="AboutDialog.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="MinMaxCloseControl.xaml">
<SubType>Designer</SubType>
</Page>
Expand Down Expand Up @@ -132,6 +135,9 @@
<ClInclude Include="AppKeyBindings.h">
<DependentUpon>AppKeyBindings.idl</DependentUpon>
</ClInclude>
<ClInclude Include="AboutDialog.h">
<DependentUpon>AboutDialog.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="App.h">
<DependentUpon>App.xaml</DependentUpon>
</ClInclude>
Expand Down Expand Up @@ -231,6 +237,9 @@
<ClCompile Include="ShortcutActionDispatch.cpp">
<DependentUpon>ShortcutActionDispatch.idl</DependentUpon>
</ClCompile>
<ClCompile Include="AboutDialog.cpp">
<DependentUpon>AboutDialog.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="App.cpp">
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
Expand All @@ -256,6 +265,9 @@
<Midl Include="ActionPaletteItem.idl" />
<Midl Include="CommandLinePaletteItem.idl" />
<Midl Include="IDirectKeyListener.idl" />
<Midl Include="AboutDialog.idl">
<DependentUpon>AboutDialog.xaml</DependentUpon>
</Midl>
<Midl Include="App.idl">
<DependentUpon>App.xaml</DependentUpon>
</Midl>
Expand Down
17 changes: 1 addition & 16 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ namespace winrt::TerminalApp::implementation
// Notes link, send feedback link and privacy policy link.
void TerminalPage::_ShowAboutDialog()
{
AboutDialog().QueueUpdateCheck();
_ShowDialogHelper(L"AboutDialog");
}

Expand All @@ -698,22 +699,6 @@ namespace winrt::TerminalApp::implementation
return CascadiaSettings::ApplicationVersion();
}

void TerminalPage::_SendFeedbackOnClick(const IInspectable& /*sender*/, const Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs& /*eventArgs*/)
{
#if defined(WT_BRANDING_RELEASE)
ShellExecute(nullptr, nullptr, L"https://go.microsoft.com/fwlink/?linkid=2125419", nullptr, nullptr, SW_SHOW);
#else
ShellExecute(nullptr, nullptr, L"https://go.microsoft.com/fwlink/?linkid=2204904", nullptr, nullptr, SW_SHOW);
#endif
}

void TerminalPage::_ThirdPartyNoticesOnClick(const IInspectable& /*sender*/, const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
{
std::filesystem::path currentPath{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
currentPath.replace_filename(L"NOTICE.html");
ShellExecute(nullptr, nullptr, currentPath.c_str(), nullptr, nullptr, SW_SHOW);
}

// Method Description:
// - Helper to show a content dialog
// - We only open a content dialog if there isn't one open already
Expand Down
2 changes: 0 additions & 2 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,6 @@ namespace winrt::TerminalApp::implementation
void _SettingsButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _CommandPaletteButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _AboutButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _SendFeedbackOnClick(const IInspectable& sender, const Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs& eventArgs);

void _KeyDownHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
Expand Down
26 changes: 2 additions & 24 deletions src/cascadia/TerminalApp/TerminalPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,30 +96,8 @@
just this weird hole that appeared in Row 0.
-->

<ContentDialog x:Name="AboutDialog"
x:Uid="AboutDialog"
Grid.Row="2"
x:Load="False"
DefaultButton="Close"
PrimaryButtonClick="_SendFeedbackOnClick">
<StackPanel Orientation="Vertical">
<TextBlock IsTextSelectionEnabled="True">
<Run Text="{x:Bind ApplicationDisplayName}" /> <LineBreak />
<Run x:Uid="AboutDialog_VersionLabel" />
<Run Text="{x:Bind ApplicationVersion}" />
</TextBlock>
<HyperlinkButton x:Uid="AboutDialog_SourceCodeLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2203152" />
<HyperlinkButton x:Uid="AboutDialog_DocumentationLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125416" />
<HyperlinkButton x:Uid="AboutDialog_ReleaseNotesLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125417" />
<HyperlinkButton x:Uid="AboutDialog_PrivacyPolicyLink"
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125418" />
<HyperlinkButton x:Uid="AboutDialog_ThirdPartyNoticesLink"
Click="_ThirdPartyNoticesOnClick" />
</StackPanel>
</ContentDialog>
<local:AboutDialog x:Name="AboutDialog"
Grid.Row="2" />

<ContentDialog x:Name="QuitDialog"
x:Uid="QuitDialog"
Expand Down
Loading

0 comments on commit ea44375

Please sign in to comment.