diff --git a/src/modules/peek/Peek.UI/Helpers/DefaultAppHelper.cs b/src/modules/peek/Peek.UI/Helpers/DefaultAppHelper.cs
new file mode 100644
index 000000000000..1064a86d2751
--- /dev/null
+++ b/src/modules/peek/Peek.UI/Helpers/DefaultAppHelper.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+using Peek.Common.Models;
+using Peek.UI.Native;
+
+namespace Peek.UI.Helpers
+{
+ public static class DefaultAppHelper
+ {
+ public static string TryGetDefaultAppName(string extension)
+ {
+ string appName = string.Empty;
+
+ // Get the length of the app name
+ uint length = 0;
+ HResult ret = NativeMethods.AssocQueryString(NativeMethods.AssocF.Verify, NativeMethods.AssocStr.FriendlyAppName, extension, null, null, ref length);
+ if (ret != HResult.False)
+ {
+ Debug.WriteLine($"Error when getting accessString for {extension} file: {Marshal.GetExceptionForHR((int)ret)!.Message}");
+ return appName;
+ }
+
+ // Get the the app name
+ StringBuilder sb = new ((int)length);
+ ret = NativeMethods.AssocQueryString(NativeMethods.AssocF.Verify, NativeMethods.AssocStr.FriendlyAppName, extension, null, sb, ref length);
+ if (ret != HResult.Ok)
+ {
+ Debug.WriteLine($"Error when getting accessString for {extension} file: {Marshal.GetExceptionForHR((int)ret)!.Message}" );
+ return appName;
+ }
+
+ appName = sb.ToString();
+ return appName;
+ }
+ }
+}
diff --git a/src/modules/peek/Peek.UI/MainWindow.xaml b/src/modules/peek/Peek.UI/MainWindow.xaml
index 437c141fa8e3..45ceb78a3585 100644
--- a/src/modules/peek/Peek.UI/MainWindow.xaml
+++ b/src/modules/peek/Peek.UI/MainWindow.xaml
@@ -22,11 +22,15 @@
-
+
-
+
Peek
+ Name of application.
-
- Peek
+
+ ({0}/{1} files)
+ Text for the file count in the titlebar. 0: the index of the current file. 1: the total number of files selected.
+
+
+ Open with
+ Text for button to launch the application picker.
+
+
+ Open with (Enter)
+ Tooltip for button to launch the application picker.
+
+
+ Open with {0}
+ Text for button to launch default application. 0: name of the default application.
+
+
+ Open with {0} (Enter)
+ Tooltip for button to launch default application. 0: name of the default application.
\ No newline at end of file
diff --git a/src/modules/peek/Peek.UI/Views/TitleBar.xaml b/src/modules/peek/Peek.UI/Views/TitleBar.xaml
index 51fb817eb5a0..4e3239446fec 100644
--- a/src/modules/peek/Peek.UI/Views/TitleBar.xaml
+++ b/src/modules/peek/Peek.UI/Views/TitleBar.xaml
@@ -10,16 +10,126 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
-
+
+
+
+
+
+
-
+
+
+
+ x:Name="AppTitle_FileCount"
+ x:Uid="AppTitle_FileCount"
+ Margin="4,0,0,0"
+ VerticalAlignment="Center"
+ FontWeight="Bold"
+ Style="{StaticResource CaptionTextBlockStyle}"
+ Text="{x:Bind FileCountText, Mode=OneWay}"
+ Visibility="Collapsed" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/peek/Peek.UI/Views/TitleBar.xaml.cs b/src/modules/peek/Peek.UI/Views/TitleBar.xaml.cs
index 9574efdf76ee..04102ae2deca 100644
--- a/src/modules/peek/Peek.UI/Views/TitleBar.xaml.cs
+++ b/src/modules/peek/Peek.UI/Views/TitleBar.xaml.cs
@@ -5,34 +5,76 @@
namespace Peek.UI.Views
{
using System;
+ using CommunityToolkit.Mvvm.ComponentModel;
+ using CommunityToolkit.Mvvm.Input;
using ManagedCommon;
using Microsoft.UI;
using Microsoft.UI.Windowing;
+ using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
+ using Peek.Common.Models;
+ using Peek.UI.Helpers;
+ using Windows.ApplicationModel.Resources;
+ using Windows.Storage;
+ using Windows.System;
using WinUIEx;
- using MUX = Microsoft.UI.Xaml;
+ [INotifyPropertyChanged]
public sealed partial class TitleBar : UserControl
{
+ public static readonly DependencyProperty FileProperty =
+ DependencyProperty.Register(
+ nameof(File),
+ typeof(File),
+ typeof(TitleBar),
+ new PropertyMetadata(null, (d, e) => ((TitleBar)d).OnFilePropertyChanged()));
+
+ public static readonly DependencyProperty NumberOfFilesProperty =
+ DependencyProperty.Register(
+ nameof(NumberOfFiles),
+ typeof(int),
+ typeof(TitleBar),
+ new PropertyMetadata(null, null));
+
+ private string? defaultAppName;
+
+ [ObservableProperty]
+ private string openWithAppText = ResourceLoader.GetForViewIndependentUse().GetString("LaunchAppButton_OpenWith_Text");
+
+ [ObservableProperty]
+ private string openWithAppToolTip = ResourceLoader.GetForViewIndependentUse().GetString("LaunchAppButton_OpenWith_ToolTip");
+
+ [ObservableProperty]
+ private string? fileCountText;
+
public TitleBar()
{
InitializeComponent();
}
- public void SetToWindow(MainWindow mainWindow)
+ public File File
+ {
+ get => (File)GetValue(FileProperty);
+ set => SetValue(FileProperty, value);
+ }
+
+ public int NumberOfFiles
+ {
+ get => (int)GetValue(NumberOfFilesProperty);
+ set => SetValue(NumberOfFilesProperty, value);
+ }
+
+ public void SetTitleBarToWindow(MainWindow mainWindow)
{
if (AppWindowTitleBar.IsCustomizationSupported())
{
- AppWindow window = mainWindow.GetAppWindow();
- window.TitleBar.ExtendsContentIntoTitleBar = true;
- window.TitleBar.ButtonBackgroundColor = Colors.Transparent;
- mainWindow.SetTitleBar(this);
+ UpdateTitleBarCustomization(mainWindow);
}
else
{
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
ThemeHelpers.SetImmersiveDarkMode(hWnd, ThemeHelpers.GetAppTheme() == AppTheme.Dark);
- Visibility = MUX.Visibility.Collapsed;
+ Visibility = Visibility.Collapsed;
// Set window icon
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
@@ -40,5 +82,77 @@ public void SetToWindow(MainWindow mainWindow)
appWindow.SetIcon("Assets/Icon.ico");
}
}
+
+ private void UpdateTitleBarCustomization(MainWindow mainWindow)
+ {
+ if (AppWindowTitleBar.IsCustomizationSupported())
+ {
+ AppWindow appWindow = mainWindow.GetAppWindow();
+ appWindow.TitleBar.ExtendsContentIntoTitleBar = true;
+ appWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
+ appWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
+ appWindow.TitleBar.SetDragRectangles(new Windows.Graphics.RectInt32[]
+ {
+ new Windows.Graphics.RectInt32(0, 0, (int)TitleBarRootContainer.ActualWidth, (int)TitleBarRootContainer.ActualHeight),
+ });
+
+ mainWindow.SetTitleBar(this);
+ }
+ }
+
+ private void OnFilePropertyChanged()
+ {
+ UpdateFileCountText();
+ UpdateDefaultAppToLaunch();
+ }
+
+ private void UpdateFileCountText()
+ {
+ // Update file count
+ if (NumberOfFiles > 1)
+ {
+ // TODO: Update the hardcoded fileIndex when the NFQ PR gets merged
+ int currentFileIndex = 1;
+ string fileCountTextFormat = ResourceLoader.GetForViewIndependentUse().GetString("AppTitle_FileCounts_Text");
+ FileCountText = string.Format(fileCountTextFormat, currentFileIndex, NumberOfFiles);
+ }
+ }
+
+ private void UpdateDefaultAppToLaunch()
+ {
+ // Update the name of default app to launch
+ defaultAppName = DefaultAppHelper.TryGetDefaultAppName(File.Extension);
+
+ string openWithAppTextFormat = ResourceLoader.GetForViewIndependentUse().GetString("LaunchAppButton_OpenWithApp_Text");
+ OpenWithAppText = string.Format(openWithAppTextFormat, defaultAppName);
+
+ string openWithAppToolTipFormat = ResourceLoader.GetForViewIndependentUse().GetString("LaunchAppButton_OpenWithApp_ToolTip");
+ OpenWithAppToolTip = string.Format(openWithAppToolTipFormat, defaultAppName);
+ }
+
+ [RelayCommand]
+ private async void LaunchDefaultAppButtonAsync()
+ {
+ StorageFile storageFile = await File.GetStorageFileAsync();
+ LauncherOptions options = new ();
+
+ if (string.IsNullOrEmpty(defaultAppName))
+ {
+ // If there's no default app found, open the App picker
+ options.DisplayApplicationPicker = true;
+ }
+ else
+ {
+ // Try to launch the default app for current file format
+ bool result = await Launcher.LaunchFileAsync(storageFile, options);
+
+ if (!result)
+ {
+ // If we couldn't successfully open the default app, open the App picker as a fallback
+ options.DisplayApplicationPicker = true;
+ await Launcher.LaunchFileAsync(storageFile, options);
+ }
+ }
+ }
}
}