XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using CommunityToolkit.Mvvm.ComponentModel;
using XFEToolBox.Client.Utilities.Chat;
using XFEToolBox.Core.Chat;

namespace XFEToolBox.Client.Models.Chat;

public enum ChatSection
{
    Conversations,
    Lobby,
    Friends,
    Groups
}

public sealed class ChatConversationItem(ChatConversationInfo conversation)
{
    public ChatConversationInfo Conversation { get; } = conversation;
    public string Id => Conversation.Id;
    public string Title => Conversation.Kind == ChatConversationKind.Group
        ? Conversation.Group?.Name ?? "群聊"
        : Conversation.Friend?.NickName ?? "好友";
    public string Subtitle => Conversation.LastMessage is null
        ? "还没有消息"
        : ChatMessageItem.DescribeMessage(Conversation.LastMessage);
    public string Initials => Title;
    public string KindText => Conversation.Kind == ChatConversationKind.Group ? "群聊" : "好友";
    public string TimeText => Conversation.LastMessage?.CreatedAtUtc.ToLocalTime().ToString("MM-dd HH:mm") ?? string.Empty;
    public string UnreadText => Conversation.UnreadCount > 99 ? "99+" : Conversation.UnreadCount.ToString();
    public bool HasUnread => Conversation.UnreadCount > 0;
}

public sealed class ChatNavigationItem
{
    public ChatNavigationItem(ChatConversationInfo? conversation, ChatFriendInfo friend)
    {
        Conversation = conversation;
        Friend = friend;
        Key = $"friend:{friend.User.Id}";
        Title = friend.User.NickName;
        Initials = Title;
    }

    public ChatNavigationItem(ChatConversationInfo? conversation, ChatGroupSummary group)
    {
        Conversation = conversation;
        Group = group;
        Key = $"group:{group.Id}";
        Title = group.Name;
        Initials = Title;
    }

    public ChatNavigationItem(ChatConversationInfo conversation)
    {
        Conversation = conversation;
        Friend = conversation.Kind == ChatConversationKind.Direct && conversation.Friend is not null
            ? new ChatFriendInfo
            {
                User = conversation.Friend,
                ConversationId = conversation.Id,
                FriendsSinceUtc = conversation.CreatedAtUtc
            }
            : null;
        Group = conversation.Kind == ChatConversationKind.Group ? conversation.Group : null;
        Key = conversation.Kind == ChatConversationKind.Group
            ? $"group:{conversation.Group?.Id ?? conversation.Id}"
            : $"friend:{conversation.Friend?.Id ?? conversation.Id}";
        Title = conversation.Kind == ChatConversationKind.Group
            ? conversation.Group?.Name ?? "群聊"
            : conversation.Friend?.NickName ?? "好友";
        Initials = Title;
    }

    public string Key { get; }
    public ChatConversationInfo? Conversation { get; }
    public ChatFriendInfo? Friend { get; }
    public ChatGroupSummary? Group { get; }
    public string Title { get; }
    public string Initials { get; }
    public bool IsGroup => Group is not null || Conversation?.Kind == ChatConversationKind.Group;
    public bool IsFriend => !IsGroup;
    public string Subtitle => Conversation?.LastMessage is null
        ? "暂无消息"
        : ChatMessageItem.DescribeMessage(Conversation.LastMessage);
    public DateTimeOffset? LastMessageAtUtc => Conversation?.LastMessage?.CreatedAtUtc;
    public string TimeText => LastMessageAtUtc?.ToLocalTime().ToString("MM-dd HH:mm") ?? string.Empty;
    public long UnreadCount => Conversation?.UnreadCount ?? 0;
    public string UnreadText => UnreadCount > 99 ? "99+" : UnreadCount.ToString();
    public bool HasUnread => UnreadCount > 0;
    public bool IsMuted => IsGroup && ChatNotificationPreferences.IsGroupMuted(Group?.Id ?? Conversation?.Group?.Id);
    public string MutedText => IsMuted ? "免打扰" : string.Empty;
}

