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";
        }
예제 #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";
        }
예제 #3
0
        internal static async Task <WorkspaceConfiguration> CreateAsync(
            IAgentConnection agent,
            ClientSessionKind sessionKind,
            CancellationToken cancellationToken = default)
        {
            // HACK: This is a temporary fix to get iOS agent/app assemblies
            // sent to the Windows client when using the remote simulator.
            var includePeImage = agent.IncludePeImage;

            var configuration = await agent.Api.InitializeEvaluationContextAsync(includePeImage)
                                .ConfigureAwait(false);

            if (configuration == null)
            {
                throw new Exception(
                          $"{nameof (agent.Api.InitializeEvaluationContextAsync)} " +
                          $"did not return a {nameof (TargetCompilationConfiguration)}");
            }

            var dependencyResolver = CreateDependencyResolver(
                agent.Type,
                agent.AssemblySearchPaths);

            var defaultRefs = await agent.Api.GetAppDomainAssembliesAsync(includePeImage)
                              .ConfigureAwait(false);

            // Only do this for Inspector sessions. Workbooks will do their own Forms init later.
            if (sessionKind == ClientSessionKind.LiveInspection)
            {
                var formsReference = defaultRefs.FirstOrDefault(ra => ra.Name.Name == "Xamarin.Forms.Core");
                if (formsReference != null)
                {
                    await LoadFormsAgentExtensions(
                        formsReference.Name.Version,
                        agent,
                        dependencyResolver,
                        configuration.EvaluationContextId,
                        includePeImage).ConfigureAwait(false);
                }
            }

            dependencyResolver.AddDefaultReferences(defaultRefs);

            return(new WorkspaceConfiguration(
                       configuration,
                       dependencyResolver,
                       includePeImage,
                       ResolveHostObjectType(
                           dependencyResolver,
                           configuration,
                           agent.Type)));
        }
