Merge branch 'dev' into SearchProgramsInPATH

This commit is contained in:
VictoriousRaptor 2022-11-13 16:36:31 +08:00 committed by GitHub
commit 2263c94010
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 391 additions and 393 deletions

View file

@ -52,6 +52,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public double SettingWindowHeight { get; set; } = 700; public double SettingWindowHeight { get; set; } = 700;
public double SettingWindowTop { get; set; } public double SettingWindowTop { get; set; }
public double SettingWindowLeft { get; set; } public double SettingWindowLeft { get; set; }
public System.Windows.WindowState SettingWindowState { get; set; } = WindowState.Normal;
public int CustomExplorerIndex { get; set; } = 0; public int CustomExplorerIndex { get; set; } = 0;

View file

@ -98,6 +98,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" /> <PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="SharpVectors" Version="1.7.6" /> <PackageReference Include="SharpVectors" Version="1.7.6" />
<PackageReference Include="VirtualizingWrapPanel" Version="1.5.7" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -120,7 +121,7 @@
<!-- Work around https://github.com/dotnet/wpf/issues/6792 --> <!-- Work around https://github.com/dotnet/wpf/issues/6792 -->
<ItemGroup> <ItemGroup>
<FilteredAnalyzer Include="@(Analyzer->Distinct())" /> <FilteredAnalyzer Include="@(Analyzer-&gt;Distinct())" />
<Analyzer Remove="@(Analyzer)" /> <Analyzer Remove="@(Analyzer)" />
<Analyzer Include="@(FilteredAnalyzer)" /> <Analyzer Include="@(FilteredAnalyzer)" />
</ItemGroup> </ItemGroup>

View file

@ -69,6 +69,8 @@
<SolidColorBrush x:Key="CustomContextDisabled" Color="#868686" /> <SolidColorBrush x:Key="CustomContextDisabled" Color="#868686" />
<SolidColorBrush x:Key="ContextSeparator" Color="#3c3c3c" /> <SolidColorBrush x:Key="ContextSeparator" Color="#3c3c3c" />
<SolidColorBrush x:Key="HoverStoreGrid2">#272727</SolidColorBrush>
<Color x:Key="Color01">#202020</Color> <Color x:Key="Color01">#202020</Color>
<Color x:Key="Color02">#2b2b2b</Color> <Color x:Key="Color02">#2b2b2b</Color>
<Color x:Key="Color03">#1d1d1d</Color> <Color x:Key="Color03">#1d1d1d</Color>

View file

@ -62,6 +62,8 @@
<SolidColorBrush x:Key="CustomContextDisabled" Color="#868686" /> <SolidColorBrush x:Key="CustomContextDisabled" Color="#868686" />
<SolidColorBrush x:Key="ContextSeparator" Color="#dadada" /> <SolidColorBrush x:Key="ContextSeparator" Color="#dadada" />
<SolidColorBrush x:Key="HoverStoreGrid2">#f6f6f6</SolidColorBrush>
<Color x:Key="Color01">#f3f3f3</Color> <Color x:Key="Color01">#f3f3f3</Color>
<Color x:Key="Color02">#ffffff</Color> <Color x:Key="Color02">#ffffff</Color>
<Color x:Key="Color03">#e5e5e5</Color> <Color x:Key="Color03">#e5e5e5</Color>

View file

@ -11,6 +11,7 @@
xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure" xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure"
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel" xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
xmlns:wpftk="clr-namespace:WpfToolkit.Controls;assembly=VirtualizingWrapPanel"
Title="{DynamicResource flowlauncher_settings}" Title="{DynamicResource flowlauncher_settings}"
Width="{Binding SettingWindowWidth, Mode=TwoWay}" Width="{Binding SettingWindowWidth, Mode=TwoWay}"
Height="{Binding SettingWindowHeight, Mode=TwoWay}" Height="{Binding SettingWindowHeight, Mode=TwoWay}"
@ -47,7 +48,25 @@
<scm:SortDescription PropertyName="Source" /> <scm:SortDescription PropertyName="Source" />
</CollectionViewSource.SortDescriptions> </CollectionViewSource.SortDescriptions>
</CollectionViewSource> </CollectionViewSource>
<CollectionViewSource x:Key="PluginStoreCollectionView"
Source="{Binding ExternalPlugins}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Category"></PropertyGroupDescription>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<Style x:Key="StoreItemFocusVisualStyleKey">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle
Margin="0"
Stroke="Black"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SettingGrid" TargetType="ItemsControl"> <Style x:Key="SettingGrid" TargetType="ItemsControl">
<Setter Property="Focusable" Value="False" /> <Setter Property="Focusable" Value="False" />
<Setter Property="Margin" Value="0" /> <Setter Property="Margin" Value="0" />
@ -130,6 +149,7 @@
<Setter Property="Margin" Value="0,0,-18,0" /> <Setter Property="Margin" Value="0,0,-18,0" />
</Style> </Style>
<Style x:Key="logo" TargetType="{x:Type TabItem}"> <Style x:Key="logo" TargetType="{x:Type TabItem}">
<!--#region Logo Style--> <!--#region Logo Style-->
<Setter Property="Margin" Value="0" /> <Setter Property="Margin" Value="0" />
@ -243,11 +263,7 @@
</Style> </Style>
<!-- Plugin Store Item when Selected layout for nothing --> <!-- Plugin Store Item when Selected layout for nothing -->
<Style x:Key="StoreItem" TargetType="{x:Type ToggleButton}"> <Style x:Key="StoreItem" TargetType="{x:Type ToggleButton}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True" />
</Style.Triggers>
</Style>
<Style x:Key="PluginList" TargetType="ListBoxItem"> <Style x:Key="PluginList" TargetType="ListBoxItem">
<Setter Property="Background" Value="{DynamicResource Color00B}" /> <Setter Property="Background" Value="{DynamicResource Color00B}" />
@ -320,11 +336,12 @@
</Style> </Style>
<!--#region PluginStore Style--> <!--#region PluginStore Style-->
<Style x:Key="StoreList" TargetType="ListBoxItem"> <Style x:Key="StoreList" TargetType="ListViewItem">
<Setter Property="Background" Value="{DynamicResource Color02B}" />
<Setter Property="Padding" Value="0,0,0,0" /> <Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="Margin" Value="0,0,8,5" /> <Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="BorderBrush" Value="{DynamicResource Color03B}" /> <Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0,0,8,8" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<!--#region Template for blue highlight win10--> <!--#region Template for blue highlight win10-->
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
@ -336,7 +353,8 @@
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5" CornerRadius="5"
SnapsToDevicePixels="True"> SnapsToDevicePixels="True"
UseLayoutRounding="True">
<ContentPresenter <ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
@ -345,43 +363,6 @@
ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplate="{TemplateBinding ContentTemplate}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border> </Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource Color07B}" />
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource Color03B}" />
<Setter TargetName="Bd" Property="CornerRadius" Value="5" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource Color02B}" />
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource Color03B}" />
<Setter TargetName="Bd" Property="Margin" Value="0,0,0,0" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource Color02B}" />
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource Color03B}" />
<Setter TargetName="Bd" Property="CornerRadius" Value="5" />
<Setter TargetName="Bd" Property="Margin" Value="0,0,0,0" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Bd" Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -485,7 +466,6 @@
Width="16" Width="16"
Height="16" Height="16"
Margin="10,4,4,4" Margin="10,4,4,4"
RenderOptions.BitmapScalingMode="HighQuality"
Source="/Images/app.png" /> Source="/Images/app.png" />
<TextBlock <TextBlock
Grid.Column="1" Grid.Column="1"
@ -633,8 +613,10 @@
<ScrollViewer <ScrollViewer
Margin="0,0,0,0" Margin="0,0,0,0"
Background="{DynamicResource Color01B}" Background="{DynamicResource Color01B}"
ScrollViewer.CanContentScroll="False"> CanContentScroll="False"
<StackPanel Margin="5,18,25,30" Orientation="Vertical"> VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingStackPanel.IsVirtualizing="True">
<VirtualizingStackPanel Margin="5,18,25,30" Orientation="Vertical">
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"
Margin="0,5,0,5" Margin="0,5,0,5"
@ -941,7 +923,7 @@
</TextBlock> </TextBlock>
</ItemsControl> </ItemsControl>
</Border> </Border>
</StackPanel> </VirtualizingStackPanel>
</ScrollViewer> </ScrollViewer>
</TabItem> </TabItem>
<TabItem KeyDown="OnPluginSettingKeydown"> <TabItem KeyDown="OnPluginSettingKeydown">
@ -1044,14 +1026,17 @@
Background="{DynamicResource Color01B}" Background="{DynamicResource Color01B}"
ItemContainerStyle="{StaticResource PluginList}" ItemContainerStyle="{StaticResource PluginList}"
ItemsSource="{Binding PluginViewModels}" ItemsSource="{Binding PluginViewModels}"
ScrollViewer.CanContentScroll="False" ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding SelectedPlugin}" SelectedItem="{Binding SelectedPlugin}"
SnapsToDevicePixels="True" SnapsToDevicePixels="True"
Style="{DynamicResource PluginListStyle}"> Style="{DynamicResource PluginListStyle}"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListBox.ItemsPanel> <ListBox.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Margin="0,0,0,18" /> <VirtualizingStackPanel Margin="0,0,0,18" />
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ListBox.ItemsPanel> </ListBox.ItemsPanel>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
@ -1401,10 +1386,12 @@
Text="{DynamicResource pluginStore}" Text="{DynamicResource pluginStore}"
TextAlignment="left" /> TextAlignment="left" />
</Border> </Border>
<DockPanel <DockPanel
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Margin="5,24,0,0"> Margin="5,24,0,0">
<TextBox <TextBox
Name="pluginStoreFilterTxb" Name="pluginStoreFilterTxb"
Width="150" Width="150"
@ -1456,290 +1443,223 @@
Padding="12,4,12,4" Padding="12,4,12,4"
HorizontalAlignment="Right" HorizontalAlignment="Right"
VerticalAlignment="Center" VerticalAlignment="Center"
Click="OnPluginStoreRefreshClick" Command="{Binding RefreshExternalPluginsCommand}"
Content="{DynamicResource refresh}" Content="{DynamicResource refresh}"
DockPanel.Dock="Right" DockPanel.Dock="Right"
FontSize="13" /> FontSize="13" />
</DockPanel> </DockPanel>
<Border <ListView
x:Name="StoreListBox"
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="2" Grid.ColumnSpan="2"
Padding="0,0,0,0"> Margin="4,0,0,0"
<ListBox Padding="0,0,18,0"
x:Name="StoreListBox" ItemContainerStyle="{StaticResource StoreList}"
Width="Auto" ItemsSource="{Binding Source={StaticResource PluginStoreCollectionView}}"
Margin="5,1,0,0" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Padding="0,0,0,0" SelectionMode="Single"
HorizontalAlignment="Stretch" Style="{DynamicResource StoreListStyle}"
VerticalContentAlignment="Center" VirtualizingPanel.CacheLength="1,1"
Background="{DynamicResource Color01B}" VirtualizingPanel.CacheLengthUnit="Page"
ItemContainerStyle="{StaticResource StoreList}" VirtualizingPanel.IsVirtualizingWhenGrouping="True"
ItemsSource="{Binding ExternalPlugins}" VirtualizingPanel.ScrollUnit="Pixel"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" VirtualizingPanel.VirtualizationMode="Standard">
SelectionMode="Single" <ListView.ItemsPanel>
Style="{DynamicResource StoreListStyle}"> <ItemsPanelTemplate>
<ListBox.GroupStyle> <wpftk:VirtualizingWrapPanel
<GroupStyle> x:Name="ItemWrapPanel"
<GroupStyle.ContainerStyle> Margin="0,0,0,10"
<Style TargetType="{x:Type GroupItem}"> ItemSize="216,184"
<Setter Property="Template"> MouseWheelDelta="48"
<Setter.Value> Orientation="Vertical"
<ControlTemplate> ScrollLineDelta="16"
<Grid> SpacingMode="None"
<StackPanel Orientation="Vertical"> StretchItems="True" />
<TextBlock </ItemsPanelTemplate>
Margin="0,0,0,10" </ListView.ItemsPanel>
VerticalAlignment="Top" <ListView.GroupStyle>
FontSize="16" <GroupStyle HidesIfEmpty="True">
FontWeight="Bold" <GroupStyle.ContainerStyle>
Text="{Binding Name, Converter={StaticResource TextConverter}}" /> <Style TargetType="{x:Type GroupItem}">
<ItemsPresenter /> <Setter Property="Template">
</StackPanel> <Setter.Value>
<ControlTemplate>
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock
Margin="2,0,0,10"
VerticalAlignment="Top"
FontSize="16"
FontWeight="Bold"
Foreground="{DynamicResource Color05B}"
Text="{Binding Name, Converter={StaticResource TextConverter}}" />
<ItemsPresenter />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="{Binding Orientation, Mode=OneWay}" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListView.GroupStyle>
</Grid> <ListView.ItemTemplate>
</ControlTemplate> <DataTemplate>
</Setter.Value> <!-- Hover Layout Style -->
</Setter> <Button
</Style> Name="StoreListItem"
</GroupStyle.ContainerStyle> Margin="0"
</GroupStyle> Padding="0"
</ListBox.GroupStyle> HorizontalAlignment="Stretch"
<ListBox.ItemsPanel> VerticalAlignment="Stretch"
<ItemsPanelTemplate> HorizontalContentAlignment="Stretch"
<UniformGrid VerticalContentAlignment="Stretch"
Margin="0,0,17,18" BorderThickness="0"
HorizontalAlignment="Left" Click="StoreListItem_Click"
VerticalAlignment="Top" FocusVisualStyle="{StaticResource StoreItemFocusVisualStyleKey}">
Columns="3" <ui:FlyoutService.Flyout>
IsItemsHost="True" <ui:Flyout x:Name="InstallFlyout" Placement="Bottom">
SnapsToDevicePixels="True" /> <Grid MinWidth="200">
</ItemsPanelTemplate> <Grid.ColumnDefinitions>
</ListBox.ItemsPanel> <ColumnDefinition Width="*" />
<ListBox.ItemTemplate> <ColumnDefinition Width="Auto" />
<DataTemplate> </Grid.ColumnDefinitions>
<!-- Hover Layout Style --> <Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<VirtualizingStackPanel
Grid.Row="0"
Grid.Column="0"
Margin="5,0,0,0"
Orientation="Horizontal">
<TextBlock
Margin="0,0,5,0"
VerticalAlignment="Center"
FontSize="14"
FontWeight="Bold"
Foreground="{DynamicResource Color05B}"
Text="{Binding Name}"
TextWrapping="Wrap"
ToolTip="{Binding Name}" />
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource Color05B}"
Text="{Binding Version}"
TextWrapping="Wrap"
ToolTip="{Binding Version}" />
</VirtualizingStackPanel>
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="5,4,0,0"
TextWrapping="Wrap">
<Hyperlink
Foreground="{DynamicResource Color04B}"
NavigateUri="{Binding Website}"
RequestNavigate="OnRequestNavigate">
<Run FontSize="12" Text="{Binding Author, Mode=OneWay}" />
</Hyperlink>
</TextBlock>
<ToggleButton <VirtualizingStackPanel
Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Grid.Row="0"
HorizontalAlignment="Left" Grid.RowSpan="2"
HorizontalContentAlignment="left" Grid.Column="1"
Background="Transparent" Margin="20,0,0,0"
IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" HorizontalAlignment="Right"
Style="{StaticResource StoreItem}"> Orientation="Horizontal">
<ToggleButton.Template> <Button
<ControlTemplate TargetType="{x:Type ButtonBase}"> MinHeight="42"
<ContentPresenter Margin="5,0,5,0"
x:Name="contentPresenter" Padding="15,5,15,5"
Margin="{TemplateBinding Padding}" HorizontalAlignment="Stretch"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="Center"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Click="OnExternalPluginInstallClick"
Content="{TemplateBinding Content}" Content="{DynamicResource installbtn}"
ContentStringFormat="{TemplateBinding ContentStringFormat}" Visibility="{Binding LabelInstalled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter='!'}" />
ContentTemplate="{TemplateBinding ContentTemplate}" <Button
Focusable="False" MinHeight="42"
RecognizesAccessKey="True" Margin="5,0,5,0"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> Padding="15,5,15,5"
<ControlTemplate.Triggers /> HorizontalAlignment="Right"
</ControlTemplate> VerticalAlignment="Center"
</ToggleButton.Template> Click="OnExternalPluginUninstallClick"
Content="{DynamicResource uninstallbtn}"
<Grid Visibility="{Binding LabelInstalled, Converter={StaticResource BoolToVisibilityConverter}}" />
Height="160" <Button
HorizontalAlignment="Left" MinHeight="42"
VerticalAlignment="Top"> Margin="5,0,5,0"
<Grid.RowDefinitions> Padding="15,5,15,5"
<RowDefinition Height="56" /> HorizontalAlignment="Right"
<RowDefinition Height="*" /> VerticalAlignment="Center"
</Grid.RowDefinitions> Click="OnExternalPluginUpdateClick"
<StackPanel Content="{DynamicResource updatebtn}"
Grid.Row="0" Style="{DynamicResource AccentButtonStyle}"
Grid.RowSpan="2" Visibility="{Binding LabelUpdate, Converter={StaticResource BoolToVisibilityConverter}}" />
Grid.Column="0" </VirtualizingStackPanel>
Grid.ColumnSpan="2" </Grid>
Margin="0,0,2,0" </ui:Flyout>
HorizontalAlignment="Right" </ui:FlyoutService.Flyout>
Orientation="Horizontal"> <Grid>
<StackPanel Width="200">
<StackPanel Orientation="Horizontal">
<Image
Grid.Column="0"
Width="32"
Height="32"
Margin="18,24,0,0"
HorizontalAlignment="Left"
RenderOptions.BitmapScalingMode="Fant"
Source="{Binding IcoPath, IsAsync=True}" />
<Border <Border
x:Name="LabelUpdate" x:Name="LabelUpdate"
Height="12" Height="12"
Margin="0,10,8,0" Margin="10,24,0,0"
Padding="6,2,6,2" Padding="6,2,6,2"
HorizontalAlignment="Right" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Top"
Background="#45BD59" Background="#45BD59"
CornerRadius="36" CornerRadius="36"
ToolTip="{DynamicResource LabelUpdateToolTip}" ToolTip="{DynamicResource LabelUpdateToolTip}"
Visibility="{Binding LabelUpdate, Converter={StaticResource BoolToVisibilityConverter}}" /> Visibility="{Binding LabelUpdate, Converter={StaticResource BoolToVisibilityConverter}}" />
</StackPanel> </StackPanel>
<TextBlock
<StackPanel
Grid.Row="0"
Margin="0,0,0,0"
VerticalAlignment="Top">
<StackPanel.Style>
<Style>
<Setter Property="StackPanel.Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" Value="true">
<Setter Property="StackPanel.Opacity" Value="1" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Image
Width="32"
Height="32"
Margin="20,20,6,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding IcoPath, IsAsync=True}"
Stretch="Uniform" />
</StackPanel>
<StackPanel
Grid.Row="1"
Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Margin="0,6,0,0"
VerticalAlignment="Top"
Panel.ZIndex="0">
<StackPanel.Style>
<Style>
<Setter Property="StackPanel.Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" Value="true">
<Setter Property="StackPanel.Opacity" Value="1" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock
Padding="20,0,20,0"
VerticalAlignment="Top"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}"
Text="{Binding Name}"
TextWrapping="WrapWithOverflow"
ToolTip="{Binding Version}" />
<TextBlock
Margin="0,6,0,0"
Padding="20,0,22,20"
Foreground="{DynamicResource Color04B}"
TextWrapping="WrapWithOverflow">
<Run
FontSize="12"
Foreground="{DynamicResource Color04B}"
Text="{Binding Description, Mode=OneWay}" />
</TextBlock>
</StackPanel>
<StackPanel
Grid.RowSpan="2"
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="2" Margin="18,10,18,0"
HorizontalAlignment="Stretch" FontWeight="SemiBold"
VerticalAlignment="Stretch"> Foreground="{DynamicResource Color05B}"
<StackPanel.Style> Text="{Binding Name}"
<Style> TextWrapping="Wrap"
<Setter Property="StackPanel.Visibility" Value="Collapsed" /> ToolTip="{Binding Version}" />
<Style.Triggers> <TextBlock
<DataTrigger Binding="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" Value="true"> Grid.Column="0"
<Setter Property="StackPanel.Visibility" Value="Visible" /> Height="60"
</DataTrigger> Margin="18,6,18,0"
</Style.Triggers> Padding="0,0,0,10"
</Style> FontSize="12"
</StackPanel.Style> Foreground="{DynamicResource Color04B}"
Text="{Binding Description, Mode=OneWay}"
TextTrimming="WordEllipsis"
TextWrapping="Wrap" />
</StackPanel>
<Grid </Grid>
Height="180" </Button>
HorizontalAlignment="Stretch" </DataTemplate>
VerticalAlignment="Stretch" </ListView.ItemTemplate>
Panel.ZIndex="1"> </ListView>
<Grid.Background>
<SolidColorBrush Opacity=".95" Color="{DynamicResource HoverStoreGrid}" />
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<StackPanel Orientation="Vertical">
<TextBlock
Margin="20,20,20,0"
Padding="0,0,0,0"
FontWeight="Bold"
Foreground="{DynamicResource Color05B}"
Text="{Binding Name}"
TextWrapping="WrapWithOverflow"
ToolTip="{Binding Name}" />
<TextBlock
Margin="20,4,20,0"
Padding="0,0,20,0"
Foreground="{DynamicResource Color05B}"
Text="{Binding Version}"
TextWrapping="WrapWithOverflow"
ToolTip="{Binding Version}" />
</StackPanel>
<StackPanel Margin="20,6,20,0" Orientation="Vertical">
<TextBlock Padding="0,0,0,0" TextWrapping="Wrap">
<Hyperlink
Foreground="{DynamicResource Color04B}"
NavigateUri="{Binding Website}"
RequestNavigate="OnRequestNavigate">
<Run FontSize="12" Text="{Binding Author, Mode=OneWay}" />
</Hyperlink>
</TextBlock>
</StackPanel>
</StackPanel>
<Grid Grid.Row="0" Grid.Column="1">
<StackPanel
Margin="0,70,20,0"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
MinHeight="40"
Padding="15,5,15,5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="OnExternalPluginInstallClick"
Content="{DynamicResource installbtn}"
Visibility="{Binding LabelInstalled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter='!'}" />
<Button
MinHeight="40"
Margin="5,0,0,0"
Padding="15,5,15,5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="OnExternalPluginUninstallClick"
Content="{DynamicResource uninstallbtn}"
Visibility="{Binding LabelInstalled, Converter={StaticResource BoolToVisibilityConverter}}" />
<Button
MinHeight="40"
Margin="5,0,0,0"
Padding="15,5,15,5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="OnExternalPluginUpdateClick"
Content="{DynamicResource updatebtn}"
Visibility="{Binding LabelUpdate, Converter={StaticResource BoolToVisibilityConverter}}" />
<!-- Hide Install Button when installed Item -->
</StackPanel>
</Grid>
</Grid>
</StackPanel>
</Grid>
</ToggleButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</Grid> </Grid>
</TabItem> </TabItem>
<!--#endregion--> <!--#endregion-->
@ -1763,7 +1683,9 @@
<ScrollViewer <ScrollViewer
Margin="0,0,0,0" Margin="0,0,0,0"
Padding="6,0,24,0" Padding="6,0,24,0"
ScrollViewer.CanContentScroll="False"> ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.ScrollUnit="Pixel">
<Grid Margin="0,0,0,0"> <Grid Margin="0,0,0,0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="0" /> <RowDefinition Height="0" />
@ -2339,7 +2261,9 @@
<ScrollViewer <ScrollViewer
Margin="0,0,0,0" Margin="0,0,0,0"
Padding="0,0,6,0" Padding="0,0,6,0"
ScrollViewer.CanContentScroll="False"> ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.ScrollUnit="Pixel">
<Border> <Border>
<Grid Margin="5,18,18,10"> <Grid Margin="5,18,18,10">
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -2520,8 +2444,8 @@
Foreground="{DynamicResource Color05B}" Foreground="{DynamicResource Color05B}"
Text="{DynamicResource customQueryShortcut}" /> Text="{DynamicResource customQueryShortcut}" />
<ListView <ListView
Grid.Row="7"
Name="customShortcutView" Name="customShortcutView"
Grid.Row="7"
MinHeight="160" MinHeight="160"
Margin="0,6,0,0" Margin="0,6,0,0"
Background="{DynamicResource Color02B}" Background="{DynamicResource Color02B}"
@ -2633,7 +2557,9 @@
<ScrollViewer <ScrollViewer
Margin="0,0,0,0" Margin="0,0,0,0"
Padding="5,0,24,0" Padding="5,0,24,0"
ScrollViewer.CanContentScroll="False"> ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.ScrollUnit="Pixel">
<Border> <Border>
<StackPanel> <StackPanel>
@ -2805,7 +2731,9 @@
<ScrollViewer <ScrollViewer
Margin="0,0,0,0" Margin="0,0,0,0"
Background="{DynamicResource Color01B}" Background="{DynamicResource Color01B}"
ScrollViewer.CanContentScroll="False"> ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.ScrollUnit="Pixel">
<StackPanel Margin="5,14,25,30" Orientation="Vertical"> <StackPanel Margin="5,14,25,30" Orientation="Vertical">
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"

View file

@ -8,14 +8,19 @@ using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using ModernWpf; using ModernWpf;
using ModernWpf.Controls;
using System; using System;
using System.Drawing.Printing;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Navigation; using System.Windows.Navigation;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
using Button = System.Windows.Controls.Button; using Button = System.Windows.Controls.Button;
using Control = System.Windows.Controls.Control; using Control = System.Windows.Controls.Control;
using KeyEventArgs = System.Windows.Input.KeyEventArgs; using KeyEventArgs = System.Windows.Input.KeyEventArgs;
@ -39,10 +44,6 @@ namespace Flow.Launcher
API = api; API = api;
InitializePosition(); InitializePosition();
InitializeComponent(); InitializeComponent();
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("Category");
view.GroupDescriptions.Add(groupDescription);
} }
#region General #region General
@ -252,6 +253,7 @@ namespace Flow.Launcher
private void OnClosed(object sender, EventArgs e) private void OnClosed(object sender, EventArgs e)
{ {
settings.SettingWindowState = WindowState;
settings.SettingWindowTop = Top; settings.SettingWindowTop = Top;
settings.SettingWindowLeft = Left; settings.SettingWindowLeft = Left;
viewModel.Save(); viewModel.Save();
@ -296,17 +298,35 @@ namespace Flow.Launcher
} }
} }
private void OnPluginStoreRefreshClick(object sender, RoutedEventArgs e) private static T FindParent<T>(DependencyObject child) where T : DependencyObject
{ {
_ = viewModel.RefreshExternalPluginsAsync(); //get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
} }
private void OnExternalPluginInstallClick(object sender, RoutedEventArgs e) private void OnExternalPluginInstallClick(object sender, RoutedEventArgs e)
{ {
if (sender is Button { DataContext: PluginStoreItemViewModel plugin }) if (sender is not Button { DataContext: PluginStoreItemViewModel plugin } button)
{ {
viewModel.DisplayPluginQuery($"install {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); return;
} }
if (storeClickedButton != null)
{
FlyoutService.GetFlyout(storeClickedButton).Hide();
}
viewModel.DisplayPluginQuery($"install {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
} }
private void OnExternalPluginUninstallClick(object sender, MouseButtonEventArgs e) private void OnExternalPluginUninstallClick(object sender, MouseButtonEventArgs e)
@ -317,18 +337,30 @@ namespace Flow.Launcher
viewModel.DisplayPluginQuery($"uninstall {name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); viewModel.DisplayPluginQuery($"uninstall {name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
} }
} }
private void OnExternalPluginUninstallClick(object sender, RoutedEventArgs e) private void OnExternalPluginUninstallClick(object sender, RoutedEventArgs e)
{ {
if (storeClickedButton != null)
{
FlyoutService.GetFlyout(storeClickedButton).Hide();
}
if (sender is Button { DataContext: PluginStoreItemViewModel plugin }) if (sender is Button { DataContext: PluginStoreItemViewModel plugin })
viewModel.DisplayPluginQuery($"uninstall {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); viewModel.DisplayPluginQuery($"uninstall {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
} }
private void OnExternalPluginUpdateClick(object sender, RoutedEventArgs e) private void OnExternalPluginUpdateClick(object sender, RoutedEventArgs e)
{ {
if (storeClickedButton != null)
{
FlyoutService.GetFlyout(storeClickedButton).Hide();
}
if (sender is Button { DataContext: PluginStoreItemViewModel plugin }) if (sender is Button { DataContext: PluginStoreItemViewModel plugin })
viewModel.DisplayPluginQuery($"update {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); viewModel.DisplayPluginQuery($"update {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
} }
private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */
@ -522,6 +554,7 @@ namespace Flow.Launcher
Top = WindowTop(); Top = WindowTop();
Left = WindowLeft(); Left = WindowLeft();
} }
WindowState = settings.SettingWindowState;
} }
public double WindowLeft() public double WindowLeft()
{ {
@ -541,5 +574,21 @@ namespace Flow.Launcher
return top; return top;
} }
private Button storeClickedButton;
private void StoreListItem_Click(object sender, RoutedEventArgs e)
{
if (sender is not Button button)
return;
storeClickedButton = button;
var flyout = FlyoutService.GetFlyout(button);
flyout.Closed += (_, _) =>
{
storeClickedButton = null;
};
}
} }
} }

View file

@ -20,10 +20,11 @@ using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.Plugin.SharedModels;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.Input;
namespace Flow.Launcher.ViewModel namespace Flow.Launcher.ViewModel
{ {
public class SettingWindowViewModel : BaseModel public partial class SettingWindowViewModel : BaseModel
{ {
private readonly Updater _updater; private readonly Updater _updater;
private readonly IPortable _portable; private readonly IPortable _portable;
@ -330,7 +331,8 @@ namespace Flow.Launcher.ViewModel
} }
} }
public async Task RefreshExternalPluginsAsync() [RelayCommand]
private async Task RefreshExternalPluginsAsync()
{ {
await PluginsManifest.UpdateManifestAsync(); await PluginsManifest.UpdateManifestAsync();
OnPropertyChanged(nameof(ExternalPlugins)); OnPropertyChanged(nameof(ExternalPlugins));
@ -535,6 +537,8 @@ namespace Flow.Launcher.ViewModel
var bitmap = new BitmapImage(); var bitmap = new BitmapImage();
bitmap.BeginInit(); bitmap.BeginInit();
bitmap.StreamSource = memStream; bitmap.StreamSource = memStream;
bitmap.DecodePixelWidth = 800;
bitmap.DecodePixelHeight = 600;
bitmap.EndInit(); bitmap.EndInit();
var brush = new ImageBrush(bitmap) var brush = new ImageBrush(bitmap)
{ {

View file

@ -601,92 +601,97 @@ namespace Flow.Launcher.Plugin.Program.Programs
// windows 8.1 https://msdn.microsoft.com/en-us/library/windows/apps/hh965372.aspx#target_size // windows 8.1 https://msdn.microsoft.com/en-us/library/windows/apps/hh965372.aspx#target_size
// windows 8 https://msdn.microsoft.com/en-us/library/windows/apps/br211475.aspx // windows 8 https://msdn.microsoft.com/en-us/library/windows/apps/br211475.aspx
string path; string path = Path.Combine(Package.Location, uri);
if (uri.Contains("\\"))
{ var logoPath = TryToFindLogo(uri, path);
path = Path.Combine(Package.Location, uri); if (String.IsNullOrEmpty(logoPath))
}
else
{ {
// TODO: Don't know why, just keep it at the moment
// Maybe on older version of Windows 10?
// for C:\Windows\MiracastView etc // for C:\Windows\MiracastView etc
path = Path.Combine(Package.Location, "Assets", uri); return TryToFindLogo(uri, Path.Combine(Package.Location, "Assets", uri));
} }
return logoPath;
var extension = Path.GetExtension(path); string TryToFindLogo(string uri, string path)
if (extension != null)
{ {
var end = path.Length - extension.Length; var extension = Path.GetExtension(path);
var prefix = path.Substring(0, end); if (extension != null)
var paths = new List<string>
{ {
path //if (File.Exists(path))
}; //{
// return path; // shortcut, avoid enumerating files
//}
var scaleFactors = new Dictionary<PackageVersion, List<int>> var logoNamePrefix = Path.GetFileNameWithoutExtension(uri); // e.g Square44x44
{ var logoDir = Path.GetDirectoryName(path); // e.g ..\..\Assets
// scale factors on win10: https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/tiles-and-notifications-app-assets#asset-size-tables, if (String.IsNullOrEmpty(logoNamePrefix) || String.IsNullOrEmpty(logoDir) || !Directory.Exists(logoDir))
{ {
PackageVersion.Windows10, new List<int> // Known issue: Edge always triggers it since logo is not at uri
{ ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Package.Location}" +
100, $"|{UserModelId} can't find logo uri for {uri} in package location (logo name or directory not found): {Package.Location}", new FileNotFoundException());
125, return string.Empty;
150, }
200,
400 var files = Directory.EnumerateFiles(logoDir);
}
}, // Currently we don't care which one to choose
// Just ignore all qualifiers
// select like logo.[xxx_yyy].png
// https://learn.microsoft.com/en-us/windows/uwp/app-resources/tailor-resources-lang-scale-contrast
var logos = files.Where(file =>
Path.GetFileName(file)?.StartsWith(logoNamePrefix, StringComparison.OrdinalIgnoreCase) ?? false
&& extension.Equals(Path.GetExtension(file), StringComparison.OrdinalIgnoreCase)
);
var selected = logos.FirstOrDefault();
var closest = selected;
int min = int.MaxValue;
foreach(var logo in logos)
{ {
PackageVersion.Windows81, new List<int>
var imageStream = File.OpenRead(logo);
var decoder = BitmapDecoder.Create(imageStream, BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.None);
var height = decoder.Frames[0].PixelHeight;
var width = decoder.Frames[0].PixelWidth;
int pixelCountDiff = Math.Abs(height * width - 1936); // 44*44=1936
if(pixelCountDiff < min)
{ {
100, // try to find the closest to 44x44 logo
120, closest = logo;
140, if (pixelCountDiff == 0)
160, break; // found 44x44
180 min = pixelCountDiff;
}
},
{
PackageVersion.Windows8, new List<int>
{
100
} }
} }
};
if (scaleFactors.ContainsKey(Package.Version)) selected = closest;
{ if (!string.IsNullOrEmpty(selected))
foreach (var factor in scaleFactors[Package.Version])
{ {
paths.Add($"{prefix}.scale-{factor}{extension}"); return selected;
}
else
{
ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Package.Location}" +
$"|{UserModelId} can't find logo uri for {uri} in package location (can't find specified logo): {Package.Location}", new FileNotFoundException());
return string.Empty;
} }
}
var selected = paths.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(selected))
{
return selected;
} }
else else
{ {
ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Package.Location}" + ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Package.Location}" +
$"|{UserModelId} can't find logo uri for {uri} in package location: {Package.Location}", new FileNotFoundException()); $"|Unable to find extension from {uri} for {UserModelId} " +
$"in package location {Package.Location}", new FileNotFoundException());
return string.Empty; return string.Empty;
} }
} }
else
{
ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Package.Location}" +
$"|Unable to find extension from {uri} for {UserModelId} " +
$"in package location {Package.Location}", new FileNotFoundException());
return string.Empty;
}
} }
public ImageSource Logo() public ImageSource Logo()
{ {
var logo = ImageFromPath(LogoPath); var logo = ImageFromPath(LogoPath);
var plated = PlatedImage(logo); var plated = PlatedImage(logo); // TODO: maybe get plated directly from app package?
// todo magic! temp fix for cross thread object // todo magic! temp fix for cross thread object
plated.Freeze(); plated.Freeze();

View file

@ -7,6 +7,10 @@ init:
- sc config WSearch start= auto # Starts Windows Search service- Needed for running ExplorerTest - sc config WSearch start= auto # Starts Windows Search service- Needed for running ExplorerTest
- net start WSearch - net start WSearch
cache:
- '%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
@ -28,7 +32,9 @@ before_build:
build: build:
project: Flow.Launcher.sln project: Flow.Launcher.sln
verbosity: minimal verbosity: minimal
after_build: test_script:
- dotnet test --no-build -c Release
after_test:
- ps: .\Scripts\post_build.ps1 - ps: .\Scripts\post_build.ps1
artifacts: artifacts: