Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for updates automatically (but don't install) #13437

Merged
merged 12 commits into from
Apr 6, 2023
Merged
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 @@ -656,6 +656,7 @@ namespace winrt::TerminalApp::implementation
// Notes link, send feedback link and privacy policy link.
void TerminalPage::_ShowAboutDialog()
{
AboutDialog().QueueUpdateCheck();
_ShowDialogHelper(L"AboutDialog");
}

Expand All @@ -669,22 +670,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