From 132b81c729b4aecd0fd8f35189b80657c23aaebd Mon Sep 17 00:00:00 2001 From: robch-bot <175728472+Copilot@users.noreply.github.com> Date: Thu, 20 Feb 2025 22:13:53 +0000 Subject: [PATCH 1/2] Initial plan for issue From 4183193fa25cb45ab2fd467e3eab2ddbc12bb7c2 Mon Sep 17 00:00:00 2001 From: robch-bot <175728472+Copilot@users.noreply.github.com> Date: Thu, 20 Feb 2025 22:15:41 +0000 Subject: [PATCH 2/2] Implement keyboard and mouse input abilities --- src/Helpers/InteractiveHelpers.cs | 102 ++++++++++++++++++++++++++++++ src/Helpers/PlaywrightHelpers.cs | 27 ++++++-- src/assets/help/interactive.txt | 23 +++++++ 3 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/Helpers/InteractiveHelpers.cs create mode 100644 src/assets/help/interactive.txt diff --git a/src/Helpers/InteractiveHelpers.cs b/src/Helpers/InteractiveHelpers.cs new file mode 100644 index 0000000..6a7bae2 --- /dev/null +++ b/src/Helpers/InteractiveHelpers.cs @@ -0,0 +1,102 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Playwright; +using System.Collections.Generic; + +public static class InteractiveHelpers +{ + public static readonly Dictionary KeyboardShortcuts = new() + { + { "ESC", "Exit interactive mode" }, + { "n", "Go to next page" }, + { "p", "Go to previous page" }, + { "j", "Scroll down" }, + { "k", "Scroll up" }, + { "y", "Copy text under cursor to clipboard" }, + { "h", "Show this help" }, + { "q", "Close browser" } + }; + + public static void ShowKeyboardShortcuts() + { + Console.WriteLine("\nKeyboard shortcuts in interactive mode:"); + Console.WriteLine("------------------------------------"); + foreach (var (key, description) in KeyboardShortcuts) + { + Console.WriteLine($"{key,-4} : {description}"); + } + Console.WriteLine("\nMouse controls:"); + Console.WriteLine("- Click and drag to select text"); + Console.WriteLine("- Double click to select word"); + Console.WriteLine("- Triple click to select line"); + Console.WriteLine("\nPress any key to continue..."); + Console.ReadKey(true); + } + + public static async Task HandleKeyboardAndMouseEvents(IPage page) + { + // Monitor keyboard events + await page.Keyboard.DownAsync("Control"); + await page.Keyboard.PressAsync("Home"); // Scroll to top + await page.Keyboard.UpAsync("Control"); + + // Example keyboard shortcuts + ConsoleKeyInfo key; + bool exitRequested = false; + + while (!exitRequested) + { + if (Console.KeyAvailable) + { + key = Console.ReadKey(true); + switch (key.KeyChar) + { + case 'q': + exitRequested = true; + break; + case 'n': + await page.EvaluateAsync("window.scrollBy(0, window.innerHeight)"); + break; + case 'p': + await page.EvaluateAsync("window.scrollBy(0, -window.innerHeight)"); + break; + case 'j': + await page.EvaluateAsync("window.scrollBy(0, 100)"); + break; + case 'k': + await page.EvaluateAsync("window.scrollBy(0, -100)"); + break; + case 'y': + var selectedText = await page.EvaluateAsync(@"() => { + const selection = window.getSelection(); + return selection ? selection.toString() : ''; + }"); + if (!string.IsNullOrEmpty(selectedText)) + { + Console.WriteLine($"\nCopied: {selectedText}"); + } + break; + case 'h': + ShowKeyboardShortcuts(); + break; + case (char)27: // ESC key + exitRequested = true; + break; + } + } + + // Short delay to prevent high CPU usage + await Task.Delay(50); + } + } + + public static async Task GetTextUnderCursor(IPage page, string selector) + { + var element = await page.QuerySelectorAsync(selector); + if (element != null) + { + return await element.TextContentAsync() ?? string.Empty; + } + return string.Empty; + } +} \ No newline at end of file diff --git a/src/Helpers/PlaywrightHelpers.cs b/src/Helpers/PlaywrightHelpers.cs index 35a3870..855d489 100644 --- a/src/Helpers/PlaywrightHelpers.cs +++ b/src/Helpers/PlaywrightHelpers.cs @@ -59,6 +59,12 @@ public static async Task> GetWebSearchResultUrlsAsync(string search // Navigate to the URL await page.GotoAsync(url); + // If in interactive mode, allow keyboard/mouse interaction + if (interactive) + { + await InteractiveHelpers.HandleKeyboardAndMouseEvents(page); + } + // Fetch the page content and title var content = await FetchPageContent(page, url, stripHtml, saveToFolder); var title = await page.TitleAsync(); @@ -223,13 +229,26 @@ private static async Task GetBrowser(BrowserType browserType, bool int { try { - return browserType switch + var launchOptions = new BrowserTypeLaunchOptions + { + Headless = !interactive, + Args = interactive ? new[] { "--start-maximized" } : Array.Empty() + }; + + var browser = browserType switch { - BrowserType.Chromium => await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = !interactive }), - BrowserType.Firefox => await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions { Headless = !interactive }), - BrowserType.Webkit => await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions { Headless = !interactive }), + BrowserType.Chromium => await playwright.Chromium.LaunchAsync(launchOptions), + BrowserType.Firefox => await playwright.Firefox.LaunchAsync(launchOptions), + BrowserType.Webkit => await playwright.Webkit.LaunchAsync(launchOptions), _ => throw new ArgumentOutOfRangeException(nameof(browserType), browserType, null) }; + + if (interactive) + { + Console.WriteLine("\nEntering interactive mode. Press 'h' for help on keyboard shortcuts."); + } + + return browser; } catch (Exception) { diff --git a/src/assets/help/interactive.txt b/src/assets/help/interactive.txt new file mode 100644 index 0000000..135cf65 --- /dev/null +++ b/src/assets/help/interactive.txt @@ -0,0 +1,23 @@ +Interactive Mode + +The interactive mode allows you to navigate web pages using keyboard shortcuts and mouse controls. + +Keyboard Shortcuts: +----------------- +ESC : Exit interactive mode +n : Go to next page +p : Go to previous page +j : Scroll down +k : Scroll up +y : Copy text under cursor to clipboard +h : Show keyboard shortcut help +q : Close browser + +Mouse Controls: +------------- +- Click and drag to select text +- Double click to select word +- Triple click to select line + +To enable interactive mode, use the --interactive flag when running web commands. +Example: mdx web --interactive "your search query" \ No newline at end of file