/// <summary> /// Load image data from a local file and set it to current image data. /// </summary> /// <param name="item">Target item</param> internal async Task LoadSetAsync(FileItemViewModel item) { if ((_tokenSourceLoading != null) && !_tokenSourceLoading.IsCancellationRequested) { _tokenSourceLoading.TryCancel(); } try { _tokenSourceLoading = new CancellationTokenSourcePlus(); byte[] data = null; if (item.IsAvailableLocal && item.CanLoadDataLocal) data = await FileAddition.ReadAllBytesAsync(ComposeLocalPath(item), _tokenSourceLoading.Token); CurrentItem = item; CurrentImageData = data; } catch (OperationCanceledException) { // None. } catch (FileNotFoundException) { item.Status = FileStatus.NotCopied; item.IsAliveLocal = false; } catch (IOException) { item.IsAvailableLocal = false; } catch (Exception ex) { Debug.WriteLine("Failed to load image data from local file. {0}", ex); throw new UnexpectedException("Failed to load image data from local file.", ex); } finally { if (_tokenSourceLoading != null) _tokenSourceLoading.Dispose(); } }
/// <summary> /// Check files in FlashAir card. /// </summary> private async Task CheckFileBaseAsync() { OperationStatus = Resources.OperationStatus_Checking; try { _tokenSourceWorking = new CancellationTokenSourcePlus(); // Check firmware version. _card.FirmwareVersion = await FileManager.GetFirmwareVersionAsync(_tokenSourceWorking.Token); // Check CID. if (_card.CanGetCid) _card.Cid = await FileManager.GetCidAsync(_tokenSourceWorking.Token); // Check SSID and check if PC is connected to FlashAir card by a wireless connection. _card.Ssid = await FileManager.GetSsidAsync(_tokenSourceWorking.Token); _card.IsWirelessConnected = NetworkChecker.IsWirelessNetworkConnected(_card.Ssid); // Get all items. var fileListNew = (await FileManager.GetFileListRootAsync(_card, _tokenSourceWorking.Token)) .Select(fileItem => new FileItemViewModel(fileItem)) .ToList(); fileListNew.Sort(); // Record time stamp of write event. if (_card.CanGetWriteTimeStamp) _card.WriteTimeStamp = await FileManager.GetWriteTimeStampAsync(_tokenSourceWorking.Token); // Check if any sample is in old items. var isSample = FileListCore.Any(x => x.Size == 0); // Check if FlashAir card is changed. bool isChanged; if (_card.IsChanged.HasValue) { isChanged = _card.IsChanged.Value; } else { var signatures = FileListCore.Select(x => x.Signature).ToArray(); isChanged = !fileListNew.Select(x => x.Signature).Any(x => signatures.Contains(x)); } if (isSample || isChanged) FileListCore.Clear(); // Check old items. foreach (var itemOld in FileListCore) { var itemSame = fileListNew.FirstOrDefault(x => x.FilePath.Equals(itemOld.FilePath, StringComparison.OrdinalIgnoreCase) && (x.Size == itemOld.Size)); if (itemSame != null) { fileListNew.Remove(itemSame); itemOld.IsAliveRemote = true; itemOld.FileItem = itemSame.FileItem; continue; } itemOld.IsAliveRemote = false; } // Add new items. var isLeadOff = true; foreach (var itemNew in fileListNew) { if (isLeadOff) { FileListCoreViewIndex = FileListCoreView.IndexOf(itemNew); isLeadOff = false; } itemNew.IsAliveRemote = true; FileListCore.Insert(itemNew); // Customized Insert method } // Check all local files. foreach (var item in FileListCore) { var info = GetFileInfoLocal(item); item.IsAliveLocal = IsAliveLocal(info, item.Size); item.IsAvailableLocal = IsAvailableLocal(info); item.Status = item.IsAliveLocal ? FileStatus.Copied : FileStatus.NotCopied; } // Manage lost items. var itemsLost = FileListCore.Where(x => !x.IsAliveRemote).ToArray(); if (itemsLost.Any()) { if (Settings.Current.MovesFileToRecycle) { foreach (var item in itemsLost) { if (!item.IsDescendant || (item.Status != FileStatus.Copied)) continue; try { Recycle.MoveToRecycle(ComposeLocalPath(item)); } catch (Exception ex) { Debug.WriteLine("Failed to move a file to Recycle. {0}", ex); item.Status = FileStatus.NotCopied; continue; } item.Status = FileStatus.Recycled; } } for (int i = itemsLost.Length - 1; i >= 0; i--) { var item = itemsLost[i]; if (item.IsDescendant && ((item.Status == FileStatus.Copied) || (item.Status == FileStatus.Recycled))) continue; FileListCore.Remove(item); } } // Get thumbnails (from local). foreach (var item in FileListCore.Where(x => x.IsTarget && !x.HasThumbnail)) { if (!item.IsAliveLocal || !item.IsAvailableLocal || !item.CanLoadDataLocal) continue; _tokenSourceWorking.Token.ThrowIfCancellationRequested(); try { if (item.CanReadExif) item.Thumbnail = await ImageManager.ReadThumbnailAsync(ComposeLocalPath(item)); else if (item.CanLoadDataLocal) item.Thumbnail = await ImageManager.CreateThumbnailAsync(ComposeLocalPath(item)); } catch (FileNotFoundException) { item.Status = FileStatus.NotCopied; item.IsAliveLocal = false; } catch (IOException) { item.IsAvailableLocal = false; } catch (ImageNotSupportedException) { item.CanLoadDataLocal = false; } } // Get thumbnails (from remote). foreach (var item in FileListCore.Where(x => x.IsTarget && !x.HasThumbnail)) { if (!item.IsAliveRemote || !item.CanGetThumbnailRemote) continue; if (!_card.CanGetThumbnail) continue; _tokenSourceWorking.Token.ThrowIfCancellationRequested(); try { item.Thumbnail = await FileManager.GetThumbnailAsync(item.FilePath, _card, _tokenSourceWorking.Token); } catch (RemoteFileThumbnailFailedException) { item.CanGetThumbnailRemote = false; _card.RecordThumbnailFailedPath(item.FilePath); } } OperationStatus = Resources.OperationStatus_CheckCompleted; } finally { FileListCoreViewIndex = -1; // No selection if (_tokenSourceWorking != null) _tokenSourceWorking.Dispose(); } }
/// <summary> /// Copy files from FlashAir card. /// </summary> /// <param name="progress">Progress</param> private async Task CopyFileBaseAsync(IProgress<ProgressInfo> progress) { CopyStartTime = DateTime.Now; _copyFileCount = 0; if (!FileListCore.Any(x => x.IsTarget && (x.Status == FileStatus.ToBeCopied))) { OperationStatus = Resources.OperationStatus_NoFileToBeCopied; return; } OperationStatus = Resources.OperationStatus_Copying; try { _tokenSourceWorking = new CancellationTokenSourcePlus(); // Check CID. if (_card.CanGetCid) { if (await FileManager.GetCidAsync(_tokenSourceWorking.Token) != _card.Cid) throw new CardChangedException(); } // Check if upload.cgi is disabled. if (Settings.Current.DeleteOnCopy && _card.CanGetUpload) { _card.Upload = await FileManager.GetUploadAsync(_tokenSourceWorking.Token); if (_card.IsUploadDisabled) throw new CardUploadDisabledException(); } while (true) { var item = FileListCore.FirstOrDefault(x => x.IsTarget && (x.Status == FileStatus.ToBeCopied)); if (item == null) break; // Copy completed. _tokenSourceWorking.Token.ThrowIfCancellationRequested(); try { item.Status = FileStatus.Copying; FileListCoreViewIndex = FileListCoreView.IndexOf(item); var localPath = ComposeLocalPath(item); var localDirectory = Path.GetDirectoryName(localPath); if (!String.IsNullOrEmpty(localDirectory) && !Directory.Exists(localDirectory)) Directory.CreateDirectory(localDirectory); var data = await FileManager.GetSaveFileAsync(item.FilePath, localPath, item.Size, item.Date, item.CanReadExif, progress, _card, _tokenSourceWorking.Token); CurrentItem = item; CurrentImageData = data; if (!item.HasThumbnail) { try { if (item.CanReadExif) item.Thumbnail = await ImageManager.ReadThumbnailAsync(CurrentImageData); else if (item.CanLoadDataLocal) item.Thumbnail = await ImageManager.CreateThumbnailAsync(CurrentImageData); } catch (ImageNotSupportedException) { item.CanLoadDataLocal = false; } } item.CopiedTime = DateTime.Now; item.IsAliveLocal = true; item.IsAvailableLocal = true; item.Status = FileStatus.Copied; _copyFileCount++; } catch (RemoteFileNotFoundException) { item.IsAliveRemote = false; } catch (RemoteFileInvalidException) { item.Status = FileStatus.Weird; } catch { item.Status = FileStatus.ToBeCopied; // Revert to status before copying. throw; } if (Settings.Current.DeleteOnCopy && !item.IsReadOnly && IsAliveLocal(item)) { await FileManager.DeleteFileAsync(item.FilePath, _tokenSourceWorking.Token); } } OperationStatus = String.Format(Resources.OperationStatus_CopyCompleted, _copyFileCount, (int)(DateTime.Now - CopyStartTime).TotalSeconds); } finally { FileListCoreViewIndex = -1; // No selection if (_tokenSourceWorking != null) _tokenSourceWorking.Dispose(); } }