Files
FluentTerminal/FluentTerminal.App/Dialogs/CustomCommandDialog.xaml.cs
T
2019-08-30 15:03:58 +02:00

227 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Storage.Pickers;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using FluentTerminal.App.Services;
using FluentTerminal.App.Services.Dialogs;
using FluentTerminal.App.Services.Utilities;
using FluentTerminal.App.Utilities;
using FluentTerminal.App.ViewModels.Profiles;
using FluentTerminal.Models;
using System.Linq;
using Windows.System;
using Windows.UI.Xaml.Input;
using FluentTerminal.App.ViewModels;
using FluentTerminal.App.ViewModels.Infrastructure;
// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace FluentTerminal.App.Dialogs
{
// ReSharper disable once RedundantExtendsListEntry
public sealed partial class CustomCommandDialog : ContentDialog, ICustomCommandDialog
{
private readonly ISettingsService _settingsService;
private readonly IApplicationView _applicationView;
private readonly ITrayProcessCommunicationService _trayProcessCommunicationService;
private readonly IApplicationDataContainer _historyContainer;
private ExecutedCommand _lastChosenCommand;
public CommandProfileProviderViewModel ViewModel { get; private set; }
public IAsyncCommand SaveLinkCommand { get; }
public CustomCommandDialog(ISettingsService settingsService, IApplicationView applicationView,
ITrayProcessCommunicationService trayProcessCommunicationService, ApplicationDataContainers containers)
{
_settingsService = settingsService;
_applicationView = applicationView;
_trayProcessCommunicationService = trayProcessCommunicationService;
_historyContainer = containers.HistoryContainer;
InitializeComponent();
SaveLinkCommand = new AsyncCommand(SaveLink);
PrimaryButtonText = I18N.Translate("OK");
SecondaryButtonText = I18N.Translate("Cancel");
var currentTheme = settingsService.GetCurrentTheme();
RequestedTheme = ContrastHelper.GetIdealThemeForBackgroundColor(currentTheme.Colors.Background);
}
private void SetupFocus()
{
CommandTextBox.Focus(FocusState.Programmatic);
}
private async void OnPrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
var deferral = args.GetDeferral();
var error = await ViewModel.AcceptChangesAsync();
if (!string.IsNullOrEmpty(error))
{
args.Cancel = true;
await new MessageDialog(error, I18N.Translate("InvalidInput")).ShowAsync();
SetupFocus();
}
deferral.Complete();
}
private async Task SaveLink()
{
var link = await ViewModel.GetUrlAsync();
if (!link.Item1)
{
await new MessageDialog(link.Item2, I18N.Translate("InvalidInput")).ShowAsync();
return;
}
var content = ProfileProviderViewModelBase.GetShortcutFileContent(link.Item2);
var savePicker = new FileSavePicker { SuggestedStartLocation = PickerLocationId.Desktop };
savePicker.FileTypeChoices.Add("Shortcut", new List<string> { ".url" });
var file = await savePicker.PickSaveFileAsync();
if (file == null)
{
return;
}
try
{
await _trayProcessCommunicationService.SaveTextFileAsync(file.Path, content);
}
catch (Exception ex)
{
await new MessageDialog(ex.Message, I18N.Translate("Error")).ShowAsync();
}
}
private void CommandTextBox_OnTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
ViewModel.SetFilter(sender.Text.Trim());
}
}
private void CommandTextBox_OnSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
{
_lastChosenCommand = (args.SelectedItem as CommandItemViewModel)?.ExecutedCommand;
}
private void CommandTextBox_OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
_lastChosenCommand = null;
if (args.ChosenSuggestion is CommandItemViewModel commandItem)
{
var executedCommand = ViewModel.Commands
.FirstOrDefault(c =>
c.ExecutedCommand.Value.Equals(commandItem.ExecutedCommand.Value.ToString(),
StringComparison.OrdinalIgnoreCase))?.ExecutedCommand;
if (executedCommand != null)
{
ViewModel.SetProfile(executedCommand.ShellProfile.Clone());
}
}
}
private void CommandTextBox_OnPreviewKeyUp(object sender, KeyRoutedEventArgs e)
{
var command = _lastChosenCommand;
if (e.Key == VirtualKey.Delete && !ViewModel.IsProfileCommand(command))
{
ViewModel.RemoveCommand(command);
e.Handled = true;
}
else
{
e.Handled = false;
}
}
private void CommandTextBox_OnKeyUp(object sender, KeyRoutedEventArgs e)
{
switch (e.Key)
{
case VirtualKey.Down:
case VirtualKey.Up:
if (!CommandTextBox.IsSuggestionListOpen)
{
CommandTextBox.IsSuggestionListOpen = true;
}
break;
case VirtualKey.Enter:
if (string.IsNullOrWhiteSpace(CommandTextBox.Text) && !CommandTextBox.IsSuggestionListOpen)
{
CommandTextBox.IsSuggestionListOpen = true;
}
else
{
// TODO: Try to find a better way to handle [Enter] on auto-complete field.
// Weird way to move the focus to the primary button...
if (!(FocusManager.FindLastFocusableElement(this) is Control secondaryButton) ||
!secondaryButton.Name.Equals("SecondaryButton"))
{
return;
}
secondaryButton.Focus(FocusState.Programmatic);
var options = new FindNextElementOptions
{
SearchRoot = this,
XYFocusNavigationStrategyOverride = XYFocusNavigationStrategyOverride.Projection
};
if (FocusManager.FindNextElement(FocusNavigationDirection.Left, options) is Control primaryButton)
{
primaryButton.Focus(FocusState.Programmatic);
}
}
break;
}
}
public async Task<ShellProfile> GetCustomCommandAsync(ShellProfile input = null)
{
ViewModel = new CommandProfileProviderViewModel(_settingsService, _applicationView,
_trayProcessCommunicationService, _historyContainer, input);
SetupFocus();
if (await ShowAsync() != ContentDialogResult.Primary)
{
return null;
}
ViewModel.Model.Tag = new DelayedHistorySaver(ViewModel);
return ViewModel.Model;
}
}
}