예제 #1
0
        public MainWindowViewModel()
        {
            Locator.CurrentMutable.RegisterConstant(this);
            User = new CurrentUserViewModel();
            Locator.CurrentMutable.RegisterConstant <ICurrentUser>(User);
            configuration = Locator.Current.GetService <IConfiguration>();
            settings      = configuration?.GetSection("ChatClientSettings")?.Get <ChatClientSettings>();

            var mapper = Locator.Current.GetService <IMapper>();

            if (settings == null)
            {
                settings = new ChatClientSettings();
            }

            if (settings.HostUrl.IsNullOrEmpty())
            {
                settings.HostUrl = "http://localhost:5000";
            }

            if (settings.AttachmentDefaultPath.IsNullOrEmpty())
            {
                settings.AttachmentDefaultPath = "\\Download";
            }

            serviceClient = new JsonServiceClient(settings.HostUrl);

            ProfileViewModel = new ProfileViewModel(serviceClient);
            Locator.CurrentMutable.RegisterConstant <IProfile>(ProfileViewModel);
            ProfileViewModel.IsOpenProfileEvent += () => WindowStates(WindowState.OpenProfile);

            AttachmentViewModel = new SendAttachmentsViewModel(serviceClient);

            SettingsViewModel = new SettingsViewModel(serviceClient);
            SettingsViewModel.OpenSettingsActiveEvent        += (e) => { WindowStates(WindowState.WindowSettings); };
            SettingsViewModel.TypeEnterEvent                 += (e) => { KeySendMessage = e; };
            SettingsViewModel.ContextMenuSettingsActiveEvent += (e) => { WindowStates(WindowState.HeaderMenuPopup); };
            SettingsViewModel.SetSelectedOnSettingsItemEvent += e => { TextHeaderMenuInSettings = SettingsViewModel.SettingsMenuActiveMain ? "Сообщения и чаты" : "Аудит входа"; };

            Width(false);
            User.UserName = settings.UserName;
            Tokens        = new TokenResult {
                AccessToken = settings.AccessToken, RefreshToken = settings.RefreshToken
            };

            Messages = new ObservableCollection <IMessagesContainerViewModel>();

            var bits            = Environment.Is64BitOperatingSystem ? "PC 64bit, " : "PC 32bit, ";
            var operatingSystem = bits + RuntimeInformation.OSDescription;

            string ipAddress = "";

            try
            {
                ipAddress = new WebClient().DownloadString("https://api.ipify.org");
            }
            catch (Exception e)
            {
                try
                {
                    IPHostEntry ipHost = Dns.GetHostEntry("localhost");
                    if (ipHost.AddressList.Length > 0)
                    {
                        ipAddress = ipHost.AddressList.Last().ToString();
                    }
                }
                catch (Exception exception) { }
            }
            var nameVersionClient = "SkillChat Avalonia Client 1.0";

            ConnectCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    _connection = new HubConnectionBuilder()
                                  .WithUrl(settings.HostUrl + "/ChatHub")
                                  .Build();

                    _hub = _connection.CreateHub <IChatHub>();
                    ProfileViewModel.SetChatHub(_hub);
                    AttachmentViewModel.SetChatHub(_hub);

                    if (Tokens == null || Tokens.AccessToken.IsNullOrEmpty())
                    {
                        Tokens = await serviceClient.PostAsync(new AuthViaPassword
                        {
                            Login = User.UserName, Password = User.Password
                        });
                        settings.AccessToken  = Tokens.AccessToken;
                        settings.RefreshToken = Tokens.RefreshToken;
                        settings.UserName     = User.UserName;
                        configuration.GetSection("ChatClientSettings").Set(settings);
                    }

                    serviceClient.BearerToken = Tokens.AccessToken;
                    this.ObservableForProperty(m => m.ExpireTime).Subscribe(change =>
                    {
                        if (change.Value != null)
                        {
                            //TODO запуск обновления токена
                        }
                    });

                    _connection.Subscribe <LogOn>(async data =>
                    {
                        if (data.Error)
                        {
                            IsSignedIn = false;
                            serviceClient.BearerToken = Tokens.RefreshToken;
                            try
                            {
                                Tokens = await serviceClient.PostAsync(new PostRefreshToken());
                                settings.AccessToken  = Tokens.AccessToken;
                                settings.RefreshToken = Tokens.RefreshToken;
                                configuration.GetSection("ChatClientSettings").Set(configuration);
                                await _hub.Login(Tokens.AccessToken, operatingSystem, ipAddress, nameVersionClient);
                            }
                            catch (Exception e)
                            {
                                Tokens = null;
                            }
                        }
                        else
                        {
                            IsSignedIn = true;
                            User.Id    = data.Id;
                            User.Login = data.UserLogin;
                            ExpireTime = data.ExpireTime;
                            var chats  = await serviceClient.GetAsync(new GetChatsList());
                            var chat   = chats.Chats.FirstOrDefault();
                            ChatId     = chat?.Id;
                            ChatName   = chat?.ChatName;
                            LoadMessageHistoryCommand.Execute(null);
                            //Получаем настройки
                            SettingsViewModel.ChatSettings = await serviceClient.GetAsync(new GetMySettings());
                            KeySendMessage = SettingsViewModel.ChatSettings.SendingMessageByEnterKey;
                        }
                    });

                    _connection.Subscribe <UpdateUserDisplayName>(async user =>
                    {
                        try
                        {
                            var updateMessages = Messages.Where(s => s is UserMessagesContainerViewModel);
                            foreach (var message in updateMessages)
                            {
                                foreach (var item in message.Messages.Where(s => s.UserId == user.Id))
                                {
                                    item.UserNickname = user.DisplayName;
                                }
                            }

                            ProfileViewModel.UpdateUserProfile(user.DisplayName, user.Id);
                        }
                        catch (Exception e)
                        {
                            SignOutCommand.Execute(null);
                        }
                    });

                    _connection.Subscribe <ReceiveMessage>(async data =>
                    {
                        var isMyMessage    = User.Id == data.UserId;
                        var hasAttachments = data.Attachments != null && data.Attachments.Count > 0;

                        MessageViewModel newMessage;

                        if (isMyMessage)
                        {
                            newMessage = hasAttachments ? new MyAttachmentViewModel() : new MyMessageViewModel();
                        }
                        else
                        {
                            newMessage = hasAttachments ? new UserAttachmentViewModel() : new UserMessageViewModel();
                        }

                        newMessage.Id           = data.Id;
                        newMessage.Text         = data.Message;
                        newMessage.PostTime     = data.PostTime;
                        newMessage.UserNickname = data.UserNickname ?? data.UserLogin;
                        newMessage.UserId       = data.UserId;

                        newMessage.Attachments = data.Attachments?
                                                 .Select(s =>
                        {
                            var attah = mapper?.Map <AttachmentMold>(s);
                            return(new AttachmentMessageViewModel(attah));
                        }).ToList();

                        var container = Messages.LastOrDefault();

                        if (isMyMessage)
                        {
                            if (!(container is MyMessagesContainerViewModel))
                            {
                                container = new MyMessagesContainerViewModel();
                                Messages.Add(container);
                            }
                        }
                        else
                        {
                            if (container is UserMessagesContainerViewModel)
                            {
                                var lastMessage = container.Messages.LastOrDefault();
                                if (lastMessage?.UserId != newMessage.UserId)
                                {
                                    container = new UserMessagesContainerViewModel();
                                    Messages.Add(container);
                                }
                            }
                            else
                            {
                                container = new UserMessagesContainerViewModel();
                                Messages.Add(container);
                            }

                            if (!windowIsFocused || SettingsViewModel.IsOpened)
                            {
                                Notify.NewMessage(newMessage.UserNickname, newMessage.Text.Replace("\r\n", " "));
                            }
                        }

                        container.Messages.Add(newMessage);
                        if (container.Messages.First() == newMessage)
                        {
                            newMessage.ShowNickname = true;
                        }

                        MessageReceived?.Invoke(new ReceivedMessageArgs(newMessage));
                    });

                    _connection.Closed += connectionOnClosed();
                    await _connection.StartAsync();
                    await _hub.Login(Tokens.AccessToken, operatingSystem, ipAddress, nameVersionClient);
                    //Messages.Add("Connection started");
                    IsShowingLoginPage    = false;
                    IsShowingRegisterPage = false;
                    ValidationError       = "";
                    IsConnected           = true;
                    User.Password         = "";
                }
                catch (Exception ex)
                {
                    //Изменение параеметров TextBox в случае ошибки
                    User.Error("неверный логин или пароль");
                    ErrorBe?.Invoke();
                    IsShowingLoginPage = _connection.State != HubConnectionState.Connected ? true : false;
                    //Messages.Add(ex.Message);
                }
            });

            if (Tokens.AccessToken.IsNullOrEmpty() == false)
            {
                ConnectCommand.Execute(null);
            }

            SendCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    await _hub.SendMessage(new HubMessage(ChatId, MessageText));
                    MessageText = null;
                }
                catch (Exception ex)
                {
                    SignOutCommand.Execute(null);
                }
            },
                                                         this.WhenAnyValue(m => m.IsConnected, m => m.MessageText,
                                                                           (b, m) => b == true && !string.IsNullOrEmpty(m)));

            LoadMessageHistoryCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    var first   = Messages.FirstOrDefault()?.Messages.FirstOrDefault();
                    var request = new GetMessages {
                        ChatId = ChatId, BeforePostTime = first?.PostTime
                    };

                    // Логика выбора сообщений по id чата
                    var result = await serviceClient.GetAsync(request);
                    foreach (var item in result.Messages)
                    {
                        var isMyMessage    = User.Id == item.UserId;
                        var hasAttachments = item.Attachments != null && item.Attachments.Count > 0;

                        MessageViewModel newMessage;

                        if (isMyMessage)
                        {
                            newMessage = hasAttachments ? new MyAttachmentViewModel() : new MyMessageViewModel();
                        }
                        else
                        {
                            newMessage = hasAttachments ? new UserAttachmentViewModel() : new UserMessageViewModel();
                        }

                        newMessage.Id           = item.Id;
                        newMessage.Text         = item.Text;
                        newMessage.PostTime     = item.PostTime;
                        newMessage.UserNickname = item.UserNickName;
                        newMessage.UserId       = item.UserId;

                        newMessage.Attachments = item.Attachments?.Select(s => new AttachmentMessageViewModel(s)).ToList();

                        var container = Messages.FirstOrDefault();

                        if (isMyMessage)
                        {
                            if (!(container is MyMessagesContainerViewModel))
                            {
                                container = new MyMessagesContainerViewModel();
                                Messages.Insert(0, container);
                            }
                        }
                        else
                        {
                            if (container is UserMessagesContainerViewModel)
                            {
                                var firstMessage = container.Messages.FirstOrDefault();
                                if (firstMessage?.UserId != newMessage.UserId)
                                {
                                    container = new UserMessagesContainerViewModel();
                                    Messages.Insert(0, container);
                                }
                            }
                            else
                            {
                                container = new UserMessagesContainerViewModel();
                                Messages.Insert(0, container);
                            }
                        }

                        container.Messages.Insert(0, newMessage);

                        var firstInBlock = container.Messages.First();
                        foreach (var message in container.Messages)
                        {
                            message.ShowNickname = firstInBlock == message;
                        }
                    }
                }
                catch (Exception e)
                {
                }
            });

            SignOutCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    Messages.Clear();
                    MessageText = null;
                    Tokens      = null;
                    IsSignedIn  = false;
                    IsConnected = false;
                    serviceClient.BearerToken = null;
                    if (_connection != null)
                    {
                        _connection.Closed -= connectionOnClosed();
                        await _connection.StopAsync();
                    }

                    _connection = null;
                    _hub        = null;

                    settings.AccessToken  = null;
                    settings.RefreshToken = null;
                    configuration.GetSection("ChatClientSettings").Set(settings);

                    WindowStates(WindowState.SignOut);
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    IsShowingLoginPage = true;
                }
            });
            IsShowingLoginPage = true;

            // Скрывает окно регистрации
            IsShowingRegisterPage = false;
            IsShowingLoginPage    = true;
            GoToRegisterCommand   = ReactiveCommand.Create <object>(_ =>
            {
                IsShowingRegisterPage = true;
                IsShowingLoginPage    = false;
                RegisterUser.Login    = User.UserName;
                User.Password         = "";
            });

            RegisterUser = new RegisterUserViewModel();
            RegisterUser.GoToLoginCommand = ReactiveCommand.Create <object>(_ =>
            {
                IsShowingRegisterPage = false;
                IsShowingLoginPage    = true;
                RegisterUser.Password = "";
                User.UserName         = RegisterUser.Login;
            });
            IsConnected     = false; //Скрывает окно чата
            RegisterCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                var request = new RegisterNewUser();
                try
                {
                    ValidationError = "";
                    if (string.IsNullOrWhiteSpace(RegisterUser.Login) ||
                        string.IsNullOrWhiteSpace(RegisterUser.Password))
                    {
                        throw new Exception("Не заполнены логин и/или пароль");
                    }
                    request.Login    = RegisterUser.Login;
                    request.Password = RegisterUser.Password;
                    request.UserName = RegisterUser.UserName;

                    Tokens = await serviceClient.PostAsync(request);

                    settings.AccessToken  = Tokens.AccessToken;
                    settings.RefreshToken = Tokens.RefreshToken;
                    settings.UserName     = RegisterUser.Login;
                    configuration.GetSection("ChatClientSettings").Set(settings);
                    ConnectCommand.Execute(null);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Ошибка регистрации {ex.Message}");
                    ValidationError = ex.Message;
                }
            });

            NotifyCommand = ReactiveCommand.Create <object>(obj =>
            {
                if (obj is IHaveIsActive win)
                {
                    windowIsFocused = win.IsActive;
                }
            });
            PointerPressedCommand = ReactiveCommand.Create <object>(obj =>
            {
                ProfileViewModel.ContextMenuClose();
                SettingsViewModel.CloseContextMenu();
            });

            ProfileViewModel.SignOutCommand            = SignOutCommand;
            ProfileViewModel.LoadMessageHistoryCommand = LoadMessageHistoryCommand;
        }
