wip
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>nos2x</title>
|
<title>Nostr Connect (formerly nos2x)</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link href="/build/style.css" rel="stylesheet" />
|
<link href="/build/style.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import QRCode from 'react-qr-code'
|
|||||||
import * as Tabs from '@radix-ui/react-tabs'
|
import * as Tabs from '@radix-ui/react-tabs'
|
||||||
import {LogoIcon} from './icons'
|
import {LogoIcon} from './icons'
|
||||||
import {removePermissions} from './common'
|
import {removePermissions} from './common'
|
||||||
|
import * as Checkbox from '@radix-ui/react-checkbox'
|
||||||
|
|
||||||
function Options() {
|
function Options() {
|
||||||
let [privKey, setPrivKey] = useState('')
|
let [privKey, setPrivKey] = useState('')
|
||||||
@@ -185,22 +186,76 @@ function Options() {
|
|||||||
className="flex-1 h-9 bg-transparent border px-3 py-1 border-primary rounded-lg placeholder:text-muted"
|
className="flex-1 h-9 bg-transparent border px-3 py-1 border-primary rounded-lg placeholder:text-muted"
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<label className="inline-flex items-center gap-2 text-muted font-medium">
|
<div className="inline-flex items-center gap-2">
|
||||||
<input
|
<Checkbox.Root
|
||||||
type="checkbox"
|
id={`read-${i}`}
|
||||||
checked={policy.read}
|
checked={policy.read}
|
||||||
onChange={toggleRelayPolicy.bind(null, i, 'read')}
|
onCheckedChange={toggleRelayPolicy.bind(
|
||||||
/>
|
null,
|
||||||
<p>Read</p>
|
i,
|
||||||
</label>
|
'read'
|
||||||
<label className="inline-flex items-center gap-2 text-muted font-medium">
|
)}
|
||||||
<input
|
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"
|
||||||
type="checkbox"
|
>
|
||||||
|
<Checkbox.Indicator className="text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
stroke="currentColor"
|
||||||
|
className="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M4.5 12.75l6 6 9-13.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label
|
||||||
|
htmlFor={`read-${i}`}
|
||||||
|
className="text-muted font-medium"
|
||||||
|
>
|
||||||
|
Read
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="inline-flex items-center gap-2">
|
||||||
|
<Checkbox.Root
|
||||||
|
id={`write-${i}`}
|
||||||
checked={policy.write}
|
checked={policy.write}
|
||||||
onChange={toggleRelayPolicy.bind(null, i, 'write')}
|
onCheckedChange={toggleRelayPolicy.bind(
|
||||||
/>
|
null,
|
||||||
<p>Write</p>
|
i,
|
||||||
</label>
|
'write'
|
||||||
|
)}
|
||||||
|
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"
|
||||||
|
>
|
||||||
|
<Checkbox.Indicator className="text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
stroke="currentColor"
|
||||||
|
className="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M4.5 12.75l6 6 9-13.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label
|
||||||
|
htmlFor={`write-${i}`}
|
||||||
|
className="text-muted font-medium"
|
||||||
|
>
|
||||||
|
Write
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={removeRelay.bind(null, i)}
|
onClick={removeRelay.bind(null, i)}
|
||||||
@@ -317,15 +372,34 @@ function Options() {
|
|||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="flex gap-2 items-center">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<Checkbox.Root
|
||||||
type="checkbox"
|
id="notification"
|
||||||
|
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"
|
||||||
checked={showNotifications}
|
checked={showNotifications}
|
||||||
onChange={handleNotifications}
|
onCheckedChange={handleNotifications}
|
||||||
className="w-6 h-6 rounded-md border border-gray-200 dark:border-gray-800 appearance-none"
|
>
|
||||||
/>
|
<Checkbox.Indicator className="text-white">
|
||||||
Show desktop notifications when a permissions has been used
|
<svg
|
||||||
</label>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
stroke="currentColor"
|
||||||
|
className="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M4.5 12.75l6 6 9-13.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label htmlFor="notification">
|
||||||
|
Show desktop notifications when a permissions has been used
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<details>
|
<details>
|
||||||
@@ -349,47 +423,48 @@ function Options() {
|
|||||||
</div>
|
</div>
|
||||||
</summary>
|
</summary>
|
||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<label className="flex gap-2 items-center">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<Checkbox.Root
|
||||||
type="checkbox"
|
id="notification"
|
||||||
|
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"
|
||||||
checked={handleNostrLinks}
|
checked={handleNostrLinks}
|
||||||
onChange={changeHandleNostrLinks}
|
onCheckedChange={changeHandleNostrLinks}
|
||||||
className="w-6 h-6 rounded-md border border-gray-200 dark:border-gray-800 appearance-none"
|
>
|
||||||
/>
|
<Checkbox.Indicator className="text-white">
|
||||||
Handle nostr links
|
<svg
|
||||||
</label>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
</div>
|
fill="none"
|
||||||
</details>
|
viewBox="0 0 24 24"
|
||||||
</div>
|
strokeWidth={1.5}
|
||||||
{/*<div>
|
stroke="currentColor"
|
||||||
<label style={{display: 'flex', alignItems: 'center'}}>
|
className="w-4 h-4"
|
||||||
<div>
|
>
|
||||||
handle{' '}
|
<path
|
||||||
<span style={{padding: '2px', background: 'silver'}}>nostr:</span>{' '}
|
strokeLinecap="round"
|
||||||
links:
|
strokeLinejoin="round"
|
||||||
</div>
|
d="M4.5 12.75l6 6 9-13.5"
|
||||||
<input
|
/>
|
||||||
type="checkbox"
|
</svg>
|
||||||
checked={handleNostrLinks}
|
</Checkbox.Indicator>
|
||||||
onChange={changeHandleNostrLinks}
|
</Checkbox.Root>
|
||||||
/>
|
<label htmlFor="notification">Handle nostr links</label>
|
||||||
</label>
|
|
||||||
<div style={{marginLeft: '10px'}}>
|
|
||||||
{handleNostrLinks && (
|
|
||||||
<div>
|
|
||||||
<div style={{display: 'flex'}}>
|
|
||||||
<input
|
|
||||||
placeholder="url template"
|
|
||||||
value={protocolHandler}
|
|
||||||
onChange={handleChangeProtocolHandler}
|
|
||||||
style={{width: '680px', maxWidth: '90%'}}
|
|
||||||
/>
|
|
||||||
{!showProtocolHandlerHelp && (
|
|
||||||
<button onClick={changeShowProtocolHandlerHelp}>?</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{showProtocolHandlerHelp && (
|
{handleNostrLinks && (
|
||||||
<pre>{`
|
<div className="mt-3">
|
||||||
|
<div className="flex">
|
||||||
|
<input
|
||||||
|
placeholder="url template"
|
||||||
|
value={protocolHandler}
|
||||||
|
onChange={handleChangeProtocolHandler}
|
||||||
|
/>
|
||||||
|
{!showProtocolHandlerHelp && (
|
||||||
|
<button onClick={changeShowProtocolHandlerHelp}>
|
||||||
|
?
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{showProtocolHandlerHelp && (
|
||||||
|
<pre className="bg-muted p-2 rounded-xl break-all">{`
|
||||||
{raw} = anything after the colon, i.e. the full nip19 bech32 string
|
{raw} = anything after the colon, i.e. the full nip19 bech32 string
|
||||||
{hex} = hex pubkey for npub or nprofile, hex event id for note or nevent
|
{hex} = hex pubkey for npub or nprofile, hex event id for note or nevent
|
||||||
{p_or_e} = "p" for npub or nprofile, "e" for note or nevent
|
{p_or_e} = "p" for npub or nprofile, "e" for note or nevent
|
||||||
@@ -404,16 +479,12 @@ function Options() {
|
|||||||
- https://snort.social/{raw}
|
- https://snort.social/{raw}
|
||||||
- https://nostr.band/{raw}
|
- https://nostr.band/{raw}
|
||||||
`}</pre>
|
`}</pre>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
</details>
|
||||||
</div>
|
</div>
|
||||||
</div>*/}
|
|
||||||
{/*<div style={{fontSize: '120%'}}>
|
|
||||||
{messages.map((message, i) => (
|
|
||||||
<div key={i}>{message}</div>
|
|
||||||
))}
|
|
||||||
</div>*/}
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
disabled={!unsavedChanges.length}
|
disabled={!unsavedChanges.length}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>nos2x</title>
|
<title>Nostr Connect (formerly nos2x)</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link href="/build/style.css" rel="stylesheet" />
|
<link href="/build/style.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
import browser from 'webextension-polyfill'
|
import browser from 'webextension-polyfill'
|
||||||
import {render} from 'react-dom'
|
import {render} from 'react-dom'
|
||||||
import {getPublicKey, nip19} from 'nostr-tools'
|
import {getPublicKey, nip19} from 'nostr-tools'
|
||||||
import React, {useState, useMemo, useRef, useEffect} from 'react'
|
import React, {useState, useMemo, useEffect} from 'react'
|
||||||
import QRCode from 'react-qr-code'
|
import QRCode from 'react-qr-code'
|
||||||
import {SettingsIcon} from './icons'
|
import {SettingsIcon} from './icons'
|
||||||
import {minidenticon} from 'minidenticons'
|
import {minidenticon} from 'minidenticons'
|
||||||
import * as Tabs from '@radix-ui/react-tabs'
|
import * as Tabs from '@radix-ui/react-tabs'
|
||||||
|
|
||||||
function Popup() {
|
function Popup() {
|
||||||
let [pubKey, setPubKey] = useState('')
|
let [keys, setKeys] = useState(null)
|
||||||
|
|
||||||
let keys = useRef({npub: '', hex: '', nprofile: ''})
|
|
||||||
let avatarURI = useMemo(
|
let avatarURI = useMemo(
|
||||||
() =>
|
() =>
|
||||||
pubKey
|
keys
|
||||||
? 'data:image/svg+xml;utf8,' +
|
? 'data:image/svg+xml;utf8,' +
|
||||||
encodeURIComponent(minidenticon(pubKey, 90, 30))
|
encodeURIComponent(minidenticon(keys.npub, 90, 30))
|
||||||
: null,
|
: null,
|
||||||
[pubKey]
|
[keys]
|
||||||
)
|
)
|
||||||
|
|
||||||
const gotoSettings = () => {
|
const gotoSettings = () => {
|
||||||
@@ -32,10 +30,7 @@ function Popup() {
|
|||||||
let hexKey = getPublicKey(results.private_key)
|
let hexKey = getPublicKey(results.private_key)
|
||||||
let npubKey = nip19.npubEncode(hexKey)
|
let npubKey = nip19.npubEncode(hexKey)
|
||||||
|
|
||||||
setPubKey(npubKey)
|
setKeys({npub: npubKey, hex: hexKey})
|
||||||
|
|
||||||
keys.current.npub = npubKey
|
|
||||||
keys.current.hex = hexKey
|
|
||||||
|
|
||||||
if (results.relays) {
|
if (results.relays) {
|
||||||
let relaysList = []
|
let relaysList = []
|
||||||
@@ -50,18 +45,18 @@ function Popup() {
|
|||||||
pubkey: hexKey,
|
pubkey: hexKey,
|
||||||
relays: relaysList
|
relays: relaysList
|
||||||
})
|
})
|
||||||
keys.current.nprofile = nprofileKey
|
setKeys(prev => ({...prev, nprofile: nprofileKey}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setPubKey(null)
|
setKeys(null)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-[320px] p-6">
|
<div className="w-[320px] p-6">
|
||||||
{!pubKey ? (
|
{!keys ? (
|
||||||
<div className="flex items-center justify-between gap-6">
|
<div className="flex items-center justify-between gap-6">
|
||||||
<div className="flex-1 flex items-center justify-between">
|
<div className="flex-1 flex items-center justify-between">
|
||||||
<p className="text-sm font-medium">
|
<p className="text-sm font-medium">
|
||||||
@@ -129,31 +124,53 @@ function Popup() {
|
|||||||
>
|
>
|
||||||
hex
|
hex
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger
|
{keys.nprofile ? (
|
||||||
value="nprofile"
|
<Tabs.Trigger
|
||||||
className="font-medium flex-1 flex items-center justify-center text-muted h-10 data-[state=active]:text-primary data-[state=active]:border-b data-[state=active]:border-secondary"
|
value="nprofile"
|
||||||
>
|
className="font-medium flex-1 flex items-center justify-center text-muted h-10 data-[state=active]:text-primary data-[state=active]:border-b data-[state=active]:border-secondary"
|
||||||
naddr
|
>
|
||||||
</Tabs.Trigger>
|
nprofile
|
||||||
|
</Tabs.Trigger>
|
||||||
|
) : null}
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
<Tabs.Content value="npub">
|
<Tabs.Content value="npub">
|
||||||
<div className="my-4">
|
<div className="my-4">
|
||||||
<textarea
|
<textarea
|
||||||
|
value={keys.npub}
|
||||||
readOnly
|
readOnly
|
||||||
className="w-full h-20 resize-none p-3 bg-muted rounded-xl"
|
className="w-full h-20 resize-none p-3 bg-muted rounded-xl"
|
||||||
>
|
|
||||||
{pubKey}
|
|
||||||
</textarea>
|
|
||||||
</div>
|
|
||||||
<div className="w-full rounded-xl border border-primary p-4 flex items-center justify-center">
|
|
||||||
<QRCode
|
|
||||||
size={128}
|
|
||||||
value={
|
|
||||||
pubKey.startsWith('n') ? pubKey.toUpperCase() : pubKey
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-full rounded-xl border border-primary p-4 flex items-center justify-center">
|
||||||
|
<QRCode size={128} value={keys.npub} />
|
||||||
|
</div>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
|
<Tabs.Content value="hex">
|
||||||
|
<div className="my-4">
|
||||||
|
<textarea
|
||||||
|
value={keys.hex}
|
||||||
|
readOnly
|
||||||
|
className="w-full h-20 resize-none p-3 bg-muted rounded-xl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full rounded-xl border border-primary p-4 flex items-center justify-center">
|
||||||
|
<QRCode size={128} value={keys.hex} />
|
||||||
|
</div>
|
||||||
|
</Tabs.Content>
|
||||||
|
{keys.nprofile ? (
|
||||||
|
<Tabs.Content value="nprofile">
|
||||||
|
<div className="my-4">
|
||||||
|
<textarea
|
||||||
|
value={keys.nprofile}
|
||||||
|
readOnly
|
||||||
|
className="w-full h-20 resize-none p-3 bg-muted rounded-xl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full rounded-xl border border-primary p-4 flex items-center justify-center">
|
||||||
|
<QRCode size={128} value={keys.nprofile} />
|
||||||
|
</div>
|
||||||
|
</Tabs.Content>
|
||||||
|
) : null}
|
||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>nos2x</title>
|
<title>Nostr Connect (formerly nos2x)</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link href="/build/style.css" rel="stylesheet" />
|
<link href="/build/style.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
import browser from 'webextension-polyfill'
|
import browser from 'webextension-polyfill'
|
||||||
import {render} from 'react-dom'
|
import {render} from 'react-dom'
|
||||||
import React from 'react'
|
import React, {useState} from 'react'
|
||||||
|
|
||||||
import {PERMISSION_NAMES} from './common'
|
import {PERMISSION_NAMES} from './common'
|
||||||
|
import {LogoIcon} from './icons'
|
||||||
|
import * as Checkbox from '@radix-ui/react-checkbox'
|
||||||
|
|
||||||
function Prompt() {
|
function Prompt() {
|
||||||
|
const [isRemember, setIsRemember] = useState(false)
|
||||||
|
|
||||||
let qs = new URLSearchParams(location.search)
|
let qs = new URLSearchParams(location.search)
|
||||||
let id = qs.get('id')
|
let id = qs.get('id')
|
||||||
let host = qs.get('host')
|
let host = qs.get('host')
|
||||||
let type = qs.get('type')
|
let type = qs.get('type')
|
||||||
let params, event
|
let params, event
|
||||||
|
|
||||||
try {
|
try {
|
||||||
params = JSON.parse(qs.get('params'))
|
params = JSON.parse(qs.get('params'))
|
||||||
if (Object.keys(params).length === 0) params = null
|
if (Object.keys(params).length === 0) params = null
|
||||||
@@ -18,83 +23,8 @@ function Prompt() {
|
|||||||
params = null
|
params = null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
function authorizeHandler(accept) {
|
||||||
<>
|
const conditions = isRemember ? {} : null
|
||||||
<div>
|
|
||||||
<b style={{display: 'block', textAlign: 'center', fontSize: '200%'}}>
|
|
||||||
{host}
|
|
||||||
</b>{' '}
|
|
||||||
<p>
|
|
||||||
is requesting your permission to <b>{PERMISSION_NAMES[type]}:</b>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{params && (
|
|
||||||
<>
|
|
||||||
<p>now acting on</p>
|
|
||||||
<pre style={{overflow: 'auto', maxHeight: '120px'}}>
|
|
||||||
<code>{JSON.stringify(event || params, null, 2)}</code>
|
|
||||||
</pre>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
justifyContent: 'space-around'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
style={{marginTop: '5px'}}
|
|
||||||
onClick={authorizeHandler(
|
|
||||||
true,
|
|
||||||
{} // store this and answer true forever
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
authorize forever
|
|
||||||
</button>
|
|
||||||
{event?.kind !== undefined && (
|
|
||||||
<button
|
|
||||||
style={{marginTop: '5px'}}
|
|
||||||
onClick={authorizeHandler(
|
|
||||||
true,
|
|
||||||
{kinds: {[event.kind]: true}} // store and always answer true for all events that match this condition
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
authorize kind {event.kind} forever
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
<button style={{marginTop: '5px'}} onClick={authorizeHandler(true)}>
|
|
||||||
authorize just this
|
|
||||||
</button>
|
|
||||||
{event?.kind !== undefined ? (
|
|
||||||
<button
|
|
||||||
style={{marginTop: '5px'}}
|
|
||||||
onClick={authorizeHandler(
|
|
||||||
false,
|
|
||||||
{kinds: {[event.kind]: true}} // idem
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
reject kind {event.kind} forever
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
style={{marginTop: '5px'}}
|
|
||||||
onClick={authorizeHandler(
|
|
||||||
false,
|
|
||||||
{} // idem
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
reject forever
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
<button style={{marginTop: '5px'}} onClick={authorizeHandler(false)}>
|
|
||||||
reject
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
function authorizeHandler(accept, conditions) {
|
|
||||||
return function (ev) {
|
return function (ev) {
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
@@ -107,6 +37,129 @@ function Prompt() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-screen h-screen flex flex-col items-center justify-center">
|
||||||
|
<div className="p-8 shadow-primary border border-primary rounded-2xl max-w-xl mx-auto flex flex-col gap-5">
|
||||||
|
<div className="flex flex-col items-center gap-5">
|
||||||
|
<LogoIcon />
|
||||||
|
<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>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{params && (
|
||||||
|
<div>
|
||||||
|
<p>Now acting on</p>
|
||||||
|
<pre className="bg-muted rounded-xl p-3">
|
||||||
|
<code>{JSON.stringify(event || params, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
<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}
|
||||||
|
>
|
||||||
|
<Checkbox.Indicator className="text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
stroke="currentColor"
|
||||||
|
className="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M4.5 12.75l6 6 9-13.5"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label htmlFor="remember" className="text-muted">
|
||||||
|
Remember my preference forever
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<button
|
||||||
|
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
|
||||||
|
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
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/*
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
justifyContent: 'space-around'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
style={{marginTop: '5px'}}
|
||||||
|
onClick={authorizeHandler(
|
||||||
|
true,
|
||||||
|
{} // store this and answer true forever
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
authorize forever
|
||||||
|
</button>
|
||||||
|
{event?.kind !== undefined && (
|
||||||
|
<button
|
||||||
|
style={{marginTop: '5px'}}
|
||||||
|
onClick={authorizeHandler(
|
||||||
|
true,
|
||||||
|
{kinds: {[event.kind]: true}} // store and always answer true for all events that match this condition
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
authorize kind {event.kind} forever
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button style={{marginTop: '5px'}} onClick={authorizeHandler(true)}>
|
||||||
|
authorize just this
|
||||||
|
</button>
|
||||||
|
{event?.kind !== undefined ? (
|
||||||
|
<button
|
||||||
|
style={{marginTop: '5px'}}
|
||||||
|
onClick={authorizeHandler(
|
||||||
|
false,
|
||||||
|
{kinds: {[event.kind]: true}} // idem
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
reject kind {event.kind} forever
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
style={{marginTop: '5px'}}
|
||||||
|
onClick={authorizeHandler(
|
||||||
|
false,
|
||||||
|
{} // idem
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
reject forever
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button style={{marginTop: '5px'}} onClick={authorizeHandler(false)}>
|
||||||
|
reject
|
||||||
|
</button>
|
||||||
|
</div>*/}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render(<Prompt />, document.getElementById('main'))
|
render(<Prompt />, document.getElementById('main'))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"license": "WTFPL",
|
"license": "WTFPL",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-tabs": "^1.0.4",
|
"@radix-ui/react-tabs": "^1.0.4",
|
||||||
"async-mutex": "^0.3.2",
|
"async-mutex": "^0.3.2",
|
||||||
"esbuild": "^0.14.54",
|
"esbuild": "^0.14.54",
|
||||||
|
|||||||
56
pnpm-lock.yaml
generated
56
pnpm-lock.yaml
generated
@@ -5,6 +5,9 @@ settings:
|
|||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@radix-ui/react-checkbox':
|
||||||
|
specifier: ^1.0.4
|
||||||
|
version: 1.0.4(react-dom@17.0.2)(react@17.0.2)
|
||||||
'@radix-ui/react-tabs':
|
'@radix-ui/react-tabs':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.0.4(react-dom@17.0.2)(react@17.0.2)
|
version: 1.0.4(react-dom@17.0.2)(react@17.0.2)
|
||||||
@@ -1730,6 +1733,32 @@ packages:
|
|||||||
'@babel/runtime': 7.23.2
|
'@babel/runtime': 7.23.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-checkbox@1.0.4(react-dom@17.0.2)(react@17.0.2):
|
||||||
|
resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(react@17.0.2)
|
||||||
|
'@radix-ui/react-context': 1.0.1(react@17.0.2)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(react-dom@17.0.2)(react@17.0.2)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(react-dom@17.0.2)(react@17.0.2)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(react@17.0.2)
|
||||||
|
'@radix-ui/react-use-previous': 1.0.1(react@17.0.2)
|
||||||
|
'@radix-ui/react-use-size': 1.0.1(react@17.0.2)
|
||||||
|
react: 17.0.2
|
||||||
|
react-dom: 17.0.2(react@17.0.2)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-collection@1.0.3(react-dom@17.0.2)(react@17.0.2):
|
/@radix-ui/react-collection@1.0.3(react-dom@17.0.2)(react@17.0.2):
|
||||||
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1951,6 +1980,33 @@ packages:
|
|||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-use-previous@1.0.1(react@17.0.2):
|
||||||
|
resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
react: 17.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-use-size@1.0.1(react@17.0.2):
|
||||||
|
resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.2
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.0.1(react@17.0.2)
|
||||||
|
react: 17.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@react-native-community/cli-clean@11.3.10:
|
/@react-native-community/cli-clean@11.3.10:
|
||||||
resolution: {integrity: sha512-g6QjW+DSqoWRHzmIQW3AH22k1AnynWuOdy2YPwYEGgPddTeXZtJphIpEVwDOiC0L4mZv2VmiX33/cGNUwO0cIA==}
|
resolution: {integrity: sha512-g6QjW+DSqoWRHzmIQW3AH22k1AnynWuOdy2YPwYEGgPddTeXZtJphIpEVwDOiC0L4mZv2VmiX33/cGNUwO0cIA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user