zkit-ui 2.0.5 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryLayoutSupport.java → NativeImagePreviewLayoutSupport.java} +12 -12
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryMediaItem.java → NativeImagePreviewMediaItem.java} +2 -2
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewModule.kt +43 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryPagerAdapter.java → NativeImagePreviewPagerAdapter.java} +18 -18
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GallerySharedElementGeometry.java → NativeImagePreviewSharedElementGeometry.java} +2 -2
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSharedElementNames.java +39 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GallerySharedElementState.java → NativeImagePreviewSharedElementState.java} +4 -4
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GallerySourceViewRegistry.java → NativeImagePreviewSourceViewRegistry.java} +2 -2
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryTransitionSnapshotView.java → NativeImagePreviewTransitionSnapshotView.java} +3 -3
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryVideoPlayerView.java → NativeImagePreviewVideoPlayerView.java} +7 -7
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GaleriaView.kt → NativeImagePreviewView.kt} +18 -18
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryViewerOverlayView.java → NativeImagePreviewViewerOverlayView.java} +49 -49
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryViewerPageView.java → NativeImagePreviewViewerPageView.java} +27 -27
- package/android/src/main/java/cn/fontree/zkit/ui/preview/{GalleryViewerTransitionController.java → NativeImagePreviewViewerTransitionController.java} +22 -22
- package/dist/ui/Button/index.d.ts +1 -1
- package/dist/ui/Button/index.d.ts.map +1 -1
- package/dist/ui/Button/index.js +18 -3
- package/dist/ui/NativeImagePreview/NativeImagePreview.js +6 -6
- package/dist/ui/NativeImagePreview/NativeImagePreview.web.d.ts +1 -0
- package/dist/ui/NativeImagePreview/NativeImagePreview.web.d.ts.map +1 -1
- package/dist/ui/NativeImagePreview/NativeImagePreview.web.js +105 -11
- package/dist/ui/NativeImagePreview/context.d.ts +1 -1
- package/dist/ui/NativeImagePreview/context.d.ts.map +1 -1
- package/dist/ui/NativeImagePreview/types.d.ts +3 -1
- package/dist/ui/NativeImagePreview/types.d.ts.map +1 -1
- package/dist/ui/NativeImagePreview/utils.d.ts.map +1 -1
- package/dist/ui/NativeImagePreview/utils.js +1 -0
- package/dist/ui/NativeImagePreview/web/geometry.d.ts +20 -0
- package/dist/ui/NativeImagePreview/web/geometry.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/geometry.js +121 -0
- package/dist/ui/NativeImagePreview/web/media.d.ts +6 -0
- package/dist/ui/NativeImagePreview/web/media.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/media.js +90 -0
- package/dist/ui/NativeImagePreview/web/styles.css +137 -0
- package/dist/ui/NativeImagePreview/web/transition.d.ts +15 -0
- package/dist/ui/NativeImagePreview/web/transition.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/transition.js +77 -0
- package/dist/ui/NativeImagePreview/web/types.d.ts +74 -0
- package/dist/ui/NativeImagePreview/web/types.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/types.js +3 -0
- package/dist/ui/NativeImagePreview/web/viewer.d.ts +104 -0
- package/dist/ui/NativeImagePreview/web/viewer.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/viewer.js +894 -0
- package/expo-module.config.json +2 -2
- package/ios/{GalleryViewer/GaleriaImageLoader.swift → NativeImagePreview/NativeImagePreviewImageLoader.swift} +7 -7
- package/ios/NativeImagePreview/NativeImagePreviewImageViewInteraction.swift +245 -0
- package/ios/{GalleryViewer/GaleriaLayoutSupport.swift → NativeImagePreview/NativeImagePreviewLayoutSupport.swift} +19 -19
- package/ios/NativeImagePreview/NativeImagePreviewMedia.swift +28 -0
- package/ios/NativeImagePreview/NativeImagePreviewSourceViewRegistry.swift +80 -0
- package/ios/{GalleryViewer/GaleriaVideoPlayerView.swift → NativeImagePreview/NativeImagePreviewVideoPlayerView.swift} +1 -1
- package/ios/{GalleryViewer/GaleriaViewerConfiguration.swift → NativeImagePreview/NativeImagePreviewViewerConfiguration.swift} +7 -7
- package/ios/{GalleryViewer/GaleriaViewerController.swift → NativeImagePreview/NativeImagePreviewViewerController.swift} +36 -36
- package/ios/{GalleryViewer/GaleriaViewerPageView.swift → NativeImagePreview/NativeImagePreviewViewerPageView.swift} +33 -33
- package/ios/{GalleryViewer/GaleriaViewerTransitionCoordinator.swift → NativeImagePreview/NativeImagePreviewViewerTransitionCoordinator.swift} +16 -16
- package/ios/{GaleriaModule.swift → NativeImagePreviewModule.swift} +4 -4
- package/ios/{GaleriaView.swift → NativeImagePreviewView.swift} +26 -27
- package/package.json +18 -12
- package/src/services/ImagePreviewService/README.md +1 -1
- package/src/types.d.ts +1 -0
- package/src/ui/Button/README.md +1 -1
- package/src/ui/Button/index.tsx +27 -7
- package/src/ui/NativeImagePreview/NativeImagePreview.tsx +7 -7
- package/src/ui/NativeImagePreview/NativeImagePreview.web.tsx +175 -11
- package/src/ui/NativeImagePreview/README.md +3 -3
- package/src/ui/NativeImagePreview/context.tsx +1 -1
- package/src/ui/NativeImagePreview/types.ts +3 -1
- package/src/ui/NativeImagePreview/utils.ts +1 -0
- package/src/ui/NativeImagePreview/web/geometry.ts +134 -0
- package/src/ui/NativeImagePreview/web/media.ts +91 -0
- package/src/ui/NativeImagePreview/web/styles.css +137 -0
- package/src/ui/NativeImagePreview/web/transition.ts +111 -0
- package/src/ui/NativeImagePreview/web/types.ts +88 -0
- package/src/ui/NativeImagePreview/web/viewer.ts +1024 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/GaleriaModule.kt +0 -43
- package/android/src/main/java/cn/fontree/zkit/ui/preview/GallerySharedElementNames.java +0 -39
- package/ios/GalleryViewer/GaleriaImageViewInteraction.swift +0 -245
- package/ios/GalleryViewer/GaleriaMedia.swift +0 -28
- package/ios/GalleryViewer/GaleriaSourceViewRegistry.swift +0 -80
- /package/android/src/main/res/layout/{galeria_player_view.xml → native_image_preview_player_view.xml} +0 -0
package/expo-module.config.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"platforms": ["apple", "android"],
|
|
3
3
|
"apple": {
|
|
4
|
-
"modules": ["
|
|
4
|
+
"modules": ["NativeImagePreviewModule"],
|
|
5
5
|
"podspecPath": "zkit-ui.podspec",
|
|
6
6
|
"swiftModuleName": "zkit_ui"
|
|
7
7
|
},
|
|
8
8
|
"android": {
|
|
9
|
-
"modules": ["cn.fontree.zkit.ui.preview.
|
|
9
|
+
"modules": ["cn.fontree.zkit.ui.preview.NativeImagePreviewModule"]
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -4,7 +4,7 @@ import UIKit
|
|
|
4
4
|
import SDWebImage
|
|
5
5
|
#endif
|
|
6
6
|
|
|
7
|
-
public protocol
|
|
7
|
+
public protocol NativeImagePreviewImageLoading {
|
|
8
8
|
func loadImage(
|
|
9
9
|
_ url: URL,
|
|
10
10
|
placeholder: UIImage?,
|
|
@@ -13,7 +13,7 @@ public protocol GaleriaImageLoading {
|
|
|
13
13
|
)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
public struct
|
|
16
|
+
public struct NativeImagePreviewURLSessionImageLoader: NativeImagePreviewImageLoading {
|
|
17
17
|
public init() {}
|
|
18
18
|
|
|
19
19
|
public func loadImage(
|
|
@@ -41,7 +41,7 @@ public struct GaleriaURLSessionImageLoader: GaleriaImageLoading {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
#if canImport(SDWebImage)
|
|
44
|
-
struct
|
|
44
|
+
struct NativeImagePreviewSDWebImageLoader: NativeImagePreviewImageLoading {
|
|
45
45
|
func loadImage(
|
|
46
46
|
_ url: URL,
|
|
47
47
|
placeholder: UIImage?,
|
|
@@ -62,12 +62,12 @@ struct GaleriaSDWebImageLoader: GaleriaImageLoading {
|
|
|
62
62
|
}
|
|
63
63
|
#endif
|
|
64
64
|
|
|
65
|
-
public enum
|
|
66
|
-
public static func makeDefault() ->
|
|
65
|
+
public enum NativeImagePreviewImageLoaderFactory {
|
|
66
|
+
public static func makeDefault() -> NativeImagePreviewImageLoading {
|
|
67
67
|
#if canImport(SDWebImage)
|
|
68
|
-
return
|
|
68
|
+
return NativeImagePreviewSDWebImageLoader()
|
|
69
69
|
#else
|
|
70
|
-
return
|
|
70
|
+
return NativeImagePreviewURLSessionImageLoader()
|
|
71
71
|
#endif
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import ObjectiveC
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
extension UIImageView {
|
|
5
|
+
private struct NativeImagePreviewAnchorRegistration {
|
|
6
|
+
let previewGroupId: String
|
|
7
|
+
let index: Int
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
private final class NativeImagePreviewTapGestureRecognizer: UITapGestureRecognizer {
|
|
11
|
+
weak var fromViewController: UIViewController?
|
|
12
|
+
var dataSource: NativeImagePreviewDataSource?
|
|
13
|
+
var imageLoader: NativeImagePreviewImageLoading?
|
|
14
|
+
var initialIndex = 0
|
|
15
|
+
var previewGroupId: String?
|
|
16
|
+
var configuration = NativeImagePreviewViewerConfiguration()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private static var anchorRegistrationKey: UInt8 = 0
|
|
20
|
+
private static var gestureRecognizerKey: UInt8 = 0
|
|
21
|
+
|
|
22
|
+
private var topMostHostViewController: UIViewController? {
|
|
23
|
+
let keyWindow: UIWindow? = {
|
|
24
|
+
if #available(iOS 13.0, *) {
|
|
25
|
+
let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
|
|
26
|
+
let activeScene = scenes.first(where: { $0.activationState == .foregroundActive }) ?? scenes.first
|
|
27
|
+
return activeScene?.windows.first(where: { $0.isKeyWindow }) ?? activeScene?.windows.first
|
|
28
|
+
} else {
|
|
29
|
+
return UIApplication.shared.windows.first(where: { $0.isKeyWindow }) ?? UIApplication.shared.windows.first
|
|
30
|
+
}
|
|
31
|
+
}()
|
|
32
|
+
guard let rootViewController = keyWindow?.rootViewController else { return nil }
|
|
33
|
+
return rootViewController.presentedViewController ?? rootViewController
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public func setupNativeImagePreviewViewer(
|
|
37
|
+
configuration: NativeImagePreviewViewerConfiguration = NativeImagePreviewViewerConfiguration(),
|
|
38
|
+
from viewController: UIViewController? = nil,
|
|
39
|
+
imageLoader: NativeImagePreviewImageLoading? = nil,
|
|
40
|
+
previewGroupId: String? = nil
|
|
41
|
+
) {
|
|
42
|
+
configureNativeImagePreviewViewer(
|
|
43
|
+
dataSource: NativeImagePreviewArrayDataSource(items: [.image(image)]),
|
|
44
|
+
initialIndex: 0,
|
|
45
|
+
configuration: configuration,
|
|
46
|
+
from: viewController,
|
|
47
|
+
imageLoader: imageLoader,
|
|
48
|
+
previewGroupId: previewGroupId
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public func setupNativeImagePreviewViewer(
|
|
53
|
+
url: URL,
|
|
54
|
+
initialIndex: Int = 0,
|
|
55
|
+
placeholder: UIImage? = nil,
|
|
56
|
+
configuration: NativeImagePreviewViewerConfiguration = NativeImagePreviewViewerConfiguration(),
|
|
57
|
+
from viewController: UIViewController? = nil,
|
|
58
|
+
imageLoader: NativeImagePreviewImageLoading? = nil,
|
|
59
|
+
previewGroupId: String? = nil
|
|
60
|
+
) {
|
|
61
|
+
configureNativeImagePreviewViewer(
|
|
62
|
+
dataSource: NativeImagePreviewArrayDataSource(items: [.imageURL(url, placeholder: placeholder)]),
|
|
63
|
+
initialIndex: initialIndex,
|
|
64
|
+
configuration: configuration,
|
|
65
|
+
from: viewController,
|
|
66
|
+
imageLoader: imageLoader,
|
|
67
|
+
previewGroupId: previewGroupId
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public func setupNativeImagePreviewViewer(
|
|
72
|
+
images: [UIImage],
|
|
73
|
+
initialIndex: Int = 0,
|
|
74
|
+
configuration: NativeImagePreviewViewerConfiguration = NativeImagePreviewViewerConfiguration(),
|
|
75
|
+
from viewController: UIViewController? = nil,
|
|
76
|
+
imageLoader: NativeImagePreviewImageLoading? = nil,
|
|
77
|
+
previewGroupId: String? = nil
|
|
78
|
+
) {
|
|
79
|
+
let items = images.map { NativeImagePreviewMediaItem.image($0) }
|
|
80
|
+
configureNativeImagePreviewViewer(
|
|
81
|
+
dataSource: NativeImagePreviewArrayDataSource(items: items),
|
|
82
|
+
initialIndex: initialIndex,
|
|
83
|
+
configuration: configuration,
|
|
84
|
+
from: viewController,
|
|
85
|
+
imageLoader: imageLoader,
|
|
86
|
+
previewGroupId: previewGroupId
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public func setupNativeImagePreviewViewer(
|
|
91
|
+
urls: [URL],
|
|
92
|
+
initialIndex: Int = 0,
|
|
93
|
+
placeholder: UIImage? = nil,
|
|
94
|
+
configuration: NativeImagePreviewViewerConfiguration = NativeImagePreviewViewerConfiguration(),
|
|
95
|
+
from viewController: UIViewController? = nil,
|
|
96
|
+
imageLoader: NativeImagePreviewImageLoading? = nil,
|
|
97
|
+
previewGroupId: String? = nil
|
|
98
|
+
) {
|
|
99
|
+
let items = urls.map { NativeImagePreviewMediaItem.imageURL($0, placeholder: placeholder) }
|
|
100
|
+
configureNativeImagePreviewViewer(
|
|
101
|
+
dataSource: NativeImagePreviewArrayDataSource(items: items),
|
|
102
|
+
initialIndex: initialIndex,
|
|
103
|
+
configuration: configuration,
|
|
104
|
+
from: viewController,
|
|
105
|
+
imageLoader: imageLoader,
|
|
106
|
+
previewGroupId: previewGroupId
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public func setupNativeImagePreviewViewer(
|
|
111
|
+
dataSource: NativeImagePreviewDataSource,
|
|
112
|
+
initialIndex: Int = 0,
|
|
113
|
+
configuration: NativeImagePreviewViewerConfiguration = NativeImagePreviewViewerConfiguration(),
|
|
114
|
+
from viewController: UIViewController? = nil,
|
|
115
|
+
imageLoader: NativeImagePreviewImageLoading? = nil,
|
|
116
|
+
previewGroupId: String? = nil
|
|
117
|
+
) {
|
|
118
|
+
configureNativeImagePreviewViewer(
|
|
119
|
+
dataSource: dataSource,
|
|
120
|
+
initialIndex: initialIndex,
|
|
121
|
+
configuration: configuration,
|
|
122
|
+
from: viewController,
|
|
123
|
+
imageLoader: imageLoader,
|
|
124
|
+
previewGroupId: previewGroupId
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func removeNativeImagePreviewViewerInteraction() {
|
|
129
|
+
if let recognizer = nativeImagePreviewTapGestureRecognizer {
|
|
130
|
+
removeGestureRecognizer(recognizer)
|
|
131
|
+
}
|
|
132
|
+
nativeImagePreviewTapGestureRecognizer = nil
|
|
133
|
+
|
|
134
|
+
if let registration = nativeImagePreviewAnchorRegistration {
|
|
135
|
+
NativeImagePreviewSourceViewRegistry.shared.unregister(
|
|
136
|
+
self,
|
|
137
|
+
previewGroupId: registration.previewGroupId,
|
|
138
|
+
index: registration.index
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
nativeImagePreviewAnchorRegistration = nil
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private func configureNativeImagePreviewViewer(
|
|
145
|
+
dataSource: NativeImagePreviewDataSource?,
|
|
146
|
+
initialIndex: Int,
|
|
147
|
+
configuration: NativeImagePreviewViewerConfiguration,
|
|
148
|
+
from viewController: UIViewController?,
|
|
149
|
+
imageLoader: NativeImagePreviewImageLoading?,
|
|
150
|
+
previewGroupId: String?
|
|
151
|
+
) {
|
|
152
|
+
let recognizer = nativeImagePreviewTapGestureRecognizer ?? {
|
|
153
|
+
let recognizer = NativeImagePreviewTapGestureRecognizer(target: self, action: #selector(showNativeImagePreviewViewer(_:)))
|
|
154
|
+
recognizer.numberOfTouchesRequired = 1
|
|
155
|
+
recognizer.numberOfTapsRequired = 1
|
|
156
|
+
nativeImagePreviewTapGestureRecognizer = recognizer
|
|
157
|
+
return recognizer
|
|
158
|
+
}()
|
|
159
|
+
|
|
160
|
+
isUserInteractionEnabled = true
|
|
161
|
+
clipsToBounds = true
|
|
162
|
+
|
|
163
|
+
recognizer.dataSource = dataSource
|
|
164
|
+
recognizer.imageLoader = imageLoader
|
|
165
|
+
recognizer.initialIndex = initialIndex
|
|
166
|
+
recognizer.previewGroupId = previewGroupId
|
|
167
|
+
recognizer.configuration = configuration
|
|
168
|
+
recognizer.fromViewController = viewController
|
|
169
|
+
|
|
170
|
+
if recognizer.view !== self {
|
|
171
|
+
addGestureRecognizer(recognizer)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
updateNativeImagePreviewAnchorRegistration(previewGroupId: previewGroupId, index: initialIndex)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private var nativeImagePreviewTapGestureRecognizer: NativeImagePreviewTapGestureRecognizer? {
|
|
178
|
+
get {
|
|
179
|
+
objc_getAssociatedObject(self, &Self.gestureRecognizerKey) as? NativeImagePreviewTapGestureRecognizer
|
|
180
|
+
}
|
|
181
|
+
set {
|
|
182
|
+
objc_setAssociatedObject(
|
|
183
|
+
self,
|
|
184
|
+
&Self.gestureRecognizerKey,
|
|
185
|
+
newValue,
|
|
186
|
+
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private var nativeImagePreviewAnchorRegistration: NativeImagePreviewAnchorRegistration? {
|
|
192
|
+
get {
|
|
193
|
+
objc_getAssociatedObject(self, &Self.anchorRegistrationKey) as? NativeImagePreviewAnchorRegistration
|
|
194
|
+
}
|
|
195
|
+
set {
|
|
196
|
+
objc_setAssociatedObject(
|
|
197
|
+
self,
|
|
198
|
+
&Self.anchorRegistrationKey,
|
|
199
|
+
newValue,
|
|
200
|
+
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@objc
|
|
206
|
+
private func showNativeImagePreviewViewer(_ recognizer: NativeImagePreviewTapGestureRecognizer) {
|
|
207
|
+
guard let sourceView = recognizer.view as? UIImageView else { return }
|
|
208
|
+
let resolvedImageLoader = recognizer.imageLoader ?? NativeImagePreviewImageLoaderFactory.makeDefault()
|
|
209
|
+
let viewerController = NativeImagePreviewViewerController(
|
|
210
|
+
sourceView: sourceView,
|
|
211
|
+
dataSource: recognizer.dataSource,
|
|
212
|
+
imageLoader: resolvedImageLoader,
|
|
213
|
+
configuration: recognizer.configuration,
|
|
214
|
+
initialIndex: recognizer.initialIndex,
|
|
215
|
+
previewGroupId: recognizer.previewGroupId
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
let rootViewController = recognizer.fromViewController ?? topMostHostViewController
|
|
219
|
+
let presenter = rootViewController.flatMap(topMostPresentedController(from:))
|
|
220
|
+
presenter?.present(viewerController, animated: false)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private func topMostPresentedController(from rootViewController: UIViewController) -> UIViewController {
|
|
224
|
+
var controller = rootViewController
|
|
225
|
+
while let presented = controller.presentedViewController {
|
|
226
|
+
controller = presented
|
|
227
|
+
}
|
|
228
|
+
return controller
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private func updateNativeImagePreviewAnchorRegistration(previewGroupId: String?, index: Int) {
|
|
232
|
+
if let existing = nativeImagePreviewAnchorRegistration {
|
|
233
|
+
NativeImagePreviewSourceViewRegistry.shared.unregister(
|
|
234
|
+
self,
|
|
235
|
+
previewGroupId: existing.previewGroupId,
|
|
236
|
+
index: existing.index
|
|
237
|
+
)
|
|
238
|
+
nativeImagePreviewAnchorRegistration = nil
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
guard let previewGroupId = previewGroupId, previewGroupId.isEmpty == false else { return }
|
|
242
|
+
NativeImagePreviewSourceViewRegistry.shared.register(self, previewGroupId: previewGroupId, index: index)
|
|
243
|
+
nativeImagePreviewAnchorRegistration = NativeImagePreviewAnchorRegistration(previewGroupId: previewGroupId, index: index)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
|
|
3
|
-
struct
|
|
3
|
+
struct NativeImagePreviewSharedElementGeometry {
|
|
4
4
|
let visibleFrameInWindow: CGRect
|
|
5
5
|
let contentFrameInVisibleBounds: CGRect
|
|
6
6
|
let cornerRadius: CGFloat
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
struct
|
|
9
|
+
struct NativeImagePreviewSharedElementState {
|
|
10
10
|
let image: UIImage
|
|
11
|
-
let geometry:
|
|
11
|
+
let geometry: NativeImagePreviewSharedElementGeometry
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
extension CGRect {
|
|
15
|
-
func
|
|
15
|
+
func nativeImagePreviewPixelAligned(scale: CGFloat) -> CGRect {
|
|
16
16
|
guard scale > 0 else { return self }
|
|
17
17
|
return CGRect(
|
|
18
18
|
x: (origin.x * scale).rounded() / scale,
|
|
@@ -22,7 +22,7 @@ extension CGRect {
|
|
|
22
22
|
)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
func
|
|
25
|
+
func nativeImagePreviewApproximatelyEquals(_ other: CGRect, tolerance: CGFloat = 0.5) -> Bool {
|
|
26
26
|
abs(minX - other.minX) <= tolerance
|
|
27
27
|
&& abs(minY - other.minY) <= tolerance
|
|
28
28
|
&& abs(width - other.width) <= tolerance
|
|
@@ -30,18 +30,18 @@ extension CGRect {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
extension
|
|
34
|
-
func
|
|
35
|
-
|
|
36
|
-
visibleFrameInWindow: visibleFrameInWindow.
|
|
37
|
-
contentFrameInVisibleBounds: contentFrameInVisibleBounds.
|
|
33
|
+
extension NativeImagePreviewSharedElementGeometry {
|
|
34
|
+
func nativeImagePreviewPixelAligned(scale: CGFloat) -> NativeImagePreviewSharedElementGeometry {
|
|
35
|
+
NativeImagePreviewSharedElementGeometry(
|
|
36
|
+
visibleFrameInWindow: visibleFrameInWindow.nativeImagePreviewPixelAligned(scale: scale),
|
|
37
|
+
contentFrameInVisibleBounds: contentFrameInVisibleBounds.nativeImagePreviewPixelAligned(scale: scale),
|
|
38
38
|
cornerRadius: (cornerRadius * scale).rounded() / scale
|
|
39
39
|
)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
func approximatelyEquals(_ other:
|
|
43
|
-
visibleFrameInWindow.
|
|
44
|
-
&& contentFrameInVisibleBounds.
|
|
42
|
+
func approximatelyEquals(_ other: NativeImagePreviewSharedElementGeometry, tolerance: CGFloat = 0.5) -> Bool {
|
|
43
|
+
visibleFrameInWindow.nativeImagePreviewApproximatelyEquals(other.visibleFrameInWindow, tolerance: tolerance)
|
|
44
|
+
&& contentFrameInVisibleBounds.nativeImagePreviewApproximatelyEquals(
|
|
45
45
|
other.contentFrameInVisibleBounds,
|
|
46
46
|
tolerance: tolerance
|
|
47
47
|
)
|
|
@@ -49,8 +49,8 @@ extension GaleriaSharedElementGeometry {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
extension
|
|
53
|
-
func approximatelyEquals(_ other:
|
|
52
|
+
extension NativeImagePreviewSharedElementState {
|
|
53
|
+
func approximatelyEquals(_ other: NativeImagePreviewSharedElementState, tolerance: CGFloat = 0.5) -> Bool {
|
|
54
54
|
geometry.approximatelyEquals(other.geometry, tolerance: tolerance)
|
|
55
55
|
&& abs(image.size.width - other.image.size.width) <= tolerance
|
|
56
56
|
&& abs(image.size.height - other.image.size.height) <= tolerance
|
|
@@ -113,7 +113,7 @@ extension UIImageView {
|
|
|
113
113
|
return convert(contentFrame, to: nil)
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
func
|
|
116
|
+
func nativeImagePreviewSharedElementState(clippingFrameInWindow: CGRect? = nil) -> NativeImagePreviewSharedElementState? {
|
|
117
117
|
guard let image = image else { return nil }
|
|
118
118
|
guard image.size.width > 0, image.size.height > 0 else { return nil }
|
|
119
119
|
|
|
@@ -126,7 +126,7 @@ extension UIImageView {
|
|
|
126
126
|
visibleFrame = clippingFrame
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
let geometry =
|
|
129
|
+
let geometry = NativeImagePreviewSharedElementGeometry(
|
|
130
130
|
visibleFrameInWindow: visibleFrame,
|
|
131
131
|
contentFrameInVisibleBounds: contentFrame.offsetBy(
|
|
132
132
|
dx: -visibleFrame.minX,
|
|
@@ -135,9 +135,9 @@ extension UIImageView {
|
|
|
135
135
|
cornerRadius: (clipsToBounds || layer.masksToBounds) ? layer.cornerRadius : 0
|
|
136
136
|
)
|
|
137
137
|
let scale = window?.screen.scale ?? UIScreen.main.scale
|
|
138
|
-
return
|
|
138
|
+
return NativeImagePreviewSharedElementState(
|
|
139
139
|
image: image,
|
|
140
|
-
geometry: geometry.
|
|
140
|
+
geometry: geometry.nativeImagePreviewPixelAligned(scale: scale)
|
|
141
141
|
)
|
|
142
142
|
}
|
|
143
143
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
public enum NativeImagePreviewMediaItem {
|
|
4
|
+
case image(UIImage?)
|
|
5
|
+
case imageURL(URL, placeholder: UIImage?)
|
|
6
|
+
case video(url: URL, poster: URL?)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public protocol NativeImagePreviewDataSource: AnyObject {
|
|
10
|
+
func numberOfItems() -> Int
|
|
11
|
+
func item(at index: Int) -> NativeImagePreviewMediaItem
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public final class NativeImagePreviewArrayDataSource: NativeImagePreviewDataSource {
|
|
15
|
+
private let items: [NativeImagePreviewMediaItem]
|
|
16
|
+
|
|
17
|
+
public init(items: [NativeImagePreviewMediaItem]) {
|
|
18
|
+
self.items = items
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public func numberOfItems() -> Int {
|
|
22
|
+
items.count
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public func item(at index: Int) -> NativeImagePreviewMediaItem {
|
|
26
|
+
items[index]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
final class NativeImagePreviewSourceViewRegistry {
|
|
4
|
+
static let shared = NativeImagePreviewSourceViewRegistry()
|
|
5
|
+
|
|
6
|
+
private final class WeakImageView {
|
|
7
|
+
weak var value: UIImageView?
|
|
8
|
+
|
|
9
|
+
init(_ value: UIImageView) {
|
|
10
|
+
self.value = value
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private var anchors: [String: [Int: WeakImageView]] = [:]
|
|
15
|
+
|
|
16
|
+
private init() {}
|
|
17
|
+
|
|
18
|
+
func register(_ imageView: UIImageView, previewGroupId: String, index: Int) {
|
|
19
|
+
cleanup()
|
|
20
|
+
var previewGroupAnchors = anchors[previewGroupId] ?? [:]
|
|
21
|
+
previewGroupAnchors[index] = WeakImageView(imageView)
|
|
22
|
+
anchors[previewGroupId] = previewGroupAnchors
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func unregister(_ imageView: UIImageView, previewGroupId: String?, index: Int?) {
|
|
26
|
+
cleanup()
|
|
27
|
+
if let previewGroupId = previewGroupId {
|
|
28
|
+
remove(imageView, from: previewGroupId, index: index)
|
|
29
|
+
} else {
|
|
30
|
+
for previewGroupId in Array(anchors.keys) {
|
|
31
|
+
remove(imageView, from: previewGroupId, index: nil)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
cleanup()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func sourceView(for previewGroupId: String, index: Int) -> UIImageView? {
|
|
38
|
+
cleanup()
|
|
39
|
+
guard
|
|
40
|
+
let imageView = anchors[previewGroupId]?[index]?.value,
|
|
41
|
+
let window = imageView.window,
|
|
42
|
+
!imageView.isHidden
|
|
43
|
+
else {
|
|
44
|
+
return nil
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let frameInWindow = imageView.frameInWindow()
|
|
48
|
+
guard !frameInWindow.isEmpty, frameInWindow.intersects(window.bounds) else {
|
|
49
|
+
return nil
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return imageView
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private func remove(_ imageView: UIImageView, from previewGroupId: String, index: Int?) {
|
|
56
|
+
guard var previewGroupAnchors = anchors[previewGroupId] else { return }
|
|
57
|
+
|
|
58
|
+
if let index = index {
|
|
59
|
+
if let registeredView = previewGroupAnchors[index]?.value, registeredView === imageView {
|
|
60
|
+
previewGroupAnchors.removeValue(forKey: index)
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
previewGroupAnchors = previewGroupAnchors.filter { _, weakImageView in
|
|
64
|
+
guard let registeredView = weakImageView.value else { return false }
|
|
65
|
+
return registeredView !== imageView
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
anchors[previewGroupId] = previewGroupAnchors.isEmpty ? nil : previewGroupAnchors
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private func cleanup() {
|
|
73
|
+
anchors = anchors.compactMapValues { previewGroupAnchors in
|
|
74
|
+
let activeAnchors = previewGroupAnchors.filter { _, weakImageView in
|
|
75
|
+
weakImageView.value != nil
|
|
76
|
+
}
|
|
77
|
+
return activeAnchors.isEmpty ? nil : activeAnchors
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
|
|
3
|
-
public enum
|
|
3
|
+
public enum NativeImagePreviewViewerTheme {
|
|
4
4
|
case light
|
|
5
5
|
case dark
|
|
6
6
|
|
|
@@ -23,23 +23,23 @@ public enum GaleriaViewerTheme {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
public enum
|
|
26
|
+
public enum NativeImagePreviewViewerBarButton {
|
|
27
27
|
case title(String, onTap: ((Int) -> Void)?)
|
|
28
28
|
case icon(UIImage, onTap: ((Int) -> Void)?)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
public struct
|
|
32
|
-
public var theme:
|
|
31
|
+
public struct NativeImagePreviewViewerConfiguration {
|
|
32
|
+
public var theme: NativeImagePreviewViewerTheme
|
|
33
33
|
public var contentMode: UIView.ContentMode
|
|
34
34
|
public var closeIcon: UIImage?
|
|
35
|
-
public var rightBarButton:
|
|
35
|
+
public var rightBarButton: NativeImagePreviewViewerBarButton?
|
|
36
36
|
public var onIndexChange: ((Int) -> Void)?
|
|
37
37
|
|
|
38
38
|
public init(
|
|
39
|
-
theme:
|
|
39
|
+
theme: NativeImagePreviewViewerTheme = .light,
|
|
40
40
|
contentMode: UIView.ContentMode = .scaleAspectFit,
|
|
41
41
|
closeIcon: UIImage? = nil,
|
|
42
|
-
rightBarButton:
|
|
42
|
+
rightBarButton: NativeImagePreviewViewerBarButton? = nil,
|
|
43
43
|
onIndexChange: ((Int) -> Void)? = nil
|
|
44
44
|
) {
|
|
45
45
|
self.theme = theme
|