Skip to content

Commit

Permalink
[AdvancedPaste] Paste as file and many other improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
drawbyperpetual committed Sep 18, 2024
1 parent 7dc0f7f commit b953218
Show file tree
Hide file tree
Showing 15 changed files with 563 additions and 412 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Threading.Tasks;
using AdvancedPaste.Helpers;
using AdvancedPaste.Models;
using AdvancedPaste.Services;
using AdvancedPaste.Settings;
using AdvancedPaste.ViewModels;
using ManagedCommon;
Expand Down Expand Up @@ -61,8 +62,10 @@ public App()

Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder().UseContentRoot(AppContext.BaseDirectory).ConfigureServices((context, services) =>
{
services.AddSingleton<OptionsViewModel>();
services.AddSingleton<IUserSettings, UserSettings>();
services.AddSingleton<AICompletionsHelper>();
services.AddSingleton<OptionsViewModel>();
services.AddSingleton<IPasteFormatExecutor, PasteFormatExecutor>();
}).Build();

viewModel = GetService<OptionsViewModel>();
Expand Down Expand Up @@ -112,7 +115,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)

private void ProcessNamedPipe(string pipeName)
{
void OnMessage(string message) => _dispatcherQueue.TryEnqueue(() => OnNamedPipeMessage(message));
void OnMessage(string message) => _dispatcherQueue.TryEnqueue(async () => await OnNamedPipeMessage(message));

Task.Run(async () =>
{
Expand All @@ -121,30 +124,30 @@ private void ProcessNamedPipe(string pipeName)
});
}

private void OnNamedPipeMessage(string message)
private async Task OnNamedPipeMessage(string message)
{
var messageParts = message.Split();
var messageType = messageParts.First();

if (messageType == PowerToys.Interop.Constants.AdvancedPasteShowUIMessage())
{
OnAdvancedPasteHotkey();
await ShowWindow();
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteMarkdownMessage())
{
OnAdvancedPasteMarkdownHotkey();
await viewModel.ExceutePasteFormatAsync(PasteFormats.Markdown, PasteActionSource.GlobalKeyboardShortcut);
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteJsonMessage())
{
OnAdvancedPasteJsonHotkey();
await viewModel.ExceutePasteFormatAsync(PasteFormats.Json, PasteActionSource.GlobalKeyboardShortcut);
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteAdditionalActionMessage())
{
OnAdvancedPasteAdditionalActionHotkey(messageParts);
await OnAdvancedPasteAdditionalActionHotkey(messageParts);
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteCustomActionMessage())
{
OnAdvancedPasteCustomActionHotkey(messageParts);
await OnAdvancedPasteCustomActionHotkey(messageParts);
}
}

Expand All @@ -153,24 +156,7 @@ private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledEx
Logger.LogError("Unhandled exception", e.Exception);
}

private void OnAdvancedPasteJsonHotkey()
{
viewModel.ReadClipboard();
viewModel.ToJsonFunction(true);
}

private void OnAdvancedPasteMarkdownHotkey()
{
viewModel.ReadClipboard();
viewModel.ToMarkdownFunction(true);
}

private void OnAdvancedPasteHotkey()
{
ShowWindow();
}

private void OnAdvancedPasteAdditionalActionHotkey(string[] messageParts)
private async Task OnAdvancedPasteAdditionalActionHotkey(string[] messageParts)
{
if (messageParts.Length != 2)
{
Expand All @@ -184,14 +170,13 @@ private void OnAdvancedPasteAdditionalActionHotkey(string[] messageParts)
}
else
{
ShowWindow();
viewModel.ReadClipboard();
viewModel.ExecuteAdditionalAction(pasteFormat);
await ShowWindow();
await viewModel.ExceutePasteFormatAsync(pasteFormat, PasteActionSource.GlobalKeyboardShortcut);
}
}
}

