import browser from 'webextension-polyfill'
import React, {useState, useCallback, useEffect} from 'react'
import {render} from 'react-dom'
import {generatePrivateKey, nip19} from 'nostr-tools'
import {
getPermissionsString,
readPermissions,
removePermissions
} from './common'
function Options() {
let [key, setKey] = useState('')
let [relays, setRelays] = useState([])
let [newRelayURL, setNewRelayURL] = useState('')
let [permissions, setPermissions] = useState()
let [message, setMessage] = useState('')
const showMessage = useCallback(msg => {
setMessage(msg)
setTimeout(setMessage, 3000)
})
useEffect(() => {
browser.storage.local.get(['private_key', 'relays']).then(results => {
if (results.private_key) setKey(nip19.nsecEncode(results.private_key))
if (results.relays) {
let relaysList = []
for (let url in results.relays) {
relaysList.push({
url,
policy: results.relays[url]
})
}
setRelays(relaysList)
}
})
}, [])
useEffect(() => {
loadPermissions()
}, [])
return (
<>
nos2x
nostr signer extension
options
{permissions?.length > 0 && (
<>
permissions
| domain |
permissions |
condition |
since |
|
{permissions.map(({host, level, condition, created_at}) => (
| {host} |
{getPermissionsString(level)} |
{condition} |
{new Date(created_at * 1000)
.toISOString()
.split('.')[0]
.split('T')
.join(' ')}
|
|
))}
>
)}
{message}
>
)
async function handleKeyChange(e) {
let key = e.target.value.toLowerCase().trim()
setKey(key)
}
async function generate(e) {
setKey(nip19.nsecEncode(generatePrivateKey()))
}
async function saveKey() {
if (!isKeyValid()) return
let hexOrEmptyKey = key
try {
let {type, data} = nip19.decode(key)
if (type === 'nsec') hexOrEmptyKey = data
} catch (_) {}
await browser.storage.local.set({
private_key: hexOrEmptyKey
})
if (hexOrEmptyKey !== '') {
setKey(nip19.nsecEncode(hexOrEmptyKey))
}
showMessage('saved private key!')
}
function isKeyValid() {
if (key === '') return true
if (key.match(/^[a-f0-9]{64}$/)) return true
try {
if (nip19.decode(key).type === 'nsec') return true
} catch (_) {}
return false
}
function changeRelayURL(i, ev) {
setRelays([
...relays.slice(0, i),
{url: ev.target.value, policy: relays[i].policy},
...relays.slice(i + 1)
])
}
function toggleRelayPolicy(i, cat) {
setRelays([
...relays.slice(0, i),
{
url: relays[i].url,
policy: {...relays[i].policy, [cat]: !relays[i].policy[cat]}
},
...relays.slice(i + 1)
])
}
function addNewRelay() {
relays.push({
url: newRelayURL,
policy: {read: true, write: true}
})
setRelays(relays)
setNewRelayURL('')
}
async function handleRevoke(e) {
e.preventDefault()
let host = e.target.dataset.domain
if (window.confirm(`revoke all permissions from ${host}?`)) {
await removePermissions(host)
showMessage(`removed permissions from ${host}`)
loadPermissions()
}
}
function loadPermissions() {
readPermissions().then(permissions => {
setPermissions(
Object.entries(permissions).map(
([host, {level, condition, created_at}]) => ({
host,
level,
condition,
created_at
})
)
)
})
}
async function saveRelays() {
await browser.storage.local.set({
relays: Object.fromEntries(
relays
.filter(({url}) => url.trim() !== '')
.map(({url, policy}) => [url.trim(), policy])
)
})
showMessage('saved relays!')
}
}
render(, document.getElementById('main'))