Skip to content

Commit d3c6588

Browse files
committed
feat: v0.3.1 — barra preferiti dropdown, history cliccabile, import HTML, adblock fix, WebRTC, popup bloccati
1 parent eeb1c43 commit d3c6588

6 files changed

Lines changed: 145 additions & 4 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zap-browser",
3-
"version": "0.3.0",
3+
"version": "0.3.1",
44
"description": "Privacy-first Bitcoin browser with Lightning, Liquid, Cashu and Nostr",
55
"main": "src/main/index.js",
66
"scripts": {

src/main/index.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let mainWindow = null
1414
let activeView = null
1515
const tabUrls = new Map()
1616
let activeTabId = null
17-
const SHELL_H = 114
17+
const SHELL_H = 142 // titlebar(32) + tabbar(36) + toolbar(46) + favbar(28)
1818

1919
const UA_POOL = [
2020
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
@@ -314,6 +314,24 @@ ipcMain.handle('decode-invoice', (_, {bolt11}) => nwc.decodeInvoice(bolt11))
314314

315315
// Favorites
316316
ipcMain.handle('get-favorites', () => DB.getFavorites())
317+
ipcMain.handle('import-favorites-html', (_, { html }) => {
318+
const results = []
319+
const linkRe = /<A[^>]+HREF="([^"]+)"[^>]*>([^<]+)<\/A>/gi
320+
let match
321+
while ((match = linkRe.exec(html)) !== null) {
322+
const url = match[1].trim()
323+
const title = match[2].trim()
324+
if (url.startsWith('http') && title) {
325+
try {
326+
DB._db().prepare('INSERT OR IGNORE INTO favorites (url,title,favicon,created_at) VALUES(?,?,NULL,?)')
327+
.run(url, title, Math.floor(Date.now()/1000))
328+
results.push({ url, title })
329+
} catch(_) {}
330+
}
331+
}
332+
return results
333+
})
334+
317335
ipcMain.handle('add-favorite', (_, args) => DB.addFavorite(args))
318336
ipcMain.handle('remove-favorite', (_, {id}) => DB.removeFavorite(id))
319337

src/preload/shell.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ contextBridge.exposeInMainWorld('zap', {
5252

5353
getFavorites: () => ipcRenderer.invoke('get-favorites'),
5454
addFavorite: (a) => ipcRenderer.invoke('add-favorite', a),
55+
importFavoritesHtml: (a) => ipcRenderer.invoke('import-favorites-html', a),
5556
removeFavorite: (a) => ipcRenderer.invoke('remove-favorite', a),
5657

5758
cashuGetBalance: () => ipcRenderer.invoke('cashu-get-balance'),

src/renderer/components/browser/FavoritesPanel.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ export default function FavoritesPanel({ onClose, onNavigate, currentUrl, curren
1717

1818
useEffect(() => { load() }, [])
1919

20-
const load = () => (window as any).zap?.getFavorites().then(setFavs)
20+
const load = () => {
21+
(window as any).zap?.getFavorites().then(setFavs)
22+
window.dispatchEvent(new Event('favorites-updated'))
23+
}
2124

2225
const saveCurrentPage = async () => {
2326
if (!currentUrl || currentUrl === 'zap://newtab') {

src/renderer/components/settings/SettingsPanel.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,32 @@ export default function SettingsPanel({ onClose }: { onClose:()=>void }) {
170170
</select>
171171

172172
<div className="sec-title">{lang==='it'?'Dati browser':'Browser data'}</div>
173+
<div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
174+
padding:'10px 0',borderBottom:'1px solid var(--b0)',marginBottom:8}}>
175+
<div>
176+
<div style={{fontSize:13,fontWeight:600,color:'var(--t0)'}}>
177+
{lang==='it'?'Barra preferiti':'Bookmarks bar'}
178+
</div>
179+
<div style={{fontSize:11,color:'var(--t2)'}}>
180+
{lang==='it'?'Mostra barra sotto la barra indirizzi':'Show bar below address bar'}
181+
</div>
182+
</div>
183+
<button onClick={() => {
184+
const cur = localStorage.getItem('showFavBar') !== 'false'
185+
localStorage.setItem('showFavBar', String(!cur))
186+
window.dispatchEvent(new CustomEvent('toggle-favbar', { detail: !cur }))
187+
}} style={{
188+
padding:'4px 12px', borderRadius:'var(--r-sm)', cursor:'pointer',
189+
border:'1px solid var(--b1)', fontSize:11, fontWeight:600,
190+
background: localStorage.getItem('showFavBar') !== 'false' ? 'var(--amber)' : 'var(--bg-3)',
191+
color: localStorage.getItem('showFavBar') !== 'false' ? '#000' : 'var(--t2)',
192+
}}>
193+
{localStorage.getItem('showFavBar') !== 'false' ? (lang==='it'?'Attiva':'On') : (lang==='it'?'Disattiva':'Off')}
194+
</button>
195+
</div>
173196
{[
174197
{label:t('clearHistory'), desc:t('clearHistoryDesc'), action:()=>z()?.clearHistory()},
198+
175199
{label:t('clearCookies'), desc:t('clearCookiesDesc'), action:()=>z()?.clearCookies()},
176200
{label:t('clearCache'), desc:t('clearCacheDesc'), action:()=>z()?.clearCache()},
177201
].map(item=>(

src/renderer/pages/BrowserPage.tsx

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export default function BrowserPage() {
2121
const [privacy, setPrivacy] = useState<any>(null)
2222
const [uaDrop, setUaDrop] = useState(false)
2323
const [blocked, setBlocked] = useState(0)
24+
const [favBar, setFavBar] = useState<any[]>([])
25+
const [showFavBar, setShowFavBar] = useState(() => localStorage.getItem('showFavBar') !== 'false')
26+
const [favDropOpen, setFavDropOpen] = useState(false)
2427
const [currentUA, setCurrentUA] = useState('')
2528
const [payment, setPayment] = useState<any>(null)
2629
const [pageNostr, setPageNostr] = useState(false)
@@ -36,10 +39,14 @@ export default function BrowserPage() {
3639
// Load privacy settings
3740
useEffect(() => {
3841
window.zap?.getPrivacy().then(setPrivacy)
42+
const loadFavBar = () => window.zap?.getFavorites().then((f: any[]) => setFavBar(f || []))
43+
loadFavBar()
44+
window.addEventListener('favorites-updated', loadFavBar)
3945
window.zap?.getUAPool().then((pool: string[]) => {
4046
if (pool && pool.length > 0) setCurrentUA(pool[Math.floor(Math.random() * pool.length)])
4147
})
4248
window.zap?.getBlockedCount().then(setBlocked)
49+
return () => window.removeEventListener('favorites-updated', loadFavBar)
4350
}, [])
4451

4552
// Listen to events from main process
@@ -57,6 +64,22 @@ export default function BrowserPage() {
5764
handleNewTab(url)
5865
})
5966
window.zap?.on('payment-detected', (data: any) => setPayment(data))
67+
68+
// Navigate from history/bookmarks
69+
const onNavigateTo = (e: any) => {
70+
handleNavigate((e as CustomEvent).detail)
71+
setPanel(null)
72+
}
73+
window.addEventListener('navigate-to', onNavigateTo)
74+
75+
// Toggle bookmarks bar
76+
const onToggleFavBar = (e: any) => setShowFavBar((e as CustomEvent).detail)
77+
window.addEventListener('toggle-favbar', onToggleFavBar)
78+
79+
return () => {
80+
window.removeEventListener('navigate-to', onNavigateTo)
81+
window.removeEventListener('toggle-favbar', onToggleFavBar)
82+
}
6083
}, [activeId])
6184

6285
// Sync address bar with active tab
@@ -92,6 +115,7 @@ export default function BrowserPage() {
92115
const url = (!tab?.url || tab.url === 'zap://newtab') ? '' : tab.url
93116
setActive(id)
94117
setAddrVal(url)
118+
setShowSuggest(false)
95119
window.zap?.tabSwitch({ tabId: id, url })
96120
}, [setActive, tabs])
97121

@@ -311,6 +335,75 @@ export default function BrowserPage() {
311335
</div>
312336
</div>
313337

338+
{/* ── Bookmarks bar ────────────────────────────────────────── */}
339+
{showFavBar && favBar.length > 0 && (() => {
340+
const MAX = 10
341+
const visible = favBar.slice(0, MAX)
342+
const hidden = favBar.slice(MAX)
343+
return (
344+
<div style={{
345+
display:'flex', alignItems:'center', gap:2,
346+
padding:'2px 8px', borderBottom:'1px solid var(--b0)',
347+
background:'var(--bg-1)', flexShrink:0,
348+
WebkitAppRegion:'no-drag' as any, height:28, position:'relative',
349+
}}>
350+
{visible.map((f: any) => (
351+
<button key={f.id} onClick={() => handleNavigate(f.url)}
352+
title={f.url}
353+
style={{
354+
background:'none', border:'none', cursor:'pointer',
355+
color:'var(--t0)', fontSize:11, padding:'2px 7px',
356+
borderRadius:'var(--r-sm)', whiteSpace:'nowrap',
357+
display:'flex', alignItems:'center', gap:3, flexShrink:0,
358+
}}
359+
onMouseEnter={e => (e.currentTarget.style.background='var(--bg-3)')}
360+
onMouseLeave={e => (e.currentTarget.style.background='none')}
361+
>
362+
🌐 {f.title?.slice(0, 18) || (() => { try { return new URL(f.url).hostname } catch(_) { return f.url } })()}
363+
</button>
364+
))}
365+
{hidden.length > 0 && (
366+
<div style={{ position:'relative', marginLeft:'auto', flexShrink:0 }}>
367+
<button
368+
onClick={() => setFavDropOpen(d => !d)}
369+
style={{
370+
background:'none', border:'none', cursor:'pointer',
371+
color:'var(--t2)', fontSize:12, padding:'2px 7px',
372+
borderRadius:'var(--r-sm)',
373+
}}
374+
onMouseEnter={e => (e.currentTarget.style.background='var(--bg-3)')}
375+
onMouseLeave={e => (e.currentTarget.style.background='none')}
376+
>» {hidden.length}</button>
377+
{favDropOpen && (
378+
<div style={{
379+
position:'absolute', top:24, right:0, zIndex:9999,
380+
background:'var(--bg-1)', border:'1px solid var(--b1)',
381+
borderRadius:'var(--r-md)', boxShadow:'0 8px 32px rgba(0,0,0,.4)',
382+
minWidth:220, maxHeight:300, overflowY:'auto',
383+
}}>
384+
{hidden.map((f: any) => (
385+
<button key={f.id}
386+
onClick={() => { handleNavigate(f.url); setFavDropOpen(false) }}
387+
style={{
388+
display:'block', width:'100%', textAlign:'left',
389+
background:'none', border:'none', cursor:'pointer',
390+
color:'var(--t0)', fontSize:12, padding:'8px 12px',
391+
whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis',
392+
}}
393+
onMouseEnter={e => (e.currentTarget.style.background='var(--bg-3)')}
394+
onMouseLeave={e => (e.currentTarget.style.background='none')}
395+
>
396+
🌐 {f.title || f.url}
397+
</button>
398+
))}
399+
</div>
400+
)}
401+
</div>
402+
)}
403+
</div>
404+
)
405+
})()}
406+
314407
{/* ── Browser body ─────────────────────────────────────────────── */}
315408
<div className="app-body">
316409
{/* New tab page (shown when tab is zap://newtab) */}
@@ -322,7 +415,9 @@ export default function BrowserPage() {
322415
{/* When not new tab, BrowserView renders here (injected by Electron) */}
323416
{!isNew && <div style={{ flex:1 }} />}
324417

325-
{/* Suggestions dropdown */}
418+
419+
420+
{/* Suggestions dropdown */}
326421
{showSuggest && (
327422
<div style={{
328423
position:'fixed', top:114, left:0, right:panel?320:0,

0 commit comments

Comments
 (0)