add list of "preferred" relays with policies.

This commit is contained in:
fiatjaf
2022-02-15 16:09:33 -03:00
parent 643a0b759e
commit 414c0ea337
3 changed files with 151 additions and 39 deletions

View File

@@ -1,17 +1,51 @@
import browser from 'webextension-polyfill'
import React, {useState, useEffect} from 'react'
import React, {useState, useCallback, useEffect} from 'react'
import {render} from 'react-dom'
import {normalizeRelayURL} from 'nostr-tools/relay'
import {useDebouncedCallback} from 'use-debounce'
import {getPermissionsString, readPermissions} 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)
})
const saveRelays = useDebouncedCallback(async () => {
await browser.storage.local.set({
relays: Object.fromEntries(
relays
.filter(({url}) => url.trim() !== '')
.map(({url, policy}) => [url.trim(), policy])
)
})
showMessage('saved relays!')
}, 700)
useEffect(() => {
browser.storage.local.get(['private_key']).then(results => {
saveRelays()
}, [relays])
useEffect(() => {
browser.storage.local.get(['private_key', 'relays']).then(results => {
if (results.private_key) setKey(results.private_key)
if (results.relays) {
let relaysList = []
for (let url in results.relays) {
relaysList.push({
url,
policy: results.relays[url]
})
}
setRelays(relaysList)
}
})
}, [])
@@ -35,42 +69,81 @@ function Options() {
<h1>nos2x</h1>
<p>nostr signer extension</p>
<h2>options</h2>
<label>
private key:&nbsp;
<input value={key} onChange={handleKeyChange} />
</label>
{permissions?.length > 0 && (
<>
<h2>permissions</h2>
<table>
<thead>
<tr>
<th>domain</th>
<th>permissions</th>
<th>condition</th>
<th>since</th>
</tr>
</thead>
<tbody>
{permissions.map(({host, level, condition, created_at}) => (
<tr key={host}>
<td>{host}</td>
<td>{getPermissionsString(level)}</td>
<td>{condition}</td>
<td>
{new Date(created_at * 1000)
.toISOString()
.split('.')[0]
.split('T')
.join(' ')}
</td>
<div style={{marginBottom: '10px'}}>
<div>preferred relays:</div>
<div style={{marginLeft: '10px'}}>
{relays.map(({url, policy}, i) => (
<div key={i} style={{display: 'flex'}}>
<input
style={{marginRight: '10px'}}
value={url}
onChange={changeRelayURL.bind(null, i)}
/>
<label>
read
<input
type="checkbox"
checked={policy.read}
onChange={toggleRelayPolicy.bind(null, i, 'read')}
/>
</label>
<label>
write
<input
type="checkbox"
checked={policy.write}
onChange={toggleRelayPolicy.bind(null, i, 'write')}
/>
</label>
</div>
))}
<div style={{display: 'flex'}}>
<input
value={newRelayURL}
onChange={e => setNewRelayURL(e.target.value)}
onBlur={addNewRelay}
/>
</div>
</div>
</div>
<div>
<label>
private key:&nbsp;
<input value={key} onChange={handleKeyChange} />
</label>
{permissions?.length > 0 && (
<>
<h2>permissions</h2>
<table>
<thead>
<tr>
<th>domain</th>
<th>permissions</th>
<th>condition</th>
<th>since</th>
</tr>
))}
</tbody>
</table>
</>
)}
<div>{message}</div>
</thead>
<tbody>
{permissions.map(({host, level, condition, created_at}) => (
<tr key={host}>
<td>{host}</td>
<td>{getPermissionsString(level)}</td>
<td>{condition}</td>
<td>
{new Date(created_at * 1000)
.toISOString()
.split('.')[0]
.split('T')
.join(' ')}
</td>
</tr>
))}
</tbody>
</table>
</>
)}
</div>
<div style={{marginTop: '12px', fontSize: '120%'}}>{message}</div>
</>
)
@@ -82,10 +155,37 @@ function Options() {
await browser.storage.local.set({
private_key: key
})
setMessage('saved!')
setTimeout(setMessage, 3000)
showMessage('saved private key!')
}
}
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: normalizeRelayURL(newRelayURL),
policy: {read: true, write: true}
})
setRelays(relays)
setNewRelayURL('')
}
}
render(<Options />, document.getElementById('main'))

View File

@@ -11,6 +11,8 @@
"prettier": "^2.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"use-boolean-state": "^1.0.2",
"use-debounce": "^7.0.1",
"webextension-polyfill": "^0.8.0"
},
"scripts": {

View File

@@ -1450,6 +1450,16 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
use-boolean-state@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/use-boolean-state/-/use-boolean-state-1.0.2.tgz#4583f570a5f650741e808b5fa8a274f01adf764a"
integrity sha512-2qjR94L8GSbBKr7/qZrf14DH0PEREbtVMGeJ9kxAbpdgFp2xDux7rShCcHdnya5ca8jG+5fiRdX/aJqXi56BxA==
use-debounce@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-7.0.1.tgz#380e6191cc13ad29f8e2149a12b5c37cc2891190"
integrity sha512-fOrzIw2wstbAJuv8PC9Vg4XgwyTLEOdq4y/Z3IhVl8DAE4svRcgyEUvrEXu+BMNgMoc3YND6qLT61kkgEKXh7Q==
utf-8-validate@^5.0.2:
version "5.0.8"
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.8.tgz#4a735a61661dbb1c59a0868c397d2fe263f14e58"