mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into rename-file
This commit is contained in:
commit
11dbce65c4
69 changed files with 628 additions and 350 deletions
2
.github/workflows/default_plugins.yml
vendored
2
.github/workflows/default_plugins.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
|
|
|
|||
2
.github/workflows/dotnet.yml
vendored
2
.github/workflows/dotnet.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
NUGET_CERT_REVOCATION_MODE: offline
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set Flow.Launcher.csproj version
|
||||
id: update
|
||||
uses: vers-one/dotnet-project-version-updater@v1.7
|
||||
|
|
|
|||
2
.github/workflows/release_pr.yml
vendored
2
.github/workflows/release_pr.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
update-pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
|
||||
<!-- Work around https://github.com/dotnet/runtime/issues/109682 -->
|
||||
<CETCompat>false</CETCompat>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -11,6 +11,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
{
|
||||
internal class PythonEnvironment : AbstractPluginEnvironment
|
||||
{
|
||||
private static readonly string ClassName = nameof(PythonEnvironment);
|
||||
|
||||
internal override string Language => AllowedLanguage.Python;
|
||||
|
||||
internal override string EnvName => DataLocation.PythonEnvironmentName;
|
||||
|
|
@ -39,9 +41,20 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
|
||||
// Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and
|
||||
// uses Python plugin they need to custom install and use v3.8.9
|
||||
JTF.Run(() => DroplexPackage.Drop(App.python_3_11_4_embeddable, InstallPath));
|
||||
JTF.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DroplexPackage.Drop(App.python_3_11_4_embeddable, InstallPath);
|
||||
|
||||
PluginsSettingsFilePath = ExecutablePath;
|
||||
PluginsSettingsFilePath = ExecutablePath;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
API.ShowMsgError(API.GetTranslation("failToInstallPythonEnv"));
|
||||
API.LogException(ClassName, "Failed to install Python environment", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal override PluginPair CreatePluginPair(string filePath, PluginMetadata metadata)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
{
|
||||
internal class TypeScriptEnvironment : AbstractPluginEnvironment
|
||||
{
|
||||
private static readonly string ClassName = nameof(TypeScriptEnvironment);
|
||||
|
||||
internal override string Language => AllowedLanguage.TypeScript;
|
||||
|
||||
internal override string EnvName => DataLocation.NodeEnvironmentName;
|
||||
|
|
@ -34,9 +36,20 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
{
|
||||
FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s));
|
||||
|
||||
JTF.Run(() => DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath));
|
||||
JTF.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath);
|
||||
|
||||
PluginsSettingsFilePath = ExecutablePath;
|
||||
PluginsSettingsFilePath = ExecutablePath;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
API.ShowMsgError(API.GetTranslation("failToInstallTypeScriptEnv"));
|
||||
API.LogException(ClassName, "Failed to install TypeScript environment", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal override PluginPair CreatePluginPair(string filePath, PluginMetadata metadata)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
{
|
||||
internal class TypeScriptV2Environment : AbstractPluginEnvironment
|
||||
{
|
||||
private static readonly string ClassName = nameof(TypeScriptV2Environment);
|
||||
|
||||
internal override string Language => AllowedLanguage.TypeScriptV2;
|
||||
|
||||
internal override string EnvName => DataLocation.NodeEnvironmentName;
|
||||
|
|
@ -34,9 +36,20 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
{
|
||||
FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s));
|
||||
|
||||
JTF.Run(() => DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath));
|
||||
JTF.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath);
|
||||
|
||||
PluginsSettingsFilePath = ExecutablePath;
|
||||
PluginsSettingsFilePath = ExecutablePath;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
API.ShowMsgError(API.GetTranslation("failToInstallTypeScriptEnv"));
|
||||
API.LogException(ClassName, "Failed to install TypeScript environment", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal override PluginPair CreatePluginPair(string filePath, PluginMetadata metadata)
|
||||
|
|
|
|||
|
|
@ -124,13 +124,9 @@ namespace Flow.Launcher.Core.Plugin
|
|||
API.GetTranslation("pluginsHaveErrored") :
|
||||
API.GetTranslation("pluginHasErrored");
|
||||
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
API.ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
|
||||
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
|
||||
API.GetTranslation("referToLogs"), string.Empty,
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
});
|
||||
API.ShowMsgError($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
|
||||
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
|
||||
API.GetTranslation("referToLogs"));
|
||||
}
|
||||
|
||||
return plugins;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace Flow.Launcher.Core.Resource
|
|||
public static Language German = new Language("de", "Deutsch");
|
||||
public static Language Korean = new Language("ko", "한국어");
|
||||
public static Language Serbian = new Language("sr", "Srpski");
|
||||
public static Language Serbian_Cyrillic = new Language("sr-Cyrl-RS", "Српски");
|
||||
public static Language Portuguese_Portugal = new Language("pt-pt", "Português");
|
||||
public static Language Portuguese_Brazil = new Language("pt-br", "Português (Brasil)");
|
||||
public static Language Spanish = new Language("es", "Spanish");
|
||||
|
|
@ -47,6 +48,7 @@ namespace Flow.Launcher.Core.Resource
|
|||
German,
|
||||
Korean,
|
||||
Serbian,
|
||||
Serbian_Cyrillic,
|
||||
Portuguese_Portugal,
|
||||
Portuguese_Brazil,
|
||||
Spanish,
|
||||
|
|
@ -79,7 +81,8 @@ namespace Flow.Launcher.Core.Resource
|
|||
"da" => "System",
|
||||
"de" => "System",
|
||||
"ko" => "시스템",
|
||||
"sr" => "Систем",
|
||||
"sr" => "Sistem",
|
||||
"sr-Cyrl-RS" => "Систем",
|
||||
"pt-pt" => "Sistema",
|
||||
"pt-br" => "Sistema",
|
||||
"es" => "Sistema",
|
||||
|
|
|
|||
|
|
@ -161,8 +161,8 @@
|
|||
},
|
||||
"Microsoft.Win32.SystemEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.7",
|
||||
"contentHash": "lFGY2aGgmMREPJEfOmZcA6v0CLjWVpcfNHRgqYMoSQhy80+GxhYqdW5xe+DCLrVqE1M7/0RpOkIo49/KH/cd/A=="
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
|
||||
},
|
||||
"Mono.Cecil": {
|
||||
"type": "Transitive",
|
||||
|
|
@ -222,10 +222,10 @@
|
|||
},
|
||||
"System.Drawing.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.7",
|
||||
"contentHash": "1k/Pk7hcM3vP2tfIRRS2ECCCN7ya+hvocsM1JMc4ZDCU6qw7yOuUmqmCDfgXZ4Q4FS6jass2EAai5ByKodDi0g==",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.SystemEvents": "9.0.7"
|
||||
"Microsoft.Win32.SystemEvents": "7.0.0"
|
||||
}
|
||||
},
|
||||
"System.IO.Pipelines": {
|
||||
|
|
@ -262,7 +262,7 @@
|
|||
"NLog": "[6.0.1, )",
|
||||
"NLog.OutputDebugString": "[6.0.1, )",
|
||||
"SharpVectors.Wpf": "[1.8.4.2, )",
|
||||
"System.Drawing.Common": "[9.0.7, )",
|
||||
"System.Drawing.Common": "[7.0.0, )",
|
||||
"ToolGood.Words.Pinyin": "[3.1.0.3, )"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -74,7 +74,9 @@
|
|||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SharpVectors.Wpf" Version="1.8.4.2" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.7" />
|
||||
<!-- Do not upgrade this to higher version since it can cause this issue on WinForm platform: -->
|
||||
<!-- PlatformNotSupportedException: SystemEvents is not supported on this platform. -->
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="ToolGood.Words.Pinyin" Version="3.1.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -108,11 +108,11 @@
|
|||
},
|
||||
"System.Drawing.Common": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.7, )",
|
||||
"resolved": "9.0.7",
|
||||
"contentHash": "1k/Pk7hcM3vP2tfIRRS2ECCCN7ya+hvocsM1JMc4ZDCU6qw7yOuUmqmCDfgXZ4Q4FS6jass2EAai5ByKodDi0g==",
|
||||
"requested": "[7.0.0, )",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.SystemEvents": "9.0.7"
|
||||
"Microsoft.Win32.SystemEvents": "7.0.0"
|
||||
}
|
||||
},
|
||||
"ToolGood.Words.Pinyin": {
|
||||
|
|
@ -156,8 +156,8 @@
|
|||
},
|
||||
"Microsoft.Win32.SystemEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.7",
|
||||
"contentHash": "lFGY2aGgmMREPJEfOmZcA6v0CLjWVpcfNHRgqYMoSQhy80+GxhYqdW5xe+DCLrVqE1M7/0RpOkIo49/KH/cd/A=="
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
|
|
|
|||
|
|
@ -57,7 +57,10 @@ namespace Flow.Launcher.Plugin
|
|||
/// for user on the plugin result. If autocomplete action for example is tab, pressing tab will have
|
||||
/// the default constructed autocomplete text (result's Title), or the text provided here if not empty.
|
||||
/// </summary>
|
||||
/// <remarks>When a value is not set, the <see cref="Title"/> will be used.</remarks>
|
||||
/// <remarks>
|
||||
/// When a value is not set, the <see cref="Title"/> will be used.
|
||||
/// Please include the action keyword prefix when necessary because Flow does not prepend it automatically.
|
||||
/// </remarks>
|
||||
public string AutoCompleteText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -257,6 +260,17 @@ namespace Flow.Launcher.Plugin
|
|||
/// </summary>
|
||||
public bool ShowBadge { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// This holds the text which can be shown as a query suggestion.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When a value is not set, the <see cref="Title"/> will be used.
|
||||
/// Do not include the action keyword prefix because Flow prepends it automatically.
|
||||
/// If the it does not start with the query text, it will not be shown as a suggestion.
|
||||
/// So make sure to set this value to start with the query text.
|
||||
/// </remarks>
|
||||
public string QuerySuggestionText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of hotkey IDs that are supported for this result.
|
||||
/// Those hotkeys should be registered by IPluginHotkey interface.
|
||||
|
|
@ -314,6 +328,7 @@ namespace Flow.Launcher.Plugin
|
|||
AddSelectedCount = AddSelectedCount,
|
||||
RecordKey = RecordKey,
|
||||
ShowBadge = ShowBadge,
|
||||
QuerySuggestionText = QuerySuggestionText,
|
||||
HotkeyIds = HotkeyIds,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,6 +297,7 @@ namespace Flow.Launcher
|
|||
});
|
||||
}
|
||||
|
||||
[Conditional("RELEASE")]
|
||||
private static void AutoPluginUpdates()
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
|
|
|
|||
|
|
@ -33,15 +33,39 @@ public class QuerySuggestionBoxConverter : IMultiValueConverter
|
|||
{
|
||||
var selectedResult = selectedItem.Result;
|
||||
var selectedResultActionKeyword = string.IsNullOrEmpty(selectedResult.ActionKeywordAssigned) ? "" : selectedResult.ActionKeywordAssigned + " ";
|
||||
var selectedResultPossibleSuggestion = selectedResultActionKeyword + selectedResult.Title;
|
||||
|
||||
if (!selectedResultPossibleSuggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
|
||||
string selectedResultPossibleSuggestion = null;
|
||||
|
||||
// Firstly check if the result has QuerySuggestionText
|
||||
if (!string.IsNullOrEmpty(selectedResult.QuerySuggestionText))
|
||||
{
|
||||
selectedResultPossibleSuggestion = selectedResultActionKeyword + selectedResult.QuerySuggestionText;
|
||||
|
||||
// If this QuerySuggestionText does not start with the queryText, set it to null
|
||||
if (!selectedResultPossibleSuggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
selectedResultPossibleSuggestion = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Then check Title as suggestion
|
||||
if (string.IsNullOrEmpty(selectedResultPossibleSuggestion))
|
||||
{
|
||||
selectedResultPossibleSuggestion = selectedResultActionKeyword + selectedResult.Title;
|
||||
|
||||
// If this QuerySuggestionText does not start with the queryText, set it to null
|
||||
if (!selectedResultPossibleSuggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
selectedResultPossibleSuggestion = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(selectedResultPossibleSuggestion))
|
||||
return string.Empty;
|
||||
|
||||
|
||||
// For AutocompleteQueryCommand.
|
||||
// When user typed lower case and result title is uppercase, we still want to display suggestion
|
||||
selectedItem.QuerySuggestionText = queryText + selectedResultPossibleSuggestion.Substring(queryText.Length);
|
||||
selectedItem.QuerySuggestionText = string.Concat(queryText, selectedResultPossibleSuggestion.AsSpan(queryText.Length));
|
||||
|
||||
// Check if Text will be larger than our QueryTextBox
|
||||
Typeface typeface = new Typeface(queryTextBox.FontFamily, queryTextBox.FontStyle, queryTextBox.FontWeight, queryTextBox.FontStretch);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,48 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="RemoveUnnecessaryRuntimesAfterBuild" AfterTargets="Build">
|
||||
<RemoveDir Directories="$(OutputPath)runtimes\browser-wasm;
|
||||
$(OutputPath)runtimes\linux-arm;
|
||||
$(OutputPath)runtimes\linux-arm64;
|
||||
$(OutputPath)runtimes\linux-armel;
|
||||
$(OutputPath)runtimes\linux-mips64;
|
||||
$(OutputPath)runtimes\linux-musl-arm;
|
||||
$(OutputPath)runtimes\linux-musl-arm64;
|
||||
$(OutputPath)runtimes\linux-musl-x64;
|
||||
$(OutputPath)runtimes\linux-musl-s390x;
|
||||
$(OutputPath)runtimes\linux-ppc64le;
|
||||
$(OutputPath)runtimes\linux-s390x;
|
||||
$(OutputPath)runtimes\linux-x64;
|
||||
$(OutputPath)runtimes\linux-x86;
|
||||
$(OutputPath)runtimes\maccatalyst-arm64;
|
||||
$(OutputPath)runtimes\maccatalyst-x64;
|
||||
$(OutputPath)runtimes\osx;
|
||||
$(OutputPath)runtimes\osx-arm64;
|
||||
$(OutputPath)runtimes\osx-x64"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="RemoveUnnecessaryRuntimesAfterPublish" AfterTargets="Publish">
|
||||
<RemoveDir Directories="$(PublishDir)runtimes\browser-wasm;
|
||||
$(PublishDir)runtimes\linux-arm;
|
||||
$(PublishDir)runtimes\linux-arm64;
|
||||
$(PublishDir)runtimes\linux-armel;
|
||||
$(PublishDir)runtimes\linux-mips64;
|
||||
$(PublishDir)runtimes\linux-musl-arm;
|
||||
$(PublishDir)runtimes\linux-musl-arm64;
|
||||
$(PublishDir)runtimes\linux-musl-x64;
|
||||
$(PublishDir)runtimes\linux-musl-s390x;
|
||||
$(PublishDir)runtimes\linux-ppc64le;
|
||||
$(PublishDir)runtimes\linux-s390x;
|
||||
$(PublishDir)runtimes\linux-x64;
|
||||
$(PublishDir)runtimes\linux-x86;
|
||||
$(PublishDir)runtimes\maccatalyst-arm64;
|
||||
$(PublishDir)runtimes\maccatalyst-x64;
|
||||
$(PublishDir)runtimes\osx;
|
||||
$(PublishDir)runtimes\osx-arm64;
|
||||
$(PublishDir)runtimes\osx-x64"/>
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Remove="App.xaml" />
|
||||
</ItemGroup>
|
||||
|
|
@ -136,7 +178,6 @@
|
|||
|
||||
<Target Name="RemoveDuplicateAnalyzers" BeforeTargets="CoreCompile">
|
||||
<!-- Work around https://github.com/dotnet/wpf/issues/6792 -->
|
||||
|
||||
<ItemGroup>
|
||||
<FilteredAnalyzer Include="@(Analyzer->Distinct())" />
|
||||
<Analyzer Remove="@(Analyzer)" />
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@
|
|||
<system:String x:Key="pleaseTryAgain">Please try again</system:String>
|
||||
<system:String x:Key="parseProxyFailed">Unable to parse Http Proxy</system:String>
|
||||
|
||||
<!-- AbstractPluginEnvironment -->
|
||||
<system:String x:Key="failToInstallTypeScriptEnv">Failed to install TypeScript environment. Please try again later</system:String>
|
||||
<system:String x:Key="failToInstallPythonEnv">Failed to install Python environment. Please try again later.</system:String>
|
||||
|
||||
<!-- MainWindow -->
|
||||
<system:String x:Key="registerHotkeyFailed">Failed to register hotkey "{0}". The hotkey may be in use by another program. Change to a different hotkey, or exit another program.</system:String>
|
||||
<system:String x:Key="unregisterHotkeyFailed">Failed to unregister hotkey "{0}". Please try again or see log for details</system:String>
|
||||
|
|
|
|||
|
|
@ -371,10 +371,8 @@
|
|||
MinHeight="380"
|
||||
MaxHeight="{Binding ElementName=ResultListBox, Path=ActualHeight}"
|
||||
Padding="0 0 10 10"
|
||||
d:DataContext="{d:DesignInstance vm:ResultViewModel}"
|
||||
DataContext="{Binding PreviewSelectedItem, Mode=OneWay}"
|
||||
Visibility="{Binding ShowCustomizedPreview}">
|
||||
<ContentControl Content="{Binding Result.PreviewPanel.Value}" />
|
||||
<ContentControl Content="{Binding CustomizedPreviewControl}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
|
@ -379,24 +380,35 @@ namespace Flow.Launcher
|
|||
explorer.Start();
|
||||
}
|
||||
}
|
||||
catch (COMException ex) when (ex.ErrorCode == unchecked((int)0x80004004))
|
||||
{
|
||||
/*
|
||||
* The COMException with HResult 0x80004004 is E_ABORT (operation aborted).
|
||||
* Shell APIs often return this when the operation is canceled or the shell cannot complete it cleanly.
|
||||
* It most likely comes from Win32Helper.OpenFolderAndSelectFile(targetPath).
|
||||
* Typical triggers:
|
||||
* The target file/folder was deleted/moved between computing targetPath and the shell call.
|
||||
* The folder is on an offline network/removable drive.
|
||||
* Explorer is restarting/busy and aborts the request.
|
||||
* A selection request to a new/closing Explorer window is canceled.
|
||||
* Because it is commonly user- or environment-driven and not actionable,
|
||||
* we should treat it as expected noise and ignore it to avoid bothering users.
|
||||
*/
|
||||
}
|
||||
catch (Win32Exception ex) when (ex.NativeErrorCode == 2)
|
||||
{
|
||||
LogError(ClassName, "File Manager not found");
|
||||
ShowMsgBox(
|
||||
string.Format(GetTranslation("fileManagerNotFound"), ex.Message),
|
||||
ShowMsgError(
|
||||
GetTranslation("fileManagerNotFoundTitle"),
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
string.Format(GetTranslation("fileManagerNotFound"), ex.Message)
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ClassName, "Failed to open folder", ex);
|
||||
ShowMsgBox(
|
||||
string.Format(GetTranslation("folderOpenError"), ex.Message),
|
||||
ShowMsgError(
|
||||
GetTranslation("errorTitle"),
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
string.Format(GetTranslation("folderOpenError"), ex.Message)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -424,11 +436,9 @@ namespace Flow.Launcher
|
|||
{
|
||||
var tabOrWindow = browserInfo.OpenInTab ? "tab" : "window";
|
||||
LogException(ClassName, $"Failed to open URL in browser {tabOrWindow}: {path}, {inPrivate ?? browserInfo.EnablePrivate}, {browserInfo.PrivateArg}", e);
|
||||
ShowMsgBox(
|
||||
GetTranslation("browserOpenError"),
|
||||
ShowMsgError(
|
||||
GetTranslation("errorTitle"),
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
GetTranslation("browserOpenError")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@
|
|||
FontSize="14"
|
||||
ItemContainerStyle="{StaticResource PluginList}"
|
||||
ItemsSource="{Binding Source={StaticResource PluginCollectionView}}"
|
||||
Loaded="PluginListBox_Loaded"
|
||||
ScrollViewer.CanContentScroll="False"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
SnapsToDevicePixels="True"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Navigation;
|
||||
|
|
@ -33,6 +35,14 @@ public partial class SettingsPanePlugins
|
|||
base.OnNavigatedTo(e);
|
||||
}
|
||||
|
||||
private void PluginListBox_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// After list is loaded, we need to clear selection to make sure all items can be mouse hovered
|
||||
// because the selected item cannot be hovered.
|
||||
if (sender is not ListBox listBox) return;
|
||||
listBox.SelectedIndex = -1;
|
||||
}
|
||||
|
||||
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(SettingsPanePluginsViewModel.FilterText))
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Threading.Channels;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
|
|
@ -890,6 +891,12 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
public Visibility ShowCustomizedPreview
|
||||
=> InternalPreviewVisible && PreviewSelectedItem?.Result.PreviewPanel != null ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
public UserControl CustomizedPreviewControl
|
||||
=> ShowCustomizedPreview == Visibility.Visible ? PreviewSelectedItem?.Result.PreviewPanel.Value : null;
|
||||
|
||||
public Visibility ProgressBarVisibility { get; set; }
|
||||
public Visibility MainWindowVisibility { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -37,12 +37,17 @@ namespace Flow.Launcher.ViewModel
|
|||
OnPropertyChanged(nameof(Image));
|
||||
}
|
||||
|
||||
private bool _imageLoaded = false;
|
||||
|
||||
public ImageSource Image
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_image == ImageLoader.MissingImage)
|
||||
if (!_imageLoaded)
|
||||
{
|
||||
_imageLoaded = true;
|
||||
_ = LoadIconAsync();
|
||||
}
|
||||
|
||||
return _image;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,8 +66,6 @@ namespace Flow.Launcher.ViewModel
|
|||
|
||||
public Visibility ShowDefaultPreview => Result.PreviewPanel == null ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
public Visibility ShowCustomizedPreview => Result.PreviewPanel == null ? Visibility.Collapsed : Visibility.Visible;
|
||||
|
||||
public Visibility ShowIcon
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -552,8 +552,8 @@
|
|||
},
|
||||
"Microsoft.Win32.SystemEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.7",
|
||||
"contentHash": "lFGY2aGgmMREPJEfOmZcA6v0CLjWVpcfNHRgqYMoSQhy80+GxhYqdW5xe+DCLrVqE1M7/0RpOkIo49/KH/cd/A=="
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
|
||||
},
|
||||
"Mono.Cecil": {
|
||||
"type": "Transitive",
|
||||
|
|
@ -677,10 +677,10 @@
|
|||
},
|
||||
"System.Drawing.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.7",
|
||||
"contentHash": "1k/Pk7hcM3vP2tfIRRS2ECCCN7ya+hvocsM1JMc4ZDCU6qw7yOuUmqmCDfgXZ4Q4FS6jass2EAai5ByKodDi0g==",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.SystemEvents": "9.0.7"
|
||||
"Microsoft.Win32.SystemEvents": "7.0.0"
|
||||
}
|
||||
},
|
||||
"System.Globalization": {
|
||||
|
|
@ -862,7 +862,7 @@
|
|||
"NLog": "[6.0.1, )",
|
||||
"NLog.OutputDebugString": "[6.0.1, )",
|
||||
"SharpVectors.Wpf": "[1.8.4.2, )",
|
||||
"System.Drawing.Common": "[9.0.7, )",
|
||||
"System.Drawing.Common": "[7.0.0, )",
|
||||
"ToolGood.Words.Pinyin": "[3.1.0.3, )"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Flow.Launcher.Plugin.BrowserBookmark.Helper;
|
||||
|
|
@ -134,10 +135,6 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader
|
|||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(bookmark.Url))
|
||||
return;
|
||||
|
||||
// Extract domain from URL
|
||||
if (!Uri.TryCreate(bookmark.Url, UriKind.Absolute, out Uri uri))
|
||||
return;
|
||||
|
||||
|
|
@ -146,43 +143,49 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader
|
|||
// Query for latest Firefox version favicon structure
|
||||
using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = @"
|
||||
SELECT i.data
|
||||
SELECT i.id, i.data
|
||||
FROM moz_icons i
|
||||
JOIN moz_icons_to_pages ip ON i.id = ip.icon_id
|
||||
JOIN moz_pages_w_icons p ON ip.page_id = p.id
|
||||
WHERE p.page_url LIKE @url
|
||||
AND i.data IS NOT NULL
|
||||
ORDER BY i.width DESC -- Select largest icon available
|
||||
WHERE p.page_url LIKE @domain
|
||||
ORDER BY i.width DESC
|
||||
LIMIT 1";
|
||||
|
||||
cmd.Parameters.AddWithValue("@url", $"%{domain}%");
|
||||
cmd.Parameters.AddWithValue("@domain", $"%{domain}%");
|
||||
|
||||
using var reader = cmd.ExecuteReader();
|
||||
if (!reader.Read() || reader.IsDBNull(0))
|
||||
if (!reader.Read() || reader.IsDBNull(1))
|
||||
return;
|
||||
|
||||
var iconId = reader.GetInt64(0).ToString();
|
||||
var imageData = (byte[])reader["data"];
|
||||
|
||||
if (imageData is not { Length: > 0 })
|
||||
return;
|
||||
|
||||
string faviconPath;
|
||||
if (FaviconHelper.IsSvgData(imageData))
|
||||
// Check if the image data is compressed (GZip)
|
||||
if (imageData.Length > 2 && imageData[0] == 0x1f && imageData[1] == 0x8b)
|
||||
{
|
||||
faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.svg");
|
||||
}
|
||||
else
|
||||
{
|
||||
faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png");
|
||||
using var inputStream = new MemoryStream(imageData);
|
||||
using var gZipStream = new GZipStream(inputStream, CompressionMode.Decompress);
|
||||
using var outputStream = new MemoryStream();
|
||||
gZipStream.CopyTo(outputStream);
|
||||
imageData = outputStream.ToArray();
|
||||
}
|
||||
|
||||
// Filter out duplicate favicons
|
||||
if (savedPaths.TryAdd(faviconPath, true))
|
||||
// Convert the image data to WebP format
|
||||
var webpData = FaviconHelper.TryConvertToWebp(imageData);
|
||||
if (webpData != null)
|
||||
{
|
||||
FaviconHelper.SaveBitmapData(imageData, faviconPath);
|
||||
}
|
||||
var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}_{iconId}.webp");
|
||||
|
||||
bookmark.FaviconPath = faviconPath;
|
||||
if (savedPaths.TryAdd(faviconPath, true))
|
||||
{
|
||||
FaviconHelper.SaveBitmapData(webpData, faviconPath);
|
||||
}
|
||||
|
||||
bookmark.FaviconPath = faviconPath;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,12 +45,14 @@
|
|||
$(OutputPath)runtimes\linux-musl-arm;
|
||||
$(OutputPath)runtimes\linux-musl-arm64;
|
||||
$(OutputPath)runtimes\linux-musl-x64;
|
||||
$(OutputPath)runtimes\linux-musl-s390x;
|
||||
$(OutputPath)runtimes\linux-ppc64le;
|
||||
$(OutputPath)runtimes\linux-s390x;
|
||||
$(OutputPath)runtimes\linux-x64;
|
||||
$(OutputPath)runtimes\linux-x86;
|
||||
$(OutputPath)runtimes\maccatalyst-arm64;
|
||||
$(OutputPath)runtimes\maccatalyst-x64;
|
||||
$(OutputPath)runtimes\osx;
|
||||
$(OutputPath)runtimes\osx-arm64;
|
||||
$(OutputPath)runtimes\osx-x64"/>
|
||||
</Target>
|
||||
|
|
@ -64,12 +66,14 @@
|
|||
$(PublishDir)runtimes\linux-musl-arm;
|
||||
$(PublishDir)runtimes\linux-musl-arm64;
|
||||
$(PublishDir)runtimes\linux-musl-x64;
|
||||
$(PublishDir)runtimes\linux-musl-s390x;
|
||||
$(PublishDir)runtimes\linux-ppc64le;
|
||||
$(PublishDir)runtimes\linux-s390x;
|
||||
$(PublishDir)runtimes\linux-x64;
|
||||
$(PublishDir)runtimes\linux-x86;
|
||||
$(PublishDir)runtimes\maccatalyst-arm64;
|
||||
$(PublishDir)runtimes\maccatalyst-x64;
|
||||
$(PublishDir)runtimes\osx;
|
||||
$(PublishDir)runtimes\osx-arm64;
|
||||
$(PublishDir)runtimes\osx-x64"/>
|
||||
</Target>
|
||||
|
|
@ -96,7 +100,9 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.4" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.8" />
|
||||
<PackageReference Include="Svg.Skia" Version="3.0.4" />
|
||||
<PackageReference Include="SkiaSharp" Version="3.119.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using SkiaSharp;
|
||||
using Svg.Skia;
|
||||
|
||||
namespace Flow.Launcher.Plugin.BrowserBookmark.Helper;
|
||||
|
||||
|
|
@ -65,12 +67,58 @@ public static class FaviconHelper
|
|||
}
|
||||
}
|
||||
|
||||
public static bool IsSvgData(byte[] data)
|
||||
public static byte[] TryConvertToWebp(byte[] data)
|
||||
{
|
||||
if (data.Length < 5)
|
||||
return false;
|
||||
string start = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(100, data.Length));
|
||||
return start.Contains("<svg") ||
|
||||
(start.StartsWith("<?xml") && start.Contains("<svg"));
|
||||
if (data == null || data.Length == 0)
|
||||
return null;
|
||||
|
||||
SKBitmap bitmap = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var ms = new MemoryStream(data))
|
||||
{
|
||||
var svg = new SKSvg();
|
||||
if (svg.Load(ms) != null && svg.Picture != null)
|
||||
{
|
||||
bitmap = new SKBitmap((int)svg.Picture.CullRect.Width, (int)svg.Picture.CullRect.Height);
|
||||
using (var canvas = new SKCanvas(bitmap))
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
canvas.DrawPicture(svg.Picture);
|
||||
canvas.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { /* Not an SVG */ }
|
||||
|
||||
if (bitmap == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
bitmap = SKBitmap.Decode(data);
|
||||
}
|
||||
catch { /* Not a decodable bitmap */ }
|
||||
}
|
||||
|
||||
if (bitmap != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var image = SKImage.FromBitmap(bitmap))
|
||||
using (var webp = image.Encode(SKEncodedImageFormat.Webp, 65))
|
||||
{
|
||||
if (webp != null)
|
||||
return webp.ToArray();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,26 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex
|
|||
_faviconCacheDir = Path.Combine(
|
||||
context.CurrentPluginMetadata.PluginCacheDirectoryPath,
|
||||
"FaviconCache");
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(_faviconCacheDir))
|
||||
{
|
||||
var files = Directory.GetFiles(_faviconCacheDir);
|
||||
foreach (var file in files)
|
||||
{
|
||||
var extension = Path.GetExtension(file);
|
||||
if (extension is ".db-shm" or ".db-wal" or ".sqlite-shm" or ".sqlite-wal")
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Context.API.LogException(ClassName, "Failed to clean up orphaned cache files.", e);
|
||||
}
|
||||
|
||||
LoadBookmarksIfEnabled();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">آلة حاسبة</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">تمكنك من إجراء العمليات الحسابية. (جرب 5*3-2 في Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">آلة حاسبة</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">تمكنك من إجراء العمليات الحسابية. (جرب 5*3-2 في Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">ليست رقمًا (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">التعبير خاطئ أو غير مكتمل (هل نسيت بعض الأقواس؟)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">نسخ هذا الرقم إلى الحافظة</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Kalkulačka</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Umožňuje provádět matematické výpočty.(Try 5*3-2 v průtokovém spouštěči)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Kalkulačka</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Umožňuje provádět matematické výpočty.(Try 5*3-2 v průtokovém spouštěči)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Není číslo (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Nesprávný nebo neúplný výraz (Nezapomněli jste na závorky?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Kopírování výsledku do schránky</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copy this number to the clipboard</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Rechner</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Ermöglicht mathematische Berechnungen. (Versuchen Sie 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Rechner</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Ermöglicht mathematische Berechnungen. (Versuchen Sie 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Nicht eine Zahl (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Ausdruck falsch oder unvollständig (Haben Sie einige Klammern vergessen?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Diese Zahl in die Zwischenablage kopieren</system:String>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place.</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copy this number to the clipboard</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Permite hacer cálculos matemáticos. (Pruebe con 5*3-2 en Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Permite hacer cálculos matemáticos. (Pruebe con 5*3-2 en Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">No es un número (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expresión incorrecta o incompleta (¿Olvidó algún paréntesis?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copiar este número al portapapeles</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Permite hacer cálculos matemáticos. (Pruebe 5*3-2 en Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Permite hacer cálculos matemáticos. (Pruebe 5*3-2 en Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">No es un número (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expresión incorrecta o incompleta (¿Ha olvidado algunos paréntesis?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copiar este número al portapapeles</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculatrice</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Permet de faire des calculs mathématiques.(Essayez 5*3-2 dans Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculatrice</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Permet de faire des calculs mathématiques.(Essayez 5*3-2 dans Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Pas un nombre (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression incorrecte ou incomplète (avez-vous oublié certaines parenthèses ?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copier ce chiffre dans le presse-papiers</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">מחשבון</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">מאפשר לבצע חישובים מתמטיים. (נסה 5*3-2 ב-Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">מחשבון</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">מאפשר לבצע חישובים מתמטיים. (נסה 5*3-2 ב-Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">לא מספר (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">הביטוי שגוי או לא שלם (האם שכחת סוגריים?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">העתק מספר זה ללוח</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calcolatrice</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Consente di eseguire calcoli matematici (provare 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calcolatrice</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Consente di eseguire calcoli matematici (provare 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Non è un numero (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Espressione sbagliata o incompleta (avete dimenticato delle parentesi?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copiare questo numero negli appunti</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">電卓</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">数式の計算ができます(Flow Launcherで「5*3-2」と入力してみてください)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">電卓</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">数式の計算ができます(Flow Launcherで「5*3-2」と入力してみてください)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">この数字をクリップボードにコピーします</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">계산기</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">수학 계산을 할 수 있습니다. Flow Launcher에서 5*3-2를 입력해보세요.</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">계산기</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">수학 계산을 할 수 있습니다. Flow Launcher에서 5*3-2를 입력해보세요.</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">숫자가 아님 (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">표현식이 잘못되었거나 불완전합니다. (괄호를 깜빡하셨나요?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">해당 숫자를 클립보드에 복사</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Kalkulator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Lar deg gjøre matematiske beregninger. (Prøv 5*3-2 i Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Kalkulator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Lar deg gjøre matematiske beregninger. (Prøv 5*3-2 i Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Ikke et tall (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Uttrykk feil eller ufullstendig (glem noen parenteser?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Kopier dette nummeret til utklippstavlen</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copy this number to the clipboard</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Kalkulator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Szybkie wykonywanie obliczeń matematycznych. (Spróbuj wpisać 5*3-2 w oknie Flow Launchera)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Kalkulator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Szybkie wykonywanie obliczeń matematycznych. (Spróbuj wpisać 5*3-2 w oknie Flow Launchera)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Nie liczba (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Wyrażenie niepoprawne lub niekompletne (Czy zapomniałeś o nawiasach?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Skopiuj ten numer do schowka</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Permite fazer cálculos matemáticos.(Tente 5*3-2 no Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Permite fazer cálculos matemáticos.(Tente 5*3-2 no Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Não é um número (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expressão errada ou incompleta (Você esqueceu de adicionar parênteses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copiar este numero para a área de transferência</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Permite a execução de cálculos matemáticos (experimente 5*3-2)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculadora</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Permite a execução de cálculos matemáticos (experimente 5*3-2)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Não é número (NN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expressão errada ou incompleta (esqueceu-se de algum parêntese?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copiar número para a área de transferência</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Калькулятор</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Позволяет выполнять математические вычисления. (Попробуйте 5*3-2 в Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Калькулятор</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Позволяет выполнять математические вычисления. (Попробуйте 5*3-2 в Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Не является числом (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Выражение неправильное или неполное (Вы забыли скобки?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Скопировать этот номер в буфер обмена</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Kalkulačka</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Spracúva matematické operácie. (Skúste 5*3-2 vo Flow Launcheri)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Kalkulačka</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Spracúva matematické operácie. (Skúste 5*3-2 vo Flow Launcheri)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Nie je číslo (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Nesprávny alebo neúplný výraz (Nezabudli ste na zátvorky?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Kopírovať výsledok do schránky</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Copy this number to the clipboard</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Hesap Makinesi</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Matematiksel hesaplamalar yapmaya yarar. (5*3-2 yazmayı deneyin)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Hesap Makinesi</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Matematiksel hesaplamalar yapmaya yarar. (5*3-2 yazmayı deneyin)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Sayı değil (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">İfade hatalı ya da eksik. (Parantez koymayı mı unuttunuz?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Bu sayıyı panoya kopyala</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Калькулятор</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Дозволяє виконувати математичні обчислення (спробуйте 5*3-2 у Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Калькулятор</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Дозволяє виконувати математичні обчислення (спробуйте 5*3-2 у Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Не є числом (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Вираз неправильний або неповний (Ви забули якісь дужки?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Скопіюйте це число в буфер обміну</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">Máy tính</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">Cho phép thực hiện các phép tính toán học. (Thử 5*3-2 trong Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">Máy tính</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">Cho phép thực hiện các phép tính toán học. (Thử 5*3-2 trong Flow Launcher)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">Không phải là số (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Biểu thức sai hoặc không đầy đủ (Bạn có quên một số dấu ngoặc đơn không?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">Sao chép số này vào clipboard</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">计算器</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">为 Flow Launcher 提供数学计算能力。(试着在 Flow Launcher 输入 5*3-2)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">计算器</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">为 Flow Launcher 提供数学计算能力。(试着在 Flow Launcher 输入 5*3-2)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">请输入数字</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">表达错误或不完整(您是否忘记了一些括号?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">将结果复制到剪贴板</system:String>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_name">計算機</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_caculator_plugin_description">為 Flow Launcher 提供數學計算功能。(試著在 Flow Launcher 輸入 5*3-2)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_name">計算機</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_plugin_description">為 Flow Launcher 提供數學計算功能。(試著在 Flow Launcher 輸入 5*3-2)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_not_a_number">不是一個數 (NaN)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_calculator_copy_number_to_clipboard">複製此數至剪貼簿</system:String>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Controls;
|
||||
|
|
@ -14,6 +15,9 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
{
|
||||
private static readonly Regex RegValidExpressChar = MainRegexHelper.GetRegValidExpressChar();
|
||||
private static readonly Regex RegBrackets = MainRegexHelper.GetRegBrackets();
|
||||
private static readonly Regex ThousandGroupRegex = MainRegexHelper.GetThousandGroupRegex();
|
||||
private static readonly Regex NumberRegex = MainRegexHelper.GetNumberRegex();
|
||||
|
||||
private static Engine MagesEngine;
|
||||
private const string Comma = ",";
|
||||
private const string Dot = ".";
|
||||
|
|
@ -23,6 +27,16 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
private Settings _settings;
|
||||
private SettingsViewModel _viewModel;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the formatting information for a single query.
|
||||
/// This is used to ensure thread safety by keeping query state local.
|
||||
/// </summary>
|
||||
private class ParsingContext
|
||||
{
|
||||
public string InputDecimalSeparator { get; set; }
|
||||
public bool InputUsesGroupSeparators { get; set; }
|
||||
}
|
||||
|
||||
public void Init(PluginInitContext context)
|
||||
{
|
||||
Context = context;
|
||||
|
|
@ -45,20 +59,11 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
return new List<Result>();
|
||||
}
|
||||
|
||||
var context = new ParsingContext();
|
||||
|
||||
try
|
||||
{
|
||||
string expression;
|
||||
|
||||
switch (_settings.DecimalSeparator)
|
||||
{
|
||||
case DecimalSeparator.Comma:
|
||||
case DecimalSeparator.UseSystemLocale when CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator == ",":
|
||||
expression = query.Search.Replace(",", ".");
|
||||
break;
|
||||
default:
|
||||
expression = query.Search;
|
||||
break;
|
||||
}
|
||||
var expression = NumberRegex.Replace(query.Search, m => NormalizeNumber(m.Value, context));
|
||||
|
||||
var result = MagesEngine.Interpret(expression);
|
||||
|
||||
|
|
@ -71,7 +76,7 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
if (!string.IsNullOrEmpty(result?.ToString()))
|
||||
{
|
||||
decimal roundedResult = Math.Round(Convert.ToDecimal(result), _settings.MaxDecimalPlaces, MidpointRounding.AwayFromZero);
|
||||
string newResult = ChangeDecimalSeparator(roundedResult, GetDecimalSeparator());
|
||||
string newResult = FormatResult(roundedResult, context);
|
||||
|
||||
return new List<Result>
|
||||
{
|
||||
|
|
@ -107,9 +112,137 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
return new List<Result>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a string representation of a number, detecting its format. It uses structural analysis
|
||||
/// and falls back to system culture for truly ambiguous cases (e.g., "1,234").
|
||||
/// It populates the provided ParsingContext with the detected format for later use.
|
||||
/// </summary>
|
||||
/// <returns>A normalized number string with '.' as the decimal separator for the Mages engine.</returns>
|
||||
private string NormalizeNumber(string numberStr, ParsingContext context)
|
||||
{
|
||||
var systemGroupSep = CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator;
|
||||
int dotCount = numberStr.Count(f => f == '.');
|
||||
int commaCount = numberStr.Count(f => f == ',');
|
||||
|
||||
// Case 1: Unambiguous mixed separators (e.g., "1.234,56")
|
||||
if (dotCount > 0 && commaCount > 0)
|
||||
{
|
||||
context.InputUsesGroupSeparators = true;
|
||||
if (numberStr.LastIndexOf('.') > numberStr.LastIndexOf(','))
|
||||
{
|
||||
context.InputDecimalSeparator = Dot;
|
||||
return numberStr.Replace(Comma, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.InputDecimalSeparator = Comma;
|
||||
return numberStr.Replace(Dot, string.Empty).Replace(Comma, Dot);
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: Only dots
|
||||
if (dotCount > 0)
|
||||
{
|
||||
if (dotCount > 1)
|
||||
{
|
||||
context.InputUsesGroupSeparators = true;
|
||||
return numberStr.Replace(Dot, string.Empty);
|
||||
}
|
||||
// A number is ambiguous if it has a single Dot in the thousands position,
|
||||
// and does not start with a "0." or "."
|
||||
bool isAmbiguous = numberStr.Length - numberStr.LastIndexOf('.') == 4
|
||||
&& !numberStr.StartsWith("0.")
|
||||
&& !numberStr.StartsWith(".");
|
||||
if (isAmbiguous)
|
||||
{
|
||||
if (systemGroupSep == Dot)
|
||||
{
|
||||
context.InputUsesGroupSeparators = true;
|
||||
return numberStr.Replace(Dot, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.InputDecimalSeparator = Dot;
|
||||
return numberStr;
|
||||
}
|
||||
}
|
||||
else // Unambiguous decimal (e.g., "12.34" or "0.123" or ".123")
|
||||
{
|
||||
context.InputDecimalSeparator = Dot;
|
||||
return numberStr;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 3: Only commas
|
||||
if (commaCount > 0)
|
||||
{
|
||||
if (commaCount > 1)
|
||||
{
|
||||
context.InputUsesGroupSeparators = true;
|
||||
return numberStr.Replace(Comma, string.Empty);
|
||||
}
|
||||
// A number is ambiguous if it has a single Comma in the thousands position,
|
||||
// and does not start with a "0," or ","
|
||||
bool isAmbiguous = numberStr.Length - numberStr.LastIndexOf(',') == 4
|
||||
&& !numberStr.StartsWith("0,")
|
||||
&& !numberStr.StartsWith(",");
|
||||
if (isAmbiguous)
|
||||
{
|
||||
if (systemGroupSep == Comma)
|
||||
{
|
||||
context.InputUsesGroupSeparators = true;
|
||||
return numberStr.Replace(Comma, string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.InputDecimalSeparator = Comma;
|
||||
return numberStr.Replace(Comma, Dot);
|
||||
}
|
||||
}
|
||||
else // Unambiguous decimal (e.g., "12,34" or "0,123" or ",123")
|
||||
{
|
||||
context.InputDecimalSeparator = Comma;
|
||||
return numberStr.Replace(Comma, Dot);
|
||||
}
|
||||
}
|
||||
|
||||
// Case 4: No separators
|
||||
return numberStr;
|
||||
}
|
||||
|
||||
private string FormatResult(decimal roundedResult, ParsingContext context)
|
||||
{
|
||||
string decimalSeparator = context.InputDecimalSeparator ?? GetDecimalSeparator();
|
||||
string groupSeparator = GetGroupSeparator(decimalSeparator);
|
||||
|
||||
string resultStr = roundedResult.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
string[] parts = resultStr.Split('.');
|
||||
string integerPart = parts[0];
|
||||
string fractionalPart = parts.Length > 1 ? parts[1] : string.Empty;
|
||||
|
||||
if (context.InputUsesGroupSeparators && integerPart.Length > 3)
|
||||
{
|
||||
integerPart = ThousandGroupRegex.Replace(integerPart, groupSeparator);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(fractionalPart))
|
||||
{
|
||||
return integerPart + decimalSeparator + fractionalPart;
|
||||
}
|
||||
|
||||
return integerPart;
|
||||
}
|
||||
|
||||
private string GetGroupSeparator(string decimalSeparator)
|
||||
{
|
||||
// This logic is now independent of the system's group separator
|
||||
// to ensure consistent output for unit testing.
|
||||
return decimalSeparator == Dot ? Comma : Dot;
|
||||
}
|
||||
|
||||
private bool CanCalculate(Query query)
|
||||
{
|
||||
// Don't execute when user only input "e" or "i" keyword
|
||||
if (query.Search.Length < 2)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -125,28 +258,10 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((query.Search.Contains(Dot) && GetDecimalSeparator() != Dot) ||
|
||||
(query.Search.Contains(Comma) && GetDecimalSeparator() != Comma))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string ChangeDecimalSeparator(decimal value, string newDecimalSeparator)
|
||||
{
|
||||
if (string.IsNullOrEmpty(newDecimalSeparator))
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
var numberFormatInfo = new NumberFormatInfo
|
||||
{
|
||||
NumberDecimalSeparator = newDecimalSeparator
|
||||
};
|
||||
return value.ToString(numberFormatInfo);
|
||||
}
|
||||
|
||||
private string GetDecimalSeparator()
|
||||
private string GetDecimalSeparator()
|
||||
{
|
||||
string systemDecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
||||
return _settings.DecimalSeparator switch
|
||||
|
|
@ -179,12 +294,12 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
|
||||
public string GetTranslatedPluginTitle()
|
||||
{
|
||||
return Localize.flowlauncher_plugin_caculator_plugin_name();
|
||||
return Localize.flowlauncher_plugin_calculator_plugin_name();
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginDescription()
|
||||
{
|
||||
return Localize.flowlauncher_plugin_caculator_plugin_description();
|
||||
return Localize.flowlauncher_plugin_calculator_plugin_description();
|
||||
}
|
||||
|
||||
public Control CreateSettingPanel()
|
||||
|
|
|
|||
|
|
@ -10,4 +10,10 @@ internal static partial class MainRegexHelper
|
|||
|
||||
[GeneratedRegex(@"^(ceil|floor|exp|pi|e|max|min|det|abs|log|ln|sqrt|sin|cos|tan|arcsin|arccos|arctan|eigval|eigvec|eig|sum|polar|plot|round|sort|real|zeta|bin2dec|hex2dec|oct2dec|factorial|sign|isprime|isinfty|==|~=|&&|\|\||(?:\<|\>)=?|[ei]|[0-9]|0x[\da-fA-F]+|[\+\%\-\*\/\^\., ""]|[\(\)\|\!\[\]])+$", RegexOptions.Compiled)]
|
||||
public static partial Regex GetRegValidExpressChar();
|
||||
|
||||
[GeneratedRegex(@"[\d\.,]+", RegexOptions.Compiled)]
|
||||
public static partial Regex GetNumberRegex();
|
||||
|
||||
[GeneratedRegex(@"\B(?=(\d{3})+(?!\d))", RegexOptions.Compiled)]
|
||||
public static partial Regex GetThousandGroupRegex();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Calculator
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to convert all numbers in a text from one culture format to another.
|
||||
/// </summary>
|
||||
public class NumberTranslator
|
||||
{
|
||||
private readonly CultureInfo sourceCulture;
|
||||
private readonly CultureInfo targetCulture;
|
||||
private readonly Regex splitRegexForSource;
|
||||
private readonly Regex splitRegexForTarget;
|
||||
|
||||
private NumberTranslator(CultureInfo sourceCulture, CultureInfo targetCulture)
|
||||
{
|
||||
this.sourceCulture = sourceCulture;
|
||||
this.targetCulture = targetCulture;
|
||||
|
||||
this.splitRegexForSource = GetSplitRegex(this.sourceCulture);
|
||||
this.splitRegexForTarget = GetSplitRegex(this.targetCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="NumberTranslator"/> - returns null if no number conversion
|
||||
/// is required between the cultures.
|
||||
/// </summary>
|
||||
/// <param name="sourceCulture">source culture</param>
|
||||
/// <param name="targetCulture">target culture</param>
|
||||
/// <returns></returns>
|
||||
public static NumberTranslator Create(CultureInfo sourceCulture, CultureInfo targetCulture)
|
||||
{
|
||||
bool conversionRequired = sourceCulture.NumberFormat.NumberDecimalSeparator != targetCulture.NumberFormat.NumberDecimalSeparator
|
||||
|| sourceCulture.NumberFormat.PercentGroupSeparator != targetCulture.NumberFormat.PercentGroupSeparator
|
||||
|| sourceCulture.NumberFormat.NumberGroupSizes != targetCulture.NumberFormat.NumberGroupSizes;
|
||||
return conversionRequired
|
||||
? new NumberTranslator(sourceCulture, targetCulture)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate from source to target culture.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public string Translate(string input)
|
||||
{
|
||||
return this.Translate(input, this.sourceCulture, this.targetCulture, this.splitRegexForSource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate from target to source culture.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public string TranslateBack(string input)
|
||||
{
|
||||
return this.Translate(input, this.targetCulture, this.sourceCulture, this.splitRegexForTarget);
|
||||
}
|
||||
|
||||
private string Translate(string input, CultureInfo cultureFrom, CultureInfo cultureTo, Regex splitRegex)
|
||||
{
|
||||
var outputBuilder = new StringBuilder();
|
||||
|
||||
string[] tokens = splitRegex.Split(input);
|
||||
foreach (string token in tokens)
|
||||
{
|
||||
decimal number;
|
||||
outputBuilder.Append(
|
||||
decimal.TryParse(token, NumberStyles.Number, cultureFrom, out number)
|
||||
? number.ToString(cultureTo)
|
||||
: token);
|
||||
}
|
||||
|
||||
return outputBuilder.ToString();
|
||||
}
|
||||
|
||||
private Regex GetSplitRegex(CultureInfo culture)
|
||||
{
|
||||
var splitPattern = $"((?:\\d|{Regex.Escape(culture.NumberFormat.NumberDecimalSeparator)}";
|
||||
if (!string.IsNullOrEmpty(culture.NumberFormat.NumberGroupSeparator))
|
||||
{
|
||||
splitPattern += $"|{Regex.Escape(culture.NumberFormat.NumberGroupSeparator)}";
|
||||
}
|
||||
splitPattern += ")+)";
|
||||
return new Regex(splitPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls;
|
||||
using Flow.Launcher.Plugin.Calculator.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Calculator.Views
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
"ID": "CEA0FDFC6D3B4085823D60DC76F28855",
|
||||
"ActionKeyword": "*",
|
||||
"Name": "Calculator",
|
||||
"Description": "Perform mathematical calculations (including hexadecimal values)",
|
||||
"Author": "cxfksword",
|
||||
"Description": "Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place.",
|
||||
"Author": "cxfksword, dcog989",
|
||||
"Version": "1.0.0",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="300"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
mc:Ignorable="d">
|
||||
<Grid x:Name="PreviewGrid" VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
|
|
@ -20,40 +21,22 @@
|
|||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
MaxWidth="96"
|
||||
MaxHeight="96"
|
||||
Margin="5 12 8 0"
|
||||
Source="{Binding PreviewImage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
|
||||
<Image.Style>
|
||||
<Style TargetType="Image">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding UseBigThumbnail}" Value="False">
|
||||
<Setter Property="MaxWidth" Value="96" />
|
||||
<Setter Property="MaxHeight" Value="96" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Image.Style>
|
||||
</Image>
|
||||
Source="{Binding PreviewImage, IsAsync=True, Mode=OneWay}" />
|
||||
<Grid Grid.Row="1">
|
||||
<TextBlock
|
||||
Margin="5 6 5 16"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Style="{DynamicResource PreviewItemTitleStyle}"
|
||||
Text="{Binding Result.Title}"
|
||||
Text="{Binding FileName, Mode=OneTime}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="1">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Result.SubTitle.Length}" Value="0">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<Rectangle
|
||||
x:Name="PreviewSep"
|
||||
Width="Auto"
|
||||
|
|
@ -64,7 +47,7 @@
|
|||
<TextBlock
|
||||
Margin="5 8 8 8"
|
||||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{Binding Result.SubTitle}" />
|
||||
Text="{Binding FilePath, Mode=OneTime}" />
|
||||
<Rectangle
|
||||
Width="Auto"
|
||||
Height="1"
|
||||
|
|
@ -77,9 +60,9 @@
|
|||
<Style.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding FileSizeVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Value="Collapsed" />
|
||||
<Condition Binding="{Binding CreatedAtVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Value="Collapsed" />
|
||||
<Condition Binding="{Binding LastModifiedAtVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Value="Collapsed" />
|
||||
<Condition Binding="{Binding FileSizeVisibility}" Value="Collapsed" />
|
||||
<Condition Binding="{Binding CreatedAtVisibility}" Value="Collapsed" />
|
||||
<Condition Binding="{Binding LastModifiedAtVisibility}" Value="Collapsed" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</MultiDataTrigger>
|
||||
|
|
@ -87,7 +70,7 @@
|
|||
</Style>
|
||||
</Rectangle.Style>
|
||||
</Rectangle>
|
||||
<Grid Margin="0 10 0 0" Visibility="{Binding FileInfoVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
|
||||
<Grid Margin="0 10 0 0" Visibility="{Binding FileInfoVisibility, Mode=OneTime}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100" />
|
||||
<ColumnDefinition Width="*" />
|
||||
|
|
@ -105,7 +88,7 @@
|
|||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{DynamicResource FileSize}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding FileSizeVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
|
||||
Visibility="{Binding FileSizeVisibility, Mode=OneTime}" />
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
|
|
@ -113,9 +96,9 @@
|
|||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{Binding FileSize, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Mode=OneWay}"
|
||||
Text="{Binding FileSize, Mode=OneWay}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding FileSizeVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
|
||||
Visibility="{Binding FileSizeVisibility, Mode=OneTime}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
|
|
@ -125,7 +108,7 @@
|
|||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{DynamicResource Created}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding CreatedAtVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
|
||||
Visibility="{Binding CreatedAtVisibility, Mode=OneTime}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
|
|
@ -133,9 +116,9 @@
|
|||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{Binding CreatedAt, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
|
||||
Text="{Binding CreatedAt, Mode=OneWay}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding CreatedAtVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
|
||||
Visibility="{Binding CreatedAtVisibility, Mode=OneTime}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
|
|
@ -145,7 +128,7 @@
|
|||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{DynamicResource LastModified}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding LastModifiedAtVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
|
||||
Visibility="{Binding LastModifiedAtVisibility, Mode=OneTime}" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
|
|
@ -153,9 +136,9 @@
|
|||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Style="{DynamicResource PreviewItemSubTitleStyle}"
|
||||
Text="{Binding LastModifiedAt, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
|
||||
Text="{Binding LastModifiedAt, Mode=OneWay}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding LastModifiedAtVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
|
||||
Visibility="{Binding LastModifiedAtVisibility, Mode=OneTime}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -21,22 +21,22 @@ public partial class PreviewPanel : UserControl
|
|||
{
|
||||
private static readonly string ClassName = nameof(PreviewPanel);
|
||||
|
||||
private string FilePath { get; }
|
||||
public string FileSize { get; private set; } = Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown");
|
||||
public string CreatedAt { get; } = "";
|
||||
public string LastModifiedAt { get; } = "";
|
||||
private ImageSource _previewImage = new BitmapImage();
|
||||
private Settings Settings { get; }
|
||||
public string FilePath { get; }
|
||||
public string FileName { get; }
|
||||
|
||||
public ImageSource PreviewImage
|
||||
{
|
||||
get => _previewImage;
|
||||
private set
|
||||
{
|
||||
_previewImage = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string _fileSize = Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown");
|
||||
|
||||
[ObservableProperty]
|
||||
private string _createdAt = "";
|
||||
|
||||
[ObservableProperty]
|
||||
private string _lastModifiedAt = "";
|
||||
|
||||
[ObservableProperty]
|
||||
private ImageSource _previewImage = new BitmapImage();
|
||||
|
||||
private Settings Settings { get; }
|
||||
|
||||
public Visibility FileSizeVisibility => Settings.ShowFileSizeInPreviewPanel
|
||||
? Visibility.Visible
|
||||
|
|
@ -57,11 +57,11 @@ public partial class PreviewPanel : UserControl
|
|||
|
||||
public PreviewPanel(Settings settings, string filePath, ResultType type)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Settings = settings;
|
||||
|
||||
FilePath = filePath;
|
||||
FileName = Path.GetFileName(filePath);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
if (Settings.ShowFileSizeInPreviewPanel)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
<system:String x:Key="flowlauncher_plugin_websearch_edit">Edit</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_websearch_add">Add</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_websearch_enabled_label">Enabled</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_websearch_private_mode_label">Private Mode</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_websearch_true">Enabled</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_websearch_false">Disabled</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_websearch_confirm">Confirm</system:String>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
Score = score,
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.OpenWebUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword)));
|
||||
_context.API.OpenWebUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword)), searchSource.IsPrivateMode);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
|
@ -135,7 +135,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword,
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.OpenWebUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
|
||||
_context.API.OpenWebUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)), searchSource.IsPrivateMode);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
public class SearchSource : BaseModel
|
||||
{
|
||||
public string Title { get; set; }
|
||||
|
||||
public string ActionKeyword { get; set; }
|
||||
|
||||
[NotNull]
|
||||
|
|
@ -19,21 +20,17 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
/// Custom icons are placed in the user data directory
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string IconPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CustomIcon)
|
||||
return Path.Combine(Main.CustomImagesDirectory, Icon);
|
||||
|
||||
return Path.Combine(Main.DefaultImagesDirectory, Icon);
|
||||
}
|
||||
}
|
||||
public string IconPath => CustomIcon
|
||||
? Path.Combine(Main.CustomImagesDirectory, Icon)
|
||||
: Path.Combine(Main.DefaultImagesDirectory, Icon);
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool Status => Enabled;
|
||||
|
||||
public bool IsPrivateMode { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public SearchSource DeepCopy()
|
||||
|
|
@ -45,8 +42,10 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
Url = Url,
|
||||
Icon = Icon,
|
||||
CustomIcon = CustomIcon,
|
||||
IsPrivateMode = IsPrivateMode,
|
||||
Enabled = Enabled
|
||||
};
|
||||
|
||||
return webSearch;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@
|
|||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
|
|
@ -181,12 +182,26 @@
|
|||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_websearch_enabled_label}" />
|
||||
Text="{DynamicResource flowlauncher_plugin_websearch_private_mode_label}" />
|
||||
<CheckBox
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Margin="10 10 10 15"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding SearchSource.IsPrivateMode}" />
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="10 0 10 10"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_websearch_enabled_label}" />
|
||||
<CheckBox
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Margin="10 0 10 10"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding SearchSource.Enabled}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
|
|
|||
|
|
@ -191,7 +191,19 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
[JsonIgnore]
|
||||
public SearchSource SelectedSearchSource { get; set; }
|
||||
|
||||
public bool EnableSuggestion { get; set; }
|
||||
private bool enableSuggestion;
|
||||
public bool EnableSuggestion
|
||||
{
|
||||
get => enableSuggestion;
|
||||
set
|
||||
{
|
||||
if (enableSuggestion != value)
|
||||
{
|
||||
enableSuggestion = value;
|
||||
OnPropertyChanged(nameof(EnableSuggestion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public SuggestionSource[] Suggestions { get; set; } = {
|
||||
|
|
@ -221,9 +233,5 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string BrowserPath { get; set; }
|
||||
|
||||
public bool OpenInNewBrowser { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,6 @@
|
|||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="BrowserPathBoxStyle" TargetType="TextBox">
|
||||
<Setter Property="Height" Value="28" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
<DataTemplate x:Key="HeaderTemplateArrowUp">
|
||||
<DockPanel>
|
||||
<TextBlock HorizontalAlignment="Center" Text="{Binding}" />
|
||||
|
|
@ -96,6 +92,20 @@
|
|||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn
|
||||
Width="120"
|
||||
Header="{DynamicResource flowlauncher_plugin_websearch_private_mode_label}">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding IsPrivateMode}"
|
||||
IsEnabled="False"
|
||||
/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
|
|
@ -138,7 +148,7 @@
|
|||
Margin="{StaticResource SettingPanelItemLeftMargin}"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11"
|
||||
IsEnabled="{Binding ElementName=EnableSuggestion, Path=IsChecked}"
|
||||
IsEnabled="{Binding Settings.EnableSuggestion}"
|
||||
ItemsSource="{Binding Settings.Suggestions}"
|
||||
SelectedItem="{Binding Settings.SelectedSuggestion}" />
|
||||
<CheckBox
|
||||
|
|
@ -149,7 +159,6 @@
|
|||
Content="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion}"
|
||||
IsChecked="{Binding Settings.EnableSuggestion}" />
|
||||
</StackPanel>
|
||||
<!-- Not sure why binding IsEnabled directly to Settings.EnableWebSearchSuggestion is not working -->
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
@ -94,7 +94,8 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
var columnBinding = headerClicked.Column.DisplayMemberBinding as Binding;
|
||||
var sortBy = columnBinding?.Path.Path ?? headerClicked.Column.Header as string;
|
||||
|
||||
if(sortBy != null) {
|
||||
if (sortBy != null)
|
||||
{
|
||||
Sort(sortBy, direction);
|
||||
|
||||
if (direction == ListSortDirection.Ascending)
|
||||
|
|
|
|||
|
|
@ -141,6 +141,6 @@
|
|||
"Enabled": true
|
||||
}
|
||||
],
|
||||
"EnableWebSearchSuggestion": false,
|
||||
"WebSearchSuggestionSource": "Google"
|
||||
"EnableSuggestion": false,
|
||||
"Suggestion": "Google"
|
||||
}
|
||||
Loading…
Reference in a new issue