Add share intent
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -20,6 +20,24 @@
|
|||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="image/bmp" />
|
||||||
|
<data android:mimeType="image/jpeg" />
|
||||||
|
<data android:mimeType="image/png" />
|
||||||
|
<data android:mimeType="image/webp" />
|
||||||
|
<data android:mimeType="image/gif" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="image/bmp" />
|
||||||
|
<data android:mimeType="image/jpeg" />
|
||||||
|
<data android:mimeType="image/png" />
|
||||||
|
<data android:mimeType="image/webp" />
|
||||||
|
<data android:mimeType="image/gif" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
24
package-lock.json
generated
24
package-lock.json
generated
@@ -32,6 +32,7 @@
|
|||||||
"react-native-scoped-storage": "^1.9.3",
|
"react-native-scoped-storage": "^1.9.3",
|
||||||
"react-native-screens": "^3.22.1",
|
"react-native-screens": "^3.22.1",
|
||||||
"react-native-share": "^9.2.3",
|
"react-native-share": "^9.2.3",
|
||||||
|
"react-native-share-menu": "^6.0.0",
|
||||||
"react-native-vector-icons": "^9.2.0",
|
"react-native-vector-icons": "^9.2.0",
|
||||||
"react-native-video": "^6.0.0-alpha.6",
|
"react-native-video": "^6.0.0-alpha.6",
|
||||||
"react-redux": "^8.1.1",
|
"react-redux": "^8.1.1",
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
"@types/jest": "^29.5.2",
|
"@types/jest": "^29.5.2",
|
||||||
"@types/metro-config": "^0.76.3",
|
"@types/metro-config": "^0.76.3",
|
||||||
"@types/react": "^18.2.14",
|
"@types/react": "^18.2.14",
|
||||||
|
"@types/react-native-share-menu": "^5.0.2",
|
||||||
"@types/react-native-vector-icons": "^6.4.13",
|
"@types/react-native-vector-icons": "^6.4.13",
|
||||||
"@types/react-native-video": "^5.0.15",
|
"@types/react-native-video": "^5.0.15",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
@@ -4615,6 +4617,12 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-native-share-menu": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-native-share-menu/-/react-native-share-menu-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-Qa9DGfL6Bvng2DXgCK0fFzdi9SJMGfs06MLSkCfSXBCGKlFLzSHCsXztvXlCCChn3dQArFHyz/uRUN3Sbt6LtQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/react-native-vector-icons": {
|
"node_modules/@types/react-native-vector-icons": {
|
||||||
"version": "6.4.13",
|
"version": "6.4.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.13.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.13.tgz",
|
||||||
@@ -13542,6 +13550,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-9.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-9.2.3.tgz",
|
||||||
"integrity": "sha512-y6ju4HS6ydJoPVoacZ/Hp3i47AfI9W4e76Jv00r01dVbr6SCCcuqk37kIbn+kYivdTxOW77UGEbhtBHHtXnhzg=="
|
"integrity": "sha512-y6ju4HS6ydJoPVoacZ/Hp3i47AfI9W4e76Jv00r01dVbr6SCCcuqk37kIbn+kYivdTxOW77UGEbhtBHHtXnhzg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-share-menu": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-share-menu/-/react-native-share-menu-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-KdmRnqjI/B2MigSxGmhbYJ3WMJxKXj+0c47ANcVZ/PTzc2vtz6d1r4KQJgkBImXgNC+vowpuD2UGdPllxadr2A=="
|
||||||
|
},
|
||||||
"node_modules/react-native-vector-icons": {
|
"node_modules/react-native-vector-icons": {
|
||||||
"version": "9.2.0",
|
"version": "9.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz",
|
||||||
@@ -19197,6 +19210,12 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-native-share-menu": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-native-share-menu/-/react-native-share-menu-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-Qa9DGfL6Bvng2DXgCK0fFzdi9SJMGfs06MLSkCfSXBCGKlFLzSHCsXztvXlCCChn3dQArFHyz/uRUN3Sbt6LtQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/react-native-vector-icons": {
|
"@types/react-native-vector-icons": {
|
||||||
"version": "6.4.13",
|
"version": "6.4.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.13.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.13.tgz",
|
||||||
@@ -25904,6 +25923,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-9.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-9.2.3.tgz",
|
||||||
"integrity": "sha512-y6ju4HS6ydJoPVoacZ/Hp3i47AfI9W4e76Jv00r01dVbr6SCCcuqk37kIbn+kYivdTxOW77UGEbhtBHHtXnhzg=="
|
"integrity": "sha512-y6ju4HS6ydJoPVoacZ/Hp3i47AfI9W4e76Jv00r01dVbr6SCCcuqk37kIbn+kYivdTxOW77UGEbhtBHHtXnhzg=="
|
||||||
},
|
},
|
||||||
|
"react-native-share-menu": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-share-menu/-/react-native-share-menu-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-KdmRnqjI/B2MigSxGmhbYJ3WMJxKXj+0c47ANcVZ/PTzc2vtz6d1r4KQJgkBImXgNC+vowpuD2UGdPllxadr2A=="
|
||||||
|
},
|
||||||
"react-native-vector-icons": {
|
"react-native-vector-icons": {
|
||||||
"version": "9.2.0",
|
"version": "9.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz",
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
"react-native-scoped-storage": "^1.9.3",
|
"react-native-scoped-storage": "^1.9.3",
|
||||||
"react-native-screens": "^3.22.1",
|
"react-native-screens": "^3.22.1",
|
||||||
"react-native-share": "^9.2.3",
|
"react-native-share": "^9.2.3",
|
||||||
|
"react-native-share-menu": "^6.0.0",
|
||||||
"react-native-vector-icons": "^9.2.0",
|
"react-native-vector-icons": "^9.2.0",
|
||||||
"react-native-video": "^6.0.0-alpha.6",
|
"react-native-video": "^6.0.0-alpha.6",
|
||||||
"react-redux": "^8.1.1",
|
"react-redux": "^8.1.1",
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
"@types/jest": "^29.5.2",
|
"@types/jest": "^29.5.2",
|
||||||
"@types/metro-config": "^0.76.3",
|
"@types/metro-config": "^0.76.3",
|
||||||
"@types/react": "^18.2.14",
|
"@types/react": "^18.2.14",
|
||||||
|
"@types/react-native-share-menu": "^5.0.2",
|
||||||
"@types/react-native-vector-icons": "^6.4.13",
|
"@types/react-native-vector-icons": "^6.4.13",
|
||||||
"@types/react-native-video": "^5.0.15",
|
"@types/react-native-video": "^5.0.15",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
|
38
patches/react-native-share-menu+6.0.0.patch
Normal file
38
patches/react-native-share-menu+6.0.0.patch
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
diff --git a/node_modules/react-native-share-menu/android/build.gradle b/node_modules/react-native-share-menu/android/build.gradle
|
||||||
|
index 9557fdb..b0503cb 100644
|
||||||
|
--- a/node_modules/react-native-share-menu/android/build.gradle
|
||||||
|
+++ b/node_modules/react-native-share-menu/android/build.gradle
|
||||||
|
@@ -1,12 +1,12 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
- compileSdkVersion 29
|
||||||
|
- buildToolsVersion "29.0.2"
|
||||||
|
+ compileSdkVersion 33
|
||||||
|
+ buildToolsVersion "33.0.0"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
- minSdkVersion 16
|
||||||
|
- targetSdkVersion 29
|
||||||
|
+ minSdkVersion 21
|
||||||
|
+ targetSdkVersion 33
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
ndk {
|
||||||
|
diff --git a/node_modules/react-native-share-menu/android/src/main/java/com/meedan/ShareMenuModule.java b/node_modules/react-native-share-menu/android/src/main/java/com/meedan/ShareMenuModule.java
|
||||||
|
index 09abd7b..af552b1 100644
|
||||||
|
--- a/node_modules/react-native-share-menu/android/src/main/java/com/meedan/ShareMenuModule.java
|
||||||
|
+++ b/node_modules/react-native-share-menu/android/src/main/java/com/meedan/ShareMenuModule.java
|
||||||
|
@@ -163,4 +163,12 @@ public class ShareMenuModule extends ReactContextBaseJavaModule implements Activ
|
||||||
|
// Update intent in case the user calls `getSharedText` again
|
||||||
|
currentActivity.setIntent(intent);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ @ReactMethod
|
||||||
|
+ public void addListener(String eventName) {
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @ReactMethod
|
||||||
|
+ public void removeListeners(Integer count) {
|
||||||
|
+ }
|
||||||
|
}
|
@@ -5,7 +5,7 @@ import { ParamListBase, useNavigation } from '@react-navigation/native';
|
|||||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||||
import { pick } from 'react-native-document-picker';
|
import { pick } from 'react-native-document-picker';
|
||||||
import { useDeviceOrientation } from '@react-native-community/hooks';
|
import { useDeviceOrientation } from '@react-native-community/hooks';
|
||||||
import { ROUTE } from '../types';
|
import { documentPickerResponseToAddMemeFile, ROUTE } from '../types';
|
||||||
import { allowedMimeTypes, noOp } from '../utilities';
|
import { allowedMimeTypes, noOp } from '../utilities';
|
||||||
|
|
||||||
const floatingActionButtonStyles = StyleSheet.create({
|
const floatingActionButtonStyles = StyleSheet.create({
|
||||||
@@ -54,22 +54,16 @@ const FloatingActionButton = ({ visible = true }: { visible?: boolean }) => {
|
|||||||
label: 'Tag',
|
label: 'Tag',
|
||||||
onPress: () => navigate(ROUTE.ADD_TAG),
|
onPress: () => navigate(ROUTE.ADD_TAG),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: 'note-text',
|
|
||||||
label: 'Text',
|
|
||||||
onPress: () => {
|
|
||||||
throw new Error('Not yet implemented');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
onStateChange={({ open }) => setState(open)}
|
onStateChange={({ open }) => setState(open)}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
if (!state) return;
|
if (!state) return;
|
||||||
const files = await pick({
|
const response = await pick({
|
||||||
type: allowedMimeTypes,
|
type: allowedMimeTypes,
|
||||||
allowMultiSelection: true,
|
allowMultiSelection: true,
|
||||||
}).catch(noOp);
|
}).catch(noOp);
|
||||||
if (!files) return;
|
if (!response) return;
|
||||||
|
const files = documentPickerResponseToAddMemeFile(response);
|
||||||
navigate(ROUTE.ADD_MEME, { files });
|
navigate(ROUTE.ADD_MEME, { files });
|
||||||
}}
|
}}
|
||||||
style={
|
style={
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
import React from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { NavigationContainer as NavigationContainerBase } from '@react-navigation/native';
|
import {
|
||||||
|
NavigationContainer as NavigationContainerBase,
|
||||||
|
ParamListBase,
|
||||||
|
createNavigationContainerRef,
|
||||||
|
} from '@react-navigation/native';
|
||||||
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
|
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
|
||||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
@@ -20,8 +24,14 @@ import {
|
|||||||
FloatingActionButton,
|
FloatingActionButton,
|
||||||
HideableBottomNavigationBar,
|
HideableBottomNavigationBar,
|
||||||
} from './components';
|
} from './components';
|
||||||
import { ROUTE, RootStackParamList } from './types';
|
import {
|
||||||
|
ROUTE,
|
||||||
|
RootStackParamList,
|
||||||
|
SharedItem,
|
||||||
|
sharedItemToAddMemeFile,
|
||||||
|
} from './types';
|
||||||
import { RootState } from './state';
|
import { RootState } from './state';
|
||||||
|
import ShareMenu from 'react-native-share-menu';
|
||||||
|
|
||||||
const TabNavigator = () => {
|
const TabNavigator = () => {
|
||||||
const navVisible = useSelector(
|
const navVisible = useSelector(
|
||||||
@@ -84,10 +94,28 @@ const TabNavigator = () => {
|
|||||||
const NavigationContainer = () => {
|
const NavigationContainer = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const navigationRef = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
|
const handleShare = useCallback(
|
||||||
|
(item: SharedItem | undefined) => {
|
||||||
|
if (!item) return;
|
||||||
|
const files = sharedItemToAddMemeFile(item);
|
||||||
|
navigationRef.current?.navigate(ROUTE.ADD_MEME, { files });
|
||||||
|
},
|
||||||
|
[navigationRef],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
ShareMenu.getInitialShare(handleShare);
|
||||||
|
const listener = ShareMenu.addNewShareListener(handleShare);
|
||||||
|
return () => listener.remove();
|
||||||
|
}, [handleShare]);
|
||||||
|
|
||||||
const StackNavigatorBase = createNativeStackNavigator<RootStackParamList>();
|
const StackNavigatorBase = createNativeStackNavigator<RootStackParamList>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationContainerBase
|
<NavigationContainerBase
|
||||||
|
ref={navigationRef}
|
||||||
theme={theme.dark ? darkNavigationTheme : lightNavigationTheme}>
|
theme={theme.dark ? darkNavigationTheme : lightNavigationTheme}>
|
||||||
<StackNavigatorBase.Navigator
|
<StackNavigatorBase.Navigator
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
|
@@ -9,8 +9,12 @@ import { AndroidScoped, FileSystem } from 'react-native-file-access';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { extension } from 'react-native-mime-types';
|
import { extension } from 'react-native-mime-types';
|
||||||
import { useDeviceOrientation } from '@react-native-community/hooks';
|
import { useDeviceOrientation } from '@react-native-community/hooks';
|
||||||
import { DocumentPickerResponse, pick } from 'react-native-document-picker';
|
import { pick } from 'react-native-document-picker';
|
||||||
import { ROUTE, RootStackParamList } from '../../types';
|
import {
|
||||||
|
documentPickerResponseToAddMemeFile,
|
||||||
|
ROUTE,
|
||||||
|
RootStackParamList,
|
||||||
|
} from '../../types';
|
||||||
import { Meme, Tag } from '../../database';
|
import { Meme, Tag } from '../../database';
|
||||||
import { RootState } from '../../state';
|
import { RootState } from '../../state';
|
||||||
import {
|
import {
|
||||||
@@ -39,9 +43,7 @@ const AddMeme = ({
|
|||||||
const isLastFile = index === files.current.length - 1;
|
const isLastFile = index === files.current.length - 1;
|
||||||
|
|
||||||
const [memeUri, setMemeUri] = useState(file.current.uri);
|
const [memeUri, setMemeUri] = useState(file.current.uri);
|
||||||
const [memeFilename, setMemeFilename] = useState(
|
const [memeFilename, setMemeFilename] = useState(file.current.filename);
|
||||||
file.current.name ?? undefined,
|
|
||||||
);
|
|
||||||
const [memeError, setMemeError] = useState<Error>();
|
const [memeError, setMemeError] = useState<Error>();
|
||||||
const [memeTitle, setMemeTitle] = useState(validateMemeTitle('New Meme'));
|
const [memeTitle, setMemeTitle] = useState(validateMemeTitle('New Meme'));
|
||||||
const [memeIsFavorite, setMemeIsFavorite] = useState(false);
|
const [memeIsFavorite, setMemeIsFavorite] = useState(false);
|
||||||
@@ -105,7 +107,7 @@ const AddMeme = ({
|
|||||||
file.current = files.current[index + 1];
|
file.current = files.current[index + 1];
|
||||||
|
|
||||||
setMemeUri(file.current.uri);
|
setMemeUri(file.current.uri);
|
||||||
setMemeFilename(file.current.name ?? undefined);
|
setMemeFilename(file.current.filename);
|
||||||
setMemeTitle(validateMemeTitle('New Meme'));
|
setMemeTitle(validateMemeTitle('New Meme'));
|
||||||
setMemeIsFavorite(false);
|
setMemeIsFavorite(false);
|
||||||
setMemeTags(new Map<string, Tag>());
|
setMemeTags(new Map<string, Tag>());
|
||||||
@@ -117,14 +119,16 @@ const AddMeme = ({
|
|||||||
setIsSavingAndAddingMore(false);
|
setIsSavingAndAddingMore(false);
|
||||||
|
|
||||||
setIndex(0);
|
setIndex(0);
|
||||||
files.current = (await pick({
|
const response = await pick({
|
||||||
type: allowedMimeTypes,
|
type: allowedMimeTypes,
|
||||||
allowMultiSelection: true,
|
allowMultiSelection: true,
|
||||||
}).catch(goBack)) as DocumentPickerResponse[];
|
}).catch(goBack);
|
||||||
|
if (!response) return;
|
||||||
|
files.current = documentPickerResponseToAddMemeFile(response);
|
||||||
file.current = files.current[0];
|
file.current = files.current[0];
|
||||||
|
|
||||||
setMemeUri(file.current.uri);
|
setMemeUri(file.current.uri);
|
||||||
setMemeFilename(file.current.name ?? undefined);
|
setMemeFilename(file.current.filename);
|
||||||
setMemeTitle(validateMemeTitle('New Meme'));
|
setMemeTitle(validateMemeTitle('New Meme'));
|
||||||
setMemeIsFavorite(false);
|
setMemeIsFavorite(false);
|
||||||
setMemeTags(new Map<string, Tag>());
|
setMemeTags(new Map<string, Tag>());
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
export { type Dimensions } from './dimensions';
|
export { type Dimensions } from './dimensions';
|
||||||
export { ROUTE, type RootStackParamList } from './route';
|
export {
|
||||||
|
ROUTE,
|
||||||
|
type RootStackParamList,
|
||||||
|
documentPickerResponseToAddMemeFile,
|
||||||
|
sharedItemToAddMemeFile,
|
||||||
|
} from './route';
|
||||||
|
export { type SharedItem } from './share';
|
||||||
export {
|
export {
|
||||||
MEME_SORT,
|
MEME_SORT,
|
||||||
memesSortQuery,
|
memesSortQuery,
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
import { DocumentPickerResponse } from 'react-native-document-picker';
|
import { DocumentPickerResponse } from 'react-native-document-picker';
|
||||||
|
import { getFilenameFromUri, guessMimeType } from '../utilities';
|
||||||
|
import { SharedItem } from './share';
|
||||||
|
|
||||||
enum ROUTE {
|
enum ROUTE {
|
||||||
MAIN = 'Main',
|
MAIN = 'Main',
|
||||||
@@ -17,8 +19,48 @@ interface MemeViewRouteParams {
|
|||||||
index: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface AddMemeFile {
|
||||||
|
uri: string;
|
||||||
|
filename: string;
|
||||||
|
type?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const documentPickerResponseToAddMemeFile = (
|
||||||
|
response: DocumentPickerResponse[],
|
||||||
|
): AddMemeFile[] => {
|
||||||
|
return response.map(item => {
|
||||||
|
const { uri, name, type } = item;
|
||||||
|
|
||||||
|
return {
|
||||||
|
uri,
|
||||||
|
filename: name ?? getFilenameFromUri(uri),
|
||||||
|
type: type ?? guessMimeType(uri),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const sharedItemToAddMemeFile = (item: SharedItem): AddMemeFile[] => {
|
||||||
|
const { data, mimeType } = item;
|
||||||
|
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
uri: data,
|
||||||
|
filename: getFilenameFromUri(data),
|
||||||
|
type: mimeType,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.map(uri => ({
|
||||||
|
uri,
|
||||||
|
filename: getFilenameFromUri(uri),
|
||||||
|
type: guessMimeType(uri),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
interface AddMemeRouteParams {
|
interface AddMemeRouteParams {
|
||||||
files: DocumentPickerResponse[];
|
files: AddMemeFile[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EditMemeRouteParams {
|
interface EditMemeRouteParams {
|
||||||
@@ -44,4 +86,9 @@ interface RootStackParamList {
|
|||||||
[ROUTE.EDIT_TAG]: EditTagRouteParams;
|
[ROUTE.EDIT_TAG]: EditTagRouteParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ROUTE, type RootStackParamList };
|
export {
|
||||||
|
ROUTE,
|
||||||
|
type RootStackParamList,
|
||||||
|
documentPickerResponseToAddMemeFile,
|
||||||
|
sharedItemToAddMemeFile,
|
||||||
|
};
|
||||||
|
7
src/types/share.ts
Normal file
7
src/types/share.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
interface SharedItem {
|
||||||
|
data: string | string[];
|
||||||
|
mimeType: string;
|
||||||
|
extraData?: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type SharedItem };
|
@@ -25,9 +25,32 @@ const getMemeType = (mimeType: string): MEME_TYPE | undefined => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const guessMimeType = (filename: string): string | undefined => {
|
||||||
|
const extension = filename.split('.').pop()?.toLowerCase();
|
||||||
|
switch (extension) {
|
||||||
|
case 'bmp': {
|
||||||
|
return 'image/bmp';
|
||||||
|
}
|
||||||
|
case 'jpg':
|
||||||
|
case 'jpeg': {
|
||||||
|
return 'image/jpeg';
|
||||||
|
}
|
||||||
|
case 'png': {
|
||||||
|
return 'image/png';
|
||||||
|
}
|
||||||
|
case 'webp': {
|
||||||
|
return 'image/webp';
|
||||||
|
}
|
||||||
|
case 'gif': {
|
||||||
|
return 'image/gif';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
allowedImageMimeTypes,
|
allowedImageMimeTypes,
|
||||||
allowedGifMimeTypes,
|
allowedGifMimeTypes,
|
||||||
allowedMimeTypes,
|
allowedMimeTypes,
|
||||||
getMemeType,
|
getMemeType,
|
||||||
|
guessMimeType,
|
||||||
};
|
};
|
||||||
|
@@ -14,6 +14,7 @@ export {
|
|||||||
allowedGifMimeTypes,
|
allowedGifMimeTypes,
|
||||||
allowedMimeTypes,
|
allowedMimeTypes,
|
||||||
getMemeType,
|
getMemeType,
|
||||||
|
guessMimeType,
|
||||||
} from './filesystem';
|
} from './filesystem';
|
||||||
export { getSortIcon, getViewIcon } from './icon';
|
export { getSortIcon, getViewIcon } from './icon';
|
||||||
export {
|
export {
|
||||||
@@ -26,6 +27,7 @@ export {
|
|||||||
export {
|
export {
|
||||||
isPermissionForPath,
|
isPermissionForPath,
|
||||||
clearPermissions,
|
clearPermissions,
|
||||||
|
getFilenameFromUri,
|
||||||
} from './permissions';
|
} from './permissions';
|
||||||
export { deleteTag } from './tag';
|
export { deleteTag } from './tag';
|
||||||
export {
|
export {
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { Util } from 'react-native-file-access';
|
||||||
import {
|
import {
|
||||||
getPersistedUriPermissions,
|
getPersistedUriPermissions,
|
||||||
releasePersistableUriPermission,
|
releasePersistableUriPermission,
|
||||||
@@ -16,4 +17,8 @@ const clearPermissions = async (excepts: string[] = []) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export { isPermissionForPath, clearPermissions };
|
const getFilenameFromUri = (uri: string) => {
|
||||||
|
return Util.basename(uri.replaceAll('%2F', '/'));
|
||||||
|
};
|
||||||
|
|
||||||
|
export { isPermissionForPath, clearPermissions, getFilenameFromUri };
|
||||||
|
Reference in New Issue
Block a user