mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-13 21:24:25 +00:00
Check for updates automatically (but don't install) (#13437)
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>
This commit is contained in:
2
.github/actions/spelling/expect/expect.txt
vendored
2
.github/actions/spelling/expect/expect.txt
vendored
@@ -2283,6 +2283,8 @@ xunit
|
||||
xutr
|
||||
XVIRTUALSCREEN
|
||||
XWalk
|
||||
xwwyzz
|
||||
xxyyzz
|
||||
yact
|
||||
YCast
|
||||
YCENTER
|
||||
|
||||
128
src/cascadia/TerminalApp/AboutDialog.cpp
Normal file
128
src/cascadia/TerminalApp/AboutDialog.cpp
Normal file
@@ -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
src/cascadia/TerminalApp/AboutDialog.h
Normal file
40
src/cascadia/TerminalApp/AboutDialog.h
Normal file
@@ -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
src/cascadia/TerminalApp/AboutDialog.idl
Normal file
19
src/cascadia/TerminalApp/AboutDialog.idl
Normal file
@@ -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
src/cascadia/TerminalApp/AboutDialog.xaml
Normal file
63
src/cascadia/TerminalApp/AboutDialog.xaml
Normal file
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
||||
#include <winrt/Microsoft.Terminal.Settings.Editor.h>
|
||||
#include <winrt/Microsoft.Terminal.Settings.Model.h>
|
||||
#include <winrt/Windows.Services.Store.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
#include <winrt/Windows.Storage.Provider.h>
|
||||
#include <winrt/Windows.Storage.Pickers.h>
|
||||
|
||||
Reference in New Issue
Block a user