Skip to content

Commit

Permalink
feat: support refreshing photo selection on iOS (#2291)
Browse files Browse the repository at this point in the history
Co-authored-by: Khushal Agarwal <[email protected]>
  • Loading branch information
santhoshvai and khushal87 authored Nov 9, 2023
1 parent 20bbaed commit 5613dfd
Show file tree
Hide file tree
Showing 20 changed files with 72 additions and 6 deletions.
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ export function oniOS14GalleryLibrarySelectionChange(callback: () => void): {
unsubscribe: () => {},
};
}

export const iOS14RefreshGallerySelection = (): Promise<void> => {
if (isAboveIOS14) {
return MediaLibrary.presentPermissionsPickerAsync();
}
return Promise.resolve();
};
2 changes: 1 addition & 1 deletion package/expo-package/src/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ export * from './compressImage';
export * from './deleteFile';
export * from './getLocalAssetUri';
export * from './getPhotos';
export * from './iOS14RefreshGallerySelection';
export * from './NetInfo';
export * from './saveFile';
export * from './Sound';
export * from './takePhoto';
export * from './Video';
export * from './oniOS14GalleryLibrarySelectionChange';
2 changes: 2 additions & 0 deletions package/expo-package/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
deleteFile,
getLocalAssetUri,
getPhotos,
iOS14RefreshGallerySelection,
NetInfo,
oniOS14GalleryLibrarySelectionChange,
saveFile,
Expand All @@ -28,6 +29,7 @@ registerNativeHandlers({
FlatList,
getLocalAssetUri,
getPhotos,
iOS14RefreshGallerySelection,
NetInfo,
oniOS14GalleryLibrarySelectionChange,
pickDocument,
Expand Down
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,6 +66,7 @@
"{{ replyCount }} Replies": "{{ replyCount }} Replies",
"{{ replyCount }} Thread Replies": "{{ replyCount }} Thread Replies",
"{{ user }} is typing": "{{ user }} is typing",
"Select More Photos": "Select More Photos",
"🏙 Attachment...": "🏙 Attachment...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB."
}
1 change: 1 addition & 0 deletions package/src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ 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...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Taille maximale de téléchargement de fichier atteinte. Veuillez télécharger un fichier inférieur à {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} Mo."
}
1 change: 1 addition & 0 deletions package/src/i18n/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ replyCount }} Replies": "{{ replyCount }} תגובות",
"{{ replyCount }} Thread Replies": "{{ replyCount }} תגובות שרשור",
"{{ user }} is typing": "{{ user }} מקליד/ה",
"Select More Photos": "בחר עוד תמונות",
"🏙 Attachment...": "🏙 קובץ מצורף...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "הגעת למגבלת העלאת גודל הקובץ המקסימלית. אנא העלה קובץ מתחת ל-{{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB"
}
1 change: 1 addition & 0 deletions package/src/i18n/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ replyCount }} Replies": "{{ replyCount }} रिप्लाई",
"{{ replyCount }} Thread Replies": "{{ replyCount }}} थ्रेड उत्तर",
"{{ user }} is typing": "{{ user }} टाइप कर रहा है",
"Select More Photos": "अधिक फ़ोटो चुनें",
"🏙 Attachment...": "🏙 अटैचमेंट...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "अधिकतम फ़ाइल आकार अपलोड सीमा पूरी हो गई। कृपया {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} एमबी से नीचे की फ़ाइल अपलोड करें।"
}
1 change: 1 addition & 0 deletions package/src/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ 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...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "È stato raggiunto il limite massimo di caricamento delle dimensioni del file. Carica un file inferiore a {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB."
}
1 change: 1 addition & 0 deletions package/src/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"Reply to Message": "メッセージに返信",
"🏙 Attachment...": "🏙 アタッチメント...",
"Not supported": "サポートしていません",
"Select More Photos": "さらに写真を選択",
"File type not supported": "サポートされていないファイルです",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "最大ファイル サイズのアップロード制限に達しました。 {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB 以下のファイルをアップロードしてください"
}
1 change: 1 addition & 0 deletions package/src/i18n/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"Reply to Message": "메시지에 답장",
"🏙 Attachment...": "🏙 부착...",
"File type not supported": "지원하지 않는 파일입니다.",
"Select More Photos": "추가 사진 선택",
"Not supported": "지원하지 않습니다",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "최대 파일 크기 업로드 제한에 도달했습니다. {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}}MB 미만의 파일을 업로드하세요."
}
1 change: 1 addition & 0 deletions package/src/i18n/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ 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...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maximale uploadlimiet voor bestandsgrootte bereikt. Upload een bestand van minder dan {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB."
}
1 change: 1 addition & 0 deletions package/src/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ replyCount }} Replies": "{{ replyCount }} Ответов",
"{{ replyCount }} Thread Replies": "{{replyCount}} Ответы в темах",
"{{ user }} is typing": "{{ user }} пишет",
"Select More Photos": "Выбрать больше фотографий",
"🏙 Attachment...": "🏙 Вложение...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Достигнут предел максимального размера файла для загрузки. Загрузите файл размером менее {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} МБ."
}
1 change: 1 addition & 0 deletions package/src/i18n/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"{{ 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...",
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maksimum dosya boyutu yükleme sınırına ulaşıldı. Lütfen {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB'ın altında bir dosya yükleyin."
}
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

0 comments on commit 5613dfd

Please sign in to comment.