@@ -32,6 +32,8 @@ export default function BrowserPage() {
3232 const [ paying , setPaying ] = useState ( false )
3333 const [ suggestions , setSuggestions ] = useState < any [ ] > ( [ ] )
3434 const [ showSuggest , setShowSuggest ] = useState ( false )
35+ const [ sitePermOpen , setSitePermOpen ] = useState ( false )
36+ const [ sitePermissions , setSitePermissions ] = useState < any [ ] > ( [ ] )
3537
3638 const activeTab = tabs . find ( t => t . id === activeId ) || tabs [ 0 ]
3739 const isNew = ! activeTab ?. url || activeTab . url === 'zap://newtab' || activeTab . url === '' || activeTab . url === ''
@@ -92,6 +94,31 @@ export default function BrowserPage() {
9294 window . zap ?. shellResize ( { panelOpen : panel !== null } )
9395 } , [ panel ] )
9496
97+
98+ const getActiveOrigin = ( ) => {
99+ try {
100+ const u = activeTab ?. url || ''
101+ if ( ! u . startsWith ( 'http://' ) && ! u . startsWith ( 'https://' ) ) return null
102+ return new URL ( u ) . origin
103+ } catch ( _ ) {
104+ return null
105+ }
106+ }
107+
108+ const openSitePermissions = async ( ) => {
109+ const origin = getActiveOrigin ( )
110+ const perms = await window . zap ?. nostrListPermissions ( )
111+ setSitePermissions ( ( perms || [ ] ) . filter ( ( p : any ) => p . origin === origin ) )
112+ setSitePermOpen ( false )
113+ setPanel ( 'nostr' )
114+ }
115+
116+ const revokeSitePermission = async ( origin : string , action : string ) => {
117+ await window . zap ?. nostrRemovePermission ( { origin, action } )
118+ const perms = await window . zap ?. nostrListPermissions ( )
119+ setSitePermissions ( ( perms || [ ] ) . filter ( ( p : any ) => p . origin === origin ) )
120+ }
121+
95122 const togglePanel = ( p : Panel ) => setPanel ( prev => prev === p ? null : p )
96123
97124 // Create a new tab
@@ -267,7 +294,21 @@ export default function BrowserPage() {
267294 style = { { background :'none' , border :'none' , cursor :'pointer' , color :'var(--t2)' , fontSize :14 , padding :'0 4px' , flexShrink :0 } }
268295 > 🏠</ button >
269296 < div className = "addr-wrap" style = { { cursor :'text' } } >
270- < span className = "addr-icon" > { secIcon ( ) } </ span >
297+ < button
298+ title = "Site permissions"
299+ onClick = { openSitePermissions }
300+ style = { {
301+ background :'none' ,
302+ border :'none' ,
303+ cursor :'pointer' ,
304+ color :'var(--t2)' ,
305+ fontSize :14 ,
306+ padding :0 ,
307+ marginRight :4 ,
308+ } }
309+ >
310+ { secIcon ( ) }
311+ </ button >
271312 < input className = "addr-input"
272313 value = { addrVal }
273314 onChange = { e => handleAddrInput ( e . target . value ) }
@@ -279,6 +320,8 @@ export default function BrowserPage() {
279320 />
280321 </ div >
281322
323+ { /* Site permissions are shown inside the Nostr side panel */ }
324+
282325 { /* 3 privacy buttons */ }
283326 < div className = "priv-row" >
284327 < button className = { `priv-btn ${ privacy ?. adblock ? 'on' : 'off' } ` } onClick = { toggleAdblock }
0 commit comments