Skip to content

Fix copy to clipboard STA thread issue & Support retry for copy & Async build-in shortcut model & Fix build shortcuts text replace issue & Fix startup window hide issue #3314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 100 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
9f8e829
Delete CopyToClipboard function in JsonRPC api
Jack251970 Mar 6, 2025
d7a29e5
Revert "Delete CopyToClipboard function in JsonRPC api"
Jack251970 Mar 6, 2025
e5ad777
Fix copy to clipboard STA thread issue
Jack251970 Mar 6, 2025
04f6d14
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Mar 20, 2025
17ecebf
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Mar 20, 2025
b034f0d
Update Flow.Launcher.Infrastructure/Win32Helper.cs
Jack251970 Mar 20, 2025
c98c419
Update Flow.Launcher.Infrastructure/Win32Helper.cs
Jack251970 Mar 20, 2025
338c8e2
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Mar 26, 2025
ff2cb96
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Mar 27, 2025
817d247
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Mar 30, 2025
e0a651c
Add async buildin shortcut model
Jack251970 Mar 30, 2025
a49c465
Add async buildin shortcuts in mainvm
Jack251970 Mar 30, 2025
9897213
Improve log
Jack251970 Mar 30, 2025
123802b
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 4, 2025
246b1fb
Improve code comments
Jack251970 Apr 5, 2025
3b30209
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 9, 2025
c1602b0
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 12, 2025
8168d8a
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 13, 2025
3fc69ab
Fix typos
Jack251970 Apr 13, 2025
0314a9f
Add SetText back
Jack251970 Apr 13, 2025
ff9f1e1
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 14, 2025
8db8d5c
Add dispatcher back
Jack251970 Apr 14, 2025
f742460
Add code comments
Jack251970 Apr 14, 2025
ae7cea1
Fix COMException
Jack251970 Apr 14, 2025
3be057d
Revert "Fix COMException"
Jack251970 Apr 14, 2025
2f27fa6
Do not open report window for task scheduler exception
Jack251970 Apr 14, 2025
1b412da
Improve error reporting
Jack251970 Apr 15, 2025
370be2a
Use JoinableTaskFactory instead
Jack251970 Apr 15, 2025
0c592b1
Fix typos
Jack251970 Apr 15, 2025
d08deab
Code quality
Jack251970 Apr 15, 2025
e55f79e
Improve code comments & code quality
Jack251970 Apr 15, 2025
0eeaaea
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 15, 2025
bd1da94
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 16, 2025
882b7dc
Check ui thread access when calling ui thread
Jack251970 Apr 16, 2025
ba5a76a
Improve performance
Jack251970 Apr 16, 2025
632dbeb
Check ui thread access when calling ui thread
Jack251970 Apr 16, 2025
8f23870
Back to original style for fixing task issues
Jack251970 Apr 16, 2025
9dc9cde
Check token
Jack251970 Apr 16, 2025
5990820
Set update source null
Jack251970 Apr 16, 2025
72c2d7f
Wait update source cancellation before next update source
Jack251970 Apr 16, 2025
9242f8e
Valid plugin after
Jack251970 Apr 16, 2025
0e70519
Adjust ident
Jack251970 Apr 16, 2025
290750a
Dispose update slim
Jack251970 Apr 16, 2025
a780719
Improve code comments
Jack251970 Apr 16, 2025
00c496f
Revert "Set update source null"
Jack251970 Apr 16, 2025
5002449
Use gloabl token & remove useless check
Jack251970 Apr 16, 2025
396cd69
Do not dispose update source
Jack251970 Apr 16, 2025
893ec48
Remove unused check
Jack251970 Apr 16, 2025
a22306a
Use Query check instead of bool check
Jack251970 Apr 16, 2025
8e15e7f
Change variable name
Jack251970 Apr 16, 2025
67ed7a1
Do not use dispatcher
Jack251970 Apr 17, 2025
14cdf8a
Add cancel token check
Jack251970 Apr 17, 2025
be0c1ad
Switch to ThreadPool thread to keep UI responsive when waiting update…
Jack251970 Apr 17, 2025
43826cb
Add cancel token
Jack251970 Apr 17, 2025
5441fc4
Fix log message issue
Jack251970 Apr 17, 2025
20b5c47
Fix progress bar issue when cancelling query with empty
Jack251970 Apr 17, 2025
9eb7c9c
Wait last query to be canceled and then do resetting actions
Jack251970 Apr 17, 2025
b9e04ff
Improve code comments
Jack251970 Apr 17, 2025
236abc8
Add test codes
Jack251970 Apr 17, 2025
96bb07d
Use dispatcher for performance
Jack251970 Apr 17, 2025
56a3551
Fix performance issue
Jack251970 Apr 17, 2025
4ca8c60
Add test codes
Jack251970 Apr 17, 2025
ab95342
Improve test codes
Jack251970 Apr 17, 2025
186cd2c
Remove useless switch
Jack251970 Apr 17, 2025
4aa9a34
Fix test codes
Jack251970 Apr 17, 2025
e9a0868
Add running query check
Jack251970 Apr 17, 2025
854e61d
Add test codes
Jack251970 Apr 17, 2025
7961615
Improve test codes
Jack251970 Apr 17, 2025
e5b5ec5
Improve test codes
Jack251970 Apr 17, 2025
30a840a
Improve test codes
Jack251970 Apr 17, 2025
b918d00
Improve display performance
Jack251970 Apr 17, 2025
adde491
Suppress warning
Jack251970 Apr 18, 2025
6859232
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 18, 2025
c78a558
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 19, 2025
c0b792c
Set running query null after update lock and update cancellation
Jack251970 Apr 20, 2025
7669bba
Inline update source
Jack251970 Apr 22, 2025
ccfc6fd
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 22, 2025
282f486
Fix query input check issue
Jack251970 Apr 22, 2025
a143cb4
Improve code comments
Jack251970 Apr 22, 2025
1ffbbca
Remove _updateToken
Jack251970 Apr 22, 2025
836d09e
Ignore main window show when exiting
Jack251970 Apr 23, 2025
6bb638b
Fix window blink issue
Jack251970 Apr 23, 2025
dd467e2
Fix typo
Jack251970 Apr 25, 2025
023f511
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 25, 2025
74f274a
Add hotkey mapper initialization back
Jack251970 Apr 25, 2025
7800540
Improve code quality
Jack251970 Apr 25, 2025
15e6754
Fix code comments
Jack251970 Apr 25, 2025
7a879c9
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 25, 2025
fa49c08
Add ConfigureAwait(false) to slightly reduce the risk of deadlocks
Jack251970 Apr 25, 2025
ebc81c0
Improve code quality
Jack251970 Apr 25, 2025
593a360
Remove selected item binding & Use filter instead of data change
Jack251970 Apr 25, 2025
4283ef5
Enlarge update flow number
Jack251970 Apr 27, 2025
0347703
Remove update lock
Jack251970 Apr 27, 2025
ebaffc6
Fix result update issue
Jack251970 Apr 27, 2025
d446824
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 29, 2025
cb673f6
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 30, 2025
96eb673
Merge branch 'dev' into delete_clipboard_jsonrpc
Jack251970 Apr 30, 2025
68e1aad
Revert logic change
Jack251970 Apr 30, 2025
1cec01c
Merge branch 'delete_clipboard_jsonrpc' of https://github.com/Jack251…
Jack251970 Apr 30, 2025
d023ecd
Make ConstructQuery async
Jack251970 May 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Flow.Launcher.Core/Plugin/QueryBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Flow.Launcher.Plugin;

