mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
Yizzho/peek/videos (#25983)
* Add basics of VideoPreviewer to build on * WIP * Minimal working code, todo next:dimension + MTC * Nits * Change back to GetImageSize as it indeed doesn't work with videos * Add win32 helper methods to get video size; Refactor get size operation; * Remove unused code * Set VideoTask; Add message error for HR result; * Add open read only for filestream * Remove unused code * Update expect.txt * Remove comment * Cleanup code * Force pause videopreview on previewer change --------- Co-authored-by: Jojo Zhou <yizzho@microsoft.com> Co-authored-by: Yawen Hou <yawenhou@microsoft.com> Co-authored-by: Clint Rutkas <clint@rutkas.com> Co-authored-by: Yawen Hou <Sytta@users.noreply.github.com> Co-authored-by: Samuel Chapleau 🌈 <sachaple@microsoft.com>
This commit is contained in:
11
.github/actions/spell-check/expect.txt
vendored
11
.github/actions/spell-check/expect.txt
vendored
@@ -113,6 +113,7 @@ arsinh
|
|||||||
artanh
|
artanh
|
||||||
arw
|
arw
|
||||||
asdf
|
asdf
|
||||||
|
asf
|
||||||
AShortcut
|
AShortcut
|
||||||
ASingle
|
ASingle
|
||||||
ASSOCCHANGED
|
ASSOCCHANGED
|
||||||
@@ -225,8 +226,8 @@ bytearray
|
|||||||
CABD
|
CABD
|
||||||
CALG
|
CALG
|
||||||
callbackptr
|
callbackptr
|
||||||
cameligo
|
|
||||||
calpwstr
|
calpwstr
|
||||||
|
cameligo
|
||||||
Cangjie
|
Cangjie
|
||||||
CANRENAME
|
CANRENAME
|
||||||
CAPTUREBLT
|
CAPTUREBLT
|
||||||
@@ -771,6 +772,7 @@ google
|
|||||||
gpedit
|
gpedit
|
||||||
gpo
|
gpo
|
||||||
GPOCA
|
GPOCA
|
||||||
|
gpp
|
||||||
GPT
|
GPT
|
||||||
gpu
|
gpu
|
||||||
graphql
|
graphql
|
||||||
@@ -1121,13 +1123,13 @@ LPCTSTR
|
|||||||
LPCWSTR
|
LPCWSTR
|
||||||
lpdw
|
lpdw
|
||||||
lpfn
|
lpfn
|
||||||
lpmi
|
|
||||||
LPINPUT
|
LPINPUT
|
||||||
|
lpmi
|
||||||
LPMINMAXINFO
|
LPMINMAXINFO
|
||||||
LPMONITORINFO
|
LPMONITORINFO
|
||||||
LPOSVERSIONINFOEXW
|
LPOSVERSIONINFOEXW
|
||||||
lprc
|
|
||||||
LPPOINT
|
LPPOINT
|
||||||
|
lprc
|
||||||
LPRECT
|
LPRECT
|
||||||
LPSAFEARRAY
|
LPSAFEARRAY
|
||||||
LPSTR
|
LPSTR
|
||||||
@@ -1230,6 +1232,7 @@ Miracast
|
|||||||
mjpg
|
mjpg
|
||||||
mkd
|
mkd
|
||||||
mkdn
|
mkdn
|
||||||
|
mkv
|
||||||
mlcfg
|
mlcfg
|
||||||
mmc
|
mmc
|
||||||
mmcexe
|
mmcexe
|
||||||
@@ -1511,7 +1514,6 @@ pft
|
|||||||
pgp
|
pgp
|
||||||
pgsql
|
pgsql
|
||||||
pguid
|
pguid
|
||||||
pkey
|
|
||||||
PHANDLE
|
PHANDLE
|
||||||
phbm
|
phbm
|
||||||
phbmp
|
phbmp
|
||||||
@@ -1525,6 +1527,7 @@ pinfo
|
|||||||
pinvoke
|
pinvoke
|
||||||
pipename
|
pipename
|
||||||
PKBDLLHOOKSTRUCT
|
PKBDLLHOOKSTRUCT
|
||||||
|
pkey
|
||||||
PKEY
|
PKEY
|
||||||
plib
|
plib
|
||||||
PLK
|
PLK
|
||||||
|
|||||||
@@ -33,5 +33,29 @@ namespace Peek.Common.Extensions
|
|||||||
|
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Run work on UI thread safely.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the work was run successfully, False otherwise.</returns>
|
||||||
|
public static Task RunOnUiThread(this DispatcherQueue dispatcher, Action work)
|
||||||
|
{
|
||||||
|
var tcs = new TaskCompletionSource();
|
||||||
|
dispatcher.TryEnqueue(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
work();
|
||||||
|
|
||||||
|
tcs.SetResult();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
tcs.SetException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tcs.Task;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.IO;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using Peek.Common.Helpers;
|
||||||
using Peek.Common.Models;
|
using Peek.Common.Models;
|
||||||
using Scripting;
|
using Scripting;
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
@@ -19,17 +20,12 @@ namespace Peek.Common.Extensions
|
|||||||
{
|
{
|
||||||
public static Size? GetImageSize(this IFileSystemItem item)
|
public static Size? GetImageSize(this IFileSystemItem item)
|
||||||
{
|
{
|
||||||
Size? size = null;
|
return PropertyStoreHelper.TryGetUintSizeProperty(item.Path, PropertyKey.ImageHorizontalSize, PropertyKey.ImageVerticalSize);
|
||||||
|
|
||||||
var width = item.Width;
|
|
||||||
var height = item.Height;
|
|
||||||
|
|
||||||
if (width != null && height != null)
|
|
||||||
{
|
|
||||||
size = new Size((int)width, (int)height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
public static Size? GetVideoSize(this IFileSystemItem item)
|
||||||
|
{
|
||||||
|
return PropertyStoreHelper.TryGetUintSizeProperty(item.Path, PropertyKey.FrameWidth, PropertyKey.FrameHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Size? GetSvgSize(this IFileSystemItem item)
|
public static Size? GetSvgSize(this IFileSystemItem item)
|
||||||
|
|||||||
@@ -7,24 +7,13 @@ using System.Globalization;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Peek.Common.Extensions;
|
using Peek.Common.Extensions;
|
||||||
using Peek.Common.Models;
|
using Peek.Common.Models;
|
||||||
|
using Windows.Foundation;
|
||||||
using Windows.Win32.UI.Shell.PropertiesSystem;
|
using Windows.Win32.UI.Shell.PropertiesSystem;
|
||||||
|
|
||||||
namespace Peek.Common.Helpers
|
namespace Peek.Common.Helpers
|
||||||
{
|
{
|
||||||
public static partial class PropertyStoreHelper
|
public static partial class PropertyStoreHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets a uint type value from PropertyStore from the given item.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file/folder path</param>
|
|
||||||
/// <param name="key">The property key</param>
|
|
||||||
/// <returns>a nullable uint</returns>
|
|
||||||
public static uint? TryGetUintProperty(string path, PropertyKey key)
|
|
||||||
{
|
|
||||||
using DisposablePropertyStore propertyStore = GetPropertyStoreFromPath(path);
|
|
||||||
return propertyStore.TryGetUInt(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a ulong type value from PropertyStore from the given item.
|
/// Gets a ulong type value from PropertyStore from the given item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -49,6 +38,28 @@ namespace Peek.Common.Helpers
|
|||||||
return propertyStore.TryGetString(key);
|
return propertyStore.TryGetString(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets Size composed of weight (uint) and height (uint) from PropertyStore from the given item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file/folder path</param>
|
||||||
|
/// <param name="widthKey">The property key for width</param>
|
||||||
|
/// <param name="heightKey">The property key for height</param>
|
||||||
|
/// <returns>a nullable string</returns>
|
||||||
|
public static Size? TryGetUintSizeProperty(string path, PropertyKey widthKey, PropertyKey heightKey)
|
||||||
|
{
|
||||||
|
Size? size = null;
|
||||||
|
using DisposablePropertyStore propertyStore = GetPropertyStoreFromPath(path);
|
||||||
|
uint? width = propertyStore.TryGetUInt(widthKey);
|
||||||
|
uint? height = propertyStore.TryGetUInt(heightKey);
|
||||||
|
|
||||||
|
if (width != null && height != null)
|
||||||
|
{
|
||||||
|
size = new Size((float)width, (float)height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a IPropertyStore interface (wrapped in DisposablePropertyStore) from the given path.
|
/// Gets a IPropertyStore interface (wrapped in DisposablePropertyStore) from the given path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -73,7 +84,7 @@ namespace Peek.Common.Helpers
|
|||||||
|
|
||||||
if (hr != 0)
|
if (hr != 0)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "GetPropertyStore returned hresult={0}", hr));
|
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "GetPropertyStore returned hresult={0}, errorMessage={1}", hr, Marshal.GetExceptionForHR(hr)!.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DisposablePropertyStore((IPropertyStore)Marshal.GetObjectForIUnknown(ppPropertyStore));
|
return new DisposablePropertyStore((IPropertyStore)Marshal.GetObjectForIUnknown(ppPropertyStore));
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Peek.Common.Extensions;
|
|
||||||
using Peek.Common.Helpers;
|
using Peek.Common.Helpers;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
|
|
||||||
@@ -39,10 +38,6 @@ namespace Peek.Common.Models
|
|||||||
|
|
||||||
public string Path { get; init; }
|
public string Path { get; init; }
|
||||||
|
|
||||||
public uint? Width => PropertyStoreHelper.TryGetUintProperty(Path, PropertyKey.ImageHorizontalSize);
|
|
||||||
|
|
||||||
public uint? Height => PropertyStoreHelper.TryGetUintProperty(Path, PropertyKey.ImageVerticalSize);
|
|
||||||
|
|
||||||
public ulong FileSizeBytes => PropertyStoreHelper.TryGetUlongProperty(Path, PropertyKey.FileSizeBytes) ?? 0;
|
public ulong FileSizeBytes => PropertyStoreHelper.TryGetUlongProperty(Path, PropertyKey.FileSizeBytes) ?? 0;
|
||||||
|
|
||||||
public string FileType => PropertyStoreHelper.TryGetStringProperty(Path, PropertyKey.FileType) ?? string.Empty;
|
public string FileType => PropertyStoreHelper.TryGetStringProperty(Path, PropertyKey.FileType) ?? string.Empty;
|
||||||
|
|||||||
@@ -61,5 +61,7 @@ namespace Peek.Common.Models
|
|||||||
public static readonly PropertyKey ImageVerticalSize = new PropertyKey(new Guid(0x6444048F, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03), 4);
|
public static readonly PropertyKey ImageVerticalSize = new PropertyKey(new Guid(0x6444048F, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03), 4);
|
||||||
public static readonly PropertyKey FileSizeBytes = new PropertyKey(new Guid(0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac), 12);
|
public static readonly PropertyKey FileSizeBytes = new PropertyKey(new Guid(0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac), 12);
|
||||||
public static readonly PropertyKey FileType = new PropertyKey(new Guid(0xd5cdd502, 0x2e9c, 0x101b, 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae), 26);
|
public static readonly PropertyKey FileType = new PropertyKey(new Guid(0xd5cdd502, 0x2e9c, 0x101b, 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae), 26);
|
||||||
|
public static readonly PropertyKey FrameWidth = new PropertyKey(new Guid(0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03), 3);
|
||||||
|
public static readonly PropertyKey FrameHeight = new PropertyKey(new Guid(0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03), 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,22 @@
|
|||||||
ToolTipService.ToolTip="{x:Bind ImageInfoTooltip, Mode=OneWay}"
|
ToolTipService.ToolTip="{x:Bind ImageInfoTooltip, Mode=OneWay}"
|
||||||
Visibility="{x:Bind IsPreviewVisible(ImagePreviewer, Previewer.State), Mode=OneWay}" />
|
Visibility="{x:Bind IsPreviewVisible(ImagePreviewer, Previewer.State), Mode=OneWay}" />
|
||||||
|
|
||||||
|
<MediaPlayerElement
|
||||||
|
x:Name="VideoPreview"
|
||||||
|
AreTransportControlsEnabled="True"
|
||||||
|
AutoPlay="True"
|
||||||
|
Source="{x:Bind VideoPreviewer.Preview, Mode=OneWay}"
|
||||||
|
ToolTipService.ToolTip="{x:Bind ImageInfoTooltip, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind IsPreviewVisible(VideoPreviewer, Previewer.State), Mode=OneWay}">
|
||||||
|
<MediaPlayerElement.TransportControls>
|
||||||
|
<MediaTransportControls
|
||||||
|
x:Name="mediaTransport"
|
||||||
|
Width="auto"
|
||||||
|
MaxWidth="420"
|
||||||
|
IsCompact="True" />
|
||||||
|
</MediaPlayerElement.TransportControls>
|
||||||
|
</MediaPlayerElement>
|
||||||
|
|
||||||
<controls:BrowserControl
|
<controls:BrowserControl
|
||||||
x:Name="BrowserPreview"
|
x:Name="BrowserPreview"
|
||||||
x:Load="True"
|
x:Load="True"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace Peek.FilePreviewer
|
|||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[NotifyPropertyChangedFor(nameof(ImagePreviewer))]
|
[NotifyPropertyChangedFor(nameof(ImagePreviewer))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(VideoPreviewer))]
|
||||||
[NotifyPropertyChangedFor(nameof(BrowserPreviewer))]
|
[NotifyPropertyChangedFor(nameof(BrowserPreviewer))]
|
||||||
[NotifyPropertyChangedFor(nameof(UnsupportedFilePreviewer))]
|
[NotifyPropertyChangedFor(nameof(UnsupportedFilePreviewer))]
|
||||||
|
|
||||||
@@ -89,6 +90,8 @@ namespace Peek.FilePreviewer
|
|||||||
|
|
||||||
public IImagePreviewer? ImagePreviewer => Previewer as IImagePreviewer;
|
public IImagePreviewer? ImagePreviewer => Previewer as IImagePreviewer;
|
||||||
|
|
||||||
|
public IVideoPreviewer? VideoPreviewer => Previewer as IVideoPreviewer;
|
||||||
|
|
||||||
public IBrowserPreviewer? BrowserPreviewer => Previewer as IBrowserPreviewer;
|
public IBrowserPreviewer? BrowserPreviewer => Previewer as IBrowserPreviewer;
|
||||||
|
|
||||||
public IUnsupportedFilePreviewer? UnsupportedFilePreviewer => Previewer as IUnsupportedFilePreviewer;
|
public IUnsupportedFilePreviewer? UnsupportedFilePreviewer => Previewer as IUnsupportedFilePreviewer;
|
||||||
@@ -140,6 +143,7 @@ namespace Peek.FilePreviewer
|
|||||||
{
|
{
|
||||||
Previewer = null;
|
Previewer = null;
|
||||||
ImagePreview.Visibility = Visibility.Collapsed;
|
ImagePreview.Visibility = Visibility.Collapsed;
|
||||||
|
VideoPreview.Visibility = Visibility.Collapsed;
|
||||||
BrowserPreview.Visibility = Visibility.Collapsed;
|
BrowserPreview.Visibility = Visibility.Collapsed;
|
||||||
UnsupportedFilePreview.Visibility = Visibility.Collapsed;
|
UnsupportedFilePreview.Visibility = Visibility.Collapsed;
|
||||||
return;
|
return;
|
||||||
@@ -199,6 +203,8 @@ namespace Peek.FilePreviewer
|
|||||||
|
|
||||||
partial void OnPreviewerChanging(IPreviewer? value)
|
partial void OnPreviewerChanging(IPreviewer? value)
|
||||||
{
|
{
|
||||||
|
VideoPreview.MediaPlayer.Pause();
|
||||||
|
|
||||||
if (Previewer != null)
|
if (Previewer != null)
|
||||||
{
|
{
|
||||||
Previewer.PropertyChanged -= Previewer_PropertyChanged;
|
Previewer.PropertyChanged -= Previewer_PropertyChanged;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// 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 Windows.Media.Core;
|
||||||
|
|
||||||
|
namespace Peek.FilePreviewer.Previewers.Interfaces
|
||||||
|
{
|
||||||
|
public interface IVideoPreviewer : IPreviewer
|
||||||
|
{
|
||||||
|
public MediaSource? Preview { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
|
using Microsoft.UI.Dispatching;
|
||||||
|
using Peek.Common.Extensions;
|
||||||
|
using Peek.Common.Helpers;
|
||||||
|
using Peek.Common.Models;
|
||||||
|
using Peek.FilePreviewer.Previewers.Interfaces;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Media.Core;
|
||||||
|
using Windows.Storage;
|
||||||
|
|
||||||
|
namespace Peek.FilePreviewer.Previewers
|
||||||
|
{
|
||||||
|
public partial class VideoPreviewer : ObservableObject, IVideoPreviewer, IDisposable
|
||||||
|
{
|
||||||
|
[ObservableProperty]
|
||||||
|
private MediaSource? preview;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private PreviewState state;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private Size videoSize;
|
||||||
|
|
||||||
|
public VideoPreviewer(IFileSystemItem file)
|
||||||
|
{
|
||||||
|
Item = file;
|
||||||
|
Dispatcher = DispatcherQueue.GetForCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IFileSystemItem Item { get; }
|
||||||
|
|
||||||
|
private DispatcherQueue Dispatcher { get; }
|
||||||
|
|
||||||
|
private Task<bool>? VideoTask { get; set; }
|
||||||
|
|
||||||
|
public static bool IsFileTypeSupported(string fileExt)
|
||||||
|
{
|
||||||
|
return _supportedFileTypes.Contains(fileExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadPreviewAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
State = PreviewState.Loading;
|
||||||
|
VideoTask = LoadVideoAsync(cancellationToken);
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
await VideoTask;
|
||||||
|
|
||||||
|
if (Preview == null && HasFailedLoadingPreview())
|
||||||
|
{
|
||||||
|
State = PreviewState.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnPreviewChanged(MediaSource? value)
|
||||||
|
{
|
||||||
|
if (Preview != null)
|
||||||
|
{
|
||||||
|
State = PreviewState.Loaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Size?> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
return await Task.Run(Item.GetVideoSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CopyAsync()
|
||||||
|
{
|
||||||
|
await Dispatcher.RunOnUiThread(async () =>
|
||||||
|
{
|
||||||
|
var storageItem = await Item.GetStorageItemAsync();
|
||||||
|
ClipboardHelper.SaveToClipboard(storageItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<bool> LoadVideoAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return TaskExtension.RunSafe(async () =>
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var storageFile = await Item.GetStorageItemAsync() as StorageFile;
|
||||||
|
|
||||||
|
await Dispatcher.RunOnUiThread(() =>
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
Preview = MediaSource.CreateFromStorageFile(storageFile);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasFailedLoadingPreview()
|
||||||
|
{
|
||||||
|
return !(VideoTask?.Result ?? true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly HashSet<string> _supportedFileTypes = new()
|
||||||
|
{
|
||||||
|
".mp4", ".3g2", ".3gp", ".3gp2", ".3gpp", ".asf", ".avi", ".m2t", ".m2ts",
|
||||||
|
".m4v", ".mkv", ".mov", ".mp4", ".mp4v", ".mts", ".wm", ".wmv",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,10 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
{
|
{
|
||||||
return new ImagePreviewer(file);
|
return new ImagePreviewer(file);
|
||||||
}
|
}
|
||||||
|
else if (VideoPreviewer.IsFileTypeSupported(file.Extension))
|
||||||
|
{
|
||||||
|
return new VideoPreviewer(file);
|
||||||
|
}
|
||||||
else if (WebBrowserPreviewer.IsFileTypeSupported(file.Extension))
|
else if (WebBrowserPreviewer.IsFileTypeSupported(file.Extension))
|
||||||
{
|
{
|
||||||
return new WebBrowserPreviewer(file);
|
return new WebBrowserPreviewer(file);
|
||||||
|
|||||||
Reference in New Issue
Block a user