public sealed class ChatGroupItem(ChatGroupSummary group)
{
    public ChatGroupSummary Group { get; } = group;
    public string Id => Group.Id;
    public string Name => Group.Name;
    public string Description => string.IsNullOrWhiteSpace(Group.Description) ? "群主暂未填写简介" : Group.Description;
    public string GroupNumberText => $"群号 {Group.GroupNumber}";
    public string MemberText => $"{Group.MemberCount} 位成员";
    public string VisibilityText => Group.Visibility == ChatGroupVisibility.Public ? "公开群聊" : "私密群聊";
    public bool IsJoined => Group.CurrentUserRole is not null;
    public string JoinActionText => IsJoined ? "进入" : "加入";
    public bool CanManage => Group.CurrentUserRole is ChatGroupRole.Administrator or ChatGroupRole.Owner;
    public bool IsOwner => Group.CurrentUserRole == ChatGroupRole.Owner;
}

public sealed class ChatFriendItem(ChatFriendInfo friend)
{
    public ChatFriendInfo Friend { get; } = friend;
    public string Id => Friend.User.Id;
    public string Name => Friend.User.NickName;
    public string AccountText => $"@{Friend.User.UserName}";
    public string Bio => string.IsNullOrWhiteSpace(Friend.User.Bio) ? "这位好友还没有填写简介" : Friend.User.Bio;
}

public sealed class ChatUserSearchItem(ChatUserSummary user)
{
    public ChatUserSummary User { get; } = user;
    public string Name => User.NickName;
    public string AccountText => $"@{User.UserName}";
    public string Bio => string.IsNullOrWhiteSpace(User.Bio) ? "暂无个人简介" : User.Bio;
}

public sealed class ChatFriendRequestItem(ChatFriendRequestInfo request)
{
    public ChatFriendRequestInfo Request { get; } = request;
    public ChatUserSummary OtherUser => Request.IsIncoming ? Request.FromUser : Request.ToUser;
    public string Name => OtherUser.NickName;
    public string AccountText => $"@{OtherUser.UserName}";
    public string Message => string.IsNullOrWhiteSpace(Request.Message) ? "希望添加你为好友" : Request.Message;
    public bool CanRespond => Request.IsIncoming && Request.Status == ChatFriendRequestStatus.Pending;
    public string StatusText => Request.Status switch
    {
        ChatFriendRequestStatus.Pending when Request.IsIncoming => "等待你处理",
        ChatFriendRequestStatus.Pending => "等待对方处理",
        ChatFriendRequestStatus.Accepted => "已同意",
        ChatFriendRequestStatus.Rejected => "已拒绝",
        ChatFriendRequestStatus.Cancelled => "已取消",
        _ => "已处理"
    };
}

public sealed class ChatInvitationItem(ChatGroupInvitationInfo invitation, string currentUserId)
{
    public ChatGroupInvitationInfo Invitation { get; } = invitation;
    public string GroupName => Invitation.Group.Name;
    public string GroupNumberText => $"群号 {Invitation.Group.GroupNumber}";
    public bool IsIncoming => string.Equals(Invitation.InvitedUser.Id, currentUserId, StringComparison.Ordinal);
    public string InviterText => IsIncoming
        ? $"{Invitation.InvitedBy.NickName} 邀请你加入"
        : $"已邀请 {Invitation.InvitedUser.NickName} 加入";
    public string Message => string.IsNullOrWhiteSpace(Invitation.Message) ? "一起来聊天吧" : Invitation.Message;
    public bool CanRespond => Invitation.Status == ChatGroupInvitationStatus.Pending && IsIncoming;
    public string StatusText => Invitation.Status switch
    {
        ChatGroupInvitationStatus.Pending when IsIncoming => "待你处理",
        ChatGroupInvitationStatus.Pending => "等待对方处理",
        ChatGroupInvitationStatus.Accepted => "已加入",
        ChatGroupInvitationStatus.Rejected => "已拒绝",
        ChatGroupInvitationStatus.Cancelled => "已取消",
        ChatGroupInvitationStatus.Expired => "已过期",
        _ => "已处理"
    };
}

