Skip to content

Commit 737ad21

Browse files
authored
Merge pull request #212 from baronha/improve/preview
🦄 Improve Preview
2 parents 7698ddb + 48a33c7 commit 737ad21

21 files changed

+139
-45
lines changed

android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePicker.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ class MultipleImagePicker : HybridMultipleImagePickerSpec() {
2929
override fun openPreview(
3030
media: Array<MediaPreview>,
3131
index: Double,
32-
config: NitroPreviewConfig
32+
config: NitroPreviewConfig,
33+
onLongPress: (index: Double) -> Unit
3334
) {
34-
pickerModule.openPreview(media, index.toInt(), config)
35+
pickerModule.openPreview(media, index.toInt(), config, onLongPress)
3536
}
3637

3738
override fun openCamera(

android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt

+25-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.luck.picture.lib.config.SelectModeConfig
2020
import com.luck.picture.lib.engine.PictureSelectorEngine
2121
import com.luck.picture.lib.entity.LocalMedia
2222
import com.luck.picture.lib.interfaces.OnCustomLoadingListener
23+
import com.luck.picture.lib.interfaces.OnExternalPreviewEventListener
2324
import com.luck.picture.lib.interfaces.OnMediaEditInterceptListener
2425
import com.luck.picture.lib.interfaces.OnResultCallbackListener
2526
import com.luck.picture.lib.language.LanguageConfig
@@ -264,7 +265,12 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
264265
}
265266

266267
@ReactMethod
267-
fun openPreview(media: Array<MediaPreview>, index: Int, config: NitroPreviewConfig) {
268+
fun openPreview(
269+
media: Array<MediaPreview>,
270+
index: Int,
271+
config: NitroPreviewConfig,
272+
onLongPress: (index: Double) -> Unit
273+
) {
268274
val imageEngine = GlideEngine.createGlideEngine()
269275

270276
val assets: ArrayList<LocalMedia> = arrayListOf()
@@ -279,7 +285,8 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
279285
titleBarStyle.previewTitleBackgroundColor = Color.BLACK
280286
previewStyle.titleBarStyle = titleBarStyle
281287

282-
media.forEach { mediaItem ->
288+
media.withIndex().forEach { (index, mediaItem) ->
289+
283290
var asset: LocalMedia? = null
284291

285292
mediaItem.path?.let { path ->
@@ -297,7 +304,10 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
297304
}
298305
}
299306

300-
asset?.let { assets.add(it) }
307+
asset?.let {
308+
it.setPosition(index)
309+
assets.add(it)
310+
}
301311
}
302312

303313
PictureSelector
@@ -311,9 +321,20 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
311321
.setVideoPlayerEngine(ExoPlayerEngine())
312322
.isVideoPauseResumePlay(true)
313323
.setCustomLoadingListener(getCustomLoadingListener())
314-
.startActivityPreview(index, false, assets)
324+
.setExternalPreviewEventListener(object : OnExternalPreviewEventListener {
325+
override fun onPreviewDelete(position: Int) {
326+
//
327+
}
328+
329+
override fun onLongPressDownload(context: Context, media: LocalMedia): Boolean {
330+
onLongPress(media.position.toDouble())
331+
return true
332+
}
333+
})
334+
.startFragmentPreview(index, false, assets)
315335
}
316336

337+
317338
private fun getCustomLoadingListener(): OnCustomLoadingListener {
318339
return OnCustomLoadingListener { context -> LoadingDialog(context) }
319340
}

docs/docs/PREVIEW.mdx

+19-4
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ Preview is a simple image viewer that supports both local and remote media. It a
2222
## Usage
2323

2424
```typescript
25-
import { openPreview } from '@baronha/react-native-multiple-image-picker'
25+
import {
26+
openPreview,
27+
PreviewConfig,
28+
} from '@baronha/react-native-multiple-image-picker'
2629

27-
const cropConfig: CropConfig = {
30+
const previewConfig: PreviewConfig = {
2831
language: 'system',
2932
}
3033

@@ -49,7 +52,7 @@ const media: MediaPreview[] = [
4952
]
5053

5154
// call to preview
52-
openPreview(media, 2, cropConfig)
55+
openPreview(media, 2, previewConfig)
5356
```
5457

5558
## `MediaPreview[]`
@@ -65,12 +68,24 @@ openPreview(media, 2, cropConfig)
6568

6669
## `index`
6770

71+
default: `0`
72+
6873
The `index` parameter in the `openPreview` function specifies the initial media item to display. It is a zero-based index, meaning that `0` will display the first item in the `MediaPreview` array.
6974

70-
## `cropConfig`
75+
## `previewConfig`
7176

7277
### [`language`](/config/#language)
7378

79+
see [`language`](/config/#language)
80+
81+
### `onLongPress`
82+
83+
`onLongPress` is a callback function that is called when a long press is detected on the media item. It is a function that takes an index as an argument and returns void.
84+
85+
```typescript
86+
onLongPress: (index: number) => void
87+
```
88+
7489
## Additional Information
7590

7691
- Ensure that the media paths are accessible and correctly formatted.

example/src/index.tsx

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import React, { useState } from 'react'
22
import {
3+
ActionSheetIOS,
4+
Alert,
35
Appearance,
46
ColorSchemeName,
57
Image,
@@ -76,7 +78,42 @@ export default function App() {
7678
}
7779

7880
const onPressImage = (_: PickerResult, index: number) => {
79-
openPreview(images, index, {})
81+
openPreview(images, index, {
82+
onLongPress: () => {
83+
if (Platform.OS === 'ios') {
84+
ActionSheetIOS.showActionSheetWithOptions(
85+
{
86+
options: ['Download', 'Cancel'],
87+
cancelButtonIndex: 1,
88+
userInterfaceStyle: colorScheme ?? 'light',
89+
},
90+
(buttonIndex) => {
91+
if (buttonIndex === 0) {
92+
// Download
93+
} else if (buttonIndex === 1) {
94+
// Cancel
95+
}
96+
}
97+
)
98+
} else {
99+
Alert.alert('Options', '', [
100+
{
101+
text: 'Cancel',
102+
style: 'cancel',
103+
onPress: () => {
104+
console.log('Cancel')
105+
},
106+
},
107+
{
108+
text: 'Download',
109+
onPress: () => {
110+
console.log('Download')
111+
},
112+
},
113+
])
114+
}
115+
},
116+
})
80117
}
81118

82119
const onPicker = async () => {

example/yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -5414,10 +5414,10 @@ react-native-builder-bob@^0.30.0:
54145414
which "^2.0.2"
54155415
yargs "^17.5.1"
54165416

5417-
5418-
version "0.20.0"
5419-
resolved "https://registry.yarnpkg.com/react-native-nitro-modules/-/react-native-nitro-modules-0.20.0.tgz#3c659d4c8cbc8038b1bf35af6475e77023e70ffa"
5420-
integrity sha512-u41SaGdQ/EQFuRLFPRQ+cbEemzsARmkElXErwZlXJhr2KYmVwQMrIYGe69NuMSyvHlw3JTl09SNugt3PXa2vEQ==
5417+
react-native-nitro-modules@^0.20.1:
5418+
version "0.20.1"
5419+
resolved "https://registry.yarnpkg.com/react-native-nitro-modules/-/react-native-nitro-modules-0.20.1.tgz#99568818b90e364f1e08b5341a7868eca3762333"
5420+
integrity sha512-ffa8GbnLBs7irEx1ZCl7WdHzzA5uj4ngh7hIWbeUfBs8m2iAn+byowOJWHKmO+RA2hp9dVwTxHYSBOqIvTVvHA==
54215421

54225422
54235423
version "0.76.5"

ios/HybridMultipleImagePicker+Preview.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import HXPhotoPicker
99

1010
extension HybridMultipleImagePicker {
11-
func openPreview(media: [MediaPreview], index: Double, config: NitroPreviewConfig) throws {
11+
func openPreview(media: [MediaPreview], index: Double, config: NitroPreviewConfig, onLongPress: @escaping ((Double) -> Void)) throws {
1212
var previewConfig = HXPhotoPicker.PhotoBrowser.Configuration()
1313
previewConfig.showDelete = false
1414

@@ -66,7 +66,10 @@ extension HybridMultipleImagePicker {
6666
HXPhotoPicker.PhotoBrowser.show(
6767
assets,
6868
pageIndex: Int(index),
69-
config: previewConfig
69+
config: previewConfig,
70+
longPressHandler: { index, _, _ in
71+
onLongPress(Double(index))
72+
}
7073
)
7174
}
7275
}

nitrogen/generated/android/MultipleImagePickerOnLoad.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ int initialize(JavaVM* vm) {
3333
margelo::nitro::multipleimagepicker::JFunc_void_double::registerNatives();
3434
margelo::nitro::multipleimagepicker::JFunc_void_CropResult::registerNatives();
3535
margelo::nitro::multipleimagepicker::JFunc_void_double::registerNatives();
36+
margelo::nitro::multipleimagepicker::JFunc_void_double::registerNatives();
3637
margelo::nitro::multipleimagepicker::JFunc_void_CameraResult::registerNatives();
3738
margelo::nitro::multipleimagepicker::JFunc_void_double::registerNatives();
3839

nitrogen/generated/android/c++/JFunc_void_double.hpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ namespace margelo::nitro::multipleimagepicker {
1818

1919
/**
2020
* C++ representation of the callback Func_void_double.
21-
* This is a Kotlin `(reject: Double) -> Unit`, backed by a `std::function<...>`.
21+
* This is a Kotlin `(index: Double) -> Unit`, backed by a `std::function<...>`.
2222
*/
2323
struct JFunc_void_double final: public jni::HybridClass<JFunc_void_double> {
2424
public:
25-
static jni::local_ref<JFunc_void_double::javaobject> fromCpp(const std::function<void(double /* reject */)>& func) {
25+
static jni::local_ref<JFunc_void_double::javaobject> fromCpp(const std::function<void(double /* index */)>& func) {
2626
return JFunc_void_double::newObjectCxxArgs(func);
2727
}
2828

2929
public:
30-
void call(double reject) {
31-
_func(reject);
30+
void call(double index) {
31+
_func(index);
3232
}
3333

3434
public:
@@ -38,11 +38,11 @@ namespace margelo::nitro::multipleimagepicker {
3838
}
3939

4040
private:
41-
explicit JFunc_void_double(const std::function<void(double /* reject */)>& func): _func(func) { }
41+
explicit JFunc_void_double(const std::function<void(double /* index */)>& func): _func(func) { }
4242

4343
private:
4444
friend HybridBase;
45-
std::function<void(double /* reject */)> _func;
45+
std::function<void(double /* index */)> _func;
4646
};
4747

4848
} // namespace margelo::nitro::multipleimagepicker

nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ namespace margelo::nitro::multipleimagepicker {
126126
static const auto method = _javaPart->getClass()->getMethod<void(jni::alias_ref<jni::JString> /* image */, jni::alias_ref<JNitroCropConfig> /* config */, jni::alias_ref<JFunc_void_CropResult::javaobject> /* resolved */, jni::alias_ref<JFunc_void_double::javaobject> /* rejected */)>("openCrop");
127127
method(_javaPart, jni::make_jstring(image), JNitroCropConfig::fromCpp(config), JFunc_void_CropResult::fromCpp(resolved), JFunc_void_double::fromCpp(rejected));
128128
}
129-
void JHybridMultipleImagePickerSpec::openPreview(const std::vector<MediaPreview>& media, double index, const NitroPreviewConfig& config) {
130-
static const auto method = _javaPart->getClass()->getMethod<void(jni::alias_ref<jni::JArrayClass<JMediaPreview>> /* media */, double /* index */, jni::alias_ref<JNitroPreviewConfig> /* config */)>("openPreview");
129+
void JHybridMultipleImagePickerSpec::openPreview(const std::vector<MediaPreview>& media, double index, const NitroPreviewConfig& config, const std::function<void(double /* index */)>& onLongPress) {
130+
static const auto method = _javaPart->getClass()->getMethod<void(jni::alias_ref<jni::JArrayClass<JMediaPreview>> /* media */, double /* index */, jni::alias_ref<JNitroPreviewConfig> /* config */, jni::alias_ref<JFunc_void_double::javaobject> /* onLongPress */)>("openPreview");
131131
method(_javaPart, [&]() {
132132
size_t __size = media.size();
133133
jni::local_ref<jni::JArrayClass<JMediaPreview>> __array = jni::JArrayClass<JMediaPreview>::newArray(__size);
@@ -136,7 +136,7 @@ namespace margelo::nitro::multipleimagepicker {
136136
__array->setElement(__i, *JMediaPreview::fromCpp(__element));
137137
}
138138
return __array;
139-
}(), index, JNitroPreviewConfig::fromCpp(config));
139+
}(), index, JNitroPreviewConfig::fromCpp(config), JFunc_void_double::fromCpp(onLongPress));
140140
}
141141
void JHybridMultipleImagePickerSpec::openCamera(const NitroCameraConfig& config, const std::function<void(const CameraResult& /* result */)>& resolved, const std::function<void(double /* reject */)>& rejected) {
142142
static const auto method = _javaPart->getClass()->getMethod<void(jni::alias_ref<JNitroCameraConfig> /* config */, jni::alias_ref<JFunc_void_CameraResult::javaobject> /* resolved */, jni::alias_ref<JFunc_void_double::javaobject> /* rejected */)>("openCamera");

nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace margelo::nitro::multipleimagepicker {
5353
// Methods
5454
void openPicker(const NitroConfig& config, const std::function<void(const std::vector<PickerResult>& /* result */)>& resolved, const std::function<void(double /* reject */)>& rejected) override;
5555
void openCrop(const std::string& image, const NitroCropConfig& config, const std::function<void(const CropResult& /* result */)>& resolved, const std::function<void(double /* reject */)>& rejected) override;
56-
void openPreview(const std::vector<MediaPreview>& media, double index, const NitroPreviewConfig& config) override;
56+
void openPreview(const std::vector<MediaPreview>& media, double index, const NitroPreviewConfig& config, const std::function<void(double /* index */)>& onLongPress) override;
5757
void openCamera(const NitroCameraConfig& config, const std::function<void(const CameraResult& /* result */)>& resolved, const std::function<void(double /* reject */)>& rejected) override;
5858

5959
private:

nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Func_void_double.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import com.margelo.nitro.core.*
1414
import dalvik.annotation.optimization.FastNative
1515

1616
/**
17-
* Represents the JavaScript callback `(reject: number) => void`.
17+
* Represents the JavaScript callback `(index: number) => void`.
1818
* This is implemented in C++, via a `std::function<...>`.
1919
*/
2020
@DoNotStrip
@@ -35,12 +35,12 @@ class Func_void_double {
3535
* Converts this function to a Kotlin Lambda.
3636
* This exists purely as syntactic sugar, and has minimal runtime overhead.
3737
*/
38-
fun toLambda(): (reject: Double) -> Unit = this::call
38+
fun toLambda(): (index: Double) -> Unit = this::call
3939

4040
/**
4141
* Call the given JS callback.
4242
* @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.
4343
*/
4444
@FastNative
45-
external fun call(reject: Double): Unit
45+
external fun call(index: Double): Unit
4646
}

nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/HybridMultipleImagePickerSpec.kt

+8-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,14 @@ abstract class HybridMultipleImagePickerSpec: HybridObject() {
6565

6666
@DoNotStrip
6767
@Keep
68-
abstract fun openPreview(media: Array<MediaPreview>, index: Double, config: NitroPreviewConfig): Unit
68+
abstract fun openPreview(media: Array<MediaPreview>, index: Double, config: NitroPreviewConfig, onLongPress: (index: Double) -> Unit): Unit
69+
70+
@DoNotStrip
71+
@Keep
72+
private fun openPreview(media: Array<MediaPreview>, index: Double, config: NitroPreviewConfig, onLongPress: Func_void_double): Unit {
73+
val __result = openPreview(media, index, config, onLongPress.toLambda())
74+
return __result
75+
}
6976

7077
@DoNotStrip
7178
@Keep

nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ namespace margelo::nitro::multipleimagepicker {
127127
std::rethrow_exception(__result.error());
128128
}
129129
}
130-
inline void openPreview(const std::vector<MediaPreview>& media, double index, const NitroPreviewConfig& config) override {
131-
auto __result = _swiftPart.openPreview(media, std::forward<decltype(index)>(index), config);
130+
inline void openPreview(const std::vector<MediaPreview>& media, double index, const NitroPreviewConfig& config, const std::function<void(double /* index */)>& onLongPress) override {
131+
auto __result = _swiftPart.openPreview(media, std::forward<decltype(index)>(index), config, onLongPress);
132132
if (__result.hasError()) [[unlikely]] {
133133
std::rethrow_exception(__result.error());
134134
}

nitrogen/generated/ios/swift/Func_void_double.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@
88
import NitroModules
99

1010
/**
11-
* Wraps a Swift `((_ reject: Double) -> Void)` as a class.
11+
* Wraps a Swift `((_ index: Double) -> Void)` as a class.
1212
* This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.
1313
*/
1414
public final class Func_void_double {
1515
public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift
1616

17-
private let closure: ((_ reject: Double) -> Void)
17+
private let closure: ((_ index: Double) -> Void)
1818

19-
public init(_ closure: @escaping ((_ reject: Double) -> Void)) {
19+
public init(_ closure: @escaping ((_ index: Double) -> Void)) {
2020
self.closure = closure
2121
}
2222

2323
@inline(__always)
24-
public func call(reject: Double) -> Void {
25-
self.closure(reject)
24+
public func call(index: Double) -> Void {
25+
self.closure(index)
2626
}
2727

2828
/**

nitrogen/generated/ios/swift/HybridMultipleImagePickerSpec.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public protocol HybridMultipleImagePickerSpec_protocol: AnyObject {
1616
// Methods
1717
func openPicker(config: NitroConfig, resolved: @escaping ((_ result: [PickerResult]) -> Void), rejected: @escaping ((_ reject: Double) -> Void)) throws -> Void
1818
func openCrop(image: String, config: NitroCropConfig, resolved: @escaping ((_ result: CropResult) -> Void), rejected: @escaping ((_ reject: Double) -> Void)) throws -> Void
19-
func openPreview(media: [MediaPreview], index: Double, config: NitroPreviewConfig) throws -> Void
19+
func openPreview(media: [MediaPreview], index: Double, config: NitroPreviewConfig, onLongPress: @escaping ((_ index: Double) -> Void)) throws -> Void
2020
func openCamera(config: NitroCameraConfig, resolved: @escaping ((_ result: CameraResult) -> Void), rejected: @escaping ((_ reject: Double) -> Void)) throws -> Void
2121
}
2222

nitrogen/generated/ios/swift/HybridMultipleImagePickerSpec_cxx.swift

+7-2
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,14 @@ public class HybridMultipleImagePickerSpec_cxx {
149149
}
150150

151151
@inline(__always)
152-
public func openPreview(media: bridge.std__vector_MediaPreview_, index: Double, config: NitroPreviewConfig) -> bridge.Result_void_ {
152+
public func openPreview(media: bridge.std__vector_MediaPreview_, index: Double, config: NitroPreviewConfig, onLongPress: bridge.Func_void_double) -> bridge.Result_void_ {
153153
do {
154-
try self.__implementation.openPreview(media: media.map({ __item in __item }), index: index, config: config)
154+
try self.__implementation.openPreview(media: media.map({ __item in __item }), index: index, config: config, onLongPress: { () -> ((Double) -> Void) in
155+
let __wrappedFunction = bridge.wrap_Func_void_double(onLongPress)
156+
return { (__index: Double) -> Void in
157+
__wrappedFunction.call(__index)
158+
}
159+
}())
155160
return bridge.create_Result_void_()
156161
} catch (let __error) {
157162
let __exceptionPtr = __error.toCpp()

0 commit comments

Comments
 (0)