Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[image_picker]Android update cache #4124

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
df341db
Add multiRetrieve method call
ydag Jun 30, 2021
2d1a871
Refactor finishWithSuccess to cache list of images
ydag Jun 30, 2021
30a067f
Refactor retrieveLostImage method
ydag Jun 30, 2021
01ad85e
Add new MAP_KEY_PATH_LIST key
ydag Jun 30, 2021
5a9e99f
Refactor saveTypeWithMethodCallName
ydag Jun 30, 2021
364c79d
Update saveResult method
ydag Jun 30, 2021
757da4c
Update the getCacheMap method
ydag Jun 30, 2021
3418641
Add statement to return null
ydag Jun 30, 2021
74f3990
Merge branch 'master' into image_picker/android_update_cache
ydag Jul 1, 2021
93de29f
Update CHANGELOG and version number
ydag Jul 1, 2021
9264ad9
Revert "Refactor finishWithSuccess to cache list of images"
ydag Jul 1, 2021
e585603
Refactor finishWithSuccess method
ydag Jul 1, 2021
33fb183
Update dependency version
ydag Jul 1, 2021
226ef21
Merge branch 'master' into image_picker/android_update_cache
ydag Jul 16, 2021
ec4079e
Update version and CHANGELOG
ydag Jul 16, 2021
a675352
Add unit tests
ydag Jul 16, 2021
91fd73d
Update CHANGELOG
ydag Jul 16, 2021
56c29b0
Update dependency version
ydag Jul 17, 2021
156d845
Remove unused method call
ydag Jul 21, 2021
c38ad2b
Remove unit tests from deprecated LostData
ydag Aug 20, 2021
27f87ca
Remove redundant unit test
ydag Aug 20, 2021
c567525
Refactor to assign the last item to path to avoid breaking change
ydag Aug 20, 2021
0454d80
Refactor retrieveLostData multiple files unit test
ydag Aug 20, 2021
db5d48e
Update the dependency version
ydag Aug 20, 2021
ca9c5b2
Merge branch 'master' into image_picker/android_update_cache
ydag Aug 23, 2021
e8d71e9
Fix the length call
ydag Aug 26, 2021
a1555bb
Merge branch 'master' into image_picker/android_update_cache
ydag Aug 26, 2021
933931b
Update the CHANGELOG
ydag Aug 26, 2021
c08c461
Update CHANGELOG
ydag Aug 26, 2021
a43ffeb
Add null check
ydag Aug 27, 2021
ced68ec
Add unit test
ydag Aug 27, 2021
0325f33
Update the example app
ydag Aug 27, 2021
29d9e0e
Remove redundant comment
ydag Aug 27, 2021
4ad0263
Refactor handleMultiImageResult
ydag Aug 27, 2021
0764514
Variable rename
BeMacized Aug 30, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/image_picker/image_picker/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.8.4

* Update `ImagePickerCache` to cache multiple files.

## 0.8.3+3

* Fix pickImage not returning a value on iOS when dismissing PHPicker sheet by swiping.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import io.flutter.plugin.common.MethodCall;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

