// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Framework.Lists; using osu.Game.Users; namespace osu.Game.Online.Chat { public class Channel { public readonly int MaxHistory = 300; /// /// Contains every joined user except the current logged in user. /// public readonly ObservableCollection JoinedUsers = new ObservableCollection(); public readonly SortedList Messages = new SortedList(Comparer.Default); private readonly List pendingMessages = new List(); public event Action> NewMessagesArrived; public event Action PendingMessageResolved; public event Action MessageRemoved; public readonly Bindable Joined = new Bindable(); public TargetType Target { get; } public bool ReadOnly { get; set; } public override string ToString() => Name; [JsonProperty(@"name")] public string Name; [JsonProperty(@"description")] public string Topic; [JsonProperty(@"type")] public string Type; [JsonProperty(@"channel_id")] public long Id; [JsonConstructor] public Channel() { } /// /// Contructs a private channel /// TODO this class needs to be serialized from something like channels/private, instead of creating from the contructor /// /// The user public Channel(User user) { Target = TargetType.User; Name = user.Username; Id = user.Id; JoinedUsers.Add(user); } public void AddLocalEcho(LocalEchoMessage message) { pendingMessages.Add(message); Messages.Add(message); NewMessagesArrived?.Invoke(new[] { message }); } public void AddNewMessages(params Message[] messages) { messages = messages.Except(Messages).ToArray(); Messages.AddRange(messages); purgeOldMessages(); NewMessagesArrived?.Invoke(messages); } /// /// Replace or remove a message from the channel. /// /// The local echo message (client-side). /// The response message, or null if the message became invalid. public void ReplaceMessage(LocalEchoMessage echo, Message final) { if (!pendingMessages.Remove(echo)) throw new InvalidOperationException("Attempted to remove echo that wasn't present"); Messages.Remove(echo); if (final == null) { MessageRemoved?.Invoke(echo); return; } if (Messages.Contains(final)) throw new InvalidOperationException("Attempted to add the same message again"); Messages.Add(final); PendingMessageResolved?.Invoke(echo, final); } private void purgeOldMessages() { // never purge local echos int messageCount = Messages.Count - pendingMessages.Count; if (messageCount > MaxHistory) Messages.RemoveRange(0, messageCount - MaxHistory); } } }