예제 #4
0
        public void NotifyAgentConnected(IAgentConnection agentConnection)
        {
            lock (this) {
                if (this.agentConnection != null)
                {
                    NotifyAgentDisconnected();
                }

                this.agentConnection = agentConnection;
                agentConnectionMessagesSubscription = this.agentConnection.Api.Messages.Subscribe(
                    new Observer <object> (OnAgentMessage));
            }
        }
 public AgentMainService(IAgentConnection connection, 
                         ISharedDataService data, 
                         ISettings settings,
                         IPropertyChangedTransmitter transmitter, 
                         IPropertyChangedReceiver receiver,
                         INavigationService navigation)
 {
     _connection = connection;
     _data = data;
     _settings = settings;
     _transmitter = transmitter;
     _receiver = receiver;
     _navigation = navigation;
 }
 public AgentMainService(IAgentConnection connection,
                         ISharedDataService data,
                         ISettings settings,
                         IPropertyChangedTransmitter transmitter,
                         IPropertyChangedReceiver receiver,
                         INavigationService navigation)
 {
     _connection  = connection;
     _data        = data;
     _settings    = settings;
     _transmitter = transmitter;
     _receiver    = receiver;
     _navigation  = navigation;
 }
        public AgentMeetingViewModel(
            IAgentConnection agentConnection, 
            ISharedDataService sharedDataService,
            INavigationService navigation,
            IViewModelLocator locator,
            IPlatformServices platformServices)
        {
            _sharedDataService = sharedDataService;
            _agentConnection = agentConnection;
            NavigationPane = locator.NavigationPaneViewModel;

            var startcmd = new ReactiveCommand(this.WhenAnyValue(vm => vm.MeetingStarted, vm => vm.Meeting.VideoConf.VideoInitCompleted, vm => vm.Meeting, (started, video, mtg) => !started && mtg != null));
            _startMeetingSub = startcmd.RegisterAsyncTask(async _ =>
                                                                {
                                    MeetingStarted = true;
                                    Meeting.VideoConf.Config = await _agentConnection.StartMeeting(Meeting.Id);
                                }).Subscribe();

            var endcmd = new ReactiveCommand(this.WhenAnyValue(vm => vm.MeetingStarted, vm => vm.Meeting.VideoConf.VideoInitCompleted, (meetingStarted, videoStarted) => meetingStarted && videoStarted));
            _endMeetingSub = endcmd.RegisterAsyncAction(_ => navigation.BackCommand.Execute(null)).Subscribe();

            StartMeetingCommand = startcmd;
            EndMeetingCommand = endcmd;

            _agentConnection.ClientInMeeting.ToProperty(this, t => t.IsClientInMeeting, out _isClientInMeeting);

            
            var savePdfCmd = new ReactiveCommand(this.WhenAnyValue(vm => vm.MeetingStarted, vm => vm.Meeting.VideoConf.VideoInitCompleted, (meetingStarted, videoStarted) => meetingStarted && videoStarted));
            _pdfSub = savePdfCmd.RegisterAsyncTask(async _ =>
                                                         {
                                                            await _agentConnection.GenerateIllustration(Meeting.Id, _sharedDataService.Person);
                                               }).Subscribe();

            _pdfAvailableSub = _agentConnection.PdfAvailable.ObserveOn(RxApp.MainThreadScheduler).Subscribe(async p =>
                                                    {
                                                        var result = await _agentConnection.GetIllustrationPdfAsync(p);
                                                        await platformServices.SaveAndLaunchFile(new System.IO.MemoryStream(result), "pdf");
                                                    });

            SavePdfCommand = savePdfCmd;


            _titleSub = this.WhenAnyValue(
                vm => vm.Meeting.Client,
                (client) =>
                string.Format("Meeting with {0}",
                              client.FullName)
                )
                            .ObserveOn(RxApp.MainThreadScheduler)
                            .Subscribe(t => Title = t);

            MeetingStatus = GetMeetingStatusString(IsClientInMeeting, MeetingStarted);
            _meetingStatusSub = this.WhenAnyValue(
                         vm => vm.MeetingStarted,
                         vm => vm.IsClientInMeeting,
                         (started, clientIn) => GetMeetingStatusString(clientIn, started))
                         .ObserveOn(RxApp.MainThreadScheduler)
                         .Subscribe(t => MeetingStatus = t);

            //_titleSub = this.WhenAnyValue(
            //             vm => vm.Meeting.Client,
            //             vm => vm.MeetingStarted,
            //             vm => vm.IsClientInMeeting,
            //             (client, started, clientIn) =>
            //                 string.Format("Meeting with {0}. Started: {1} Client Joined: {2}",
            //                    client.FullName, started, clientIn)
            //             )
            //             .ObserveOn(RxApp.MainThreadScheduler)
            //             .Subscribe(t => Title = t);


            // When the meeting's active tool changes, set the Tool and page number
            // into the shared state so it'll be propagated.

            // Get an observable for the currently set tool
            var activeToolObs = this.WhenAnyValue(vm => vm.Meeting.ActiveTool)
                .Where(t => t != null);

            // Every time the tool changes, watch the new tool's CurrentPageNumber
            // for changes.
            //
            // When we get a change, convert that into a ToolIdAndPageNumber, bringing in
            // the owning tool id.
            var pageChangedObs = activeToolObs
                 .Select(t => t.WhenAnyValue(v => v.CurrentPageNumber, 
                                    p => new ToolIdAndPageNumber { ToolId = t.ToolId, PageNumber = p})
                        )
                 .Switch() // Only listen to the most recent sequence of property changes (active tool)
                 .Log(this, "Current Page Changed", t => string.Format("Tool: {0}, Page: {1}", t.ToolId, t.PageNumber));
         
            // Every time the tool changes, select the tool id and current page number
            var toolChangedObs = activeToolObs
                .Select(t => new ToolIdAndPageNumber { ToolId = t.ToolId, PageNumber = t.CurrentPageNumber })
                .Log(this, "Tool Changed", t => string.Format("Tool: {0}, Page: {1}", t.ToolId, t.PageNumber));

            
            // Merge them together - tool changes and current page of the tool
            _meetingStateSub = toolChangedObs
                .Merge(pageChangedObs)
                .Subscribe(t => sharedDataService.MeetingState.State = t);

        }