public sealed class ChatMessageItem(ChatMessageInfo message, string currentUserId)
{
    public ChatMessageInfo Message { get; } = message;
    public string Id => Message.Id;
    public long Sequence => Message.Sequence;
    public string SenderName => Message.Sender.NickName;
    public bool IsMine => string.Equals(Message.Sender.Id, currentUserId, StringComparison.Ordinal);
    public string TimeText => Message.CreatedAtUtc.ToLocalTime().ToString("MM-dd HH:mm");
    public string Text => Message.Text;
    public bool HasText => !string.IsNullOrWhiteSpace(Message.Text);
    public bool HasAttachment => Message.Attachment is not null;
    public bool IsGroupInvitation => Message.MessageType == ChatMessageType.GroupInvitation && Message.GroupInvitation is not null;
    public ChatAttachmentInfo? Attachment => Message.Attachment;
    public string AttachmentTitle => Message.Attachment?.FileName ?? string.Empty;
    public string AttachmentKindText => Message.MessageType switch
    {
        ChatMessageType.Image => "图片",
        ChatMessageType.Video => "视频",
        _ => "文件"
    };
    public string AttachmentSizeText => FormatBytes(Message.Attachment?.TotalBytes ?? 0);
    public string InvitationTitle => Message.GroupInvitation is null ? string.Empty : $"邀请加入 {Message.GroupInvitation.Group.Name}";
    public string InvitationSubtitle => Message.GroupInvitation is null
        ? string.Empty
        : $"群号 {Message.GroupInvitation.Group.GroupNumber} · {Message.GroupInvitation.Group.MemberCount} 位成员";
    public string InvitationStatusText => Message.GroupInvitation?.Status switch
    {
        ChatGroupInvitationStatus.Pending => "等待处理",
        ChatGroupInvitationStatus.Accepted => "已加入",
        ChatGroupInvitationStatus.Rejected => "已拒绝",
        ChatGroupInvitationStatus.Cancelled => "已取消",
        ChatGroupInvitationStatus.Expired => "已过期",
        _ => string.Empty
    };
    public bool CanRespondToInvitation => Message.GroupInvitation?.Status == ChatGroupInvitationStatus.Pending &&
                                          string.Equals(Message.GroupInvitation.InvitedUser.Id, currentUserId, StringComparison.Ordinal);

    public static string DescribeMessage(ChatMessageInfo message) => message.MessageType switch
    {
        ChatMessageType.Image => "[图片]",
        ChatMessageType.Video => "[视频]",
        ChatMessageType.File => $"[文件] {message.Attachment?.FileName}",
        ChatMessageType.GroupInvitation => $"[群邀请] {message.GroupInvitation?.Group.Name}",
        ChatMessageType.System => message.Text,
        _ => message.Text
    };

    public static string FormatBytes(long bytes)
    {
        string[] units = ["B", "KB", "MB", "GB"];
        var value = Math.Max(0, (double)bytes);
        var index = 0;
        while (value >= 1024 && index < units.Length - 1)
        {
            value /= 1024;
            index++;
        }
        return $"{value:0.##} {units[index]}";
    }
}

public sealed partial class SelectableFriendItem(ChatFriendInfo friend) : ObservableObject
{
    public ChatFriendInfo Friend { get; } = friend;
    public string Name => Friend.User.NickName;
    public string AccountText => $"@{Friend.User.UserName}";

    [ObservableProperty]
    private bool isSelected;
}

public sealed class ChatGroupMemberItem(ChatGroupMemberInfo member, string currentUserId)
{
    public ChatGroupMemberInfo Member { get; } = member;
    public string Name => Member.User.NickName;
    public string AccountText => $"@{Member.User.UserName}";
    public string RoleText => Member.Role switch
    {
        ChatGroupRole.Owner => "群主",
        ChatGroupRole.Administrator => "管理员",
        _ => "成员"
    };
    public bool IsCurrentUser => string.Equals(Member.User.Id, currentUserId, StringComparison.Ordinal);
    public bool IsOwner => Member.Role == ChatGroupRole.Owner;
    public bool CanBeManaged => !IsCurrentUser && !IsOwner;
    public string RoleActionText => Member.Role == ChatGroupRole.Administrator ? "取消管理" : "设为管理";
}