public MeetingListViewModel(IAgentConnection connection,
                                    INavigationService navigation,
                                    IMeetingViewModelFactory meetingFactory)
        {
            // Enable the command once a meeting has been selected
            var enter = new ReactiveCommand(this.WhenAnyValue(v => v.SelectedMeeting, sm => sm != null));
            
            // Call the navigate method passing in the selected meeting
            _enterMeetingSub = enter
                .RegisterAsyncAction(_ => navigation.Navigate(Screen.AgentMeeting, SelectedMeeting))
                .Subscribe();
            EnterMeetingCommand = enter;

            _meetingStatusSub = connection.MeetingStatus.ObserveOn(RxApp.MainThreadScheduler).Subscribe(UpdateStatuses);

            // When we get a new list of meetings, add them to our list while suppressing changes
            _meetingUpdateSub = connection.Meetings
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(meetings =>
                            {
                                using (_meetings.SuppressChangeNotifications())
                                {
                                    var toAdd = meetings
                                        .Select(meetingFactory.Create)
                                        .ToArray();

                                    _meetings.Clear();
                                    _meetings.AddRange(toAdd);
                                }
                            });

            Title = "Upcoming Appointments";
        }
Exemplo n.º 2
0
        public MeetingListViewModel(IAgentConnection connection,
                                    INavigationService navigation,
                                    IMeetingViewModelFactory meetingFactory)
        {
            // Enable the command once a meeting has been selected
            var enter = new ReactiveCommand(this.WhenAnyValue(v => v.SelectedMeeting, sm => sm != null));

            // Call the navigate method passing in the selected meeting
            _enterMeetingSub = enter
                               .RegisterAsyncAction(_ => navigation.Navigate(Screen.AgentMeeting, SelectedMeeting))
                               .Subscribe();
            EnterMeetingCommand = enter;

            _meetingStatusSub = connection.MeetingStatus.ObserveOn(RxApp.MainThreadScheduler).Subscribe(UpdateStatuses);

            // When we get a new list of meetings, add them to our list while suppressing changes
            _meetingUpdateSub = connection.Meetings
                                .ObserveOn(RxApp.MainThreadScheduler)
                                .Subscribe(meetings =>
            {
                using (_meetings.SuppressChangeNotifications())
                {
                    var toAdd = meetings
                                .Select(meetingFactory.Create)
                                .ToArray();

                    _meetings.Clear();
                    _meetings.AddRange(toAdd);
                }
            });

            Title = "Upcoming Appointments";
        }
        public ClientLobbyViewModel(IClientConnection clientConnection,
                                    INavigationService navigation,
                                    IMeetingViewModelFactory meetingFactory)
        {
            _clientConnection = clientConnection;
            _navigation       = navigation;


            // This command should be available when we're not already waiting
            // but not before we get the Meeting data back.
            // Check for a non null meeting and make sure WaitingForAgent is false
            var cmd = new ReactiveCommand(this.WhenAnyValue(
                                              vm => vm.WaitingForAgent,
                                              vm => vm.Meeting,
                                              (wait, mtg) => !wait && mtg != null));

            // This is the navigation function.
            // We want to go to the ClientMeeting screen once the following conditions are met:
            // 1) We are the Active screen (IsActive == true)
            // 2) We have the meeting VM back (this gets set as a result of the previous call)
            // 3) We get the MeetingDetails (non-null). This means the agent hit Start Meeting
            //
            // Combine the three things we're observing into an anon type
            // Then check them against our conditions
            // If all true, then navigate
            _navSub = _clientConnection.MeetingDetails
                      .CombineLatest(this.WhenAnyValue(vm => vm.IsActive),
                                     this.WhenAnyValue(vm => vm.Meeting),
                                     (det, act, mtg) => new { Details = det, IsActive = act, Meeting = mtg })
                      .Where(t => t.IsActive && t.Details != null && t.Meeting != null)
                      .Subscribe(c =>
            {
                if (c.Details.MeetingId == Meeting.Id)
                {
                    Meeting.VideoConf.Config = c.Details;
                    _navigation.Navigate(Screen.ClientMeeting, Meeting);
                }
            });

            // The command's action will set the WaitingForAgent to true so we can't click
            // Join again. It will then send the join message to the server
            _joinMeetingSub = cmd.RegisterAsyncAction(p =>
            {
                WaitingForAgent    = true;
                ConnectedToMeeting = true;
                MeetingJoined      = true;
                _clientConnection.JoinMeeting(Meeting.Id);
            }).Subscribe();

            JoinMeetingCommand = cmd;


            var connectCmd = new ReactiveCommand(this.WhenAnyValue(p => p.MeetingId, p => p.ConnectedToMeeting, p => p.RequestInProgress, (id, connected, requestInProgress) => !string.IsNullOrEmpty(id) && id.Length == 6 && !connected && !requestInProgress));

            connectCmd.RegisterAsyncAction(p =>
            {
                RequestInProgress = true;
                // Kick off the GetMeetingDetails call
                // Normally you can't await a task in a ctor, but
                // Rx solves that by turning it into an Observable.
                // When we get the meeting DTO back, turn it into a MeetingVM
                // and expose it as a property here.
                clientConnection.GetMeetingDetails(MeetingId)
                .ToObservable()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Select(p1 => p1 == null ? null : meetingFactory.Create(p1))
                .Subscribe(p1 =>
                {
                    Error = string.Empty;
                    if (p1 == null)
                    {
                        Error = "Meeting with id " + MeetingId + " does not exist.";
                        return;                                                           // nothing, meeting doesn't exist
                    }
                    Meeting           = p1;
                    RequestInProgress = false;
                    JoinMeetingCommand.Execute(null);
                });
            });
            ConnectCommand = connectCmd;

            var disconnectCmd = new ReactiveCommand(this.WhenAnyValue(p => p.ConnectedToMeeting, p => p.RequestInProgress, (connected, requestInProgress) => connected && !requestInProgress));

            disconnectCmd.RegisterAsyncAction(p =>
            {
                WaitingForAgent    = false;
                ConnectedToMeeting = false;
                if (MeetingJoined)
                {
                    _clientConnection.LeaveMeeting(Meeting.Id);
                    MeetingJoined = false;
                }

                _clientConnection.LeaveMeeting(Meeting.Id);
                Meeting = null;
            });


            DisconnectCommand = disconnectCmd;

            // Update the title based on the waiting status. Once we press the button, go into
            // "waiting" mode.
            _titleSub = this.WhenAny(v => v.WaitingForAgent, v => v.Meeting,
                                     (waiting, meeting) =>
            {
                if (meeting.Value == null)
                {
                    return("Please connect to a meeting");
                }
                return(waiting.Value ? "Waiting for agent to start the meeting" : "Please join the meeting.");
            })
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(text => Title = text);

            MeetingId = "64BDF0"; // default to the first meeting for easy testing
        }
        public ClientLobbyViewModel(IClientConnection clientConnection,
                                    INavigationService navigation,
                                    IMeetingViewModelFactory meetingFactory)
        {
            _clientConnection = clientConnection;
            _navigation = navigation;


            // This command should be available when we're not already waiting
            // but not before we get the Meeting data back.
            // Check for a non null meeting and make sure WaitingForAgent is false
            var cmd = new ReactiveCommand(this.WhenAnyValue(
                vm => vm.WaitingForAgent,
                vm => vm.Meeting,
                (wait, mtg) => !wait && mtg != null));

            // This is the navigation function.
            // We want to go to the ClientMeeting screen once the following conditions are met:
            // 1) We are the Active screen (IsActive == true)
            // 2) We have the meeting VM back (this gets set as a result of the previous call)
            // 3) We get the MeetingDetails (non-null). This means the agent hit Start Meeting
            //
            // Combine the three things we're observing into an anon type
            // Then check them against our conditions
            // If all true, then navigate
            _navSub = _clientConnection.MeetingDetails
                                       .CombineLatest(this.WhenAnyValue(vm => vm.IsActive),
                                                      this.WhenAnyValue(vm => vm.Meeting),
                                                      (det, act, mtg) => new { Details = det, IsActive = act, Meeting = mtg })
                .Where(t => t.IsActive && t.Details != null && t.Meeting != null)
                                       .Subscribe(c =>
                                       {
                                           if (c.Details.MeetingId == Meeting.Id)
                                           {
                                               Meeting.VideoConf.Config = c.Details;
                                               _navigation.Navigate(Screen.ClientMeeting, Meeting);
                                           }
                                       });

            // The command's action will set the WaitingForAgent to true so we can't click
            // Join again. It will then send the join message to the server
            _joinMeetingSub = cmd.RegisterAsyncAction(p =>
                                                      {
                                                          WaitingForAgent = true;
                                                          ConnectedToMeeting = true;
                                                          MeetingJoined = true;
                                                          _clientConnection.JoinMeeting(Meeting.Id);
                                                      }).Subscribe();

            JoinMeetingCommand = cmd;


            var connectCmd = new ReactiveCommand(this.WhenAnyValue(p => p.MeetingId, p => p.ConnectedToMeeting, p => p.RequestInProgress, (id, connected, requestInProgress) => !string.IsNullOrEmpty(id) && id.Length == 6 && !connected && !requestInProgress));
            connectCmd.RegisterAsyncAction(p =>
                                           {
                                               RequestInProgress = true;
                                               // Kick off the GetMeetingDetails call
                                               // Normally you can't await a task in a ctor, but
                                               // Rx solves that by turning it into an Observable.
                                               // When we get the meeting DTO back, turn it into a MeetingVM
                                               // and expose it as a property here.
                                               clientConnection.GetMeetingDetails(MeetingId)
                                                               .ToObservable()
                                                               .ObserveOn(RxApp.MainThreadScheduler)
                                                               .Select(p1 => p1 == null ? null : meetingFactory.Create(p1))
                                                               .Subscribe(p1 =>
                                                                          {
                                                                              Error = string.Empty;
                                                                              if (p1 == null)
                                                                              {
                                                                                  Error = "Meeting with id " + MeetingId + " does not exist.";
                                                                                  return; // nothing, meeting doesn't exist
                                                                              }
                                                                              Meeting = p1;
                                                                              RequestInProgress = false;
                                                                              JoinMeetingCommand.Execute(null);
                                                                          });


                                           });
            ConnectCommand = connectCmd;

            var disconnectCmd = new ReactiveCommand(this.WhenAnyValue(p => p.ConnectedToMeeting, p => p.RequestInProgress, (connected,requestInProgress) => connected && !requestInProgress));
            disconnectCmd.RegisterAsyncAction(p =>
                                              {
                                                  WaitingForAgent = false;
                                                  ConnectedToMeeting = false;
                                                  if (MeetingJoined)
                                                  {
                                                      _clientConnection.LeaveMeeting(Meeting.Id);
                                                      MeetingJoined = false;
                                                  }

                                                  _clientConnection.LeaveMeeting(Meeting.Id);
                                                  Meeting = null;
                                              });


            DisconnectCommand = disconnectCmd;

            // Update the title based on the waiting status. Once we press the button, go into
            // "waiting" mode.
            _titleSub = this.WhenAny(v => v.WaitingForAgent, v => v.Meeting,
                                     (waiting, meeting) =>
                                     {
                                         if (meeting.Value == null) return "Please connect to a meeting";
                                         return waiting.Value ? "Waiting for agent to start the meeting" : "Please join the meeting.";
                                     })
                            .ObserveOn(RxApp.MainThreadScheduler)
                            .Subscribe(text => Title = text);

            MeetingId = "64BDF0"; // default to the first meeting for easy testing
        }