feat: add basic settings page
This commit is contained in:
@ -5,9 +5,10 @@ import { Icon } from "./icon";
|
||||
export interface CopyProps {
|
||||
text: string;
|
||||
maxSize?: number;
|
||||
hideText?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
export default function Copy({ text, maxSize = 32, className }: CopyProps) {
|
||||
export default function Copy({ text, maxSize = 32, className, hideText }: CopyProps) {
|
||||
const { copy, copied } = useCopy();
|
||||
const sliceLength = maxSize / 2;
|
||||
const trimmed =
|
||||
@ -20,7 +21,7 @@ export default function Copy({ text, maxSize = 32, className }: CopyProps) {
|
||||
className={`copy${className ? ` ${className}` : ""}`}
|
||||
onClick={() => copy(text)}
|
||||
>
|
||||
<span className="body">{trimmed}</span>
|
||||
{!hideText && <span className="body">{trimmed}</span>}
|
||||
<span
|
||||
className="icon"
|
||||
style={{ color: copied ? "var(--success)" : "var(--highlight)" }}
|
||||
|
@ -11,6 +11,7 @@ import Copy from "./copy";
|
||||
import { hexToBech32, openFile } from "utils";
|
||||
import { VoidApi } from "@void-cat/api";
|
||||
import { LoginType } from "login";
|
||||
import { bech32 } from "@scure/base";
|
||||
|
||||
enum Stage {
|
||||
Login = 0,
|
||||
@ -41,6 +42,26 @@ export function LoginSignup({ close }: { close: () => void }) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doLoginNsec() {
|
||||
try {
|
||||
const nsec = prompt("nsec");
|
||||
if (!nsec) {
|
||||
throw new Error("no nsec provided");
|
||||
}
|
||||
const {words} = bech32.decode(nsec, 5000);
|
||||
const data = new Uint8Array(bech32.fromWords(words));
|
||||
Login.loginWithPrivateKey(bytesToHex(data));
|
||||
close();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e instanceof Error) {
|
||||
setError(e.message);
|
||||
} else {
|
||||
setError(e as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createAccount() {
|
||||
const newKey = bytesToHex(schnorr.utils.randomPrivateKey());
|
||||
@ -108,6 +129,13 @@ export function LoginSignup({ close }: { close: () => void }) {
|
||||
>
|
||||
Create Account
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={doLoginNsec}
|
||||
>
|
||||
Enter Nsec (INSECURE)
|
||||
</button>
|
||||
{error && <b className="error">{error}</b>}
|
||||
</>
|
||||
);
|
||||
|
@ -17,6 +17,7 @@ import { LoginStore } from "login";
|
||||
import { StreamProvidersPage } from "pages/providers";
|
||||
import { defaultRelays } from "const";
|
||||
import { CatchAllRoutePage } from "pages/catch-all";
|
||||
import { SettingsPage } from "pages/settings-page";
|
||||
|
||||
export enum StreamState {
|
||||
Live = "live",
|
||||
@ -60,6 +61,10 @@ const router = createBrowserRouter([
|
||||
path: "/providers/:id?",
|
||||
element: <StreamProvidersPage />,
|
||||
},
|
||||
{
|
||||
path: "/settings",
|
||||
element: <SettingsPage />,
|
||||
},
|
||||
{
|
||||
path: "*",
|
||||
element: <CatchAllRoutePage />,
|
||||
|
@ -48,6 +48,10 @@ export function LayoutPage() {
|
||||
<Icon name="user" size={24} />
|
||||
Profile
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigate("/settings")}>
|
||||
<Icon name="settings" size={24} />
|
||||
Settings
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => Login.logout()}>
|
||||
<Icon name="logout" size={24} />
|
||||
Logout
|
||||
|
16
src/pages/settings-page.css
Normal file
16
src/pages/settings-page.css
Normal file
@ -0,0 +1,16 @@
|
||||
.profile-page {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.public-key {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.private-key {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
36
src/pages/settings-page.tsx
Normal file
36
src/pages/settings-page.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import { useLogin } from "hooks/login";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import "./settings-page.css";
|
||||
import React from "react";
|
||||
import { Button } from "@getalby/bitcoin-connect-react";
|
||||
import Copy from "element/copy";
|
||||
|
||||
export function SettingsPage() {
|
||||
const navigate = useNavigate();
|
||||
const login = useLogin();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!login) {
|
||||
|
||||
navigate("/");
|
||||
}
|
||||
}, [login])
|
||||
|
||||
|
||||
return (
|
||||
<div className="settings-page">
|
||||
<h1>Account</h1>
|
||||
{login?.pubkey && <div className="public-key">
|
||||
<p>Logged in as</p>
|
||||
<Copy text={login?.pubkey} maxSize={64} />
|
||||
</div>}
|
||||
{login?.privateKey && <div className="private-key">
|
||||
<p>Private key</p>
|
||||
<Copy text={login.privateKey} hideText />
|
||||
</div>}
|
||||
|
||||
<h1>Zaps</h1>
|
||||
<Button/>
|
||||
</div>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user