diff --git a/src/krist/wallets/utils.ts b/src/krist/wallets/utils.ts index aa66110..b39bd32 100644 --- a/src/krist/wallets/utils.ts +++ b/src/krist/wallets/utils.ts @@ -33,7 +33,7 @@ /** Hook that fetches the wallets from the Redux store. */ export function useWallets(): WalletsHookResponse { - const { wallets } = useSelector((s: RootState) => s.wallets, shallowEqual); + const wallets = useSelector((s: RootState) => s.wallets.wallets, shallowEqual); const walletAddressMap = Object.values(wallets) .reduce((o, wallet) => ({ ...o, [wallet.address]: wallet }), {}); diff --git a/src/pages/transactions/send/SendTransactionForm.tsx b/src/pages/transactions/send/SendTransactionForm.tsx index 630773e..98f90dd 100644 --- a/src/pages/transactions/send/SendTransactionForm.tsx +++ b/src/pages/transactions/send/SendTransactionForm.tsx @@ -8,6 +8,10 @@ import { useTranslation, Trans } from "react-i18next"; import { TranslatedError } from "@utils/i18n"; +import { useSelector, useDispatch } from "react-redux"; +import { RootState } from "@store"; +import { setLastTxFrom } from "@actions/WalletsActions"; + import { useWallets, useMasterPasswordOnly, Wallet } from "@wallets"; import { useMountEffect } from "@utils"; @@ -24,6 +28,9 @@ import "./SendTransactionForm.less"; +import Debug from "debug"; +const debug = Debug("kristweb:send-transaction-form"); + // This is from https://github.com/tmpim/Krist/blob/a924f3f/src/controllers/transactions.js#L102 // except `+` is changed to `*`. const METADATA_REGEXP = /^[\x20-\x7F\n]*$/i; @@ -36,23 +43,39 @@ } interface Props { + from?: Wallet | string; + to?: string; form: FormInstance; triggerSubmit: () => Promise; } function SendTransactionForm({ + from: rawInitialFrom, + to: initialTo, form, triggerSubmit }: Props): JSX.Element { const { t } = useTranslation(); - // Used to get the initial wallet to show for the 'from' field - // TODO: Remember this value? - const { addressList } = useWallets(); - const initialFrom = addressList[0] || ""; + // Get the initial wallet to show for the 'from' field. Use the provided + // wallet if we were given one, otherwise use the saved 'last wallet', + // or the first wallet we can find. + const initialFromAddress = typeof rawInitialFrom === "string" + ? rawInitialFrom : rawInitialFrom?.address; + + const { addressList, walletAddressMap } = useWallets(); + const firstWallet = addressList[0]; + + // Validate the lastTxFrom wallet still exists + const dispatch = useDispatch(); + const lastTxFrom = useSelector((s: RootState) => s.wallets.lastTxFrom); + const lastTxFromAddress = lastTxFrom && addressList.includes(lastTxFrom) + ? lastTxFrom : undefined; + + const initialFrom = initialFromAddress || lastTxFromAddress || firstWallet; const [from, setFrom] = useState(initialFrom); - const [to, setTo] = useState(""); + const [to, setTo] = useState(initialTo); // Focus the 'to' input on initial render const toRef = useRef(null); @@ -60,9 +83,23 @@ toRef?.current?.focus(); }); - function onValuesChange(_: unknown, values: Partial) { + function onValuesChange( + changed: Partial, + values: Partial + ) { setFrom(values.from || ""); setTo(values.to || ""); + + // Update and save the lastTxFrom so the next time the modal is opened + // it will remain on this address + if (changed.from) { + const currentWallet = walletAddressMap[changed.from]; + if (currentWallet && currentWallet.address !== lastTxFromAddress) { + debug("updating lastTxFrom to %s", currentWallet.address); + dispatch(setLastTxFrom(currentWallet)); + localStorage.setItem("lastTxFrom", currentWallet.address); + } + } } return
void; onSuccess?: (transaction: KristTransaction) => void; } @@ -152,6 +191,8 @@ } export function useTransactionForm({ + from: initialFrom, + to: initialTo, onError, onSuccess }: TransactionFormHookProps = {}): TransactionFormHookResponse { @@ -287,6 +328,8 @@ // Create the transaction form instance here to be rendered by the caller const txForm = <> diff --git a/src/store/actions/WalletsActions.ts b/src/store/actions/WalletsActions.ts index 3bad1f0..aa188d2 100644 --- a/src/store/actions/WalletsActions.ts +++ b/src/store/actions/WalletsActions.ts @@ -38,3 +38,5 @@ export interface RecalculateWalletsPayload { wallets: Record } export const recalculateWallets = createAction(constants.RECALCULATE_WALLETS, (wallets): RecalculateWalletsPayload => ({ wallets }))(); + +export const setLastTxFrom = createAction(constants.SET_LAST_TX_FROM)(); diff --git a/src/store/constants.ts b/src/store/constants.ts index f5bf7fc..31a24fc 100644 --- a/src/store/constants.ts +++ b/src/store/constants.ts @@ -17,6 +17,7 @@ export const SYNC_WALLETS = "SYNC_WALLETS"; export const UNSYNC_WALLET = "UNSYNC_WALLET"; export const RECALCULATE_WALLETS = "RECALCULATE_WALLETS"; +export const SET_LAST_TX_FROM = "SET_LAST_TX_FROM"; // Settings // --- diff --git a/src/store/reducers/WalletsReducer.ts b/src/store/reducers/WalletsReducer.ts index 63fc2ea..38e4e4f 100644 --- a/src/store/reducers/WalletsReducer.ts +++ b/src/store/reducers/WalletsReducer.ts @@ -8,11 +8,15 @@ export interface State { readonly wallets: WalletMap; + readonly lastTxFrom: string; } export function getInitialWalletsState(): State { const wallets = loadWallets(); - return { wallets }; + return { + wallets, + lastTxFrom: localStorage.getItem("lastTxFrom") || "" + }; } function assignNewWalletProperties(state: State, id: string, partialWallet: Partial, allowedKeys?: (keyof Wallet)[]) { @@ -102,5 +106,8 @@ .reduce((o, wallet) => ({ ...o, [wallet.id]: wallet }), {}); return { ...state, wallets: { ...state.wallets, ...updatedWallets }}; - }); + }) + // Set last transaction from + .handleAction(actions.setLastTxFrom, (state, { payload }) => + ({ ...state, lastTxFrom: payload.address }));