v1.0.1: Fix AMO warnings, add extension ID
This commit is contained in:
parent
f8f6a95b0f
commit
0fde22d6e2
3 changed files with 126 additions and 42 deletions
|
|
@ -1,11 +1,21 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Embermarks",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Rediscover your forgotten bookmarks. Surface the ones you never visit.",
|
||||
"author": "Bastian Gruber",
|
||||
"homepage_url": "https://github.com/gruberb/embermarks",
|
||||
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "embermarks@gruberb.dev",
|
||||
"strict_min_version": "109.0",
|
||||
"data_collection_permissions": {
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"icons": {
|
||||
"48": "icons/ember-48.svg",
|
||||
"96": "icons/ember-96.svg"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
action: "getBookmarkFolders",
|
||||
});
|
||||
|
||||
folderList.innerHTML = "";
|
||||
// Clear loading text
|
||||
while (folderList.firstChild) {
|
||||
folderList.removeChild(folderList.firstChild);
|
||||
}
|
||||
|
||||
for (const folder of folders) {
|
||||
const item = document.createElement("div");
|
||||
|
|
@ -28,11 +31,18 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
|
||||
const isExcluded = settings.excludedFolders.includes(folder.id);
|
||||
|
||||
item.innerHTML = `
|
||||
<input type="checkbox" id="folder-${folder.id}" value="${folder.id}" ${isExcluded ? "checked" : ""}>
|
||||
<label for="folder-${folder.id}">📁 ${folder.title || "(unnamed)"}</label>
|
||||
`;
|
||||
const checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.id = `folder-${folder.id}`;
|
||||
checkbox.value = folder.id;
|
||||
checkbox.checked = isExcluded;
|
||||
|
||||
const label = document.createElement("label");
|
||||
label.htmlFor = `folder-${folder.id}`;
|
||||
label.textContent = `📁 ${folder.title || "(unnamed)"}`;
|
||||
|
||||
item.appendChild(checkbox);
|
||||
item.appendChild(label);
|
||||
folderList.appendChild(item);
|
||||
}
|
||||
|
||||
|
|
|
|||
136
shared/ui.js
136
shared/ui.js
|
|
@ -20,13 +20,6 @@ function formatDaysAgo(days) {
|
|||
return `${Math.floor(days / 365)}y ago`;
|
||||
}
|
||||
|
||||
// Escape HTML
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
// Create a bookmark card element
|
||||
function createBookmarkCard(bookmark) {
|
||||
const card = document.createElement("a");
|
||||
|
|
@ -35,20 +28,47 @@ function createBookmarkCard(bookmark) {
|
|||
card.target = "_blank";
|
||||
card.rel = "noopener";
|
||||
|
||||
const faviconUrl = getFaviconUrl(bookmark.url);
|
||||
// Favicon container
|
||||
const favicon = document.createElement("div");
|
||||
favicon.className = "bookmark-favicon";
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="bookmark-favicon">
|
||||
${faviconUrl ? `<img src="${faviconUrl}" alt="">` : "🔖"}
|
||||
</div>
|
||||
<div class="bookmark-info">
|
||||
<div class="bookmark-title" title="${escapeHtml(bookmark.title)}">${escapeHtml(bookmark.title)}</div>
|
||||
<div class="bookmark-meta">
|
||||
${bookmark.visitCount} visit${bookmark.visitCount !== 1 ? "s" : ""} · Added ${formatDaysAgo(bookmark.daysSinceAdded)}
|
||||
</div>
|
||||
${bookmark.path ? `<div class="bookmark-folder">${escapeHtml(bookmark.path)}</div>` : ""}
|
||||
</div>
|
||||
`;
|
||||
const faviconUrl = getFaviconUrl(bookmark.url);
|
||||
if (faviconUrl) {
|
||||
const img = document.createElement("img");
|
||||
img.src = faviconUrl;
|
||||
img.alt = "";
|
||||
favicon.appendChild(img);
|
||||
} else {
|
||||
favicon.textContent = "🔖";
|
||||
}
|
||||
|
||||
// Info container
|
||||
const info = document.createElement("div");
|
||||
info.className = "bookmark-info";
|
||||
|
||||
const title = document.createElement("div");
|
||||
title.className = "bookmark-title";
|
||||
title.title = bookmark.title;
|
||||
title.textContent = bookmark.title;
|
||||
|
||||
const meta = document.createElement("div");
|
||||
meta.className = "bookmark-meta";
|
||||
const visitText =
|
||||
bookmark.visitCount === 1 ? "1 visit" : `${bookmark.visitCount} visits`;
|
||||
meta.textContent = `${visitText} · Added ${formatDaysAgo(bookmark.daysSinceAdded)}`;
|
||||
|
||||
info.appendChild(title);
|
||||
info.appendChild(meta);
|
||||
|
||||
if (bookmark.path) {
|
||||
const folder = document.createElement("div");
|
||||
folder.className = "bookmark-folder";
|
||||
folder.textContent = bookmark.path;
|
||||
info.appendChild(folder);
|
||||
}
|
||||
|
||||
card.appendChild(favicon);
|
||||
card.appendChild(info);
|
||||
|
||||
return card;
|
||||
}
|
||||
|
|
@ -70,18 +90,66 @@ function showEmptyState(container, reason = "none") {
|
|||
|
||||
const msg = messages[reason] || messages.none;
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="icon">${msg.icon}</div>
|
||||
<h2>${msg.title}</h2>
|
||||
<p>${msg.text}</p>
|
||||
</div>
|
||||
`;
|
||||
// Clear container
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
const emptyState = document.createElement("div");
|
||||
emptyState.className = "empty-state";
|
||||
|
||||
const icon = document.createElement("div");
|
||||
icon.className = "icon";
|
||||
icon.textContent = msg.icon;
|
||||
|
||||
const heading = document.createElement("h2");
|
||||
heading.textContent = msg.title;
|
||||
|
||||
const paragraph = document.createElement("p");
|
||||
paragraph.textContent = msg.text;
|
||||
|
||||
emptyState.appendChild(icon);
|
||||
emptyState.appendChild(heading);
|
||||
emptyState.appendChild(paragraph);
|
||||
|
||||
container.appendChild(emptyState);
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
function showLoading(container) {
|
||||
container.innerHTML = '<div class="loading"></div>';
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
const loading = document.createElement("div");
|
||||
loading.className = "loading";
|
||||
container.appendChild(loading);
|
||||
}
|
||||
|
||||
// Show error state
|
||||
function showError(container) {
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
const emptyState = document.createElement("div");
|
||||
emptyState.className = "empty-state";
|
||||
|
||||
const icon = document.createElement("div");
|
||||
icon.className = "icon";
|
||||
icon.textContent = "!";
|
||||
|
||||
const heading = document.createElement("h2");
|
||||
heading.textContent = "Oops";
|
||||
|
||||
const paragraph = document.createElement("p");
|
||||
paragraph.textContent = "Failed to load bookmarks";
|
||||
|
||||
emptyState.appendChild(icon);
|
||||
emptyState.appendChild(heading);
|
||||
emptyState.appendChild(paragraph);
|
||||
|
||||
container.appendChild(emptyState);
|
||||
}
|
||||
|
||||
// Load and display bookmarks
|
||||
|
|
@ -93,7 +161,9 @@ async function loadBookmarks(container) {
|
|||
action: "getForgottenBookmarks",
|
||||
});
|
||||
|
||||
container.innerHTML = "";
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
if (!bookmarks || bookmarks.length === 0) {
|
||||
showEmptyState(container, "none");
|
||||
|
|
@ -105,12 +175,6 @@ async function loadBookmarks(container) {
|
|||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load bookmarks:", error);
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="icon">!</div>
|
||||
<h2>Oops</h2>
|
||||
<p>Failed to load bookmarks</p>
|
||||
</div>
|
||||
`;
|
||||
showError(container);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue