Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 71 additions & 18 deletions src/ScriptRunner/ScriptRunner.GUI/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@
private readonly ObservableAsPropertyHelper<IEnumerable<ScriptConfigGroupWrapper>> _filteredActionList;
public IEnumerable<ScriptConfigGroupWrapper> FilteredActionList => _filteredActionList.Value;

private readonly ObservableAsPropertyHelper<int> _actionCount;
public int ActionCount => _actionCount.Value;




public ObservableCollection<RunningJobViewModel> RunningJobs { get; set; } = new();
Expand Down Expand Up @@ -215,9 +219,13 @@
set
{
this.RaiseAndSetIfChanged(ref _selectedActionOrGroup, value);
if (value is TaggedScriptConfig {Config: var scriptConfig})
if (value is TaggedScriptConfig {Config: var scriptConfig, ArgumentSet: var argumentSet})
{
SelectedAction = scriptConfig;
if (argumentSet != null)
{
SelectedArgumentSet = argumentSet;
}
}
}
}
Expand Down Expand Up @@ -393,12 +401,8 @@
{
var (textFilter, categoryFilter, actions) = tuple;

// Apply text filter
var configs = string.IsNullOrWhiteSpace(textFilter)
? actions
: actions.Where(x => x.Name.Contains(textFilter, StringComparison.InvariantCultureIgnoreCase));

// Apply category filter (AND operator with text filter)
// Apply category filter first
IEnumerable<ScriptConfig> configs = actions;
if (!string.IsNullOrWhiteSpace(categoryFilter) && categoryFilter != "All")
{
if (categoryFilter == "(No Category)")
Expand All @@ -416,38 +420,82 @@
// When a specific category is filtered, show each action only once under that category
if (!string.IsNullOrWhiteSpace(categoryFilter) && categoryFilter != "All")
{
scriptConfigGroupWrappers = new[]
var expandedEntries = configs.SelectMany(c =>
c.PredefinedArgumentSets.Select(p => new TaggedScriptConfig(
categoryFilter,
p.Description == "<default>" ? c.Name : $"{c.Name} - {p.Description}",
c,
p
))
);

// Apply text filter to expanded entries
if (!string.IsNullOrWhiteSpace(textFilter))
{
new ScriptConfigGroupWrapper
expandedEntries = expandedEntries.Where(x => x.Name.Contains(textFilter, StringComparison.InvariantCultureIgnoreCase));
}

var children = expandedEntries.OrderBy(x => x.Name).ToList();

// Only create group if it has children
scriptConfigGroupWrappers = children.Any()
? new[]
{
Name = categoryFilter,
Children = configs.Select(c => new TaggedScriptConfig(categoryFilter, c.Name, c)).OrderBy(x => x.Name)
new ScriptConfigGroupWrapper
{
Name = categoryFilter,
Children = children
}
}
};
: Enumerable.Empty<ScriptConfigGroupWrapper>();
}
else
{
// When no filter or "All" is selected, show actions grouped by all their categories
scriptConfigGroupWrappers = configs.SelectMany(c =>
var groupedConfigs = configs.SelectMany(c =>
{
if (c.Categories is {Count: > 0})
{
return c.Categories.DistinctBy(x=>x).Select((cat) => (category: cat, script: c));
}

return new[] {(category: "(No Category)", script: c)};
}).GroupBy(x => x.category).OrderBy(x=>x.Key)
.Select(x=> new ScriptConfigGroupWrapper
}).GroupBy(x => x.category).OrderBy(x=>x.Key);

scriptConfigGroupWrappers = groupedConfigs.Select(x =>
{
var expandedEntries = x.SelectMany(p =>
p.script.PredefinedArgumentSets.Select(argSet => new TaggedScriptConfig(
x.Key,
argSet.Description == "<default>" ? p.script.Name : $"{p.script.Name} - {argSet.Description}",
p.script,
argSet
))
);

// Apply text filter to expanded entries
if (!string.IsNullOrWhiteSpace(textFilter))
{
expandedEntries = expandedEntries.Where(e => e.Name.Contains(textFilter, StringComparison.InvariantCultureIgnoreCase));
}

return new ScriptConfigGroupWrapper
{
Name = x.Key,
Children = x.Select(p=> new TaggedScriptConfig(x.Key, p.script.Name, p.script)).OrderBy(x=>x.Name)
});
Children = expandedEntries.OrderBy(e => e.Name)
};
}).Where(group => group.Children.Any()); // Filter out empty groups
}

return scriptConfigGroupWrappers;
})
.ObserveOn(RxApp.MainThreadScheduler)
.ToProperty(this, x => x.FilteredActionList, out _filteredActionList);

this.WhenAnyValue(x => x.Actions)
.Select(list => list?.Count ?? 0)
.ObserveOn(RxApp.MainThreadScheduler)
.ToProperty(this, x => x.ActionCount, out _actionCount);

Observable
.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
Expand Down Expand Up @@ -1448,4 +1496,9 @@
public IEnumerable<TaggedScriptConfig> Children { get; set; }
}

public record TaggedScriptConfig(string Tag, string Name, ScriptConfig Config);
public record TaggedScriptConfig(string Tag, string Name, ScriptConfig Config, ArgumentSet ArgumentSet = null)

Check warning on line 1499 in src/ScriptRunner/ScriptRunner.GUI/ViewModels/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build-extension

