diff --git a/apps/pay/components/Currency/currency-dropdown.tsx b/apps/pay/components/Currency/currency-dropdown.tsx
index edaaa6056d3..c66b6129edf 100644
--- a/apps/pay/components/Currency/currency-dropdown.tsx
+++ b/apps/pay/components/Currency/currency-dropdown.tsx
@@ -1,6 +1,7 @@
+"use client"
import React, { useEffect } from "react"
-import { useRouter } from "next/router"
+import { useSearchParams } from "next/navigation"
import { useCurrencyListQuery } from "../../lib/graphql/generated"
@@ -15,18 +16,20 @@ export default function CurrencyDropdown({
style?: React.CSSProperties
showOnlyFlag?: boolean
}) {
- const router = useRouter()
+ const searchParams = useSearchParams()
+ const display = searchParams?.get("display")
+
const { data: currencyData } = useCurrencyListQuery()
const [selectedDisplayCurrency, setSelectedDisplayCurrency] = React.useState(
- router.query.display && typeof router.query.display === "string"
- ? router.query.display
+ display && typeof display === "string"
+ ? display
: localStorage.getItem("display") ?? "USD",
)
const [isDropDownOpen, setIsDropDownOpen] = React.useState(false)
useEffect(() => {
- if (router.query?.display && typeof router.query.display === "string") {
- setSelectedDisplayCurrency(router.query.display)
+ if (display && typeof display === "string") {
+ setSelectedDisplayCurrency(display)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
diff --git a/apps/pay/components/Layouts/AppLayout.tsx b/apps/pay/components/Layouts/AppLayout.tsx
index 50191d023d3..8b04fcb56eb 100644
--- a/apps/pay/components/Layouts/AppLayout.tsx
+++ b/apps/pay/components/Layouts/AppLayout.tsx
@@ -1,6 +1,8 @@
-import copy from "copy-to-clipboard"
+"use client"
+
import Link from "next/link"
-import { useRouter } from "next/router"
+import copy from "copy-to-clipboard"
+import { useRouter, useSearchParams } from "next/navigation"
import React from "react"
import { Image, OverlayTrigger, Tooltip } from "react-bootstrap"
@@ -15,7 +17,8 @@ type Props = {
const AppLayout = ({ children, username }: Props) => {
const router = useRouter()
- const { memo } = useRouter().query
+ const searchParams = useSearchParams()
+ const memo = searchParams?.get("memo")
const [openSideBar, setOpenSideBar] = React.useState
(false)
const [copied, setCopied] = React.useState(false)
const lightningAddr = username
@@ -40,15 +43,9 @@ const AppLayout = ({ children, username }: Props) => {
const navigateHome = () => {
let pathname = "/"
if (username) pathname = `/${username}`
- router.push(
- {
- pathname,
- },
- undefined,
- { shallow: true },
- )
+ window.history.pushState({}, "", `${pathname}`)
setTimeout(() => {
- router.reload() // Force a reload after a short delay to allow location href to update
+ router.refresh() // Force a reload after a short delay to allow location href to update
}, 200)
}
diff --git a/apps/pay/components/Memo/index.tsx b/apps/pay/components/Memo/index.tsx
index 8c9bd4379bc..6df45c2ce5a 100644
--- a/apps/pay/components/Memo/index.tsx
+++ b/apps/pay/components/Memo/index.tsx
@@ -1,8 +1,9 @@
-import { useRouter } from "next/router"
import React from "react"
import { Modal } from "react-bootstrap"
-import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer"
+import { useSearchParams, useParams } from "next/navigation"
+
+import { ACTIONS, ACTION_TYPE } from "../../app/_reducer"
import styles from "./memo.module.css"
@@ -12,35 +13,32 @@ interface Props {
}
const Memo = ({ state, dispatch }: Props) => {
- const router = useRouter()
- const { username, amount, sats, unit, memo, display } = router.query
+ const searchParams = useSearchParams()
+ const { username } = useParams()
+ const query = searchParams ? Object.fromEntries(searchParams.entries()) : {}
+
+ const { amount, sats, unit, memo, display } = query
const [openModal, setOpenModal] = React.useState(false)
const [note, setNote] = React.useState(memo?.toString() || "")
const handleSetMemo = () => {
if (unit === "SAT" || unit === "CENT") {
- router.push(
- {
- pathname: `${username}`,
- query: {
- amount: amount,
- sats: sats,
- unit: unit,
- memo: note,
- display,
- },
- },
- undefined,
- { shallow: true },
+ window.history.pushState(
+ {},
+ "",
+ `${username}?${new URLSearchParams({
+ amount: amount,
+ sats: sats,
+ unit: unit,
+ memo: note,
+ display,
+ }).toString()}`,
)
} else {
- router.push(
- {
- pathname: `${username}`,
- query: { memo: note, display },
- },
- undefined,
- { shallow: true },
+ window.history.pushState(
+ {},
+ "",
+ `${username}?${new URLSearchParams({ memo: note, display }).toString()}`,
)
}
handleClose()
diff --git a/apps/pay/components/ParsePOSPayment/Digit-Button.tsx b/apps/pay/components/ParsePOSPayment/Digit-Button.tsx
index 32d91548bc1..46c5ed42483 100644
--- a/apps/pay/components/ParsePOSPayment/Digit-Button.tsx
+++ b/apps/pay/components/ParsePOSPayment/Digit-Button.tsx
@@ -1,6 +1,6 @@
import React from "react"
-import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer"
+import { ACTIONS, ACTION_TYPE } from "../../app/_reducer"
interface Props {
digit: string
diff --git a/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx b/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx
index 8ba2f355dd2..d2b1dbb7360 100644
--- a/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx
+++ b/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx
@@ -1,7 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
// TODO: remove eslint-disable, the logic likely needs to be reworked
import copy from "copy-to-clipboard"
-import { useRouter } from "next/router"
+import { useParams, useSearchParams } from "next/navigation"
import React, { useCallback } from "react"
import Image from "react-bootstrap/Image"
import OverlayTrigger from "react-bootstrap/OverlayTrigger"
@@ -13,7 +13,7 @@ import { USD_INVOICE_EXPIRE_INTERVAL, getClientSidePayDomain } from "../../confi
import useCreateInvoice from "../../hooks/use-Create-Invoice"
import { LnInvoiceObject } from "../../lib/graphql/index.types.d"
import useSatPrice from "../../lib/use-sat-price"
-import { ACTION_TYPE } from "../../pages/_reducer"
+import { ACTION_TYPE } from "../../app/_reducer"
import PaymentOutcome from "../PaymentOutcome"
import { Share } from "../Share"
@@ -32,9 +32,11 @@ const USD_MAX_INVOICE_TIME = 5 // minutes
const PROGRESS_BAR_MAX_WIDTH = 100 // percent
function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }: Props) {
- const deviceDetails = window.navigator.userAgent
- const router = useRouter()
- const { username, amount, unit, sats, memo } = router.query
+ const deviceDetails = window.navigator?.userAgent
+ const searchParams = useSearchParams()
+ const { username } = useParams()
+ const query = searchParams ? Object.fromEntries(searchParams.entries()) : {}
+ const { amount, unit, sats, memo } = query
const { usdToSats, satsToUsd } = useSatPrice()
@@ -109,11 +111,11 @@ function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }:
)
const paymentAmount = React.useMemo(() => {
- if (!router.query.sats || typeof router.query.sats !== "string") {
+ if (!query.sats || typeof query.sats !== "string") {
alert("No sats amount provided")
return
}
- let amt = safeAmount(router.query.sats)
+ let amt = safeAmount(query.sats)
if (recipientWalletCurrency === "USD") {
const usdAmount = satsToUsd(Number(amt))
if (isNaN(usdAmount)) return
@@ -137,11 +139,11 @@ function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }:
let amt = paymentAmount
if (recipientWalletCurrency === "USD") {
- if (!router.query.sats || typeof router.query.sats !== "string") {
+ if (!query.sats || typeof query.sats !== "string") {
alert("No sats amount provided")
return
} else {
- const usdAmount = satsToUsd(Number(router.query.sats))
+ const usdAmount = satsToUsd(Number(query.sats))
if (isNaN(usdAmount)) return
const cents = parseFloat(usdAmount.toFixed(2)) * 100
amt = cents.toFixed()
@@ -175,7 +177,7 @@ function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }:
const isMobileDevice = useCallback(() => {
const mobileDevice = /android|iPhone|iPod|kindle|HMSCore|windows phone|ipad/i
- if (window.navigator.maxTouchPoints > 1 || mobileDevice.test(deviceDetails)) {
+ if (window.navigator?.maxTouchPoints > 1 || mobileDevice.test(deviceDetails)) {
return true
}
return false
diff --git a/apps/pay/components/ParsePOSPayment/index.tsx b/apps/pay/components/ParsePOSPayment/index.tsx
index f0c6366cde2..90106ec1a59 100644
--- a/apps/pay/components/ParsePOSPayment/index.tsx
+++ b/apps/pay/components/ParsePOSPayment/index.tsx
@@ -1,6 +1,5 @@
-import { ParsedUrlQuery } from "querystring"
-
-import { useRouter } from "next/router"
+"use client"
+import { useRouter, useSearchParams } from "next/navigation"
import React, { useEffect } from "react"
import Container from "react-bootstrap/Container"
import Image from "react-bootstrap/Image"
@@ -8,13 +7,8 @@ import Image from "react-bootstrap/Image"
import CurrencyInput, { formatValue } from "react-currency-input-field"
import useRealtimePrice from "../../lib/use-realtime-price"
-import { ACTION_TYPE, ACTIONS } from "../../pages/_reducer"
-import {
- formatOperand,
- parseDisplayCurrency,
- safeAmount,
- getLocaleConfig,
-} from "../../utils/utils"
+import { ACTION_TYPE, ACTIONS } from "../../app/_reducer"
+import { formatOperand, safeAmount, getLocaleConfig } from "../../utils/utils"
import Memo from "../Memo"
import { useDisplayCurrency } from "../../lib/use-display-currency"
@@ -26,6 +20,9 @@ import styles from "./parse-payment.module.css"
import ReceiveInvoice from "./Receive-Invoice"
function isRunningStandalone() {
+ if (typeof window === "undefined") {
+ return false
+ }
return window.matchMedia("(display-mode: standalone)").matches
}
@@ -34,6 +31,7 @@ interface Props {
walletId?: string
dispatch: React.Dispatch
state: React.ComponentState
+ username: string
}
interface UpdateAmount {
@@ -56,10 +54,19 @@ const defaultCurrencyMetadata: Currency = {
__typename: "Currency",
}
-function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Props) {
+function ParsePayment({
+ defaultWalletCurrency,
+ walletId,
+ dispatch,
+ state,
+ username,
+}: Props) {
const router = useRouter()
- const { username, amount, sats, unit, memo, currency } = router.query
- const { display } = parseDisplayCurrency(router.query)
+ const searchParams = useSearchParams()
+ const query = searchParams ? Object.fromEntries(searchParams.entries()) : {}
+ const { amount, sats, unit, memo, currency } = query
+
+ const display = searchParams?.get("display") ?? localStorage.getItem("display") ?? "USD"
const { currencyToSats, satsToCurrency, hasLoaded } = useRealtimePrice(display)
const { currencyList } = useDisplayCurrency()
const [valueInFiat, setValueInFiat] = React.useState(0)
@@ -96,10 +103,11 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
const initialAmount = safeAmount(amount).toString()
const initialSats = safeAmount(sats).toString()
const initialDisplay = display ?? localStorage.getItem("display") ?? "USD"
- const initialUsername = router.query.username
- const initialQuery = { ...router.query }
+ const initialUsername = username
+ const initialQuery = searchParams ? Object.fromEntries(searchParams.entries()) : {}
+
delete initialQuery?.currency
- const newQuery: ParsedUrlQuery = {
+ const newQuery = {
amount: initialAmount,
sats: initialSats,
unit: initialUnit,
@@ -108,20 +116,14 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
username: initialUsername,
}
if (initialQuery !== newQuery) {
- router.push(
- {
- pathname: `${username}`,
- query: {
- amount: initialAmount,
- sats: initialSats,
- unit: initialUnit,
- memo: memo ?? "",
- display: initialDisplay,
- },
- },
- undefined,
- { shallow: true },
- )
+ const newUrl = `${username}?${new URLSearchParams({
+ amount: initialAmount,
+ sats: initialSats,
+ unit: initialUnit,
+ memo: memo ?? "",
+ display: initialDisplay,
+ }).toString()}`
+ window.history.pushState({}, "", newUrl)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
@@ -136,7 +138,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
} else if (sats) {
return {
shouldUpdate: true,
- value: sats.toString(),
+ value: sats?.toString(),
}
}
} else {
@@ -152,20 +154,15 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
const toggleCurrency = () => {
const newUnit = unit === AmountUnit.Sat ? AmountUnit.Cent : AmountUnit.Sat
prevUnit.current = (unit as AmountUnit) || AmountUnit.Cent
- router.push(
- {
- pathname: `${username}`,
- query: {
- currency: defaultWalletCurrency,
- unit: newUnit,
- memo,
- display,
- amount,
- sats,
- },
- },
- undefined,
- { shallow: true },
+ router.replace(
+ `${username}?${new URLSearchParams({
+ currency: defaultWalletCurrency || "USD",
+ unit: newUnit.toString(),
+ memo: memo?.toString(),
+ display: display.toString(),
+ amount: amount.toString(),
+ sats: sats?.toString(),
+ }).toString()}`,
)
}
@@ -192,7 +189,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
if (isNaN(Number(amt))) return
const formattedValue = formatValue({
value: amt,
- intlConfig: { locale: navigator.language, currency: display },
+ intlConfig: { locale: navigator?.language, currency: display },
})
localStorage.setItem("formattedFiatValue", formattedValue)
setValueInFiat(amt)
@@ -209,21 +206,20 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
// 3) update the query params
const newQuery = {
- amount: amt,
- sats: satsAmt,
- currency: defaultWalletCurrency,
- unit,
- memo,
- display,
+ amount: amt.toString(),
+ sats: satsAmt.toString(),
+ currency: defaultWalletCurrency?.toString() || "USD",
+ unit: unit.toString(),
+ memo: memo?.toString(),
+ display: display.toString(),
}
- if (router.query !== newQuery && !skipRouterPush) {
- router.push(
- {
- pathname: `${username}`,
- query: newQuery,
- },
- undefined,
- { shallow: true },
+
+ const initalQuery = searchParams ? Object.fromEntries(searchParams.entries()) : {}
+ if (initalQuery !== newQuery && !skipRouterPush) {
+ window.history.pushState(
+ {},
+ "",
+ `${username}?${new URLSearchParams(newQuery).toString()}`,
)
}
}
@@ -323,7 +319,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
fontWeight: 600,
}}
value={!amount ? 0 : valueInFiat}
- intlConfig={{ locale: navigator.language, currency: display }}
+ intlConfig={{ locale: navigator?.language, currency: display }}
readOnly={true}
/>
@@ -388,7 +384,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop
dispatch={dispatch}
disabled={unit === AmountUnit.Sat}
displayValue={
- getLocaleConfig({ locale: navigator.language, currency: display })
+ getLocaleConfig({ locale: navigator?.language, currency: display })
.decimalSeparator
}
/>
diff --git a/apps/pay/components/PaymentOutcome/index.tsx b/apps/pay/components/PaymentOutcome/index.tsx
index 5094d765172..c77da47ed45 100644
--- a/apps/pay/components/PaymentOutcome/index.tsx
+++ b/apps/pay/components/PaymentOutcome/index.tsx
@@ -1,4 +1,5 @@
-import { useRouter } from "next/router"
+"use client"
+import { useParams, useSearchParams } from "next/navigation"
import React, { useRef } from "react"
import Image from "react-bootstrap/Image"
@@ -6,7 +7,7 @@ import { useReactToPrint } from "react-to-print"
import { gql } from "@apollo/client"
-import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer"
+import { ACTIONS, ACTION_TYPE } from "../../app/_reducer"
import { useLnInvoicePaymentStatusSubscription } from "../../lib/graphql/generated"
@@ -33,8 +34,10 @@ gql`
`
function PaymentOutcome({ paymentRequest, paymentAmount, dispatch }: Props) {
- const router = useRouter()
- const { amount, sats, username, memo } = router.query
+ const searchParams = useSearchParams()
+ const query = searchParams ? Object.fromEntries(searchParams.entries()) : {}
+ const { username } = useParams()
+ const { amount, sats, memo } = query
const componentRef = useRef