feat: add bounded session and history navigation
Add session scrolling, latest-message navigation and fingerprint location under the shared UI gate; reuse navigation in history reads and provide read-only smoke. Navigation index snapshot passed 124 tests and a full build. Windows 4.1.13.63 read-only validation passed 10/10, including two-scroll history location; no sends. Record scope limits, including next-unread navigation not yet implemented.
This commit is contained in:
@@ -303,8 +303,10 @@ public static partial class WechatChatClient
|
||||
public static async Task<IReadOnlyList<ChatMessageSnapshot>> ReadHistoryAsync(
|
||||
int maxMessages,
|
||||
int maxScrolls,
|
||||
CancellationToken cancellationToken)
|
||||
CancellationToken cancellationToken,
|
||||
string session = WechatLocators.FileTransferAssistant)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(session);
|
||||
if (maxMessages is < 1 or > 1000 || maxScrolls is < 0 or > 100)
|
||||
{
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "History limits are maxMessages 1-1000 and maxScrolls 0-100.");
|
||||
@@ -315,7 +317,7 @@ public static partial class WechatChatClient
|
||||
{
|
||||
using var automation = new UIA3Automation();
|
||||
var window = AttachWindow(automation, cancellationToken);
|
||||
await OpenFileTransferAssistantCoreAsync(window, cancellationToken);
|
||||
await OpenNamedSessionAsync(window, session, cancellationToken).ConfigureAwait(false);
|
||||
var messages = new List<ChatMessageSnapshot>();
|
||||
var deduper = new BoundedMessageDeduper(Math.Max(2048, maxMessages * 4));
|
||||
var unchanged = 0;
|
||||
@@ -323,24 +325,21 @@ public static partial class WechatChatClient
|
||||
for (var page = 0; page <= maxScrolls; page++)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
window = WechatDoctor.FindWechatWindow(automation) ?? window;
|
||||
RequireNavigationSession(window, session);
|
||||
var visible = ReadVisible(window);
|
||||
var older = visible.Where(message => deduper.TryAdd(message.Fingerprint)).ToArray();
|
||||
if (older.Length == 0) unchanged++; else unchanged = 0;
|
||||
if (page == 0) messages.AddRange(older); else messages.InsertRange(0, older);
|
||||
if (messages.Count >= maxMessages || unchanged >= 2 || page == maxScrolls) break;
|
||||
|
||||
var list = FindByAutomationId(window, WechatLocators.MessageList)
|
||||
?? throw new WxAgentException(WxAgentErrorCode.ControlNotFound, $"Control {WechatLocators.MessageList} was not found.");
|
||||
MoveToCenter(list);
|
||||
Mouse.Scroll(5);
|
||||
ScrollNavigationList(window, WechatLocators.MessageList, WechatScrollDirection.Up);
|
||||
scrolled++;
|
||||
await Task.Delay(350, cancellationToken);
|
||||
}
|
||||
|
||||
if (scrolled > 0)
|
||||
{
|
||||
Mouse.Scroll(-5d * scrolled);
|
||||
await GoToLatestCoreAsync(window, session, 100, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return messages.Count <= maxMessages ? messages : messages.TakeLast(maxMessages).ToArray();
|
||||
|
||||
Reference in New Issue
Block a user