diff --git a/CHANGELOG.md b/CHANGELOG.md index 10f41b309..4b2b266f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [62.1.4] +- [Gallery] Fixed issue where only one of multiple image rotations was retained. + ## [62.1.3] - [Dictation][Android] The dictation microphone now shows above the keyboard when the focused field is in a modal or a bottom sheet, instead of being hidden behind it. diff --git a/src/library/DIPS.Mobile.UI/API/Camera/Gallery/BottomSheet/GalleryBottomSheet.cs b/src/library/DIPS.Mobile.UI/API/Camera/Gallery/BottomSheet/GalleryBottomSheet.cs index 3b6c56c67..094edc257 100644 --- a/src/library/DIPS.Mobile.UI/API/Camera/Gallery/BottomSheet/GalleryBottomSheet.cs +++ b/src/library/DIPS.Mobile.UI/API/Camera/Gallery/BottomSheet/GalleryBottomSheet.cs @@ -30,7 +30,7 @@ namespace DIPS.Mobile.UI.API.Camera.Gallery.BottomSheet; internal partial class GalleryBottomSheet : ContentPage, IGalleryDefaultStateObserver, IImageEditStateObserver { private readonly Action m_onRemoveImage; - private readonly Action m_updateImages; + private readonly Action> m_updateImages; private readonly Button m_navigatePreviousImageButton; private readonly Button m_navigateNextImageButton; private readonly ContentView m_carouselViewWrapperView = new(); @@ -54,7 +54,7 @@ internal partial class GalleryBottomSheet : ContentPage, IGalleryDefaultStateObs private int? m_positionBeforeRemoval; private int? m_positionBeforeEdit; - public GalleryBottomSheet(List images, int startingIndex, Action onRemoveImage, Action updateImages) + public GalleryBottomSheet(List images, int startingIndex, Action onRemoveImage, Action> updateImages) { Background = Microsoft.Maui.Graphics.Colors.Black; @@ -432,7 +432,7 @@ void IImageEditStateObserver.OnSaveButtonTapped() Images[m_carouselView!.Position] = m_currentlyRotatedCaptureImageDisplayed; m_currentlyCapturedImageDisplayed = m_currentlyRotatedCaptureImageDisplayed; GoToDefaultState(); - m_updateImages.Invoke(); + m_updateImages.Invoke(Images); } void IImageEditStateObserver.OnCancelButtonTapped() diff --git a/src/library/DIPS.Mobile.UI/API/Camera/Gallery/GalleryThumbnails.cs b/src/library/DIPS.Mobile.UI/API/Camera/Gallery/GalleryThumbnails.cs index e87c300a7..78d3a2eec 100644 --- a/src/library/DIPS.Mobile.UI/API/Camera/Gallery/GalleryThumbnails.cs +++ b/src/library/DIPS.Mobile.UI/API/Camera/Gallery/GalleryThumbnails.cs @@ -61,10 +61,9 @@ private void OnTappedImage(int imageIndex) Shell.Current.Navigation.PushModalAsync(new NavigationPage(new GalleryBottomSheet(Images, imageIndex, OnRemoveImage, UpdateImages))); } - private void UpdateImages() + internal void UpdateImages(IReadOnlyList images) { - var copyOfImages = Images.ToList(); - Images = copyOfImages; + Images = images.ToList(); } private void OnRemoveImage(int imageIndex) diff --git a/src/tests/unittests/API/Camera/Gallery/GalleryThumbnailsTests.cs b/src/tests/unittests/API/Camera/Gallery/GalleryThumbnailsTests.cs new file mode 100644 index 000000000..436a14b30 --- /dev/null +++ b/src/tests/unittests/API/Camera/Gallery/GalleryThumbnailsTests.cs @@ -0,0 +1,26 @@ +using System.Linq; +using DIPS.Mobile.UI.API.Camera.Gallery; +using DIPS.Mobile.UI.API.Camera.ImageCapturing; + +namespace DIPS.Mobile.UI.UnitTests.API.Camera.Gallery; + +public class GalleryThumbnailsTests +{ + [Fact] + public void UpdateImages_MultipleEditsFromOpenGallery_RetainsEveryEdit() + { + var firstImage = new CapturedImage(); + var secondImage = new CapturedImage(); + var firstEditedImage = new CapturedImage(); + var secondEditedImage = new CapturedImage(); + var imagesBeingEdited = new List { firstImage, secondImage }; + var gallery = new GalleryThumbnails { Images = imagesBeingEdited.ToList() }; + + imagesBeingEdited[0] = firstEditedImage; + gallery.UpdateImages(imagesBeingEdited); + imagesBeingEdited[1] = secondEditedImage; + gallery.UpdateImages(imagesBeingEdited); + + gallery.Images.Should().Equal(firstEditedImage, secondEditedImage); + } +} diff --git a/wiki/Media/ImageCapture.md b/wiki/Media/ImageCapture.md index 78b685ac9..03f95f681 100644 --- a/wiki/Media/ImageCapture.md +++ b/wiki/Media/ImageCapture.md @@ -106,6 +106,17 @@ private void OnImageCaptured(CapturedImage capturedImage) In multi-capture this method is called once per image, in capture order. Pair it with `OnImageRemoved` so your list reflects every add and every removal the user makes. +## Reviewing captured images after capture + +Use `GalleryThumbnails` to display a list of captured images after the camera closes: + +```xaml + +``` + +Tapping a thumbnail opens a full-screen preview where the user can browse, rotate, inspect, or remove images. Saving a rotation updates `Images` immediately. Multiple images can be rotated during the same preview session, and every saved rotation is retained in the bound list. + ## Handling camera failures ```csharp