Skip to content

Commit

Permalink
Avoid foreground prompts for self-created token (#201)
Browse files Browse the repository at this point in the history
* add a share function helper

* Fixes #170
  • Loading branch information
KKA11010 committed Sep 13, 2023
1 parent 87f06ee commit 8ea155b
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 82 deletions.
29 changes: 3 additions & 26 deletions src/components/Backup.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { l } from '@log'
import { useThemeContext } from '@src/context/Theme'
import { NS } from '@src/i18n'
import { globals } from '@styles'
import { formatMintUrl } from '@util'
import { formatMintUrl, share } from '@util'
import { useTranslation } from 'react-i18next'
import { Share, StyleSheet, Text } from 'react-native'
import { StyleSheet, Text } from 'react-native'

import ActionButtons from './ActionButtons'
import useCopy from './hooks/Copy'
Expand All @@ -19,28 +18,6 @@ export default function BackupSuccess({ token, mint }: IBackupSuccessProps) {
const { color } = useThemeContext()
const { copied, copy } = useCopy()

const handleShare = async () => {
try {
const res = await Share.share({
message: token, // `cashu://${route.params.token}`
url: `cashu://${token}`
})
if (res.action === Share.sharedAction) {
if (res.activityType) {
// shared with activity type of result.activityType
l('shared with activity type of result.activityType')
} else {
// shared
l('shared')
}
} else if (res.action === Share.dismissedAction) {
// dismissed
l('sharing dismissed')
}
} catch (e) {
l(e)
}
}
return (
<>
<Text style={[globals(color).navTxt, styles.subTxt]}>
Expand All @@ -57,7 +34,7 @@ export default function BackupSuccess({ token, mint }: IBackupSuccessProps) {
<ActionButtons
absolutePos
topBtnTxt={t('share')}
topBtnAction={() => void handleShare()}
topBtnAction={() => void share(token, `cashu://${token}`)}
bottomBtnTxt={copied ? t('copied') : t('copyToken')}
bottomBtnAction={() => void copy(token)}
/>
Expand Down
4 changes: 4 additions & 0 deletions src/context/FocusClaim.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { getMintsUrls } from '@db'
import { l } from '@log'
import type { ITokenInfo } from '@model'
import { NS } from '@src/i18n'
import { store } from '@store'
import { STORE_KEYS } from '@store/consts'
import { addToHistory } from '@store/latestHistoryEntries'
import { formatInt, formatMintUrl, getStrFromClipboard, hasTrustedMint, isCashuToken, isErr, sleep } from '@util'
import { claimToken, isTokenSpendable } from '@wallet'
Expand All @@ -29,8 +31,10 @@ const useFocusClaim = () => {
// in an empty string returned. Find a better way than the following function to handle it.
let isSpent = false
const fn = async () => {
const selfCreated = await store.get(STORE_KEYS.createdToken)
const clipboard = await getStrFromClipboard()
if (!clipboard?.length || !isCashuToken(clipboard)) { return false }
if (selfCreated === clipboard) { return false }
const info = getTokenInfo(clipboard)
if (!info) { return false }
// check if mint is a trusted one
Expand Down
28 changes: 3 additions & 25 deletions src/screens/Payment/Receive/Invoice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import { NS } from '@src/i18n'
import { getBalance } from '@src/storage/db'
import { addToHistory } from '@store/latestHistoryEntries'
import { globals, highlight as hi, mainColors } from '@styles'
import { formatMintUrl, formatSeconds, isErr, openUrl } from '@util'
import { formatMintUrl, formatSeconds, isErr, openUrl, share } from '@util'
import { requestToken } from '@wallet'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Share, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

export default function InvoiceScreen({ navigation, route }: TMintInvoicePageProps) {
Expand Down Expand Up @@ -62,28 +62,6 @@ export default function InvoiceScreen({ navigation, route }: TMintInvoicePagePro
}
}

const handleShare = async () => {
try {
const res = await Share.share({
message: paymentRequest,
})
if (res.action === Share.sharedAction) {
if (res.activityType) {
// shared with activity type of result.activityType
l('shared with activity type of result.activityType')
} else {
// shared
l('shared')
}
} else if (res.action === Share.dismissedAction) {
// dismissed
l('sharing dismissed')
}
} catch (e) {
l(e)
}
}

// countdown
useEffect(() => {
const timeLeft = Math.ceil((expiryTime - Date.now()) / 1000)
Expand Down Expand Up @@ -157,7 +135,7 @@ export default function InvoiceScreen({ navigation, route }: TMintInvoicePagePro
<TxtButton
txt={t('shareInvoice')}
icon={<ShareIcon width={24} height={24} color={hi[highlight]} />}
onPress={() => void handleShare()}
onPress={() => void share(paymentRequest)}
/>
</View>
:
Expand Down
39 changes: 10 additions & 29 deletions src/screens/Payment/Send/EncodedToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ import useCopy from '@comps/hooks/Copy'
import { CopyIcon, ShareIcon } from '@comps/Icons'
import QR from '@comps/QR'
import Txt from '@comps/Txt'
import { l } from '@log'
import type { TEncodedTokenPageProps } from '@model/nav'
import TopNav from '@nav/TopNav'
import { isIOS } from '@src/consts'
import { useThemeContext } from '@src/context/Theme'
import { NS } from '@src/i18n'
import { store } from '@store'
import { STORE_KEYS } from '@store/consts'
import { globals, highlight as hi, mainColors } from '@styles'
import { vib } from '@util'
import { share, vib } from '@util'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Share, StyleSheet, View } from 'react-native'
import { StyleSheet, View } from 'react-native'

/**
* The page that shows the created Cashu token that can be scanned, copied or shared
Expand All @@ -24,31 +25,11 @@ export default function EncodedTokenPage({ navigation, route }: TEncodedTokenPag
const { copied, copy } = useCopy()
const [error, setError] = useState({ msg: '', open: false })

useEffect(() => vib(400), [])

// share token
const handleShare = async () => {
try {
const res = await Share.share({
message: route.params.token, // `cashu://${route.params.token}`
url: `cashu://${route.params.token}`
})
if (res.action === Share.sharedAction) {
if (res.activityType) {
// shared with activity type of result.activityType
l('shared with activity type of result.activityType')
} else {
// shared
l('shared')
}
} else if (res.action === Share.dismissedAction) {
// dismissed
l('sharing dismissed')
}
} catch (e) {
l(e)
}
}
useEffect(() => {
// we can save the created token here to avoid foreground prompts of self-created tokens
void store.set(STORE_KEYS.createdToken, route.params.token)
vib(400)
}, [route.params.token])

return (
<View style={[globals(color).container, styles.container, { paddingBottom: isIOS ? 50 : 20 }]}>
Expand Down Expand Up @@ -79,7 +60,7 @@ export default function EncodedTokenPage({ navigation, route }: TEncodedTokenPag
<ActionButtons
topBtnTxt={t('share')}
topIcon={<ShareIcon width={20} height={20} color={mainColors.WHITE} />}
topBtnAction={() => void handleShare()}
topBtnAction={() => void share(route.params.token, `cashu://${route.params.token}`)}
bottomBtnTxt={copied ? t('copied') + '!' : t('copyToken')}
bottomIcon={<CopyIcon color={hi[highlight]} />}
bottomBtnAction={() => void copy(route.params.token)}
Expand Down
3 changes: 2 additions & 1 deletion src/storage/store/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export const STORE_KEYS = {
defaultMint: 'MINT_STORE=|:|=default_mint',
hiddenBal: 'privacy_balance',
hiddenTxs: 'privacy_txs',
latestHistory: 'history_latest'
latestHistory: 'history_latest',
createdToken: 'createdToken',
}

export const SECURESTORE_KEY = 'auth_pin'
Expand Down
22 changes: 21 additions & 1 deletion src/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { ILnUrl, IProofSelection } from '@model'
import axios from 'axios'
import type { Buffer } from 'buffer/'
import * as Clipboard from 'expo-clipboard'
import { Linking, Vibration } from 'react-native'
import { Linking, Share, Vibration } from 'react-native'

import { getLanguageCode } from './localization'
import { isArr, isBuf, isNum, isStr } from './typeguards'
Expand Down Expand Up @@ -276,4 +276,24 @@ export async function copyStrToClipboard(str: string) {
export async function getStrFromClipboard() {
const s = await Clipboard.getStringAsync()
return !s || s === 'null' ? null : s
}

export async function share(message: string, url?: string) {
try {
const res = await Share.share({ message, url })
if (res.action === Share.sharedAction) {
if (res.activityType) {
// shared with activity type of result.activityType
l('shared with activity type of result.activityType')
} else {
// shared
l('shared')
}
} else if (res.action === Share.dismissedAction) {
// dismissed
l('sharing dismissed')
}
} catch (e) {
l('[quick-share error] ', e)
}
}

0 comments on commit 8ea155b

Please sign in to comment.