wip: migrate to typescript
This commit is contained in:
7
extension/global.d.ts
vendored
Normal file
7
extension/global.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { WindowNostr } from "nostr-tools/nip07";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
nostr?: WindowNostr;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 />);
|
||||
@@ -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 />);
|
||||
Reference in New Issue
Block a user