corp-app/CORP-MAUI/Pages/ChatPage.xaml.cs

214 lines
7.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.ObjectModel;
using CORP_MAUI.Models;
using CORP_MAUI.Services;
namespace CORP_MAUI.Pages;
public partial class ChatPage : ContentPage
{
private readonly ObservableCollection<MessageViewModel> _messages;
private User _currentUser = new();
private User _recipient;
private System.Timers.Timer _typingTimer = new();
public ChatPage(User recipient)
{
InitializeComponent();
_recipient = recipient;
_messages = new ObservableCollection<MessageViewModel>();
MessagesCollectionView.ItemsSource = _messages;
// Подписываемся на события WebSocket
ServiceProvider.WebSocketService.MessageReceived += OnMessageReceived;
ServiceProvider.WebSocketService.ConnectionStatusChanged += OnConnectionStatusChanged;
// Инициализация
_ = InitializeAsync();
}
private async Task InitializeAsync()
{
try
{
// Получаем текущего пользователя
var user = await ServiceProvider.ApiService.GetCurrentUserAsync();
if (user != null)
{
_currentUser = user;
}
// Отображаем информацию о получателе
RecipientName.Text = _recipient.FullName ?? _recipient.Username;
RecipientStatus.Text = _recipient.IsOnline ? "В сети" : "Не в сети";
// Загружаем историю сообщений
await LoadMessagesAsync();
}
catch (Exception ex)
{
await DisplayAlert("Ошибка", $"Не удалось загрузить данные: {ex.Message}", "OK");
}
}
private async Task LoadMessagesAsync()
{
try
{
var messages = await ServiceProvider.ApiService.GetMessagesAsync(_recipient.Id);
_messages.Clear();
foreach (var message in messages.OrderBy(m => m.Timestamp))
{
_messages.Add(new MessageViewModel
{
Id = message.Id,
SenderId = message.SenderId,
SenderName = message.SenderName,
Content = message.Content,
Timestamp = message.Timestamp,
IsMyMessage = message.SenderId == _currentUser?.Id
});
}
// Прокручиваем к последнему сообщению
if (_messages.Any())
{
MessagesCollectionView.ScrollTo(_messages.Last(), position: ScrollToPosition.End, animate: false);
}
}
catch (Exception ex)
{
await DisplayAlert("Ошибка", $"Не удалось загрузить сообщения: {ex.Message}", "OK");
}
}
private async void OnSendMessageClicked(object sender, EventArgs e)
{
var content = MessageEntry.Text?.Trim();
if (string.IsNullOrEmpty(content))
return;
try
{
var message = new Message
{
SenderId = _currentUser.Id,
SenderName = _currentUser.FullName ?? _currentUser.Username,
ReceiverId = _recipient.Id,
ReceiverName = _recipient.FullName ?? _recipient.Username,
Content = content,
Timestamp = DateTime.Now,
Type = MessageType.Personal
};
// Отправляем через WebSocket
if (ServiceProvider.WebSocketService.IsConnected)
{
await ServiceProvider.WebSocketService.SendMessageAsync(message);
}
else
{
// Резервный вариант через REST API
await ServiceProvider.ApiService.SendMessageAsync(message);
}
// Добавляем сообщение в список
_messages.Add(new MessageViewModel
{
SenderId = message.SenderId,
SenderName = message.SenderName,
Content = message.Content,
Timestamp = message.Timestamp,
IsMyMessage = true
});
// Очищаем поле ввода
MessageEntry.Text = string.Empty;
// Прокручиваем к последнему сообщению
MessagesCollectionView.ScrollTo(_messages.Last(), position: ScrollToPosition.End, animate: true);
}
catch (Exception ex)
{
await DisplayAlert("Ошибка", $"Не удалось отправить сообщение: {ex.Message}", "OK");
}
}
private void OnMessageTextChanged(object sender, TextChangedEventArgs e)
{
// Отправляем индикатор набора текста
if (!string.IsNullOrEmpty(e.NewTextValue) && ServiceProvider.WebSocketService.IsConnected)
{
_ = ServiceProvider.WebSocketService.SendTypingIndicatorAsync(_recipient.Id, true);
// Отменяем предыдущий таймер
_typingTimer?.Stop();
_typingTimer?.Dispose();
// Создаем новый таймер для отправки статуса "не печатает"
_typingTimer = new System.Timers.Timer(2000);
_typingTimer.Elapsed += async (s, args) =>
{
await ServiceProvider.WebSocketService.SendTypingIndicatorAsync(_recipient.Id, false);
_typingTimer?.Dispose();
};
_typingTimer.Start();
}
}
private void OnMessageReceived(object? sender, Message message)
{
// Проверяем, что сообщение от нашего собеседника
if (message.SenderId == _recipient.Id)
{
MainThread.BeginInvokeOnMainThread(() =>
{
_messages.Add(new MessageViewModel
{
Id = message.Id,
SenderId = message.SenderId,
SenderName = message.SenderName,
Content = message.Content,
Timestamp = message.Timestamp,
IsMyMessage = false
});
MessagesCollectionView.ScrollTo(_messages.Last(), position: ScrollToPosition.End, animate: true);
});
}
}
private void OnConnectionStatusChanged(object? sender, bool isConnected)
{
MainThread.BeginInvokeOnMainThread(() =>
{
ConnectionIndicator.IsVisible = !isConnected;
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
// Отписываемся от событий
ServiceProvider.WebSocketService.MessageReceived -= OnMessageReceived;
ServiceProvider.WebSocketService.ConnectionStatusChanged -= OnConnectionStatusChanged;
_typingTimer?.Dispose();
}
}
public class MessageViewModel
{
public int Id { get; set; }
public int SenderId { get; set; }
public string SenderName { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public DateTime Timestamp { get; set; }
public bool IsMyMessage { get; set; }
}