From 971c7a840fcf642c4ef5aa41adbe54cabeaa0ea1 Mon Sep 17 00:00:00 2001 From: Jojo Zhou Date: Tue, 9 May 2023 18:54:57 -0400 Subject: [PATCH] WIP --- .../peek/Peek.FilePreviewer/FilePreview.xaml | 7 +- .../Peek.FilePreviewer/FilePreview.xaml.cs | 4 + .../Previewers/Interfaces/IVideoPreviewer.cs | 13 +++ .../MediaPreviewer/VideoPreviewer.cs | 107 ++++++++++++++++++ .../Previewers/PreviewerFactory.cs | 4 + 5 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IVideoPreviewer.cs create mode 100644 src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs diff --git a/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml b/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml index 761d02db2c..b68ca7a709 100644 --- a/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml +++ b/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml @@ -26,15 +26,12 @@ ToolTipService.ToolTip="{x:Bind ImageInfoTooltip, Mode=OneWay}" Visibility="{x:Bind IsPreviewVisible(ImagePreviewer, Previewer.State), Mode=OneWay}" /> - + Visibility="{x:Bind IsPreviewVisible(VideoPreviewer, Previewer.State), Mode=OneWay}" /> Previewer as IImagePreviewer; + public IVideoPreviewer? VideoPreviewer => Previewer as IVideoPreviewer; + public IBrowserPreviewer? BrowserPreviewer => Previewer as IBrowserPreviewer; public IUnsupportedFilePreviewer? UnsupportedFilePreviewer => Previewer as IUnsupportedFilePreviewer; @@ -131,6 +134,7 @@ namespace Peek.FilePreviewer { Previewer = null; ImagePreview.Visibility = Visibility.Collapsed; + VideoPreview.Visibility = Visibility.Collapsed; BrowserPreview.Visibility = Visibility.Collapsed; UnsupportedFilePreview.Visibility = Visibility.Collapsed; return; diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IVideoPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IVideoPreviewer.cs new file mode 100644 index 0000000000..ae7d26d1b1 --- /dev/null +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IVideoPreviewer.cs @@ -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; } + } +} diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs new file mode 100644 index 0000000000..82c4e50f84 --- /dev/null +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/MediaPreviewer/VideoPreviewer.cs @@ -0,0 +1,107 @@ +// 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.UI.Dispatching; +using Peek.Common.Constants; +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 + { + private static readonly HashSet _supportedFileTypes = new HashSet + { + ".mp4", ".3g2", ".3gp", ".3gp2", ".3gpp", ".asf", ".avi", ".m2t", ".m2ts", + ".m4v", ".mkv", ".mov", ".mp4", ".mp4v", ".mts", ".wm", ".wmv", + }; + + [ObservableProperty] + private MediaSource? preview; + + [ObservableProperty] + private PreviewState state; + + public VideoPreviewer(IFileSystemItem file) + { + File = file; + Dispatcher = DispatcherQueue.GetForCurrentThread(); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + } + + private IFileSystemItem File { get; } + + public bool IsPreviewLoaded => preview != null; + + private DispatcherQueue Dispatcher { get; } + + private Task? DisplayInfoTask { get; set; } + + public Task GetPreviewSizeAsync(CancellationToken cancellationToken) + { + Size? size = null; + return Task.FromResult(size); + } + + public async Task LoadPreviewAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + State = PreviewState.Loading; + await LoadDisplayInfoAsync(cancellationToken); + + if (HasFailedLoadingPreview()) + { + State = PreviewState.Error; + } + } + + public Task LoadDisplayInfoAsync(CancellationToken cancellationToken) + { + return TaskExtension.RunSafe(async () => + { + cancellationToken.ThrowIfCancellationRequested(); + + await Dispatcher.RunOnUiThread(async () => + { + var storageItem = await File.GetStorageItemAsync(); + Preview = MediaSource.CreateFromStorageFile(storageItem as StorageFile); + }); + }); + } + + public async Task CopyAsync() + { + await Dispatcher.RunOnUiThread(async () => + { + var storageItem = await File.GetStorageItemAsync(); + ClipboardHelper.SaveToClipboard(storageItem); + }); + } + + public static bool IsFileTypeSupported(string fileExt) + { + return _supportedFileTypes.Contains(fileExt); + } + + private bool HasFailedLoadingPreview() + { + return !(DisplayInfoTask?.Result ?? true); + } + } +} diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs index 8a8b0becdc..f03a8435be 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs @@ -16,6 +16,10 @@ namespace Peek.FilePreviewer.Previewers { return new ImagePreviewer(file); } + else if (VideoPreviewer.IsFileTypeSupported(file.Extension)) + { + return new VideoPreviewer(file); + } else if (WebBrowserPreviewer.IsFileTypeSupported(file.Extension)) { return new WebBrowserPreviewer(file);