예제 #8
0
        internal static async Task LoadFormsAgentExtensions(
            Version formsVersion,
            IAgentConnection agent,
            DependencyResolver dependencyResolver,
            EvaluationContextId evaluationContextId,
            bool includePeImage)
        {
            var formsAssembly = InteractiveInstallation.Default.LocateFormsAssembly(agent.Type);

            if (string.IsNullOrWhiteSpace(formsAssembly))
            {
                return;
            }

            var deps = dependencyResolver.Resolve(new [] { new FilePath(formsAssembly) });

            // Now dig out the resolved assembly that is Xamarin.Forms.Core, and compare it to the
            // default ref.
            var resolvedFormsAssembly = deps.FirstOrDefault(d => d.AssemblyName.Name == "Xamarin.Forms.Core");

            if (resolvedFormsAssembly == null)
            {
                Log.Warning(TAG,
                            "Cannot enable Forms integration because Forms cannot be " +
                            "resolved. Check log for assembly search path issues.");
                return;
            }
            var ourVersion   = resolvedFormsAssembly.AssemblyName.Version;
            var theirVersion = formsVersion;

            if (ourVersion.Major != theirVersion.Major)
            {
                Log.Warning(
                    TAG,
                    "Assembly version mismatch between app's Xamarin.Forms.Core and" +
                    $"our referenced Xamarin.Forms.Core. Our version: {ourVersion}, " +
                    $"their version: {theirVersion}. Won't load Xamarin.Forms agent " +
                    "integration, as it probably won't work."
                    );
                return;
            }

            var assembliesToLoad = deps.Select(dep => {
                var peImage = includePeImage ? GetFileBytes(dep.Path) : null;
                var syms    = includePeImage ? GetDebugSymbolsFromAssemblyPath(dep.Path) : null;
                return(new AssemblyDefinition(
                           dep.AssemblyName,
                           dep.Path,
                           peImage: peImage,
                           debugSymbols: syms
                           ));
            }).ToArray();

            var res = await agent.Api.LoadAssembliesAsync(
                evaluationContextId,
                assembliesToLoad);

            var failed = res.LoadResults.Where(p => !p.Success);

            if (failed.Any())
            {
                var failedLoads = string.Join(", ", failed.Select(p => p.AssemblyName.Name));
                Log.Warning(
                    TAG,
                    $"Xamarin.Forms reference detected, but integration may not have" +
                    $" loaded properly. Assemblies that did not load: {failedLoads}");
            }
        }
예제 #9
0
        async Task LoadPackageIntegrationsAsync(
            IAgentConnection agent,
            InteractivePackage package,
            CancellationToken cancellationToken)
        {
            // Forms is special-cased because we own it and load the extension from our framework.
            if (PackageIdComparer.Equals(package.Identity.Id, "Xamarin.Forms"))
            {
                await WorkspaceConfiguration.LoadFormsAgentExtensions(
                    package.Identity.Version.Version,
                    agent,
                    dependencyResolver,
                    evaluationService.Id,
                    agent.IncludePeImage);
            }

            var assembliesToLoadOnAgent = new List <ResolvedAssembly> ();

            // Integration assemblies are not expected to be in a TFM directory—we look for them in
            // the `xamarin.interactive` folder inside the NuGet package.
            var packagePath = packageManager.GetPackageInstallPath(package);

            var interactivePath = packagePath.Combine("xamarin.interactive");

            if (interactivePath.DirectoryExists)
            {
                var interactiveAssemblies = interactivePath.EnumerateFiles("*.dll");
                foreach (var interactiveReference in interactiveAssemblies)
                {
                    var resolvedAssembly = dependencyResolver.ResolveWithoutReferences(interactiveReference);

                    if (HasIntegration(resolvedAssembly))
                    {
                        assembliesToLoadOnAgent.Add(resolvedAssembly);
                    }
                }
            }

            if (assembliesToLoadOnAgent.Count > 0)
            {
                var assembliesToLoad = assembliesToLoadOnAgent.Select(dep => {
                    var peImage = agent.IncludePeImage
                       ? GetFileBytes(dep.Path)
                       : null;
                    var syms = agent.IncludePeImage
                        ? GetDebugSymbolsFromAssemblyPath(dep.Path)
                        : null;
                    return(new AssemblyDefinition(
                               dep.AssemblyName,
                               dep.Path,
                               peImage: peImage,
                               debugSymbols: syms
                               ));
                }).ToArray();

                await agent.Api.LoadAssembliesAsync(
                    evaluationService.Id,
                    assembliesToLoad);
            }

            await getAgentConnectionHandler(true, cancellationToken);
        }
        public AgentMeetingViewModel(
            IAgentConnection agentConnection,
            ISharedDataService sharedDataService,
            INavigationService navigation,
            IViewModelLocator locator,
            IPlatformServices platformServices)
        {
            _sharedDataService = sharedDataService;
            _agentConnection   = agentConnection;
            NavigationPane     = locator.NavigationPaneViewModel;

            var startcmd = new ReactiveCommand(this.WhenAnyValue(vm => vm.MeetingStarted, vm => vm.Meeting.VideoConf.VideoInitCompleted, vm => vm.Meeting, (started, video, mtg) => !started && mtg != null));

            _startMeetingSub = startcmd.RegisterAsyncTask(async _ =>
            {
                MeetingStarted           = true;
                Meeting.VideoConf.Config = await _agentConnection.StartMeeting(Meeting.Id);
            }).Subscribe();

            var endcmd = new ReactiveCommand(this.WhenAnyValue(vm => vm.MeetingStarted, vm => vm.Meeting.VideoConf.VideoInitCompleted, (meetingStarted, videoStarted) => meetingStarted && videoStarted));

            _endMeetingSub = endcmd.RegisterAsyncAction(_ => navigation.BackCommand.Execute(null)).Subscribe();

            StartMeetingCommand = startcmd;
            EndMeetingCommand   = endcmd;

            _agentConnection.ClientInMeeting.ToProperty(this, t => t.IsClientInMeeting, out _isClientInMeeting);


            var savePdfCmd = new ReactiveCommand(this.WhenAnyValue(vm => vm.MeetingStarted, vm => vm.Meeting.VideoConf.VideoInitCompleted, (meetingStarted, videoStarted) => meetingStarted && videoStarted));

            _pdfSub = savePdfCmd.RegisterAsyncTask(async _ =>
            {
                await _agentConnection.GenerateIllustration(Meeting.Id, _sharedDataService.Person);
            }).Subscribe();

            _pdfAvailableSub = _agentConnection.PdfAvailable.ObserveOn(RxApp.MainThreadScheduler).Subscribe(async p =>
            {
                var result = await _agentConnection.GetIllustrationPdfAsync(p);
                await platformServices.SaveAndLaunchFile(new System.IO.MemoryStream(result), "pdf");
            });

            SavePdfCommand = savePdfCmd;


            _titleSub = this.WhenAnyValue(
                vm => vm.Meeting.Client,
                (client) =>
                string.Format("Meeting with {0}",
                              client.FullName)
                )
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(t => Title = t);

            MeetingStatus     = GetMeetingStatusString(IsClientInMeeting, MeetingStarted);
            _meetingStatusSub = this.WhenAnyValue(
                vm => vm.MeetingStarted,
                vm => vm.IsClientInMeeting,
                (started, clientIn) => GetMeetingStatusString(clientIn, started))
                                .ObserveOn(RxApp.MainThreadScheduler)
                                .Subscribe(t => MeetingStatus = t);

            //_titleSub = this.WhenAnyValue(
            //             vm => vm.Meeting.Client,
            //             vm => vm.MeetingStarted,
            //             vm => vm.IsClientInMeeting,
            //             (client, started, clientIn) =>
            //                 string.Format("Meeting with {0}. Started: {1} Client Joined: {2}",
            //                    client.FullName, started, clientIn)
            //             )
            //             .ObserveOn(RxApp.MainThreadScheduler)
            //             .Subscribe(t => Title = t);


            // When the meeting's active tool changes, set the Tool and page number
            // into the shared state so it'll be propagated.

            // Get an observable for the currently set tool
            var activeToolObs = this.WhenAnyValue(vm => vm.Meeting.ActiveTool)
                                .Where(t => t != null);

            // Every time the tool changes, watch the new tool's CurrentPageNumber
            // for changes.
            //
            // When we get a change, convert that into a ToolIdAndPageNumber, bringing in
            // the owning tool id.
            var pageChangedObs = activeToolObs
                                 .Select(t => t.WhenAnyValue(v => v.CurrentPageNumber,
                                                             p => new ToolIdAndPageNumber {
                ToolId = t.ToolId, PageNumber = p
            })
                                         )
                                 .Switch() // Only listen to the most recent sequence of property changes (active tool)
                                 .Log(this, "Current Page Changed", t => string.Format("Tool: {0}, Page: {1}", t.ToolId, t.PageNumber));

            // Every time the tool changes, select the tool id and current page number
            var toolChangedObs = activeToolObs
                                 .Select(t => new ToolIdAndPageNumber {
                ToolId = t.ToolId, PageNumber = t.CurrentPageNumber
            })
                                 .Log(this, "Tool Changed", t => string.Format("Tool: {0}, Page: {1}", t.ToolId, t.PageNumber));


            // Merge them together - tool changes and current page of the tool
            _meetingStateSub = toolChangedObs
                               .Merge(pageChangedObs)
                               .Subscribe(t => sharedDataService.MeetingState.State = t);
        }