public FriendConversationViewModel(Tox tox, uint friendNumber)
        {
            var messages = new SourceList <MessageViewModel>();

            messages.Connect()
            .AutoRefresh(x => x.Read)
            .Filter(x => !x.Read)
            .AsObservableList()
            .CountChanged
            .ToPropertyEx(this, x => x.UnreadCount);

            this.SendMessage = ReactiveCommand.Create <string>(msg =>
            {
                if (!string.IsNullOrWhiteSpace(msg))
                {
                    _ = tox.SendMessage(friendNumber, msg, ToxMessageType.Message, out _);
                    messages.Add(new MessageViewModel("Me", msg, DateTime.Now.Ticks));
                }
            });
            ReadOnlyObservableCollection <MessageViewModel> msgs;

            messages.Connect()
            .Bind(out msgs)
            .Subscribe();

            this.Messages = msgs;

            this.SendTypedMessage = ReactiveCommand.Create(() =>
            {
                var msg           = this.InputMessage;
                this.InputMessage = string.Empty;
                return(msg);
            }, this.WhenAnyValue(x => x.InputMessage, (string s) => !string.IsNullOrWhiteSpace(s)));

            this.WhenAnyValue(x => x.InputMessage)
            .Select(msg => !string.IsNullOrWhiteSpace(msg))
            .Where(x => x)
            .Do(x => tox.SetTypingStatus(friendNumber, true, out _))
            .Throttle(TimeSpan.FromMilliseconds(500))
            .Subscribe(x => tox.SetTypingStatus(friendNumber, false, out _));

            tox.Events().Friends
            .Message
            .Where(x => x.FriendNumber == friendNumber && x.MessageType == ToxMessageType.Message)
            .Select(x => x.Message)
            .Subscribe(msg => messages.Add(new MessageViewModel(tox.GetFriendName(friendNumber, out _), msg, DateTime.Now.Ticks)));

            this.WhenAnyObservable(x => x.SendTypedMessage)
            .InvokeCommand(this, x => x.SendMessage);
        }
        public void TestToxTyping()
        {
            bool isTyping     = true;
            bool testFinished = false;

            _tox2.OnFriendTypingChanged += (sender, args) =>
            {
                if (args.IsTyping != isTyping)
                {
                    Assert.Fail("IsTyping value received does not equal the one we set");
                }

                var  error  = ToxErrorFriendQuery.Ok;
                bool result = _tox2.GetFriendTypingStatus(0, out error);
                if (!result || error != ToxErrorFriendQuery.Ok)
                {
                    Assert.Fail("Failed to get typing status, error: {0}, result: {1}", error, result);
                }

                testFinished = true;
            };
            {
                var  error  = ToxErrorSetTyping.Ok;
                bool result = _tox1.SetTypingStatus(0, isTyping, out error);
                if (!result || error != ToxErrorSetTyping.Ok)
                {
                    Assert.Fail("Failed to set typing status, error: {0}, result: {1}", error, result);
                }

                while (!testFinished)
                {
                    DoIterate();
                }
            }
        }