@hortemo/expo-photos 3.0.0 → 5.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/README.md +22 -0
- package/build/ExpoPhotos.types.d.ts +12 -0
- package/build/ExpoPhotos.types.d.ts.map +1 -1
- package/build/ExpoPhotos.types.js.map +1 -1
- package/build/ExpoPhotosModule.d.ts +1 -0
- package/build/ExpoPhotosModule.d.ts.map +1 -1
- package/build/ExpoPhotosModule.js.map +1 -1
- package/build/PHVideo.d.ts +13 -0
- package/build/PHVideo.d.ts.map +1 -0
- package/build/PHVideo.js +6 -0
- package/build/PHVideo.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/ios/ExpoPhotosModule.swift +23 -1
- package/ios/PHVideoView.swift +164 -0
- package/package.json +1 -2
- package/src/ExpoPhotos.types.ts +11 -0
- package/src/ExpoPhotosModule.ts +1 -0
- package/src/PHVideo.tsx +19 -0
- package/src/index.ts +2 -0
package/README.md
CHANGED
|
@@ -10,10 +10,32 @@ npm install @hortemo/expo-photos
|
|
|
10
10
|
|
|
11
11
|
## API Reference
|
|
12
12
|
|
|
13
|
+
### Functions
|
|
14
|
+
|
|
13
15
|
- `fetchAssets(options: FetchAssetsOptions): Promise<PHAsset[]>`
|
|
14
16
|
- `requestImage(options: RequestImageOptions): Promise<void>`
|
|
15
17
|
- `requestVideo(options: RequestVideoOptions): Promise<void>`
|
|
16
18
|
- `pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>`
|
|
19
|
+
- `authorizationStatus(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>`
|
|
17
20
|
- `requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>`
|
|
18
21
|
- `presentLimitedLibraryPicker(): Promise<void>`
|
|
19
22
|
- `createPHImageSource(options: PHImageSourceOptions): ImageSourcePropType | undefined`
|
|
23
|
+
|
|
24
|
+
### Components
|
|
25
|
+
|
|
26
|
+
#### PHVideo
|
|
27
|
+
|
|
28
|
+
A video player component that streams videos from the library.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { PHVideo, PHVideoRequestOptionsDeliveryMode } from "@hortemo/expo-photos";
|
|
32
|
+
|
|
33
|
+
<PHVideo
|
|
34
|
+
localIdentifier={asset.localIdentifier}
|
|
35
|
+
isNetworkAccessAllowed={true}
|
|
36
|
+
deliveryMode={PHVideoRequestOptionsDeliveryMode.Automatic}
|
|
37
|
+
onLoad={(event) => console.log(event.nativeEvent)}
|
|
38
|
+
onError={(event) => console.log(event.nativeEvent.message)}
|
|
39
|
+
style={{ width: 300, height: 200 }}
|
|
40
|
+
/>
|
|
41
|
+
```
|
|
@@ -4,6 +4,8 @@ export interface PHAsset {
|
|
|
4
4
|
mediaType: PHAssetMediaType;
|
|
5
5
|
mediaSubtypes: PHAssetMediaSubtype;
|
|
6
6
|
duration: number;
|
|
7
|
+
pixelWidth: number;
|
|
8
|
+
pixelHeight: number;
|
|
7
9
|
}
|
|
8
10
|
export declare enum PHAuthorizationStatus {
|
|
9
11
|
notDetermined = 0,
|
|
@@ -175,4 +177,14 @@ export interface PickAssetsOptions {
|
|
|
175
177
|
filter?: PHPickerFilter;
|
|
176
178
|
selectionLimit?: number;
|
|
177
179
|
}
|
|
180
|
+
export interface PHVideoLoadEvent {
|
|
181
|
+
duration: number;
|
|
182
|
+
naturalSize: {
|
|
183
|
+
width: number;
|
|
184
|
+
height: number;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
export interface PHVideoErrorEvent {
|
|
188
|
+
message: string;
|
|
189
|
+
}
|
|
178
190
|
//# sourceMappingURL=ExpoPhotos.types.d.ts.map
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"ExpoPhotos.types.d.ts","sourceRoot":"","sources":["../src/ExpoPhotos.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoPhotos.types.js","sourceRoot":"","sources":["../src/ExpoPhotos.types.ts"],"names":[],"mappings":"
|
|
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 pixelWidth: number;\n pixelHeight: 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 type PHImageManagerMaximumSize = \"PHImageManagerMaximumSize\";\n\nexport type RequestImageTargetSize = CGSize | PHImageManagerMaximumSize;\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: RequestImageTargetSize;\n contentMode: PHImageContentMode;\n outputURL?: string;\n timeout?: number;\n}\n\nexport interface RequestImageResult {\n size: CGSize;\n scale: number;\n imageOrientation: 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\nexport interface PHVideoLoadEvent {\n duration: number;\n naturalSize: { width: number; height: number };\n}\n\nexport interface PHVideoErrorEvent {\n message: string;\n}\n"]}
|
|
@@ -5,6 +5,7 @@ export declare class ExpoPhotosModule extends NativeModule {
|
|
|
5
5
|
requestImage(options: RequestImageOptions): Promise<RequestImageResult>;
|
|
6
6
|
requestVideo(options: RequestVideoOptions): Promise<void>;
|
|
7
7
|
pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>;
|
|
8
|
+
authorizationStatus(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;
|
|
8
9
|
requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;
|
|
9
10
|
presentLimitedLibraryPicker(): Promise<void>;
|
|
10
11
|
}
|
|
@@ -1 +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,EACnB,kBAAkB,EACnB,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,kBAAkB,CAAC;IACvE,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"}
|
|
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,EACnB,kBAAkB,EACnB,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,kBAAkB,CAAC;IACvE,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IACzD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1D,mBAAmB,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAC/E,oBAAoB,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAChF,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;CAC7C;;AAED,wBAAmE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoPhotosModule.js","sourceRoot":"","sources":["../src/ExpoPhotosModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpoPhotosModule.js","sourceRoot":"","sources":["../src/ExpoPhotosModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAsBtE,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 RequestImageResult,\n} from \"./ExpoPhotos.types\";\n\nexport declare class ExpoPhotosModule extends NativeModule {\n fetchAssets(options: FetchAssetsOptions): Promise<PHAsset[]>;\n requestImage(options: RequestImageOptions): Promise<RequestImageResult>;\n requestVideo(options: RequestVideoOptions): Promise<void>;\n pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>;\n authorizationStatus(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;\n requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;\n presentLimitedLibraryPicker(): Promise<void>;\n}\n\nexport default requireNativeModule<ExpoPhotosModule>(\"ExpoPhotos\");\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ViewProps } from "react-native";
|
|
2
|
+
import { PHVideoLoadEvent, PHVideoErrorEvent, PHVideoRequestOptions } from "./ExpoPhotos.types";
|
|
3
|
+
export interface PHVideoProps extends ViewProps, PHVideoRequestOptions {
|
|
4
|
+
localIdentifier: string;
|
|
5
|
+
onLoad?: (event: {
|
|
6
|
+
nativeEvent: PHVideoLoadEvent;
|
|
7
|
+
}) => void;
|
|
8
|
+
onError?: (event: {
|
|
9
|
+
nativeEvent: PHVideoErrorEvent;
|
|
10
|
+
}) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function PHVideo(props: PHVideoProps): import("react").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=PHVideo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PHVideo.d.ts","sourceRoot":"","sources":["../src/PHVideo.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,YAAa,SAAQ,SAAS,EAAE,qBAAqB;IACpE,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,gBAAgB,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,iBAAiB,CAAA;KAAE,KAAK,IAAI,CAAC;CAC/D;AAID,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,+BAE1C"}
|
package/build/PHVideo.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PHVideo.js","sourceRoot":"","sources":["../src/PHVideo.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAc7D,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAEhF,MAAM,UAAU,OAAO,CAAC,KAAmB;IACzC,OAAO,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AAC1C,CAAC","sourcesContent":["import { requireNativeViewManager } from \"expo-modules-core\";\nimport { ViewProps } from \"react-native\";\nimport {\n PHVideoLoadEvent,\n PHVideoErrorEvent,\n PHVideoRequestOptions,\n} from \"./ExpoPhotos.types\";\n\nexport interface PHVideoProps extends ViewProps, PHVideoRequestOptions {\n localIdentifier: string;\n onLoad?: (event: { nativeEvent: PHVideoLoadEvent }) => void;\n onError?: (event: { nativeEvent: PHVideoErrorEvent }) => void;\n}\n\nconst NativePHVideoView = requireNativeViewManager(\"ExpoPhotos\", \"PHVideoView\");\n\nexport function PHVideo(props: PHVideoProps) {\n return <NativePHVideoView {...props} />;\n}\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -2,4 +2,6 @@ export { default } from "./ExpoPhotosModule";
|
|
|
2
2
|
export * from "./ExpoPhotos.types";
|
|
3
3
|
export { createPHImageSource } from "./PHImageSource";
|
|
4
4
|
export type { PHImageSourceOptions } from "./PHImageSource";
|
|
5
|
+
export { PHVideo } from "./PHVideo";
|
|
6
|
+
export type { PHVideoProps } from "./PHVideo";
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +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;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
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;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +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;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export { default } from \"./ExpoPhotosModule\";\nexport * from \"./ExpoPhotos.types\";\nexport { createPHImageSource } from \"./PHImageSource\";\nexport type { PHImageSourceOptions } from \"./PHImageSource\";\n"]}
|
|
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;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export { default } from \"./ExpoPhotosModule\";\nexport * from \"./ExpoPhotos.types\";\nexport { createPHImageSource } from \"./PHImageSource\";\nexport type { PHImageSourceOptions } from \"./PHImageSource\";\nexport { PHVideo } from \"./PHVideo\";\nexport type { PHVideoProps } from \"./PHVideo\";\n"]}
|
|
@@ -57,7 +57,7 @@ enum ExpoPhotosError: Error {
|
|
|
57
57
|
case unknown
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
public class ExpoPhotos: Module {
|
|
60
|
+
public final class ExpoPhotos: Module {
|
|
61
61
|
private var pickAssetsContinuations = [
|
|
62
62
|
ObjectIdentifier: CheckedContinuation<[[String: Any]], Error>
|
|
63
63
|
]()
|
|
@@ -87,6 +87,10 @@ public class ExpoPhotos: Module {
|
|
|
87
87
|
return assets
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
AsyncFunction("authorizationStatus") { (accessLevel: PHAccessLevel) -> Int in
|
|
91
|
+
return PHPhotoLibrary.authorizationStatus(for: accessLevel).rawValue
|
|
92
|
+
}
|
|
93
|
+
|
|
90
94
|
AsyncFunction("requestAuthorization") { (accessLevel: PHAccessLevel) async throws -> Int in
|
|
91
95
|
let status = await PHPhotoLibrary.requestAuthorization(for: accessLevel)
|
|
92
96
|
return status.rawValue
|
|
@@ -297,6 +301,22 @@ public class ExpoPhotos: Module {
|
|
|
297
301
|
}
|
|
298
302
|
}
|
|
299
303
|
}
|
|
304
|
+
|
|
305
|
+
View(PHVideoView.self) {
|
|
306
|
+
Prop("localIdentifier") { (view: PHVideoView, localIdentifier: String?) in
|
|
307
|
+
view.localIdentifier = localIdentifier
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
Prop("isNetworkAccessAllowed") { (view: PHVideoView, isNetworkAccessAllowed: Bool?) in
|
|
311
|
+
view.isNetworkAccessAllowed = isNetworkAccessAllowed ?? true
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
Prop("deliveryMode") { (view: PHVideoView, deliveryMode: PHVideoRequestOptionsDeliveryMode?) in
|
|
315
|
+
view.deliveryMode = deliveryMode ?? .automatic
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
Events("onLoad", "onError")
|
|
319
|
+
}
|
|
300
320
|
}
|
|
301
321
|
}
|
|
302
322
|
|
|
@@ -358,6 +378,8 @@ extension PHAsset {
|
|
|
358
378
|
"mediaType": mediaType.rawValue,
|
|
359
379
|
"mediaSubtypes": mediaSubtypes.rawValue,
|
|
360
380
|
"duration": duration.toJS(),
|
|
381
|
+
"pixelWidth": pixelWidth,
|
|
382
|
+
"pixelHeight": pixelHeight,
|
|
361
383
|
]
|
|
362
384
|
}
|
|
363
385
|
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
import ExpoModulesCore
|
|
3
|
+
import Photos
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
public final class PHVideoView: ExpoView {
|
|
7
|
+
let onLoad = EventDispatcher()
|
|
8
|
+
let onError = EventDispatcher()
|
|
9
|
+
|
|
10
|
+
private var playerLayer: AVPlayerLayer?
|
|
11
|
+
private var playerLooper: AVPlayerLooper?
|
|
12
|
+
private var queuePlayer: AVQueuePlayer?
|
|
13
|
+
private var templateItem: AVPlayerItem?
|
|
14
|
+
private var currentRequestId: PHImageRequestID?
|
|
15
|
+
private var statusObserver: NSKeyValueObservation?
|
|
16
|
+
private var didSendLoadEvent = false
|
|
17
|
+
|
|
18
|
+
var localIdentifier: String? {
|
|
19
|
+
didSet {
|
|
20
|
+
if localIdentifier != oldValue {
|
|
21
|
+
loadVideo()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var isNetworkAccessAllowed: Bool = true {
|
|
27
|
+
didSet {
|
|
28
|
+
if isNetworkAccessAllowed != oldValue {
|
|
29
|
+
loadVideo()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var deliveryMode: PHVideoRequestOptionsDeliveryMode = .automatic {
|
|
35
|
+
didSet {
|
|
36
|
+
if deliveryMode != oldValue {
|
|
37
|
+
loadVideo()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public required init(appContext: AppContext? = nil) {
|
|
43
|
+
super.init(appContext: appContext)
|
|
44
|
+
setupPlayerLayer()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private func setupPlayerLayer() {
|
|
48
|
+
let layer = AVPlayerLayer()
|
|
49
|
+
layer.videoGravity = .resizeAspect
|
|
50
|
+
self.layer.addSublayer(layer)
|
|
51
|
+
playerLayer = layer
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public override func layoutSubviews() {
|
|
55
|
+
super.layoutSubviews()
|
|
56
|
+
playerLayer?.frame = bounds
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public override func willMove(toWindow newWindow: UIWindow?) {
|
|
60
|
+
super.willMove(toWindow: newWindow)
|
|
61
|
+
if newWindow == nil {
|
|
62
|
+
cleanup()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private func loadVideo() {
|
|
67
|
+
cleanup()
|
|
68
|
+
|
|
69
|
+
guard let localIdentifier = localIdentifier else { return }
|
|
70
|
+
|
|
71
|
+
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil).firstObject else {
|
|
72
|
+
onError(["message": "Asset not found for identifier: \(localIdentifier)"])
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let options = PHVideoRequestOptions()
|
|
77
|
+
options.isNetworkAccessAllowed = isNetworkAccessAllowed
|
|
78
|
+
options.deliveryMode = deliveryMode
|
|
79
|
+
|
|
80
|
+
currentRequestId = PHImageManager.default().requestPlayerItem(forVideo: asset, options: options) { [weak self] playerItem, info in
|
|
81
|
+
guard let self = self else { return }
|
|
82
|
+
|
|
83
|
+
DispatchQueue.main.async {
|
|
84
|
+
if let error = info?[PHImageErrorKey] as? Error {
|
|
85
|
+
self.onError(["message": error.localizedDescription])
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
guard let playerItem = playerItem else {
|
|
90
|
+
self.onError(["message": "Failed to load video"])
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
self.setupPlayer(with: playerItem)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func setupPlayer(with playerItem: AVPlayerItem) {
|
|
100
|
+
didSendLoadEvent = false
|
|
101
|
+
|
|
102
|
+
// AVPlayerLooper requires an empty AVQueuePlayer - it manages the items
|
|
103
|
+
let queuePlayer = AVQueuePlayer()
|
|
104
|
+
queuePlayer.isMuted = false
|
|
105
|
+
|
|
106
|
+
// Keep strong reference to template item
|
|
107
|
+
self.templateItem = playerItem
|
|
108
|
+
|
|
109
|
+
// Create looper - it will insert copies of the template item
|
|
110
|
+
let looper = AVPlayerLooper(player: queuePlayer, templateItem: playerItem)
|
|
111
|
+
|
|
112
|
+
playerLayer?.player = queuePlayer
|
|
113
|
+
self.queuePlayer = queuePlayer
|
|
114
|
+
self.playerLooper = looper
|
|
115
|
+
|
|
116
|
+
// Observe the queue player's current item status
|
|
117
|
+
statusObserver = queuePlayer.observe(\.status, options: [.initial, .new]) { [weak self] player, _ in
|
|
118
|
+
guard let self = self else { return }
|
|
119
|
+
|
|
120
|
+
DispatchQueue.main.async {
|
|
121
|
+
switch player.status {
|
|
122
|
+
case .readyToPlay:
|
|
123
|
+
if !self.didSendLoadEvent {
|
|
124
|
+
self.didSendLoadEvent = true
|
|
125
|
+
let duration = playerItem.asset.duration.seconds.isFinite ? playerItem.asset.duration.seconds * 1000 : 0
|
|
126
|
+
let tracks = playerItem.asset.tracks(withMediaType: .video)
|
|
127
|
+
let size = tracks.first?.naturalSize ?? .zero
|
|
128
|
+
self.onLoad([
|
|
129
|
+
"duration": duration,
|
|
130
|
+
"naturalSize": [
|
|
131
|
+
"width": size.width,
|
|
132
|
+
"height": size.height
|
|
133
|
+
]
|
|
134
|
+
])
|
|
135
|
+
}
|
|
136
|
+
player.play()
|
|
137
|
+
case .failed:
|
|
138
|
+
let message = player.error?.localizedDescription ?? "Unknown error"
|
|
139
|
+
self.onError(["message": message])
|
|
140
|
+
default:
|
|
141
|
+
break
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private func cleanup() {
|
|
148
|
+
statusObserver?.invalidate()
|
|
149
|
+
statusObserver = nil
|
|
150
|
+
|
|
151
|
+
if let requestId = currentRequestId {
|
|
152
|
+
PHImageManager.default().cancelImageRequest(requestId)
|
|
153
|
+
currentRequestId = nil
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
queuePlayer?.pause()
|
|
157
|
+
queuePlayer?.removeAllItems()
|
|
158
|
+
playerLooper = nil
|
|
159
|
+
queuePlayer = nil
|
|
160
|
+
templateItem = nil
|
|
161
|
+
playerLayer?.player = nil
|
|
162
|
+
didSendLoadEvent = false
|
|
163
|
+
}
|
|
164
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hortemo/expo-photos",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Expo module exposing advanced iOS Photos APIs.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"expo": "*",
|
|
40
|
-
"react": "*",
|
|
41
40
|
"react-native": "*"
|
|
42
41
|
},
|
|
43
42
|
"codegenConfig": {
|
package/src/ExpoPhotos.types.ts
CHANGED
|
@@ -4,6 +4,8 @@ export interface PHAsset {
|
|
|
4
4
|
mediaType: PHAssetMediaType;
|
|
5
5
|
mediaSubtypes: PHAssetMediaSubtype;
|
|
6
6
|
duration: number;
|
|
7
|
+
pixelWidth: number;
|
|
8
|
+
pixelHeight: number;
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
export enum PHAuthorizationStatus {
|
|
@@ -205,3 +207,12 @@ export interface PickAssetsOptions {
|
|
|
205
207
|
filter?: PHPickerFilter;
|
|
206
208
|
selectionLimit?: number;
|
|
207
209
|
}
|
|
210
|
+
|
|
211
|
+
export interface PHVideoLoadEvent {
|
|
212
|
+
duration: number;
|
|
213
|
+
naturalSize: { width: number; height: number };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface PHVideoErrorEvent {
|
|
217
|
+
message: string;
|
|
218
|
+
}
|
package/src/ExpoPhotosModule.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class ExpoPhotosModule extends NativeModule {
|
|
|
15
15
|
requestImage(options: RequestImageOptions): Promise<RequestImageResult>;
|
|
16
16
|
requestVideo(options: RequestVideoOptions): Promise<void>;
|
|
17
17
|
pickAssets(options: PickAssetsOptions): Promise<PHAsset[]>;
|
|
18
|
+
authorizationStatus(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;
|
|
18
19
|
requestAuthorization(accessLevel: PHAccessLevel): Promise<PHAuthorizationStatus>;
|
|
19
20
|
presentLimitedLibraryPicker(): Promise<void>;
|
|
20
21
|
}
|
package/src/PHVideo.tsx
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { requireNativeViewManager } from "expo-modules-core";
|
|
2
|
+
import { ViewProps } from "react-native";
|
|
3
|
+
import {
|
|
4
|
+
PHVideoLoadEvent,
|
|
5
|
+
PHVideoErrorEvent,
|
|
6
|
+
PHVideoRequestOptions,
|
|
7
|
+
} from "./ExpoPhotos.types";
|
|
8
|
+
|
|
9
|
+
export interface PHVideoProps extends ViewProps, PHVideoRequestOptions {
|
|
10
|
+
localIdentifier: string;
|
|
11
|
+
onLoad?: (event: { nativeEvent: PHVideoLoadEvent }) => void;
|
|
12
|
+
onError?: (event: { nativeEvent: PHVideoErrorEvent }) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const NativePHVideoView = requireNativeViewManager("ExpoPhotos", "PHVideoView");
|
|
16
|
+
|
|
17
|
+
export function PHVideo(props: PHVideoProps) {
|
|
18
|
+
return <NativePHVideoView {...props} />;
|
|
19
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,3 +2,5 @@ export { default } from "./ExpoPhotosModule";
|
|
|
2
2
|
export * from "./ExpoPhotos.types";
|
|
3
3
|
export { createPHImageSource } from "./PHImageSource";
|
|
4
4
|
export type { PHImageSourceOptions } from "./PHImageSource";
|
|
5
|
+
export { PHVideo } from "./PHVideo";
|
|
6
|
+
export type { PHVideoProps } from "./PHVideo";
|