| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- using System.Runtime.InteropServices;
- using Avalonia;
- using Avalonia.Controls.ApplicationLifetimes;
- using Avalonia.Controls.Shapes;
- using Avalonia.Input;
- using Avalonia.Input.Platform;
- using Avalonia.Media;
- using Avalonia.Media.Imaging;
- using Avalonia.Platform.Storage;
- using Avalonia.Threading;
- using PicView.Avalonia.Animations;
- using PicView.Avalonia.ImageHandling;
- using PicView.Avalonia.Navigation;
- using PicView.Avalonia.UI;
- using PicView.Avalonia.ViewModels;
- using PicView.Core.FileHandling;
- using PicView.Core.Localization;
- using PicView.Core.ProcessHandling;
- namespace PicView.Avalonia.Clipboard;
- public static class ClipboardHelper
- {
- public static async Task CopyAnimation()
- {
- const double speed = 0.2;
- const double opacity = 0.4;
- var startOpacityAnimation = AnimationsHelper.OpacityAnimation(0, opacity, speed);
- var endOpacityAnimation = AnimationsHelper.OpacityAnimation(opacity, 0, speed);
- Rectangle? rectangle = null;
- await Dispatcher.UIThread.InvokeAsync(() =>
- {
- rectangle = new Rectangle
- {
- Width = UIHelper.GetMainView.Width,
- Height = UIHelper.GetMainView.Height,
- Opacity = 0,
- Fill = Brushes.Black,
- IsHitTestVisible = false
- };
- UIHelper.GetMainView.MainGrid.Children.Add(rectangle);
- });
- await startOpacityAnimation.RunAsync(rectangle);
- await endOpacityAnimation.RunAsync(rectangle);
- await Task.Delay(200);
- await Dispatcher.UIThread.InvokeAsync(() =>
- {
- UIHelper.GetMainView.MainGrid.Children.Remove(rectangle);
- });
- }
- public static async Task Duplicate(MainViewModel vm)
- {
- if (!NavigationHelper.CanNavigate(vm))
- {
- return;
- }
- vm.IsLoading = true;
- var oldPath = vm.FileInfo.FullName;
- var duplicatedPathTask = Task.FromResult(FileHelper.DuplicateAndReturnFileName(oldPath));
- await Task.WhenAll(CopyAnimation(), duplicatedPathTask);
- var duplicatedPath = await duplicatedPathTask;
- if (!File.Exists(duplicatedPath))
- {
- return;
- }
- vm.ImageIterator.Clear();
- await NavigationHelper.LoadPicFromFile(duplicatedPath, vm);
- }
-
- public static async Task CopyTextToClipboard(string text)
- {
- if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
- {
- return;
- }
- await desktop.MainWindow.Clipboard.SetTextAsync(text);
- await CopyAnimation();
- }
- public static async Task CopyFileToClipboard(string? file, MainViewModel vm)
- {
- var success = await Task.Run(() => vm.PlatformService.CopyFile(file));
- if (success)
- {
- await CopyAnimation();
- }
- }
- public static async Task CopyImageToClipboard(MainViewModel vm)
- {
- if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
- {
- return;
- }
- var clipboard = desktop.MainWindow.Clipboard;
-
- if (vm.ImageSource is not Bitmap bitmap)
- {
- return;
- }
- await clipboard.ClearAsync();
-
- // Handle for Windows
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- await Task.WhenAll(vm.PlatformService.CopyImageToClipboard(bitmap), CopyAnimation());
- return;
- }
-
- using var ms = new MemoryStream();
- bitmap.Save(ms);
-
- var dataObject = new DataObject();
- dataObject.Set("image/png", ms.ToArray());
- await Task.WhenAll(clipboard.SetDataObjectAsync(dataObject), CopyAnimation());
- }
- public static async Task CopyBase64ToClipboard(string path, MainViewModel vm)
- {
- if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
- {
- return;
- }
- var clipboard = desktop.MainWindow.Clipboard;
- string base64;
- if (string.IsNullOrWhiteSpace(path))
- {
- switch (vm.ImageType)
- {
- case ImageType.AnimatedGif:
- case ImageType.AnimatedWebp:
- throw new ArgumentOutOfRangeException();
- case ImageType.Bitmap:
- if (vm.ImageSource is not Bitmap bitmap)
- {
- throw new ArgumentOutOfRangeException();
- }
- var stream = new MemoryStream();
- bitmap.Save(stream, quality: 100);
- base64 = Convert.ToBase64String(stream.ToArray());
- break;
- case ImageType.Svg:
- return;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- else
- {
- base64 = Convert.ToBase64String(await File.ReadAllBytesAsync(path));
- }
- if (string.IsNullOrEmpty(base64))
- {
- return;
- }
- await clipboard.SetTextAsync(base64);
- await CopyAnimation();
- }
- public static async Task CutFile(string path, MainViewModel vm)
- {
- var success = await Task.Run(() => vm.PlatformService.CutFile(path));
- if (success)
- {
- await CopyAnimation();
- }
- }
-
- public static async Task Paste(MainViewModel vm)
- {
- if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
- {
- return;
- }
- var clipboard = desktop.MainWindow.Clipboard;
- var files = await clipboard.GetDataAsync(DataFormats.Files);
- if (files is not null)
- {
- // ReSharper disable once ConvertIfStatementToSwitchStatement
- if (files is IEnumerable<IStorageItem> items)
- {
- var storageItems = items.ToArray(); // Ensure we have an array for indexed access
- if (storageItems.Length > 0)
- {
- // load the first file
- var firstFile = storageItems[0];
- var firstPath = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? firstFile.Path.AbsolutePath : firstFile.Path.LocalPath;
- await NavigationHelper.LoadPicFromStringAsync(firstPath, vm).ConfigureAwait(false);
- // Open consecutive files in a new process
- foreach (var file in storageItems.Skip(1))
- {
- var path = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? file.Path.AbsolutePath : file.Path.LocalPath;
- ProcessHelper.StartNewProcess(path);
- }
- }
- }
- else if (files is IStorageItem singleFile)
- {
- var path = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? singleFile.Path.AbsolutePath : singleFile.Path.LocalPath;
- await NavigationHelper.LoadPicFromStringAsync(path, vm).ConfigureAwait(false);
- }
- return;
- }
-
- var text = await clipboard.GetTextAsync();
- if (!string.IsNullOrWhiteSpace(text))
- {
- await NavigationHelper.LoadPicFromStringAsync(text, vm).ConfigureAwait(false);
- return;
- }
-
- await PasteClipboardImage(vm, clipboard);
-
- }
-
- public static async Task PasteClipboardImage(MainViewModel vm, IClipboard clipboard)
- {
- var name = TranslationHelper.Translation.ClipboardImage;
- var imageType = ImageType.Bitmap;
- var bitmap = await GetBitmapFromBytes("PNG");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
-
- bitmap = await GetBitmapFromBytes("image/jpeg");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("image/png");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("image/bmp");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("BMP");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("JPG");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("JPEG");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("image/tiff");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("GIF");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- bitmap = await GetBitmapFromBytes("image/gif");
- if (bitmap is not null)
- {
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- // Handle for Windows
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- bitmap = await vm.PlatformService.GetImageFromClipboard();
- UpdateImage.SetSingleImage(bitmap, imageType, name, vm);
- return;
- }
- return;
-
- async Task<Bitmap?> GetBitmapFromBytes(string format)
- {
- var data = await clipboard.GetDataAsync(format);
- if (data is byte[] dataBytes)
- {
- using var memoryStream = new MemoryStream(dataBytes);
- var image = new Bitmap(memoryStream);
- return image;
- }
-
- return null;
- }
- }
- }
|