Expand Down Expand Up @@ -33,7 +33,7 @@ public static Query Build(string text, Dictionary<string, PluginPair> nonGlobalP
searchTerms = terms;
}

return new Query ()
return new Query()
{
Search = search,
RawQuery = rawQuery,
Expand All @@ -42,4 +42,4 @@ public static Query Build(string text, Dictionary<string, PluginPair> nonGlobalP
};
}
}
}
}
20 changes: 10 additions & 10 deletions Flow.Launcher.Core/Resource/Theme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public Theme(IPublicAPI publicAPI, Settings settings)
{
_api.LogError(ClassName, "Current theme resource not found. Initializing with default theme.");
_oldTheme = Constant.DefaultTheme;
};
}
}

#endregion
Expand Down Expand Up @@ -126,7 +126,7 @@ public void UpdateFonts()
// Load a ResourceDictionary for the specified theme.
var themeName = _settings.Theme;
var dict = GetThemeResourceDictionary(themeName);

// Apply font settings to the theme resource.
ApplyFontSettings(dict);
UpdateResourceDictionary(dict);
Expand All @@ -152,11 +152,11 @@ private void ApplyFontSettings(ResourceDictionary dict)
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.QueryBoxFontStyle);
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.QueryBoxFontWeight);
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.QueryBoxFontStretch);

SetFontProperties(queryBoxStyle, fontFamily, fontStyle, fontWeight, fontStretch, true);
SetFontProperties(querySuggestionBoxStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
}

