Revert JSON Null change + fix more warnings

See comment inline re:JSON null
This commit is contained in:
Oren Nachman 2022-08-08 17:35:38 -07:00
parent b85399137e
commit 3648126854
26 changed files with 158 additions and 68 deletions

View file

@ -69,7 +69,13 @@ namespace Flow.Launcher.Core.Plugin
private static readonly JsonSerializerOptions options = new()
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
#pragma warning disable SYSLIB0020
// IgnoreNullValues is obsolete, but the replacement JsonIgnoreCondition.WhenWritingNull still
// deserializes null, instead of ignoring it and leaving the default (empty list). We can change the behaviour
// to accept null and fallback to a default etc, or just keep IgnoreNullValues for now
// see: https://github.com/dotnet/runtime/issues/39152
IgnoreNullValues = true,
#pragma warning restore SYSLIB0020 // Type or member is obsolete
Converters =
{
new JsonObjectConverter()
@ -82,12 +88,15 @@ namespace Flow.Launcher.Core.Plugin
};
private Dictionary<string, object> Settings { get; set; }
private Dictionary<string, FrameworkElement> _settingControls = new();
private readonly Dictionary<string, FrameworkElement> _settingControls = new();
private async Task<List<Result>> DeserializedResultAsync(Stream output)
{
if (output == Stream.Null) return null;
var temp = System.Text.Encoding.UTF8.GetString(((MemoryStream)output).ToArray());
System.Diagnostics.Debug.WriteLine(temp);
var queryResponseModel =
await JsonSerializer.DeserializeAsync<JsonRPCQueryResponseModel>(output, options);

View file

@ -74,7 +74,7 @@ namespace Flow.Launcher.Core.Plugin
}
}
public static async Task ReloadData()
public static async Task ReloadDataAsync()
{
await Task.WhenAll(AllPlugins.Select(plugin => plugin.Plugin switch
{
@ -327,4 +327,4 @@ namespace Flow.Launcher.Core.Plugin
}
}
}
}
}

View file

@ -45,8 +45,10 @@ namespace Flow.Launcher.Core.Plugin
var assembly = assemblyLoader.LoadAssemblyAndDependencies();
var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly,
typeof(IAsyncPlugin));
#pragma warning disable IDE0019 // "Use Pattern Matching" - disabled because the pattern is useful for RELEASE
var plugin = Activator.CreateInstance(type) as IAsyncPlugin;
#pragma warning restore IDE0019
#else
Assembly assembly = null;
IAsyncPlugin plugin = null;

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
@ -40,7 +40,7 @@ namespace Flow.Launcher.Core
api.ShowMsg(api.GetTranslation("pleaseWait"),
api.GetTranslation("update_flowlauncher_update_check"));
using var updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false);
using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false);
// UpdateApp CheckForUpdate will return value only if the app is squirrel installed
var newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false);
@ -115,7 +115,7 @@ namespace Flow.Launcher.Core
}
/// https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/UpdateManager.Factory.cs
private async Task<UpdateManager> GitHubUpdateManager(string repository)
private async Task<UpdateManager> GitHubUpdateManagerAsync(string repository)
{
var uri = new Uri(repository);
var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases";
@ -145,4 +145,4 @@ namespace Flow.Launcher.Core
}
}
}
}

View file

@ -78,7 +78,7 @@ namespace Flow.Launcher.Infrastructure.Exception
sb.AppendLine();
sb.AppendLine("## Assemblies - " + AppDomain.CurrentDomain.FriendlyName);
sb.AppendLine();
foreach (var ass in AppDomain.CurrentDomain.GetAssemblies().OrderBy(o => o.GlobalAssemblyCache ? 50 : 0))
foreach (var ass in AppDomain.CurrentDomain.GetAssemblies())
{
sb.Append("* ");
sb.Append(ass.FullName);

View file

@ -14,30 +14,23 @@ namespace Flow.Launcher.Infrastructure.Image
{
public string GetHashFromImage(ImageSource imageSource)
{
if (!(imageSource is BitmapSource image))
if (imageSource is not BitmapSource image)
{
return null;
}
try
{
using (var outStream = new MemoryStream())
{
// PngBitmapEncoder enc2 = new PngBitmapEncoder();
// enc2.Frames.Add(BitmapFrame.Create(tt));
var enc = new JpegBitmapEncoder();
var bitmapFrame = BitmapFrame.Create(image);
bitmapFrame.Freeze();
enc.Frames.Add(bitmapFrame);
enc.Save(outStream);
var byteArray = outStream.GetBuffer();
using (var sha1 = new SHA1CryptoServiceProvider())
{
var hash = Convert.ToBase64String(sha1.ComputeHash(byteArray));
return hash;
}
}
using var outStream = new MemoryStream();
var enc = new JpegBitmapEncoder();
var bitmapFrame = BitmapFrame.Create(image);
bitmapFrame.Freeze();
enc.Frames.Add(bitmapFrame);
enc.Save(outStream);
var byteArray = outStream.GetBuffer();
using var sha1 = SHA1.Create();
var hash = Convert.ToBase64String(sha1.ComputeHash(byteArray));
return hash;
}
catch
{
@ -46,4 +39,4 @@ namespace Flow.Launcher.Infrastructure.Image
}
}
}
}

