mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #3561 from onesounds/250520-FixFilesConfig
Improve File Manager Configuration Error Handling
This commit is contained in:
commit
ac614696b1
12 changed files with 337 additions and 136 deletions
|
|
@ -226,8 +226,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
|||
new()
|
||||
{
|
||||
Name = "Files",
|
||||
Path = "Files",
|
||||
DirectoryArgument = "-select \"%d\"",
|
||||
Path = "Files-Stable",
|
||||
DirectoryArgument = "\"%d\"",
|
||||
FileArgument = "-select \"%f\""
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,6 +98,10 @@ namespace Flow.Launcher
|
|||
.AddTransient<SettingsPanePluginStoreViewModel>()
|
||||
.AddTransient<SettingsPaneProxyViewModel>()
|
||||
.AddTransient<SettingsPaneThemeViewModel>()
|
||||
// Use transient instance for dialog view models because
|
||||
// settings will change and we need to recreate them
|
||||
.AddTransient<SelectBrowserViewModel>()
|
||||
.AddTransient<SelectFileManagerViewModel>()
|
||||
).Build();
|
||||
Ioc.Default.ConfigureServices(host.Services);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@
|
|||
|
||||
<!-- FileManager Setting Dialog -->
|
||||
<system:String x:Key="fileManagerWindow">Select File Manager</system:String>
|
||||
<system:String x:Key="fileManager_learnMore">Learn more</system:String>
|
||||
<system:String x:Key="fileManager_tips">Please specify the file location of the file manager you using and add arguments as required. The "%d" represents the directory path to open for, used by the Arg for Folder field and for commands opening specific directories. The "%f" represents the file path to open for, used by the Arg for File field and for commands opening specific files.</system:String>
|
||||
<system:String x:Key="fileManager_tips2">For example, if the file manager uses a command such as "totalcmd.exe /A c:\windows" to open the c:\windows directory, the File Manager Path will be totalcmd.exe, and the Arg For Folder will be /A "%d". Certain file managers like QTTabBar may just require a path to be supplied, in this instance use "%d" as the File Manager Path and leave the rest of the fileds blank.</system:String>
|
||||
<system:String x:Key="fileManager_name">File Manager</system:String>
|
||||
|
|
@ -373,6 +374,8 @@
|
|||
<system:String x:Key="fileManager_path">File Manager Path</system:String>
|
||||
<system:String x:Key="fileManager_directory_arg">Arg For Folder</system:String>
|
||||
<system:String x:Key="fileManager_file_arg">Arg For File</system:String>
|
||||
<system:String x:Key="fileManagerPathNotFound">The file manager '{0}' could not be located at '{1}'. Would you like to continue?</system:String>
|
||||
<system:String x:Key="fileManagerPathError">File Manager Path Error</system:String>
|
||||
|
||||
<!-- DefaultBrowser Setting Dialog -->
|
||||
<system:String x:Key="defaultBrowserTitle">Default Web Browser</system:String>
|
||||
|
|
@ -462,6 +465,14 @@
|
|||
<system:String x:Key="reportWindow_upload_log">1. Upload log file: {0}</system:String>
|
||||
<system:String x:Key="reportWindow_copy_below">2. Copy below exception message</system:String>
|
||||
|
||||
<!-- File Open Error -->
|
||||
<system:String x:Key="fileManagerNotFoundTitle">File Manager Error</system:String>
|
||||
<system:String x:Key="fileManagerNotFound">
|
||||
The specified file manager could not be found. Please check the Custom File Manager setting under Settings > General.
|
||||
</system:String>
|
||||
<system:String x:Key="errorTitle">Error</system:String>
|
||||
<system:String x:Key="folderOpenError">An error occurred while opening the folder. {0}</system:String>
|
||||
|
||||
<!-- General Notice -->
|
||||
<system:String x:Key="pleaseWait">Please wait...</system:String>
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@ namespace Flow.Launcher
|
|||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static MessageBoxResult Show(string messageBoxText)
|
||||
=> Show(messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.OK);
|
||||
|
||||
public static MessageBoxResult Show(
|
||||
string messageBoxText,
|
||||
string caption = "",
|
||||
|
|
|
|||
|
|
@ -32,11 +32,14 @@ using Flow.Launcher.ViewModel;
|
|||
using JetBrains.Annotations;
|
||||
using Squirrel;
|
||||
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
public class PublicAPIInstance : IPublicAPI, IRemovable
|
||||
{
|
||||
private static readonly string ClassName = nameof(PublicAPIInstance);
|
||||
|
||||
private readonly Settings _settings;
|
||||
private readonly MainViewModel _mainVM;
|
||||
|
||||
|
|
@ -316,40 +319,63 @@ namespace Flow.Launcher
|
|||
|
||||
public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null)
|
||||
{
|
||||
using var explorer = new Process();
|
||||
var explorerInfo = _settings.CustomExplorer;
|
||||
var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant();
|
||||
var targetPath = FileNameOrFilePath is null
|
||||
? DirectoryPath
|
||||
: Path.IsPathRooted(FileNameOrFilePath)
|
||||
? FileNameOrFilePath
|
||||
: Path.Combine(DirectoryPath, FileNameOrFilePath);
|
||||
try
|
||||
{
|
||||
using var explorer = new Process();
|
||||
var explorerInfo = _settings.CustomExplorer;
|
||||
var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant();
|
||||
var targetPath = FileNameOrFilePath is null
|
||||
? DirectoryPath
|
||||
: Path.IsPathRooted(FileNameOrFilePath)
|
||||
? FileNameOrFilePath
|
||||
: Path.Combine(DirectoryPath, FileNameOrFilePath);
|
||||
|
||||
if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer")
|
||||
{
|
||||
// Windows File Manager
|
||||
// We should ignore and pass only the path to Shell to prevent zombie explorer.exe processes
|
||||
explorer.StartInfo = new ProcessStartInfo
|
||||
if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer")
|
||||
{
|
||||
FileName = targetPath, // Not explorer, Only path.
|
||||
UseShellExecute = true // Must be true to open folder
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Custom File Manager
|
||||
explorer.StartInfo = new ProcessStartInfo
|
||||
// Windows File Manager
|
||||
explorer.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = targetPath,
|
||||
UseShellExecute = true
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = explorerInfo.Path.Replace("%d", DirectoryPath),
|
||||
UseShellExecute = true,
|
||||
Arguments = FileNameOrFilePath is null
|
||||
? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath)
|
||||
: explorerInfo.FileArgument
|
||||
.Replace("%d", DirectoryPath)
|
||||
.Replace("%f", targetPath)
|
||||
};
|
||||
// Custom File Manager
|
||||
explorer.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = explorerInfo.Path.Replace("%d", DirectoryPath),
|
||||
UseShellExecute = true,
|
||||
Arguments = FileNameOrFilePath is null
|
||||
? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath)
|
||||
: explorerInfo.FileArgument
|
||||
.Replace("%d", DirectoryPath)
|
||||
.Replace("%f", targetPath)
|
||||
};
|
||||
}
|
||||
|
||||
explorer.Start();
|
||||
}
|
||||
catch (Win32Exception ex) when (ex.NativeErrorCode == 2)
|
||||
{
|
||||
LogError(ClassName, "File Manager not found");
|
||||
ShowMsgBox(
|
||||
string.Format(GetTranslation("fileManagerNotFound"), ex.Message),
|
||||
GetTranslation("fileManagerNotFoundTitle"),
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ClassName, "Failed to open folder", ex);
|
||||
ShowMsgBox(
|
||||
string.Format(GetTranslation("folderOpenError"), ex.Message),
|
||||
GetTranslation("errorTitle"),
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
);
|
||||
}
|
||||
explorer.Start();
|
||||
}
|
||||
|
||||
private void OpenUri(Uri uri, bool? inPrivate = null)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@
|
|||
xmlns:local="clr-namespace:Flow.Launcher"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
|
||||
Title="{DynamicResource defaultBrowserTitle}"
|
||||
Width="550"
|
||||
d:DataContext="{d:DesignInstance vm:SelectBrowserViewModel}"
|
||||
Background="{DynamicResource PopuBGColor}"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
Foreground="{DynamicResource PopupTextColor}"
|
||||
ResizeMode="NoResize"
|
||||
SizeToContent="Height"
|
||||
|
|
@ -97,11 +98,11 @@
|
|||
</ComboBox>
|
||||
<Button
|
||||
Margin="10 0 0 0"
|
||||
Click="btnAdd_Click"
|
||||
Command="{Binding AddCommand}"
|
||||
Content="{DynamicResource add}" />
|
||||
<Button
|
||||
Margin="10 0 0 0"
|
||||
Click="btnDelete_Click"
|
||||
Command="{Binding DeleteCommand}"
|
||||
Content="{DynamicResource delete}"
|
||||
IsEnabled="{Binding CustomBrowser.Editable}" />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,18 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Flow.Launcher.ViewModel;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
[INotifyPropertyChanged]
|
||||
public partial class SelectBrowserWindow : Window
|
||||
{
|
||||
private readonly Settings _settings;
|
||||
private readonly SelectBrowserViewModel _viewModel;
|
||||
|
||||
private int selectedCustomBrowserIndex;
|
||||
|
||||
public int SelectedCustomBrowserIndex
|
||||
public SelectBrowserWindow()
|
||||
{
|
||||
get => selectedCustomBrowserIndex;
|
||||
set
|
||||
{
|
||||
selectedCustomBrowserIndex = value;
|
||||
OnPropertyChanged(nameof(CustomBrowser));
|
||||
}
|
||||
}
|
||||
public ObservableCollection<CustomBrowserViewModel> CustomBrowsers { get; set; }
|
||||
|
||||
public CustomBrowserViewModel CustomBrowser => CustomBrowsers[SelectedCustomBrowserIndex];
|
||||
public SelectBrowserWindow(Settings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
CustomBrowsers = new ObservableCollection<CustomBrowserViewModel>(_settings.CustomBrowserList.Select(x => x.Copy()));
|
||||
SelectedCustomBrowserIndex = _settings.CustomBrowserIndex;
|
||||
_viewModel = Ioc.Default.GetRequiredService<SelectBrowserViewModel>();
|
||||
DataContext = _viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
|
@ -41,33 +23,20 @@ namespace Flow.Launcher
|
|||
|
||||
private void btnDone_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_settings.CustomBrowserList = CustomBrowsers.ToList();
|
||||
_settings.CustomBrowserIndex = SelectedCustomBrowserIndex;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void btnAdd_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CustomBrowsers.Add(new()
|
||||
if (_viewModel.SaveSettings())
|
||||
{
|
||||
Name = "New Profile"
|
||||
});
|
||||
SelectedCustomBrowserIndex = CustomBrowsers.Count - 1;
|
||||
}
|
||||
|
||||
private void btnDelete_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CustomBrowsers.RemoveAt(SelectedCustomBrowserIndex--);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnBrowseFile_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
|
||||
var result = dlg.ShowDialog();
|
||||
if (result == true)
|
||||
var selectedFilePath = _viewModel.SelectFile();
|
||||
|
||||
if (!string.IsNullOrEmpty(selectedFilePath))
|
||||
{
|
||||
TextBox path = (TextBox)(((FrameworkElement)sender).Parent as FrameworkElement).FindName("PathTextBox");
|
||||
path.Text = dlg.FileName;
|
||||
var path = (TextBox)(((FrameworkElement)sender).Parent as FrameworkElement).FindName("PathTextBox");
|
||||
path.Text = selectedFilePath;
|
||||
path.Focus();
|
||||
((Button)sender).Focus();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@
|
|||
xmlns:local="clr-namespace:Flow.Launcher"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
|
||||
Title="{DynamicResource fileManagerWindow}"
|
||||
Width="600"
|
||||
d:DataContext="{d:DesignInstance vm:SelectFileManagerViewModel}"
|
||||
Background="{DynamicResource PopuBGColor}"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
Foreground="{DynamicResource PopupTextColor}"
|
||||
ResizeMode="NoResize"
|
||||
SizeToContent="Height"
|
||||
|
|
@ -73,9 +74,17 @@
|
|||
<TextBlock Margin="0 14 0 0" FontSize="14">
|
||||
<TextBlock Text="{DynamicResource fileManager_tips2}" TextWrapping="WrapWithOverflow" />
|
||||
</TextBlock>
|
||||
<TextBlock Margin="0 14 0 0" VerticalAlignment="Center">
|
||||
<Hyperlink NavigateUri="https://www.flowlauncher.com/docs/#/filemanager" RequestNavigate="Hyperlink_RequestNavigate">
|
||||
<TextBlock FontSize="14" Text="{DynamicResource fileManager_learnMore}" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="14 28 0 0" Orientation="Horizontal">
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Margin="0 20 0 20"
|
||||
Fill="{StaticResource SeparatorForeground}" />
|
||||
<StackPanel Margin="14 0 0 0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
|
|
@ -99,11 +108,11 @@
|
|||
</ComboBox>
|
||||
<Button
|
||||
Margin="10 0 0 0"
|
||||
Click="btnAdd_Click"
|
||||
Command="{Binding AddCommand}"
|
||||
Content="{DynamicResource add}" />
|
||||
<Button
|
||||
Margin="10 0 0 0"
|
||||
Click="btnDelete_Click"
|
||||
Command="{Binding DeleteCommand}"
|
||||
Content="{DynamicResource delete}"
|
||||
IsEnabled="{Binding CustomExplorer.Editable}" />
|
||||
|
||||
|
|
@ -111,7 +120,7 @@
|
|||
<Rectangle
|
||||
Height="1"
|
||||
Margin="0 20 0 12"
|
||||
Fill="{StaticResource Color03B}" />
|
||||
Fill="{StaticResource SeparatorForeground}" />
|
||||
<StackPanel
|
||||
Margin="0 0 0 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
|
|
|
|||
|
|
@ -1,38 +1,19 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using System.Windows.Navigation;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Flow.Launcher.ViewModel;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
[INotifyPropertyChanged]
|
||||
public partial class SelectFileManagerWindow : Window
|
||||
{
|
||||
private readonly Settings _settings;
|
||||
private readonly SelectFileManagerViewModel _viewModel;
|
||||
|
||||
private int selectedCustomExplorerIndex;
|
||||
|
||||
public int SelectedCustomExplorerIndex
|
||||
public SelectFileManagerWindow()
|
||||
{
|
||||
get => selectedCustomExplorerIndex;
|
||||
set
|
||||
{
|
||||
selectedCustomExplorerIndex = value;
|
||||
OnPropertyChanged(nameof(CustomExplorer));
|
||||
}
|
||||
}
|
||||
public ObservableCollection<CustomExplorerViewModel> CustomExplorers { get; set; }
|
||||
|
||||
public CustomExplorerViewModel CustomExplorer => CustomExplorers[SelectedCustomExplorerIndex];
|
||||
public SelectFileManagerWindow(Settings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
CustomExplorers = new ObservableCollection<CustomExplorerViewModel>(_settings.CustomExplorerList.Select(x => x.Copy()));
|
||||
SelectedCustomExplorerIndex = _settings.CustomExplorerIndex;
|
||||
_viewModel = Ioc.Default.GetRequiredService<SelectFileManagerViewModel>();
|
||||
DataContext = _viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
|
@ -43,33 +24,26 @@ namespace Flow.Launcher
|
|||
|
||||
private void btnDone_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_settings.CustomExplorerList = CustomExplorers.ToList();
|
||||
_settings.CustomExplorerIndex = SelectedCustomExplorerIndex;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void btnAdd_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CustomExplorers.Add(new()
|
||||
if (_viewModel.SaveSettings())
|
||||
{
|
||||
Name = "New Profile"
|
||||
});
|
||||
SelectedCustomExplorerIndex = CustomExplorers.Count - 1;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnDelete_Click(object sender, RoutedEventArgs e)
|
||||
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
CustomExplorers.RemoveAt(SelectedCustomExplorerIndex--);
|
||||
_viewModel.OpenUrl(e.Uri.AbsoluteUri);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void btnBrowseFile_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
|
||||
var result = dlg.ShowDialog();
|
||||
if (result == true)
|
||||
var selectedFilePath = _viewModel.SelectFile();
|
||||
|
||||
if (!string.IsNullOrEmpty(selectedFilePath))
|
||||
{
|
||||
TextBox path = (TextBox)(((FrameworkElement)sender).Parent as FrameworkElement).FindName("PathTextBox");
|
||||
path.Text = dlg.FileName;
|
||||
var path = (TextBox)(((FrameworkElement)sender).Parent as FrameworkElement).FindName("PathTextBox");
|
||||
path.Text = selectedFilePath;
|
||||
path.Focus();
|
||||
((Button)sender).Focus();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -335,14 +335,14 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
|
|||
[RelayCommand]
|
||||
private void SelectFileManager()
|
||||
{
|
||||
var fileManagerChangeWindow = new SelectFileManagerWindow(Settings);
|
||||
var fileManagerChangeWindow = new SelectFileManagerWindow();
|
||||
fileManagerChangeWindow.ShowDialog();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SelectBrowser()
|
||||
{
|
||||
var browserWindow = new SelectBrowserWindow(Settings);
|
||||
var browserWindow = new SelectBrowserWindow();
|
||||
browserWindow.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
74
Flow.Launcher/ViewModel/SelectBrowserViewModel.cs
Normal file
74
Flow.Launcher/ViewModel/SelectBrowserViewModel.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
|
||||
namespace Flow.Launcher.ViewModel;
|
||||
|
||||
public partial class SelectBrowserViewModel : BaseModel
|
||||
{
|
||||
private readonly Settings _settings;
|
||||
|
||||
private int selectedCustomBrowserIndex;
|
||||
|
||||
public int SelectedCustomBrowserIndex
|
||||
{
|
||||
get => selectedCustomBrowserIndex;
|
||||
set
|
||||
{
|
||||
selectedCustomBrowserIndex = value;
|
||||
OnPropertyChanged(nameof(CustomBrowser));
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<CustomBrowserViewModel> CustomBrowsers { get; }
|
||||
|
||||
public CustomBrowserViewModel CustomBrowser => CustomBrowsers[SelectedCustomBrowserIndex];
|
||||
|
||||
public SelectBrowserViewModel(Settings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
CustomBrowsers = new ObservableCollection<CustomBrowserViewModel>(_settings.CustomBrowserList.Select(x => x.Copy()));
|
||||
SelectedCustomBrowserIndex = _settings.CustomBrowserIndex;
|
||||
}
|
||||
|
||||
public bool SaveSettings()
|
||||
{
|
||||
_settings.CustomBrowserList = CustomBrowsers.ToList();
|
||||
_settings.CustomBrowserIndex = SelectedCustomBrowserIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal string SelectFile()
|
||||
{
|
||||
var dlg = new Microsoft.Win32.OpenFileDialog();
|
||||
var result = dlg.ShowDialog();
|
||||
if (result == true)
|
||||
return dlg.FileName;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Add()
|
||||
{
|
||||
CustomBrowsers.Add(new()
|
||||
{
|
||||
Name = "New Profile"
|
||||
});
|
||||
SelectedCustomBrowserIndex = CustomBrowsers.Count - 1;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Delete()
|
||||
{
|
||||
var currentIndex = SelectedCustomBrowserIndex;
|
||||
if (currentIndex >= 0 && currentIndex < CustomBrowsers.Count)
|
||||
{
|
||||
CustomBrowsers.RemoveAt(currentIndex);
|
||||
SelectedCustomBrowserIndex = currentIndex > 0 ? currentIndex - 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs
Normal file
136
Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
|
||||
namespace Flow.Launcher.ViewModel;
|
||||
|
||||
public partial class SelectFileManagerViewModel : BaseModel
|
||||
{
|
||||
private readonly Settings _settings;
|
||||
|
||||
private int selectedCustomExplorerIndex;
|
||||
|
||||
public int SelectedCustomExplorerIndex
|
||||
{
|
||||
get => selectedCustomExplorerIndex;
|
||||
set
|
||||
{
|
||||
if (selectedCustomExplorerIndex != value)
|
||||
{
|
||||
selectedCustomExplorerIndex = value;
|
||||
OnPropertyChanged(nameof(CustomExplorer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<CustomExplorerViewModel> CustomExplorers { get; }
|
||||
|
||||
public CustomExplorerViewModel CustomExplorer => CustomExplorers[SelectedCustomExplorerIndex];
|
||||
|
||||
public SelectFileManagerViewModel(Settings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
CustomExplorers = new ObservableCollection<CustomExplorerViewModel>(_settings.CustomExplorerList.Select(x => x.Copy()));
|
||||
SelectedCustomExplorerIndex = _settings.CustomExplorerIndex;
|
||||
}
|
||||
|
||||
public bool SaveSettings()
|
||||
{
|
||||
// Check if the selected file manager path is valid
|
||||
if (!IsFileManagerValid(CustomExplorer.Path))
|
||||
{
|
||||
var result = App.API.ShowMsgBox(
|
||||
string.Format(App.API.GetTranslation("fileManagerPathNotFound"),
|
||||
CustomExplorer.Name, CustomExplorer.Path),
|
||||
App.API.GetTranslation("fileManagerPathError"),
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
if (result == MessageBoxResult.No)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_settings.CustomExplorerList = CustomExplorers.ToList();
|
||||
_settings.CustomExplorerIndex = SelectedCustomExplorerIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsFileManagerValid(string path)
|
||||
{
|
||||
if (string.Equals(path, "explorer", StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
if (Path.IsPathRooted(path))
|
||||
{
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "where",
|
||||
Arguments = path,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
process.Start();
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
return !string.IsNullOrEmpty(output);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal void OpenUrl(string absoluteUri)
|
||||
{
|
||||
App.API.OpenUrl(absoluteUri);
|
||||
}
|
||||
|
||||
internal string SelectFile()
|
||||
{
|
||||
var dlg = new Microsoft.Win32.OpenFileDialog();
|
||||
var result = dlg.ShowDialog();
|
||||
if (result == true)
|
||||
return dlg.FileName;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Add()
|
||||
{
|
||||
CustomExplorers.Add(new()
|
||||
{
|
||||
Name = "New Profile"
|
||||
});
|
||||
SelectedCustomExplorerIndex = CustomExplorers.Count - 1;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Delete()
|
||||
{
|
||||
var currentIndex = SelectedCustomExplorerIndex;
|
||||
if (currentIndex >= 0 && currentIndex < CustomExplorers.Count)
|
||||
{
|
||||
CustomExplorers.RemoveAt(currentIndex);
|
||||
SelectedCustomExplorerIndex = currentIndex > 0 ? currentIndex - 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue