Skip to content

Commit 1d9bb63

Browse files
committed
fix TurnstileBridge
1 parent 42bbac8 commit 1d9bb63

File tree

4 files changed

+148
-41
lines changed

4 files changed

+148
-41
lines changed

src/AppHelmet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default function AppHelmet() {
3030
navigate('/login');
3131
}
3232
}
33-
}, []);
33+
}, [token, location.pathname, navigate]);
3434

3535
useEffect(() => {
3636
if (

src/components/ErrorBoundary.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react';
2+
3+
interface ErrorBoundaryState {
4+
hasError: boolean;
5+
error?: Error;
6+
}
7+
8+
interface ErrorBoundaryProps {
9+
children: React.ReactNode;
10+
}
11+
12+
export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
13+
constructor(props: ErrorBoundaryProps) {
14+
super(props);
15+
this.state = { hasError: false };
16+
}
17+
18+
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
19+
return { hasError: true, error };
20+
}
21+
22+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
23+
console.error('ErrorBoundary caught an error:', error, errorInfo);
24+
}
25+
26+
render() {
27+
if (this.state.hasError) {
28+
return (
29+
<div
30+
style={{
31+
minHeight: '100vh',
32+
display: 'flex',
33+
alignItems: 'center',
34+
justifyContent: 'center',
35+
flexDirection: 'column',
36+
padding: '20px',
37+
backgroundColor: '#f5f5f5',
38+
}}
39+
>
40+
<h2 style={{ color: '#e74c3c', marginBottom: '20px' }}>
41+
Turnstile Error
42+
</h2>
43+
<p style={{ color: '#666', textAlign: 'center', maxWidth: '400px', marginBottom: '20px' }}>
44+
Something went wrong with the Turnstile verification. Please try again.
45+
</p>
46+
<button
47+
onClick={() => window.location.reload()}
48+
style={{
49+
padding: '10px 20px',
50+
backgroundColor: '#3498db',
51+
color: 'white',
52+
border: 'none',
53+
borderRadius: '5px',
54+
cursor: 'pointer',
55+
}}
56+
>
57+
Reload page
58+
</button>
59+
</div>
60+
);
61+
}
62+
63+
return this.props.children;
64+
}
65+
}

src/pages/TurnstileBridge.tsx

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useEffect, useRef } from 'react';
2-
import { useSearchParams } from 'react-router-dom';
32

43
const DEFAULT_SITE_KEY = import.meta.env.VITE_TURNSTILE_SITE_KEY as string;
54

@@ -12,67 +11,105 @@ declare global {
1211

1312
export default function TurnstileBridge() {
1413
const containerRef = useRef<HTMLDivElement | null>(null);
15-
const [searchParams] = useSearchParams();
16-
17-
const siteKey = searchParams.get('sitekey') || DEFAULT_SITE_KEY;
14+
const scriptLoadedRef = useRef(false);
1815

1916
useEffect(() => {
17+
const urlParams = new URLSearchParams(window.location.search);
18+
const siteKey = urlParams.get('sitekey') || DEFAULT_SITE_KEY;
19+
20+
if (!siteKey) {
21+
console.error('No sitekey provided');
22+
return;
23+
}
24+
25+
if (scriptLoadedRef.current) {
26+
return;
27+
}
28+
29+
const existingScript = document.querySelector('script[src*="turnstile"]');
30+
if (existingScript) {
31+
scriptLoadedRef.current = true;
32+
initializeTurnstile(siteKey);
33+
return;
34+
}
35+
2036
const script = document.createElement('script');
2137
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
2238
script.async = true;
2339
script.defer = true;
40+
2441
script.onload = () => {
25-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
26-
const ts = (window as any).turnstile as
27-
| {
28-
render: (
29-
el: HTMLElement,
30-
opts: {
31-
sitekey: string;
32-
callback?: (token: string) => void;
33-
'error-callback'?: (error: string) => void;
34-
action?: string;
35-
theme?: 'light' | 'dark' | 'auto';
36-
}
37-
) => void;
38-
}
39-
| undefined;
42+
scriptLoadedRef.current = true;
43+
initializeTurnstile(siteKey);
44+
};
4045

41-
if (containerRef.current && ts) {
42-
ts.render(containerRef.current, {
43-
sitekey: siteKey,
44-
callback: (token: string) => {
45-
window.location.href =
46-
'ethoraappreactnative://turnstile?token=' +
47-
encodeURIComponent(token);
48-
},
49-
'error-callback': (error: string) => {
50-
window.location.href =
51-
'ethoraappreactnative://turnstile?error=' +
52-
encodeURIComponent(String(error));
53-
},
54-
action: 'signup',
55-
theme: 'light',
56-
});
57-
}
46+
script.onerror = () => {
47+
console.error('Failed to load Turnstile script');
5848
};
5949

6050
document.head.appendChild(script);
51+
6152
return () => {
62-
document.head.removeChild(script);
6353
};
6454
}, []);
6555

56+
const initializeTurnstile = (siteKey: string) => {
57+
if (!containerRef.current) {
58+
console.error('Container not found');
59+
return;
60+
}
61+
62+
if (typeof (window as any).turnstile === 'undefined') {
63+
console.error('Turnstile not available');
64+
return;
65+
}
66+
67+
try {
68+
(window as any).turnstile.render(containerRef.current, {
69+
sitekey: siteKey,
70+
callback: (token: string) => {
71+
try {
72+
window.location.href =
73+
'ethoraappreactnative://turnstile?token=' +
74+
encodeURIComponent(token);
75+
} catch (err) {
76+
console.error('Error redirecting with token:', err);
77+
}
78+
},
79+
'error-callback': (error: string) => {
80+
try {
81+
window.location.href =
82+
'ethoraappreactnative://turnstile?error=' +
83+
encodeURIComponent(String(error));
84+
} catch (err) {
85+
console.error('Error redirecting with error:', err);
86+
}
87+
},
88+
action: 'signup',
89+
theme: 'light',
90+
});
91+
} catch (err) {
92+
console.error('Error initializing Turnstile:', err);
93+
}
94+
};
95+
6696
return (
6797
<div
6898
style={{
6999
minHeight: '100vh',
70100
display: 'flex',
71101
alignItems: 'center',
72102
justifyContent: 'center',
103+
backgroundColor: '#f5f5f5',
73104
}}
74105
>
75-
<div ref={containerRef} />
106+
<div
107+
ref={containerRef}
108+
style={{
109+
minHeight: '65px',
110+
minWidth: '300px',
111+
}}
112+
/>
76113
</div>
77114
);
78-
}
115+
}

src/router.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import LoginComponent from './pages/AuthPage/Login';
88
import Register from './pages/AuthPage/Register';
99
import Chat from './pages/Chat';
1010
import { Error404Page } from './pages/ErrorPage/Error404Page';
11+
import { ErrorBoundary } from './components/ErrorBoundary';
1112
const Admin = lazy(() => import('./pages/Admin'));
1213
const AdminApp = lazy(() => import('./pages/AdminApp'));
1314
const AdminApps = lazy(() => import('./pages/AdminApps'));
@@ -49,7 +50,11 @@ export const router = createBrowserRouter(
4950
},
5051
{
5152
path: '/turnstile',
52-
Component: TurnstileBridge,
53+
element: (
54+
<ErrorBoundary>
55+
<TurnstileBridge />
56+
</ErrorBoundary>
57+
),
5358
},
5459
{
5560
path: '/app',

0 commit comments

Comments
 (0)