private void OnAdvancedPasteCustomActionHotkey(string[] messageParts)
private async Task OnAdvancedPasteCustomActionHotkey(string[] messageParts)
{
if (messageParts.Length != 2)
{
Expand All @@ -205,16 +190,15 @@ private void OnAdvancedPasteCustomActionHotkey(string[] messageParts)
}
else
{
ShowWindow();
viewModel.ReadClipboard();
viewModel.ExecuteCustomActionWithPaste(customActionId);
await ShowWindow();
await viewModel.ExecuteCustomAction(customActionId, PasteActionSource.GlobalKeyboardShortcut);
}
}
}

private void ShowWindow()
private async Task ShowWindow()
{
viewModel.OnShow();
await viewModel.OnShow();

if (window is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@
Background="Transparent"
Visibility="{x:Bind ViewModel.IsCustomAIEnabled, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
<ToolTipService.ToolTip>
<ToolTip Content="{x:Bind ViewModel.GeneralErrorText}" />
<ToolTip Content="{x:Bind ViewModel.AIDisabledErrorText}" />
</ToolTipService.ToolTip>
</Grid>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,20 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Net;
using System.Threading.Tasks;
using AdvancedPaste.Helpers;
using AdvancedPaste.Settings;
using AdvancedPaste.Models;
using AdvancedPaste.ViewModels;
using CommunityToolkit.Mvvm.Input;
using ManagedCommon;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace AdvancedPaste.Controls
{
public sealed partial class PromptBox : Microsoft.UI.Xaml.Controls.UserControl
{
// Minimum time to show spinner when generating custom format using forcePasteCustom
private static readonly TimeSpan MinTaskTime = TimeSpan.FromSeconds(2);

private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
private readonly IUserSettings _userSettings;

public OptionsViewModel ViewModel { get; private set; }

public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register(
Expand Down Expand Up @@ -53,63 +44,41 @@ public object Footer

public PromptBox()
{
this.InitializeComponent();

_userSettings = App.GetService<IUserSettings>();
InitializeComponent();

ViewModel = App.GetService<OptionsViewModel>();
ViewModel.CustomActionActivated += (_, e) => GenerateCustom(e.ForcePasteCustom);
ViewModel.PropertyChanged += ViewModel_PropertyChanged;
ViewModel.CustomActionActivated += ViewModel_CustomActionActivated;
}

private void Grid_Loaded(object sender, RoutedEventArgs e)
private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
InputTxtBox.Focus(FocusState.Programmatic);
if (e.PropertyName == nameof(ViewModel.Busy) || e.PropertyName == nameof(ViewModel.ApiErrorText))
{
var state = ViewModel.Busy ? "LoadingState" : string.IsNullOrEmpty(ViewModel.ApiErrorText) ? "DefaultState" : "ErrorState";
VisualStateManager.GoToState(this, state, true);
}
}

[RelayCommand]
private void GenerateCustom() => GenerateCustom(false);

private void GenerateCustom(bool forcePasteCustom)
private void ViewModel_CustomActionActivated(object sender, Models.CustomActionActivatedEventArgs e)
{
Logger.LogTrace();

VisualStateManager.GoToState(this, "LoadingState", true);
string inputInstructions = ViewModel.Query;
ViewModel.SaveQuery(inputInstructions);

var customFormatTask = ViewModel.GenerateCustomFunction(inputInstructions);
var delayTask = forcePasteCustom ? Task.Delay(MinTaskTime) : Task.CompletedTask;
Task.WhenAll(customFormatTask, delayTask)
.ContinueWith(
_ =>
{
_dispatcherQueue.TryEnqueue(() =>
{
ViewModel.CustomFormatResult = customFormatTask.Result;
if (ViewModel.ApiRequestStatus == (int)HttpStatusCode.OK)
{
VisualStateManager.GoToState(this, "DefaultState", true);
if (_userSettings.ShowCustomPreview && !forcePasteCustom)
{
PreviewGrid.Width = InputTxtBox.ActualWidth;
PreviewFlyout.ShowAt(InputTxtBox);
}
else
{
ViewModel.PasteCustom();
InputTxtBox.Text = string.Empty;
}
}
else
{
VisualStateManager.GoToState(this, "ErrorState", true);
}
});
},
TaskScheduler.Default);
if (!e.PasteResult)
{
PreviewGrid.Width = InputTxtBox.ActualWidth;
PreviewFlyout.ShowAt(InputTxtBox);
}
}

private void Grid_Loaded(object sender, RoutedEventArgs e)
{
InputTxtBox.Focus(FocusState.Programmatic);
}

[RelayCommand]
private async Task GenerateCustom() => await ViewModel.GenerateCustomFunction(PasteActionSource.PromptBox);

[RelayCommand]
private void Recall()
{
Expand All @@ -126,29 +95,24 @@ private void Recall()
ClipboardHelper.SetClipboardTextContent(lastQuery.ClipboardData);
}

private void InputTxtBox_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
private async void InputTxtBox_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && InputTxtBox.Text.Length > 0 && ViewModel.IsCustomAIEnabled)
{
GenerateCustom();
await GenerateCustom();
}
}

private void PreviewPasteBtn_Click(object sender, RoutedEventArgs e)
{
ViewModel.PasteCustom();
InputTxtBox.Text = string.Empty;
}

private void ThumbUpDown_Click(object sender, RoutedEventArgs e)
{
if (sender is Button btn)
if (sender is Button btn && bool.TryParse(btn.CommandParameter as string, out bool result))
{
bool result;
if (bool.TryParse(btn.CommandParameter as string, out result))
{
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteCustomFormatOutputThumbUpDownEvent(result));
}
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteCustomFormatOutputThumbUpDownEvent(result));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ private void ClipboardHistoryItemDeleteButton_Click(object sender, RoutedEventAr
}
}

private void ListView_Button_Click(object sender, RoutedEventArgs e)
private async void ListView_Button_Click(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: PasteFormat format })
{
ViewModel.ExecutePasteFormat(format);
await ViewModel.ExecutePasteFormatAsync(format, PasteActionSource.ContextMenu);
}
}