View file

@ -13,11 +13,11 @@ namespace Flow.Launcher.Infrastructure.Image
{
public static class ImageLoader
{
private static readonly ImageCache ImageCache = new ImageCache();
private static readonly ImageCache ImageCache = new();
private static BinaryStorage<Dictionary<string, int>> _storage;
private static readonly ConcurrentDictionary<string, string> GuidToKey = new ConcurrentDictionary<string, string>();
private static readonly ConcurrentDictionary<string, string> GuidToKey = new();
private static IImageHashGenerator _hashGenerator;
private static bool EnableImageHash = true;
private static readonly bool EnableImageHash = true;
public static ImageSource DefaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon));
@ -243,7 +243,6 @@ namespace Flow.Launcher.Infrastructure.Image
ImageCache[path] = img;
}
return img;
}

View file

@ -9,6 +9,7 @@ using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.Infrastructure.Storage
{
#pragma warning disable SYSLIB0011 // BinaryFormatter is obsolete.
/// <summary>
/// Stroage object using binary data
/// Normally, it has better performance, but not readable
@ -113,4 +114,5 @@ namespace Flow.Launcher.Infrastructure.Storage
}
}
}
#pragma warning enable SYSLIB0011
}

View file

@ -1,5 +1,6 @@
namespace Flow.Launcher.Plugin
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public static class AllowedLanguage
{
public static string Python
@ -35,4 +36,5 @@
|| language.ToUpper() == Executable.ToUpper();
}
}
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
}

View file

@ -4,14 +4,24 @@ using JetBrains.Annotations;
namespace Flow.Launcher.Plugin
{
/// <summary>
/// Base model for plugin classes
/// </summary>
public class BaseModel : INotifyPropertyChanged
{
/// <summary>
/// Property changed event handler
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Invoked when a property changes
/// </summary>
/// <param name="propertyName"></param>
[NotifyPropertyChangedInvocator]
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

View file

@ -3,9 +3,24 @@ using System.Windows.Input;
namespace Flow.Launcher.Plugin
{
/// <summary>
/// Delegate for key down event
/// </summary>
/// <param name="e"></param>
public delegate void FlowLauncherKeyDownEventHandler(FlowLauncherKeyDownEventArgs e);
/// <summary>
/// Delegate for query event
/// </summary>
/// <param name="e"></param>
public delegate void AfterFlowLauncherQueryEventHandler(FlowLauncherQueryEventArgs e);
/// <summary>
/// Delegate for drop events [unused?]
/// </summary>
/// <param name="result"></param>
/// <param name="dropObject"></param>
/// <param name="e"></param>
public delegate void ResultItemDropEventHandler(Result result, IDataObject dropObject, DragEventArgs e);
/// <summary>
@ -17,14 +32,30 @@ namespace Flow.Launcher.Plugin
/// <returns>return true to continue handling, return false to intercept system handling</returns>
public delegate bool FlowLauncherGlobalKeyboardEventHandler(int keyevent, int vkcode, SpecialKeyState state);
/// <summary>
/// Arguments container for the Key Down event
/// </summary>
public class FlowLauncherKeyDownEventArgs
{
/// <summary>
/// The actual query
/// </summary>
public string Query { get; set; }
/// <summary>
/// Relevant key events for this event
/// </summary>
public KeyEventArgs keyEventArgs { get; set; }
}
/// <summary>
/// Arguments container for the Query event
/// </summary>
public class FlowLauncherQueryEventArgs
{
/// <summary>
/// The actual query
/// </summary>
public Query Query { get; set; }
}
}

View file

@ -15,6 +15,10 @@ namespace Flow.Launcher.Plugin
/// </summary>
public interface IAsyncReloadable : IFeatures
{
/// <summary>
/// Reload plugin data
/// </summary>
/// <returns></returns>
Task ReloadDataAsync();
}
}
}

View file

@ -17,6 +17,9 @@
/// </summary>
public interface IReloadable : IFeatures
{
/// <summary>
/// Synchronously reload plugin data
/// </summary>
void ReloadData();
}
}
}