예제 #2
0
        public MainWindowViewModel()
        {
            _connection = new HubConnectionBuilder()
                          .WithUrl("http://localhost:53353/ChatHub")
                          .Build();

            _connection.Closed += async(error) =>
            {
                await Task.Delay(new Random().Next(0, 5) * 1000);

                await _connection.StartAsync();
            };

            var hub = _connection.CreateHub <IChatHub>();

            Messages       = new ObservableCollection <string>();
            ConnectCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                //Native subcribe
                //_connection.On<string, string>("ReceiveMessage", (user, message) =>
                //{
                //    var newMessage = $"{user}: {message}";
                //    Messages.Add(newMessage);

                //});

                //EasyUse subcribe
                _connection.Subscribe <ReceiveMessage>(data =>
                {
                    var newMessage = $"{data.User}: {data.Message}";
                    Messages.Add(newMessage);
                });

                try
                {
                    await _connection.StartAsync();
                    Messages.Add("Connection started");
                    IsConnected = true;
                }
                catch (Exception ex)
                {
                    IsConnected = false;
                    Messages.Add(ex.Message);
                }
            }, this.WhenAnyValue(m => m.IsConnected, b => b == false));

            SendCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    //Native send message
                    //await _connection.InvokeAsync("SendMessage", UserName, MessageText);

                    //EasyUse send message
                    await hub.SendMessage(UserName, MessageText);
                }
                catch (Exception ex)
                {
                    IsConnected = false;
                    Messages.Add(ex.Message);
                }
            }, this.WhenAnyValue(m => m.IsConnected, b => b == true));
            IsConnected = false;
        }