/// <summary> /// Create the download controller for this file /// </summary> /// <param name="file"></param> public FileDownloadController(IFile file, IBlobCache cache = null) { File = file; Cache = cache ?? Blobs.LocalStorage; // Download or update the file. DownloadOrUpdate = ReactiveCommand.Create(); var hasCachedValue = DownloadOrUpdate .SelectMany(_ => File.GetCacheCreateTime(Cache)) .Select(dt => dt.HasValue) .Publish().RefCount(); var cacheUpdateRequired = hasCachedValue .Where(isCached => isCached) .SelectMany(_ => File.CheckForUpdate(Cache)) .Where(isNewOneEB => isNewOneEB) .Select(_ => default(Unit)) .Publish(); cacheUpdateRequired.Connect(); var firstDownloadRequired = hasCachedValue .Where(isCached => !isCached) .Select(_ => default(Unit)); var downloadInProgress = new Subject <bool>(); var downloadRequired = Observable.Merge(cacheUpdateRequired, firstDownloadRequired) .Do(_ => downloadInProgress.OnNext(true)); var downloadSuccessful = downloadRequired .LimitGlobally(goSeq => goSeq .WriteLine("Starting download...") .SelectMany(_ => Download()) .SelectMany(data => File.SaveFileInCache(data.Item1, data.Item2, Cache)) .WriteLine(" Done download and cache insert"), _gLimit) .Finally(() => downloadInProgress.OnNext(false)) .Do(_ => downloadInProgress.OnNext(false)) .Catch(Observable.Empty <Unit>()) .Select(_ => true) .Replay(1); downloadSuccessful.Connect(); FileDownloadedAndCached = downloadSuccessful.Select(_ => default(Unit)); // When we are downloading, set the IsDownloading to true. downloadInProgress .ToProperty(this, x => x.IsDownloading, out _isDownloading, false); // Track the status of the download // Note the concatenate when we combine - we very much want this to run // in order, no matter what latencies get caught up in the system. // This must be run when we are subscribed to, hence the defer. var initiallyCached = Observable.Defer(() => File.GetCacheCreateTime(Cache) .Delay(TimeSpan.FromMilliseconds(50)) .Select(dt => dt.HasValue)); Observable.Concat(initiallyCached, downloadSuccessful) .WriteLine(v => string.Format("We are doing the IsDownloaded to {0}", v)) .ToProperty(this, x => x.IsDownloaded, out _isDownloaded, false); }