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"; }
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))); }
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 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); }
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}"); } }
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); }