View file

@ -5,6 +5,9 @@ using System.Windows;
namespace Flow.Launcher.Plugin.SharedCommands
{
/// <summary>
/// Commands that are useful to run on files... and folders!
/// </summary>
public static class FilesFolders
{
private const string FileExplorerProgramName = "explorer";
@ -65,6 +68,13 @@ namespace Flow.Launcher.Plugin.SharedCommands
}
/// <summary>
/// Check if the files and directories are identical between <paramref name="fromPath"/>
/// and <paramref name="toPath"/>
/// </summary>
/// <param name="fromPath"></param>
/// <param name="toPath"></param>
/// <returns></returns>
public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath)
{
try
@ -92,6 +102,10 @@ namespace Flow.Launcher.Plugin.SharedCommands
}
/// <summary>
/// Deletes a folder if it exists
/// </summary>
/// <param name="path"></param>
public static void RemoveFolderIfExists(this string path)
{
try
@ -109,16 +123,30 @@ namespace Flow.Launcher.Plugin.SharedCommands
}
}
/// <summary>
/// Checks if a directory exists
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool LocationExists(this string path)
{
return Directory.Exists(path);
}
/// <summary>
/// Checks if a file exists
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static bool FileExists(this string filePath)
{
return File.Exists(filePath);
}
/// <summary>
/// Open a directory window (using the OS's default handler, usually explorer)
/// </summary>
/// <param name="fileOrFolderPath"></param>
public static void OpenPath(string fileOrFolderPath)
{
var psi = new ProcessStartInfo { FileName = FileExplorerProgramName, UseShellExecute = true, Arguments = '"' + fileOrFolderPath + '"' };
@ -137,6 +165,10 @@ namespace Flow.Launcher.Plugin.SharedCommands
}
}
/// <summary>
/// Open the folder that contains <paramref name="path"/>
/// </summary>
/// <param name="path"></param>
public static void OpenContainingFolder(string path)
{
Process.Start(FileExplorerProgramEXE, $" /select,\"{path}\"");

View file

@ -81,7 +81,7 @@ namespace Flow.Launcher
}
tbAction.Text = updateCustomHotkey.ActionKeyword;
ctlHotkey.SetHotkey(updateCustomHotkey.Hotkey, false);
_ = ctlHotkey.SetHotkey(updateCustomHotkey.Hotkey, false);
update = true;
lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update");
}

View file

@ -400,6 +400,7 @@ namespace Flow.Launcher.Helper
/// to ensure that lease never expires.
/// </summary>
/// <returns>Always null.</returns>
[Obsolete] // overrides an obsolete method, so also needs to be obsolete
public override object InitializeLifetimeService()
{
return null;

View file

@ -82,7 +82,7 @@ namespace Flow.Launcher
ImageLoader.Save();
}
public Task ReloadAllPluginData() => PluginManager.ReloadData();
public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync();
public void ShowMsgError(string title, string subTitle = "") =>
ShowMsg(title, subTitle, Constant.ErrorIcon, true);

View file

@ -101,7 +101,7 @@ namespace Flow.Launcher
private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e)
{
HotkeyControl.SetHotkey(viewModel.Settings.Hotkey, false);
_ = HotkeyControl.SetHotkey(viewModel.Settings.Hotkey, false);
}
private void OnHotkeyControlFocused(object sender, RoutedEventArgs e)

View file

