Example #1
0
        /// <summary>
        /// Adds the argument message as a local echo. When this local echo is resolved <see cref="PendingMessageResolved"/> will get called.
        /// </summary>
        /// <param name="message"></param>
        public void AddLocalEcho(LocalEchoMessage message)
        {
            pendingMessages.Add(message);
            Messages.Add(message);

            NewMessagesArrived?.Invoke(new[] { message });
        }
Example #2
0
        /// <summary>
        /// Replace or remove a message from the channel.
        /// </summary>
        /// <param name="echo">The local echo message (client-side).</param>
        /// <param name="final">The response message, or null if the message became invalid.</param>
        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))
            {
                // message already inserted, so let's throw away this update.
                // we may want to handle this better in the future, but for the time being api requests are single-threaded so order is assumed.
                MessageRemoved?.Invoke(echo);
                return;
            }

            Messages.Add(final);
            PendingMessageResolved?.Invoke(echo, final);
        }
Example #3
0
        /// <summary>
        /// Replace or remove a message from the channel.
        /// </summary>
        /// <param name="echo">The local echo message (client-side).</param>
        /// <param name="final">The response message, or null if the message became invalid.</param>
        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);
        }
Example #4
0
        /// <summary>
        /// Posts a message to the currently opened channel.
        /// </summary>
        /// <param name="text">The message text that is going to be posted</param>
        /// <param name="isAction">Is true if the message is an action, e.g.: user is currently eating </param>
        /// <param name="target">An optional target channel. If null, <see cref="CurrentChannel"/> will be used.</param>
        public void PostMessage(string text, bool isAction = false, Channel target = null)
        {
            if (target == null)
            {
                target = CurrentChannel.Value;
            }

            if (target == null)
            {
                return;
            }

            void dequeueAndRun()
            {
                if (postQueue.Count > 0)
                {
                    postQueue.Dequeue().Invoke();
                }
            }

            postQueue.Enqueue(() =>
            {
                if (!api.IsLoggedIn)
                {
                    target.AddNewMessages(new ErrorMessage("Please sign in to participate in chat!"));
                    return;
                }

                var message = new LocalEchoMessage
                {
                    Sender    = api.LocalUser.Value,
                    Timestamp = DateTimeOffset.Now,
                    ChannelId = target.Id,
                    IsAction  = isAction,
                    Content   = text
                };

                target.AddLocalEcho(message);

                // if this is a PM and the first message, we need to do a special request to create the PM channel
                if (target.Type == ChannelType.PM && !target.Joined)
                {
                    var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message);

                    createNewPrivateMessageRequest.Success += createRes =>
                    {
                        target.Id = createRes.ChannelID;
                        target.ReplaceMessage(message, createRes.Message);
                        dequeueAndRun();
                    };

                    createNewPrivateMessageRequest.Failure += exception =>
                    {
                        Logger.Error(exception, "Posting message failed.");
                        target.ReplaceMessage(message, null);
                        dequeueAndRun();
                    };

                    api.Queue(createNewPrivateMessageRequest);
                    return;
                }

                var req = new PostMessageRequest(message);

                req.Success += m =>
                {
                    target.ReplaceMessage(message, m);
                    dequeueAndRun();
                };

                req.Failure += exception =>
                {
                    Logger.Error(exception, "Posting message failed.");
                    target.ReplaceMessage(message, null);
                    dequeueAndRun();
                };

                api.Queue(req);
            });

            // always run if the queue is empty
            if (postQueue.Count == 1)
            {
                dequeueAndRun();
            }
        }