From a8211975bb3cff17006e8630ec74271b2c31c45f Mon Sep 17 00:00:00 2001 From: RealWorld777 Date: Fri, 24 May 2024 12:07:43 +0900 Subject: [PATCH 1/2] fix: some bug fix - settings page refresh - fix tokenlist showing difference - canceling my orders error - transaction reverse order - add transfer fab border - logout clean user data --- mobile/src/context/AuthContext.tsx | 14 +++++++++++- .../Main/Orderbook/components/Core.tsx | 15 ++++++------- mobile/src/screens/Main/Orderbook/index.tsx | 9 +++++--- mobile/src/screens/Main/Settings/index.tsx | 22 ++++++++++++------- mobile/src/screens/Main/Transaction/index.tsx | 2 +- .../screens/Main/Wallet/TransferButtonFab.tsx | 2 ++ .../src/screens/Main/components/Tokenlist.tsx | 18 +++++++-------- mobile/src/screens/Setup/Create/Reminder.tsx | 2 +- 8 files changed, 53 insertions(+), 31 deletions(-) diff --git a/mobile/src/context/AuthContext.tsx b/mobile/src/context/AuthContext.tsx index 9f0cfd9..dd1ad41 100644 --- a/mobile/src/context/AuthContext.tsx +++ b/mobile/src/context/AuthContext.tsx @@ -101,10 +101,22 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { const logout = () => { dispatch(setIsAuthenticated(false)); dispatch(setPassword("")); + setTempPassword(""); setUser(null); + setBalances({}); + setCurrentAddress(""); + setAllAddresses([]); + setHistories([]); + setTxStatus("Closed"); + setTxId(""); + setExpectedTick(0); + setTxResult(""); + setTokenBalances({}); + setIsLoading(false); }; useEffect(() => { + setTokens([]); if (currentAddress != "") { setIsLoading(true); getHistory(currentAddress); @@ -116,7 +128,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { if (currentAddress != "") { getHistory(currentAddress); } - }, [balances]); + }, [balances[currentAddress]]); useEffect(() => { if (user?.accountInfo) { diff --git a/mobile/src/screens/Main/Orderbook/components/Core.tsx b/mobile/src/screens/Main/Orderbook/components/Core.tsx index 84ba334..807a3ce 100644 --- a/mobile/src/screens/Main/Orderbook/components/Core.tsx +++ b/mobile/src/screens/Main/Orderbook/components/Core.tsx @@ -97,20 +97,19 @@ const Core: React.FC = ({ const validateOrder = (orderList: IOrderUnit[], flag: string) => { let isValidAddress = false; + let isValidPriceOrAmount = false; for (const order of orderList) { if (order[1] === currentAddress) { isValidAddress = true; - if (order[3] !== price || parseInt(order[2]) < parseInt(amount)) { - showError( - "E-34: " + - (order[3] !== price - ? lang.toast_NotExistOrder - : lang.toast_NoOrder) - ); - return false; + if (order[3] == price && parseInt(order[2]) >= parseInt(amount)) { + isValidPriceOrAmount = true; } } } + if (!isValidPriceOrAmount) { + showError("E-34: " + lang.toast_NotExistOrder); + return false; + } if (!isValidAddress) { showError("E-35: " + lang.toast_NoOrder); return false; diff --git a/mobile/src/screens/Main/Orderbook/index.tsx b/mobile/src/screens/Main/Orderbook/index.tsx index 9376681..f48ad1a 100644 --- a/mobile/src/screens/Main/Orderbook/index.tsx +++ b/mobile/src/screens/Main/Orderbook/index.tsx @@ -14,6 +14,7 @@ import Orderlist from "./components/Orderlist"; import { useAuth } from "@app/context/AuthContext"; import { myOrders } from "@app/api/api"; import eventEmitter from "@app/api/eventEmitter"; +import { useIsFocused } from "@react-navigation/native"; type IOrderUnit = [number, string, string, string]; // index, address, amount, price interface IOrderData { @@ -35,11 +36,13 @@ const Orderbook: React.FC = () => { const [orderData, setOrderData] = useState({}); const modal1 = useDisclose(); const lang = local.Main.Orderbook; - const { currentAddress, allAddresses, txResult, isLoading, setIsLoading } = - useAuth(); + const { currentAddress, txResult, txStatus } = useAuth(); useEffect(() => { myOrders(); + }, [currentAddress, txResult, useIsFocused()]); + + useEffect(() => { const handleMyOrdersEvent = (res: any) => { setOrderData(res.data); }; @@ -47,7 +50,7 @@ const Orderbook: React.FC = () => { return () => { eventEmitter.off("S2C/my-orders", handleMyOrdersEvent); }; - }, [currentAddress, txResult]); + }, []); return ( <> diff --git a/mobile/src/screens/Main/Settings/index.tsx b/mobile/src/screens/Main/Settings/index.tsx index 67d097f..d1a2742 100644 --- a/mobile/src/screens/Main/Settings/index.tsx +++ b/mobile/src/screens/Main/Settings/index.tsx @@ -8,7 +8,7 @@ import { VStack, useColorMode, } from "native-base"; -import React, { useMemo, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import ColorModeSetting from "./ColorModeSetting"; import LanguageSetting from "./LanguageSetting"; import NetworkSetting from "./NetworkSetting"; @@ -16,11 +16,13 @@ import SecuritySetting from "./SecuritySetting"; import local from "@app/utils/locales"; import { Image } from "react-native"; import About from "./About"; +import { useIsFocused } from "@react-navigation/native"; const Settings: React.FC = () => { const { bgColor, textColor } = useColors(); const [language, setLanguage] = useState(""); const lang = local.Main.Settings; + const isFocused = useIsFocused(); return ( { {lang.Settings} - - - - - - - + {isFocused ? ( + + + + + + + + ) : ( + <> + )} ); }; diff --git a/mobile/src/screens/Main/Transaction/index.tsx b/mobile/src/screens/Main/Transaction/index.tsx index e8515d6..d9e748b 100644 --- a/mobile/src/screens/Main/Transaction/index.tsx +++ b/mobile/src/screens/Main/Transaction/index.tsx @@ -30,7 +30,7 @@ const Transaction: React.FC = () => { <> {histories.length ? ( - {histories?.map((tx, key) => ( + {histories?.reverse().map((tx, key) => ( { diff --git a/mobile/src/screens/Main/Wallet/TransferButtonFab.tsx b/mobile/src/screens/Main/Wallet/TransferButtonFab.tsx index 54fbaff..c8bb103 100644 --- a/mobile/src/screens/Main/Wallet/TransferButtonFab.tsx +++ b/mobile/src/screens/Main/Wallet/TransferButtonFab.tsx @@ -36,6 +36,8 @@ const TransferButtonFab: React.FC = ({ onToggle }) => { right: -1, zIndex: 100, }} + borderColor="white" + borderWidth="1" > )} diff --git a/mobile/src/screens/Main/components/Tokenlist.tsx b/mobile/src/screens/Main/components/Tokenlist.tsx index 1d23395..0eaa2b2 100644 --- a/mobile/src/screens/Main/components/Tokenlist.tsx +++ b/mobile/src/screens/Main/components/Tokenlist.tsx @@ -75,15 +75,15 @@ const Tokenlist: React.FC = () => { - ) : Object.keys(tokenBalances).length === 0 ? ( - -
- - - {lang.NoAssets} - -
-
+ // ) : Object.keys(tokenBalances).length === 0 ? ( + // + //
+ // + // + // {lang.NoAssets} + // + //
+ //
) : ( {formattedItems} diff --git a/mobile/src/screens/Setup/Create/Reminder.tsx b/mobile/src/screens/Setup/Create/Reminder.tsx index 04e901a..9a25b63 100644 --- a/mobile/src/screens/Setup/Create/Reminder.tsx +++ b/mobile/src/screens/Setup/Create/Reminder.tsx @@ -34,7 +34,7 @@ const Reminder: React.FC = () => { justifyItems="center" > {step == 1 && ( - + Date: Fri, 24 May 2024 16:28:26 +0900 Subject: [PATCH 2/2] feat: add some feature - repeat fetch history - receive qu detection - receive toast --- mobile/src/components/SocketComponent.tsx | 11 ++- mobile/src/context/AuthContext.tsx | 54 +++++++++-- .../src/screens/Main/components/Tokenlist.tsx | 92 +++++++++---------- .../screens/Main/components/TransferModal.tsx | 1 - mobile/src/utils/locales/languages.json | 21 +++-- mobile/src/utils/locales/setItem.js | 16 ++-- 6 files changed, 120 insertions(+), 75 deletions(-) diff --git a/mobile/src/components/SocketComponent.tsx b/mobile/src/components/SocketComponent.tsx index 3a983cc..b4c3287 100644 --- a/mobile/src/components/SocketComponent.tsx +++ b/mobile/src/components/SocketComponent.tsx @@ -11,8 +11,13 @@ import { useAuth } from "@app/context/AuthContext"; export const SocketCom: React.FC = () => { const dispatch = useDispatch(); - const { setBalances, setTokenBalances, allAddresses, setIsLoading } = - useAuth(); + const { + setBalances, + setTokenBalances, + allAddresses, + balances, + setPrevBalances, + } = useAuth(); useEffect(() => { eventEmitter.on("S2C/live", (res) => { if (res.data.command == "CurrentTickInfo") { @@ -34,6 +39,7 @@ export const SocketCom: React.FC = () => { if (res.data.balance) { setBalances((prev) => { + setPrevBalances(prev); return { ...prev, [res.data.address]: parseFloat(res.data.balance), @@ -44,6 +50,7 @@ export const SocketCom: React.FC = () => { res.data.balances.map((balance: [number, string]) => { if (balance[0] < allAddresses.length) setBalances((prev) => { + setPrevBalances(prev); return { ...prev, [allAddresses[balance[0]]]: parseFloat(balance[1]), diff --git a/mobile/src/context/AuthContext.tsx b/mobile/src/context/AuthContext.tsx index dd1ad41..e8eef33 100644 --- a/mobile/src/context/AuthContext.tsx +++ b/mobile/src/context/AuthContext.tsx @@ -63,6 +63,7 @@ interface AuthContextType { }> >; setIsLoading: React.Dispatch>; + setPrevBalances: React.Dispatch>; } type TransactionItem = [string, string, string, string, string, string]; @@ -82,13 +83,18 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { >("Closed"); const [txId, setTxId] = useState(""); const [expectedTick, setExpectedTick] = useState(0); - const [txResult, setTxResult] = useState(""); + const [txResult, setTxResult] = useState("Unknown"); const [tokenBalances, setTokenBalances] = useState<{ [name: string]: Balances; }>({}); const [statusInterval, setStatusInterval] = useState(); const [isLoading, setIsLoading] = useState(false); + const [outTx, setOutTx] = useState(false); + const [prevBalances, setPrevBalances] = useState({}); + const [historyNum, setHistoryNum] = useState(histories.length); + const [expectingHistoryUpdate, setExpectingHistoryUpdate] = useState(false); + const lang = local.Toast; const login = (userDetails: UserDetailType | null) => { @@ -124,10 +130,16 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { } }, [currentAddress]); + // If someone send qu to me useEffect(() => { - if (currentAddress != "") { - getHistory(currentAddress); - } + if (currentAddress == "") return; + if (Object.is(prevBalances, {})) return; + if (!balances[currentAddress] || !prevBalances[currentAddress]) return; + if (balances[currentAddress] > prevBalances[currentAddress]) setOutTx(true); + else setOutTx(false); + setHistoryNum(histories.length + 1); + getHistory(currentAddress); + setExpectingHistoryUpdate(true); }, [balances[currentAddress]]); useEffect(() => { @@ -137,6 +149,30 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { } }, [user]); + useEffect(() => { + if (expectingHistoryUpdate && currentAddress !== "") { + const interval = setInterval(() => { + if (histories.length !== historyNum) { + getHistory(currentAddress); + } else { + const newHistory = histories.reverse()[0]; + if (outTx) + Toast.show({ + type: "info", + text1: lang.ReceivedQUFrom.replace( + "{amount}", + `${Math.abs(parseInt(newHistory[3]))}` + ).replace("{address}", newHistory[2]), + }); + setExpectingHistoryUpdate(false); // Clear the flag when history is up-to-date + clearInterval(interval); // Clear the interval when done + } + }, 1500); + + return () => clearInterval(interval); + } + }, [histories.length, historyNum, currentAddress, expectingHistoryUpdate]); + useEffect(() => { const handleHistoryEvent = (res: any) => { console.log("S2C/histories: ", res); @@ -178,9 +214,11 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { if (res.data) { if (res.data == "failed") { setTxStatus("Rejected"); + setTxResult("Failed"); Toast.show({ type: "error", text1: "E-23: " + lang.TransferFailed }); } else if (res.data.value.result == 0) { setTxStatus("Pending"); + setTxResult("Pending"); } else if (res.data.value.result == 1) { setTxResult(res.data.value.display); } else { @@ -189,6 +227,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { } else { Toast.show({ type: "error", text1: "E-24: " + lang.TransferFailed }); setTxStatus("Rejected"); + setTxResult("Pending"); clearInterval(statusInterval); } }; @@ -241,12 +280,6 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => { } }, [txResult]); - // useEffect(() => { - // setTokenBalances((prev) => { - // return { ...prev, QU: balances }; - // }); - // }, [balances]); - return ( { setExpectedTick, setTokenBalances, setIsLoading, + setPrevBalances, }} > {children} diff --git a/mobile/src/screens/Main/components/Tokenlist.tsx b/mobile/src/screens/Main/components/Tokenlist.tsx index 0eaa2b2..5685894 100644 --- a/mobile/src/screens/Main/components/Tokenlist.tsx +++ b/mobile/src/screens/Main/components/Tokenlist.tsx @@ -26,48 +26,46 @@ const Tokenlist: React.FC = () => { ); const lang = local.Main.Components; - // const formattedItems = useMemo(() => { - // return ( - const formattedItems = ( - <> - {tokens?.map((token, key) => { - const TokenIcon = tokenIcons.find((t) => t.symbol == token)?.icon; - const balance = tokenBalances?.[token]?.[currentAddress] || 0; - const price = parseInt(tokenprices?.[token]?.[0] || "0"); // Handle missing price + const formattedItems = useMemo(() => { + return ( + <> + {tokens?.map((token, key) => { + const TokenIcon = tokenIcons.find((t) => t.symbol == token)?.icon; + const balance = tokenBalances?.[token]?.[currentAddress] || 0; + const price = parseInt(tokenprices?.[token]?.[0] || "0"); // Handle missing price - const valueInQU = balance * price; - const usdValue = valueInQU * parseFloat(marketcap.price); + const valueInQU = balance * price; + const usdValue = valueInQU * parseFloat(marketcap.price); - return ( - - - - {TokenIcon && } - - {token} - {balance.toLocaleString()} + return ( + + + + {TokenIcon && } + + {token} + {balance.toLocaleString()} + + + + {valueInQU} QU + $ {usdValue.toFixed(7)} - - {valueInQU} QU - $ {usdValue.toFixed(7)} - - - - ); - })} - - ); - // ); - // }, [tokenBalances, tokenprices, marketcap?.price, tokens]); +
+ ); + })} + + ); + }, [tokenBalances, tokenprices, marketcap?.price, tokens]); return ( <> @@ -75,16 +73,16 @@ const Tokenlist: React.FC = () => { - // ) : Object.keys(tokenBalances).length === 0 ? ( - // - //
- // - // - // {lang.NoAssets} - // - //
- //
) : ( + // ) : Object.keys(tokenBalances).length === 0 ? ( + // + //
+ // + // + // {lang.NoAssets} + // + //
+ //
{formattedItems} diff --git a/mobile/src/screens/Main/components/TransferModal.tsx b/mobile/src/screens/Main/components/TransferModal.tsx index 0c532fc..0c1e600 100644 --- a/mobile/src/screens/Main/components/TransferModal.tsx +++ b/mobile/src/screens/Main/components/TransferModal.tsx @@ -196,7 +196,6 @@ const TransferModal: React.FC = ({ isOpen, onToggle, onPress }) => { label={lang.ExpectedTick} value={expectedTick.toString()} /> -
diff --git a/mobile/src/utils/locales/languages.json b/mobile/src/utils/locales/languages.json index a0e366b..316cc0c 100644 --- a/mobile/src/utils/locales/languages.json +++ b/mobile/src/utils/locales/languages.json @@ -227,7 +227,8 @@ "ErrorGettingToken": "Error occurred in getting tokens!", "ErrorTransfer": "Error occurred in transfer!", "TransferFailed": "Transfer Failed!", - "TransactionCompleted": "Transaction Completed Successfully!" + "TransactionCompleted": "Transaction Completed Successfully!", + "ReceivedQUFrom": "You received {amount} QU from {address}" } }, "zh": { @@ -458,7 +459,8 @@ "ErrorGettingToken": "获取令牌时发生错误!", "ErrorTransfer": "转账时发生错误!", "TransferFailed": "转账失败!", - "TransactionCompleted": "交易成功完成!" + "TransactionCompleted": "交易成功完成!", + "ReceivedQUFrom": "你收到来自 {address} 的 {amount} QU" } }, "es": { @@ -689,7 +691,8 @@ "ErrorGettingToken": "¡Error al obtener los tokens!", "ErrorTransfer": "¡Error al transferir!", "TransferFailed": "¡Transferencia fallida!", - "TransactionCompleted": "¡Transacción completada con éxito!" + "TransactionCompleted": "¡Transacción completada con éxito!", + "ReceivedQUFrom": "Has recibido {amount} QU de {address}" } }, "fr": { @@ -920,7 +923,8 @@ "ErrorGettingToken": "Erreur lors de l'obtention des jetons !", "ErrorTransfer": "Erreur lors du transfert !", "TransferFailed": "Échec du transfert !", - "TransactionCompleted": "Transaction terminée avec succès !" + "TransactionCompleted": "Transaction terminée avec succès !", + "ReceivedQUFrom": "Vous avez reçu {amount} QU de {address}" } }, "de": { @@ -1151,7 +1155,8 @@ "ErrorGettingToken": "Fehler beim Abrufen der Token!", "ErrorTransfer": "Fehler beim Übertragen!", "TransferFailed": "Übertragung fehlgeschlagen!", - "TransactionCompleted": "Transaktion erfolgreich abgeschlossen!" + "TransactionCompleted": "Transaktion erfolgreich abgeschlossen!", + "ReceivedQUFrom": "Sie haben {amount} QU von {address} erhalten" } }, "ru": { @@ -1382,7 +1387,8 @@ "ErrorGettingToken": "Произошла ошибка при получении токенов!", "ErrorTransfer": "Произошла ошибка при переводе!", "TransferFailed": "Перевод не удался!", - "TransactionCompleted": "Транзакция успешно завершена!" + "TransactionCompleted": "Транзакция успешно завершена!", + "ReceivedQUFrom": "Вы получили {amount} QU от {address}" } }, "ja": { @@ -1613,7 +1619,8 @@ "ErrorGettingToken": "トークンの取得中にエラーが発生しました!", "ErrorTransfer": "転送中にエラーが発生しました!", "TransferFailed": "転送に失敗しました!", - "TransactionCompleted": "取引が正常に完了しました!" + "TransactionCompleted": "取引が正常に完了しました!", + "ReceivedQUFrom": "{address} から {amount} QU を受け取りました" } } } \ No newline at end of file diff --git a/mobile/src/utils/locales/setItem.js b/mobile/src/utils/locales/setItem.js index e394c65..924be0d 100644 --- a/mobile/src/utils/locales/setItem.js +++ b/mobile/src/utils/locales/setItem.js @@ -80,15 +80,15 @@ function deleteKeyPath(keyPath, filePath = "languages.json") { } // Example -const keyPath = "Toast.TransactionCompleted"; +const keyPath = "Toast.ReceivedQUFrom"; const newTranslations = { - en: "Transaction Completed Successfully!", - zh: "交易成功完成!", - es: "¡Transacción completada con éxito!", - fr: "Transaction terminée avec succès !", - de: "Transaktion erfolgreich abgeschlossen!", - ja: "取引が正常に完了しました!", - ru: "Транзакция успешно завершена!", + en: "You received {amount} QU from {address}", + zh: "你收到来自 {address} 的 {amount} QU", + es: "Has recibido {amount} QU de {address}", + fr: "Vous avez reçu {amount} QU de {address}", + de: "Sie haben {amount} QU von {address} erhalten", + ja: "{address} から {amount} QU を受け取りました", + ru: "Вы получили {amount} QU от {address}", }; addTranslation(keyPath, newTranslations);