Initial commit to new repository
This commit is contained in:
192
.decompiledproj/AxCopilot/Handlers/ClipboardHistoryHandler.cs
Normal file
192
.decompiledproj/AxCopilot/Handlers/ClipboardHistoryHandler.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using AxCopilot.SDK;
|
||||
using AxCopilot.Services;
|
||||
|
||||
namespace AxCopilot.Handlers;
|
||||
|
||||
public class ClipboardHistoryHandler : IActionHandler
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = 40)]
|
||||
private struct INPUT
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public uint Type;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public KEYBDINPUT ki;
|
||||
}
|
||||
|
||||
private struct KEYBDINPUT
|
||||
{
|
||||
public ushort wVk;
|
||||
|
||||
public ushort wScan;
|
||||
|
||||
public uint dwFlags;
|
||||
|
||||
public uint time;
|
||||
|
||||
public nint dwExtraInfo;
|
||||
}
|
||||
|
||||
private readonly ClipboardHistoryService _historyService;
|
||||
|
||||
private static readonly Dictionary<string, string> CategoryFilters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "url", "URL" },
|
||||
{ "코드", "코드" },
|
||||
{ "code", "코드" },
|
||||
{ "경로", "경로" },
|
||||
{ "path", "경로" },
|
||||
{ "핀", "핀" },
|
||||
{ "pin", "핀" }
|
||||
};
|
||||
|
||||
public string? Prefix => "#";
|
||||
|
||||
public PluginMetadata Metadata => new PluginMetadata("ClipboardHistory", "클립보드 히스토리 — # 뒤에 검색어 (또는 빈 입력으로 전체 보기)", "1.0", "AX");
|
||||
|
||||
public ClipboardHistoryHandler(ClipboardHistoryService historyService)
|
||||
{
|
||||
_historyService = historyService;
|
||||
}
|
||||
|
||||
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||||
{
|
||||
IReadOnlyList<ClipboardEntry> history = _historyService.History;
|
||||
if (history.Count == 0)
|
||||
{
|
||||
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("클립보드 히스토리가 없습니다", "텍스트를 복사하면 이 곳에 기록됩니다", null, null, null, "\ue81c")));
|
||||
}
|
||||
string q = query.Trim().ToLowerInvariant();
|
||||
string catFilter = null;
|
||||
foreach (var (text3, text4) in CategoryFilters)
|
||||
{
|
||||
if (q == text3 || q.StartsWith(text3 + " "))
|
||||
{
|
||||
catFilter = text4;
|
||||
object obj;
|
||||
if (q.Length <= text3.Length)
|
||||
{
|
||||
obj = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
string text5 = q;
|
||||
int num = text3.Length + 1;
|
||||
obj = text5.Substring(num, text5.Length - num).Trim();
|
||||
}
|
||||
q = (string)obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
IEnumerable<ClipboardEntry> source = history.AsEnumerable();
|
||||
if (catFilter == "핀")
|
||||
{
|
||||
source = source.Where((ClipboardEntry e) => e.IsPinned);
|
||||
}
|
||||
else if (catFilter != null)
|
||||
{
|
||||
source = source.Where((ClipboardEntry e) => e.Category == catFilter);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(q))
|
||||
{
|
||||
source = source.Where((ClipboardEntry e) => e.Preview.ToLowerInvariant().Contains(q));
|
||||
}
|
||||
IOrderedEnumerable<ClipboardEntry> source2 = from e in source
|
||||
orderby e.IsPinned descending, e.CopiedAt descending
|
||||
select e;
|
||||
List<LauncherItem> list = source2.Select(delegate(ClipboardEntry e)
|
||||
{
|
||||
string text6 = (e.IsPinned ? "\ud83d\udccc " : "");
|
||||
string value = ((e.Category != "일반") ? ("[" + e.Category + "] ") : "");
|
||||
return new LauncherItem(text6 + e.Preview, $"{value}{e.RelativeTime} · {e.CopiedAt:MM/dd HH:mm}", null, e, null, e.IsPinned ? "\ue728" : (e.IsText ? "\ue81c" : "\ueb9f"));
|
||||
}).ToList();
|
||||
if (list.Count == 0)
|
||||
{
|
||||
list.Add(new LauncherItem("'" + query + "'에 해당하는 항목 없음", "#pin #url #코드 #경로 로 필터링 가능", null, null, null, "\ue81c"));
|
||||
}
|
||||
return Task.FromResult((IEnumerable<LauncherItem>)list);
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||||
{
|
||||
object data = item.Data;
|
||||
if (!(data is ClipboardEntry entry))
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
_historyService.SuppressNextCapture();
|
||||
_historyService.PromoteEntry(entry);
|
||||
if (!entry.IsText && entry.Image != null)
|
||||
{
|
||||
BitmapSource originalImg = ClipboardHistoryService.LoadOriginalImage(entry.OriginalImagePath);
|
||||
Clipboard.SetImage(originalImg ?? entry.Image);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(entry.Text))
|
||||
{
|
||||
Clipboard.SetText(entry.Text);
|
||||
nint prevWindow = WindowTracker.PreviousWindow;
|
||||
if (prevWindow != IntPtr.Zero)
|
||||
{
|
||||
await Task.Delay(300, ct);
|
||||
uint lpdwProcessId;
|
||||
uint targetThread = GetWindowThreadProcessId(prevWindow, out lpdwProcessId);
|
||||
uint currentThread = GetCurrentThreadId();
|
||||
AttachThreadInput(currentThread, targetThread, fAttach: true);
|
||||
SetForegroundWindow(prevWindow);
|
||||
AttachThreadInput(currentThread, targetThread, fAttach: false);
|
||||
await Task.Delay(100, ct);
|
||||
SendCtrlV();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
LogService.Warn("클립보드 히스토리 붙여넣기 실패: " + ex2.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SendCtrlV()
|
||||
{
|
||||
INPUT[] array = new INPUT[4];
|
||||
array[0].Type = 1u;
|
||||
array[0].ki.wVk = 17;
|
||||
array[1].Type = 1u;
|
||||
array[1].ki.wVk = 86;
|
||||
array[2].Type = 1u;
|
||||
array[2].ki.wVk = 86;
|
||||
array[2].ki.dwFlags = 2u;
|
||||
array[3].Type = 1u;
|
||||
array[3].ki.wVk = 17;
|
||||
array[3].ki.dwFlags = 2u;
|
||||
SendInput((uint)array.Length, array, Marshal.SizeOf<INPUT>());
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetForegroundWindow(nint hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern uint GetWindowThreadProcessId(nint hWnd, out uint lpdwProcessId);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, [MarshalAs(UnmanagedType.Bool)] bool fAttach);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern uint GetCurrentThreadId();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray)] INPUT[] pInputs, int cbSize);
|
||||
}
|
||||
Reference in New Issue
Block a user