if (dict["ItemTitleStyle"] is Style resultItemStyle &&
dict["ItemTitleSelectedStyle"] is Style resultItemSelectedStyle &&
dict["ItemHotkeyStyle"] is Style resultHotkeyItemStyle &&
Expand All @@ -172,7 +172,7 @@ private void ApplyFontSettings(ResourceDictionary dict)
SetFontProperties(resultHotkeyItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
SetFontProperties(resultHotkeyItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
}

if (dict["ItemSubTitleStyle"] is Style resultSubItemStyle &&
dict["ItemSubTitleSelectedStyle"] is Style resultSubItemSelectedStyle)
{
Expand All @@ -197,7 +197,7 @@ private static void SetFontProperties(Style style, FontFamily fontFamily, FontSt
// First, find the setters to remove and store them in a list
var settersToRemove = style.Setters
.OfType<Setter>()
.Where(setter =>
.Where(setter =>
setter.Property == Control.FontFamilyProperty ||
setter.Property == Control.FontStyleProperty ||
setter.Property == Control.FontWeightProperty ||
Expand Down Expand Up @@ -227,18 +227,18 @@ private static void SetFontProperties(Style style, FontFamily fontFamily, FontSt
{
var settersToRemove = style.Setters
.OfType<Setter>()
.Where(setter =>
.Where(setter =>
setter.Property == TextBlock.FontFamilyProperty ||
setter.Property == TextBlock.FontStyleProperty ||
setter.Property == TextBlock.FontWeightProperty ||
setter.Property == TextBlock.FontStretchProperty)
.ToList();

foreach (var setter in settersToRemove)
{
style.Setters.Remove(setter);
}

style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, fontFamily));
style.Setters.Add(new Setter(TextBlock.FontStyleProperty, fontStyle));
style.Setters.Add(new Setter(TextBlock.FontWeightProperty, fontWeight));
Expand Down Expand Up @@ -421,7 +421,7 @@ public bool ChangeTheme(string theme = null)

// Retrieve theme resource – always use the resource with font settings applied.
var resourceDict = GetResourceDictionary(theme);

UpdateResourceDictionary(resourceDict);

_settings.Theme = theme;
Expand Down
5 changes: 4 additions & 1 deletion Flow.Launcher.Infrastructure/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ MONITORINFOEXW
WM_ENTERSIZEMOVE
WM_EXITSIZEMOVE

OleInitialize
OleUninitialize

GetKeyboardLayout
GetWindowThreadProcessId
ActivateKeyboardLayout
Expand All @@ -53,4 +56,4 @@ INPUTLANGCHANGE_FORWARD
LOCALE_TRANSIENT_KEYBOARD1
LOCALE_TRANSIENT_KEYBOARD2
LOCALE_TRANSIENT_KEYBOARD3
LOCALE_TRANSIENT_KEYBOARD4
LOCALE_TRANSIENT_KEYBOARD4
67 changes: 54 additions & 13 deletions Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
using System;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace Flow.Launcher.Infrastructure.UserSettings
{
#region Base

public abstract class ShortcutBaseModel
{
public string Key { get; set; }

[JsonIgnore]
public Func<string> Expand { get; set; } = () => { return ""; };

public override bool Equals(object obj)
{
return obj is ShortcutBaseModel other &&
Expand All @@ -22,16 +22,14 @@ public override int GetHashCode()
}
}

public class CustomShortcutModel : ShortcutBaseModel
public class BaseCustomShortcutModel : ShortcutBaseModel
{
public string Value { get; set; }

[JsonConstructorAttribute]
public CustomShortcutModel(string key, string value)
public BaseCustomShortcutModel(string key, string value)
{
Key = key;
Value = value;
Expand = () => { return Value; };
}

public void Deconstruct(out string key, out string value)
Expand All @@ -40,26 +38,69 @@ public void Deconstruct(out string key, out string value)
value = Value;
}

public static implicit operator (string Key, string Value)(CustomShortcutModel shortcut)
public static implicit operator (string Key, string Value)(BaseCustomShortcutModel shortcut)
{
return (shortcut.Key, shortcut.Value);
}

public static implicit operator CustomShortcutModel((string Key, string Value) shortcut)
public static implicit operator BaseCustomShortcutModel((string Key, string Value) shortcut)
{
return new CustomShortcutModel(shortcut.Key, shortcut.Value);
return new BaseCustomShortcutModel(shortcut.Key, shortcut.Value);
}
}

public class BuiltinShortcutModel : ShortcutBaseModel
public class BaseBuiltinShortcutModel : ShortcutBaseModel
{
public string Description { get; set; }

public BuiltinShortcutModel(string key, string description, Func<string> expand)
public BaseBuiltinShortcutModel(string key, string description)
{
Key = key;
Description = description;
Expand = expand ?? (() => { return ""; });
}
}

#endregion

#region Custom Shortcut

public class CustomShortcutModel : BaseCustomShortcutModel
{
[JsonIgnore]
public Func<string> Expand { get; set; } = () => { return string.Empty; };

[JsonConstructor]
public CustomShortcutModel(string key, string value) : base(key, value)
{
Expand = () => { return Value; };
}
}

#endregion

#region Builtin Shortcut

public class BuiltinShortcutModel : BaseBuiltinShortcutModel
{
[JsonIgnore]
public Func<string> Expand { get; set; } = () => { return string.Empty; };

public BuiltinShortcutModel(string key, string description, Func<string> expand) : base(key, description)
{
Expand = expand ?? (() => { return string.Empty; });
}
}

public class AsyncBuiltinShortcutModel : BaseBuiltinShortcutModel
{
[JsonIgnore]
public Func<Task<string>> ExpandAsync { get; set; } = () => { return Task.FromResult(string.Empty); };

public AsyncBuiltinShortcutModel(string key, string description, Func<Task<string>> expandAsync) : base(key, description)
{
ExpandAsync = expandAsync ?? (() => { return Task.FromResult(string.Empty); });
}
}

#endregion
}
4 changes: 2 additions & 2 deletions Flow.Launcher.Infrastructure/UserSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ public bool KeepMaxResults
public ObservableCollection<CustomShortcutModel> CustomShortcuts { get; set; } = new ObservableCollection<CustomShortcutModel>();

[JsonIgnore]
public ObservableCollection<BuiltinShortcutModel> BuiltinShortcuts { get; set; } = new()
public ObservableCollection<BaseBuiltinShortcutModel> BuiltinShortcuts { get; set; } = new()
{
new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText),
new AsyncBuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", () => Win32Helper.StartSTATaskAsync(Clipboard.GetText)),
new BuiltinShortcutModel("{active_explorer_path}", "shortcut_active_explorer_path", FileExplorerHelper.GetActiveExplorerPath)
};

Expand Down
74 changes: 74 additions & 0 deletions Flow.Launcher.Infrastructure/Win32Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Markup;
Expand Down Expand Up @@ -337,6 +339,78 @@ internal static HWND GetWindowHandle(Window window, bool ensure = false)

#endregion

#region STA Thread

/*
Inspired by https://github.com/files-community/Files code on STA Thread handling.
*/

public static Task StartSTATaskAsync(Action action)
{
var taskCompletionSource = new TaskCompletionSource();
Thread thread = new(() =>
{
PInvoke.OleInitialize();

try
{
action();
taskCompletionSource.SetResult();
}
catch (System.Exception ex)
{
taskCompletionSource.SetException(ex);
}
finally
{
PInvoke.OleUninitialize();
}
})
{
IsBackground = true,
Priority = ThreadPriority.Normal
};

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

return taskCompletionSource.Task;
}

public static Task<T> StartSTATaskAsync<T>(Func<T> func)
{
var taskCompletionSource = new TaskCompletionSource<T>();

Thread thread = new(() =>
{
PInvoke.OleInitialize();

try
{
taskCompletionSource.SetResult(func());
}
catch (System.Exception ex)
{
taskCompletionSource.SetException(ex);
}
finally
{
PInvoke.OleUninitialize();
}
})
{
IsBackground = true,
Priority = ThreadPriority.Normal
};

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

return taskCompletionSource.Task;
}

#endregion

#region Keyboard Layout

private const string UserProfileRegistryPath = @"Control Panel\International\User Profile";
Expand Down
5 changes: 4 additions & 1 deletion Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,11 @@ public interface IPublicAPI
public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default);

/// <summary>
/// Get the plugin manifest
/// Get the plugin manifest.
/// </summary>
/// <remarks>
/// If Flow cannot get manifest data, this could be null
/// </remarks>
/// <returns></returns>
public IReadOnlyList<UserPlugin> GetPluginManifest();

Expand Down
7 changes: 4 additions & 3 deletions Flow.Launcher.Plugin/Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace Flow.Launcher.Plugin
public class Query
{
/// <summary>
/// Raw query, this includes action keyword if it has
/// Raw query, this includes action keyword if it has.
/// It has handled buildin custom query shortkeys and build-in shortcuts, and it trims the whitespace.
/// We didn't recommend use this property directly. You should always use Search property.
/// </summary>
public string RawQuery { get; internal init; }
Expand Down Expand Up @@ -63,10 +64,10 @@ public class Query
/// </remarks>
[JsonIgnore]
public string FirstSearch => SplitSearch(0);

[JsonIgnore]
private string _secondToEndSearch;

/// <summary>
/// strings from second search (including) to last search
/// </summary>
Expand Down
Loading
Loading