From 8c2004fe6c9c9265f131190d6ae3b03908089e56 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Sun, 8 May 2022 12:15:16 +0200 Subject: [PATCH] Upload GIF using Android keyboard https://github.com/tooot-app/app/issues/261 --- package.json | 1 + src/App.tsx | 1 + src/i18n/en/common.json | 1 + src/i18n/en/screens/compose.json | 8 +++- src/screens/Compose.tsx | 1 - .../Compose/Root/Footer/Attachments.tsx | 18 +++++++-- src/screens/Compose/Root/Header/TextInput.tsx | 40 ++++++++++++++++++- .../Shared/Account/Information/Account.tsx | 2 +- yarn.lock | 5 +++ 9 files changed, 69 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 3e8a9733..48e443fc 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "react-native-flash-message": "0.2.1", "react-native-gesture-handler": "2.4.1", "react-native-htmlview": "0.16.0", + "react-native-image-keyboard": "^2.2.0", "react-native-pager-view": "5.4.11", "react-native-reanimated": "2.8.0", "react-native-safe-area-context": "4.2.5", diff --git a/src/App.tsx b/src/App.tsx index 21c6fbf3..e1057e8c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,6 +19,7 @@ import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' import { AppState, LogBox, Platform } from 'react-native' import { GestureHandlerRootView } from 'react-native-gesture-handler' +import 'react-native-image-keyboard' import { enableFreeze } from 'react-native-screens' import { QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' diff --git a/src/i18n/en/common.json b/src/i18n/en/common.json index 97e95f44..4b3fa57e 100644 --- a/src/i18n/en/common.json +++ b/src/i18n/en/common.json @@ -1,5 +1,6 @@ { "buttons": { + "OK": "OK", "apply": "Apply", "cancel": "Cancel" }, diff --git a/src/i18n/en/screens/compose.json b/src/i18n/en/screens/compose.json index 92e65384..10bae903 100644 --- a/src/i18n/en/screens/compose.json +++ b/src/i18n/en/screens/compose.json @@ -42,7 +42,13 @@ "placeholder": "Spoiler warning message" }, "textInput": { - "placeholder": "What's on your mind" + "placeholder": "What's on your mind", + "keyboardImage": { + "exceedMaximum": { + "title": "Maximum attachments amount reached", + "OK": "$t(common:buttons.OK)" + } + } } }, "footer": { diff --git a/src/screens/Compose.tsx b/src/screens/Compose.tsx index 285b849f..712e31db 100644 --- a/src/screens/Compose.tsx +++ b/src/screens/Compose.tsx @@ -1,4 +1,3 @@ -import apiInstance from '@api/instance' import analytics from '@components/analytics' import { HeaderLeft, HeaderRight } from '@components/Header' import { createNativeStackNavigator } from '@react-navigation/native-stack' diff --git a/src/screens/Compose/Root/Footer/Attachments.tsx b/src/screens/Compose/Root/Footer/Attachments.tsx index 0d77c515..8df70266 100644 --- a/src/screens/Compose/Root/Footer/Attachments.tsx +++ b/src/screens/Compose/Root/Footer/Attachments.tsx @@ -5,6 +5,7 @@ import Icon from '@components/Icon' import CustomText from '@components/Text' import { useActionSheet } from '@expo/react-native-action-sheet' import { useNavigation } from '@react-navigation/native' +import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/instancesSlice' import { StyleConstants } from '@utils/styles/constants' import layoutAnimation from '@utils/styles/layoutAnimation' import { useTheme } from '@utils/styles/ThemeManager' @@ -17,8 +18,10 @@ import React, { useRef } from 'react' import { useTranslation } from 'react-i18next' -import { FlatList, Image, Pressable, StyleSheet, View } from 'react-native' +import { FlatList, Pressable, StyleSheet, View } from 'react-native' import { Circle } from 'react-native-animated-spinkit' +import FastImage from 'react-native-fast-image' +import { useSelector } from 'react-redux' import ComposeContext from '../../utils/createContext' import { ExtendedAttachment } from '../../utils/types' import chooseAndUploadAttachment from './addAttachment' @@ -33,9 +36,14 @@ const ComposeAttachments: React.FC = ({ accessibleRefAttachments }) => { const { showActionSheetWithOptions } = useActionSheet() const { composeState, composeDispatch } = useContext(ComposeContext) const { t } = useTranslation('screenCompose') - const { colors, mode } = useTheme() + const { colors } = useTheme() const navigation = useNavigation() + const maxAttachments = useSelector( + getInstanceConfigurationStatusMaxAttachments, + () => true + ) + const flatListRef = useRef(null) const sensitiveOnPress = useCallback(() => { @@ -124,7 +132,7 @@ const ComposeAttachments: React.FC = ({ accessibleRefAttachments }) => { width: calculateWidth(item) }} > - = ({ accessibleRefAttachments }) => { item.local?.uri || item.remote?.url || Math.random().toString() } ListFooterComponent={ - composeState.attachments.uploads.length < 4 ? listFooter : null + composeState.attachments.uploads.length < maxAttachments + ? listFooter + : null } /> diff --git a/src/screens/Compose/Root/Header/TextInput.tsx b/src/screens/Compose/Root/Header/TextInput.tsx index af518beb..d9325197 100644 --- a/src/screens/Compose/Root/Header/TextInput.tsx +++ b/src/screens/Compose/Root/Header/TextInput.tsx @@ -1,17 +1,25 @@ import CustomText from '@components/Text' +import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/instancesSlice' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useContext } from 'react' import { useTranslation } from 'react-i18next' -import { TextInput } from 'react-native' +import { Alert, TextInput } from 'react-native' +import { useSelector } from 'react-redux' import formatText from '../../formatText' import ComposeContext from '../../utils/createContext' +import { uploadAttachment } from '../Footer/addAttachment' const ComposeTextInput: React.FC = () => { const { composeState, composeDispatch } = useContext(ComposeContext) const { t } = useTranslation('screenCompose') const { colors, mode } = useTheme() + const maxAttachments = useSelector( + getInstanceConfigurationStatusMaxAttachments, + () => true + ) + return ( { }} ref={composeState.textInputFocus.refs.text} scrollEnabled={false} + onImageChange={({ nativeEvent }) => { + if (composeState.attachments.uploads.length >= maxAttachments) { + Alert.alert( + t( + 'content.root.header.textInput.keyboardImage.exceedMaximum.title' + ), + undefined, + [ + { + text: t( + 'content.root.header.textInput.keyboardImage.exceedMaximum.OK' + ), + style: 'default' + } + ] + ) + return + } + if (nativeEvent.linkUri) { + uploadAttachment({ + composeDispatch, + imageInfo: { + uri: nativeEvent.linkUri, + type: 'image', + width: 100, + height: 100 + } + }) + } + }} > {composeState.text.formatted} diff --git a/src/screens/Tabs/Shared/Account/Information/Account.tsx b/src/screens/Tabs/Shared/Account/Information/Account.tsx index 77a03cb3..6e4a8cbd 100644 --- a/src/screens/Tabs/Shared/Account/Information/Account.tsx +++ b/src/screens/Tabs/Shared/Account/Information/Account.tsx @@ -31,7 +31,7 @@ const AccountInformationAccount: React.FC = ({ const instanceUri = useSelector(getInstanceUri) const { data: relationship } = useRelationshipQuery({ - id: account!.id, + id: account?.id || '', options: { enabled: account !== undefined } }) diff --git a/yarn.lock b/yarn.lock index 8f67cba6..b9f41f6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6309,6 +6309,11 @@ react-native-htmlview@0.16.0: entities "^1.1.1" htmlparser2-without-node-native "^3.9.2" +react-native-image-keyboard@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/react-native-image-keyboard/-/react-native-image-keyboard-2.2.0.tgz#dc3f90aaaac20a79315015a330e62e85547e0674" + integrity sha512-2JzKCXMBYiIUR6OtGV7F/lEWqwIU/6HS1CGOBulxwYNxoa7m1nZk45hNEZPP8SA5yE2pLNXEQePjc3WGAtXo3w== + react-native-iphone-x-helper@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz#20c603e9a0e765fd6f97396638bdeb0e5a60b010"