AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
24.13k stars 2.09k forks source link

Add HotKeys Page to DevTools #15700

Closed stevemonaco closed 2 weeks ago

stevemonaco commented 2 weeks ago

What does the pull request do?

Fixes #15390

Adds a HotKey page because there's no in-app discoverability of DevTools hotkeys. Otherwise, the user must check docs.

What is the updated/expected behavior with this PR?

devtools-hotkeys

Simple display of hotkeys, no mutability. Does not display the launch hotkey as that is mutable via DevToolOptions and would require some wiring. If the user doesn't know that hotkey, then how are they in DevTools to begin with?

Very recently, the "Styles" snapshot action was modified to "Value Frames". I reflect this in the hotkey descriptions, but other places still use Styles, including the DevTools docs page.

How was the solution implemented (if it's not obvious)?

Adds an invisible TabStripItem for the HotKeys page to avoid visual crowding and avoid adding more complex navigation.

Checklist

avaloniaui-bot commented 2 weeks ago

You can test this PR using the following package version. 11.2.999-cibuild0048354-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

avaloniaui-bot commented 2 weeks ago

You can test this PR using the following package version. 11.2.999-cibuild0048407-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

stevemonaco commented 2 weeks ago

0761e382ba36af98826f04f96767a9f33b3386fb introduces HotKeyConfiguration to hold KeyGestures as named members. It doesn't include DevToolsOptions.Gesture which launches DevTools as moving that is a breaking change.

I added HotKeyConfiguration to DevToolsOptions, use it to detect keypresses in MainView, moved the functionality into separate methods, and wire it into HotKeyPageViewModel. I can still list the launch DevTools gesture from there.

It's much closer to mutability, but kept it internal so any implementer could revise. This PR doesn't support multiple gestures that can each launch the same action. Chrome DevTools has this.

workgroupengineering commented 2 weeks ago

possible enhanced

public enum HotKeyFunction
{
    [Description("Launch DevTools")]
    LaunchDevTools,
    [Description("Inspect Control Under Pointer")]
    InspectHoveredControl,
    [Description("Freeze Value Frames")]
    FramesFreeze,
    [Description("Unfreeze Value Frames")]
    FramesUnfreeze,
    [Description("Toggle Popup Freeze")]
    TogglePopupFreeze,
    [Description("Screenshot Selected Control")]
    ScreenshotSelectedControl
}

public class DevToolsOptions
{
    private readonly static KeyGesture DefaultLaunchDevToolsGesture = new(Key.F12);
    private readonly Dictionary<HotKeyFunction, KeyGesture> _hotkeyConfig = new()
    {
        {HotKeyFunction.LaunchDevTools,new(Key.F12) },
        {HotKeyFunction.InspectHoveredControl,new(Key.None, KeyModifiers.Shift | KeyModifiers.Control) },
        {HotKeyFunction.FramesFreeze,new(Key.S, KeyModifiers.Alt) },
        {HotKeyFunction.FramesUnfreeze,new(Key.D, KeyModifiers.Alt) },
        {HotKeyFunction.TogglePopupFreeze,new(Key.F, KeyModifiers.Alt | KeyModifiers.Control) },
        {HotKeyFunction.ScreenshotSelectedControl,new(Key.F8) },
    };

    /// <summary>
    /// Gets or sets the key gesture used to open DevTools.
    /// </summary>
    public KeyGesture Gesture
    {
        get => _hotkeyConfig.TryGetValue(HotKeyFunction.LaunchDevTools, out var gesture)
            ? gesture
            : DefaultLaunchDevToolsGesture;
        init => _hotkeyConfig[HotKeyFunction.LaunchDevTools] = value;
    }

    public IReadOnlyDictionary<HotKeyFunction, KeyGesture> HotKeyConfig
    {
        get => _hotkeyConfig;
        init
        {
            // Merge
            foreach (var kvp in value)
            {
                _hotkeyConfig[kvp.Key] = kvp.Value;
            }
        }
    }
...

}

using like:

var options = new DevToolsOptions()
{
    HotKeyConfig = new Dictionary<HotKeyFunction, KeyGesture>
    {
        { HotKeyFunction.LaunchDevTools , new(Key.F24) },
        { HotKeyFunction.InspectHoveredControl, new(Key.None, KeyModifiers.Shift | KeyModifiers.Control) },
    },
};
maxkatz6 commented 2 weeks ago

We probably won't have this much of hotkeys to justify a dictionary. A class looks more than enough here. Either way, it can be changed later while it's internal.