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:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
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}"
|
||||
d:DataContext="{d:DesignInstance vm:AddProgramSourceViewModel}"
|
||||
Width="Auto"
|
||||
Height="276"
|
||||
Background="{DynamicResource PopuBGColor}"
|
||||
|
|
@ -15,6 +18,9 @@
|
|||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
|
||||
</WindowChrome.WindowChrome>
|
||||
<Window.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
|
|
@ -98,11 +104,14 @@
|
|||
HorizontalAlignment="Stretch"
|
||||
Click="BrowseButton_Click"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_browse}"
|
||||
Visibility="{Binding IsCustomSource, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
DockPanel.Dock="Right" />
|
||||
<TextBox
|
||||
Name="Directory"
|
||||
Width="350"
|
||||
Margin="10"
|
||||
Text="{Binding Location, Mode=TwoWay}"
|
||||
IsReadOnly="{Binding IsNotCustomSource}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center" />
|
||||
</DockPanel>
|
||||
|
|
@ -119,6 +128,7 @@
|
|||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="10,0"
|
||||
IsChecked="{Binding Enabled, Mode=TwoWay}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
|
@ -142,7 +152,7 @@
|
|||
MinWidth="140"
|
||||
Margin="5,0,10,0"
|
||||
Click="BtnAdd_OnClick"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_update}"
|
||||
Content="{Binding AddBtnText}"
|
||||
Style="{DynamicResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using Flow.Launcher.Plugin.Program.Views.Models;
|
||||
using Flow.Launcher.Plugin.Program.Views;
|
||||
using System.Linq;
|
||||
using Flow.Launcher.Plugin.Program.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program
|
||||
{
|
||||
|
|
@ -11,41 +8,18 @@ namespace Flow.Launcher.Plugin.Program
|
|||
/// </summary>
|
||||
public partial class AddProgramSource : Window
|
||||
{
|
||||
private PluginInitContext _context;
|
||||
private ProgramSource _editing;
|
||||
private Settings _settings;
|
||||
private bool update;
|
||||
private readonly AddProgramSourceViewModel ViewModel;
|
||||
|
||||
public AddProgramSource(PluginInitContext context, Settings settings)
|
||||
public AddProgramSource(AddProgramSourceViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = viewModel;
|
||||
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)
|
||||
{
|
||||
var dialog = new FolderBrowserDialog();
|
||||
DialogResult result = dialog.ShowDialog();
|
||||
if (result == System.Windows.Forms.DialogResult.OK)
|
||||
{
|
||||
Directory.Text = dialog.SelectedPath;
|
||||
}
|
||||
ViewModel.Browse();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
string path = Directory.Text;
|
||||
bool modified = false;
|
||||
if (!System.IO.Directory.Exists(path))
|
||||
var (modified, msg) = ViewModel.AddOrUpdate();
|
||||
if (modified == false && msg != null)
|
||||
{
|
||||
System.Windows.MessageBox.Show(_context.API.GetTranslation("flowlauncher_plugin_program_invalid_path"));
|
||||
MessageBox.Show(msg); // Invalid
|
||||
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;
|
||||
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()
|
||||
{
|
||||
return HashCode.Combine(UniqueIdentifier);
|
||||
return uniqueIdentifier.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
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"
|
||||
xmlns:program="clr-namespace:Flow.Launcher.Plugin.Program"
|
||||
Height="520"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
mc:Ignorable="d">
|
||||
|
|
@ -180,7 +179,7 @@
|
|||
<GridViewColumn Header="{DynamicResource flowlauncher_plugin_program_location}">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Location, ConverterParameter=(null), Converter={program:LocationConverter}}" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Text="{Binding Location}" TextTrimming="CharacterEllipsis" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using Flow.Launcher.Plugin.Program.Views.Commands;
|
|||
using Flow.Launcher.Plugin.Program.Programs;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Data;
|
||||
using System;
|
||||
using Flow.Launcher.Plugin.Program.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program.Views
|
||||
{
|
||||
|
|
@ -136,7 +136,8 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
|
||||
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)
|
||||
{
|
||||
ReIndexing();
|
||||
|
|
@ -171,7 +172,12 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
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 (selectedProgramSource.Enabled)
|
||||
|
|
@ -186,6 +192,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
ReIndexing();
|
||||
}
|
||||
programSourceView.SelectedIndex = selectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue