Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support refreshing photo selection on iOS #2291

Merged
merged 2 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package/expo-package/src/handlers/getPhotos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type ReturnType = {
assets: Array<Omit<Asset, 'source'> & { source: 'picker' }>;
endCursor: string | undefined;
hasNextPage: boolean;
iOSLimited: boolean;
};

export const getPhotos = async ({
Expand All @@ -16,7 +17,7 @@ export const getPhotos = async ({
// should always check first before requesting permission
// because always requesting permission will cause
// the app to go to background even if it was granted
const { status } = await MediaLibrary.getPermissionsAsync();
const { accessPrivileges, status } = await MediaLibrary.getPermissionsAsync();
if (status !== 'granted') {
const { status: newStatus } = await MediaLibrary.requestPermissionsAsync();
if (newStatus !== 'granted') {
Expand All @@ -42,7 +43,7 @@ export const getPhotos = async ({

const hasNextPage = results.hasNextPage;
const endCursor = results.endCursor;
return { assets, endCursor, hasNextPage };
return { assets, endCursor, hasNextPage, iOSLimited: accessPrivileges === 'limited' };
} catch {
throw new Error('getPhotos Error');
}
Expand Down
29 changes: 29 additions & 0 deletions package/expo-package/src/handlers/iOS14RefreshGallerySelection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Platform } from 'react-native';

import * as MediaLibrary from 'expo-media-library';

const isAboveIOS14 = Platform.OS === 'ios' && parseInt(Platform.Version as string, 10) >= 14;

export function oniOS14GalleryLibrarySelectionChange(callback: () => void): {
unsubscribe: () => void;
} {
if (isAboveIOS14) {
const subscription = MediaLibrary.addListener(callback);
return {
unsubscribe: () => {
subscription.remove();
},
};
}
return {
// eslint-disable-next-line @typescript-eslint/no-empty-function
unsubscribe: () => {},
};
}

export const iOS14RefreshGallerySelection = (): Promise<void> => {
if (isAboveIOS14) {
return MediaLibrary.presentPermissionsPickerAsync();
}
return Promise.resolve();
};
3 changes: 2 additions & 1 deletion package/native-package/src/handlers/getPhotos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type ReturnType = {
assets: Array<Omit<Asset, 'source'> & { source: 'picker' }>;
endCursor: string | undefined;
hasNextPage: boolean;
iOSLimited: boolean;
};

const verifyAndroidPermissions = async () => {
Expand Down Expand Up @@ -84,7 +85,7 @@ export const getPhotos = async ({
}));
const hasNextPage = results.page_info.has_next_page;
const endCursor = results.page_info.end_cursor;
return { assets, endCursor, hasNextPage };
return { assets, endCursor, hasNextPage, iOSLimited: !!results.limited };
} catch (_error) {
throw new Error('getPhotos Error');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Platform } from 'react-native';

import { iosRefreshGallerySelection } from '@react-native-camera-roll/camera-roll';

const isAboveIOS14 = Platform.OS === 'ios' && parseInt(Platform.Version as string, 10) >= 14;

export const iOS14RefreshGallerySelection = (): Promise<void> => {
if (isAboveIOS14) {
return iosRefreshGallerySelection().then(() => {
//do nothing
});
}
return Promise.resolve();
};
1 change: 1 addition & 0 deletions package/native-package/src/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './takePhoto';
export * from './Sound';
export * from './Video';
export * from './oniOS14GalleryLibrarySelectionChange';
export * from './iOS14RefreshGallerySelection';
2 changes: 2 additions & 0 deletions package/native-package/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
deleteFile,
getLocalAssetUri,
getPhotos,
iOS14RefreshGallerySelection,
NetInfo,
oniOS14GalleryLibrarySelectionChange,
saveFile,
Expand All @@ -29,6 +30,7 @@ registerNativeHandlers({
FlatList,
getLocalAssetUri,
getPhotos,
iOS14RefreshGallerySelection,
NetInfo,
oniOS14GalleryLibrarySelectionChange,
pickDocument,
Expand Down
23 changes: 21 additions & 2 deletions package/src/components/AttachmentPicker/AttachmentPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { BackHandler, Dimensions, Keyboard, Platform, StatusBar, StyleSheet } from 'react-native';
import {
BackHandler,
Button,
Dimensions,
Keyboard,
Platform,
StatusBar,
StyleSheet,
} from 'react-native';

import BottomSheet, { BottomSheetFlatList, BottomSheetHandleProps } from '@gorhom/bottom-sheet';
import dayjs from 'dayjs';
Expand All @@ -11,7 +19,12 @@ import { renderAttachmentPickerItem } from './components/AttachmentPickerItem';

import { useAttachmentPickerContext } from '../../contexts/attachmentPickerContext/AttachmentPickerContext';
import { useTheme } from '../../contexts/themeContext/ThemeContext';
import { getPhotos, oniOS14GalleryLibrarySelectionChange } from '../../native';
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
import {
getPhotos,
iOS14RefreshGallerySelection,
oniOS14GalleryLibrarySelectionChange,
} from '../../native';
import type { Asset } from '../../types/types';
import { vh } from '../../utils/utils';

Expand Down Expand Up @@ -97,10 +110,12 @@ export const AttachmentPicker = React.forwardRef(
const [currentIndex, setCurrentIndex] = useState(-1);
const endCursorRef = useRef<string>();
const [photoError, setPhotoError] = useState(false);
const [iOSLimited, setIosLimited] = useState(false);
const hasNextPageRef = useRef(true);
const [loadingPhotos, setLoadingPhotos] = useState(false);
const [photos, setPhotos] = useState<Asset[]>([]);
const attemptedToLoadPhotosOnOpenRef = useRef(false);
const { t } = useTranslationContext();

const getMorePhotos = useCallback(async () => {
if (
Expand All @@ -121,6 +136,7 @@ export const AttachmentPicker = React.forwardRef(
setPhotos((prevPhotos) =>
endCursor ? [...prevPhotos, ...results.assets] : results.assets,
);
setIosLimited(results.iOSLimited);
hasNextPageRef.current = !!results.hasNextPage;
} catch (error) {
setPhotoError(true);
Expand Down Expand Up @@ -299,6 +315,9 @@ export const AttachmentPicker = React.forwardRef(
ref={ref}
snapPoints={snapPoints}
>
{iOSLimited && (
<Button onPress={iOS14RefreshGallerySelection} title={t('Select More Photos')} />
)}
<BottomSheetFlatList
contentContainerStyle={[
styles.container,
Expand Down
1 change: 1 addition & 0 deletions package/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} Replies",
"{{ replyCount }} Thread Replies": "{{ replyCount }} Thread Replies",
"{{ user }} is typing": "{{ user }} is typing",
"Select More Photos": "Select More Photos",
"🏙 Attachment...": "🏙 Attachment..."
}
1 change: 1 addition & 0 deletions package/src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} Réponses",
"{{ replyCount }} Thread Replies": "{{replyCount}} Réponses à la discussion",
"{{ user }} is typing": "{{ user }} est en train d'écrire",
"Select More Photos": "Sélectionner plus de photos",
"🏙 Attachment...": "🏙 Pièce jointe..."
}
1 change: 1 addition & 0 deletions package/src/i18n/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} תגובות",
"{{ replyCount }} Thread Replies": "{{ replyCount }} תגובות שרשור",
"{{ user }} is typing": "{{ user }} מקליד/ה",
"Select More Photos": "בחר עוד תמונות",
"🏙 Attachment...": "🏙 קובץ מצורף..."
}
1 change: 1 addition & 0 deletions package/src/i18n/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} रिप्लाई",
"{{ replyCount }} Thread Replies": "{{ replyCount }}} थ्रेड उत्तर",
"{{ user }} is typing": "{{ user }} टाइप कर रहा है",
"Select More Photos": "अधिक फ़ोटो चुनें",
"🏙 Attachment...": "🏙 अटैचमेंट..."
}
1 change: 1 addition & 0 deletions package/src/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} Risposte",
"{{ replyCount }} Thread Replies": "{{replyCount}} Risposte alle Conversazione",
"{{ user }} is typing": "{{ user }} sta scrivendo",
"Select More Photos": "Seleziona Altre foto",
"🏙 Attachment...": "🏙 Allegato..."
}
1 change: 1 addition & 0 deletions package/src/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@
"Reply to Message": "メッセージに返信",
"🏙 Attachment...": "🏙 アタッチメント...",
"Not supported": "サポートしていません",
"Select More Photos": "さらに写真を選択",
"File type not supported": "サポートされていないファイルです"
}
1 change: 1 addition & 0 deletions package/src/i18n/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@
"Reply to Message": "메시지에 답장",
"🏙 Attachment...": "🏙 부착...",
"File type not supported": "지원하지 않는 파일입니다.",
"Select More Photos": "추가 사진 선택",
"Not supported": "지원하지 않습니다"
}
1 change: 1 addition & 0 deletions package/src/i18n/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} Antwoorden",
"{{ replyCount }} Thread Replies": "{{replyCount}} Discussiereacties",
"{{ user }} is typing": "{{ user }} is aan het typen",
"Select More Photos": "Selecteer Meer foto's",
"🏙 Attachment...": "🏙 Bijlage..."
}
1 change: 1 addition & 0 deletions package/src/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} Ответов",
"{{ replyCount }} Thread Replies": "{{replyCount}} Ответы в темах",
"{{ user }} is typing": "{{ user }} пишет",
"Select More Photos": "Выбрать больше фотографий",
"🏙 Attachment...": "🏙 Вложение..."
}
1 change: 1 addition & 0 deletions package/src/i18n/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@
"{{ replyCount }} Replies": "{{ replyCount }} Cevap",
"{{ replyCount }} Thread Replies": "{{responseCount}} Konu Cevapı",
"{{ user }} is typing": "{{ user }} yazıyor",
"Select More Photos": "Daha Fazla Fotoğraf Seçin",
"🏙 Attachment...": "🏙 Ek..."
}
9 changes: 9 additions & 0 deletions package/src/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ export let getLocalAssetUri: GetLocalAssetUri = fail;
type OniOS14LibrarySelectionChange = (callback: () => void) => { unsubscribe: () => void };
export let oniOS14GalleryLibrarySelectionChange: OniOS14LibrarySelectionChange = fail;

