public async Task DashboardViewModelTests_ForgetProxyWithConsent() { await this.viewModel.ActivateAsync(); Assert.IsNotNull( await this.proxyProvider.ProxyFolder.GetFileAsync(this.proxyFileName) ); int originalCount = this.viewModel.StoredFiles.Count; StoredFileDescriptor proxyDescriptor = this.viewModel.StoredFiles.Last(); Assert.IsTrue(proxyDescriptor.IsAppOwned); this.promptingService.Result = true; await proxyDescriptor.ForgetCommand.ExecuteAsync(proxyDescriptor); Assert.AreEqual(originalCount - 1, this.viewModel.StoredFiles.Count); // XXX - This shouldn't be needed but it seems GetFileAsync succeeds after a DeleteAsync without a short wait await AwaitableTimeout(200); try { StorageFile proxyFile = await this.proxyProvider.ProxyFolder.GetFileAsync(this.proxyFileName); Assert.Fail("The file should have been deleted"); } catch (FileNotFoundException) { // Pass test } }
/// <summary> /// Handles primary taps/clicks on recent databases. /// Attempts to open the files. /// </summary> /// <param name="sender">The GridView.</param> /// <param name="e">EventArgs for the click.</param> private async void RecentDatabases_ItemClick(object sender, ItemClickEventArgs e) { StoredFileDescriptor tappedDescriptor = e.ClickedItem as StoredFileDescriptor; DebugHelper.Assert(tappedDescriptor != null); await AttemptToLoadRecentDatabase(tappedDescriptor); }
/// <summary> /// Activates the dashboard ViewModel by resolving each stored file /// to update the descriptors and remove bad bookmarks. /// </summary> /// <returns>A Task representing the activation.</returns> public override async Task ActivateAsync() { await base.ActivateAsync(); List <StoredFileDescriptor> badDescriptors = new List <StoredFileDescriptor>(); foreach (StoredFileDescriptor descriptor in StoredFiles) { WireDescriptorEvents(descriptor); ITestableFile file = await GetFileAsync(descriptor); if (file != null) { descriptor.IsAppOwned = await this.proxyProvider.PathIsInScopeAsync(file.AsIStorageItem2); } else { badDescriptors.Add(descriptor); } } Task[] forgetTasks = new Task[badDescriptors.Count]; for (int i = 0; i < forgetTasks.Length; i++) { StoredFileDescriptor descriptor = badDescriptors[i]; forgetTasks[i] = descriptor.ForgetCommand.ExecuteAsync(null); } await Task.WhenAll(forgetTasks); }
/// <summary> /// Adds predefined handles for the Export and Update requested events. /// </summary> /// <param name="sender">The descriptor to wire.</param> protected virtual void WireDescriptorEvents(StoredFileDescriptor sender) { DebugHelper.Assert(sender != null); sender.ForgetRequested += ForgetRequestedHandler; sender.ExportRequested += ExportRequestedHandler; sender.UpdateRequested += UpdateRequestedHandler; }
/// <summary> /// Helper to hook up UI events from a <see cref="StoredFileDescriptor"/>. /// </summary> /// <param name="descriptor">The descriptor to hook up events for.</param> protected override void WireDescriptorEvents(StoredFileDescriptor descriptor) { base.WireDescriptorEvents(descriptor); descriptor.OpenRequested += (s, e) => { FireRequestOpenFile(s); }; }
public async Task DashboardViewModelTests_GetFile() { await this.viewModel.ActivateAsync(); StoredFileDescriptor descriptor = this.viewModel.StoredFiles[0]; IStorageFile file = (await this.viewModel.GetFileAsync(descriptor)).AsIStorageFile; Assert.IsNotNull(file, "Fetched file should not be null"); Assert.AreEqual(descriptor.Metadata, file.Name, "Correct file should be fetched."); }
/// <summary> /// Attempts to fetch an IStorageFile based on a descriptor. /// </summary> /// <param name="descriptor">A previously stored reference to a file.</param> /// <returns>An IStorageFile if possible, else null.</returns> public async Task <ITestableFile> GetFileAsync(StoredFileDescriptor descriptor) { try { return(await this.accessList.GetFileAsync(descriptor.Token).ConfigureAwait(false)); } catch (FileNotFoundException) { return(null); } }
public async Task DashboardViewModelTests_ForgetWithoutConsent() { await this.viewModel.ActivateAsync(); int originalCount = this.viewModel.StoredFiles.Count; StoredFileDescriptor descriptor = this.viewModel.StoredFiles.First(); descriptor.IsAppOwned = true; this.promptingService.Result = false; await descriptor.ForgetCommand.ExecuteAsync(descriptor); Assert.AreEqual(originalCount, this.viewModel.StoredFiles.Count); }
/// <summary> /// Asynchronously clears and adds back <see cref="StoredFileDescriptor"/> to updated /// <see cref="StoredFiles"/>. /// </summary> /// <returns></returns> private async Task ResyncFiles() { ClearAllFiles(); foreach (ITestableFile file in await this.proxyProvider.GetKnownProxiesAsync() .ConfigureAwait(false) ) { var allStoredFiles = this.accessList.Entries .Select(e => new { Entry = e, FileTask = this.accessList.GetFileAsync(e.Token) }); AccessListEntry?entry = null; foreach (var stored in allStoredFiles) { ITestableFile storedFile = await stored.FileTask.ConfigureAwait(false); if (storedFile.AsIStorageItem.Path == file.AsIStorageItem.Path) { entry = stored.Entry; } } // If we couldn't find the file in the access list, add it. // This asserts because these lists shouldn't be out of sync in the first place. if (!entry.HasValue) { string metadata = file.AsIStorageItem.Name; entry = new AccessListEntry { Metadata = metadata, Token = this.accessList.Add(file, metadata) }; DebugHelper.Assert(false); } StoredFileDescriptor descriptor = new StoredFileDescriptor( entry.Value ); descriptor.IsAppOwned = await this.proxyProvider.PathIsInScopeAsync(file.AsIStorageItem2); // Wire events WireDescriptorEvents(descriptor); AddFile(descriptor); } }
/// <summary> /// Attempts to load a recent database from a StoredFileDescriptor. /// </summary> /// <param name="descriptor">The descriptor to load.</param> private async Task AttemptToLoadRecentDatabase(StoredFileDescriptor descriptor) { if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } ITestableFile storedFile = await ViewModel.GetFileAsync(descriptor); if (storedFile == null) { Debug.WriteLine("Warning: Could not fetch StorageFile. Forgetting descriptor."); descriptor.ForgetCommand.Execute(null); } else { Debug.WriteLine("Retrieved StorageFile from descriptor."); NavigateToOpenedFile(await DatabaseCandidateFactory.AssembleAsync(storedFile)); } }
/// <summary> /// Intended to be registered as a handler for <see cref="StoredFileDescriptor.ForgetRequested"/>. /// </summary> /// <param name="sender">The descriptor being deleted.</param> /// <param name="e">Unused.</param> private async void ForgetRequestedHandler(StoredFileDescriptor sender, RequestForgetDescriptorEventArgs args) { // Ask the user whether they consent/understand the deletion if (!sender.IsAppOwned || await this.deletePrompter.PromptYesNoAsync()) { // Delete from access list if appropriate if (this.accessList.ContainsItem(sender.Token)) { this.accessList.Remove(sender.Token); } // Update ViewModel's data list this.data.Remove(sender); // If this represents a proxy, delete it if (sender.IsAppOwned) { // Delete the proxy await this.proxyProvider.TryDeleteProxyAsync(sender.Metadata); } } }
/// <summary> /// Asynchronously exports the specified file to the specified location. /// </summary> /// <param name="file">The file to export.</param> /// <param name="targetLocation">The location to export to.</param> /// <returns>A task that resolves to the exported file location.</returns> public async Task <ITestableFile> ExportAsync(StoredFileDescriptor file) { if (file == null) { throw new ArgumentNullException(nameof(file)); } // If this is not a valid descriptor it should be forgotten ITestableFile fileToCopy = await this.accessList.GetFileAsync(file.Token).ConfigureAwait(false); if (fileToCopy == null) { await file.ForgetCommand.ExecuteAsync(null).ConfigureAwait(false); return(null); } ITestableFile savedFile = await this.fileService.PickFileForSaveAsync(file.Metadata) .ConfigureAwait(false); if (savedFile != null) { try { await fileToCopy.AsIStorageFile.CopyAndReplaceAsync(savedFile.AsIStorageFile) .AsTask().ConfigureAwait(false); } catch (Exception ex) { DebugHelper.Assert(false, "Should not have problems exporting files"); DebugHelper.Trace($"Failed to export: {ex}"); return(null); } } return(savedFile); }
public async Task DashboardViewModelTests_ForgetFiles() { await this.viewModel.ActivateAsync(); Assert.IsTrue( this.viewModel.StoredFiles.Count > 0, "RecentDatabases should not start empty." ); this.promptingService.Result = true; while (this.viewModel.StoredFiles.Count > 0) { int count = this.viewModel.StoredFiles.Count; StoredFileDescriptor selectedFile = this.viewModel.StoredFiles[0]; Assert.IsTrue( selectedFile.ForgetCommand.CanExecute(selectedFile), "ForgetCommand should be executable as long as recent databases remain." ); Assert.IsTrue( this.accessList.ContainsItem(selectedFile.Token), "AccessList should contain the tokens in the ViewMode list." ); await selectedFile.ForgetCommand.ExecuteAsync(selectedFile); Assert.AreEqual( count - 1, this.viewModel.StoredFiles.Count, "Forgetting a database should cause the count to decrement." ); Assert.IsFalse( this.accessList.ContainsItem(selectedFile.Token), "Forgetting a database should remove it from the AccessList." ); } }
/// <summary> /// Intended to be registered as a handler for <see cref="StoredFileDescriptor.UpdateRequested"/>. /// </summary> /// <param name="sender">The descriptor being updated.</param> /// <param name="args">EventArgs used to request the file to update with.</param> private async void UpdateRequestedHandler(StoredFileDescriptor sender, RequestUpdateDescriptorEventArgs args) { if (!sender.IsAppOwned) { DebugHelper.Assert(false, "This should be impossible"); return; } ITestableFile file = await this.fileService.PickFileForOpenAsync().ConfigureAwait(false); if (file != null) { DebugHelper.Trace($"Updating cached file"); ITestableFile storedFile = await GetFileAsync(sender).ConfigureAwait(false); if (await CheckShouldProceedWithUpdateAsync(storedFile, file).ConfigureAwait(false)) { await file.AsIStorageFile.CopyAndReplaceAsync(storedFile.AsIStorageFile) .AsTask().ConfigureAwait(false); await storedFile.ClearReadOnlyFlag().ConfigureAwait(false); } } }
/// <summary> /// Helper to fire <see cref="RequestOpenFile"/>. /// </summary> /// <param name="file">The file to open.</param> private void FireRequestOpenFile(StoredFileDescriptor file) { RequestOpenFile?.Invoke(this, file); }
/// <summary> /// Intended to be registered as a handler for <see cref="StoredFileDescriptor.ExportRequested"/>. /// </summary> /// <param name="sender">The descriptor being exported.</param> /// <param name="e">Unused.</param> private void ExportRequestedHandler(StoredFileDescriptor sender, EventArgs e) { this.exportService.ExportAsync(sender); }
public async void RequestOpenFileHandler(IDashboardViewModel sender, StoredFileDescriptor eventArgs) { await AttemptToLoadRecentDatabase(eventArgs); }
/// <summary> /// Initializes the event args. /// </summary> /// <param name="descriptor">The descriptor being deleted.</param> public RequestUpdateDescriptorEventArgs(StoredFileDescriptor descriptor) { this.descriptor = descriptor ?? throw new ArgumentNullException(nameof(descriptor)); }
/// <summary> /// Adds the specified file to the internal list for tracking. /// </summary> /// <param name="descriptor">The descriptor to add.</param> protected void AddFile(StoredFileDescriptor descriptor) { DebugHelper.Assert(descriptor != null); this.data.Add(descriptor); }
private void Descriptor_ForgetRequested(StoredFileDescriptor sender, EventArgClasses.RequestForgetDescriptorEventArgs args) { throw new NotImplementedException(); }
/// <summary> /// Not implemented. /// </summary> /// <param name="descriptor">A previously stored reference to a file.</param> /// <returns>An IStorageFile if possible, else null.</returns> public Task <ITestableFile> GetFileAsync(StoredFileDescriptor descriptor) { return(null); }
/// <summary> /// Initializes the event args. /// </summary> /// <param name="descriptor">The descriptor being deleted.</param> public RequestForgetDescriptorEventArgs(StoredFileDescriptor descriptor) : base(true) { this.descriptor = descriptor ?? throw new ArgumentNullException(nameof(descriptor)); }