wip: migrate to typescript

This commit is contained in:
reya
2024-12-22 08:25:14 +07:00
parent a1d87bcd74
commit db9e0b43e5
9 changed files with 303 additions and 153 deletions

7
extension/global.d.ts vendored Normal file
View File

@@ -0,0 +1,7 @@
import type { WindowNostr } from "nostr-tools/nip07";
declare global {
interface Window {
nostr?: WindowNostr;
}
}

View File

@@ -1,7 +1,7 @@
import * as Checkbox from "@radix-ui/react-checkbox";
import * as Tabs from "@radix-ui/react-tabs";
import { generatePrivateKey, nip19 } from "nostr-tools";
import React, { useState, useCallback, useEffect } from "react";
import { nip19, generateSecretKey } from "nostr-tools";
import { useState, useCallback, useEffect } from "react";
import QRCode from "react-qr-code";
import browser from "webextension-polyfill";
import { removePermissions } from "./common";
@@ -17,16 +17,17 @@ function Options() {
);
const [hidingPrivateKey, hidePrivateKey] = useState(true);
const [showNotifications, setNotifications] = useState(false);
const [messages, setMessages] = useState([]);
const [messages, setMessages] = useState<string[]>([]);
const [handleNostrLinks, setHandleNostrLinks] = useState(false);
const [showProtocolHandlerHelp, setShowProtocolHandlerHelp] = useState(false);
const [unsavedChanges, setUnsavedChanges] = useState([]);
const showMessage = useCallback((msg) => {
const showMessage = useCallback((msg: string) => {
messages.push(msg);
setMessages(messages);
setTimeout(() => setMessages([]), 3000);
});
}, []);
useEffect(() => {
browser.storage.local
@@ -515,7 +516,7 @@ examples:
}
async function generate() {
setPrivKey(nip19.nsecEncode(generatePrivateKey()));
setPrivKey(nip19.nsecEncode(generateSecretKey()));
addUnsavedChanges("private_key");
}

View File

@@ -1,13 +1,21 @@
import * as Tabs from "@radix-ui/react-tabs";
import { minidenticon } from "minidenticons";
import { getPublicKey, nip19 } from "nostr-tools";
import React, { useState, useMemo, useEffect } from "react";
import { useState, useMemo, useEffect } from "react";
import QRCode from "react-qr-code";
import browser from "webextension-polyfill";
import { SettingsIcon } from "./icons";
import { createRoot } from "react-dom/client";
type Keys = {
npub: string;
hex: string;
nprofile: string;
};
function Popup() {
const [keys, setKeys] = useState(null);
const [keys, setKeys] = useState<Keys | null>(null);
const avatarURI = useMemo(
() =>
keys
@@ -25,26 +33,38 @@ function Popup() {
useEffect(() => {
browser.storage.local.get(["private_key", "relays"]).then((results) => {
if (results.private_key) {
const hexKey = getPublicKey(results.private_key);
const npubKey = nip19.npubEncode(hexKey);
const decoded = nip19.decode(results.private_key as unknown as string);
setKeys({ npub: npubKey, hex: hexKey });
if (decoded.type === "nsec") {
const nsec = decoded.data;
const hexKey = getPublicKey(nsec);
const npubKey = nip19.npubEncode(hexKey);
if (results.relays) {
const relaysList = [];
for (const url in results.relays) {
if (results.relays[url].write) {
relaysList.push(url);
if (relaysList.length >= 3) break;
setKeys({ npub: npubKey, hex: hexKey, nprofile: "" });
if (results.relays) {
const relaysList: string[] = [];
for (const url in results.relays) {
if (results.relays[url].write) {
relaysList.push(url);
if (relaysList.length >= 3) break;
}
}
if (relaysList.length) {
const nprofileKey = nip19.nprofileEncode({
pubkey: hexKey,
relays: relaysList,
});
setKeys((prev) =>
prev ? { ...prev, nprofile: nprofileKey } : null,
);
}
}
if (relaysList.length) {
const nprofileKey = nip19.nprofileEncode({
pubkey: hexKey,
relays: relaysList,
});
setKeys((prev) => ({ ...prev, nprofile: nprofileKey }));
}
} else {
setKeys(null);
}
} else {
setKeys(null);
@@ -179,6 +199,6 @@ function Popup() {
}
const container = document.getElementById("main");
const root = createRoot(container);
const root = createRoot(container!);
root.render(<Popup />);

View File

@@ -1,4 +1,5 @@
import React, { useState } from "react";
import { useState } from "react";
import { createRoot } from "react-dom/client";
import browser from "webextension-polyfill";
import * as Checkbox from "@radix-ui/react-checkbox";
import { PERMISSION_NAMES } from "./common";
@@ -12,20 +13,27 @@ function Prompt() {
const host = qs.get("host");
const type = qs.get("type");
let params;
let event;
let params: { [key: string]: string } | null;
let event = "";
try {
params = JSON.parse(qs.get("params"));
if (Object.keys(params).length === 0) params = null;
else if (params.event) event = params.event;
params = JSON.parse(qs.get("params") as string);
if (params) {
if (Object.keys(params).length === 0) {
params = null;
} else if (params.event) {
event = params.event;
}
}
} catch (err) {
params = null;
}
function authorizeHandler(accept) {
function authorizeHandler(accept: boolean) {
const conditions = isRemember ? {} : null;
return (ev) => {
return (ev: React.FormEvent<HTMLInputElement>) => {
ev.preventDefault();
browser.runtime.sendMessage({
prompt: true,
@@ -46,7 +54,8 @@ function Prompt() {
<div className="flex flex-col items-center text-center">
<h1 className="font-semibold text-lg">{host}</h1>
<p>
is requesting your permission to <b>{PERMISSION_NAMES[type]}</b>
is requesting your permission to{" "}
<b>{PERMISSION_NAMES[type ? type : "unknown"]}</b>
</p>
</div>
</div>
@@ -63,7 +72,7 @@ function Prompt() {
<Checkbox.Root
id="remember"
className="flex h-6 w-6 appearance-none items-center justify-center rounded-lg bg-white outline-none border border-primary data-[state=checked]:bg-primary data-[state=checked]:border-secondary"
onCheckedChange={setIsRemember}
onCheckedChange={() => setIsRemember((prev) => !prev)}
>
<Checkbox.Indicator className="text-white">
<svg
@@ -89,14 +98,14 @@ function Prompt() {
<div className="flex gap-3">
<button
type="button"
onClick={authorizeHandler(false)}
onClick={() => authorizeHandler(false)}
className="flex-1 h-10 rounded-lg shadow-sm border border-primary inline-flex items-center justify-center font-semibold"
>
Reject
</button>
<button
type="button"
onClick={authorizeHandler(true)}
onClick={() => authorizeHandler(true)}
className="flex-1 h-10 rounded-lg shadow-sm border border-secondary bg-primary text-white inline-flex items-center justify-center font-semibold"
>
Authorize
@@ -109,6 +118,6 @@ function Prompt() {
}
const container = document.getElementById("main");
const root = createRoot(container);
const root = createRoot(container!);
root.render(<Prompt />);