private void KeyboardAccelerator_Invoked(Microsoft.UI.Xaml.Input.KeyboardAccelerator sender, Microsoft.UI.Xaml.Input.KeyboardAcceleratorInvokedEventArgs args)
private async void KeyboardAccelerator_Invoked(Microsoft.UI.Xaml.Input.KeyboardAccelerator sender, Microsoft.UI.Xaml.Input.KeyboardAcceleratorInvokedEventArgs args)
{
if (GetMainWindow()?.Visible is false)
{
Expand Down Expand Up @@ -170,7 +170,7 @@ private void KeyboardAccelerator_Invoked(Microsoft.UI.Xaml.Input.KeyboardAcceler
case VirtualKey.Number7:
case VirtualKey.Number8:
case VirtualKey.Number9:
ViewModel.ExecutePasteFormat(sender.Key);
await ViewModel.ExecutePasteFormat(sender.Key);
break;

default:
Expand Down
Loading

1 comment on commit b953218

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@check-spelling-bot Report

🔴 Please review

See the 📜action log or 📝 job summary for details.

Unrecognized words (1)

Exceute

Previously acknowledged words that are now absent applayout appsfolder cswinrt systemsettings SYSTEMWOW USEPOSITION USESIZE 🫥
To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the [email protected]:microsoft/PowerToys.git repository
on the dev/ani/advanced-paste-additional-actions branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.22/apply.pl' |
perl - 'https://github.com/microsoft/PowerToys/actions/runs/10921927762/attempts/1'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (1897) from .github/actions/spell-check/expect.txt and unrecognized words (1)

Dictionary Entries Covers Uniquely
cspell:r/src/r.txt 543 1 1
cspell:cpp/src/people.txt 23 1
cspell:cpp/src/ecosystem.txt 51 1

Consider adding them (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

      with:
        extra_dictionaries:
          cspell:r/src/r.txt
          cspell:cpp/src/people.txt
          cspell:cpp/src/ecosystem.txt

To stop checking additional dictionaries, add (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

check_extra_dictionaries: ''
Warnings (1)

See the 📜action log or 📝 job summary for details.

ℹ️ Warnings Count
ℹ️ non-alpha-in-dictionary 1

See ℹ️ Event descriptions for more information.

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.