Merge branch 'administrator_mode' of https://github.com/Flow-Launcher/Flow.Launcher into administrator_mode

This commit is contained in:
Jack251970 2025-06-15 01:27:58 +08:00
commit 39de484d2d
11 changed files with 167 additions and 136 deletions

View file

@ -385,7 +385,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool AlwaysRunAsAdministrator { get; set; } = false; public bool AlwaysRunAsAdministrator { get; set; } = false;
private bool _showAtTopmost = true; private bool _showAtTopmost = false;
public bool ShowAtTopmost public bool ShowAtTopmost
{ {
get => _showAtTopmost; get => _showAtTopmost;

View file

@ -14,10 +14,10 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Version>4.5.0</Version> <Version>4.6.0</Version>
<PackageVersion>4.5.0</PackageVersion> <PackageVersion>4.6.0</PackageVersion>
<AssemblyVersion>4.5.0</AssemblyVersion> <AssemblyVersion>4.6.0</AssemblyVersion>
<FileVersion>4.5.0</FileVersion> <FileVersion>4.6.0</FileVersion>
<PackageId>Flow.Launcher.Plugin</PackageId> <PackageId>Flow.Launcher.Plugin</PackageId>
<Authors>Flow-Launcher</Authors> <Authors>Flow-Launcher</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>

View file

@ -342,13 +342,28 @@ namespace Flow.Launcher.Plugin
public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null); public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null);
/// <summary> /// <summary>
/// Opens the URL with the given Uri object. /// Opens the URL using the browser with the given Uri object, even if the URL is a local file.
/// The browser and mode used is based on what's configured in Flow's default browser settings.
/// </summary>
public void OpenWebUrl(Uri url, bool? inPrivate = null);
/// <summary>
/// Opens the URL using the browser with the given string, even if the URL is a local file.
/// The browser and mode used is based on what's configured in Flow's default browser settings.
/// Non-C# plugins should use this method.
/// </summary>
public void OpenWebUrl(string url, bool? inPrivate = null);
/// <summary>
/// Opens the URL with the given Uri object in browser if scheme is Http or Https.
/// If the URL is a local file, it will instead be opened with the default application for that file type.
/// The browser and mode used is based on what's configured in Flow's default browser settings. /// The browser and mode used is based on what's configured in Flow's default browser settings.
/// </summary> /// </summary>
public void OpenUrl(Uri url, bool? inPrivate = null); public void OpenUrl(Uri url, bool? inPrivate = null);
/// <summary> /// <summary>
/// Opens the URL with the given string. /// Opens the URL with the given string in browser if scheme is Http or Https.
/// If the URL is a local file, it will instead be opened with the default application for that file type.
/// The browser and mode used is based on what's configured in Flow's default browser settings. /// The browser and mode used is based on what's configured in Flow's default browser settings.
/// Non-C# plugins should use this method. /// Non-C# plugins should use this method.
/// </summary> /// </summary>

View file

@ -14,102 +14,102 @@
<WindowChrome.WindowChrome> <WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" /> <WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome> </WindowChrome.WindowChrome>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition /> <RowDefinition />
<RowDefinition Height="80" /> <RowDefinition Height="80" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid> <Grid.ColumnDefinitions>
<StackPanel Grid.Row="0"> <ColumnDefinition Width="Auto" />
<StackPanel> <ColumnDefinition Width="*" />
<Grid> </Grid.ColumnDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26 12 26 0">
<StackPanel Grid.Row="0" Margin="0 0 0 12">
<TextBlock
Grid.Column="0"
Margin="0 0 0 0"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource actionKeywordsTitle}"
TextAlignment="Left" />
</StackPanel>
<StackPanel>
<TextBlock
FontSize="14"
Text="{DynamicResource actionkeyword_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Margin="0 18 0 0" Orientation="Horizontal"> <Button
<TextBlock Grid.Row="0"
Grid.Row="0" Grid.Column="1"
Grid.Column="1" HorizontalAlignment="Right"
HorizontalAlignment="Left" Click="BtnCancel_OnClick"
VerticalAlignment="Center" Style="{StaticResource TitleBarCloseButtonStyle}">
FontSize="14" <Path
Text="{DynamicResource currentActionKeywords}" /> Width="46"
<TextBlock Height="32"
x:Name="tbOldActionKeyword" Data="M 18,11 27,20 M 18,20 27,11"
Grid.Row="0" Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Grid.Column="1" StrokeThickness="1">
Margin="14 10 10 10" <Path.Style>
HorizontalAlignment="Left" <Style TargetType="Path">
VerticalAlignment="Center" <Style.Triggers>
FontSize="14" <DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
FontWeight="SemiBold" <Setter Property="Opacity" Value="0.5" />
Foreground="{DynamicResource Color05B}" /> </DataTrigger>
</StackPanel> </Style.Triggers>
<StackPanel Margin="0 0 0 10" Orientation="Horizontal"> </Style>
<TextBlock </Path.Style>
Grid.Row="1" </Path>
Grid.Column="1" </Button>
HorizontalAlignment="Left"
VerticalAlignment="Center" <TextBlock
FontSize="14"
Text="{DynamicResource newActionKeyword}" />
<TextBox
x:Name="tbAction"
Width="105"
Margin="10 10 15 10"
HorizontalAlignment="Left"
VerticalAlignment="Center" />
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
<Border
Grid.Row="1" Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="26 12 26 12"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource actionKeywordsTitle}"
TextAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="26 0 26 10"
FontSize="14"
Text="{DynamicResource actionkeyword_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="26 0 10 0"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource currentActionKeywords}" />
<TextBox
x:Name="tbOldActionKeyword"
Grid.Row="3"
Grid.Column="1"
Margin="10 10 26 6"
VerticalAlignment="Center"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}"
IsReadOnly="True"
Text="List of old keyword(s)" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="26 6 10 12"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource newActionKeyword}" />
<TextBox
x:Name="tbAction"
Grid.Row="4"
Grid.Column="1"
Margin="10 6 26 10"
VerticalAlignment="Center" />
<Border
Grid.Row="5"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0 10 0 0"
Background="{DynamicResource PopupButtonAreaBGColor}" Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}" BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0 1 0 0"> BorderThickness="0 1 0 0">
@ -117,15 +117,15 @@
<Button <Button
x:Name="btnCancel" x:Name="btnCancel"
Width="145" Width="145"
Height="30" Height="38"
Margin="10 0 5 0" Margin="10 0 10 0"
Click="BtnCancel_OnClick" Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" /> Content="{DynamicResource cancel}" />
<Button <Button
x:Name="btnDone" x:Name="btnDone"
Width="145" Width="145"
Height="30" Height="38"
Margin="5 0 10 0" Margin="10 0 10 0"
Click="btnDone_OnClick" Click="btnDone_OnClick"
Style="{StaticResource AccentButtonStyle}"> Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" /> <TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />

View file

@ -20,7 +20,9 @@ namespace Flow.Launcher
private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e) private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e)
{ {
tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeparator, _plugin.Metadata.ActionKeywords.ToArray()); tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeparator, _plugin.Metadata.ActionKeywords);
tbAction.Text = tbOldActionKeyword.Text;
tbAction.SelectAll();
tbAction.Focus(); tbAction.Focus();
} }
@ -33,38 +35,39 @@ namespace Flow.Launcher
{ {
var oldActionKeywords = _plugin.Metadata.ActionKeywords; var oldActionKeywords = _plugin.Metadata.ActionKeywords;
var newActionKeywords = tbAction.Text.Split(Query.ActionKeywordSeparator).ToList(); var newActionKeywords = tbAction.Text.Split(Query.ActionKeywordSeparator)
newActionKeywords.RemoveAll(string.IsNullOrEmpty); .Where(s => !string.IsNullOrEmpty(s))
newActionKeywords = newActionKeywords.Distinct().ToList(); .Distinct()
.ToList();
newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign }; newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign };
var addedActionKeywords = newActionKeywords.Except(oldActionKeywords).ToList(); var addedActionKeywords = newActionKeywords.Except(oldActionKeywords).ToList();
var removedActionKeywords = oldActionKeywords.Except(newActionKeywords).ToList(); var removedActionKeywords = oldActionKeywords.Except(newActionKeywords).ToList();
if (!addedActionKeywords.Any(App.API.ActionKeywordAssigned))
if (addedActionKeywords.Any(App.API.ActionKeywordAssigned))
{ {
if (oldActionKeywords.Count != newActionKeywords.Count) App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsHasBeenAssigned"));
{ return;
ReplaceActionKeyword(_plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); }
return;
}
var sortedOldActionKeywords = oldActionKeywords.OrderBy(s => s).ToList(); if (oldActionKeywords.Count != newActionKeywords.Count)
var sortedNewActionKeywords = newActionKeywords.OrderBy(s => s).ToList(); {
ReplaceActionKeyword(_plugin.Metadata.ID, removedActionKeywords, addedActionKeywords);
return;
}
if (sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords)) var sortedOldActionKeywords = oldActionKeywords.OrderBy(s => s).ToList();
{ var sortedNewActionKeywords = newActionKeywords.OrderBy(s => s).ToList();
// User just changes the sequence of action keywords
App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsSameAsOld")); if (sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords))
} {
else // User just changes the sequence of action keywords
{ App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsSameAsOld"));
ReplaceActionKeyword(_plugin.Metadata.ID, removedActionKeywords, addedActionKeywords);
}
} }
else else
{ {
App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsHasBeenAssigned")); ReplaceActionKeyword(_plugin.Metadata.ID, removedActionKeywords, addedActionKeywords);
} }
} }

View file

@ -132,8 +132,8 @@
<system:String x:Key="historyResultsForHomePage">Show History Results in Home Page</system:String> <system:String x:Key="historyResultsForHomePage">Show History Results in Home Page</system:String>
<system:String x:Key="historyResultsCountForHomePage">Maximum History Results Shown in Home Page</system:String> <system:String x:Key="historyResultsCountForHomePage">Maximum History Results Shown in Home Page</system:String>
<system:String x:Key="homeToggleBoxToolTip">This can only be edited if plugin supports Home feature and Home Page is enabled.</system:String> <system:String x:Key="homeToggleBoxToolTip">This can only be edited if plugin supports Home feature and Home Page is enabled.</system:String>
<system:String x:Key="showAtTopmost">Show Search Window at Topmost</system:String> <system:String x:Key="showAtTopmost">Show Search Window at Foremost</system:String>
<system:String x:Key="showAtTopmostToolTip">Show search window above other windows</system:String> <system:String x:Key="showAtTopmostToolTip">Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position.</system:String>
<system:String x:Key="alwaysRunAsAdministrator">Always run as administrator</system:String> <system:String x:Key="alwaysRunAsAdministrator">Always run as administrator</system:String>
<system:String x:Key="alwaysRunAsAdministratorToolTip">Run Flow Launcher as administrator on startup</system:String> <system:String x:Key="alwaysRunAsAdministratorToolTip">Run Flow Launcher as administrator on startup</system:String>
<system:String x:Key="runAsAdministratorChange">Administrator Mode Change</system:String> <system:String x:Key="runAsAdministratorChange">Administrator Mode Change</system:String>

View file

