private async Task <MemoryStream> GetPhoto(Attachment attachment, SignWith signWith, DateTime now) { // 1. Found in cache? if (this.imageCacheService.TryGet(attachment.Url, out MemoryStream stream)) { return(stream); } // 2. Needs download KeyValuePair <string, TemporaryFile> pair = await this.neuronService.Contracts.GetAttachment(attachment.Url, signWith, Constants.Timeouts.DownloadFile); // If download has been cancelled any time _during_ download, stop here. if (this.loadPhotosTimestamp > now) { pair.Value.Dispose(); return(null); } using (TemporaryFile file = pair.Value) { file.Reset(); MemoryStream ms = new MemoryStream(); await file.CopyToAsync(ms); // 3. Save to cache ms.Reset(); await this.imageCacheService.Add(attachment.Url, ms); ms.Reset(); return(ms); } }
/// <summary> /// Downloads one photo and stores in cache. /// </summary> /// <param name="attachment">The attachment to download.</param> /// <param name="signWith">How the requests are signed. For identity attachments, especially for attachments to an identity being created, <see cref="SignWith.CurrentKeys"/> should be used. For requesting attachments relating to a contract, <see cref="SignWith.LatestApprovedId"/> should be used.</param> /// <returns></returns> public async Task <MemoryStream> LoadOnePhoto(Attachment attachment, SignWith signWith) { try { if (!this.networkService.IsOnline || !this.neuronService.Contracts.IsOnline) { return(null); } if (attachment is null) { return(null); } MemoryStream stream = await GetPhoto(attachment, signWith, DateTime.UtcNow); stream?.Reset(); return(stream); } catch (Exception ex) { this.logService.LogException(ex); } return(null); }
private async Task LoadPhotos(Attachment[] attachments, SignWith signWith, DateTime now, Action whenDoneAction) { if (attachments is null || attachments.Length <= 0) { whenDoneAction?.Invoke(); return; } List <Attachment> attachmentsList = attachments.GetImageAttachments().ToList(); List <string> newAttachmentIds = attachmentsList.Select(x => x.Id).ToList(); if (this.attachmentIds.HasSameContentAs(newAttachmentIds)) { whenDoneAction?.Invoke(); return; } this.attachmentIds.Clear(); this.attachmentIds.AddRange(newAttachmentIds); foreach (Attachment attachment in attachmentsList) { if (this.loadPhotosTimestamp > now) { whenDoneAction?.Invoke(); return; } try { if (!this.networkService.IsOnline || !this.neuronService.Contracts.IsOnline) { continue; } MemoryStream stream = await GetPhoto(attachment, signWith, now); if (!(stream is null)) { byte[] bytes = stream.ToArray(); stream.Dispose(); this.uiDispatcher.BeginInvokeOnMainThread(() => { photos.Add(ImageSource.FromStream(() => new MemoryStream(bytes))); }); } } catch (Exception ex) { this.logService.LogException(ex); } } whenDoneAction?.Invoke(); }
/// <summary> /// Loads photos from the specified list of attachments. /// </summary> /// <param name="attachments">The attachments whose files to download.</param> /// <param name="signWith">How the requests are signed. For identity attachments, especially for attachments to an identity being created, <see cref="SignWith.CurrentKeys"/> should be used. For requesting attachments relating to a contract, <see cref="SignWith.LatestApprovedId"/> should be used.</param> /// <param name="whenDoneAction">A callback that is called when the photo load operation is done.</param> /// <returns></returns> public Task LoadPhotos(Attachment[] attachments, SignWith signWith, Action whenDoneAction = null) { return(LoadPhotos(attachments, signWith, DateTime.UtcNow, whenDoneAction)); }
public Task <byte[]> Sign(byte[] data, SignWith signWith) { AssertContractsIsAvailable(); return(contractsClient.SignAsync(data, signWith)); }
public Task <KeyValuePair <string, TemporaryFile> > GetAttachment(string url, SignWith signWith, TimeSpan timeout) { AssertContractsIsAvailable(); return(contractsClient.GetAttachmentAsync(url, signWith, (int)timeout.TotalMilliseconds)); }