class ImagePickerCache {

static final String MAP_KEY_PATH = "path";
static final String MAP_KEY_PATH_LIST = "pathList";
static final String MAP_KEY_MAX_WIDTH = "maxWidth";
static final String MAP_KEY_MAX_HEIGHT = "maxHeight";
static final String MAP_KEY_IMAGE_QUALITY = "imageQuality";
Expand Down Expand Up @@ -50,7 +54,8 @@ class ImagePickerCache {
}

void saveTypeWithMethodCallName(String methodCallName) {
if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_IMAGE)) {
if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_IMAGE)
| methodCallName.equals(ImagePickerPlugin.METHOD_CALL_MULTI_IMAGE)) {
setType("image");
} else if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_VIDEO)) {
setType("video");
Expand Down Expand Up @@ -99,11 +104,13 @@ String retrievePendingCameraMediaUriPath() {
}

void saveResult(
@Nullable String path, @Nullable String errorCode, @Nullable String errorMessage) {
@Nullable ArrayList<String> path, @Nullable String errorCode, @Nullable String errorMessage) {

Set<String> imageSet = new HashSet<>();
imageSet.addAll(path);
SharedPreferences.Editor editor = prefs.edit();
if (path != null) {
editor.putString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, path);
editor.putStringSet(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, imageSet);
}
if (errorCode != null) {
editor.putString(SHARED_PREFERENCE_ERROR_CODE_KEY, errorCode);
Expand All @@ -121,12 +128,17 @@ void clear() {
Map<String, Object> getCacheMap() {

Map<String, Object> resultMap = new HashMap<>();
ArrayList<String> pathList = new ArrayList<>();
boolean hasData = false;

if (prefs.contains(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY)) {
final String imagePathValue = prefs.getString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, "");
resultMap.put(MAP_KEY_PATH, imagePathValue);
hasData = true;
final Set<String> imagePathList =
prefs.getStringSet(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, null);
if (imagePathList != null) {
pathList.addAll(imagePathList);
resultMap.put(MAP_KEY_PATH_LIST, pathList);
hasData = true;
}
}

if (prefs.contains(SHARED_PREFERENCE_ERROR_CODE_KEY)) {
Expand Down Expand Up @@ -159,7 +171,6 @@ Map<String, Object> getCacheMap() {
resultMap.put(MAP_KEY_IMAGE_QUALITY, 100);
}
}

return resultMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,21 @@ void saveStateBeforeResult() {

void retrieveLostImage(MethodChannel.Result result) {
Map<String, Object> resultMap = cache.getCacheMap();
String path = (String) resultMap.get(cache.MAP_KEY_PATH);
if (path != null) {
Double maxWidth = (Double) resultMap.get(cache.MAP_KEY_MAX_WIDTH);
Double maxHeight = (Double) resultMap.get(cache.MAP_KEY_MAX_HEIGHT);
int imageQuality =
resultMap.get(cache.MAP_KEY_IMAGE_QUALITY) == null
? 100
: (int) resultMap.get(cache.MAP_KEY_IMAGE_QUALITY);

String newPath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality);
resultMap.put(cache.MAP_KEY_PATH, newPath);
ArrayList<String> pathList = (ArrayList<String>) resultMap.get(cache.MAP_KEY_PATH_LIST);
ArrayList<String> newPathList = new ArrayList<>();
if (pathList != null) {
for (String path : pathList) {
Double maxWidth = (Double) resultMap.get(cache.MAP_KEY_MAX_WIDTH);
Double maxHeight = (Double) resultMap.get(cache.MAP_KEY_MAX_HEIGHT);
int imageQuality =
resultMap.get(cache.MAP_KEY_IMAGE_QUALITY) == null
? 100
: (int) resultMap.get(cache.MAP_KEY_IMAGE_QUALITY);

newPathList.add(imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality));
}
resultMap.put(cache.MAP_KEY_PATH_LIST, newPathList);
resultMap.put(cache.MAP_KEY_PATH, newPathList.get(newPathList.size() - 1));
}
if (resultMap.isEmpty()) {
result.success(null);
Expand Down Expand Up @@ -558,6 +562,7 @@ public void onPathReady(String path) {
private void handleMultiImageResult(
ArrayList<String> paths, boolean shouldDeleteOriginalIfScaled) {
if (methodCall != null) {
ArrayList<String> finalPath = new ArrayList<>();
for (int i = 0; i < paths.size(); i++) {
String finalImagePath = getResizedImagePath(paths.get(i));

Expand All @@ -567,8 +572,10 @@ private void handleMultiImageResult(
&& shouldDeleteOriginalIfScaled) {
new File(paths.get(i)).delete();
}
paths.set(i, finalImagePath);
finalPath.add(i, finalImagePath);
}
finishWithListSuccess(finalPath);
} else {
finishWithListSuccess(paths);
}
}
Expand Down Expand Up @@ -615,7 +622,9 @@ private boolean setPendingMethodCallAndResult(

private void finishWithSuccess(String imagePath) {
if (pendingResult == null) {
cache.saveResult(imagePath, null, null);
ArrayList<String> pathList = new ArrayList<>();
pathList.add(imagePath);
cache.saveResult(pathList, null, null);
return;
}
pendingResult.success(imagePath);
Expand All @@ -624,9 +633,7 @@ private void finishWithSuccess(String imagePath) {

private void finishWithListSuccess(ArrayList<String> imagePaths) {
if (pendingResult == null) {
for (String imagePath : imagePaths) {
cache.saveResult(imagePath, null, null);
}
cache.saveResult(imagePaths, null, null);
return;
}
pendingResult.success(imagePaths);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
package io.flutter.plugins.imagepicker;

import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
Expand All @@ -26,9 +28,13 @@
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
Expand Down Expand Up @@ -368,6 +374,34 @@ public void onActivityResult_WhenImageTakenWithCamera_AndNoResizeNeeded_Finishes
verifyNoMoreInteractions(mockResult);
}

@Test
public void
retrieveLostImage_ShouldBeAbleToReturnLastItemFromResultMapWhenSingleFileIsRecovered() {
Map<String, Object> resultMap = new HashMap<>();
ArrayList<String> pathList = new ArrayList<>();
pathList.add("/example/first_item");
pathList.add("/example/last_item");
resultMap.put("pathList", pathList);

when(mockImageResizer.resizeImageIfNeeded(pathList.get(0), null, null, 100))
.thenReturn(pathList.get(0));
when(mockImageResizer.resizeImageIfNeeded(pathList.get(1), null, null, 100))
.thenReturn(pathList.get(1));
when(cache.getCacheMap()).thenReturn(resultMap);

MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

ImagePickerDelegate mockDelegate = createDelegate();

ArgumentCaptor<Map<String, Object>> valueCapture = ArgumentCaptor.forClass(Map.class);

doNothing().when(mockResult).success(valueCapture.capture());

mockDelegate.retrieveLostImage(mockResult);

assertEquals("/example/last_item", valueCapture.getValue().get("path"));
}

private ImagePickerDelegate createDelegate() {
return new ImagePickerDelegate(
mockActivity,
Expand Down
1 change: 1 addition & 0 deletions packages/image_picker/image_picker/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ class _MyHomePageState extends State<MyHomePage> {
isVideo = false;
setState(() {
_imageFile = response.file;
_imageFileList = response.files;
});
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/image_picker/image_picker/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for selecting images from the Android and iOS image
library, and taking new pictures with the camera.
repository: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
version: 0.8.3+3
version: 0.8.4

environment:
sdk: ">=2.12.0 <3.0.0"
Expand All @@ -25,7 +25,7 @@ dependencies:
sdk: flutter
flutter_plugin_android_lifecycle: ^2.0.1
image_picker_for_web: ^2.1.0
image_picker_platform_interface: ^2.2.0
image_picker_platform_interface: ^2.3.0

dev_dependencies:
flutter_test:
Expand Down
18 changes: 18 additions & 0 deletions packages/image_picker/image_picker/test/image_picker_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,24 @@ void main() {
expect(response.file!.path, '/example/path');
});

test('retrieveLostData should successfully retrieve multiple files',
() async {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return <String, dynamic>{
'type': 'image',
'path': '/example/path1',
'pathList': ['/example/path0', '/example/path1'],
};
});

final LostDataResponse response = await picker.retrieveLostData();
expect(response.type, RetrieveType.image);
expect(response.file, isNotNull);
expect(response.file!.path, '/example/path1');
expect(response.files!.first.path, '/example/path0');
expect(response.files!.length, 2);
});

test('retrieveLostData get error response', () async {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return <String, String>{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ class MethodChannelImagePicker extends ImagePickerPlatform {
final pathList = result['pathList'];
if (pathList != null) {
pickedFileList = [];
// In this case, multiRetrieve is invoked.
for (String path in pathList) {
pickedFileList.add(XFile(path));
}
Expand Down