/// <summary> /// Removes a <see cref="StorageFile"/> from this gallery. /// Note: Does not remove the file from the file system. /// </summary> /// <param name="mediaFilePath">The path of the file to remove.</param> public void RemoveFile(string mediaFilePath) { if (string.IsNullOrEmpty(mediaFilePath)) { return; } var mediaDataToRemove = GetMediaDataFromPath(mediaFilePath, MediaDatas); if (mediaDataToRemove == null) { return; } var index = MediaDatas.IndexOf(mediaDataToRemove); if (index != -1) { MediaDatas.RemoveAt(index); } if (App.Files.Keys.Contains(mediaDataToRemove.Title)) { App.Files.Remove(mediaDataToRemove.Title); } if (App.MediaDatas.Contains(mediaDataToRemove)) { App.MediaDatas.Remove(mediaDataToRemove); } }
public async Task EvaluateImagesOnline(IProgress <int> progress, CancellationToken cancellationToken) { // Sign into firebase. if (await FirebaseClient.Client.SignInPromptUserIfNecessary()) { // Find all media datas without annotation data. var mediaDatasWithoutAnnotationData = MediaDatas.Where(data => data.Meta.AnnotationData == null); var evaluated = 0; using (new DisposableLogger(GalleryLog.EvaluateOnlineBegin, (sw) => GalleryLog.EvaluateOnlineEnd(sw, evaluated))) { IsEvaluating = true; await mediaDatasWithoutAnnotationData.ForEachAsyncConcurrent(async media => { try { // Evaluate media thumbnail online. await media.EvaluateOnlineAsync(FirebaseClient.accessToken); } catch (Exception e) { // Log Exception. LifecycleLog.Exception(e); } finally { // Update and then report progress. evaluated++; progress.Report(evaluated); } }, cancellationToken, 5); IsEvaluating = false; } // Save online results to database. await DatabaseUtils.SaveAllMetadatasAsync(MediaDatas); } }
private async Task ProcessFileChange(StorageLibraryChange change) { // Temp variable used for instantiating StorageFiles for sorting if needed later //StorageFile newFile = null; var extension = Path.GetExtension(change.Path); switch (change.ChangeType) { // New File in the Library case StorageLibraryChangeType.Created: case StorageLibraryChangeType.MovedIntoLibrary: if (FileTypes.Extensions.Contains(extension, StringComparer.InvariantCultureIgnoreCase)) { try { // Don't add file to gallery if it already exists. if (MediaDatas.Any(data => data.MediaFile.Path == change.Path)) { return; } var mediaFile = (StorageFile)(await change.GetStorageItemAsync()); if (mediaFile == null) { return; } await AddFileAsync(ImageSize, mediaFile); } catch (Exception e) { // Log Exception. LifecycleLog.Exception(e); } } break; // Renamed file case StorageLibraryChangeType.MovedOrRenamed: if (FileTypes.Extensions.Contains(extension, StringComparer.InvariantCultureIgnoreCase)) { try { var mediaData = GetMediaDataFromPath(change.PreviousPath, MediaDatas); var newName = Path.GetFileName(change.Path); // If no MediaData could be found in Gallery for this renamed item AND there is an entry for it in App.MediaDatas (lostMediaData) // that probably means it has been renamed while the application was off, so update its path and add it to the gallery. var lostMediaFile = GetMediaFileFromPath(change.Path, _lostMediaFiles); if (mediaData == null && lostMediaFile != null) { var lostMetaData = GetMediaMetaDataFromPath(change.PreviousPath, App.DatabaseMetaDatas); // Update path on metadata. lostMetaData.MediaFilePath = change.Path; // Get current MediaData associated with metadata. var lostMediaData = await MediaData.CreateFromMediaMetadataAsync(lostMetaData); // If file can still not be found then return. if (lostMediaData == null) { return; } // Add file to gallery, including the lost media data. await AddFileAsync(ImageSize, lostMediaFile, false, lostMediaData); } else if (mediaData == null) { return; } // Don't rename file in gallery if it is already renamed if (MediaDatas.Any(data => data.Title == newName)) { return; } var mediaFile = (StorageFile)(await change.GetStorageItemAsync()); // Run on UI thread. await App.Current.NavigationService.Frame.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { // Update MediaFile of mediaData. mediaData.MediaFile = mediaFile; }); await mediaData.UpdateFileNameValuesAsync(newName); } catch (Exception e) { // Log Exception. LifecycleLog.Exception(e); } } break; // File Removed From Library case StorageLibraryChangeType.Deleted: case StorageLibraryChangeType.MovedOutOfLibrary: if (FileTypes.Extensions.Contains(extension, StringComparer.InvariantCultureIgnoreCase)) { try { // Only remove file from gallery if it exists in gallery. if (MediaDatas.Any(data => data.MediaFile.Path == change.Path)) { RemoveFile(change.Path); } } catch (Exception e) { // Log Exception. LifecycleLog.Exception(e); } } break; // Modified Contents case StorageLibraryChangeType.ContentsChanged: if (FileTypes.Extensions.Contains(extension, StringComparer.InvariantCultureIgnoreCase)) { /*newFile = (StorageFile)(await change.GetStorageItemAsync()); * var imageProps = await newFile.Properties.GetImagePropertiesAsync(); * var dateTaken = imageProps.DateTaken; * var dateModified = newFile.DateCreated; * if (DateTimeOffset.Compare(dateTaken.AddSeconds(70), dateModified) > 0) * { * // File was modified by the user * }*/ } break; // Ignored Cases case StorageLibraryChangeType.EncryptionChanged: case StorageLibraryChangeType.ContentsReplaced: case StorageLibraryChangeType.IndexingStatusChanged: default: // These are safe to ignore in this application break; } }
/// <summary> /// Adds a new <see cref="StorageFile"/> to this gallery. /// </summary> /// <param name="imageSize">The size of the pregenerated thumbnail.</param> /// <param name="mediaFile">The file to add.</param> /// <param name="mediaData">Optional, the data of the file to add.</param> /// <returns></returns> public async Task AddFileAsync(int imageSize, StorageFile mediaFile, bool evaluate = true, MediaData data = null) { if (data == null) { data = MediaData.CreateFromStorageFile(mediaFile); } if (data is GifData) { GifCount++; } if (data is VideoData) { VideoCount++; } if (data is ImageData) { ImageCount++; } var imageProp = await mediaFile.Properties.GetImagePropertiesAsync(); data.Meta.Height = (int)imageProp.Height; data.Meta.Width = (int)imageProp.Width; data.BasicProperties = await mediaFile.GetBasicPropertiesAsync(); var properties = await mediaFile.Properties.RetrievePropertiesAsync ( new string[] { "System.DateModified" } ); var lastModified = properties["System.DateModified"]; if (lastModified is DateTime lastModifiedDateTime) { data.Meta.LastModified = lastModifiedDateTime; } MediaDatas.Add(data); if (!App.Files.ContainsKey(mediaFile.Name)) { App.Files.Add(mediaFile.Name, mediaFile); } await ApplyThumbnails(imageSize, mediaFile, data); if (evaluate) { // Make sure local model is in memory. await LoadLocalModel(); // Evaluate locally. await data.EvaluateLocalAsync(_memeClassifier); // Scan for duplicates before evaluating online. var duplicateSets = new Dictionary <MediaData, List <MediaData> >(); ScanForDuplicate(duplicateSets, data); // For each set of duplicates found... foreach (var duplicates in duplicateSets.Values) { // ...have the user handle the duplicates. DuplicateModal.DuplicateQueue.Enqueue(duplicates); } // Process enqeued duplicates. await DuplicateModal.ProcessQueueAsync(); // If data or mediafile was removed during duplication handling, then don't try to evaluate online. var fileName = Path.GetFileName(data?.MediaFile?.Path); var exists = await _folder.TryGetItemAsync(fileName); if (exists == null) { return; } // Sign into firebase. if (await FirebaseClient.Client.SignInPromptUserIfNecessary()) { // Evaluate online. await data.EvaluateOnlineAsync(FirebaseClient.accessToken); } } }