@ -137,12 +137,11 @@ namespace Flow.Launcher
welcomeWindow.Show(); welcomeWindow.Show();
} }
if (_settings.ReleaseNotesVersion != Constant.Version) if (Constant.Version != "1.0.0" && _settings.ReleaseNotesVersion != Constant.Version) // Skip release notes notification for developer builds (version 1.0.0)
{ {
// Update release notes version // Update release notes version
_settings.ReleaseNotesVersion = Constant.Version; _settings.ReleaseNotesVersion = Constant.Version;
// Show release note popup with button
// Display message box with button
App.API.ShowMsgWithButton( App.API.ShowMsgWithButton(
string.Format(App.API.GetTranslation("appUpdateTitle"), Constant.Version), string.Format(App.API.GetTranslation("appUpdateTitle"), Constant.Version),
App.API.GetTranslation("appUpdateButtonContent"), App.API.GetTranslation("appUpdateButtonContent"),

View file

@ -404,9 +404,9 @@ namespace Flow.Launcher
} }
} }
private void OpenUri(Uri uri, bool? inPrivate = null) private void OpenUri(Uri uri, bool? inPrivate = null, bool forceBrowser = false)
{ {
if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps) if (forceBrowser || uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)
{ {
var browserInfo = _settings.CustomBrowser; var browserInfo = _settings.CustomBrowser;
@ -441,6 +441,16 @@ namespace Flow.Launcher
} }
} }
public void OpenWebUrl(string url, bool? inPrivate = null)
{
OpenUri(new Uri(url), inPrivate, true);
}
public void OpenWebUrl(Uri url, bool? inPrivate = null)
{
OpenUri(url, inPrivate, true);
}
public void OpenUrl(string url, bool? inPrivate = null) public void OpenUrl(string url, bool? inPrivate = null)
{ {
OpenUri(new Uri(url), inPrivate); OpenUri(new Uri(url), inPrivate);

View file

@ -81,6 +81,7 @@
OffContent="{DynamicResource disable}" OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" /> OnContent="{DynamicResource enable}" />
</cc:Card> </cc:Card>
<cc:Card Title="{DynamicResource hideNotifyIcon}" Sub="{DynamicResource hideNotifyIconToolTip}"> <cc:Card Title="{DynamicResource hideNotifyIcon}" Sub="{DynamicResource hideNotifyIconToolTip}">
<ui:ToggleSwitch <ui:ToggleSwitch
IsOn="{Binding Settings.HideNotifyIcon}" IsOn="{Binding Settings.HideNotifyIcon}"
@ -88,10 +89,11 @@
OnContent="{DynamicResource enable}" /> OnContent="{DynamicResource enable}" />
</cc:Card> </cc:Card>
<cc:Card <cc:Card
Title="{DynamicResource showAtTopmost}" Title="{DynamicResource showAtTopmost}"
Margin="0 14 0 0" Margin="0 14 0 0"
Icon="&#xE923;" Icon="&#xf5ed;"
Sub="{DynamicResource showAtTopmostToolTip}"> Sub="{DynamicResource showAtTopmostToolTip}">
<ui:ToggleSwitch <ui:ToggleSwitch
IsOn="{Binding Settings.ShowAtTopmost}" IsOn="{Binding Settings.ShowAtTopmost}"
@ -99,7 +101,7 @@
OnContent="{DynamicResource enable}" /> OnContent="{DynamicResource enable}" />
</cc:Card> </cc:Card>
<cc:CardGroup Margin="0 14 0 0"> <cc:CardGroup Margin="0 4 0 0">
<cc:Card Title="{DynamicResource SearchWindowPosition}" Icon="&#xe7f4;"> <cc:Card Title="{DynamicResource SearchWindowPosition}" Icon="&#xe7f4;">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<ComboBox <ComboBox

View file

@ -71,7 +71,7 @@ namespace Flow.Launcher.Plugin.WebSearch
Score = score, Score = score,
Action = c => Action = c =>
{ {
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword))); _context.API.OpenWebUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword)));
return true; return true;
}, },
@ -135,7 +135,7 @@ namespace Flow.Launcher.Plugin.WebSearch
ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword, ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword,
Action = c => Action = c =>
{ {
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o))); _context.API.OpenWebUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
return true; return true;
}, },

View file

@ -1,4 +1,7 @@
version: '1.20.0.{build}' version: '1.20.1.{build}'
# Do not build on tags because we create a release on merge to master. Otherwise will upload artifacts twice changing the hash, as well as triggering duplicate GitHub release action & NuGet deployments.
skip_tags: true
init: init:
- ps: | - ps: |
@ -14,7 +17,6 @@ init:
cache: cache:
- '%USERPROFILE%\.nuget\packages -> **.sln, **.csproj' # preserve nuget folder (packages) unless the solution or projects change - '%USERPROFILE%\.nuget\packages -> **.sln, **.csproj' # preserve nuget folder (packages) unless the solution or projects change
assembly_info: assembly_info:
patch: true patch: true
file: SolutionAssemblyInfo.cs file: SolutionAssemblyInfo.cs
@ -60,7 +62,7 @@ deploy:
- provider: NuGet - provider: NuGet
artifact: Plugin nupkg artifact: Plugin nupkg
api_key: api_key:
secure: sCSd5JWgdzJWDa9kpqECut5ACPKZqcoxKU8ERKC00k7VIjig3/+nFV5zzTcGb0w3 secure: en+/GPSgfUVARoX0+lOeAAlbzvcCZAyBeVQaNq1AeXuRjjHgMwhBnt0PHVJXOepS
on: on:
branch: master branch: master