mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #1600 from VictoriousRaptor/FixProgramSource
[Dev] Refactor AddProgramSource dialog and bugfix
This commit is contained in:
commit
71a1ca7a1d
7 changed files with 163 additions and 114 deletions
|
|
@ -4,7 +4,10 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:vm="clr-namespace:Flow.Launcher.Plugin.Program.ViewModels"
|
||||||
|
mc:Ignorable="d"
|
||||||
Title="{DynamicResource flowlauncher_plugin_program_directory}"
|
Title="{DynamicResource flowlauncher_plugin_program_directory}"
|
||||||
|
d:DataContext="{d:DesignInstance vm:AddProgramSourceViewModel}"
|
||||||
Width="Auto"
|
Width="Auto"
|
||||||
Height="276"
|
Height="276"
|
||||||
Background="{DynamicResource PopuBGColor}"
|
Background="{DynamicResource PopuBGColor}"
|
||||||
|
|
@ -15,6 +18,9 @@
|
||||||
<WindowChrome.WindowChrome>
|
<WindowChrome.WindowChrome>
|
||||||
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
|
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
|
||||||
</WindowChrome.WindowChrome>
|
</WindowChrome.WindowChrome>
|
||||||
|
<Window.Resources>
|
||||||
|
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
</Window.Resources>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
|
|
@ -98,11 +104,14 @@
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Click="BrowseButton_Click"
|
Click="BrowseButton_Click"
|
||||||
Content="{DynamicResource flowlauncher_plugin_program_browse}"
|
Content="{DynamicResource flowlauncher_plugin_program_browse}"
|
||||||
|
Visibility="{Binding IsCustomSource, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
DockPanel.Dock="Right" />
|
DockPanel.Dock="Right" />
|
||||||
<TextBox
|
<TextBox
|
||||||
Name="Directory"
|
Name="Directory"
|
||||||
Width="350"
|
Width="350"
|
||||||
Margin="10"
|
Margin="10"
|
||||||
|
Text="{Binding Location, Mode=TwoWay}"
|
||||||
|
IsReadOnly="{Binding IsNotCustomSource}"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
@ -119,6 +128,7 @@
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="10,0"
|
Margin="10,0"
|
||||||
|
IsChecked="{Binding Enabled, Mode=TwoWay}"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
@ -142,7 +152,7 @@
|
||||||
MinWidth="140"
|
MinWidth="140"
|
||||||
Margin="5,0,10,0"
|
Margin="5,0,10,0"
|
||||||
Click="BtnAdd_OnClick"
|
Click="BtnAdd_OnClick"
|
||||||
Content="{DynamicResource flowlauncher_plugin_program_update}"
|
Content="{Binding AddBtnText}"
|
||||||
Style="{DynamicResource AccentButtonStyle}" />
|
Style="{DynamicResource AccentButtonStyle}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Forms;
|
using Flow.Launcher.Plugin.Program.ViewModels;
|
||||||
using Flow.Launcher.Plugin.Program.Views.Models;
|
|
||||||
using Flow.Launcher.Plugin.Program.Views;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.Program
|
namespace Flow.Launcher.Plugin.Program
|
||||||
{
|
{
|
||||||
|
|
@ -11,41 +8,18 @@ namespace Flow.Launcher.Plugin.Program
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class AddProgramSource : Window
|
public partial class AddProgramSource : Window
|
||||||
{
|
{
|
||||||
private PluginInitContext _context;
|
private readonly AddProgramSourceViewModel ViewModel;
|
||||||
private ProgramSource _editing;
|
|
||||||
private Settings _settings;
|
|
||||||
private bool update;
|
|
||||||
|
|
||||||
public AddProgramSource(PluginInitContext context, Settings settings)
|
public AddProgramSource(AddProgramSourceViewModel viewModel)
|
||||||
{
|
{
|
||||||
|
ViewModel = viewModel;
|
||||||
|
DataContext = viewModel;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_context = context;
|
|
||||||
_settings = settings;
|
|
||||||
Directory.Focus();
|
|
||||||
Chkbox.IsChecked = true;
|
|
||||||
update = false;
|
|
||||||
btnAdd.Content = _context.API.GetTranslation("flowlauncher_plugin_program_add");
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddProgramSource(PluginInitContext context, Settings settings, ProgramSource source)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
_context = context;
|
|
||||||
_editing = source;
|
|
||||||
_settings = settings;
|
|
||||||
update = true;
|
|
||||||
Chkbox.IsChecked = _editing.Enabled;
|
|
||||||
Directory.Text = _editing.Location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BrowseButton_Click(object sender, RoutedEventArgs e)
|
private void BrowseButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var dialog = new FolderBrowserDialog();
|
ViewModel.Browse();
|
||||||
DialogResult result = dialog.ShowDialog();
|
|
||||||
if (result == System.Windows.Forms.DialogResult.OK)
|
|
||||||
{
|
|
||||||
Directory.Text = dialog.SelectedPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
|
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
|
@ -55,51 +29,12 @@ namespace Flow.Launcher.Plugin.Program
|
||||||
|
|
||||||
private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
|
private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
string path = Directory.Text;
|
var (modified, msg) = ViewModel.AddOrUpdate();
|
||||||
bool modified = false;
|
if (modified == false && msg != null)
|
||||||
if (!System.IO.Directory.Exists(path))
|
|
||||||
{
|
{
|
||||||
System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
|
MessageBox.Show(msg); // Invalid
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!update)
|
|
||||||
{
|
|
||||||
if (!ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier.Equals(path, System.StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
var source = new ProgramSource(path);
|
|
||||||
modified = true;
|
|
||||||
_settings.ProgramSources.Insert(0, source);
|
|
||||||
ProgramSetting.ProgramSettingDisplayList.Add(source);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Separate checks to avoid changing UniqueIdentifier of UWP
|
|
||||||
if (!_editing.Location.Equals(path, System.StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (ProgramSetting.ProgramSettingDisplayList
|
|
||||||
.Any(x => x.UniqueIdentifier.Equals(path, System.StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
// Check if the new location is used
|
|
||||||
// No need to check win32 or uwp, just override them
|
|
||||||
System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
modified = true;
|
|
||||||
_editing.Location = path; // Changes UniqueIdentifier internally
|
|
||||||
}
|
|
||||||
if (_editing.Enabled != Chkbox.IsChecked)
|
|
||||||
{
|
|
||||||
modified = true;
|
|
||||||
_editing.Enabled = Chkbox.IsChecked ?? true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogResult = modified;
|
DialogResult = modified;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Markup;
|
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.Program
|
|
||||||
{
|
|
||||||
public class LocationConverter : MarkupExtension, IValueConverter
|
|
||||||
{
|
|
||||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
var text = value as string;
|
|
||||||
if (string.IsNullOrEmpty(text))
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Flow.Launcher.Plugin.Program.Views;
|
||||||
|
using Flow.Launcher.Plugin.Program.Views.Models;
|
||||||
|
|
||||||
|
namespace Flow.Launcher.Plugin.Program.ViewModels
|
||||||
|
{
|
||||||
|
public class AddProgramSourceViewModel : BaseModel
|
||||||
|
{
|
||||||
|
private readonly Settings Settings;
|
||||||
|
|
||||||
|
private bool enabled = true;
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
get => enabled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
enabled = value;
|
||||||
|
StatusModified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string location = string.Empty;
|
||||||
|
public string Location
|
||||||
|
{
|
||||||
|
get => location;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
location = value;
|
||||||
|
LocationModified = true;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramSource Source { get; init; }
|
||||||
|
public IPublicAPI API { get; init; }
|
||||||
|
public string AddBtnText { get; init; }
|
||||||
|
private bool LocationModified = false;
|
||||||
|
private bool StatusModified = false;
|
||||||
|
public bool IsCustomSource { get; init; } = true;
|
||||||
|
public bool IsNotCustomSource => !IsCustomSource;
|
||||||
|
|
||||||
|
public AddProgramSourceViewModel(PluginInitContext context, Settings settings)
|
||||||
|
{
|
||||||
|
API = context.API;
|
||||||
|
Settings = settings;
|
||||||
|
AddBtnText = API.GetTranslation("flowlauncher_plugin_program_add");
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddProgramSourceViewModel(PluginInitContext context, Settings settings, ProgramSource programSource) : this(context, settings)
|
||||||
|
{
|
||||||
|
Source = programSource;
|
||||||
|
enabled = Source.Enabled;
|
||||||
|
location = Source.Location;
|
||||||
|
AddBtnText = API.GetTranslation("flowlauncher_plugin_program_update");
|
||||||
|
IsCustomSource = Settings.ProgramSources.Any(x => x.UniqueIdentifier == Source.UniqueIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Browse()
|
||||||
|
{
|
||||||
|
var dialog = new FolderBrowserDialog();
|
||||||
|
DialogResult result = dialog.ShowDialog();
|
||||||
|
if (result == DialogResult.OK)
|
||||||
|
{
|
||||||
|
Location = dialog.SelectedPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public (bool modified, string message) AddProgramSource()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(Location))
|
||||||
|
{
|
||||||
|
return (false, API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
|
||||||
|
}
|
||||||
|
else if (DuplicateSource(Location))
|
||||||
|
{
|
||||||
|
return (false, API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var source = new ProgramSource(Location, Enabled);
|
||||||
|
Settings.ProgramSources.Insert(0, source);
|
||||||
|
ProgramSetting.ProgramSettingDisplayList.Add(source);
|
||||||
|
return (true, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public (bool modified, string message) UpdateProgramSource()
|
||||||
|
{
|
||||||
|
if (LocationModified)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(Location))
|
||||||
|
{
|
||||||
|
return (false, API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
|
||||||
|
}
|
||||||
|
else if (DuplicateSource(Location))
|
||||||
|
{
|
||||||
|
return (false, API.GetTranslation("flowlauncher_plugin_program_duplicate_program_source"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Source.Location = Location; // Changes UniqueIdentifier internally
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StatusModified)
|
||||||
|
{
|
||||||
|
Source.Enabled = Enabled;
|
||||||
|
}
|
||||||
|
return (StatusModified || LocationModified, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (bool modified, string message) AddOrUpdate()
|
||||||
|
{
|
||||||
|
if (Source == null)
|
||||||
|
{
|
||||||
|
return AddProgramSource();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return UpdateProgramSource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool DuplicateSource(string location)
|
||||||
|
{
|
||||||
|
return ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier.Equals(location, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -83,7 +83,7 @@ namespace Flow.Launcher.Plugin.Program.Views.Models
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(UniqueIdentifier);
|
return uniqueIdentifier.GetHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:program="clr-namespace:Flow.Launcher.Plugin.Program"
|
|
||||||
Height="520"
|
Height="520"
|
||||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
@ -180,7 +179,7 @@
|
||||||
<GridViewColumn Header="{DynamicResource flowlauncher_plugin_program_location}">
|
<GridViewColumn Header="{DynamicResource flowlauncher_plugin_program_location}">
|
||||||
<GridViewColumn.CellTemplate>
|
<GridViewColumn.CellTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding Location, ConverterParameter=(null), Converter={program:LocationConverter}}" TextTrimming="CharacterEllipsis" />
|
<TextBlock Text="{Binding Location}" TextTrimming="CharacterEllipsis" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</GridViewColumn.CellTemplate>
|
</GridViewColumn.CellTemplate>
|
||||||
</GridViewColumn>
|
</GridViewColumn>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using Flow.Launcher.Plugin.Program.Views.Commands;
|
||||||
using Flow.Launcher.Plugin.Program.Programs;
|
using Flow.Launcher.Plugin.Program.Programs;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System;
|
using Flow.Launcher.Plugin.Program.ViewModels;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.Program.Views
|
namespace Flow.Launcher.Plugin.Program.Views
|
||||||
{
|
{
|
||||||
|
|
@ -136,7 +136,8 @@ namespace Flow.Launcher.Plugin.Program.Views
|
||||||
|
|
||||||
private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
|
private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var add = new AddProgramSource(context, _settings);
|
var vm = new AddProgramSourceViewModel(context, _settings);
|
||||||
|
var add = new AddProgramSource(vm);
|
||||||
if (add.ShowDialog() ?? false)
|
if (add.ShowDialog() ?? false)
|
||||||
{
|
{
|
||||||
ReIndexing();
|
ReIndexing();
|
||||||
|
|
@ -171,7 +172,12 @@ namespace Flow.Launcher.Plugin.Program.Views
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var add = new AddProgramSource(context, _settings, selectedProgramSource);
|
var vm = new AddProgramSourceViewModel(context, _settings, selectedProgramSource);
|
||||||
|
var add = new AddProgramSource(vm);
|
||||||
|
int selectedIndex = programSourceView.SelectedIndex;
|
||||||
|
// https://stackoverflow.com/questions/16789360/wpf-listbox-items-with-changing-hashcode
|
||||||
|
// Or it can't be unselected after changing Location
|
||||||
|
programSourceView.UnselectAll();
|
||||||
if (add.ShowDialog() ?? false)
|
if (add.ShowDialog() ?? false)
|
||||||
{
|
{
|
||||||
if (selectedProgramSource.Enabled)
|
if (selectedProgramSource.Enabled)
|
||||||
|
|
@ -186,6 +192,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
||||||
}
|
}
|
||||||
ReIndexing();
|
ReIndexing();
|
||||||
}
|
}
|
||||||
|
programSourceView.SelectedIndex = selectedIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue