You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/AI/Views/MainWindow.axaml.cs

93 lines
3.2 KiB
C#

using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using AI.ViewModels;
namespace AI.Views
{
public partial class MainWindow : Window
{
private bool _isUserAtBottom = true; // 跟踪用户是否在底部
private const double ScrollThreshold = 50.0; // 距离底部的阈值(像素)
public MainWindow()
{
InitializeComponent();
DataContextChanged += MainWindow_DataContextChanged;
}
private void MainWindow_DataContextChanged(object? sender, EventArgs e)
{
if (DataContext is MainWindowViewModel vm)
{
vm.RequestScrollToBottom += ViewModel_RequestScrollToBottom;
// 订阅文件选择请求事件
vm.RequestFileSelection += async () =>
{
var files = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = "选择文件",
AllowMultiple = false,
FileTypeFilter = new[] { FilePickerFileTypes.All }
});
return files;
};
}
// 初始化滚动视图的滚动事件监听
if (ChatMessagesScrollViewer != null)
{
ChatMessagesScrollViewer.ScrollChanged += ChatMessagesScrollViewer_ScrollChanged;
}
}
private void ChatMessagesScrollViewer_ScrollChanged(object? sender, ScrollChangedEventArgs e)
{
if (sender is ScrollViewer scrollViewer)
{
// 检查用户是否在底部(考虑一个小的阈值,避免浮点数精度问题)
var offset = scrollViewer.Offset.Y;
var extent = scrollViewer.Extent.Height;
var viewport = scrollViewer.Viewport.Height;
// 处理边界情况:如果内容高度小于视口高度,认为在底部
if (extent <= viewport)
{
_isUserAtBottom = true;
return;
}
var distanceFromBottom = extent - (offset + viewport);
// 如果距离底部小于阈值,认为用户在底部
_isUserAtBottom = distanceFromBottom <= ScrollThreshold;
}
}
private void ViewModel_RequestScrollToBottom()
{
Dispatcher.UIThread.InvokeAsync(() =>
{
// 只在用户已经在底部时才自动滚动
// 这样如果用户向上滚动查看历史消息,就不会被强制拉回底部
if (_isUserAtBottom)
{
ChatMessagesScrollViewer.ScrollToEnd();
}
});
}
private void OnDeleteSessionClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button && button.Tag is string sessionId)
{
if (DataContext is MainWindowViewModel vm)
{
vm.DeleteSessionCommand.Execute(sessionId);
}
}
}
}
}