mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-28 22:30:41 +00:00
Share contact and Upload image preview (#221)
This commit is contained in:
commit
25de204b0c
@ -2,6 +2,8 @@
|
||||
package="com.nostros">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- required for react-native-share base64 sharing -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
|
@ -156,8 +156,8 @@ export const LnPayment: React.FC<TextContentProps> = ({ open, setOpen, event, us
|
||||
>
|
||||
<Card style={styles.qrContainer}>
|
||||
<Card.Content>
|
||||
<View>
|
||||
<QRCode value={invoice} size={350} />
|
||||
<View style={styles.qr}>
|
||||
<QRCode value={invoice} size={300} quietZone={8}/>
|
||||
</View>
|
||||
<View style={styles.qrText}>
|
||||
<Text>{monto} </Text>
|
||||
@ -222,6 +222,11 @@ const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
},
|
||||
qr: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 16
|
||||
},
|
||||
})
|
||||
|
||||
export default LnPayment
|
||||
|
@ -2,7 +2,7 @@ import { t } from 'i18next'
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { Card, IconButton, Snackbar, Text, useTheme } from 'react-native-paper'
|
||||
import { Card, IconButton, Snackbar, Text, TouchableRipple, useTheme } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
@ -12,6 +12,7 @@ import {
|
||||
updateUserContact,
|
||||
User,
|
||||
} from '../../Functions/DatabaseFunctions/Users'
|
||||
import Share from 'react-native-share'
|
||||
import { populatePets, usernamePubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import LnPayment from '../LnPayment'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
@ -19,6 +20,7 @@ import { navigate, push } from '../../lib/Navigation'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getNpub } from '../../lib/nostr/Nip19'
|
||||
import ProfileData from '../ProfileData'
|
||||
import QRCode from 'react-native-qrcode-svg'
|
||||
|
||||
interface ProfileCardProps {
|
||||
userPubKey: string
|
||||
@ -32,6 +34,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
showImages = true,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const bottomSheetShareRef = React.useRef<RBSheet>(null)
|
||||
const { database } = React.useContext(AppContext)
|
||||
const { publicKey } = React.useContext(UserContext)
|
||||
const { relayPool } = React.useContext(RelayPoolContext)
|
||||
@ -40,6 +43,7 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
const [openLn, setOpenLn] = React.useState<boolean>(false)
|
||||
const [isContact, setIsContact] = React.useState<boolean>()
|
||||
const [showNotification, setShowNotification] = React.useState<undefined | string>()
|
||||
const [qrCode, setQrCode] = React.useState<any>()
|
||||
const nPub = React.useMemo(() => getNpub(userPubKey), [userPubKey])
|
||||
const username = React.useMemo(() => usernamePubKey(user?.name ?? '', nPub), [nPub, user])
|
||||
|
||||
@ -96,6 +100,21 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
push('Profile', { pubKey: userPubKey, title: username })
|
||||
}
|
||||
|
||||
const bottomSheetStyles = React.useMemo(() => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.colors.background,
|
||||
paddingTop: 16,
|
||||
paddingRight: 16,
|
||||
paddingBottom: 32,
|
||||
paddingLeft: 16,
|
||||
borderTopRightRadius: 28,
|
||||
borderTopLeftRadius: 28,
|
||||
height: 'auto',
|
||||
},
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Card onPress={goToProfile}>
|
||||
@ -144,14 +163,6 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
<Text>{isContact ? t('profileCard.unfollow') : t('profileCard.follow')}</Text>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon={blocked ? 'account-cancel' : 'account-cancel-outline'}
|
||||
size={28}
|
||||
onPress={onChangeBlockUser}
|
||||
/>
|
||||
<Text>{t(blocked ? 'profileCard.unblock' : 'profileCard.block')}</Text>
|
||||
</View>
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon='message-plus-outline'
|
||||
@ -165,14 +176,13 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
</View>
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon='content-copy'
|
||||
icon='share-variant-outline'
|
||||
size={28}
|
||||
onPress={() => {
|
||||
setShowNotification('npubCopied')
|
||||
Clipboard.setString(nPub ?? '')
|
||||
bottomSheetShareRef.current?.open()
|
||||
}}
|
||||
/>
|
||||
<Text>{t('profileCard.copyNPub')}</Text>
|
||||
<Text>{t('profileCard.share')}</Text>
|
||||
</View>
|
||||
{user?.lnurl && (
|
||||
<View style={styles.actionButton}>
|
||||
@ -187,6 +197,14 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
</>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon={blocked ? 'account-cancel' : 'account-cancel-outline'}
|
||||
size={28}
|
||||
onPress={onChangeBlockUser}
|
||||
/>
|
||||
<Text>{t(blocked ? 'profileCard.unblock' : 'profileCard.block')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{showNotification && (
|
||||
<Snackbar
|
||||
@ -200,6 +218,60 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({
|
||||
</Snackbar>
|
||||
)}
|
||||
<LnPayment setOpen={setOpenLn} open={openLn} user={user} />
|
||||
<RBSheet ref={bottomSheetShareRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
<View style={styles.mainLayout}>
|
||||
<View style={styles.qr}>
|
||||
<TouchableRipple
|
||||
onPress={() => {
|
||||
if (qrCode) {
|
||||
qrCode.toDataURL((base64: string) => {
|
||||
Share.open({
|
||||
url: `data:image/png;base64,${base64}`,
|
||||
filename: user?.id ?? 'nostrosshare'
|
||||
})
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
<QRCode
|
||||
quietZone={8}
|
||||
value={`nostr:${nPub}`}
|
||||
size={350}
|
||||
logoBorderRadius={50}
|
||||
logoSize={100}
|
||||
logo={{ uri: user?.picture }}
|
||||
getRef={setQrCode}
|
||||
/>
|
||||
</TouchableRipple>
|
||||
</View>
|
||||
<View style={styles.shareActionButton}>
|
||||
<IconButton
|
||||
icon='key-outline'
|
||||
size={28}
|
||||
onPress={() => {
|
||||
setShowNotification('npubCopied')
|
||||
Clipboard.setString(nPub ?? '')
|
||||
bottomSheetShareRef.current?.close()
|
||||
}}
|
||||
/>
|
||||
<Text>{t('profileCard.copyNPub')}</Text>
|
||||
</View>
|
||||
{user?.nip05 && (
|
||||
<View style={styles.shareActionButton}>
|
||||
<IconButton
|
||||
icon='check-decagram-outline'
|
||||
size={28}
|
||||
onPress={() => {
|
||||
setShowNotification('npubCopied')
|
||||
Clipboard.setString(user?.nip05 ?? '')
|
||||
bottomSheetShareRef.current?.close()
|
||||
}}
|
||||
/>
|
||||
<Text>{t('profileCard.copyNip05')}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</RBSheet>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@ -247,7 +319,18 @@ const styles = StyleSheet.create({
|
||||
actionButton: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexBasis: '33.333333%',
|
||||
flexBasis: '25%',
|
||||
marginBottom: 4,
|
||||
},
|
||||
qr: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
},
|
||||
shareActionButton: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexBasis: '50%',
|
||||
marginBottom: 4,
|
||||
},
|
||||
list: {
|
||||
|
@ -6,6 +6,7 @@ import { Linking, StyleSheet } from 'react-native'
|
||||
import { Text } from 'react-native-paper'
|
||||
import { Config } from '../Pages/ConfigPage'
|
||||
import { imageHostingServices } from '../Constants/Services'
|
||||
import { randomInt } from '../Functions/NativeFunctions'
|
||||
|
||||
export interface AppContextProps {
|
||||
init: () => void
|
||||
@ -22,6 +23,7 @@ export interface AppContextProps {
|
||||
setImageHostingService: (imageHostingService: string) => void
|
||||
setSatoshi: (showPublicImages: 'kebab' | 'sats') => void
|
||||
getSatoshiSymbol: (fontSize?: number) => JSX.Element
|
||||
getImageHostingService: () => string
|
||||
}
|
||||
|
||||
export interface AppContextProviderProps {
|
||||
@ -42,6 +44,7 @@ export const initialAppContext: AppContextProps = {
|
||||
setSatoshi: () => {},
|
||||
imageHostingService: Object.keys(imageHostingServices)[0],
|
||||
setImageHostingService: () => {},
|
||||
getImageHostingService: () => "",
|
||||
getSatoshiSymbol: () => <></>,
|
||||
}
|
||||
|
||||
@ -101,6 +104,14 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
|
||||
)
|
||||
}
|
||||
|
||||
const getImageHostingService: () => string = () => {
|
||||
if (imageHostingService !== 'random') return imageHostingService
|
||||
|
||||
const randomIndex = randomInt(1, Object.keys(imageHostingServices).length)
|
||||
|
||||
return Object.keys(imageHostingServices)[randomIndex - 1]
|
||||
}
|
||||
|
||||
useEffect(init, [])
|
||||
|
||||
return (
|
||||
@ -108,6 +119,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
|
||||
value={{
|
||||
imageHostingService,
|
||||
setImageHostingService,
|
||||
getImageHostingService,
|
||||
init,
|
||||
loadingDb,
|
||||
database,
|
||||
|
@ -61,3 +61,5 @@ export const validNip21: (string: string | undefined) => boolean = (string) => {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const randomInt: (min: number, max: number) => number = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
|
||||
|
@ -47,8 +47,11 @@
|
||||
"isNotContact": "Not following",
|
||||
"contentWarning": "Sensitive content",
|
||||
"send": "Send",
|
||||
"imageUploaded": "Your file has been uploaded.\nConsider donating to the service: {{uri}}",
|
||||
"imageUploadErro": "There was an error while trying to upload your file"
|
||||
"imageUploaded": "Your file has been uploaded.\nConsider donating to the service:\n{{uri}}",
|
||||
"imageUploadErro": "There was an error while trying to upload your file",
|
||||
"uploadImage": "Upload image now",
|
||||
"cancel": "Cancel",
|
||||
"poweredBy": "Powered by {{uri}}"
|
||||
},
|
||||
"menuItems": {
|
||||
"relays": "Relays",
|
||||
@ -64,7 +67,8 @@
|
||||
"showPublicImages": "Show images on public feed",
|
||||
"showSensitive": "Show sensitive notes",
|
||||
"satoshi": "Satoshi symbol",
|
||||
"imageHostingService": "Image hosting service"
|
||||
"imageHostingService": "Image hosting service",
|
||||
"random": "Random"
|
||||
},
|
||||
"noteCard": {
|
||||
"answering": "Answer to {{pubkey}}",
|
||||
@ -233,6 +237,8 @@
|
||||
"unfollow": "Following",
|
||||
"block": "Block",
|
||||
"unblock": "Unblock",
|
||||
"share": "Share",
|
||||
"copyNip05": "Copy NIP-05",
|
||||
"copyNPub": "Copy key"
|
||||
},
|
||||
"conversationsFeed": {
|
||||
|
@ -46,7 +46,12 @@
|
||||
"isContact": "Siguiendo",
|
||||
"isNotContact": "Sin seguir",
|
||||
"contentWarning": "Contenido sensible",
|
||||
"send": "Enviar"
|
||||
"send": "Enviar",
|
||||
"imageUploaded": "Tu archivo se ha subido.\nConsidera donar al servicio:\n{{uri}}",
|
||||
"imageUploadErro": "Se ha producido un error al subir la imagen.",
|
||||
"uploadImage": "Subir imagen ahora",
|
||||
"cancel": "Cancelar",
|
||||
"poweredBy": "Servido por {{uri}}"
|
||||
},
|
||||
"menuItems": {
|
||||
"relays": "Relays",
|
||||
@ -62,7 +67,8 @@
|
||||
"showPublicImages": "Mostrar imágenes en feed global",
|
||||
"showSensitive": "Mostrar notas sensibles",
|
||||
"satoshi": "Símbolo de satoshi",
|
||||
"imageHostingService": "Servicio de subida de imágenes"
|
||||
"imageHostingService": "Servicio de subida de imágenes",
|
||||
"random": "Aleatorio"
|
||||
},
|
||||
"noteCard": {
|
||||
"answering": "Responder a {{pubkey}}",
|
||||
@ -217,8 +223,10 @@
|
||||
"message": "Mensaje",
|
||||
"follow": "Seguir",
|
||||
"block": "Bloquear",
|
||||
"share": "Share",
|
||||
"unblock": "Desbloquear",
|
||||
"unfollow": "Siguiendo",
|
||||
"copyNip05": "Copiar NIP-05",
|
||||
"copyNPub": "Copiar clave"
|
||||
},
|
||||
"conversationsFeed": {
|
||||
|
@ -46,7 +46,12 @@
|
||||
"isContact": "Following",
|
||||
"isNotContact": "Not following",
|
||||
"contentWarning": "Делекатный контент",
|
||||
"send": "Send"
|
||||
"send": "Send",
|
||||
"imageUploaded": "Tu archivo se ha subido.\nConsidera donar al servicio:\n{{uri}}",
|
||||
"imageUploadErro": "Se ha producido un error al subir la imagen.",
|
||||
"uploadImage": "Subir imagen ahora",
|
||||
"cancel": "Отменить",
|
||||
"poweredBy": "Powered by {{uri}}"
|
||||
},
|
||||
"menuItems": {
|
||||
"relays": "Реле",
|
||||
@ -62,7 +67,8 @@
|
||||
"configPage": {
|
||||
"showPublicImages": "Show images on public feed",
|
||||
"showSensitive": "Show sensitive notes",
|
||||
"satoshi": "Satoshi symbol"
|
||||
"satoshi": "Satoshi symbol",
|
||||
"random": "Random"
|
||||
},
|
||||
"noteCard": {
|
||||
"answering": "Ответить {{pubkey}}",
|
||||
@ -218,6 +224,8 @@
|
||||
"block": "Block",
|
||||
"unblock": "Desbloquear",
|
||||
"unfollow": "Following",
|
||||
"share": "Share",
|
||||
"copyNip05": "Copy NIP-05",
|
||||
"copyNPub": "Copy key"
|
||||
},
|
||||
"conversationsFeed": {
|
||||
|
@ -67,10 +67,10 @@ export const ConfigPage: React.FC = () => {
|
||||
}, [])
|
||||
|
||||
const imageHostingOptions = React.useMemo(() => {
|
||||
return Object.keys(imageHostingServices).map((service, index) => {
|
||||
return ['random', ...Object.keys(imageHostingServices)].map((service, index) => {
|
||||
return {
|
||||
key: index,
|
||||
title: <Text>{imageHostingServices[service].uri}</Text>,
|
||||
title: <Text>{imageHostingServices[service]?.uri ?? t(`configPage.${service}`)}</Text>,
|
||||
onPress: () => {
|
||||
setImageHostingService(service)
|
||||
SInfo.getItem('config', {}).then((result) => {
|
||||
@ -141,7 +141,12 @@ export const ConfigPage: React.FC = () => {
|
||||
<List.Item
|
||||
title={t('configPage.imageHostingService')}
|
||||
onPress={() => bottomSheetImageHostingRef.current?.open()}
|
||||
right={() => <Text>{imageHostingServices[imageHostingService].uri}</Text>}
|
||||
right={() => (
|
||||
<Text>
|
||||
{imageHostingServices[imageHostingService]?.uri ??
|
||||
t(`configPage.${imageHostingService}`)}
|
||||
</Text>
|
||||
)}
|
||||
/>
|
||||
<RBSheet ref={bottomSheetSatoshiRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
<FlatList
|
||||
|
@ -167,15 +167,19 @@ export const RelaysPage: React.FC = () => {
|
||||
)}
|
||||
<RBSheet ref={bottomSheetAddRef} closeOnDragDown={true} customStyles={rbSheetCustomStyles}>
|
||||
<View style={styles.addRelay}>
|
||||
<TextInput
|
||||
mode='outlined'
|
||||
label={t('relaysPage.labelAdd') ?? ''}
|
||||
onChangeText={setAddRelayInput}
|
||||
value={addRelayInput}
|
||||
/>
|
||||
<Button mode='contained' onPress={onPressAddRelay}>
|
||||
{t('relaysPage.add')}
|
||||
</Button>
|
||||
<View style={styles.bottomDrawerButton}>
|
||||
<TextInput
|
||||
mode='outlined'
|
||||
label={t('relaysPage.labelAdd') ?? ''}
|
||||
onChangeText={setAddRelayInput}
|
||||
value={addRelayInput}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.bottomDrawerButton}>
|
||||
<Button mode='contained' onPress={onPressAddRelay}>
|
||||
{t('relaysPage.add')}
|
||||
</Button>
|
||||
</View>
|
||||
<Button
|
||||
mode='outlined'
|
||||
onPress={() => {
|
||||
@ -224,6 +228,9 @@ const styles = StyleSheet.create({
|
||||
title: {
|
||||
paddingLeft: 16,
|
||||
},
|
||||
bottomDrawerButton: {
|
||||
paddingBottom: 16,
|
||||
},
|
||||
container: {
|
||||
padding: 0,
|
||||
paddingBottom: 32,
|
||||
@ -243,7 +250,6 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
addRelay: {
|
||||
alignContent: 'center',
|
||||
height: '80%',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
relayActions: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import React, { useContext, useEffect, useMemo, useState } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
@ -9,15 +9,17 @@ import { Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getETags, getTaggedPubKeys } from '../../Functions/RelayFunctions/Events'
|
||||
import { getUsers, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import { launchImageLibrary } from 'react-native-image-picker'
|
||||
import { Asset, launchImageLibrary } from 'react-native-image-picker'
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
IconButton,
|
||||
Snackbar,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableRipple,
|
||||
useTheme,
|
||||
} from 'react-native-paper'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { goBack } from '../../lib/Navigation'
|
||||
@ -25,13 +27,15 @@ import { Kind } from 'nostr-tools'
|
||||
import ProfileData from '../../Components/ProfileData'
|
||||
import NoteCard from '../../Components/NoteCard'
|
||||
import { imageHostingServices } from '../../Constants/Services'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
|
||||
interface SendPageProps {
|
||||
route: { params: { note: Note; type?: 'reply' | 'repost' } | undefined }
|
||||
}
|
||||
|
||||
export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
const { database, imageHostingService } = useContext(AppContext)
|
||||
const theme = useTheme()
|
||||
const { database, getImageHostingService } = useContext(AppContext)
|
||||
const { publicKey } = useContext(UserContext)
|
||||
const { relayPool, lastConfirmationtId } = useContext(RelayPoolContext)
|
||||
const { t } = useTranslation('common')
|
||||
@ -43,7 +47,10 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
const [userSuggestions, setUserSuggestions] = useState<User[]>([])
|
||||
const [userMentions, setUserMentions] = useState<User[]>([])
|
||||
const [isSending, setIsSending] = useState<boolean>(false)
|
||||
const [imageUpload, setImageUpload] = useState<Asset>()
|
||||
const note = React.useMemo(() => route.params?.note, [])
|
||||
const [imageHostingService] = useState<string>(getImageHostingService())
|
||||
const bottomSheetImageRef = React.useRef<RBSheet>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (isSending) goBack()
|
||||
@ -76,32 +83,44 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
return `@${user.name ?? formatPubKey(user.id)}`
|
||||
}
|
||||
|
||||
const onUploadImage: () => void = async () => {
|
||||
launchImageLibrary({ selectionLimit: 1, quality: 0, mediaType: 'photo' }, async (result) => {
|
||||
const getImage: () => void = () => {
|
||||
launchImageLibrary({ selectionLimit: 1, mediaType: 'photo' }, async (result) => {
|
||||
const assets = result?.assets
|
||||
if (assets && assets.length > 0) {
|
||||
const file = assets[0]
|
||||
if (file.uri && file.type && file.fileName) {
|
||||
imageHostingServices[imageHostingService]
|
||||
.sendFunction(file.uri, file.type, file.fileName)
|
||||
.then((imageUri) => {
|
||||
setShowNotification('imageUploaded')
|
||||
setUploadingFile(false)
|
||||
setContent((prev) => `${prev}\n\n${imageUri}`)
|
||||
})
|
||||
.catch(() => {
|
||||
setShowNotification('imageUploadErro')
|
||||
setUploadingFile(false)
|
||||
})
|
||||
setImageUpload(file)
|
||||
bottomSheetImageRef.current?.open()
|
||||
} else {
|
||||
setUploadingFile(false)
|
||||
setShowNotification('imageUploadErro')
|
||||
}
|
||||
} else {
|
||||
setUploadingFile(false)
|
||||
setShowNotification('imageUploadErro')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const uploadImage: () => void = async () => {
|
||||
if (imageUpload?.uri && imageUpload.type && imageUpload.fileName) {
|
||||
imageHostingServices[imageHostingService]
|
||||
.sendFunction(imageUpload.uri, imageUpload.type, imageUpload.fileName)
|
||||
.then((imageUri) => {
|
||||
bottomSheetImageRef.current?.close()
|
||||
setUploadingFile(false)
|
||||
setContent((prev) => `${prev}\n\n${imageUri}`)
|
||||
setImageUpload(undefined)
|
||||
setShowNotification('imageUploaded')
|
||||
})
|
||||
.catch(() => {
|
||||
bottomSheetImageRef.current?.close()
|
||||
setUploadingFile(false)
|
||||
setShowNotification('imageUploadErro')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const onPressSend: () => void = () => {
|
||||
if (database && publicKey) {
|
||||
setIsSending(true)
|
||||
@ -179,6 +198,21 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
</TouchableRipple>
|
||||
)
|
||||
|
||||
const bottomSheetStyles = React.useMemo(() => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.colors.background,
|
||||
paddingTop: 16,
|
||||
paddingRight: 16,
|
||||
paddingBottom: 32,
|
||||
paddingLeft: 16,
|
||||
borderTopRightRadius: 28,
|
||||
borderTopLeftRadius: 28,
|
||||
height: 'auto',
|
||||
},
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={[styles.textInputContainer, { paddingBottom: note ? 200 : 10 }]}>
|
||||
@ -222,7 +256,7 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
icon='image-outline'
|
||||
size={25}
|
||||
style={styles.imageButton}
|
||||
onPress={onUploadImage}
|
||||
onPress={getImage}
|
||||
disabled={uploadingFile}
|
||||
/>
|
||||
</View>
|
||||
@ -239,6 +273,31 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<RBSheet ref={bottomSheetImageRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
<Card style={styles.imageUploadPreview}>
|
||||
{imageUpload && (
|
||||
<Card.Cover source={{ uri: imageUpload?.uri ?? '' }} resizeMode='contain' />
|
||||
)}
|
||||
</Card>
|
||||
<Text>{t('sendPage.poweredBy', { uri: imageHostingServices[imageHostingService].uri })}</Text>
|
||||
<Button
|
||||
style={styles.buttonSpacer}
|
||||
mode='contained'
|
||||
onPress={uploadImage}
|
||||
loading={uploadingFile}
|
||||
>
|
||||
{t('sendPage.uploadImage')}
|
||||
</Button>
|
||||
<Button
|
||||
mode='outlined'
|
||||
onPress={() => {
|
||||
bottomSheetImageRef.current?.close()
|
||||
setImageUpload(undefined)
|
||||
}}
|
||||
>
|
||||
{t('sendPage.cancel')}
|
||||
</Button>
|
||||
</RBSheet>
|
||||
{showNotification && (
|
||||
<Snackbar
|
||||
style={styles.snackbar}
|
||||
@ -324,6 +383,14 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 4,
|
||||
paddingLeft: 5,
|
||||
},
|
||||
imageUploadPreview: {
|
||||
marginTop: 16,
|
||||
marginBottom: 16,
|
||||
},
|
||||
buttonSpacer: {
|
||||
marginTop: 16,
|
||||
marginBottom: 16,
|
||||
},
|
||||
})
|
||||
|
||||
export default SendPage
|
||||
|
@ -53,6 +53,7 @@
|
||||
"react-native-screens": "^3.19.0",
|
||||
"react-native-securerandom": "^1.0.1",
|
||||
"react-native-sensitive-info": "^5.5.8",
|
||||
"react-native-share": "^8.1.0",
|
||||
"react-native-svg": "^13.7.0",
|
||||
"react-native-tab-view": "^3.3.4",
|
||||
"react-native-vector-icons": "^9.2.0",
|
||||
|
@ -7287,6 +7287,11 @@ react-native-sensitive-info@^5.5.8:
|
||||
resolved "https://registry.yarnpkg.com/react-native-sensitive-info/-/react-native-sensitive-info-5.5.8.tgz#6ebb67eed83d1c2867bd435630ef2c41eef204ed"
|
||||
integrity sha512-p99oaEW4QG1RdUNrkvd/c6Qdm856dQw/Rk81f9fA6Y3DlPs6ADNdU+jbPuTz3CcOUJwuKBDNenX6LR9KfmGFEg==
|
||||
|
||||
react-native-share@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-8.1.0.tgz#34c9977e5aa49254b191f19d779bb4cff43fe2da"
|
||||
integrity sha512-gME+6+FkQQ5/Ss4ulPjxwtgyZsF/YqBvG3qIVWN1urUhFFG2m2kycrNB0fPLLZy517/G6aDyUMioVZtPQArRHQ==
|
||||
|
||||
react-native-svg@^13.7.0:
|
||||
version "13.7.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.7.0.tgz#be2ffb935e996762543dd7376bdc910722f7a43c"
|
||||
|
Loading…
Reference in New Issue
Block a user