Skip to content

Commit 1b29610

Browse files
Fixing responsive layout (#52)
Co-authored-by: raphjaph <[email protected]>
1 parent 12d413f commit 1b29610

21 files changed

+1051
-687
lines changed

www/src/App.tsx

+63-290
Original file line numberDiff line numberDiff line change
@@ -1,316 +1,89 @@
1-
import { useEffect, useState } from "react";
2-
import { useLaserEyes, MAGIC_EDEN, ProviderType } from "@omnisat/lasereyes";
3-
import init, { verify } from "@/bip322.js";
1+
import { useEffect } from "react";
42
import VerifyForm from "@/components/VerifyForm";
5-
import ConnectWalletForm from "@/components/ConnectWallet";
63
import SignMessageForm from "@/components/SignMessage";
7-
import "@/index.css";
8-
import { Button } from "@/components/ui/button";
9-
import AnimatedContainer from "./components/AnimatedContainer";
10-
11-
export interface SignMessageState {
12-
message: string;
13-
signedData: {
14-
address: string;
15-
message: string;
16-
signature: string;
17-
} | null;
18-
}
19-
20-
export interface VerifyFormState {
21-
address: string;
22-
message: string;
23-
signature: string;
24-
verificationResult: string | null;
25-
}
4+
import { BaseButton } from "@/components/ui/base-button";
5+
import { useWasmInit } from "@/hooks/useWasmInit";
6+
import { useWalletConnection } from "@/hooks/useWalletConnection";
7+
import { useSignMessage } from "@/hooks/useSignMessage";
8+
import { useVerifyMessage } from "@/hooks/useVerifyMessage";
269

2710
function App() {
28-
const [isWasmInitialized, setWasmInitialized] = useState(false);
29-
30-
const [isSignFormVisible, setIsSignFormVisible] = useState(false);
31-
const [isVerifyFormVisible, setIsVerifyFormVisible] = useState(false);
32-
33-
const [signMessageState, setSignMessageState] = useState<SignMessageState>({
34-
message: "",
35-
signedData: null,
36-
});
37-
38-
const [verifyFormState, setVerifyFormState] = useState<VerifyFormState>({
39-
address: "",
40-
message: "",
41-
signature: "",
42-
verificationResult: null,
43-
});
44-
45-
const {
46-
connect,
47-
disconnect,
48-
address,
49-
provider,
50-
hasUnisat,
51-
hasXverse,
52-
hasOyl,
53-
hasMagicEden,
54-
hasOkx,
55-
hasLeather,
56-
hasPhantom,
57-
connected,
58-
signMessage,
59-
} = useLaserEyes();
60-
61-
const hasWallet = {
62-
unisat: hasUnisat,
63-
xverse: hasXverse,
64-
oyl: hasOyl,
65-
[MAGIC_EDEN]: hasMagicEden,
66-
okx: hasOkx,
67-
leather: hasLeather,
68-
phantom: hasPhantom,
69-
};
70-
71-
const handleConnect = async (walletName: ProviderType) => {
72-
if (provider === walletName) {
73-
disconnect();
74-
} else {
75-
await connect(walletName as never);
76-
}
77-
};
78-
79-
const handleDisconnect = async () => {
80-
try {
81-
disconnect();
82-
resetSignMessageForm();
83-
} catch (error) {
84-
console.error("Failed to disconnect wallet:", error);
85-
}
86-
};
87-
88-
const handleMessageSign = async () => {
89-
if (!connected || !signMessageState.message) return;
90-
91-
try {
92-
const signature = await signMessage(signMessageState.message, address);
93-
const newSignedData = {
94-
address: address,
95-
message: signMessageState.message,
96-
signature,
97-
};
98-
99-
setSignMessageState((prev) => ({
100-
...prev,
101-
signedData: newSignedData,
102-
}));
103-
} catch (error) {
104-
console.error("Failed to sign message:", error);
105-
}
106-
};
107-
108-
const handleVerification = async (e: React.FormEvent) => {
109-
e.preventDefault();
110-
if (!isWasmInitialized) {
111-
console.error("WASM not initialized yet");
112-
return;
113-
}
114-
115-
try {
116-
const result = verify(
117-
verifyFormState.address,
118-
verifyFormState.message,
119-
verifyFormState.signature
120-
);
121-
setVerifyFormState((prev) => ({
122-
...prev,
123-
verificationResult: result.toString(),
124-
}));
125-
} catch (error) {
126-
console.error("Verification failed:", error);
127-
setVerifyFormState((prev) => ({
128-
...prev,
129-
verificationResult: "Verification failed",
130-
}));
131-
}
132-
};
133-
134-
const handleVerifyFormChange = (e: React.ChangeEvent<HTMLInputElement>) => {
135-
setVerifyFormState((prev) => ({
136-
...prev,
137-
[e.target.id]: e.target.value,
138-
}));
139-
};
140-
141-
const resetSignMessageForm = () => {
142-
setSignMessageState({
143-
message: "",
144-
signedData: null,
145-
});
146-
};
147-
148-
const resetVerifyForm = () => {
149-
setVerifyFormState({
150-
address: "",
151-
message: "",
152-
signature: "",
153-
verificationResult: null,
154-
});
155-
};
156-
157-
useEffect(() => {
158-
init()
159-
.then(() => setWasmInitialized(true))
160-
.catch((error) => console.error("Failed to initialize WASM:", error));
161-
}, []);
11+
const { wasmError } = useWasmInit();
12+
const [walletState, walletActions] = useWalletConnection();
13+
const [signState, signActions] = useSignMessage();
14+
const [verifyState, verifyActions] = useVerifyMessage();
16215

16316
useEffect(() => {
164-
const handleBeforeUnload = async () => {
165-
if (connected) {
166-
disconnect();
17+
const handleBeforeUnload = () => {
18+
if (walletState.isConnected) {
19+
walletActions.handleDisconnect();
16720
}
16821
};
16922

17023
window.addEventListener("beforeunload", handleBeforeUnload);
17124
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
172-
}, [connected, disconnect]);
25+
}, [walletState.isConnected, walletActions]);
17326

174-
if (!isWasmInitialized) {
175-
return <div>Loading WASM...</div>;
27+
if (wasmError) {
28+
return <div>Failed to initialize WASM: {wasmError.message}</div>;
17629
}
17730

17831
return (
179-
<div className="app-container">
180-
<header className="hero">
181-
<h1 onClick={() => window.location.reload()}>bip322</h1>
32+
<div className="min-h-screen w-full flex flex-col justify-center">
33+
<header className="hero h-[calc(var(--size)*0.50)] flex justify-center w-full">
34+
<div className="w-[95%] md:w-[80vw] mx-auto">
35+
<h1 onClick={() => window.location.reload()}>bip322</h1>
36+
</div>
18237
</header>
18338

184-
<section className="grid grid-cols-2 gap-12 items-center">
185-
<AnimatedContainer isExpanded={isSignFormVisible}>
186-
<div
187-
className={`absolute inset-0 w-full h-full transition-opacity duration-300 ${
188-
!isSignFormVisible
189-
? "opacity-0 pointer-events-none"
190-
: "opacity-100"
191-
}`}
192-
>
193-
{connected && address ? (
39+
<main className="w-full">
40+
<div className="w-[95%] md:w-[65vw] mx-auto">
41+
<div className="flex flex-col lg:flex-row gap-[calc(var(--size)*0.2)] lg:gap-[calc(var(--size)*0.1)] min-h-[50vh] items-center">
42+
<div className="flex-1 w-full flex justify-center items-end lg:items-center">
19443
<SignMessageForm
195-
address={address}
196-
message={signMessageState.message}
197-
signedData={signMessageState.signedData}
198-
onMessageChange={(message) =>
199-
setSignMessageState((prev) => ({ ...prev, message }))
44+
message={signState.message}
45+
signedData={signState.signedData}
46+
onMessageChange={signActions.setMessage}
47+
onSign={() =>
48+
signActions.handleSign(
49+
walletState.address!,
50+
walletActions.signMessage
51+
)
20052
}
201-
onSign={handleMessageSign}
202-
onReset={resetSignMessageForm}
203-
onBack={handleDisconnect}
53+
onReset={signActions.reset}
20454
/>
205-
) : (
206-
<ConnectWalletForm
207-
provider={provider}
208-
hasWallet={hasWallet}
209-
onConnect={handleConnect}
210-
onDisconnect={() => {
211-
handleDisconnect();
212-
setIsSignFormVisible(false);
213-
}}
55+
</div>
56+
57+
<div className="flex-1 w-full flex justify-center items-start lg:items-center">
58+
<VerifyForm
59+
formData={verifyState}
60+
verificationResult={verifyState.verificationResult}
61+
onSubmit={verifyActions.handleVerify}
62+
onInputChange={verifyActions.handleChange}
63+
onReset={verifyActions.reset}
21464
/>
215-
)}
65+
</div>
21666
</div>
217-
<Button
218-
className={`
219-
h-[calc(var(--font-large)+3rem)] w-full
220-
text-[length:var(--font-md)]
221-
md:text-[length:var(--font-md)]
222-
bg-[hsl(var(--light-1))] text-[hsl(var(--dark-1))]
223-
[box-shadow:0_0_7px_#fff]
224-
hover:bg-[hsl(var(--light-2))]
225-
hover:text-[hsl(var(--dark-1))]
226-
hover:[box-shadow:0_0_15px_3px_#fff]
227-
rounded-xl
228-
transition-all duration-300
229-
[text-shadow:0_0_4px_rgba(0,0,0,0.3),0_0_8px_rgba(0,0,0,0.2),0_0_12px_rgba(0,0,0,0.1)]
230-
hover:[text-shadow:0_0_6px_rgba(0,0,0,0.4),0_0_12px_rgba(0,0,0,0.3),0_0_18px_rgba(0,0,0,0.2)]
231-
${
232-
isSignFormVisible
233-
? "opacity-0 pointer-events-none"
234-
: "opacity-100"
235-
}
236-
`}
237-
variant="ghost"
238-
onClick={() => setIsSignFormVisible(true)}
239-
>
240-
sign
241-
</Button>
242-
</AnimatedContainer>
243-
244-
<AnimatedContainer isExpanded={isVerifyFormVisible}>
245-
<div
246-
className={`absolute inset-0 w-full h-full transition-opacity duration-300 ${
247-
!isVerifyFormVisible
248-
? "opacity-0 pointer-events-none"
249-
: "opacity-100"
250-
}`}
251-
>
252-
<VerifyForm
253-
formData={verifyFormState}
254-
verificationResult={verifyFormState.verificationResult}
255-
onSubmit={handleVerification}
256-
onInputChange={handleVerifyFormChange}
257-
onReset={resetVerifyForm}
258-
onBack={() => setIsVerifyFormVisible(false)}
259-
/>
67+
</div>
68+
</main>
69+
70+
<footer className="flex h-[calc(var(--size)*0.40)] items-center w-full">
71+
<nav className="w-[95%] md:w-[80%] mx-auto">
72+
<div className="flex justify-between gap-4 lg:gap-8">
73+
<BaseButton variant="nav" asChild>
74+
<a href="https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki">
75+
bip
76+
</a>
77+
</BaseButton>
78+
<BaseButton variant="nav" asChild>
79+
<a href="https://github.com/rust-bitcoin/bip322">github</a>
80+
</BaseButton>
81+
<BaseButton variant="nav" asChild>
82+
<a href="https://crates.io/crates/bip322">crate</a>
83+
</BaseButton>
26084
</div>
261-
<Button
262-
className={`
263-
h-[calc(var(--font-large)+3rem)] w-full
264-
text-[length:var(--font-md)]
265-
md:text-[length:var(--font-md)]
266-
bg-[hsl(var(--light-1))] text-[hsl(var(--dark-1))]
267-
[box-shadow:0_0_10px_#fff]
268-
hover:bg-[hsl(var(--light-2))]
269-
hover:text-[hsl(var(--dark-1))]
270-
hover:[box-shadow:0_0_20px_3px_#fff]
271-
rounded-xl
272-
transition-all duration-300
273-
[text-shadow:0_0_4px_rgba(0,0,0,0.3),0_0_8px_rgba(0,0,0,0.2),0_0_12px_rgba(0,0,0,0.1)]
274-
hover:[text-shadow:0_0_6px_rgba(0,0,0,0.4),0_0_12px_rgba(0,0,0,0.3),0_0_18px_rgba(0,0,0,0.2)]
275-
${
276-
isVerifyFormVisible
277-
? "opacity-0 pointer-events-none"
278-
: "opacity-100"
279-
}
280-
`}
281-
variant="ghost"
282-
onClick={() => setIsVerifyFormVisible(true)}
283-
>
284-
verify
285-
</Button>
286-
</AnimatedContainer>
287-
</section>
288-
289-
<nav className="flex justify-between items-center absolute inset-x-0 bottom-28 py-18 mb-20">
290-
<Button
291-
asChild
292-
variant="link"
293-
className="text-[length:var(--font-small)]"
294-
>
295-
<a href="https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki">
296-
bip
297-
</a>
298-
</Button>
299-
<Button
300-
asChild
301-
variant="link"
302-
className="text-[length:var(--font-small)]"
303-
>
304-
<a href="https://github.com/rust-bitcoin/bip322">github</a>
305-
</Button>
306-
<Button
307-
asChild
308-
variant="link"
309-
className="text-[length:var(--font-small)]"
310-
>
311-
<a href="https://crates.io/crates/bip322">crate</a>
312-
</Button>
313-
</nav>
85+
</nav>
86+
</footer>
31487
</div>
31588
);
31689
}

0 commit comments

Comments
 (0)