type iOS14RefreshGallerySelection = () => Promise<void>;
export let iOS14RefreshGallerySelection: iOS14RefreshGallerySelection = fail;

type GetPhotos = ({ after, first }: { first: number; after?: string }) =>
| Promise<{
assets: Array<Omit<Asset, 'source'> & { source: 'picker' }>;
endCursor: string;
hasNextPage: boolean;
iOSLimited: boolean;
}>
| never;
export let getPhotos: GetPhotos = fail;
Expand Down Expand Up @@ -213,6 +217,7 @@ export type VideoType = {
export let Video: React.ComponentType<VideoType>;

type Handlers = {
iOS14RefreshGallerySelection: iOS14RefreshGallerySelection;
compressImage?: CompressImage;
deleteFile?: DeleteFile;
FlatList?: typeof DefaultFlatList;
Expand Down Expand Up @@ -255,6 +260,10 @@ export const registerNativeHandlers = (handlers: Handlers) => {
getPhotos = handlers.getPhotos;
}

if (handlers.iOS14RefreshGallerySelection) {
iOS14RefreshGallerySelection = handlers.iOS14RefreshGallerySelection;
}

if (handlers.oniOS14GalleryLibrarySelectionChange) {
oniOS14GalleryLibrarySelectionChange = handlers.oniOS14GalleryLibrarySelectionChange;
}
Expand Down
Loading