Cannot convert null literal to non-nullable reference type.
{
public string IconName => "fa-scroll";
public string IconColor => ArgumentSet?.Description == "<default>" ? "#3baced" : "#ff8c00";
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
Expand Down Expand Up @@ -33,7 +33,8 @@ public SearchBoxViewModel(IReadOnlyList<ScriptConfig> allActions, IReadOnlyList<
ArgumentSet = p,
FullName = p.Description == "<default>"? x.FullName : $"{x.FullName} - {p.Description}",
ActionName = p.Description == "<default>"? x.Name : $"{x.Name} - {p.Description}",
SourceName = x.SourceName
SourceName = x.SourceName,
IconColor = p.Description == "<default>" ? "#3baced" : "#ff8c00"
})).ToList();

var intial = true;
Expand Down Expand Up @@ -105,6 +106,7 @@ public class ScriptConfigWithArgumentSet
public string FullName { get; set; }
public string ActionName { get; set; }
public string SourceName { get; set; }
public string IconColor { get; set; }

}
}
24 changes: 20 additions & 4 deletions src/ScriptRunner/ScriptRunner.GUI/Views/ActionDetailsSection.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,26 @@
<Button DockPanel.Dock="Top" HorizontalAlignment="Right" Background="Transparent" avalonia:Attached.Icon="fas fa-cog" Width="35" Height="35" VerticalAlignment="Top" >
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft" >
<MenuItem Header="Reinstall script" IsVisible="{Binding InstallAvailable}" Command="{Binding InstallScript}" />
<MenuItem Header="Reset default settings" Command="{Binding ResetDefaults}" />
<MenuItem Header="Open containing dir in VSCode" Command="{Binding OpenDirInVsCode}" />
<MenuItem Header="Open definition in VSCode" Command="{Binding OpenDefinitionInVsCode}" />
<MenuItem Header="Reinstall script" IsVisible="{Binding InstallAvailable}" Command="{Binding InstallScript}">
<MenuItem.Icon>
<avalonia:Icon Value="fas fa-sync" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Reset default settings" Command="{Binding ResetDefaults}">
<MenuItem.Icon>
<avalonia:Icon Value="fas fa-undo" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Open containing dir in VSCode" Command="{Binding OpenDirInVsCode}">
<MenuItem.Icon>
<avalonia:Icon Value="fas fa-folder-open" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Open definition in VSCode" Command="{Binding OpenDefinitionInVsCode}">
<MenuItem.Icon>
<avalonia:Icon Value="fas fa-file-code" />
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</Button.Flyout>
</Button>
Expand Down
31 changes: 21 additions & 10 deletions src/ScriptRunner/ScriptRunner.GUI/Views/ActionsList.axaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<UserControl xmlns="https://github.com/avaloniaui"
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Expand Down Expand Up @@ -40,9 +40,10 @@
</Style>
</UserControl.Styles>

<Grid RowDefinitions="Auto,Auto,Auto,*">
<Grid RowDefinitions="Auto,Auto,Auto,*,Auto">
<!-- View Mode Tabs -->
<Border Grid.Row="0" Background="#252526" BorderBrush="#3f3f46" BorderThickness="0,0,0,1" Padding="10,5">

<StackPanel Orientation="Horizontal" Spacing="5">
<RadioButton GroupName="ViewMode" IsChecked="{Binding IsTreeViewMode}" Padding="12,6">
<StackPanel Orientation="Horizontal" Spacing="6">
Expand Down Expand Up @@ -162,7 +163,7 @@
</TreeDataTemplate>
<DataTemplate x:DataType="viewModels:TaggedScriptConfig">
<StackPanel Orientation="Horizontal" Spacing="8">
<avalonia:Icon Value="fa-file-code" FontSize="16" Foreground="#3baced" />
<avalonia:Icon Value="{Binding IconName}" FontSize="16" Foreground="{Binding IconColor}" />
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
Expand Down Expand Up @@ -196,37 +197,37 @@
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="viewModels:TaggedScriptConfig">
<Border CornerRadius="4"
Padding="16,12"
Padding="12,12"
Margin="4,2"
Cursor="Hand"
Classes="actionTile"
Tapped="ActionTile_OnTapped">
<Grid RowDefinitions="Auto,Auto,Auto">
<!-- Action Name with Icon -->
<StackPanel Orientation="Horizontal" Spacing="10" Grid.Row="0">
<avalonia:Icon Value="fa-file-code" FontSize="20" Foreground="#3baced" VerticalAlignment="Top" Margin="0,2,0,0"/>
<TextBlock Text="{Binding Name}"
<Grid ColumnDefinitions="Auto,*" Grid.Row="0">
<avalonia:Icon Grid.Column="0" Value="{Binding IconName}" FontSize="20" Foreground="{Binding IconColor}" VerticalAlignment="Top" Margin="0,2,10,0"/>
<TextBlock Grid.Column="1" Text="{Binding Name}"
FontSize="15"
FontWeight="SemiBold"
TextWrapping="Wrap"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>

<!-- Description -->
<TextBlock Grid.Row="1"
Text="{Binding Config.Description}"
Foreground="#b0b0b0"
FontSize="12"
TextWrapping="Wrap"
Margin="30,6,0,0"
Margin="32,6,0,0"
MaxHeight="40"
TextTrimming="CharacterEllipsis"
IsVisible="{Binding Config.Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>

<!-- Category Badges -->
<ItemsControl Grid.Row="2"
ItemsSource="{Binding Config.Categories}"
Margin="30,8,0,0"
Margin="32,8,0,0"
IsVisible="{Binding Config.Categories.Count}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
Expand Down Expand Up @@ -258,5 +259,15 @@
</ItemsControl>
</ScrollViewer>
</Panel>

<!-- Footer -->
<Border Grid.Row="4" Background="#252526" BorderBrush="#3f3f46" BorderThickness="0,1,0,0" Padding="12,8">
<TextBlock Text="{Binding ActionCount, StringFormat='Total actions: {0}'}"
Foreground="#888888"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</Border>
</Grid>
</UserControl>

Loading
Loading