Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display a warning text on the home screen if the user has refundable transactions. #337

Merged
merged 9 commits into from
Feb 4, 2025
102 changes: 102 additions & 0 deletions app/components/home-screen/Info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { useEffect, useState } from "react"
import { View } from "react-native"
import { ApolloError } from "@apollo/client"
import { makeStyles, Text, useTheme } from "@rneui/themed"
import { StackNavigationProp } from "@react-navigation/stack"
import { RootStackParamList } from "@app/navigation/stack-param-lists"
import { listRefundables, RefundableSwap } from "@breeztech/react-native-breez-sdk-liquid"

// hooks
import { useI18nContext } from "@app/i18n/i18n-react"
import { useNavigation } from "@react-navigation/native"

// components
import { GaloyIcon } from "../atomic/galoy-icon"
import { GaloyErrorBox } from "../atomic/galoy-error-box"
import { GaloyTertiaryButton } from "../atomic/galoy-tertiary-button"

// gql
import { GraphQLError } from "graphql"
import { GraphQlApplicationError } from "@app/graphql/generated"
import { getErrorMessages } from "@app/graphql/utils"

type ErrorInput =
| readonly GraphQLError[]
| readonly GraphQlApplicationError[]
| ApolloError

type Props = {
error?: ErrorInput
}

const Info: React.FC<Props> = ({ error }) => {
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>()
const styles = useStyles()
const { colors, mode } = useTheme().theme
const { LL } = useI18nContext()

const [refundables, setRefundables] = useState<RefundableSwap[]>([])

const color = mode === "light" ? colors.warning : colors.black

useEffect(() => {
fetchRefundables()
}, [])

const fetchRefundables = async () => {
try {
const refundables = (await listRefundables()) || []
setRefundables(refundables)
} catch (err) {
console.log("List Refundables Err: ", err)
}
}

if (error || refundables.length > 0) {
return (
<View style={styles.marginButtonContainer}>
{refundables.length > 0 && (
<View
style={error ? { ...styles.container, marginBottom: 5 } : styles.container}
>
<GaloyIcon name="warning" size={14} color={color} />
<Text style={styles.textContainer} type={"p3"} color={color}>
{`${LL.HomeScreen.refundableWarning()} `}
<GaloyTertiaryButton
clear
title={LL.HomeScreen.refundables()}
onPress={() => navigation.navigate("RefundTransactionList")}
containerStyle={{ marginTop: -4 }}
/>
</Text>
</View>
)}
{error && <GaloyErrorBox errorMessage={getErrorMessages(error)} />}
</View>
)
} else {
return null
}
}

export default Info

const useStyles = makeStyles(({ colors }) => ({
marginButtonContainer: {
marginBottom: 20,
},
container: {
flexDirection: "row",
alignItems: "center",
justifyContent: "flex-start",
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 8,
backgroundColor: colors.warning9,
},
textContainer: {
overflow: "hidden",
marginLeft: 4,
flex: 1,
},
}))
3 changes: 2 additions & 1 deletion app/components/home-screen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import AccountCreateModal from "./AccountCreateModal"
import Header from "./Header"
import Buttons from "./Buttons"
import Transactions from "./Transactions"
import Info from "./Info"

export { AccountCreateModal, Header, Buttons, Transactions }
export { AccountCreateModal, Header, Buttons, Transactions, Info }
2 changes: 2 additions & 0 deletions app/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ const en: BaseTranslation = {
updateAvailable: "An update is available.\nTap to update now",
useLightning: "We use the Lightning Network.",
myAccounts: "My Accounts",
refundableWarning: "Please complete or refund all pending transactions before uninstalling Flash or pending funds will be lost.",
refundables: "Refundables"
},
PinScreen: {
attemptsRemaining: "Incorrect PIN. {attemptsRemaining: number} attempts remaining.",
Expand Down
16 changes: 16 additions & 0 deletions app/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,14 @@ type RootTranslation = {
* M​y​ ​A​c​c​o​u​n​t​s
*/
myAccounts: string
/**
* Please complete or refund all pending transactions before uninstalling Flash or pending funds will be lost.
*/
refundableWarning: string
/**
* Refundables
*/
refundables: string
}
PinScreen: {
/**
Expand Down Expand Up @@ -6020,6 +6028,14 @@ export type TranslationFunctions = {
* My Accounts
*/
myAccounts: () => LocalizedString
/**
* Please complete or refund all pending transactions before uninstalling Flash or pending funds will be lost.
*/
refundableWarning: () => LocalizedString
/**
* Refundables
*/
refundables: () => LocalizedString
}
PinScreen: {
/**
Expand Down
5 changes: 4 additions & 1 deletion app/i18n/raw-i18n/source/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,10 @@
"scan": "Scan QR",
"updateAvailable": "An update is available.\nTap to update now",
"useLightning": "We use the Lightning Network.",
"myAccounts": "My Accounts"
"myAccounts": "My Accounts",
"refundableWarning": "Please complete or refund all pending transactions before uninstalling Flash or pending funds will be lost.",
"refundables": "Refundables"

},
"PinScreen": {
"attemptsRemaining": "Incorrect PIN. {attemptsRemaining: number} attempts remaining.",
Expand Down
2 changes: 2 additions & 0 deletions app/rne-theme/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const light = {
red: "#DC2626",

warning: "#F59E0B",
warning9: "#fff1d8",
}

const dark = {
Expand Down Expand Up @@ -98,6 +99,7 @@ const dark = {
red: "#DC2626",

warning: "#F59E0B",
warning9: "#7d591a",
}

export { light, dark }
2 changes: 2 additions & 0 deletions app/rne-theme/themed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ declare module "@rneui/themed" {
primary5: string
error9: string

warning9: string

blue5: string

loaderForeground: string
Expand Down
23 changes: 9 additions & 14 deletions app/screens/home-screen/home-screen.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import React, { useCallback, useEffect, useState } from "react"
import { RefreshControl, ScrollView, View } from "react-native"
import { RefreshControl, ScrollView } from "react-native"
import { makeStyles, useTheme } from "@rneui/themed"

// components
import { AppUpdate } from "@app/components/app-update/app-update"
import WalletOverview from "@app/components/wallet-overview/wallet-overview"
import { GaloyErrorBox } from "@app/components/atomic/galoy-error-box"
import { SetDefaultAccountModal } from "@app/components/set-default-account-modal"
import { UnVerifiedSeedModal } from "@app/components/unverified-seed-modal"
import { Screen } from "../../components/screen"
import {
AccountCreateModal,
Buttons,
Header,
Info,
Transactions,
} from "@app/components/home-screen"

// queries
import {
Expand All @@ -18,7 +24,6 @@ import {
useRealtimePriceQuery,
} from "@app/graphql/generated"
import { useIsAuthed } from "@app/graphql/is-authed-context"
import { getErrorMessages } from "@app/graphql/utils"
import { getDefaultWallet } from "@app/graphql/wallets-utils"

// hooks
Expand All @@ -29,12 +34,6 @@ import useNostrProfile from "@app/hooks/use-nostr-profile"
import { useAppDispatch } from "@app/store/redux"
import { setUserData } from "@app/store/redux/slices/userSlice"
import { usePersistentStateContext } from "@app/store/persistent-state"
import {
AccountCreateModal,
Buttons,
Header,
Transactions,
} from "@app/components/home-screen"

export const HomeScreen: React.FC = () => {
const dispatch = useAppDispatch()
Expand Down Expand Up @@ -139,11 +138,7 @@ export const HomeScreen: React.FC = () => {
pendingBalance={null}
setIsUnverifiedSeedModalVisible={setIsUnverifiedSeedModalVisible}
/>
{error && (
<View style={styles.marginButtonContainer}>
<GaloyErrorBox errorMessage={getErrorMessages(error)} />
</View>
)}
<Info error={error} />
<Buttons
setModalVisible={setModalVisible}
setDefaultAccountModalVisible={setDefaultAccountModalVisible}
Expand Down
28 changes: 26 additions & 2 deletions app/screens/refund-flow/RefundDestination.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import React, { useState } from "react"
import React, { useEffect, useState } from "react"
import { TouchableOpacity, View } from "react-native"
import { makeStyles, Text } from "@rneui/themed"
import { useI18nContext } from "@app/i18n/i18n-react"
import { Network, parsePaymentDestination } from "@flash/client"
import { StackScreenProps } from "@react-navigation/stack"
import { RecommendedFees } from "@breeztech/react-native-breez-sdk-liquid"

// components
import { Screen } from "@app/components/screen"
import { DestinationField, Fees } from "@app/components/refund-flow"
import { GaloyPrimaryButton } from "@app/components/atomic/galoy-primary-button"

// hooks
import { useActivityIndicator } from "@app/hooks"

// utils
import { LNURL_DOMAINS } from "@app/config"
import { RootStackParamList } from "@app/navigation/stack-param-lists"
import { fetchRecommendedFees } from "@app/utils/breez-sdk-liquid"

// gql
import {
Expand All @@ -28,7 +33,9 @@ const RefundDestination: React.FC<Props> = ({ navigation, route }) => {
const styles = useStyles()
const isAuthed = useIsAuthed()
const { LL } = useI18nContext()
const { toggleActivityIndicator } = useActivityIndicator()

const [recommendedFees, setRecommendedFees] = useState<RecommendedFees>()
const [selectedFee, setSelectedFee] = useState<number>()
const [selectedFeeType, setSelectedFeeType] = useState<string>()
const [destination, setDestination] = useState<string>()
Expand All @@ -43,6 +50,19 @@ const RefundDestination: React.FC<Props> = ({ navigation, route }) => {

const usdWallet = getUsdWallet(data?.me?.defaultAccount?.wallets)

useEffect(() => {
if (!recommendedFees) {
fetchBreezRecommendedFees()
}
}, [])

const fetchBreezRecommendedFees = async () => {
toggleActivityIndicator(true)
const recommendedFees = await fetchRecommendedFees()
setRecommendedFees(recommendedFees)
toggleActivityIndicator(false)
}

const validateDestination = () => {
if (!destination) {
setError("Please, enter destination to proceed")
Expand Down Expand Up @@ -120,7 +140,11 @@ const RefundDestination: React.FC<Props> = ({ navigation, route }) => {
<Text style={styles.text}>{LL.RefundFlow.refundTo()}</Text>
</TouchableOpacity>
)}
<Fees selectedFeeType={selectedFeeType} onSelectFee={onSelectFee} />
<Fees
recommendedFees={recommendedFees}
selectedFeeType={selectedFeeType}
onSelectFee={onSelectFee}
/>
<Text style={styles.errorMsg}>{error}</Text>
<View style={styles.buttonContainer}>
<GaloyPrimaryButton
Expand Down