add share by qr code

This commit is contained in:
KraXen72
2024-09-02 22:22:22 +02:00
parent d0f650aa8c
commit 2cfe4d0fa3
5 changed files with 138 additions and 34 deletions
+8 -2
View File
@@ -1,6 +1,6 @@
import { observer } from "mobx-react-lite"
import React from "react"
import { ColorValue, Image, TextStyle, View, ViewStyle } from "react-native"
import { ColorValue, Image, Pressable, TextStyle, View, ViewStyle } from "react-native"
import { Icon, Text } from "."
import { spacing, useThemeColor } from "../theme"
import { getImageSource } from '../utils/utils'
@@ -10,6 +10,10 @@ import { iconRegistry } from '.'
export interface AvatarHeaderProps {
heading?: string,
text?: string,
/** will have no effect if text is falsy */
onTextPress?: () => void,
/** will have no effect if text is falsy */
onTextLongPress?: () => void,
picture?: string
/** default is 96 for pic, 48 for icon - another option is 90 or 80 */
pictureHeight?: number,
@@ -58,7 +62,9 @@ export const AvatarHeader = observer(function (props: AvatarHeaderProps) {
)}
</View>
{props.heading && <Text style={{ fontSize: 26, lineHeight: 40 }} text={props.heading} adjustsFontSizeToFit={true} numberOfLines={1} />}
{props.text && <Text preset='bold' text={props.text} style={{ color: 'white', marginBottom: spacing.small }} numberOfLines={2} />}
{props.text && <Pressable onPress={props.onTextPress} onLongPress={props.onTextLongPress}>
<Text preset='bold' text={props.text} style={{ color: 'white', marginBottom: spacing.small }} numberOfLines={2} />
</Pressable>}
{props.children}
</View>
)
+83
View File
@@ -0,0 +1,83 @@
import React, { useState } from 'react'
import { View } from 'react-native'
import type { TextStyle } from 'react-native';
import { BottomModal } from './BottomModal';
import { Text } from './Text';
import { QRCodeBlock, QRCodeBlockTypes } from '../screens/Wallet/QRCode';
import { spacing, useThemeColor } from '../theme';
import { translate, TxKeyPath } from '../i18n';
interface QRShareModalProps {
url: string,
isVisible?: boolean,
onClose?: () => void,
type: QRCodeBlockTypes
shareModalTitle?: string,
shareModalTx?: TxKeyPath,
subHeading?: string,
label?: string
labelTx?: TxKeyPath,
size?: number,
}
export const QRShareModal = (props: QRShareModalProps) => {
const labelText = useThemeColor('textDim')
const {
url,
isVisible = true,
onClose = () => {},
shareModalTitle,
shareModalTx,
subHeading,
type,
label,
labelTx,
size
} = props
let finalTx: TxKeyPath | undefined = shareModalTx
if (!shareModalTx && !shareModalTitle) finalTx = 'common.share'
return (
<BottomModal
isVisible={isVisible}
ContentComponent={
<>
<Text
tx={finalTx}
text={shareModalTitle}
preset="subheading"
style={{alignSelf: 'center', marginBottom: spacing.small}}
/>
<View style={$newContainer}>
<QRCodeBlock
qrCodeData={url.toString()}
title={subHeading || shareModalTitle || translate('common.share')}
type={type}
size={size}
/>
{(label || labelTx) &&
<Text
size="xxs"
style={{
color: labelText,
marginTop: spacing.medium,
alignSelf: 'center',
}}
text={label}
tx={labelTx && !label ? labelTx : undefined}
/>
}
</View>
</>
}
onBackButtonPress={onClose}
onBackdropPress={onClose}
/>
)
}
const $newContainer: TextStyle = {
alignSelf: 'stretch',
}
+17 -1
View File
@@ -33,6 +33,7 @@ import AppError, { Err } from '../utils/AppError'
import { useHeader } from '../utils/useHeader'
import { CurrencySign } from './Wallet/CurrencySign'
import { SvgXml } from 'react-native-svg'
import { QRShareModal } from '../components/QRShareModal'
if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
@@ -368,6 +369,7 @@ export const MintInfoScreen: FC<SettingsStackScreenProps<'MintInfo'>> = observer
const [mintInfo, setMintInfo] = useState<GetInfoResponse | undefined>()
const [mint, setMint] = useState<Mint>()
const [isLocalInfoVisible, setIsLocalInfoVisible] = useState<boolean>(false)
const [shareModalVisible, setShareModalVisible] = useState(false)
const [error, setError] = useState<AppError | undefined>()
const [info, setInfo] = useState('')
@@ -415,6 +417,9 @@ export const MintInfoScreen: FC<SettingsStackScreenProps<'MintInfo'>> = observer
setIsLocalInfoVisible(!isLocalInfoVisible)
}
const openShareModal = () => { setShareModalVisible(true) }
const closeShareModal = () => { setShareModalVisible(false) }
const handleError = function (e: AppError): void {
setIsLoading(false)
setError(e)
@@ -442,7 +447,10 @@ export const MintInfoScreen: FC<SettingsStackScreenProps<'MintInfo'>> = observer
}
headerHeightModifier={0.26}
heading={mintInfo?.name ?? translate('mintInfo.loadingNamePlaceholder')}
text={route.params.mintUrl}>
text={route.params.mintUrl}
onTextPress={openShareModal}
onTextLongPress={openShareModal}
>
{mint?.units ? (
<View style={{flexDirection: 'row'}}>
{mint.units.map(unit => (
@@ -515,6 +523,14 @@ export const MintInfoScreen: FC<SettingsStackScreenProps<'MintInfo'>> = observer
</>
}
/>
<QRShareModal
url={route.params.mintUrl}
shareModalTx='mintsScreen.share'
subHeading={mintInfo?.name ?? translate('mintInfo.loadingNamePlaceholder')}
type='URL'
isVisible={shareModalVisible}
onClose={closeShareModal}
/>
{error && <ErrorModal error={error} />}
{info && <InfoModal message={info} />}
</View>
+28 -29
View File
@@ -31,8 +31,7 @@ import { SvgXml } from 'react-native-svg'
import { isStateTreeNode } from 'mobx-state-tree'
import { MintKeyset } from '@cashu/cashu-ts'
import { QRCodeBlock } from './Wallet/QRCode'
import { QRShareModal } from '../components/QRShareModal'
export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(function MintsScreen({route, navigation}) {
useHeader({
@@ -47,11 +46,12 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
const [mintUrl, setMintUrl] = useState('')
const [defaultMintUrl, setDefaultMintUrl] = useState<string>(MINIBITS_MINT_URL)
const [selectedMint, setSelectedMint] = useState<Mint | undefined>()
const [sharingMint, setSharingMint] = useState<string | undefined>()
const [lastSelectedMint, setLastSelectedMint] = useState<Mint | undefined>()
const [info, setInfo] = useState('')
const [error, setError] = useState<AppError | undefined>()
const [isLoading, setIsLoading] = useState(false)
const [isAddMintVisible, setIsAddMintVisible] = useState(false)
const [shareModalVisible, setShareModalVisible] = useState(false)
const toggleAddMintModal = async function () {
@@ -75,15 +75,15 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
const gotoScan = function () {
toggleAddMintModal()
navigation.navigate('WalletNavigator', {screen: 'Scan'})
toggleAddMintModal()
navigation.navigate('WalletNavigator', {screen: 'Scan'})
}
const gotoInfo = function () {
if(!selectedMint) {return}
navigation.navigate('MintInfo', {mintUrl: selectedMint?.mintUrl})
onMintUnselect()
if(!selectedMint) {return}
navigation.navigate('MintInfo', {mintUrl: selectedMint?.mintUrl})
onMintUnselect()
}
@@ -247,20 +247,22 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
}
}
const shareMint = function () {
// setSelectedMint(void 0)
setSharingMint(selectedMint?.mintUrl)
}
const onMintSelect = function (mint: Mint) {
setSelectedMint(mint)
setLastSelectedMint(mint)
}
const onMintUnselect = function () {
setSelectedMint(undefined)
}
const openShareModal = () => {
setSelectedMint(void 0)
setShareModalVisible(true)
}
const closeShareModal = () => { setShareModalVisible(false) }
const handleError = function (e: AppError) {
setIsLoading(false)
setError(e)
@@ -379,7 +381,7 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
/>*/}
<ListItem
leftIcon="faShareNodes"
onPress={shareMint}
onPress={openShareModal}
tx="mintsScreen.share"
bottomSeparator={true}
style={{paddingHorizontal: spacing.medium}}
@@ -389,7 +391,7 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
onPress={onCopyMintUrl}
tx='mintsScreen.copy'
bottomSeparator={true}
style={{paddingHorizontal: spacing.medium}}
style={{paddingHorizontal: spacing.medium}}j
/>
<ListItem
leftIcon='faGlobe'
@@ -487,20 +489,17 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
onBackButtonPress={toggleAddMintModal}
onBackdropPress={toggleAddMintModal}
/>
{/* TODO fix */}
<BottomModal
isVisible={sharingMint && selectedMint ? true : false}
ContentComponent={
<>
<QRCodeBlock
qrCodeData={sharingMint || ''}
title='Share Mint URL'
type='URL'
/>
<Button preset='secondary' onPress={() => setSharingMint(void 0)} text='Close' />
</>
}
/>
{/* using lastSelectedMint so we can close the underlying modal */}
{lastSelectedMint && typeof lastSelectedMint?.mintUrl === 'string' &&
<QRShareModal
url={lastSelectedMint?.mintUrl as string}
shareModalTx='mintsScreen.share'
subHeading={lastSelectedMint?.shortname as string}
type='URL'
isVisible={shareModalVisible}
onClose={closeShareModal}
/>
}
{error && <ErrorModal error={error} />}
{info && <InfoModal message={info} />}
</Screen>
+2 -2
View File
@@ -11,11 +11,11 @@ import { translate } from "../../i18n"
import { CashuUtils, TokenV3 } from "../../services/cashu/cashuUtils"
import { log } from "../../services"
export type QRCodeBlockTypes = 'EncodedV3Token' | 'EncodedV4Token' | 'Bolt11Invoice' | 'URL' | 'NWC'
export const QRCodeBlock = function (props: {
qrCodeData: string
title: string
type: 'EncodedV3Token' | 'EncodedV4Token' | 'Bolt11Invoice' | 'URL' | 'NWC'
type: QRCodeBlockTypes
size?: number
}
) {