diff --git a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs index dca80eb0..59abe9ae 100644 --- a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs +++ b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoveryProviderSetting.cs @@ -1,22 +1,22 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Wino.Core.Domain.Models.AutoDiscovery { public class AutoDiscoveryProviderSetting { - [JsonProperty("protocol")] + [JsonPropertyName("protocol")] public string Protocol { get; set; } - [JsonProperty("address")] + [JsonPropertyName("address")] public string Address { get; set; } - [JsonProperty("port")] + [JsonPropertyName("port")] public int Port { get; set; } - [JsonProperty("secure")] + [JsonPropertyName("secure")] public string Secure { get; set; } - [JsonProperty("username")] + [JsonPropertyName("username")] public string Username { get; set; } } } diff --git a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs index dbc300e7..cfcb55ff 100644 --- a/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs +++ b/Wino.Core.Domain/Models/AutoDiscovery/AutoDiscoverySettings.cs @@ -1,19 +1,19 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using Wino.Core.Domain.Entities; namespace Wino.Core.Domain.Models.AutoDiscovery { public class AutoDiscoverySettings { - [JsonProperty("domain")] + [JsonPropertyName("domain")] public string Domain { get; set; } - [JsonProperty("password")] + [JsonPropertyName("password")] public string Password { get; set; } - [JsonProperty("settings")] + [JsonPropertyName("settings")] public List Settings { get; set; } /// diff --git a/Wino.Core.Domain/Models/Reader/ImageInfo.cs b/Wino.Core.Domain/Models/Reader/ImageInfo.cs new file mode 100644 index 00000000..18ef60b7 --- /dev/null +++ b/Wino.Core.Domain/Models/Reader/ImageInfo.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Wino.Core.Domain.Models.Reader; + +public class ImageInfo +{ + [JsonPropertyName("data")] + public string Data { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } +} diff --git a/Wino.Core.Domain/Models/Reader/WebViewMessage.cs b/Wino.Core.Domain/Models/Reader/WebViewMessage.cs index f3a462b1..98c4ab9e 100644 --- a/Wino.Core.Domain/Models/Reader/WebViewMessage.cs +++ b/Wino.Core.Domain/Models/Reader/WebViewMessage.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Wino.Core.Domain.Models.Reader { @@ -7,10 +7,10 @@ namespace Wino.Core.Domain.Models.Reader /// public class WebViewMessage { - [JsonProperty("type")] + [JsonPropertyName("type")] public string Type { get; set; } - [JsonProperty("value")] + [JsonPropertyName("value")] public string Value { get; set; } } } diff --git a/Wino.Core.Domain/Wino.Core.Domain.csproj b/Wino.Core.Domain/Wino.Core.Domain.csproj index 2a01010c..64fe85b1 100644 --- a/Wino.Core.Domain/Wino.Core.Domain.csproj +++ b/Wino.Core.Domain/Wino.Core.Domain.csproj @@ -62,7 +62,6 @@ - diff --git a/Wino.Core.UWP/Services/ThemeService.cs b/Wino.Core.UWP/Services/ThemeService.cs index 8db94f1c..c5166db9 100644 --- a/Wino.Core.UWP/Services/ThemeService.cs +++ b/Wino.Core.UWP/Services/ThemeService.cs @@ -4,10 +4,10 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; +using System.Text.Json; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using Microsoft.Toolkit.Uwp.Helpers; -using Newtonsoft.Json; using Windows.Storage; using Windows.UI; using Windows.UI.ViewManagement; @@ -406,7 +406,7 @@ namespace Wino.Services // Save metadata. var metadataFile = await themeFolder.CreateFileAsync($"{newTheme.Id}.json", CreationCollisionOption.ReplaceExisting); - var serialized = JsonConvert.SerializeObject(newTheme); + var serialized = JsonSerializer.Serialize(newTheme); await FileIO.WriteTextAsync(metadataFile, serialized); return newTheme; @@ -438,7 +438,7 @@ namespace Wino.Services { var fileContent = await FileIO.ReadTextAsync(file); - return JsonConvert.DeserializeObject(fileContent); + return JsonSerializer.Deserialize(fileContent); } public string GetSystemAccentColorHex() diff --git a/Wino.Core/Authenticators/GmailAuthenticator.cs b/Wino.Core/Authenticators/GmailAuthenticator.cs index 32f0235d..7bcc915f 100644 --- a/Wino.Core/Authenticators/GmailAuthenticator.cs +++ b/Wino.Core/Authenticators/GmailAuthenticator.cs @@ -1,8 +1,8 @@ using System; using System.Net.Http; using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Wino.Core.Domain; using Wino.Core.Domain.Entities; using Wino.Core.Domain.Enums; @@ -58,14 +58,14 @@ namespace Wino.Core.Authenticators if (!response.IsSuccessStatusCode) throw new GoogleAuthenticationException(Translator.Exception_GoogleAuthorizationCodeExchangeFailed); - var parsed = JObject.Parse(responseString); + var parsed = JsonNode.Parse(responseString).AsObject(); if (parsed.ContainsKey("error")) - throw new GoogleAuthenticationException(parsed["error"]["message"].Value()); + throw new GoogleAuthenticationException(parsed["error"]["message"].GetValue()); - var accessToken = parsed["access_token"].Value(); - var refreshToken = parsed["refresh_token"].Value(); - var expiresIn = parsed["expires_in"].Value(); + var accessToken = parsed["access_token"].GetValue(); + var refreshToken = parsed["refresh_token"].GetValue(); + var expiresIn = parsed["expires_in"].GetValue(); var expirationDate = DateTime.UtcNow.AddSeconds(expiresIn); @@ -76,12 +76,12 @@ namespace Wino.Core.Authenticators var userinfoResponse = await client.GetAsync(UserInfoEndpoint); string userinfoResponseContent = await userinfoResponse.Content.ReadAsStringAsync(); - var parsedUserInfo = JObject.Parse(userinfoResponseContent); + var parsedUserInfo = JsonNode.Parse(userinfoResponseContent).AsObject(); if (parsedUserInfo.ContainsKey("error")) - throw new GoogleAuthenticationException(parsedUserInfo["error"]["message"].Value()); + throw new GoogleAuthenticationException(parsedUserInfo["error"]["message"].GetValue()); - var username = parsedUserInfo["emailAddress"].Value(); + var username = parsedUserInfo["emailAddress"].GetValue(); return new TokenInformation() { @@ -166,13 +166,13 @@ namespace Wino.Core.Authenticators string responseString = await response.Content.ReadAsStringAsync(); - var parsed = JObject.Parse(responseString); + var parsed = JsonNode.Parse(responseString).AsObject(); // TODO: Error parsing is incorrect. if (parsed.ContainsKey("error")) - throw new GoogleAuthenticationException(parsed["error_description"].Value()); + throw new GoogleAuthenticationException(parsed["error_description"].GetValue()); - var accessToken = parsed["access_token"].Value(); + var accessToken = parsed["access_token"].GetValue(); string activeRefreshToken = refresh_token; @@ -182,10 +182,10 @@ namespace Wino.Core.Authenticators if (parsed.ContainsKey("refresh_token")) { - activeRefreshToken = parsed["refresh_token"].Value(); + activeRefreshToken = parsed["refresh_token"].GetValue(); } - var expiresIn = parsed["expires_in"].Value(); + var expiresIn = parsed["expires_in"].GetValue(); var expirationDate = DateTime.UtcNow.AddSeconds(expiresIn); return new TokenInformationBase() diff --git a/Wino.Core/Extensions/MimeExtensions.cs b/Wino.Core/Extensions/MimeExtensions.cs index 624645d1..bb7d776a 100644 --- a/Wino.Core/Extensions/MimeExtensions.cs +++ b/Wino.Core/Extensions/MimeExtensions.cs @@ -1,9 +1,12 @@ -using System.IO; +using System; +using System.IO; using System.Text; using Google.Apis.Gmail.v1.Data; +using HtmlAgilityPack; using MimeKit; using MimeKit.IO; using MimeKit.IO.Filters; +using MimeKit.Utils; using Wino.Core.Domain; using Wino.Core.Domain.Entities; @@ -48,5 +51,71 @@ namespace Wino.Core.Extensions return new AddressInformation() { Name = address.Name, Address = address.Address }; } + + /// + /// Sets html body replacing base64 images with cid linked resources. + /// Updates text body based on html. + /// + /// Body builder. + /// Html content that can have embedded images. + /// Body builder with set HtmlBody. + public static BodyBuilder SetHtmlBody(this BodyBuilder bodyBuilder, string htmlContent) + { + if (string.IsNullOrEmpty(htmlContent)) return bodyBuilder; + + var doc = new HtmlDocument(); + doc.LoadHtml(htmlContent); + + var imgNodes = doc.DocumentNode.SelectNodes("//img"); + + if (imgNodes != null) + { + foreach (var node in imgNodes) + { + var src = node.GetAttributeValue("src", string.Empty); + + if (string.IsNullOrEmpty(src)) continue; + + if (!src.StartsWith("data:image")) + { + continue; + } + + var parts = src.Substring(11).Split([";base64,"], StringSplitOptions.None); + + string mimeType = parts[0]; + string base64Content = parts[1]; + + var alt = node.GetAttributeValue("alt", $"Embedded_Image.{mimeType}"); + + // Convert the base64 content to binary data + byte[] imageData = Convert.FromBase64String(base64Content); + + // Create a new linked resource as MimePart + var image = new MimePart("image", mimeType) + { + ContentId = MimeUtils.GenerateMessageId(), + Content = new MimeContent(new MemoryStream(imageData)), + ContentDisposition = new ContentDisposition(ContentDisposition.Inline), + ContentDescription = alt.Replace(" ", "_"), + FileName = alt, + ContentTransferEncoding = ContentEncoding.Base64 + }; + + bodyBuilder.LinkedResources.Add(image); + + node.SetAttributeValue("src", $"cid:{image.ContentId}"); + } + } + + bodyBuilder.HtmlBody = doc.DocumentNode.InnerHtml; + + if (!string.IsNullOrEmpty(bodyBuilder.HtmlBody)) + { + bodyBuilder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(bodyBuilder.HtmlBody); + } + + return bodyBuilder; + } } } diff --git a/Wino.Core/Http/MicrosoftJsonContractResolver.cs b/Wino.Core/Http/MicrosoftJsonContractResolver.cs deleted file mode 100644 index 79148cbe..00000000 --- a/Wino.Core/Http/MicrosoftJsonContractResolver.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace Wino.Core.Http -{ - - /// - /// We need to generate HttpRequestMessage for batch requests, and sometimes we need to - /// serialize content as json. However, some of the fields like 'ODataType' must be ignored - /// in order PATCH requests to succeed. Therefore Microsoft account synchronizer uses - /// special JsonSerializerSettings for ignoring some of the properties. - /// - public class MicrosoftJsonContractResolver : DefaultContractResolver - { - private readonly HashSet ignoreProps = new HashSet() - { - "ODataType" - }; - - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - JsonProperty property = base.CreateProperty(member, memberSerialization); - - if (ignoreProps.Contains(property.PropertyName)) - { - property.ShouldSerialize = _ => false; - } - - return property; - } - } -} diff --git a/Wino.Core/Requests/Bundles/RequestBundle.cs b/Wino.Core/Requests/Bundles/RequestBundle.cs index bf8a7045..3a3ad107 100644 --- a/Wino.Core/Requests/Bundles/RequestBundle.cs +++ b/Wino.Core/Requests/Bundles/RequestBundle.cs @@ -1,15 +1,13 @@ using System; using System.Linq; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json; using Wino.Core.Domain.Interfaces; namespace Wino.Core.Domain.Models.Requests { - - /// /// Bundle that encapsulates batch request and native request without a response. /// @@ -43,7 +41,7 @@ namespace Wino.Core.Domain.Models.Requests { var content = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - return JsonConvert.DeserializeObject(content) ?? throw new InvalidOperationException("Invalid Http Response Deserialization"); + return JsonSerializer.Deserialize(content) ?? throw new InvalidOperationException("Invalid Http Response Deserialization"); } public override string ToString() diff --git a/Wino.Core/Services/AutoDiscoveryService.cs b/Wino.Core/Services/AutoDiscoveryService.cs index c788b130..dc4ee10f 100644 --- a/Wino.Core/Services/AutoDiscoveryService.cs +++ b/Wino.Core/Services/AutoDiscoveryService.cs @@ -1,7 +1,7 @@ using System; using System.Net.Http; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; using Serilog; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.AutoDiscovery; @@ -43,7 +43,7 @@ namespace Wino.Core.Services { var content = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(content); + return JsonSerializer.Deserialize(content); } catch (Exception ex) { diff --git a/Wino.Core/Services/MailService.cs b/Wino.Core/Services/MailService.cs index 43b5df39..642d14cd 100644 --- a/Wino.Core/Services/MailService.cs +++ b/Wino.Core/Services/MailService.cs @@ -636,10 +636,7 @@ namespace Wino.Core.Services _ => CreateReferencedDraft(builder, message, draftCreationOptions, account, signature), }; - if (!string.IsNullOrEmpty(builder.HtmlBody)) - { - builder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(builder.HtmlBody); - } + builder.SetHtmlBody(builder.HtmlBody); message.Body = builder.ToMessageBody(); diff --git a/Wino.Core/Services/TranslationService.cs b/Wino.Core/Services/TranslationService.cs index 5190b814..76aa32e9 100644 --- a/Wino.Core/Services/TranslationService.cs +++ b/Wino.Core/Services/TranslationService.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.IO; +using System.Text.Json; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; -using Newtonsoft.Json; using Serilog; using Wino.Core.Domain; using Wino.Core.Domain.Enums; @@ -44,7 +44,7 @@ namespace Wino.Core.Services var stremValue = await new StreamReader(resourceStream).ReadToEndAsync().ConfigureAwait(false); - var translationLookups = JsonConvert.DeserializeObject>(stremValue); + var translationLookups = JsonSerializer.Deserialize>(stremValue); // Insert new translation key-value pairs. // Overwrite existing values for the same keys. diff --git a/Wino.Core/Wino.Core.csproj b/Wino.Core/Wino.Core.csproj index a975630d..be8ca55c 100644 --- a/Wino.Core/Wino.Core.csproj +++ b/Wino.Core/Wino.Core.csproj @@ -31,7 +31,6 @@ - diff --git a/Wino.Mail.ViewModels/ComposePageViewModel.cs b/Wino.Mail.ViewModels/ComposePageViewModel.cs index 966daf57..d3424bf5 100644 --- a/Wino.Mail.ViewModels/ComposePageViewModel.cs +++ b/Wino.Mail.ViewModels/ComposePageViewModel.cs @@ -8,6 +8,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using MimeKit; +using MimeKit.Utils; using Wino.Core.Domain; using Wino.Core.Domain.Entities; using Wino.Core.Domain.Enums; @@ -237,12 +238,9 @@ namespace Wino.Mail.ViewModels { if (GetHTMLBodyFunction != null) { - bodyBuilder.HtmlBody = await GetHTMLBodyFunction(); + bodyBuilder.SetHtmlBody(await GetHTMLBodyFunction()); } - if (!string.IsNullOrEmpty(bodyBuilder.HtmlBody)) - bodyBuilder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(bodyBuilder.HtmlBody); - if (bodyBuilder.HtmlBody != null && bodyBuilder.TextBody != null) CurrentMimeMessage.Body = bodyBuilder.ToMessageBody(); } @@ -401,7 +399,6 @@ namespace Wino.Mail.ViewModels { DialogService.InfoBarMessage("Busy", "Mail is being processed. Please wait a moment and try again.", InfoBarMessageType.Warning); } - catch (ComposerMimeNotFoundException) { DialogService.InfoBarMessage(Translator.Info_ComposerMissingMIMETitle, Translator.Info_ComposerMissingMIMEMessage, InfoBarMessageType.Error); diff --git a/Wino.Mail/Activation/FileActivationHandler.cs b/Wino.Mail/Activation/FileActivationHandler.cs index 6aa7ca47..5b5814da 100644 --- a/Wino.Mail/Activation/FileActivationHandler.cs +++ b/Wino.Mail/Activation/FileActivationHandler.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.Toolkit.Uwp.Helpers; using Windows.ApplicationModel.Activation; using Windows.Storage; using Windows.UI.Xaml; @@ -9,7 +10,6 @@ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Animation; using Wino.Core.Domain.Interfaces; using Wino.Core.Services; -using Wino.Helpers; using Wino.Views; namespace Wino.Activation diff --git a/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs index 10e7cafa..821c7ec0 100644 --- a/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs +++ b/Wino.Mail/Dialogs/SignatureEditorDialog.xaml.cs @@ -1,9 +1,9 @@ using System; +using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Web.WebView2.Core; -using Newtonsoft.Json; using Windows.UI.ViewManagement.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -78,7 +78,7 @@ namespace Wino.Dialogs { var editorContent = await InvokeScriptSafeAsync("GetHTMLContent();"); - return JsonConvert.DeserializeObject(editorContent); + return JsonSerializer.Deserialize(editorContent); }); var underlyingThemeService = App.Current.Services.GetService(); @@ -193,7 +193,7 @@ namespace Wino.Dialogs string script = functionName + "("; for (int i = 0; i < parameters.Length; i++) { - script += JsonConvert.SerializeObject(parameters[i]); + script += JsonSerializer.Serialize(parameters[i]); if (i < parameters.Length - 1) { script += ", "; @@ -327,7 +327,7 @@ namespace Wino.Dialogs private void ScriptMessageReceived(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args) { - var change = JsonConvert.DeserializeObject(args.WebMessageAsJson); + var change = JsonSerializer.Deserialize(args.WebMessageAsJson); if (change.Type == "bold") { diff --git a/Wino.Mail/Helpers/JsonHelpers.cs b/Wino.Mail/Helpers/JsonHelpers.cs deleted file mode 100644 index c04ecfcc..00000000 --- a/Wino.Mail/Helpers/JsonHelpers.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading.Tasks; - -using Newtonsoft.Json; - -namespace Wino.Helpers -{ - public static class JsonHelpers - { - public static async Task ToObjectAsync(string value) - { - return await Task.Run(() => - { - return JsonConvert.DeserializeObject(value); - }); - } - - public static async Task StringifyAsync(object value) - { - return await Task.Run(() => - { - return JsonConvert.SerializeObject(value); - }); - } - } -} diff --git a/Wino.Mail/Helpers/SettingsStorageExtensions.cs b/Wino.Mail/Helpers/SettingsStorageExtensions.cs deleted file mode 100644 index a566e891..00000000 --- a/Wino.Mail/Helpers/SettingsStorageExtensions.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; - -using Windows.Storage; -using Windows.Storage.Streams; - -namespace Wino.Helpers -{ - // Use these extension methods to store and retrieve local and roaming app data - // More details regarding storing and retrieving app data at https://docs.microsoft.com/windows/uwp/app-settings/store-and-retrieve-app-data - public static class SettingsStorageExtensions - { - private const string FileExtension = ".json"; - - public static bool IsRoamingStorageAvailable(this ApplicationData appData) - { - return appData.RoamingStorageQuota == 0; - } - - public static async Task SaveAsync(this StorageFolder folder, string name, T content) - { - var file = await folder.CreateFileAsync(GetFileName(name), CreationCollisionOption.ReplaceExisting); - var fileContent = await JsonHelpers.StringifyAsync(content); - - await FileIO.WriteTextAsync(file, fileContent); - } - - public static async Task ReadAsync(this StorageFolder folder, string name) - { - if (!File.Exists(Path.Combine(folder.Path, GetFileName(name)))) - { - return default; - } - - var file = await folder.GetFileAsync($"{name}.json"); - var fileContent = await FileIO.ReadTextAsync(file); - - return await JsonHelpers.ToObjectAsync(fileContent); - } - - public static async Task SaveAsync(this ApplicationDataContainer settings, string key, T value) - { - settings.SaveString(key, await JsonHelpers.StringifyAsync(value)); - } - - public static void SaveString(this ApplicationDataContainer settings, string key, string value) - { - settings.Values[key] = value; - } - - public static async Task ReadAsync(this ApplicationDataContainer settings, string key) - { - object obj = null; - - if (settings.Values.TryGetValue(key, out obj)) - { - return await JsonHelpers.ToObjectAsync((string)obj); - } - - return default; - } - - public static async Task SaveFileAsync(this StorageFolder folder, byte[] content, string fileName, CreationCollisionOption options = CreationCollisionOption.ReplaceExisting) - { - if (content == null) - { - throw new ArgumentNullException(nameof(content)); - } - - if (string.IsNullOrEmpty(fileName)) - { - throw new ArgumentException("File name is null or empty. Specify a valid file name", nameof(fileName)); - } - - var storageFile = await folder.CreateFileAsync(fileName, options); - await FileIO.WriteBytesAsync(storageFile, content); - return storageFile; - } - - public static async Task ReadFileAsync(this StorageFolder folder, string fileName) - { - var item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false); - - if ((item != null) && item.IsOfType(StorageItemTypes.File)) - { - var storageFile = await folder.GetFileAsync(fileName); - byte[] content = await storageFile.ReadBytesAsync(); - return content; - } - - return null; - } - - public static async Task ReadBytesAsync(this StorageFile file) - { - if (file != null) - { - using (IRandomAccessStream stream = await file.OpenReadAsync()) - { - using (var reader = new DataReader(stream.GetInputStreamAt(0))) - { - await reader.LoadAsync((uint)stream.Size); - var bytes = new byte[stream.Size]; - reader.ReadBytes(bytes); - return bytes; - } - } - } - - return null; - } - - private static string GetFileName(string name) - { - return string.Concat(name, FileExtension); - } - } -} diff --git a/Wino.Mail/JS/editor.js b/Wino.Mail/JS/editor.js index 38582f3b..b26c1f10 100644 --- a/Wino.Mail/JS/editor.js +++ b/Wino.Mail/JS/editor.js @@ -48,7 +48,7 @@ function initializeJodit(fonts, defaultComposerFont, defaultComposerFontSize, de const reader = new FileReader(); reader.onload = function (event) { const base64Image = event.target.result; - insertImages([base64Image]); + insertImages([{ data: base64Image, name: file.name }]); }; reader.readAsDataURL(file); } @@ -121,8 +121,8 @@ function toggleToolbar(enable) { } } -function insertImages(images) { - images.forEach(image => { - editor.selection.insertHTML(`Embedded Image`); +function insertImages(imagesInfo) { + imagesInfo.forEach(imageInfo => { + editor.selection.insertHTML(`${imageInfo.name}`); }); }; diff --git a/Wino.Mail/Views/ComposePage.xaml.cs b/Wino.Mail/Views/ComposePage.xaml.cs index ebf04a91..b1b01c25 100644 --- a/Wino.Mail/Views/ComposePage.xaml.cs +++ b/Wino.Mail/Views/ComposePage.xaml.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Reactive.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; @@ -13,7 +14,6 @@ using Microsoft.Toolkit.Uwp.Helpers; using Microsoft.UI.Xaml.Controls; using Microsoft.Web.WebView2.Core; using MimeKit; -using Newtonsoft.Json; using Windows.ApplicationModel.DataTransfer; using Windows.Foundation; using Windows.Storage; @@ -167,7 +167,7 @@ namespace Wino.Views foreach (var file in files) { - if (ValidateImageFile(file)) + if (IsValidImageFile(file)) { isValid = true; } @@ -200,15 +200,21 @@ namespace Wino.Views var storageItems = await e.DataView.GetStorageItemsAsync(); var files = storageItems.OfType(); - var imageDataURLs = new List(); + var imagesInformation = new List(); foreach (var file in files) { - if (ValidateImageFile(file)) - imageDataURLs.Add(await GetDataURL(file)); + if (IsValidImageFile(file)) + { + imagesInformation.Add(new ImageInfo + { + Data = await GetDataURL(file), + Name = file.Name + }); + } } - await InvokeScriptSafeAsync($"insertImages({JsonConvert.SerializeObject(imageDataURLs)});"); + await InvokeScriptSafeAsync($"insertImages({JsonSerializer.Serialize(imagesInformation)});"); } } // State should be reset even when an exception occurs, otherwise the UI will be stuck in a dragging state. @@ -240,7 +246,7 @@ namespace Wino.Views } } - private bool ValidateImageFile(StorageFile file) + private bool IsValidImageFile(StorageFile file) { string[] allowedTypes = new string[] { ".jpg", ".jpeg", ".png" }; var fileType = file.FileType.ToLower(); @@ -321,7 +327,7 @@ namespace Wino.Views string script = functionName + "("; for (int i = 0; i < parameters.Length; i++) { - script += JsonConvert.SerializeObject(parameters[i]); + script += JsonSerializer.Serialize(parameters[i]); if (i < parameters.Length - 1) { script += ", "; @@ -463,7 +469,7 @@ namespace Wino.Views { var editorContent = await InvokeScriptSafeAsync("GetHTMLContent();"); - return JsonConvert.DeserializeObject(editorContent); + return JsonSerializer.Deserialize(editorContent); }); var underlyingThemeService = App.Current.Services.GetService(); @@ -487,7 +493,7 @@ namespace Wino.Views private void ScriptMessageReceived(CoreWebView2 sender, CoreWebView2WebMessageReceivedEventArgs args) { - var change = JsonConvert.DeserializeObject(args.WebMessageAsJson); + var change = JsonSerializer.Deserialize(args.WebMessageAsJson); if (change.Type == "bold") { diff --git a/Wino.Mail/Views/MailRenderingPage.xaml.cs b/Wino.Mail/Views/MailRenderingPage.xaml.cs index 85beadeb..3c1826d9 100644 --- a/Wino.Mail/Views/MailRenderingPage.xaml.cs +++ b/Wino.Mail/Views/MailRenderingPage.xaml.cs @@ -1,12 +1,12 @@ using System; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using Microsoft.AppCenter.Crashes; using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml.Controls; using Microsoft.Web.WebView2.Core; -using Newtonsoft.Json; using Windows.System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -70,7 +70,7 @@ namespace Wino.Views string script = functionName + "("; for (int i = 0; i < parameters.Length; i++) { - script += JsonConvert.SerializeObject(parameters[i]); + script += JsonSerializer.Serialize(parameters[i]); if (i < parameters.Length - 1) { script += ", "; diff --git a/Wino.Mail/Wino.Mail.csproj b/Wino.Mail/Wino.Mail.csproj index 8541d994..43c2a54b 100644 --- a/Wino.Mail/Wino.Mail.csproj +++ b/Wino.Mail/Wino.Mail.csproj @@ -298,14 +298,12 @@ AccountCreationDialog.xaml - -