@ -300,7 +300,7 @@ namespace Flow.Launcher.ViewModel
Hide();
_ = PluginManager
.ReloadData()
.ReloadDataAsync()
.ContinueWith(_ =>
Application.Current.Dispatcher.Invoke(() =>
{

View file

@ -5,7 +5,7 @@ namespace Flow.Launcher.ViewModel
{
public class RelayCommand : ICommand
{
private Action<object> _action;
private readonly Action<object> _action;
public RelayCommand(Action<object> action)
{
@ -17,7 +17,9 @@ namespace Flow.Launcher.ViewModel
return true;
}
#pragma warning disable CS0067 // the event is never used
public event EventHandler CanExecuteChanged;
#pragma warning restore CS0067
public virtual void Execute(object parameter)
{

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
@ -53,7 +53,7 @@ namespace Flow.Launcher.Plugin.Program
{
if (IsStartupIndexProgramsRequired)
_ = IndexPrograms();
_ = IndexProgramsAsync();
var result = await cache.GetOrCreateAsync(query.Search, async entry =>
{
@ -122,7 +122,7 @@ namespace Flow.Launcher.Plugin.Program
{
if (indexedWinApps && indexedUWPApps)
_settings.LastIndexTime = DateTime.Today;
});
}, TaskScheduler.Current);
if (!(_win32s.Any() && _uwps.Any()))
await indexTask;
@ -142,7 +142,7 @@ namespace Flow.Launcher.Plugin.Program
_uwps = applications;
}
public static async Task IndexPrograms()
public static async Task IndexProgramsAsync()
{
var t1 = Task.Run(IndexWin32Programs);
var t2 = Task.Run(IndexUwpPrograms);
@ -246,7 +246,7 @@ namespace Flow.Launcher.Plugin.Program
public async Task ReloadDataAsync()
{
await IndexPrograms();
await IndexProgramsAsync();
}
}
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -157,8 +157,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
#if !DEBUG
catch (Exception e)
{
ProgramLogger.LogException($"|UWP|All|{p.InstalledLocation}|An unexpected error occured and "
+ $"unable to convert Package to UWP for {p.Id.FullName}", e);
_ = ProgramLogger.LogException($"|UWP|All|{p.InstalledLocation}|An unexpected error occured and " + $"unable to convert Package to UWP for {p.Id.FullName}", e);
return new Application[] { };
}
#endif
@ -397,7 +396,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
{
try
{
appManager.ActivateApplication(UserModelId, noArgs, noFlags, out _);
_ = appManager.ActivateApplication(UserModelId, noArgs, noFlags, out _);
}
catch (Exception)
{
@ -428,10 +427,10 @@ namespace Flow.Launcher.Plugin.Program.Programs
manifestApp.GetAppUserModelId(out string tmpUserModelId);
manifestApp.GetAppUserModelId(out string tmpUniqueIdentifier);
manifestApp.GetStringValue("DisplayName", out string tmpDisplayName);
manifestApp.GetStringValue("Description", out string tmpDescription);
manifestApp.GetStringValue("BackgroundColor", out string tmpBackgroundColor);
manifestApp.GetStringValue("EntryPoint", out string tmpEntryPoint);
_ = manifestApp.GetStringValue("DisplayName", out string tmpDisplayName);
_ = manifestApp.GetStringValue("Description", out string tmpDescription);
_ = manifestApp.GetStringValue("BackgroundColor", out string tmpBackgroundColor);
_ = manifestApp.GetStringValue("EntryPoint", out string tmpEntryPoint);
UserModelId = tmpUserModelId;
UniqueIdentifier = tmpUniqueIdentifier;
@ -540,7 +539,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
if (logoKeyFromVersion.ContainsKey(Package.Version))
{
var key = logoKeyFromVersion[Package.Version];
app.GetStringValue(key, out string logoUri);
_ = app.GetStringValue(key, out string logoUri);
return logoUri;
}
else
@ -729,4 +728,4 @@ namespace Flow.Launcher.Plugin.Program.Programs
private static extern Hresult SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, uint cchOutBuf,
IntPtr ppvReserved);
}
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -517,9 +517,9 @@ namespace Flow.Launcher.Plugin.Program.Programs
return programs.Concat(autoIndexPrograms).Distinct().ToArray();
}
#if DEBUG //This is to make developer aware of any unhandled exception and add in handling.
catch (Exception e)
catch (Exception)
{
throw e;
throw;
}
#endif
@ -546,4 +546,4 @@ namespace Flow.Launcher.Plugin.Program.Programs
return UniqueIdentifier == other.UniqueIdentifier;
}
}
}
}

View file

@ -119,7 +119,7 @@ namespace Flow.Launcher.Plugin.Program.Views
{
ViewRefresh();
indexingPanel.Visibility = Visibility.Visible;
await Main.IndexPrograms();
await Main.IndexProgramsAsync();
indexingPanel.Visibility = Visibility.Hidden;
}

View file

@ -270,11 +270,12 @@ namespace Flow.Launcher.Plugin.Sys
// Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen.
Application.Current.MainWindow.Hide();
context.API.ReloadAllPluginData().ContinueWith(_ =>
_ = context.API.ReloadAllPluginData().ContinueWith(_ =>
context.API.ShowMsg(
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_success"),
context.API.GetTranslation(
"flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded")));
"flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded")),
System.Threading.Tasks.TaskScheduler.Current);
return true;
}

View file

@ -1,4 +1,4 @@
using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Infrastructure.Image;
using System;
using System.Drawing;
using System.IO;
@ -34,10 +34,10 @@ namespace Flow.Launcher.Plugin.WebSearch
{
File.Copy(fullpathToSelectedImage, destinationFileNameFullPath);
}
catch (Exception e)
catch (Exception)
{
#if DEBUG
throw e;
throw;
#else
MessageBox.Show(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath));
UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage);