feat(privacy): replace Google Favicons with local letter icons
Remove getFaviconUrl() and all external network requests. Bookmarks now show a colored letter icon with deterministic hue based on title. Eliminates privacy leak and Brave Shields compatibility issues.
This commit is contained in:
+6
-5
@@ -562,12 +562,13 @@ html, body {
|
|||||||
|
|
||||||
body.compact .bm-item { padding: var(--spacing-compact) 10px; }
|
body.compact .bm-item { padding: var(--spacing-compact) 10px; }
|
||||||
|
|
||||||
.bm-favicon { width: 14px; height: 14px; flex-shrink: 0; border-radius: 2px; opacity: 0.85; }
|
.bm-favicon-local {
|
||||||
.bm-favicon-fallback {
|
width: 16px; height: 16px; flex-shrink: 0;
|
||||||
width: 14px; height: 14px; flex-shrink: 0;
|
border-radius: 3px;
|
||||||
background: var(--accent-dim); border-radius: 2px;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
font-size: 8px; color: var(--accent);
|
font-size: 9px; font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.bm-text { flex: 1; min-width: 0; }
|
.bm-text { flex: 1; min-width: 0; }
|
||||||
.bm-title { font-size: 12px; font-weight: 400; color: var(--text-primary); line-height: 1.3; }
|
.bm-title { font-size: 12px; font-weight: 400; color: var(--text-primary); line-height: 1.3; }
|
||||||
|
|||||||
+5
-14
@@ -215,19 +215,11 @@ function createBmEl(bm) {
|
|||||||
li.dataset.bmUrl = bm.url;
|
li.dataset.bmUrl = bm.url;
|
||||||
li.draggable = true;
|
li.draggable = true;
|
||||||
|
|
||||||
const favicon = document.createElement('img');
|
const favicon = document.createElement('div');
|
||||||
favicon.className = 'bm-favicon';
|
favicon.className = 'bm-favicon-local';
|
||||||
favicon.width = 14;
|
favicon.textContent = bm.title.charAt(0).toUpperCase();
|
||||||
favicon.height = 14;
|
const hue = (bm.title.charCodeAt(0) * 137) % 360;
|
||||||
favicon.src = getFaviconUrl(bm.url);
|
favicon.style.backgroundColor = `hsl(${hue}, 45%, 35%)`;
|
||||||
favicon.addEventListener('error', function() {
|
|
||||||
this.classList.add('hidden');
|
|
||||||
this.nextElementSibling.classList.remove('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
const fallback = document.createElement('div');
|
|
||||||
fallback.className = 'bm-favicon-fallback hidden';
|
|
||||||
fallback.textContent = bm.title.charAt(0).toUpperCase();
|
|
||||||
|
|
||||||
const textDiv = document.createElement('div');
|
const textDiv = document.createElement('div');
|
||||||
textDiv.className = 'bm-text';
|
textDiv.className = 'bm-text';
|
||||||
@@ -247,7 +239,6 @@ function createBmEl(bm) {
|
|||||||
deleteBtn.textContent = '✕';
|
deleteBtn.textContent = '✕';
|
||||||
|
|
||||||
li.appendChild(favicon);
|
li.appendChild(favicon);
|
||||||
li.appendChild(fallback);
|
|
||||||
li.appendChild(textDiv);
|
li.appendChild(textDiv);
|
||||||
li.appendChild(deleteBtn);
|
li.appendChild(deleteBtn);
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,6 @@ function escHtml(str) {
|
|||||||
.replace(/"/g, '"');
|
.replace(/"/g, '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFaviconUrl(url) {
|
|
||||||
try {
|
|
||||||
const u = new URL(url);
|
|
||||||
return `https://www.google.com/s2/favicons?domain=${u.hostname}&sz=16`;
|
|
||||||
} catch {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultBoards() {
|
function getDefaultBoards() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user