Skip to content

Commit 557a29a

Browse files
[Dashboard] Fix: Copying payment link on iOS (#7008)
Signed-off-by: greg <gregfromstl@gmail.com> Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
1 parent ff565cb commit 557a29a

File tree

4 files changed

+86
-59
lines changed

4 files changed

+86
-59
lines changed

apps/dashboard/src/app/pay/components/client/PaymentLinkForm.client.tsx

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
import { SingleNetworkSelector } from "@/components/blocks/NetworkSelectors";
44
import { TokenSelector } from "@/components/blocks/TokenSelector";
5+
import { CopyTextButton } from "@/components/ui/CopyTextButton";
56
import { Button } from "@/components/ui/button";
67
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
78
import { Input } from "@/components/ui/input";
89
import { Label } from "@/components/ui/label";
10+
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
911
import { cn } from "@/lib/utils";
1012
import { ChevronDownIcon, CreditCardIcon } from "lucide-react";
1113
import { useCallback, useMemo, useState } from "react";
@@ -19,10 +21,22 @@ import {
1921
} from "thirdweb";
2022
import { getCurrencyMetadata } from "thirdweb/extensions/erc20";
2123
import { resolveScheme, upload } from "thirdweb/storage";
24+
import { setThirdwebDomains } from "thirdweb/utils";
2225
import { FileInput } from "../../../../components/shared/FileInput";
26+
import {
27+
THIRDWEB_ANALYTICS_DOMAIN,
28+
THIRDWEB_BUNDLER_DOMAIN,
29+
THIRDWEB_INAPP_WALLET_DOMAIN,
30+
THIRDWEB_INSIGHT_API_DOMAIN,
31+
THIRDWEB_PAY_DOMAIN,
32+
THIRDWEB_RPC_DOMAIN,
33+
THIRDWEB_SOCIAL_API_DOMAIN,
34+
THIRDWEB_STORAGE_DOMAIN,
35+
} from "../../../../constants/urls";
2336
import { resolveEns } from "../../../../lib/ens";
37+
import { getVercelEnv } from "../../../../lib/vercel-utils";
2438

25-
export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
39+
export function PaymentLinkForm() {
2640
const [chainId, setChainId] = useState<number>();
2741
const [recipientAddress, setRecipientAddress] = useState("");
2842
const [tokenAddressWithChain, setTokenAddressWithChain] = useState("");
@@ -32,8 +46,24 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
3246
const [imageUri, setImageUri] = useState<string>("");
3347
const [uploadingImage, setUploadingImage] = useState(false);
3448
const [isLoading, setIsLoading] = useState(false);
35-
const [error, setError] = useState<string>();
3649
const [showAdvanced, setShowAdvanced] = useState(false);
50+
const [paymentUrl, setPaymentUrl] = useState<string>("");
51+
52+
const client = useMemo(() => {
53+
if (getVercelEnv() !== "production") {
54+
setThirdwebDomains({
55+
rpc: THIRDWEB_RPC_DOMAIN,
56+
pay: THIRDWEB_PAY_DOMAIN,
57+
storage: THIRDWEB_STORAGE_DOMAIN,
58+
insight: THIRDWEB_INSIGHT_API_DOMAIN,
59+
analytics: THIRDWEB_ANALYTICS_DOMAIN,
60+
inAppWallet: THIRDWEB_INAPP_WALLET_DOMAIN,
61+
bundler: THIRDWEB_BUNDLER_DOMAIN,
62+
social: THIRDWEB_SOCIAL_API_DOMAIN,
63+
});
64+
}
65+
return getClientThirdwebClient();
66+
}, []);
3767

3868
const isFormComplete = useMemo(() => {
3969
return chainId && recipientAddress && tokenAddressWithChain && amount;
@@ -72,7 +102,6 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
72102
const handleSubmit = useCallback(
73103
async (e: React.FormEvent) => {
74104
e.preventDefault();
75-
setError(undefined);
76105
setIsLoading(true);
77106

78107
try {
@@ -112,15 +141,11 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
112141
params.set("image", imageUri);
113142
}
114143

115-
const paymentUrl = `${window.location.origin}/pay?${params.toString()}`;
116-
117-
// Copy to clipboard
118-
await navigator.clipboard.writeText(paymentUrl);
119-
120-
// Show success toast
121-
toast.success("Payment link copied to clipboard.");
144+
const url = `${window.location.origin}/pay?${params.toString()}`;
145+
setPaymentUrl(url);
146+
toast.success("Payment link created!");
122147
} catch (err) {
123-
setError(err instanceof Error ? err.message : "An error occurred");
148+
toast.error(err instanceof Error ? err.message : "An error occurred");
124149
} finally {
125150
setIsLoading(false);
126151
}
@@ -290,7 +315,7 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
290315
id="title"
291316
value={title}
292317
onChange={(e) => setTitle(e.target.value)}
293-
placeholder="A title for your payment"
318+
placeholder="Payment for..."
294319
className="w-full"
295320
/>
296321
</div>
@@ -318,25 +343,35 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
318343
</div>
319344
</div>
320345

321-
{error && <div className="text-red-500 text-sm">{error}</div>}
322-
323-
<div className="flex gap-2">
324-
<Button
325-
type="button"
326-
variant="outline"
327-
className="flex-1"
328-
disabled={isLoading || !isFormComplete}
329-
onClick={handlePreview}
330-
>
331-
Preview
332-
</Button>
333-
<Button
334-
type="submit"
335-
className="flex-1"
336-
disabled={isLoading || !isFormComplete}
337-
>
338-
{isLoading ? "Creating..." : "Create"}
339-
</Button>
346+
<div className="flex flex-col space-y-4">
347+
{paymentUrl && (
348+
<CopyTextButton
349+
textToCopy={paymentUrl}
350+
textToShow={paymentUrl}
351+
tooltip="Copy Payment Link"
352+
className="w-full justify-between truncate bg-background px-3 py-2"
353+
copyIconPosition="right"
354+
/>
355+
)}
356+
357+
<div className="flex gap-2">
358+
<Button
359+
type="button"
360+
variant="outline"
361+
className="flex-1"
362+
disabled={isLoading || !isFormComplete}
363+
onClick={handlePreview}
364+
>
365+
Preview
366+
</Button>
367+
<Button
368+
type="submit"
369+
className="flex-1"
370+
disabled={isLoading || !isFormComplete}
371+
>
372+
{isLoading ? "Creating..." : "Create"}
373+
</Button>
374+
</div>
340375
</div>
341376
</form>
342377
</CardContent>

apps/dashboard/src/app/pay/layout.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,27 @@ const fontSans = Inter({
1010
display: "swap",
1111
});
1212

13-
export default async function CheckoutLayout({
13+
export default async function PayLayout({
1414
children,
1515
}: {
1616
children: React.ReactNode;
1717
}) {
1818
return (
1919
<html lang="en" suppressHydrationWarning>
20-
<Providers>
21-
<ThemeProvider
22-
attribute="class"
23-
disableTransitionOnChange
24-
enableSystem={false}
25-
defaultTheme="dark"
26-
>
27-
<body
28-
className={cn(
29-
"h-screen w-screen bg-background font-sans antialiased",
30-
fontSans.variable,
31-
)}
20+
<body
21+
className={cn(
22+
"h-screen w-screen bg-background font-sans antialiased",
23+
fontSans.variable,
24+
)}
25+
>
26+
<Providers>
27+
<ThemeProvider
28+
attribute="class"
29+
disableTransitionOnChange
30+
enableSystem={false}
31+
defaultTheme="dark"
3232
>
33-
<div className="relative mx-auto flex h-full w-full flex-col items-center justify-center overflow-hidden border py-10">
33+
<div className="relative mx-auto flex h-full w-full flex-col items-center justify-center overflow-x-hidden overflow-y-scroll py-10">
3434
<main className="container z-10 flex justify-center">
3535
{children}
3636
</main>
@@ -42,9 +42,9 @@ export default async function CheckoutLayout({
4242
className="-bottom-12 -right-12 pointer-events-none absolute lg:right-0 lg:bottom-0"
4343
/>
4444
</div>
45-
</body>
46-
</ThemeProvider>
47-
</Providers>
45+
</ThemeProvider>
46+
</Providers>
47+
</body>
4848
</html>
4949
);
5050
}

apps/dashboard/src/app/pay/page.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { getAuthToken } from "app/(app)/api/lib/getAuthToken";
21
import type { Metadata } from "next";
32
import { createThirdwebClient, defineChain, getContract } from "thirdweb";
43
import { getCurrencyMetadata } from "thirdweb/extensions/erc20";
@@ -32,14 +31,7 @@ export default async function RoutesPage({
3231
!params.tokenAddress &&
3332
!params.amount
3433
) {
35-
const authToken = await getAuthToken();
36-
37-
const client = getClientThirdwebClient({
38-
jwt: authToken,
39-
teamId: undefined,
40-
});
41-
42-
return <PaymentLinkForm client={client} />;
34+
return <PaymentLinkForm />;
4335
}
4436

4537
// Validate query parameters

packages/thirdweb/src/extensions/erc20/read/getCurrencyMetadata.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export async function getCurrencyMetadata(
5151
symbol: symbol_,
5252
decimals: decimals_,
5353
};
54-
} catch {
55-
throw new Error("Invalid currency token");
54+
} catch (e) {
55+
throw new Error(`Invalid currency token: ${e}`);
5656
}
5757
}

0 commit comments

Comments
 (0)