@hortemo/expo-photos 1.0.0
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/.eslintrc.js +2 -0
- package/ExpoPhotos.podspec +24 -0
- package/LICENSE +21 -0
- package/README.md +18 -0
- package/build/ExpoPhotos.types.d.ts +171 -0
- package/build/ExpoPhotos.types.d.ts.map +1 -0
- package/build/ExpoPhotos.types.js +122 -0
- package/build/ExpoPhotos.types.js.map +1 -0
- package/build/ExpoPhotosModule.d.ts +13 -0
- package/build/ExpoPhotosModule.d.ts.map +1 -0
- package/build/ExpoPhotosModule.js +3 -0
- package/build/ExpoPhotosModule.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +3 -0
- package/build/index.js.map +1 -0
- package/eslint.config.js +11 -0
- package/expo-module.config.json +7 -0
- package/ios/ExpoPhotosModule.swift +443 -0
- package/package.json +43 -0
- package/src/ExpoPhotos.types.ts +197 -0
- package/src/ExpoPhotosModule.ts +21 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +9 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ExpoPhotos'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platform = :ios, '15.0'
|
|
14
|
+
s.swift_version = '5.9'
|
|
15
|
+
s.source = { git: package['repository'] || 'https://github.com/hortemo/expo-photos' }
|
|
16
|
+
s.static_framework = true
|
|
17
|
+
|
|
18
|
+
s.dependency 'ExpoModulesCore'
|
|
19
|
+
s.dependency 'React'
|
|
20
|
+
s.dependency 'SDWebImageWebPCoder', '0.15.0'
|
|
21
|
+
|
|
22
|
+
s.source_files = 'ios/**/*.{h,m,swift}'
|
|
23
|
+
s.requires_arc = true
|
|
24
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Henrik Hortemo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @hortemo/expo-photos
|
|
2
|
+
|
|
3
|
+
Lightweight Expo (React Native) wrapper for Apple's [Photos](https://developer.apple.com/documentation/photos) framework.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @hortemo/expo-photos
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## API Reference
|
|
12
|
+
|
|
13
|
+
- `fetchAssets(options: FetchAssetsOptions): Promise<PHAsset[]>`
|
|
14
|
+
- `requestImage(options: RequestImageOptions): Promise<void>`
|
|
15
|
+
- `requestVideo(options: RequestVideoOptions): Promise<void>`
|
|
16
|
+
- `pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>`
|
|
17
|
+
- `requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>`
|
|
18
|
+
- `presentLimitedLibraryPicker(): Promise<void>`
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export interface PHAsset {
|
|
2
|
+
localIdentifier: string;
|
|
3
|
+
creationDate: number;
|
|
4
|
+
mediaType: PHAssetMediaType;
|
|
5
|
+
mediaSubtypes: PHAssetMediaSubtype;
|
|
6
|
+
duration: number;
|
|
7
|
+
}
|
|
8
|
+
export declare enum PHAuthorizationStatus {
|
|
9
|
+
notDetermined = 0,
|
|
10
|
+
restricted = 1,
|
|
11
|
+
denied = 2,
|
|
12
|
+
authorized = 3,
|
|
13
|
+
limited = 4
|
|
14
|
+
}
|
|
15
|
+
export declare enum PHAccessLevel {
|
|
16
|
+
addOnly = 1,
|
|
17
|
+
readWrite = 2
|
|
18
|
+
}
|
|
19
|
+
export declare enum PHAssetMediaType {
|
|
20
|
+
Unknown = 0,
|
|
21
|
+
Image = 1,
|
|
22
|
+
Video = 2,
|
|
23
|
+
Audio = 3
|
|
24
|
+
}
|
|
25
|
+
export declare enum PHAssetMediaSubtype {
|
|
26
|
+
None = 0,
|
|
27
|
+
PhotoPanorama = 1,
|
|
28
|
+
PhotoHDR = 2,
|
|
29
|
+
PhotoScreenshot = 4,
|
|
30
|
+
PhotoLive = 8,
|
|
31
|
+
PhotoDepthEffect = 16,
|
|
32
|
+
VideoStreamed = 65536,
|
|
33
|
+
VideoHighFrameRate = 131072,
|
|
34
|
+
VideoTimelapse = 262144,
|
|
35
|
+
VideoCinematic = 524288
|
|
36
|
+
}
|
|
37
|
+
export interface NSSortDescriptor {
|
|
38
|
+
key: string;
|
|
39
|
+
ascending: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface PHFetchOptions {
|
|
42
|
+
predicate?: string;
|
|
43
|
+
fetchLimit?: number;
|
|
44
|
+
sortDescriptors?: NSSortDescriptor[];
|
|
45
|
+
}
|
|
46
|
+
export type FetchAssetsOptions = PHFetchOptions;
|
|
47
|
+
export interface CGSize {
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
}
|
|
51
|
+
export declare enum PHImageRequestOptionsResizeMode {
|
|
52
|
+
None = 0,
|
|
53
|
+
Fast = 1,
|
|
54
|
+
Exact = 2
|
|
55
|
+
}
|
|
56
|
+
export declare enum PHImageRequestOptionsDeliveryMode {
|
|
57
|
+
Opportunistic = 0,
|
|
58
|
+
HighQualityFormat = 1,
|
|
59
|
+
FastFormat = 2
|
|
60
|
+
}
|
|
61
|
+
export declare enum PHImageContentMode {
|
|
62
|
+
aspectFit = 0,
|
|
63
|
+
aspectFill = 1
|
|
64
|
+
}
|
|
65
|
+
export interface PHImageRequestOptions {
|
|
66
|
+
isNetworkAccessAllowed?: boolean;
|
|
67
|
+
resizeMode?: PHImageRequestOptionsResizeMode;
|
|
68
|
+
deliveryMode?: PHImageRequestOptionsDeliveryMode;
|
|
69
|
+
}
|
|
70
|
+
export interface SDImageCoderOptions {
|
|
71
|
+
encodeCompressionQuality?: number;
|
|
72
|
+
encodeMaxFileSize?: number;
|
|
73
|
+
}
|
|
74
|
+
export declare enum PHVideoRequestOptionsDeliveryMode {
|
|
75
|
+
Automatic = 0,
|
|
76
|
+
HighQualityFormat = 1,
|
|
77
|
+
MediumQualityFormat = 2,
|
|
78
|
+
FastFormat = 3
|
|
79
|
+
}
|
|
80
|
+
export interface PHVideoRequestOptions {
|
|
81
|
+
isNetworkAccessAllowed?: boolean;
|
|
82
|
+
deliveryMode?: PHVideoRequestOptionsDeliveryMode;
|
|
83
|
+
}
|
|
84
|
+
export interface CMTimeRange {
|
|
85
|
+
start: number;
|
|
86
|
+
duration: number;
|
|
87
|
+
}
|
|
88
|
+
export declare enum AVFileType {
|
|
89
|
+
ac3 = "public.ac3-audio",
|
|
90
|
+
aifc = "public.aifc-audio",
|
|
91
|
+
aiff = "public.aiff-audio",
|
|
92
|
+
AHAP = "com.apple.itt",
|
|
93
|
+
amr = "org.3gpp.adaptive-multi-rate-audio",
|
|
94
|
+
appleiTT = "com.apple.itt",
|
|
95
|
+
au = "public.au-audio",
|
|
96
|
+
avci = "public.avci",
|
|
97
|
+
caf = "com.apple.coreaudio-format",
|
|
98
|
+
dng = "com.adobe.raw-image",
|
|
99
|
+
eac3 = "public.eac3-audio",
|
|
100
|
+
heic = "public.heic",
|
|
101
|
+
heif = "public.heif",
|
|
102
|
+
jpg = "public.jpeg",
|
|
103
|
+
m4a = "com.apple.m4a-audio",
|
|
104
|
+
m4v = "com.apple.m4v-video",
|
|
105
|
+
mobile3GPP = "public.3gpp",
|
|
106
|
+
mobile3GPP2 = "public.3gpp2",
|
|
107
|
+
mov = "com.apple.quicktime-movie",
|
|
108
|
+
mp3 = "public.mp3",
|
|
109
|
+
mp4 = "public.mpeg-4",
|
|
110
|
+
SCC = "com.scenarist.cc",
|
|
111
|
+
tif = "public.tiff",
|
|
112
|
+
wav = "com.microsoft.waveform-audio"
|
|
113
|
+
}
|
|
114
|
+
export declare enum AVAssetExportPreset {
|
|
115
|
+
LowQuality = "AVAssetExportPresetLowQuality",
|
|
116
|
+
MediumQuality = "AVAssetExportPresetMediumQuality",
|
|
117
|
+
HighestQuality = "AVAssetExportPresetHighestQuality",
|
|
118
|
+
HEVCHighestQuality = "AVAssetExportPresetHEVCHighestQuality",
|
|
119
|
+
HEVCHighestQualityWithAlpha = "AVAssetExportPresetHEVCHighestQualityWithAlpha",
|
|
120
|
+
AVC640x480 = "AVAssetExportPreset640x480",
|
|
121
|
+
AVC960x540 = "AVAssetExportPreset960x540",
|
|
122
|
+
AVC1280x720 = "AVAssetExportPreset1280x720",
|
|
123
|
+
AVC1920x1080 = "AVAssetExportPreset1920x1080",
|
|
124
|
+
AVC3840x2160 = "AVAssetExportPreset3840x2160",
|
|
125
|
+
HEVC1920x1080 = "AVAssetExportPresetHEVC1920x1080",
|
|
126
|
+
HEVC3840x2160 = "AVAssetExportPresetHEVC3840x2160",
|
|
127
|
+
HEVC1920x1080WithAlpha = "AVAssetExportPresetHEVC1920x1080WithAlpha",
|
|
128
|
+
HEVC3840x2160WithAlpha = "AVAssetExportPresetHEVC3840x2160WithAlpha",
|
|
129
|
+
HEVC7680x4320 = "AVAssetExportPresetHEVC7680x4320",
|
|
130
|
+
MVHEVC960x960 = "AVAssetExportPresetMVHEVC960x960",
|
|
131
|
+
MVHEVC1440x1440 = "AVAssetExportPresetMVHEVC1440x1440",
|
|
132
|
+
AppleM4V480pSD = "AVAssetExportPresetAppleM4V480pSD",
|
|
133
|
+
AppleM4V720pHD = "AVAssetExportPresetAppleM4V720pHD",
|
|
134
|
+
AppleM4V1080pHD = "AVAssetExportPresetAppleM4V1080pHD",
|
|
135
|
+
AppleM4ViPod = "AVAssetExportPresetAppleM4ViPod",
|
|
136
|
+
AppleM4VAppleTV = "AVAssetExportPresetAppleM4VAppleTV",
|
|
137
|
+
AppleM4VCellular = "AVAssetExportPresetAppleM4VCellular",
|
|
138
|
+
AppleM4VWiFi = "AVAssetExportPresetAppleM4VWiFi",
|
|
139
|
+
AppleProRes422LPCM = "AVAssetExportPresetAppleProRes422LPCM",
|
|
140
|
+
AppleProRes4444LPCM = "AVAssetExportPresetAppleProRes4444LPCM",
|
|
141
|
+
Passthrough = "AVAssetExportPresetPassthrough",
|
|
142
|
+
AppleM4A = "AVAssetExportPresetAppleM4A"
|
|
143
|
+
}
|
|
144
|
+
export interface AVAssetExportSessionOptions {
|
|
145
|
+
outputURL: string;
|
|
146
|
+
outputFileType?: AVFileType;
|
|
147
|
+
fileLengthLimit?: number;
|
|
148
|
+
timeRange?: CMTimeRange;
|
|
149
|
+
}
|
|
150
|
+
export interface RequestImageOptions extends PHImageRequestOptions, SDImageCoderOptions {
|
|
151
|
+
localIdentifier: string;
|
|
152
|
+
targetSize: CGSize;
|
|
153
|
+
contentMode: PHImageContentMode;
|
|
154
|
+
outputURL: string;
|
|
155
|
+
timeout?: number;
|
|
156
|
+
}
|
|
157
|
+
export interface RequestVideoOptions extends PHVideoRequestOptions, AVAssetExportSessionOptions {
|
|
158
|
+
localIdentifier: string;
|
|
159
|
+
exportPreset: AVAssetExportPreset;
|
|
160
|
+
timeout?: number;
|
|
161
|
+
}
|
|
162
|
+
export declare enum PHPickerFilter {
|
|
163
|
+
images = "images",
|
|
164
|
+
videos = "videos",
|
|
165
|
+
any = "any"
|
|
166
|
+
}
|
|
167
|
+
export interface PickAssetsOptions {
|
|
168
|
+
filter?: PHPickerFilter;
|
|
169
|
+
selectionLimit?: number;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=ExpoPhotos.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoPhotos.types.d.ts","sourceRoot":"","sources":["../src/ExpoPhotos.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,EAAE,mBAAmB,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oBAAY,qBAAqB;IAC/B,aAAa,IAAI;IACjB,UAAU,IAAI;IACd,MAAM,IAAI;IACV,UAAU,IAAI;IACd,OAAO,IAAI;CACZ;AAED,oBAAY,aAAa;IACvB,OAAO,IAAI;IACX,SAAS,IAAI;CACd;AAED,oBAAY,gBAAgB;IAC1B,OAAO,IAAI;IACX,KAAK,IAAI;IACT,KAAK,IAAI;IACT,KAAK,IAAI;CACV;AAED,oBAAY,mBAAmB;IAC7B,IAAI,IAAI;IACR,aAAa,IAAS;IACtB,QAAQ,IAAS;IACjB,eAAe,IAAS;IACxB,SAAS,IAAS;IAClB,gBAAgB,KAAS;IACzB,aAAa,QAAU;IACvB,kBAAkB,SAAU;IAC5B,cAAc,SAAU;IACxB,cAAc,SAAU;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACtC;AAED,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAEhD,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,+BAA+B;IACzC,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAED,oBAAY,iCAAiC;IAC3C,aAAa,IAAI;IACjB,iBAAiB,IAAI;IACrB,UAAU,IAAI;CACf;AAED,oBAAY,kBAAkB;IAC5B,SAAS,IAAI;IACb,UAAU,IAAI;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,UAAU,CAAC,EAAE,+BAA+B,CAAC;IAC7C,YAAY,CAAC,EAAE,iCAAiC,CAAC;CAClD;AAED,MAAM,WAAW,mBAAmB;IAClC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,oBAAY,iCAAiC;IAC3C,SAAS,IAAI;IACb,iBAAiB,IAAI;IACrB,mBAAmB,IAAI;IACvB,UAAU,IAAI;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,YAAY,CAAC,EAAE,iCAAiC,CAAC;CAClD;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oBAAY,UAAU;IACpB,GAAG,qBAAqB;IACxB,IAAI,sBAAsB;IAC1B,IAAI,sBAAsB;IAC1B,IAAI,kBAAkB;IACtB,GAAG,uCAAuC;IAC1C,QAAQ,kBAAkB;IAC1B,EAAE,oBAAoB;IACtB,IAAI,gBAAgB;IACpB,GAAG,+BAA+B;IAClC,GAAG,wBAAwB;IAC3B,IAAI,sBAAsB;IAC1B,IAAI,gBAAgB;IACpB,IAAI,gBAAgB;IACpB,GAAG,gBAAgB;IACnB,GAAG,wBAAwB;IAC3B,GAAG,wBAAwB;IAC3B,UAAU,gBAAgB;IAC1B,WAAW,iBAAiB;IAC5B,GAAG,8BAA8B;IACjC,GAAG,eAAe;IAClB,GAAG,kBAAkB;IACrB,GAAG,qBAAqB;IACxB,GAAG,gBAAgB;IACnB,GAAG,iCAAiC;CACrC;AAED,oBAAY,mBAAmB;IAC7B,UAAU,kCAAkC;IAC5C,aAAa,qCAAqC;IAClD,cAAc,sCAAsC;IACpD,kBAAkB,0CAA0C;IAC5D,2BAA2B,mDAAmD;IAC9E,UAAU,+BAA+B;IACzC,UAAU,+BAA+B;IACzC,WAAW,gCAAgC;IAC3C,YAAY,iCAAiC;IAC7C,YAAY,iCAAiC;IAC7C,aAAa,qCAAqC;IAClD,aAAa,qCAAqC;IAClD,sBAAsB,8CAA8C;IACpE,sBAAsB,8CAA8C;IACpE,aAAa,qCAAqC;IAClD,aAAa,qCAAqC;IAClD,eAAe,uCAAuC;IACtD,cAAc,sCAAsC;IACpD,cAAc,sCAAsC;IACpD,eAAe,uCAAuC;IACtD,YAAY,oCAAoC;IAChD,eAAe,uCAAuC;IACtD,gBAAgB,wCAAwC;IACxD,YAAY,oCAAoC;IAChD,kBAAkB,0CAA0C;IAC5D,mBAAmB,2CAA2C;IAC9D,WAAW,mCAAmC;IAC9C,QAAQ,gCAAgC;CACzC;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED,MAAM,WAAW,mBACf,SAAQ,qBAAqB,EAC3B,mBAAmB;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBACf,SAAQ,qBAAqB,EAC3B,2BAA2B;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,mBAAmB,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,oBAAY,cAAc;IACxB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,GAAG,QAAQ;CACZ;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export var PHAuthorizationStatus;
|
|
2
|
+
(function (PHAuthorizationStatus) {
|
|
3
|
+
PHAuthorizationStatus[PHAuthorizationStatus["notDetermined"] = 0] = "notDetermined";
|
|
4
|
+
PHAuthorizationStatus[PHAuthorizationStatus["restricted"] = 1] = "restricted";
|
|
5
|
+
PHAuthorizationStatus[PHAuthorizationStatus["denied"] = 2] = "denied";
|
|
6
|
+
PHAuthorizationStatus[PHAuthorizationStatus["authorized"] = 3] = "authorized";
|
|
7
|
+
PHAuthorizationStatus[PHAuthorizationStatus["limited"] = 4] = "limited";
|
|
8
|
+
})(PHAuthorizationStatus || (PHAuthorizationStatus = {}));
|
|
9
|
+
export var PHAccessLevel;
|
|
10
|
+
(function (PHAccessLevel) {
|
|
11
|
+
PHAccessLevel[PHAccessLevel["addOnly"] = 1] = "addOnly";
|
|
12
|
+
PHAccessLevel[PHAccessLevel["readWrite"] = 2] = "readWrite";
|
|
13
|
+
})(PHAccessLevel || (PHAccessLevel = {}));
|
|
14
|
+
export var PHAssetMediaType;
|
|
15
|
+
(function (PHAssetMediaType) {
|
|
16
|
+
PHAssetMediaType[PHAssetMediaType["Unknown"] = 0] = "Unknown";
|
|
17
|
+
PHAssetMediaType[PHAssetMediaType["Image"] = 1] = "Image";
|
|
18
|
+
PHAssetMediaType[PHAssetMediaType["Video"] = 2] = "Video";
|
|
19
|
+
PHAssetMediaType[PHAssetMediaType["Audio"] = 3] = "Audio";
|
|
20
|
+
})(PHAssetMediaType || (PHAssetMediaType = {}));
|
|
21
|
+
export var PHAssetMediaSubtype;
|
|
22
|
+
(function (PHAssetMediaSubtype) {
|
|
23
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["None"] = 0] = "None";
|
|
24
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["PhotoPanorama"] = 1] = "PhotoPanorama";
|
|
25
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["PhotoHDR"] = 2] = "PhotoHDR";
|
|
26
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["PhotoScreenshot"] = 4] = "PhotoScreenshot";
|
|
27
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["PhotoLive"] = 8] = "PhotoLive";
|
|
28
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["PhotoDepthEffect"] = 16] = "PhotoDepthEffect";
|
|
29
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["VideoStreamed"] = 65536] = "VideoStreamed";
|
|
30
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["VideoHighFrameRate"] = 131072] = "VideoHighFrameRate";
|
|
31
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["VideoTimelapse"] = 262144] = "VideoTimelapse";
|
|
32
|
+
PHAssetMediaSubtype[PHAssetMediaSubtype["VideoCinematic"] = 524288] = "VideoCinematic";
|
|
33
|
+
})(PHAssetMediaSubtype || (PHAssetMediaSubtype = {}));
|
|
34
|
+
export var PHImageRequestOptionsResizeMode;
|
|
35
|
+
(function (PHImageRequestOptionsResizeMode) {
|
|
36
|
+
PHImageRequestOptionsResizeMode[PHImageRequestOptionsResizeMode["None"] = 0] = "None";
|
|
37
|
+
PHImageRequestOptionsResizeMode[PHImageRequestOptionsResizeMode["Fast"] = 1] = "Fast";
|
|
38
|
+
PHImageRequestOptionsResizeMode[PHImageRequestOptionsResizeMode["Exact"] = 2] = "Exact";
|
|
39
|
+
})(PHImageRequestOptionsResizeMode || (PHImageRequestOptionsResizeMode = {}));
|
|
40
|
+
export var PHImageRequestOptionsDeliveryMode;
|
|
41
|
+
(function (PHImageRequestOptionsDeliveryMode) {
|
|
42
|
+
PHImageRequestOptionsDeliveryMode[PHImageRequestOptionsDeliveryMode["Opportunistic"] = 0] = "Opportunistic";
|
|
43
|
+
PHImageRequestOptionsDeliveryMode[PHImageRequestOptionsDeliveryMode["HighQualityFormat"] = 1] = "HighQualityFormat";
|
|
44
|
+
PHImageRequestOptionsDeliveryMode[PHImageRequestOptionsDeliveryMode["FastFormat"] = 2] = "FastFormat";
|
|
45
|
+
})(PHImageRequestOptionsDeliveryMode || (PHImageRequestOptionsDeliveryMode = {}));
|
|
46
|
+
export var PHImageContentMode;
|
|
47
|
+
(function (PHImageContentMode) {
|
|
48
|
+
PHImageContentMode[PHImageContentMode["aspectFit"] = 0] = "aspectFit";
|
|
49
|
+
PHImageContentMode[PHImageContentMode["aspectFill"] = 1] = "aspectFill";
|
|
50
|
+
})(PHImageContentMode || (PHImageContentMode = {}));
|
|
51
|
+
export var PHVideoRequestOptionsDeliveryMode;
|
|
52
|
+
(function (PHVideoRequestOptionsDeliveryMode) {
|
|
53
|
+
PHVideoRequestOptionsDeliveryMode[PHVideoRequestOptionsDeliveryMode["Automatic"] = 0] = "Automatic";
|
|
54
|
+
PHVideoRequestOptionsDeliveryMode[PHVideoRequestOptionsDeliveryMode["HighQualityFormat"] = 1] = "HighQualityFormat";
|
|
55
|
+
PHVideoRequestOptionsDeliveryMode[PHVideoRequestOptionsDeliveryMode["MediumQualityFormat"] = 2] = "MediumQualityFormat";
|
|
56
|
+
PHVideoRequestOptionsDeliveryMode[PHVideoRequestOptionsDeliveryMode["FastFormat"] = 3] = "FastFormat";
|
|
57
|
+
})(PHVideoRequestOptionsDeliveryMode || (PHVideoRequestOptionsDeliveryMode = {}));
|
|
58
|
+
export var AVFileType;
|
|
59
|
+
(function (AVFileType) {
|
|
60
|
+
AVFileType["ac3"] = "public.ac3-audio";
|
|
61
|
+
AVFileType["aifc"] = "public.aifc-audio";
|
|
62
|
+
AVFileType["aiff"] = "public.aiff-audio";
|
|
63
|
+
AVFileType["AHAP"] = "com.apple.itt";
|
|
64
|
+
AVFileType["amr"] = "org.3gpp.adaptive-multi-rate-audio";
|
|
65
|
+
AVFileType["appleiTT"] = "com.apple.itt";
|
|
66
|
+
AVFileType["au"] = "public.au-audio";
|
|
67
|
+
AVFileType["avci"] = "public.avci";
|
|
68
|
+
AVFileType["caf"] = "com.apple.coreaudio-format";
|
|
69
|
+
AVFileType["dng"] = "com.adobe.raw-image";
|
|
70
|
+
AVFileType["eac3"] = "public.eac3-audio";
|
|
71
|
+
AVFileType["heic"] = "public.heic";
|
|
72
|
+
AVFileType["heif"] = "public.heif";
|
|
73
|
+
AVFileType["jpg"] = "public.jpeg";
|
|
74
|
+
AVFileType["m4a"] = "com.apple.m4a-audio";
|
|
75
|
+
AVFileType["m4v"] = "com.apple.m4v-video";
|
|
76
|
+
AVFileType["mobile3GPP"] = "public.3gpp";
|
|
77
|
+
AVFileType["mobile3GPP2"] = "public.3gpp2";
|
|
78
|
+
AVFileType["mov"] = "com.apple.quicktime-movie";
|
|
79
|
+
AVFileType["mp3"] = "public.mp3";
|
|
80
|
+
AVFileType["mp4"] = "public.mpeg-4";
|
|
81
|
+
AVFileType["SCC"] = "com.scenarist.cc";
|
|
82
|
+
AVFileType["tif"] = "public.tiff";
|
|
83
|
+
AVFileType["wav"] = "com.microsoft.waveform-audio";
|
|
84
|
+
})(AVFileType || (AVFileType = {}));
|
|
85
|
+
export var AVAssetExportPreset;
|
|
86
|
+
(function (AVAssetExportPreset) {
|
|
87
|
+
AVAssetExportPreset["LowQuality"] = "AVAssetExportPresetLowQuality";
|
|
88
|
+
AVAssetExportPreset["MediumQuality"] = "AVAssetExportPresetMediumQuality";
|
|
89
|
+
AVAssetExportPreset["HighestQuality"] = "AVAssetExportPresetHighestQuality";
|
|
90
|
+
AVAssetExportPreset["HEVCHighestQuality"] = "AVAssetExportPresetHEVCHighestQuality";
|
|
91
|
+
AVAssetExportPreset["HEVCHighestQualityWithAlpha"] = "AVAssetExportPresetHEVCHighestQualityWithAlpha";
|
|
92
|
+
AVAssetExportPreset["AVC640x480"] = "AVAssetExportPreset640x480";
|
|
93
|
+
AVAssetExportPreset["AVC960x540"] = "AVAssetExportPreset960x540";
|
|
94
|
+
AVAssetExportPreset["AVC1280x720"] = "AVAssetExportPreset1280x720";
|
|
95
|
+
AVAssetExportPreset["AVC1920x1080"] = "AVAssetExportPreset1920x1080";
|
|
96
|
+
AVAssetExportPreset["AVC3840x2160"] = "AVAssetExportPreset3840x2160";
|
|
97
|
+
AVAssetExportPreset["HEVC1920x1080"] = "AVAssetExportPresetHEVC1920x1080";
|
|
98
|
+
AVAssetExportPreset["HEVC3840x2160"] = "AVAssetExportPresetHEVC3840x2160";
|
|
99
|
+
AVAssetExportPreset["HEVC1920x1080WithAlpha"] = "AVAssetExportPresetHEVC1920x1080WithAlpha";
|
|
100
|
+
AVAssetExportPreset["HEVC3840x2160WithAlpha"] = "AVAssetExportPresetHEVC3840x2160WithAlpha";
|
|
101
|
+
AVAssetExportPreset["HEVC7680x4320"] = "AVAssetExportPresetHEVC7680x4320";
|
|
102
|
+
AVAssetExportPreset["MVHEVC960x960"] = "AVAssetExportPresetMVHEVC960x960";
|
|
103
|
+
AVAssetExportPreset["MVHEVC1440x1440"] = "AVAssetExportPresetMVHEVC1440x1440";
|
|
104
|
+
AVAssetExportPreset["AppleM4V480pSD"] = "AVAssetExportPresetAppleM4V480pSD";
|
|
105
|
+
AVAssetExportPreset["AppleM4V720pHD"] = "AVAssetExportPresetAppleM4V720pHD";
|
|
106
|
+
AVAssetExportPreset["AppleM4V1080pHD"] = "AVAssetExportPresetAppleM4V1080pHD";
|
|
107
|
+
AVAssetExportPreset["AppleM4ViPod"] = "AVAssetExportPresetAppleM4ViPod";
|
|
108
|
+
AVAssetExportPreset["AppleM4VAppleTV"] = "AVAssetExportPresetAppleM4VAppleTV";
|
|
109
|
+
AVAssetExportPreset["AppleM4VCellular"] = "AVAssetExportPresetAppleM4VCellular";
|
|
110
|
+
AVAssetExportPreset["AppleM4VWiFi"] = "AVAssetExportPresetAppleM4VWiFi";
|
|
111
|
+
AVAssetExportPreset["AppleProRes422LPCM"] = "AVAssetExportPresetAppleProRes422LPCM";
|
|
112
|
+
AVAssetExportPreset["AppleProRes4444LPCM"] = "AVAssetExportPresetAppleProRes4444LPCM";
|
|
113
|
+
AVAssetExportPreset["Passthrough"] = "AVAssetExportPresetPassthrough";
|
|
114
|
+
AVAssetExportPreset["AppleM4A"] = "AVAssetExportPresetAppleM4A";
|
|
115
|
+
})(AVAssetExportPreset || (AVAssetExportPreset = {}));
|
|
116
|
+
export var PHPickerFilter;
|
|
117
|
+
(function (PHPickerFilter) {
|
|
118
|
+
PHPickerFilter["images"] = "images";
|
|
119
|
+
PHPickerFilter["videos"] = "videos";
|
|
120
|
+
PHPickerFilter["any"] = "any";
|
|
121
|
+
})(PHPickerFilter || (PHPickerFilter = {}));
|
|
122
|
+
//# sourceMappingURL=ExpoPhotos.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoPhotos.types.js","sourceRoot":"","sources":["../src/ExpoPhotos.types.ts"],"names":[],"mappings":"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","sourcesContent":["export interface PHAsset {\n localIdentifier: string;\n creationDate: number;\n mediaType: PHAssetMediaType;\n mediaSubtypes: PHAssetMediaSubtype;\n duration: number;\n}\n\nexport enum PHAuthorizationStatus {\n notDetermined = 0,\n restricted = 1,\n denied = 2,\n authorized = 3,\n limited = 4,\n}\n\nexport enum PHAccessLevel {\n addOnly = 1,\n readWrite = 2,\n}\n\nexport enum PHAssetMediaType {\n Unknown = 0,\n Image = 1,\n Video = 2,\n Audio = 3,\n}\n\nexport enum PHAssetMediaSubtype {\n None = 0,\n PhotoPanorama = 1 << 0,\n PhotoHDR = 1 << 1,\n PhotoScreenshot = 1 << 2,\n PhotoLive = 1 << 3,\n PhotoDepthEffect = 1 << 4,\n VideoStreamed = 1 << 16,\n VideoHighFrameRate = 1 << 17,\n VideoTimelapse = 1 << 18,\n VideoCinematic = 1 << 19,\n}\n\nexport interface NSSortDescriptor {\n key: string;\n ascending: boolean;\n}\n\nexport interface PHFetchOptions {\n predicate?: string;\n fetchLimit?: number;\n sortDescriptors?: NSSortDescriptor[];\n}\n\nexport type FetchAssetsOptions = PHFetchOptions;\n\nexport interface CGSize {\n width: number;\n height: number;\n}\n\nexport enum PHImageRequestOptionsResizeMode {\n None = 0,\n Fast = 1,\n Exact = 2,\n}\n\nexport enum PHImageRequestOptionsDeliveryMode {\n Opportunistic = 0,\n HighQualityFormat = 1,\n FastFormat = 2,\n}\n\nexport enum PHImageContentMode {\n aspectFit = 0,\n aspectFill = 1,\n}\n\nexport interface PHImageRequestOptions {\n isNetworkAccessAllowed?: boolean;\n resizeMode?: PHImageRequestOptionsResizeMode;\n deliveryMode?: PHImageRequestOptionsDeliveryMode;\n}\n\nexport interface SDImageCoderOptions {\n encodeCompressionQuality?: number;\n encodeMaxFileSize?: number;\n}\n\nexport enum PHVideoRequestOptionsDeliveryMode {\n Automatic = 0,\n HighQualityFormat = 1,\n MediumQualityFormat = 2,\n FastFormat = 3,\n}\n\nexport interface PHVideoRequestOptions {\n isNetworkAccessAllowed?: boolean;\n deliveryMode?: PHVideoRequestOptionsDeliveryMode;\n}\n\nexport interface CMTimeRange {\n start: number;\n duration: number;\n}\n\nexport enum AVFileType {\n ac3 = \"public.ac3-audio\",\n aifc = \"public.aifc-audio\",\n aiff = \"public.aiff-audio\",\n AHAP = \"com.apple.itt\",\n amr = \"org.3gpp.adaptive-multi-rate-audio\",\n appleiTT = \"com.apple.itt\",\n au = \"public.au-audio\",\n avci = \"public.avci\",\n caf = \"com.apple.coreaudio-format\",\n dng = \"com.adobe.raw-image\",\n eac3 = \"public.eac3-audio\",\n heic = \"public.heic\",\n heif = \"public.heif\",\n jpg = \"public.jpeg\",\n m4a = \"com.apple.m4a-audio\",\n m4v = \"com.apple.m4v-video\",\n mobile3GPP = \"public.3gpp\",\n mobile3GPP2 = \"public.3gpp2\",\n mov = \"com.apple.quicktime-movie\",\n mp3 = \"public.mp3\",\n mp4 = \"public.mpeg-4\",\n SCC = \"com.scenarist.cc\",\n tif = \"public.tiff\",\n wav = \"com.microsoft.waveform-audio\",\n}\n\nexport enum AVAssetExportPreset {\n LowQuality = \"AVAssetExportPresetLowQuality\",\n MediumQuality = \"AVAssetExportPresetMediumQuality\",\n HighestQuality = \"AVAssetExportPresetHighestQuality\",\n HEVCHighestQuality = \"AVAssetExportPresetHEVCHighestQuality\",\n HEVCHighestQualityWithAlpha = \"AVAssetExportPresetHEVCHighestQualityWithAlpha\",\n AVC640x480 = \"AVAssetExportPreset640x480\",\n AVC960x540 = \"AVAssetExportPreset960x540\",\n AVC1280x720 = \"AVAssetExportPreset1280x720\",\n AVC1920x1080 = \"AVAssetExportPreset1920x1080\",\n AVC3840x2160 = \"AVAssetExportPreset3840x2160\",\n HEVC1920x1080 = \"AVAssetExportPresetHEVC1920x1080\",\n HEVC3840x2160 = \"AVAssetExportPresetHEVC3840x2160\",\n HEVC1920x1080WithAlpha = \"AVAssetExportPresetHEVC1920x1080WithAlpha\",\n HEVC3840x2160WithAlpha = \"AVAssetExportPresetHEVC3840x2160WithAlpha\",\n HEVC7680x4320 = \"AVAssetExportPresetHEVC7680x4320\",\n MVHEVC960x960 = \"AVAssetExportPresetMVHEVC960x960\",\n MVHEVC1440x1440 = \"AVAssetExportPresetMVHEVC1440x1440\",\n AppleM4V480pSD = \"AVAssetExportPresetAppleM4V480pSD\",\n AppleM4V720pHD = \"AVAssetExportPresetAppleM4V720pHD\",\n AppleM4V1080pHD = \"AVAssetExportPresetAppleM4V1080pHD\",\n AppleM4ViPod = \"AVAssetExportPresetAppleM4ViPod\",\n AppleM4VAppleTV = \"AVAssetExportPresetAppleM4VAppleTV\",\n AppleM4VCellular = \"AVAssetExportPresetAppleM4VCellular\",\n AppleM4VWiFi = \"AVAssetExportPresetAppleM4VWiFi\",\n AppleProRes422LPCM = \"AVAssetExportPresetAppleProRes422LPCM\",\n AppleProRes4444LPCM = \"AVAssetExportPresetAppleProRes4444LPCM\",\n Passthrough = \"AVAssetExportPresetPassthrough\",\n AppleM4A = \"AVAssetExportPresetAppleM4A\",\n}\n\nexport interface AVAssetExportSessionOptions {\n outputURL: string;\n outputFileType?: AVFileType;\n fileLengthLimit?: number;\n timeRange?: CMTimeRange;\n}\n\nexport interface RequestImageOptions\n extends PHImageRequestOptions,\n SDImageCoderOptions {\n localIdentifier: string;\n targetSize: CGSize;\n contentMode: PHImageContentMode;\n outputURL: string;\n timeout?: number;\n}\n\nexport interface RequestVideoOptions\n extends PHVideoRequestOptions,\n AVAssetExportSessionOptions {\n localIdentifier: string;\n exportPreset: AVAssetExportPreset;\n timeout?: number;\n}\n\nexport enum PHPickerFilter {\n images = \"images\",\n videos = \"videos\",\n any = \"any\",\n}\n\nexport interface PickAssetsOptions {\n filter?: PHPickerFilter;\n selectionLimit?: number;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NativeModule } from "expo-modules-core";
|
|
2
|
+
import type { FetchAssetsOptions, PHAuthorizationStatus, PHAccessLevel, PHAsset, PickAssetsOptions, RequestImageOptions, RequestVideoOptions } from "./ExpoPhotos.types";
|
|
3
|
+
export declare class ExpoPhotosModule extends NativeModule {
|
|
4
|
+
fetchAssets(options: FetchAssetsOptions): Promise<PHAsset[]>;
|
|
5
|
+
requestImage(options: RequestImageOptions): Promise<void>;
|
|
6
|
+
requestVideo(options: RequestVideoOptions): Promise<void>;
|
|
7
|
+
pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>;
|
|
8
|
+
requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;
|
|
9
|
+
presentLimitedLibraryPicker(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: ExpoPhotosModule;
|
|
12
|
+
export default _default;
|
|
13
|
+
//# sourceMappingURL=ExpoPhotosModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoPhotosModule.d.ts","sourceRoot":"","sources":["../src/ExpoPhotosModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,OAAO,EACP,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,YAAY;IACxD,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5D,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IACzD,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IACzD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1D,oBAAoB,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAChF,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;CAC7C;;AAED,wBAAmE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoPhotosModule.js","sourceRoot":"","sources":["../src/ExpoPhotosModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAoBtE,eAAe,mBAAmB,CAAmB,YAAY,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo-modules-core\";\nimport type {\n FetchAssetsOptions,\n PHAuthorizationStatus,\n PHAccessLevel,\n PHAsset,\n PickAssetsOptions,\n RequestImageOptions,\n RequestVideoOptions,\n} from \"./ExpoPhotos.types\";\n\nexport declare class ExpoPhotosModule extends NativeModule {\n fetchAssets(options: FetchAssetsOptions): Promise<PHAsset[]>;\n requestImage(options: RequestImageOptions): Promise<void>;\n requestVideo(options: RequestVideoOptions): Promise<void>;\n pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>;\n requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;\n presentLimitedLibraryPicker(): Promise<void>;\n}\n\nexport default requireNativeModule<ExpoPhotosModule>(\"ExpoPhotos\");\n"]}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,cAAc,oBAAoB,CAAC","sourcesContent":["export { default } from \"./ExpoPhotosModule\";\nexport * from \"./ExpoPhotos.types\";\n"]}
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { defineConfig } = require('eslint/config');
|
|
2
|
+
const baseConfig = require('expo-module-scripts/eslint.config.base');
|
|
3
|
+
|
|
4
|
+
const normalizedBaseConfig = Array.isArray(baseConfig) ? baseConfig : [baseConfig];
|
|
5
|
+
|
|
6
|
+
module.exports = defineConfig([
|
|
7
|
+
{
|
|
8
|
+
ignores: ['build'],
|
|
9
|
+
},
|
|
10
|
+
...normalizedBaseConfig,
|
|
11
|
+
]);
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import Foundation
|
|
3
|
+
import Photos
|
|
4
|
+
import PhotosUI
|
|
5
|
+
import SDWebImageWebPCoder
|
|
6
|
+
import UIKit
|
|
7
|
+
|
|
8
|
+
struct FetchAssetsOptions: Record {
|
|
9
|
+
@Field var predicate: NSPredicate?
|
|
10
|
+
@Field var fetchLimit: Int?
|
|
11
|
+
@Field var sortDescriptors: [NSSortDescriptor]?
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
struct RequestImageOptions: Record {
|
|
15
|
+
@Field var localIdentifier: String?
|
|
16
|
+
@Field var targetSize: CGSize?
|
|
17
|
+
@Field var contentMode: PHImageContentMode?
|
|
18
|
+
@Field var isNetworkAccessAllowed: Bool?
|
|
19
|
+
@Field var deliveryMode: PHImageRequestOptionsDeliveryMode?
|
|
20
|
+
@Field var resizeMode: PHImageRequestOptionsResizeMode?
|
|
21
|
+
@Field var outputURL: URL?
|
|
22
|
+
@Field var encodeCompressionQuality: Double?
|
|
23
|
+
@Field var encodeMaxFileSize: Int?
|
|
24
|
+
@Field var timeout: TimeInterval?
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protocol AVAssetExportSessionOptions {
|
|
28
|
+
var outputURL: URL? { get }
|
|
29
|
+
var outputFileType: AVFileType? { get }
|
|
30
|
+
var fileLengthLimit: Int64? { get }
|
|
31
|
+
var timeRange: CMTimeRange? { get }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
struct RequestVideoOptions: Record, AVAssetExportSessionOptions {
|
|
35
|
+
@Field var localIdentifier: String?
|
|
36
|
+
@Field var isNetworkAccessAllowed: Bool?
|
|
37
|
+
@Field var deliveryMode: PHVideoRequestOptionsDeliveryMode?
|
|
38
|
+
@Field var exportPreset: String?
|
|
39
|
+
@Field var outputURL: URL?
|
|
40
|
+
@Field var outputFileType: AVFileType?
|
|
41
|
+
@Field var fileLengthLimit: Int64?
|
|
42
|
+
@Field var timeRange: CMTimeRange?
|
|
43
|
+
@Field var timeout: TimeInterval?
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
struct PickAssetsOptions: Record {
|
|
47
|
+
@Field var filter: PHPickerFilter?
|
|
48
|
+
@Field var selectionLimit: Int?
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
enum ExpoPhotosError: Error {
|
|
52
|
+
case mandatoryFieldMissing
|
|
53
|
+
case couldNotFindAsset
|
|
54
|
+
case couldNotEncodeImage
|
|
55
|
+
case couldNotCreateExportSession
|
|
56
|
+
case noViewController
|
|
57
|
+
case unknown
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public class ExpoPhotos: Module {
|
|
61
|
+
private var pickAssetsContinuations = [
|
|
62
|
+
ObjectIdentifier: CheckedContinuation<[[String: Any]], Error>
|
|
63
|
+
]()
|
|
64
|
+
|
|
65
|
+
public func definition() -> ModuleDefinition {
|
|
66
|
+
Name("ExpoPhotos")
|
|
67
|
+
|
|
68
|
+
AsyncFunction("fetchAssets") { (options: FetchAssetsOptions) -> [[String: Any]] in
|
|
69
|
+
let fetchOptions = PHFetchOptions()
|
|
70
|
+
|
|
71
|
+
if let predicate = options.predicate {
|
|
72
|
+
fetchOptions.predicate = predicate
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if let fetchLimit = options.fetchLimit {
|
|
76
|
+
fetchOptions.fetchLimit = fetchLimit
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if let sortDescriptors = options.sortDescriptors {
|
|
80
|
+
fetchOptions.sortDescriptors = sortDescriptors
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
var assets: [[String: Any]] = []
|
|
84
|
+
PHAsset.fetchAssets(with: fetchOptions).enumerateObjects { asset, _, _ in
|
|
85
|
+
assets.append(asset.toJS())
|
|
86
|
+
}
|
|
87
|
+
return assets
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
AsyncFunction("requestAuthorization") { (accessLevel: PHAccessLevel) async throws -> Int in
|
|
91
|
+
let status = await PHPhotoLibrary.requestAuthorization(for: accessLevel)
|
|
92
|
+
return status.rawValue
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
AsyncFunction("requestImage") { (options: RequestImageOptions) async throws -> Void in
|
|
96
|
+
guard
|
|
97
|
+
let localIdentifier = options.localIdentifier,
|
|
98
|
+
let targetSize = options.targetSize,
|
|
99
|
+
let contentMode = options.contentMode,
|
|
100
|
+
let outputURL = options.outputURL
|
|
101
|
+
else {
|
|
102
|
+
throw ExpoPhotosError.mandatoryFieldMissing
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
guard let asset = PHAsset.fetchAsset(withLocalIdentifier: localIdentifier) else {
|
|
106
|
+
throw ExpoPhotosError.couldNotFindAsset
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let imageRequestOptions = PHImageRequestOptions()
|
|
110
|
+
|
|
111
|
+
if let isNetworkAccessAllowed = options.isNetworkAccessAllowed {
|
|
112
|
+
imageRequestOptions.isNetworkAccessAllowed = isNetworkAccessAllowed
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if let deliveryMode = options.deliveryMode {
|
|
116
|
+
imageRequestOptions.deliveryMode = deliveryMode
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if let resizeMode = options.resizeMode {
|
|
120
|
+
imageRequestOptions.resizeMode = resizeMode
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let deadline = options.timeout.map { DispatchTime.now() + $0 }
|
|
124
|
+
|
|
125
|
+
let image = try await withCheckedThrowingContinuation {
|
|
126
|
+
(continuation: CheckedContinuation<UIImage, Error>) in
|
|
127
|
+
let requestId = PHImageManager.default().requestImage(
|
|
128
|
+
for: asset,
|
|
129
|
+
targetSize: targetSize,
|
|
130
|
+
contentMode: contentMode,
|
|
131
|
+
options: imageRequestOptions
|
|
132
|
+
) { image, info in
|
|
133
|
+
guard let image = image else {
|
|
134
|
+
let error = info?[PHImageErrorKey] as? Error ?? ExpoPhotosError.unknown
|
|
135
|
+
continuation.resume(throwing: error)
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
continuation.resume(returning: image)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if let deadline = deadline {
|
|
142
|
+
DispatchQueue.global().asyncAfter(deadline: deadline) {
|
|
143
|
+
PHImageManager.default().cancelImageRequest(requestId)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
var imageCoderOptions: [SDImageCoderOption: Any] = [:]
|
|
149
|
+
|
|
150
|
+
if let encodeCompressionQuality = options.encodeCompressionQuality {
|
|
151
|
+
imageCoderOptions[.encodeCompressionQuality] = encodeCompressionQuality
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if let encodeMaxFileSize = options.encodeMaxFileSize {
|
|
155
|
+
imageCoderOptions[.encodeMaxFileSize] = encodeMaxFileSize
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
guard
|
|
159
|
+
let data = SDImageWebPCoder.shared.encodedData(
|
|
160
|
+
with: image, format: .webP, options: imageCoderOptions)
|
|
161
|
+
else {
|
|
162
|
+
throw ExpoPhotosError.couldNotEncodeImage
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try data.write(to: outputURL)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
AsyncFunction("requestVideo") { (options: RequestVideoOptions) async throws -> Void in
|
|
169
|
+
guard
|
|
170
|
+
let localIdentifier = options.localIdentifier,
|
|
171
|
+
let exportPreset = options.exportPreset,
|
|
172
|
+
options.outputURL != nil
|
|
173
|
+
else {
|
|
174
|
+
throw ExpoPhotosError.mandatoryFieldMissing
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
guard let asset = PHAsset.fetchAsset(withLocalIdentifier: localIdentifier) else {
|
|
178
|
+
throw ExpoPhotosError.couldNotFindAsset
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let videoRequestOptions = PHVideoRequestOptions()
|
|
182
|
+
|
|
183
|
+
if let isNetworkAccessAllowed = options.isNetworkAccessAllowed {
|
|
184
|
+
videoRequestOptions.isNetworkAccessAllowed = isNetworkAccessAllowed
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if let deliveryMode = options.deliveryMode {
|
|
188
|
+
videoRequestOptions.deliveryMode = deliveryMode
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let deadline = options.timeout.map { DispatchTime.now() + $0 }
|
|
192
|
+
|
|
193
|
+
let exportSession = try await withCheckedThrowingContinuation {
|
|
194
|
+
(continuation: CheckedContinuation<AVAssetExportSession, Error>) in
|
|
195
|
+
let requestId = PHImageManager.default().requestExportSession(
|
|
196
|
+
forVideo: asset,
|
|
197
|
+
options: videoRequestOptions,
|
|
198
|
+
exportPreset: exportPreset
|
|
199
|
+
) { exportSession, info in
|
|
200
|
+
guard let exportSession = exportSession else {
|
|
201
|
+
let error = info?[PHImageErrorKey] as? Error ?? ExpoPhotosError.unknown
|
|
202
|
+
continuation.resume(throwing: error)
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
continuation.resume(returning: exportSession)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if let deadline = deadline {
|
|
209
|
+
DispatchQueue.global().asyncAfter(deadline: deadline) {
|
|
210
|
+
PHImageManager.default().cancelImageRequest(requestId)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if let outputURL = options.outputURL {
|
|
216
|
+
exportSession.outputURL = outputURL
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if let outputFileType = options.outputFileType {
|
|
220
|
+
exportSession.outputFileType = outputFileType
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if let fileLengthLimit = options.fileLengthLimit {
|
|
224
|
+
exportSession.fileLengthLimit = fileLengthLimit
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if let timeRange = options.timeRange {
|
|
228
|
+
exportSession.timeRange = timeRange
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
try await withCheckedThrowingContinuation {
|
|
232
|
+
(continuation: CheckedContinuation<Void, Error>) in
|
|
233
|
+
exportSession.exportAsynchronously {
|
|
234
|
+
switch exportSession.status {
|
|
235
|
+
case .completed:
|
|
236
|
+
continuation.resume()
|
|
237
|
+
default:
|
|
238
|
+
let error = exportSession.error ?? ExpoPhotosError.unknown
|
|
239
|
+
continuation.resume(throwing: error)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if let deadline = deadline {
|
|
244
|
+
DispatchQueue.global().asyncAfter(deadline: deadline) {
|
|
245
|
+
exportSession.cancelExport()
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
AsyncFunction("presentLimitedLibraryPicker") { () async throws -> Void in
|
|
252
|
+
guard let viewController = self.appContext?.utilities?.currentViewController() else {
|
|
253
|
+
throw ExpoPhotosError.noViewController
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
await PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: viewController)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
AsyncFunction("pickAssets") { (options: PickAssetsOptions) async throws -> [[String: Any]] in
|
|
260
|
+
guard let viewController = self.appContext?.utilities?.currentViewController() else {
|
|
261
|
+
throw ExpoPhotosError.noViewController
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let picker: PHPickerViewController = await MainActor.run {
|
|
265
|
+
var config = PHPickerConfiguration(photoLibrary: .shared())
|
|
266
|
+
|
|
267
|
+
if let selectionLimit = options.selectionLimit {
|
|
268
|
+
config.selectionLimit = selectionLimit
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if let filter = options.filter {
|
|
272
|
+
config.filter = filter
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
let picker = PHPickerViewController(configuration: config)
|
|
276
|
+
picker.delegate = self
|
|
277
|
+
|
|
278
|
+
return picker
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return try await withCheckedThrowingContinuation {
|
|
282
|
+
(continuation: CheckedContinuation<[[String: Any]], Error>) in
|
|
283
|
+
self.pickAssetsContinuations[picker.id] = continuation
|
|
284
|
+
|
|
285
|
+
Task {
|
|
286
|
+
await viewController.present(picker, animated: true, completion: nil)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
extension ExpoPhotos: PHPickerViewControllerDelegate {
|
|
294
|
+
public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
|
295
|
+
picker.dismiss(animated: true, completion: nil)
|
|
296
|
+
|
|
297
|
+
guard let continuation = self.pickAssetsContinuations[picker.id] else {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
self.pickAssetsContinuations.removeValue(forKey: picker.id)
|
|
302
|
+
|
|
303
|
+
let assetIdentifiers = results.compactMap { $0.assetIdentifier }
|
|
304
|
+
var assets: [[String: Any]] = []
|
|
305
|
+
PHAsset.fetchAssets(withLocalIdentifiers: assetIdentifiers, options: nil).enumerateObjects {
|
|
306
|
+
asset, _, _ in
|
|
307
|
+
assets.append(asset.toJS())
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
continuation.resume(returning: assets)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
extension PHPickerViewController {
|
|
315
|
+
var id: ObjectIdentifier {
|
|
316
|
+
return ObjectIdentifier(self)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
extension TimeInterval: @retroactive Convertible {
|
|
321
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
322
|
+
guard let milliseconds = value as? Int else {
|
|
323
|
+
throw Conversions.ConvertingException<Self>(value)
|
|
324
|
+
}
|
|
325
|
+
return Double(milliseconds) / 1000
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
func toJS() -> Int {
|
|
329
|
+
return Int(self * 1000)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
extension CMTime {
|
|
334
|
+
func toJS() -> Int {
|
|
335
|
+
return Int(self.seconds * 1000)
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
extension PHAsset {
|
|
340
|
+
public static func fetchAsset(withLocalIdentifier identifier: String) -> PHAsset? {
|
|
341
|
+
return PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil).firstObject
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
func toJS() -> [String: Any] {
|
|
345
|
+
return [
|
|
346
|
+
"localIdentifier": localIdentifier,
|
|
347
|
+
"creationDate": creationDate?.timeIntervalSince1970.toJS() ?? NSNull(),
|
|
348
|
+
"mediaType": mediaType.rawValue,
|
|
349
|
+
"mediaSubtypes": mediaSubtypes.rawValue,
|
|
350
|
+
"duration": duration.toJS(),
|
|
351
|
+
]
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
extension NSSortDescriptor: @retroactive Convertible {
|
|
356
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
357
|
+
guard
|
|
358
|
+
let dict = value as? [String: Any],
|
|
359
|
+
let key = dict["key"] as? String,
|
|
360
|
+
let ascending = dict["ascending"] as? Bool
|
|
361
|
+
else {
|
|
362
|
+
throw Conversions.ConvertingException<NSSortDescriptor>(value)
|
|
363
|
+
}
|
|
364
|
+
return Self(key: key, ascending: ascending)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
extension NSPredicate: @retroactive Convertible {
|
|
369
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
370
|
+
guard
|
|
371
|
+
let rawValue = value as? String,
|
|
372
|
+
let predicate = NSPredicate(format: rawValue) as? Self
|
|
373
|
+
else {
|
|
374
|
+
throw Conversions.ConvertingException<Self>(value)
|
|
375
|
+
}
|
|
376
|
+
return predicate
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
extension CMTimeRange: @retroactive Convertible {
|
|
381
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
382
|
+
guard let dict = value as? [String: Any],
|
|
383
|
+
let startMs = dict["start"] as? Int,
|
|
384
|
+
let durationMs = dict["duration"] as? Int
|
|
385
|
+
else {
|
|
386
|
+
throw Conversions.ConvertingException<CMTimeRange>(value)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return Self(
|
|
390
|
+
start: CMTimeMakeWithSeconds(Double(startMs) / 1000, preferredTimescale: 600),
|
|
391
|
+
duration: CMTimeMakeWithSeconds(Double(durationMs) / 1000, preferredTimescale: 600)
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
extension Convertible where Self: RawRepresentable, Self.RawValue == Int {
|
|
397
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
398
|
+
guard
|
|
399
|
+
let rawValue = value as? Int,
|
|
400
|
+
let enumValue = Self(rawValue: rawValue)
|
|
401
|
+
else {
|
|
402
|
+
throw Conversions.ConvertingException<Self>(value)
|
|
403
|
+
}
|
|
404
|
+
return enumValue
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
extension Convertible where Self: RawRepresentable, Self.RawValue == String {
|
|
409
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
410
|
+
guard
|
|
411
|
+
let rawValue = value as? String,
|
|
412
|
+
let enumValue = Self(rawValue: rawValue)
|
|
413
|
+
else {
|
|
414
|
+
throw Conversions.ConvertingException<Self>(value)
|
|
415
|
+
}
|
|
416
|
+
return enumValue
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
extension PHImageRequestOptionsDeliveryMode: @retroactive Convertible {}
|
|
421
|
+
extension PHImageRequestOptionsResizeMode: @retroactive Convertible {}
|
|
422
|
+
extension PHImageContentMode: @retroactive Convertible {}
|
|
423
|
+
extension PHVideoRequestOptionsDeliveryMode: @retroactive Convertible {}
|
|
424
|
+
extension AVFileType: @retroactive Convertible {}
|
|
425
|
+
extension PHAccessLevel: @retroactive Convertible {}
|
|
426
|
+
|
|
427
|
+
extension PHPickerFilter: @retroactive Convertible {
|
|
428
|
+
public static func convert(from value: Any?, appContext: AppContext) throws -> Self {
|
|
429
|
+
guard let rawValue = value as? String else {
|
|
430
|
+
throw Conversions.ConvertingException<Self>(value)
|
|
431
|
+
}
|
|
432
|
+
switch rawValue {
|
|
433
|
+
case "images":
|
|
434
|
+
return .images
|
|
435
|
+
case "videos":
|
|
436
|
+
return .videos
|
|
437
|
+
case "any":
|
|
438
|
+
return .any(of: [.images, .videos])
|
|
439
|
+
default:
|
|
440
|
+
throw Conversions.ConvertingException<Self>(value)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hortemo/expo-photos",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Expo module exposing advanced iOS Photos APIs.",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "expo-module build",
|
|
9
|
+
"clean": "expo-module clean",
|
|
10
|
+
"lint": "expo-module lint",
|
|
11
|
+
"test": "./e2e/e2e.sh",
|
|
12
|
+
"prepare": "expo-module prepare",
|
|
13
|
+
"prepublishOnly": "expo-module prepublishOnly",
|
|
14
|
+
"expo-module": "expo-module"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"react-native",
|
|
18
|
+
"expo",
|
|
19
|
+
"photos",
|
|
20
|
+
"ios",
|
|
21
|
+
"@hortemo/expo-photos"
|
|
22
|
+
],
|
|
23
|
+
"repository": "https://github.com/hortemo/expo-photos",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/hortemo/expo-photos/issues"
|
|
26
|
+
},
|
|
27
|
+
"author": "Henrik Hortemo <henrikhortemo@icloud.com> (https://github.com/hortemo)",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"homepage": "https://github.com/hortemo/expo-photos#readme",
|
|
30
|
+
"dependencies": {},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/react": "~19.1.0",
|
|
33
|
+
"eslint": "^9.24.0",
|
|
34
|
+
"expo": "^54.0.12",
|
|
35
|
+
"expo-module-scripts": "^5.0.7",
|
|
36
|
+
"react-native": "0.81.4"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"expo": "*",
|
|
40
|
+
"react": "*",
|
|
41
|
+
"react-native": "*"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
export interface PHAsset {
|
|
2
|
+
localIdentifier: string;
|
|
3
|
+
creationDate: number;
|
|
4
|
+
mediaType: PHAssetMediaType;
|
|
5
|
+
mediaSubtypes: PHAssetMediaSubtype;
|
|
6
|
+
duration: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export enum PHAuthorizationStatus {
|
|
10
|
+
notDetermined = 0,
|
|
11
|
+
restricted = 1,
|
|
12
|
+
denied = 2,
|
|
13
|
+
authorized = 3,
|
|
14
|
+
limited = 4,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export enum PHAccessLevel {
|
|
18
|
+
addOnly = 1,
|
|
19
|
+
readWrite = 2,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export enum PHAssetMediaType {
|
|
23
|
+
Unknown = 0,
|
|
24
|
+
Image = 1,
|
|
25
|
+
Video = 2,
|
|
26
|
+
Audio = 3,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export enum PHAssetMediaSubtype {
|
|
30
|
+
None = 0,
|
|
31
|
+
PhotoPanorama = 1 << 0,
|
|
32
|
+
PhotoHDR = 1 << 1,
|
|
33
|
+
PhotoScreenshot = 1 << 2,
|
|
34
|
+
PhotoLive = 1 << 3,
|
|
35
|
+
PhotoDepthEffect = 1 << 4,
|
|
36
|
+
VideoStreamed = 1 << 16,
|
|
37
|
+
VideoHighFrameRate = 1 << 17,
|
|
38
|
+
VideoTimelapse = 1 << 18,
|
|
39
|
+
VideoCinematic = 1 << 19,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface NSSortDescriptor {
|
|
43
|
+
key: string;
|
|
44
|
+
ascending: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface PHFetchOptions {
|
|
48
|
+
predicate?: string;
|
|
49
|
+
fetchLimit?: number;
|
|
50
|
+
sortDescriptors?: NSSortDescriptor[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type FetchAssetsOptions = PHFetchOptions;
|
|
54
|
+
|
|
55
|
+
export interface CGSize {
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export enum PHImageRequestOptionsResizeMode {
|
|
61
|
+
None = 0,
|
|
62
|
+
Fast = 1,
|
|
63
|
+
Exact = 2,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export enum PHImageRequestOptionsDeliveryMode {
|
|
67
|
+
Opportunistic = 0,
|
|
68
|
+
HighQualityFormat = 1,
|
|
69
|
+
FastFormat = 2,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export enum PHImageContentMode {
|
|
73
|
+
aspectFit = 0,
|
|
74
|
+
aspectFill = 1,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface PHImageRequestOptions {
|
|
78
|
+
isNetworkAccessAllowed?: boolean;
|
|
79
|
+
resizeMode?: PHImageRequestOptionsResizeMode;
|
|
80
|
+
deliveryMode?: PHImageRequestOptionsDeliveryMode;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface SDImageCoderOptions {
|
|
84
|
+
encodeCompressionQuality?: number;
|
|
85
|
+
encodeMaxFileSize?: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export enum PHVideoRequestOptionsDeliveryMode {
|
|
89
|
+
Automatic = 0,
|
|
90
|
+
HighQualityFormat = 1,
|
|
91
|
+
MediumQualityFormat = 2,
|
|
92
|
+
FastFormat = 3,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface PHVideoRequestOptions {
|
|
96
|
+
isNetworkAccessAllowed?: boolean;
|
|
97
|
+
deliveryMode?: PHVideoRequestOptionsDeliveryMode;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface CMTimeRange {
|
|
101
|
+
start: number;
|
|
102
|
+
duration: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export enum AVFileType {
|
|
106
|
+
ac3 = "public.ac3-audio",
|
|
107
|
+
aifc = "public.aifc-audio",
|
|
108
|
+
aiff = "public.aiff-audio",
|
|
109
|
+
AHAP = "com.apple.itt",
|
|
110
|
+
amr = "org.3gpp.adaptive-multi-rate-audio",
|
|
111
|
+
appleiTT = "com.apple.itt",
|
|
112
|
+
au = "public.au-audio",
|
|
113
|
+
avci = "public.avci",
|
|
114
|
+
caf = "com.apple.coreaudio-format",
|
|
115
|
+
dng = "com.adobe.raw-image",
|
|
116
|
+
eac3 = "public.eac3-audio",
|
|
117
|
+
heic = "public.heic",
|
|
118
|
+
heif = "public.heif",
|
|
119
|
+
jpg = "public.jpeg",
|
|
120
|
+
m4a = "com.apple.m4a-audio",
|
|
121
|
+
m4v = "com.apple.m4v-video",
|
|
122
|
+
mobile3GPP = "public.3gpp",
|
|
123
|
+
mobile3GPP2 = "public.3gpp2",
|
|
124
|
+
mov = "com.apple.quicktime-movie",
|
|
125
|
+
mp3 = "public.mp3",
|
|
126
|
+
mp4 = "public.mpeg-4",
|
|
127
|
+
SCC = "com.scenarist.cc",
|
|
128
|
+
tif = "public.tiff",
|
|
129
|
+
wav = "com.microsoft.waveform-audio",
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export enum AVAssetExportPreset {
|
|
133
|
+
LowQuality = "AVAssetExportPresetLowQuality",
|
|
134
|
+
MediumQuality = "AVAssetExportPresetMediumQuality",
|
|
135
|
+
HighestQuality = "AVAssetExportPresetHighestQuality",
|
|
136
|
+
HEVCHighestQuality = "AVAssetExportPresetHEVCHighestQuality",
|
|
137
|
+
HEVCHighestQualityWithAlpha = "AVAssetExportPresetHEVCHighestQualityWithAlpha",
|
|
138
|
+
AVC640x480 = "AVAssetExportPreset640x480",
|
|
139
|
+
AVC960x540 = "AVAssetExportPreset960x540",
|
|
140
|
+
AVC1280x720 = "AVAssetExportPreset1280x720",
|
|
141
|
+
AVC1920x1080 = "AVAssetExportPreset1920x1080",
|
|
142
|
+
AVC3840x2160 = "AVAssetExportPreset3840x2160",
|
|
143
|
+
HEVC1920x1080 = "AVAssetExportPresetHEVC1920x1080",
|
|
144
|
+
HEVC3840x2160 = "AVAssetExportPresetHEVC3840x2160",
|
|
145
|
+
HEVC1920x1080WithAlpha = "AVAssetExportPresetHEVC1920x1080WithAlpha",
|
|
146
|
+
HEVC3840x2160WithAlpha = "AVAssetExportPresetHEVC3840x2160WithAlpha",
|
|
147
|
+
HEVC7680x4320 = "AVAssetExportPresetHEVC7680x4320",
|
|
148
|
+
MVHEVC960x960 = "AVAssetExportPresetMVHEVC960x960",
|
|
149
|
+
MVHEVC1440x1440 = "AVAssetExportPresetMVHEVC1440x1440",
|
|
150
|
+
AppleM4V480pSD = "AVAssetExportPresetAppleM4V480pSD",
|
|
151
|
+
AppleM4V720pHD = "AVAssetExportPresetAppleM4V720pHD",
|
|
152
|
+
AppleM4V1080pHD = "AVAssetExportPresetAppleM4V1080pHD",
|
|
153
|
+
AppleM4ViPod = "AVAssetExportPresetAppleM4ViPod",
|
|
154
|
+
AppleM4VAppleTV = "AVAssetExportPresetAppleM4VAppleTV",
|
|
155
|
+
AppleM4VCellular = "AVAssetExportPresetAppleM4VCellular",
|
|
156
|
+
AppleM4VWiFi = "AVAssetExportPresetAppleM4VWiFi",
|
|
157
|
+
AppleProRes422LPCM = "AVAssetExportPresetAppleProRes422LPCM",
|
|
158
|
+
AppleProRes4444LPCM = "AVAssetExportPresetAppleProRes4444LPCM",
|
|
159
|
+
Passthrough = "AVAssetExportPresetPassthrough",
|
|
160
|
+
AppleM4A = "AVAssetExportPresetAppleM4A",
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface AVAssetExportSessionOptions {
|
|
164
|
+
outputURL: string;
|
|
165
|
+
outputFileType?: AVFileType;
|
|
166
|
+
fileLengthLimit?: number;
|
|
167
|
+
timeRange?: CMTimeRange;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface RequestImageOptions
|
|
171
|
+
extends PHImageRequestOptions,
|
|
172
|
+
SDImageCoderOptions {
|
|
173
|
+
localIdentifier: string;
|
|
174
|
+
targetSize: CGSize;
|
|
175
|
+
contentMode: PHImageContentMode;
|
|
176
|
+
outputURL: string;
|
|
177
|
+
timeout?: number;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface RequestVideoOptions
|
|
181
|
+
extends PHVideoRequestOptions,
|
|
182
|
+
AVAssetExportSessionOptions {
|
|
183
|
+
localIdentifier: string;
|
|
184
|
+
exportPreset: AVAssetExportPreset;
|
|
185
|
+
timeout?: number;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export enum PHPickerFilter {
|
|
189
|
+
images = "images",
|
|
190
|
+
videos = "videos",
|
|
191
|
+
any = "any",
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface PickAssetsOptions {
|
|
195
|
+
filter?: PHPickerFilter;
|
|
196
|
+
selectionLimit?: number;
|
|
197
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NativeModule, requireNativeModule } from "expo-modules-core";
|
|
2
|
+
import type {
|
|
3
|
+
FetchAssetsOptions,
|
|
4
|
+
PHAuthorizationStatus,
|
|
5
|
+
PHAccessLevel,
|
|
6
|
+
PHAsset,
|
|
7
|
+
PickAssetsOptions,
|
|
8
|
+
RequestImageOptions,
|
|
9
|
+
RequestVideoOptions,
|
|
10
|
+
} from "./ExpoPhotos.types";
|
|
11
|
+
|
|
12
|
+
export declare class ExpoPhotosModule extends NativeModule {
|
|
13
|
+
fetchAssets(options: FetchAssetsOptions): Promise<PHAsset[]>;
|
|
14
|
+
requestImage(options: RequestImageOptions): Promise<void>;
|
|
15
|
+
requestVideo(options: RequestVideoOptions): Promise<void>;
|
|
16
|
+
pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>;
|
|
17
|
+
requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;
|
|
18
|
+
presentLimitedLibraryPicker(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default requireNativeModule<ExpoPhotosModule>("ExpoPhotos");
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED