PageSourceSearch

https://waprank.net/app/components/button/TurnStileConfirmButton.mjs

js waprank.net collected 2026-10-09 04:26:16 UTC 4,731 bytes, 149 lines download raw bytes

1import {AsyncActionButton} from "@/components/button/AsyncActionButton.mjs"
2import {html} from 'htm/preact';
3import {css} from '@/cssTool/css.mjs';
4import {useState,useEffect,useCallback,useRef} from 'preact/hooks';
5import {Config} from "@/config/config.mjs";
6
7
8
9
10function randomString(length){
11    const alphabet="AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
12    return Array.from({length}, () => alphabet[Math.floor(Math.random() * alphabet.length)]).join('');
13}
14
15
16export function TurnStileConfirmButton(
17    {
18        onClick,
19        disabled = false,
20        children,
21        preTurnStileOnClick,
22        ...props
23    }
24){
25
26    const containerRef=useRef(null);
27    const [containerClass,setContainerClass]=useState("turnstile-container-"+randomString(25));
28    const widgetId=useRef(null);
29    const [isRunning,setIsRunning]=useState(false);
30    const pendingPromiseRef=useRef(null);
31
32
33
34    useEffect(()=>{
35        let load=async ()=> {
36            
37            for(let i=0;i<200;i++){
38                if(window.turnstile){
39                    break;
40                }
41                await new Promise(resolve=>setTimeout(resolve,100));
42            }
43            const config=await Config.getConfig();
44            
45            const wid = window.turnstile.render("#" + containerClass, {
46                    sitekey: config.turnstileSiteKey,
47                    execution: "execute",
48                    appearance: "execute",
49                    callback: async (token) => {
50                        console.log("Received token")
51                        const pending = pendingPromiseRef.current;
52                        pendingPromiseRef.current = null;
53                        window.turnstile.reset(widgetId.current);
54                        setIsRunning(false);
55                        pending?.resolve(token);
56
57                    },
58                    "error-callback": (err) => {
59                        console.log("Turnstile error", err)
60                        const pending = pendingPromiseRef.current;
61                        pendingPromiseRef.current = null;
62                        window.turnstile.reset(widgetId.current);
63                        setIsRunning(false);
64                        pending?.reject(new Error("Turnstile error " + err));
65                    },
66                    "timeout-callback": () => {
67                        console.log("Turnstile timeout")
68                        const pending = pendingPromiseRef.current;
69                        pendingPromiseRef.current = null;
70                        window.turnstile.reset(widgetId.current);
71                        setIsRunning(false);
72                        pending?.reject(new Error("Turnstile timeout"));
73                    }
74
75                }
76            )
77            widgetId.current=wid;
78        }
79        load().then();
80
81
82        return ()=>{
83            if(widgetId.current!==null){
84                window.turnstile.remove(widgetId.current);
85                widgetId.current=null;
86            }
87        }
88
89    },[])
90
91    const getTokenFromTurnstile=useCallback(
92        ()=>{
93            return new Promise((resolve,reject)=>{
94                if(widgetId.current===null){
95                    reject(new Error("Turnstile widget not initialized"));
96                    return;
97                }
98                if(isRunning){
99                    reject(new Error("Turnstile already running"));
100                    return;
101                }
102                setIsRunning(true);
103                pendingPromiseRef.current={resolve,reject};
104                try {
105                    window.turnstile.execute(widgetId.current);
106                }catch(err){
107                    setIsRunning(false);
108                    pendingPromiseRef.current=null;
109                    reject(err);
110                }
111            }
112            )
113        }
114
115        ,[
116            isRunning,
117            setIsRunning,
118            widgetId,
119            pendingPromiseRef,
120            onClick
121        ]
122    )
123
124    const onClickWithTurnstile=useCallback(
125        async()=>{
126            const preTurnStileResult=await preTurnStileOnClick?.();
127            const token=await getTokenFromTurnstile();
128            await onClick?.(token,preTurnStileResult);
129        },[
130            onClick,
131            getTokenFromTurnstile,
132            preTurnStileOnClick
133        ]
134    )
135
136
137    return html`
138        <div className="d-flex flex-column gap-2">
139            <${AsyncActionButton}
140                    onClick=${onClickWithTurnstile}
141                    disabled=${disabled}
142                    ...${props}
143            >
144                ${children}
145            <//>
146            <div ref=${containerRef} id=${containerClass}></div>
147        </div>
148    `
149}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.