diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 5836eaeeb..c2ed4975b 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -54,7 +54,7 @@ Margin="0 0 22 0" VerticalAlignment="Center" Command="{Binding EditPluginPriorityCommand}" - Content="{Binding Priority, UpdateSourceTrigger=PropertyChanged}" + Content="{Binding Priority}" Cursor="Hand" ToolTip="{DynamicResource priorityToolTip}"> diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 0fa147075..dd9e5786d 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; @@ -11,7 +10,7 @@ using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.ViewModels; -public partial class SettingsPanePluginsViewModel : BaseModel +public class SettingsPanePluginsViewModel : BaseModel { private readonly Settings _settings; @@ -23,12 +22,18 @@ public partial class SettingsPanePluginsViewModel : BaseModel public string FilterText { get; set; } = string.Empty; public PluginViewModel? SelectedPlugin { get; set; } + private IEnumerable? _pluginViewModels; private IEnumerable PluginViewModels => _pluginViewModels ??= PluginManager.AllPlugins - .OrderBy(x => x.Metadata.Disabled) - .ThenBy(y => y.Metadata.Name) - .Select(p => new PluginViewModel { PluginPair = p }) + .OrderBy(plugin => plugin.Metadata.Disabled) + .ThenBy(plugin => plugin.Metadata.Name) + .Select(plugin => new PluginViewModel + { + PluginPair = plugin, + PluginSettingsObject = _settings.PluginSettings.Plugins[plugin.Metadata.ID] + }) .ToList(); + public List FilteredPluginViewModels => PluginViewModels .Where(v => string.IsNullOrEmpty(FilterText) || @@ -36,13 +41,4 @@ public partial class SettingsPanePluginsViewModel : BaseModel StringMatcher.FuzzySearch(FilterText, v.PluginPair.Metadata.Description).IsSearchPrecisionScoreMet() ) .ToList(); - - [RelayCommand] - private void TogglePlugin() - { - if (SelectedPlugin is null) return; - var id = SelectedPlugin.PluginPair.Metadata.ID; - // used to sync the current status from the plugin manager into the setting to keep consistency after save - _settings.PluginSettings.Plugins[id].Disabled = SelectedPlugin.PluginPair.Metadata.Disabled; - } } diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 0ea3eb213..98b3c12a2 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -1,541 +1,172 @@ -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Helper; -using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Hotkey; -using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; -using Flow.Launcher.ViewModel; -using ModernWpf; -using ModernWpf.Controls; -using System; -using System.ComponentModel; -using System.IO; +using System; using System.Windows; -using System.Windows.Data; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Interop; -using System.Windows.Navigation; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; -using NHotkey; -using Button = System.Windows.Controls.Button; -using Control = System.Windows.Controls.Control; -using KeyEventArgs = System.Windows.Input.KeyEventArgs; -using MessageBox = System.Windows.MessageBox; -using TextBox = System.Windows.Controls.TextBox; -using ThemeManager = ModernWpf.ThemeManager; +using Flow.Launcher.Helper; +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; using Flow.Launcher.SettingPages.Views; +using Flow.Launcher.ViewModel; +using ModernWpf.Controls; +using TextBox = System.Windows.Controls.TextBox; -namespace Flow.Launcher +namespace Flow.Launcher; + +public partial class SettingWindow { - public partial class SettingWindow + private readonly IPublicAPI _api; + private readonly Settings _settings; + private readonly SettingWindowViewModel _viewModel; + + public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) { - public readonly IPublicAPI API; - private Settings settings; - private SettingWindowViewModel viewModel; - - public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) - { - settings = viewModel.Settings; - DataContext = viewModel; - this.viewModel = viewModel; - API = api; - InitializePosition(); - InitializeComponent(); - NavView.SelectedItem = NavView.MenuItems[0]; /* Set First Page */ - } - - #region General - - private void OnLoaded(object sender, RoutedEventArgs e) - { - RefreshMaximizeRestoreButton(); - // Fix (workaround) for the window freezes after lock screen (Win+L) - // https://stackoverflow.com/questions/4951058/software-rendering-mode-wpf - HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; - HwndTarget hwndTarget = hwndSource.CompositionTarget; - hwndTarget.RenderMode = RenderMode.Default; - - //pluginListView = (CollectionView)CollectionViewSource.GetDefaultView(Plugins.ItemsSource); - //pluginListView.Filter = PluginListFilter; - - //pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); - //pluginStoreView.Filter = PluginStoreFilter; - - //viewModel.PropertyChanged += new PropertyChangedEventHandler(SettingsWindowViewModelChanged); - - InitializePosition(); - } - - //private void SettingsWindowViewModelChanged(object sender, PropertyChangedEventArgs e) - //{ - // if (e.PropertyName == nameof(viewModel.ExternalPlugins)) - // { - // pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); - // pluginStoreView.Filter = PluginStoreFilter; - // pluginStoreView.Refresh(); - // } - //} - - private void OnSelectPythonPathClick(object sender, RoutedEventArgs e) - { - var selectedFile = viewModel.GetFileFromDialog( - InternationalizationManager.Instance.GetTranslation("selectPythonExecutable"), - "Python|pythonw.exe"); - - if (!string.IsNullOrEmpty(selectedFile)) - settings.PluginSettings.PythonExecutablePath = selectedFile; - } - - private void OnSelectNodePathClick(object sender, RoutedEventArgs e) - { - var selectedFile = viewModel.GetFileFromDialog( - InternationalizationManager.Instance.GetTranslation("selectNodeExecutable")); - - if (!string.IsNullOrEmpty(selectedFile)) - settings.PluginSettings.NodeExecutablePath = selectedFile; - } - - private void OnSelectFileManagerClick(object sender, RoutedEventArgs e) - { - SelectFileManagerWindow fileManagerChangeWindow = new SelectFileManagerWindow(settings); - fileManagerChangeWindow.ShowDialog(); - } - - private void OnSelectDefaultBrowserClick(object sender, RoutedEventArgs e) - { - var browserWindow = new SelectBrowserWindow(settings); - browserWindow.ShowDialog(); - } - - #endregion - - #region Hotkey - - private void OnToggleHotkey(object sender, HotkeyEventArgs e) - { - HotKeyMapper.OnToggleHotkey(sender, e); - } - - private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e) - { - var item = viewModel.SelectedCustomPluginHotkey; - if (item == null) - { - MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); - return; - } - - string deleteWarning = - string.Format(InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), - item.Hotkey); - if ( - MessageBox.Show(deleteWarning, InternationalizationManager.Instance.GetTranslation("delete"), - MessageBoxButton.YesNo) == MessageBoxResult.Yes) - { - settings.CustomPluginHotkeys.Remove(item); - HotKeyMapper.RemoveHotkey(item.Hotkey); - } - } - - private void OnEditCustomHotkeyClick(object sender, RoutedEventArgs e) - { - var item = viewModel.SelectedCustomPluginHotkey; - if (item != null) - { - CustomQueryHotkeySetting window = new CustomQueryHotkeySetting(this, settings); - window.UpdateItem(item); - window.ShowDialog(); - } - else - { - MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); - } - } - - private void OnAddCustomHotkeyClick(object sender, RoutedEventArgs e) - { - new CustomQueryHotkeySetting(this, settings).ShowDialog(); - } - - #endregion - - #region Plugin - - private void OnPluginToggled(object sender, RoutedEventArgs e) - { - var id = viewModel.SelectedPlugin.PluginPair.Metadata.ID; - // used to sync the current status from the plugin manager into the setting to keep consistency after save - settings.PluginSettings.Plugins[id].Disabled = viewModel.SelectedPlugin.PluginPair.Metadata.Disabled; - } - - private void OnPluginPriorityClick(object sender, RoutedEventArgs e) - { - if (sender is Control { DataContext: PluginViewModel pluginViewModel }) - { - PriorityChangeWindow priorityChangeWindow = new PriorityChangeWindow(pluginViewModel.PluginPair.Metadata.ID, pluginViewModel); - priorityChangeWindow.ShowDialog(); - } - } - - #endregion - - #region Proxy - - private void OnTestProxyClick(object sender, RoutedEventArgs e) - { // TODO: change to command - var msg = viewModel.TestProxy(); - MessageBox.Show(msg); // TODO: add message box service - } - - #endregion - - private void OnCheckUpdates(object sender, RoutedEventArgs e) - { - viewModel.UpdateApp(); // TODO: change to command - } - - private void OnRequestNavigate(object sender, RequestNavigateEventArgs e) - { - API.OpenUrl(e.Uri.AbsoluteUri); - e.Handled = true; - } - - private void OnClosed(object sender, EventArgs e) - { - settings.SettingWindowState = WindowState; - settings.SettingWindowTop = Top; - settings.SettingWindowLeft = Left; - viewModel.Save(); - API.SavePluginSettings(); - } - - private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e) - { - Close(); - } - - private void OpenThemeFolder(object sender, RoutedEventArgs e) - { - PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Themes)); - } - - private void OpenSettingFolder(object sender, RoutedEventArgs e) - { - PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Settings)); - } - - private void OpenWelcomeWindow(object sender, RoutedEventArgs e) - { - var WelcomeWindow = new WelcomeWindow(settings); - WelcomeWindow.ShowDialog(); - } - private void OpenLogFolder(object sender, RoutedEventArgs e) - { - viewModel.OpenLogFolder(); - } - private void ClearLogFolder(object sender, RoutedEventArgs e) - { - var confirmResult = MessageBox.Show( - InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), - InternationalizationManager.Instance.GetTranslation("clearlogfolder"), - MessageBoxButton.YesNo); - - if (confirmResult == MessageBoxResult.Yes) - { - viewModel.ClearLogFolder(); - } - } - - private void OnExternalPluginInstallClick(object sender, RoutedEventArgs e) - { - if (sender is not Button { DataContext: PluginStoreItemViewModel plugin } button) - { - 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) - { - if (e.ChangedButton == MouseButton.Left) - { - var name = viewModel.SelectedPlugin.PluginPair.Metadata.Name; - viewModel.DisplayPluginQuery($"uninstall {name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); - } - } - - private void OnExternalPluginUninstallClick(object sender, RoutedEventArgs e) - { - if (storeClickedButton != null) - { - FlyoutService.GetFlyout(storeClickedButton).Hide(); - } - - if (sender is Button { DataContext: PluginStoreItemViewModel plugin }) - viewModel.DisplayPluginQuery($"uninstall {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); - - } - - private void OnExternalPluginUpdateClick(object sender, RoutedEventArgs e) - { - if (storeClickedButton != null) - { - FlyoutService.GetFlyout(storeClickedButton).Hide(); - } - if (sender is Button { DataContext: PluginStoreItemViewModel plugin }) - viewModel.DisplayPluginQuery($"update {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7")); - - } - - private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ - { - if (Keyboard.FocusedElement is not TextBox textBox) - { - return; - } - var tRequest = new TraversalRequest(FocusNavigationDirection.Next); - textBox.MoveFocus(tRequest); - } - - private void ColorSchemeSelectedIndexChanged(object sender, EventArgs e) - => ThemeManager.Current.ApplicationTheme = settings.ColorScheme switch - { - Constant.Light => ApplicationTheme.Light, - Constant.Dark => ApplicationTheme.Dark, - Constant.System => null, - _ => ThemeManager.Current.ApplicationTheme - }; - - /* Custom TitleBar */ - - private void OnMinimizeButtonClick(object sender, RoutedEventArgs e) - { - WindowState = WindowState.Minimized; - } - - private void OnMaximizeRestoreButtonClick(object sender, RoutedEventArgs e) - { - WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; - } - - private void OnCloseButtonClick(object sender, RoutedEventArgs e) - { - - Close(); - } - - private void RefreshMaximizeRestoreButton() - { - if (WindowState == WindowState.Maximized) - { - MaximizeButton.Visibility = Visibility.Collapsed; - RestoreButton.Visibility = Visibility.Visible; - } - else - { - MaximizeButton.Visibility = Visibility.Visible; - RestoreButton.Visibility = Visibility.Collapsed; - } - } - - private void Window_StateChanged(object sender, EventArgs e) - { - RefreshMaximizeRestoreButton(); - } - - #region Shortcut - - private void OnDeleteCustomShortCutClick(object sender, RoutedEventArgs e) - { - viewModel.DeleteSelectedCustomShortcut(); - } - - private void OnEditCustomShortCutClick(object sender, RoutedEventArgs e) - { - if (viewModel.EditSelectedCustomShortcut()) - { - //customShortcutView.Items.Refresh(); Should Fix - } - } - - private void OnAddCustomShortCutClick(object sender, RoutedEventArgs e) - { - viewModel.AddCustomShortcut(); - } - - #endregion - - private CollectionView pluginListView; - private CollectionView pluginStoreView; - - //private bool PluginListFilter(object item) - //{ - // if (string.IsNullOrEmpty(pluginFilterTxb.Text)) - // return true; - // if (item is PluginViewModel model) - // { - // return StringMatcher.FuzzySearch(pluginFilterTxb.Text, model.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet(); - // } - // return false; - //} - - //private bool PluginStoreFilter(object item) - //{ - // if (string.IsNullOrEmpty(pluginStoreFilterTxb.Text)) - // return true; - // if (item is PluginStoreItemViewModel model) - // { - // return StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Name).IsSearchPrecisionScoreMet() - // || StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Description).IsSearchPrecisionScoreMet(); - // } - // return false; - //} - - private string lastPluginListSearch = ""; - private string lastPluginStoreSearch = ""; - - //private void RefreshPluginListEventHandler(object sender, RoutedEventArgs e) - //{ - // if (pluginFilterTxb.Text != lastPluginListSearch) - // { - // lastPluginListSearch = pluginFilterTxb.Text; - // pluginListView.Refresh(); - // } - //} - - //private void RefreshPluginStoreEventHandler(object sender, RoutedEventArgs e) - //{ - // if (pluginStoreFilterTxb.Text != lastPluginStoreSearch) - // { - // lastPluginStoreSearch = pluginStoreFilterTxb.Text; - // pluginStoreView.Refresh(); - // } - //} - - //private void PluginFilterTxb_OnKeyDown(object sender, KeyEventArgs e) - //{ - // if (e.Key == Key.Enter) - // RefreshPluginListEventHandler(sender, e); - //} - - //private void PluginStoreFilterTxb_OnKeyDown(object sender, KeyEventArgs e) - //{ - // if (e.Key == Key.Enter) - // RefreshPluginStoreEventHandler(sender, e); - //} - - //private void OnPluginSettingKeydown(object sender, KeyEventArgs e) - //{ - // if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && e.Key == Key.F) - // pluginFilterTxb.Focus(); - //} - - //private void PluginStore_OnKeyDown(object sender, KeyEventArgs e) - //{ - // if (e.Key == Key.F && (Keyboard.Modifiers & ModifierKeys.Control) != 0) - // { - // pluginStoreFilterTxb.Focus(); - // } - //} - - public void InitializePosition() - { - if (settings.SettingWindowTop >= 0 && settings.SettingWindowLeft >= 0) - { - Top = settings.SettingWindowTop; - Left = settings.SettingWindowLeft; - } - else - { - Top = WindowTop(); - Left = WindowLeft(); - } - WindowState = settings.SettingWindowState; - } - - public double WindowLeft() - { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); - var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); - var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); - var left = (dip2.X - this.ActualWidth) / 2 + dip1.X; - return left; - } - - public double WindowTop() - { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); - var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); - var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); - var top = (dip2.Y - this.ActualHeight) / 2 + dip1.Y - 20; - 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; - }; - - } - - //private void PluginStore_GotFocus(object sender, RoutedEventArgs e) - //{ - // Keyboard.Focus(pluginStoreFilterTxb); - //} - - //private void Plugin_GotFocus(object sender, RoutedEventArgs e) - //{ - // Keyboard.Focus(pluginFilterTxb); - //} - - /** For Navigation View **/ - private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) - { - if (args.IsSettingsSelected) - { - ContentFrame.Navigate(typeof(SettingsPaneGeneral)); - } - else - { - var selectedItem = (NavigationViewItem)args.SelectedItem; - if (selectedItem == null) - { - return; - } - - var pageType = selectedItem.Name switch - { - nameof(General) => typeof(SettingsPaneGeneral), - nameof(Plugins) => typeof(SettingsPanePlugins), - nameof(PluginStore) => typeof(SettingsPanePluginStore), - nameof(Theme) => typeof(SettingsPaneTheme), - nameof(Hotkey) => typeof(SettingsPaneHotkey), - nameof(Proxy) => typeof(SettingsPaneProxy), - nameof(About) => typeof(SettingsPaneAbout), - _ => typeof(SettingsPaneGeneral) - }; - ContentFrame.Navigate(pageType, new PaneData(settings, viewModel.Updater, viewModel.Portable)); - } - } - public record PaneData(Settings Settings, Updater Updater, IPortable Portable); + _settings = viewModel.Settings; + DataContext = viewModel; + _viewModel = viewModel; + _api = api; + InitializePosition(); + InitializeComponent(); + NavView.SelectedItem = NavView.MenuItems[0]; /* Set First Page */ } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + RefreshMaximizeRestoreButton(); + // Fix (workaround) for the window freezes after lock screen (Win+L) + // https://stackoverflow.com/questions/4951058/software-rendering-mode-wpf + HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; + HwndTarget hwndTarget = hwndSource.CompositionTarget; + hwndTarget.RenderMode = RenderMode.Default; + + InitializePosition(); + } + + private void OnClosed(object sender, EventArgs e) + { + _settings.SettingWindowState = WindowState; + _settings.SettingWindowTop = Top; + _settings.SettingWindowLeft = Left; + _viewModel.Save(); + _api.SavePluginSettings(); + } + + private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e) + { + Close(); + } + + private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ + { + if (Keyboard.FocusedElement is not TextBox textBox) + { + return; + } + var tRequest = new TraversalRequest(FocusNavigationDirection.Next); + textBox.MoveFocus(tRequest); + } + + /* Custom TitleBar */ + + private void OnMinimizeButtonClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState.Minimized; + } + + private void OnMaximizeRestoreButtonClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState switch + { + WindowState.Maximized => WindowState.Normal, + _ => WindowState.Maximized + }; + } + + private void OnCloseButtonClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private void RefreshMaximizeRestoreButton() + { + if (WindowState == WindowState.Maximized) + { + MaximizeButton.Visibility = Visibility.Collapsed; + RestoreButton.Visibility = Visibility.Visible; + } + else + { + MaximizeButton.Visibility = Visibility.Visible; + RestoreButton.Visibility = Visibility.Collapsed; + } + } + + private void Window_StateChanged(object sender, EventArgs e) + { + RefreshMaximizeRestoreButton(); + } + + private void InitializePosition() + { + if (_settings.SettingWindowTop >= 0 && _settings.SettingWindowLeft >= 0) + { + Top = _settings.SettingWindowTop; + Left = _settings.SettingWindowLeft; + } + else + { + Top = WindowTop(); + Left = WindowLeft(); + } + WindowState = _settings.SettingWindowState; + } + + private double WindowLeft() + { + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); + var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); + var left = (dip2.X - this.ActualWidth) / 2 + dip1.X; + return left; + } + + private double WindowTop() + { + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); + var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); + var top = (dip2.Y - this.ActualHeight) / 2 + dip1.Y - 20; + return top; + } + + private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) + { + var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable); + if (args.IsSettingsSelected) + { + ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData); + } + else + { + var selectedItem = (NavigationViewItem)args.SelectedItem; + if (selectedItem == null) return; + + var pageType = selectedItem.Name switch + { + nameof(General) => typeof(SettingsPaneGeneral), + nameof(Plugins) => typeof(SettingsPanePlugins), + nameof(PluginStore) => typeof(SettingsPanePluginStore), + nameof(Theme) => typeof(SettingsPaneTheme), + nameof(Hotkey) => typeof(SettingsPaneHotkey), + nameof(Proxy) => typeof(SettingsPaneProxy), + nameof(About) => typeof(SettingsPaneAbout), + _ => typeof(SettingsPaneGeneral) + }; + ContentFrame.Navigate(pageType, paneData); + } + } + + public record PaneData(Settings Settings, Updater Updater, IPortable Portable); } diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index f3d201f0b..b4daa8c7a 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -62,7 +62,11 @@ namespace Flow.Launcher.ViewModel public bool PluginState { get => !PluginPair.Metadata.Disabled; - set => PluginPair.Metadata.Disabled = !value; + set + { + PluginPair.Metadata.Disabled = !value; + PluginSettingsObject.Disabled = !value; + } } public bool IsExpanded { @@ -96,6 +100,7 @@ namespace Flow.Launcher.ViewModel public string InitAndQueryTime => InternationalizationManager.Instance.GetTranslation("plugin_init_time") + " " + PluginPair.Metadata.InitTime + "ms, " + InternationalizationManager.Instance.GetTranslation("plugin_query_time") + " " + PluginPair.Metadata.AvgQueryTime + "ms"; public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); public int Priority => PluginPair.Metadata.Priority; + public Infrastructure.UserSettings.Plugin PluginSettingsObject { get; set; } public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword) { @@ -106,6 +111,7 @@ namespace Flow.Launcher.ViewModel public void ChangePriority(int newPriority) { PluginPair.Metadata.Priority = newPriority; + PluginSettingsObject.Priority = newPriority; OnPropertyChanged(nameof(Priority)); } diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index aadd88287..481802045 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -1,850 +1,66 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using Flow.Launcher.Core; +using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; -using Flow.Launcher.Core.ExternalPlugins; -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Helper; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using Flow.Launcher.Plugin.SharedModels; -using System.Collections.ObjectModel; -using CommunityToolkit.Mvvm.Input; -using System.Globalization; -using System.Runtime.CompilerServices; -using Flow.Launcher.Infrastructure.Hotkey; -using ModernWpf.Media.Animation; -namespace Flow.Launcher.ViewModel +namespace Flow.Launcher.ViewModel; + +public class SettingWindowViewModel : BaseModel { - public partial class SettingWindowViewModel : BaseModel + private readonly FlowLauncherJsonStorage _storage; + + public Updater Updater { get; } + + public IPortable Portable { get; } + + public Settings Settings { get; } + + public SettingWindowViewModel(Updater updater, IPortable portable) { - private readonly Updater _updater; - private readonly IPortable _portable; - private readonly FlowLauncherJsonStorage _storage; - - public Updater Updater => _updater; - public IPortable Portable => _portable; - - /* For Navigation View */ - private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo() - { - Effect = SlideNavigationTransitionEffect.FromBottom - }; - - public SettingWindowViewModel(Updater updater, IPortable portable) - { - _updater = updater; - _portable = portable; - _storage = new FlowLauncherJsonStorage(); - Settings = _storage.Load(); - Settings.PropertyChanged += (s, e) => - { - switch (e.PropertyName) - { - case nameof(Settings.ActivateTimes): - OnPropertyChanged(nameof(ActivatedTimes)); - break; - case nameof(Settings.WindowSize): - OnPropertyChanged(nameof(WindowWidthSize)); - break; - case nameof(Settings.UseDate): - case nameof(Settings.DateFormat): - OnPropertyChanged(nameof(DateText)); - break; - case nameof(Settings.UseClock): - case nameof(Settings.TimeFormat): - OnPropertyChanged(nameof(ClockText)); - break; - case nameof(Settings.Language): - OnPropertyChanged(nameof(ClockText)); - OnPropertyChanged(nameof(DateText)); - OnPropertyChanged(nameof(AlwaysPreviewToolTip)); - break; - case nameof(Settings.PreviewHotkey): - OnPropertyChanged(nameof(AlwaysPreviewToolTip)); - break; - case nameof(Settings.SoundVolume): - OnPropertyChanged(nameof(SoundEffectVolume)); - break; - } - }; - } - - [RelayCommand] - public void SetTogglingHotkey(HotkeyModel hotkey) - { - HotKeyMapper.SetHotkey(hotkey, HotKeyMapper.OnToggleHotkey); - } - - public Settings Settings { get; set; } - - public async void UpdateApp() - { - await _updater.UpdateAppAsync(App.API, false); - } - - public bool AutoUpdates - { - get => Settings.AutoUpdates; - set - { - Settings.AutoUpdates = value; - - if (value) - { - UpdateApp(); - } - } - } - - public CultureInfo Culture => CultureInfo.DefaultThreadCurrentCulture; - private Internationalization _translater => InternationalizationManager.Instance; - public string AlwaysPreviewToolTip => - string.Format(_translater.GetTranslation("AlwaysPreviewToolTip"), Settings.PreviewHotkey); - - - - /// - /// Save Flow settings. Plugins settings are not included. - /// - public void Save() - { - foreach (var vm in PluginViewModels) - { - var id = vm.PluginPair.Metadata.ID; - - Settings.PluginSettings.Plugins[id].Disabled = vm.PluginPair.Metadata.Disabled; - Settings.PluginSettings.Plugins[id].Priority = vm.Priority; - } - - _storage.Save(); - } - - public string GetFileFromDialog(string title, string filter = "") - { - var dlg = new System.Windows.Forms.OpenFileDialog - { - InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), - Multiselect = false, - CheckFileExists = true, - CheckPathExists = true, - Title = title, - Filter = filter - }; - - var result = dlg.ShowDialog(); - if (result == System.Windows.Forms.DialogResult.OK) - { - return dlg.FileName; - } - else - { - return string.Empty; - } - } - - - public string TestProxy() - { - var proxyServer = Settings.Proxy.Server; - var proxyUserName = Settings.Proxy.UserName; - if (string.IsNullOrEmpty(proxyServer)) - { - return InternationalizationManager.Instance.GetTranslation("serverCantBeEmpty"); - } - - if (Settings.Proxy.Port <= 0) - { - return InternationalizationManager.Instance.GetTranslation("portCantBeEmpty"); - } - - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_updater.GitHubRepository); - - if (string.IsNullOrEmpty(proxyUserName) || string.IsNullOrEmpty(Settings.Proxy.Password)) - { - request.Proxy = new WebProxy(proxyServer, Settings.Proxy.Port); - } - else - { - request.Proxy = new WebProxy(proxyServer, Settings.Proxy.Port) - { - Credentials = new NetworkCredential(proxyUserName, Settings.Proxy.Password) - }; - } - - try - { - var response = (HttpWebResponse)request.GetResponse(); - if (response.StatusCode == HttpStatusCode.OK) - { - return InternationalizationManager.Instance.GetTranslation("proxyIsCorrect"); - } - else - { - return InternationalizationManager.Instance.GetTranslation("proxyConnectFailed"); - } - } - catch - { - return InternationalizationManager.Instance.GetTranslation("proxyConnectFailed"); - } - } - - #region plugin - - public static string Plugin => @"https://github.com/Flow-Launcher/Flow.Launcher.PluginsManifest"; - public PluginViewModel SelectedPlugin { get; set; } - - public IList PluginViewModels - { - get => PluginManager.AllPlugins - .OrderBy(x => x.Metadata.Disabled) - .ThenBy(y => y.Metadata.Name) - .Select(p => new PluginViewModel { PluginPair = p }) - .ToList(); - } - - public IList ExternalPlugins - { - get - { - return LabelMaker(PluginsManifest.UserPlugins); - } - } - - private IList LabelMaker(IList list) - { - return list.Select(p => new PluginStoreItemViewModel(p)) - .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease) - .ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated) - .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None) - .ThenByDescending(p => p.Category == PluginStoreItemViewModel.Installed) - .ToList(); - } - - public Control SettingProvider - { - get - { - var settingProvider = SelectedPlugin.PluginPair.Plugin as ISettingProvider; - if (settingProvider != null) - { - var control = settingProvider.CreateSettingPanel(); - control.HorizontalAlignment = HorizontalAlignment.Stretch; - control.VerticalAlignment = VerticalAlignment.Stretch; - return control; - } - else - { - return new Control(); - } - } - } - - [RelayCommand] - private async Task RefreshExternalPluginsAsync() - { - await PluginsManifest.UpdateManifestAsync(); - OnPropertyChanged(nameof(ExternalPlugins)); - } - - - internal void DisplayPluginQuery(string queryToDisplay, PluginPair plugin, int actionKeywordPosition = 0) - { - var actionKeyword = plugin.Metadata.ActionKeywords.Count == 0 - ? string.Empty - : plugin.Metadata.ActionKeywords[actionKeywordPosition]; - - App.API.ChangeQuery($"{actionKeyword} {queryToDisplay}"); - App.API.ShowMainWindow(); - } - - #endregion - - #region theme - - public static string Theme => @"https://flowlauncher.com/docs/#/how-to-create-a-theme"; - public static string ThemeGallery => @"https://github.com/Flow-Launcher/Flow.Launcher/discussions/1438"; - - public string SelectedTheme - { - get { return Settings.Theme; } - set - { - ThemeManager.Instance.ChangeTheme(value); - - if (ThemeManager.Instance.BlurEnabled && Settings.UseDropShadowEffect) - DropShadowEffect = false; - } - } - - public List Themes - => ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension).ToList(); - - public bool DropShadowEffect - { - get { return Settings.UseDropShadowEffect; } - set - { - if (ThemeManager.Instance.BlurEnabled && value) - { - MessageBox.Show(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); - return; - } - - if (value) - { - ThemeManager.Instance.AddDropShadowEffectToCurrentTheme(); - } - else - { - ThemeManager.Instance.RemoveDropShadowEffectFromCurrentTheme(); - } - - Settings.UseDropShadowEffect = value; - } - } - - public class ColorScheme - { - public string Display { get; set; } - public ColorSchemes Value { get; set; } - } - - public List ColorSchemes - { - get - { - List modes = new List(); - var enums = (ColorSchemes[])Enum.GetValues(typeof(ColorSchemes)); - foreach (var e in enums) - { - var key = $"ColorScheme{e}"; - var display = _translater.GetTranslation(key); - var m = new ColorScheme { Display = display, Value = e, }; - modes.Add(m); - } - - return modes; - } - } - - - public class SearchWindowAlign - { - public string Display { get; set; } - public SearchWindowAligns Value { get; set; } - } - - public List SearchWindowAligns - { - get - { - List modes = new List(); - var enums = (SearchWindowAligns[])Enum.GetValues(typeof(SearchWindowAligns)); - foreach (var e in enums) - { - var key = $"SearchWindowAlign{e}"; - var display = _translater.GetTranslation(key); - var m = new SearchWindowAlign { Display = display, Value = e, }; - modes.Add(m); - } - - return modes; - } - } - - public List ScreenNumbers - { - get - { - var screens = System.Windows.Forms.Screen.AllScreens; - var screenNumbers = new List(); - for (int i = 1; i <= screens.Length; i++) - { - screenNumbers.Add(i); - } - - return screenNumbers; - } - } - - public List TimeFormatList { get; } = new() - { - "h:mm", - "hh:mm", - "H:mm", - "HH:mm", - "tt h:mm", - "tt hh:mm", - "h:mm tt", - "hh:mm tt", - "hh:mm:ss tt", - "HH:mm:ss" - }; - - public List DateFormatList { get; } = new() - { - "MM'/'dd dddd", - "MM'/'dd ddd", - "MM'/'dd", - "MM'-'dd", - "MMMM', 'dd", - "dd'/'MM", - "dd'-'MM", - "ddd MM'/'dd", - "dddd MM'/'dd", - "dddd", - "ddd dd'/'MM", - "dddd dd'/'MM", - "dddd dd', 'MMMM", - "dd', 'MMMM" - }; - - public string TimeFormat - { - get => Settings.TimeFormat; - set => Settings.TimeFormat = value; - } - - public string DateFormat - { - get => Settings.DateFormat; - set => Settings.DateFormat = value; - } - - public string ClockText => DateTime.Now.ToString(TimeFormat, Culture); - - public string DateText => DateTime.Now.ToString(DateFormat, Culture); - - public double WindowWidthSize - { - get => Settings.WindowSize; - set => Settings.WindowSize = value; - } - - public bool UseGlyphIcons - { - get => Settings.UseGlyphIcons; - set => Settings.UseGlyphIcons = value; - } - - public bool UseAnimation - { - get => Settings.UseAnimation; - set => Settings.UseAnimation = value; - } - - public class AnimationSpeed - { - public string Display { get; set; } - public AnimationSpeeds Value { get; set; } - } - - public List AnimationSpeeds - { - get - { - List speeds = new List(); - var enums = (AnimationSpeeds[])Enum.GetValues(typeof(AnimationSpeeds)); - foreach (var e in enums) - { - var key = $"AnimationSpeed{e}"; - var display = _translater.GetTranslation(key); - var m = new AnimationSpeed { Display = display, Value = e, }; - speeds.Add(m); - } - - return speeds; - } - } - - public bool UseSound - { - get => Settings.UseSound; - set => Settings.UseSound = value; - } - - public double SoundEffectVolume - { - get => Settings.SoundVolume; - set => Settings.SoundVolume = value; - } - - public bool UseClock - { - get => Settings.UseClock; - set => Settings.UseClock = value; - } - - public bool UseDate - { - get => Settings.UseDate; - set => Settings.UseDate = value; - } - - public double SettingWindowWidth - { - get => Settings.SettingWindowWidth; - set => Settings.SettingWindowWidth = value; - } - - public double SettingWindowHeight - { - get => Settings.SettingWindowHeight; - set => Settings.SettingWindowHeight = value; - } - - public double SettingWindowTop - { - get => Settings.SettingWindowTop; - set => Settings.SettingWindowTop = value; - } - - public double SettingWindowLeft - { - get => Settings.SettingWindowLeft; - set => Settings.SettingWindowLeft = value; - } - - public Brush PreviewBackground - { - get - { - var wallpaper = WallpaperPathRetrieval.GetWallpaperPath(); - if (wallpaper != null && File.Exists(wallpaper)) - { - var memStream = new MemoryStream(File.ReadAllBytes(wallpaper)); - var bitmap = new BitmapImage(); - bitmap.BeginInit(); - bitmap.StreamSource = memStream; - bitmap.DecodePixelWidth = 800; - bitmap.DecodePixelHeight = 600; - bitmap.EndInit(); - var brush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; - return brush; - } - else - { - var wallpaperColor = WallpaperPathRetrieval.GetWallpaperColor(); - var brush = new SolidColorBrush(wallpaperColor); - return brush; - } - } - } - - public ResultsViewModel PreviewResults - { - get - { - var results = new List - { - new Result - { - Title = InternationalizationManager.Instance.GetTranslation("SampleTitleExplorer"), - SubTitle = - InternationalizationManager.Instance.GetTranslation("SampleSubTitleExplorer"), - IcoPath = - Path.Combine(Constant.ProgramDirectory, - @"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png") - }, - new Result - { - Title = InternationalizationManager.Instance.GetTranslation("SampleTitleWebSearch"), - SubTitle = - InternationalizationManager.Instance.GetTranslation("SampleSubTitleWebSearch"), - IcoPath = - Path.Combine(Constant.ProgramDirectory, - @"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png") - }, - new Result - { - Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProgram"), - SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProgram"), - IcoPath = - Path.Combine(Constant.ProgramDirectory, - @"Plugins\Flow.Launcher.Plugin.Program\Images\program.png") - }, - new Result - { - Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProcessKiller"), - SubTitle = - InternationalizationManager.Instance.GetTranslation("SampleSubTitleProcessKiller"), - IcoPath = Path.Combine(Constant.ProgramDirectory, - @"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png") - } - }; - var vm = new ResultsViewModel(Settings); - vm.AddResults(results, "PREVIEW"); - return vm; - } - } - - public FontFamily SelectedQueryBoxFont - { - get - { - if (Fonts.SystemFontFamilies.Count(o => - o.FamilyNames.Values != null && - o.FamilyNames.Values.Contains(Settings.QueryBoxFont)) > 0) - { - var font = new FontFamily(Settings.QueryBoxFont); - return font; - } - else - { - var font = new FontFamily("Segoe UI"); - return font; - } - } - set - { - Settings.QueryBoxFont = value.ToString(); - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public FamilyTypeface SelectedQueryBoxFontFaces - { - get - { - var typeface = SyntaxSugars.CallOrRescueDefault( - () => SelectedQueryBoxFont.ConvertFromInvariantStringsOrNormal( - Settings.QueryBoxFontStyle, - Settings.QueryBoxFontWeight, - Settings.QueryBoxFontStretch - )); - return typeface; - } - set - { - Settings.QueryBoxFontStretch = value.Stretch.ToString(); - Settings.QueryBoxFontWeight = value.Weight.ToString(); - Settings.QueryBoxFontStyle = value.Style.ToString(); - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public FontFamily SelectedResultFont - { - get - { - if (Fonts.SystemFontFamilies.Count(o => - o.FamilyNames.Values != null && - o.FamilyNames.Values.Contains(Settings.ResultFont)) > 0) - { - var font = new FontFamily(Settings.ResultFont); - return font; - } - else - { - var font = new FontFamily("Segoe UI"); - return font; - } - } - set - { - Settings.ResultFont = value.ToString(); - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public FamilyTypeface SelectedResultFontFaces - { - get - { - var typeface = SyntaxSugars.CallOrRescueDefault( - () => SelectedResultFont.ConvertFromInvariantStringsOrNormal( - Settings.ResultFontStyle, - Settings.ResultFontWeight, - Settings.ResultFontStretch - )); - return typeface; - } - set - { - Settings.ResultFontStretch = value.Stretch.ToString(); - Settings.ResultFontWeight = value.Weight.ToString(); - Settings.ResultFontStyle = value.Style.ToString(); - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ThemeImage => Constant.QueryTextBoxIconImagePath; - - #endregion - - #region hotkey - - public CustomPluginHotkey SelectedCustomPluginHotkey { get; set; } - - #endregion - - #region shortcut - - public ObservableCollection CustomShortcuts => Settings.CustomShortcuts; - - public ObservableCollection BuiltinShortcuts => Settings.BuiltinShortcuts; - - public CustomShortcutModel? SelectedCustomShortcut { get; set; } - - public void DeleteSelectedCustomShortcut() - { - var item = SelectedCustomShortcut; - if (item == null) - { - MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); - return; - } - - string deleteWarning = string.Format( - InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), - item.Key, item.Value); - if (MessageBox.Show(deleteWarning, InternationalizationManager.Instance.GetTranslation("delete"), - MessageBoxButton.YesNo) == MessageBoxResult.Yes) - { - Settings.CustomShortcuts.Remove(item); - } - } - - public bool EditSelectedCustomShortcut() - { - var item = SelectedCustomShortcut; - if (item == null) - { - MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); - return false; - } - - var shortcutSettingWindow = new CustomShortcutSetting(item.Key, item.Value, this); - if (shortcutSettingWindow.ShowDialog() == true) - { - // Fix un-selectable shortcut item after the first selection - // https://stackoverflow.com/questions/16789360/wpf-listbox-items-with-changing-hashcode - SelectedCustomShortcut = null; - item.Key = shortcutSettingWindow.Key; - item.Value = shortcutSettingWindow.Value; - SelectedCustomShortcut = item; - return true; - } - - return false; - } - - public void AddCustomShortcut() - { - var shortcutSettingWindow = new CustomShortcutSetting(this); - if (shortcutSettingWindow.ShowDialog() == true) - { - var shortcut = new CustomShortcutModel(shortcutSettingWindow.Key, shortcutSettingWindow.Value); - Settings.CustomShortcuts.Add(shortcut); - } - } - - public bool ShortcutExists(string key) - { - return Settings.CustomShortcuts.Any(x => x.Key == key) || Settings.BuiltinShortcuts.Any(x => x.Key == key); - } - - #endregion - - #region about - - public string Website => Constant.Website; - public string SponsorPage => Constant.SponsorPage; - public string ReleaseNotes => _updater.GitHubRepository + @"/releases/latest"; - public string Documentation => Constant.Documentation; - public string Docs => Constant.Docs; - public string Github => Constant.GitHub; - - public string Version - { - get - { - if (Constant.Version == "1.0.0") - { - return Constant.Dev; - } - else - { - return Constant.Version; - } - } - } - - public string ActivatedTimes => - string.Format(_translater.GetTranslation("about_activate_times"), Settings.ActivateTimes); - - public string CheckLogFolder - { - get - { - var logFiles = GetLogFiles(); - long size = logFiles.Sum(file => file.Length); - return string.Format("{0} ({1})", _translater.GetTranslation("clearlogfolder"), - BytesToReadableString(size)); - } - } - - private static DirectoryInfo GetLogDir(string version = "") - { - return new DirectoryInfo(Path.Combine(DataLocation.DataDirectory(), Constant.Logs, version)); - } - - private static List GetLogFiles(string version = "") - { - return GetLogDir(version).EnumerateFiles("*", SearchOption.AllDirectories).ToList(); - } - - internal void ClearLogFolder() - { - var logDirectory = GetLogDir(); - var logFiles = GetLogFiles(); - - logFiles.ForEach(f => f.Delete()); - - logDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) - .Where(dir => !Constant.Version.Equals(dir.Name)) - .ToList() - .ForEach(dir => dir.Delete()); - - OnPropertyChanged(nameof(CheckLogFolder)); - } - - internal void OpenLogFolder() - { - App.API.OpenDirectory(GetLogDir(Constant.Version).FullName); - } - - internal static string BytesToReadableString(long bytes) - { - const int scale = 1024; - string[] orders = new string[] { "GB", "MB", "KB", "B" }; - long max = (long)Math.Pow(scale, orders.Length - 1); - - foreach (string order in orders) - { - if (bytes > max) - return string.Format("{0:##.##} {1}", decimal.Divide(bytes, max), order); - - max /= scale; - } - - return "0 B"; - } - - #endregion + _storage = new FlowLauncherJsonStorage(); + + Updater = updater; + Portable = portable; + Settings = _storage.Load(); + } + + public async void UpdateApp() + { + await Updater.UpdateAppAsync(App.API, false); + } + + + + /// + /// Save Flow settings. Plugins settings are not included. + /// + public void Save() + { + _storage.Save(); + } + + public double SettingWindowWidth + { + get => Settings.SettingWindowWidth; + set => Settings.SettingWindowWidth = value; + } + + public double SettingWindowHeight + { + get => Settings.SettingWindowHeight; + set => Settings.SettingWindowHeight = value; + } + + public double SettingWindowTop + { + get => Settings.SettingWindowTop; + set => Settings.SettingWindowTop = value; + } + + public double SettingWindowLeft + { + get => Settings.SettingWindowLeft; + set => Settings.SettingWindowLeft = value; } }