Added drag and drop for images

Fixed dropzones visual states
Corrected border radius
Fixed null reference exception when event dispatched when chromium still not initialized
This commit is contained in:
Aleh Khantsevich
2024-07-07 01:42:12 +02:00
parent 8cde976358
commit 5923d72803
7 changed files with 167 additions and 576 deletions

View File

@@ -9,6 +9,7 @@ using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI.Controls;
using EmailValidation;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
using MimeKit;
@@ -122,7 +123,7 @@ namespace Wino.Views
private void OnFileDropGridDragOver(object sender, DragEventArgs e)
{
ViewModel.IsDraggingOverDropZone = true;
ViewModel.IsDraggingOverFilesDropZone = true;
e.AcceptedOperation = DataPackageOperation.Copy;
e.DragUIOverride.Caption = Translator.ComposerAttachmentsDragDropAttach_Message;
@@ -133,21 +134,94 @@ namespace Wino.Views
private void OnFileDropGridDragLeave(object sender, DragEventArgs e)
{
ViewModel.IsDraggingOverDropZone = false;
ViewModel.IsDraggingOverFilesDropZone = false;
}
private async void OnFileDropGridFileDropped(object sender, DragEventArgs e)
{
try
{
if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
var storageItems = await e.DataView.GetStorageItemsAsync();
var files = storageItems.OfType<StorageFile>();
await AttachFiles(files);
}
}
// State should be reset even when an exception occurs, otherwise the UI will be stuck in a dragging state.
finally
{
ViewModel.IsDraggingOverComposerGrid = false;
ViewModel.IsDraggingOverFilesDropZone = false;
}
}
private void OnImageDropGridDragEnter(object sender, DragEventArgs e)
{
bool isValid = false;
if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
var storageItems = await e.DataView.GetStorageItemsAsync();
var files = storageItems.OfType<StorageFile>();
// We can't use async/await here because DragUIOverride becomes inaccessible.
// https://github.com/microsoft/microsoft-ui-xaml/issues/9296
var files = e.DataView.GetStorageItemsAsync().GetAwaiter().GetResult().OfType<StorageFile>();
await AttachFiles(files);
foreach (var file in files)
{
if (ValidateImageFile(file))
{
isValid = true;
}
}
}
ViewModel.IsDraggingOverComposerGrid = false;
ViewModel.IsDraggingOverDropZone = false;
e.AcceptedOperation = isValid ? DataPackageOperation.Copy : DataPackageOperation.None;
if (isValid)
{
ViewModel.IsDraggingOverImagesDropZone = true;
e.DragUIOverride.Caption = Translator.ComposerAttachmentsDragDropAttach_Message;
e.DragUIOverride.IsCaptionVisible = true;
e.DragUIOverride.IsGlyphVisible = true;
e.DragUIOverride.IsContentVisible = true;
}
}
private void OnImageDropGridDragLeave(object sender, DragEventArgs e)
{
ViewModel.IsDraggingOverImagesDropZone = false;
}
private async void OnImageDropGridImageDropped(object sender, DragEventArgs e)
{
try
{
if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
var storageItems = await e.DataView.GetStorageItemsAsync();
var files = storageItems.OfType<StorageFile>();
var imageDataURLs = new List<string>();
foreach (var file in files)
{
if (ValidateImageFile(file))
imageDataURLs.Add(await GetDataURL(file));
}
await InvokeScriptSafeAsync($"insertImages({JsonConvert.SerializeObject(imageDataURLs)});");
}
}
// State should be reset even when an exception occurs, otherwise the UI will be stuck in a dragging state.
finally
{
ViewModel.IsDraggingOverComposerGrid = false;
ViewModel.IsDraggingOverImagesDropZone = false;
}
static async Task<string> GetDataURL(StorageFile file)
{
return $"data:image/{file.FileType.Replace(".", "")};base64,{Convert.ToBase64String(await file.ReadBytesAsync())}";
}
}
private async Task AttachFiles(IEnumerable<StorageFile> files)
@@ -166,6 +240,14 @@ namespace Wino.Views
}
}
private bool ValidateImageFile(StorageFile file)
{
string[] allowedTypes = new string[] { ".jpg", ".jpeg", ".png" };
var fileType = file.FileType.ToLower();
return allowedTypes.Contains(fileType);
}
private async void BoldButtonClicked(object sender, RoutedEventArgs e)
{
await InvokeScriptSafeAsync("editor.execCommand('bold')");
@@ -254,7 +336,7 @@ namespace Wino.Views
{
try
{
return await Chromium.ExecuteScriptAsync(function);
return await Chromium?.ExecuteScriptAsync(function);
}
catch (Exception ex)
{
@@ -284,17 +366,6 @@ namespace Wino.Views
await FocusEditorAsync();
}
private async Task<string> TryGetSelectedTextAsync()
{
try
{
return await Chromium.ExecuteScriptAsync("getSelectedText();");
}
catch (Exception) { }
return string.Empty;
}
public async Task UpdateEditorThemeAsync()
{
await DOMLoadedTask.Task;