Add "not visited in x days" as an option
This commit is contained in:
parent
537cc1f724
commit
5cf6f68d61
7 changed files with 58 additions and 9 deletions
|
|
@ -11,9 +11,10 @@ A Firefox extension that surfaces your forgotten bookmarks — the ones you save
|
|||
## Features
|
||||
|
||||
- **Discover forgotten bookmarks** — Shows bookmarks you've rarely or never visited
|
||||
- **Stale bookmark detection** — Find bookmarks you visited a few times long ago but haven't opened in months or years
|
||||
- **Click to open** — Just click any bookmark to visit it
|
||||
- **Refresh behavior** — Choose to see new bookmarks every time, once a day, or only when you manually refresh
|
||||
- **Configurable criteria** — Set maximum visit count and minimum age for "forgotten" status
|
||||
- **Configurable criteria** — Set maximum visit count, minimum age, and "not visited in X days" threshold
|
||||
- **Exclude folders** — Keep certain bookmark folders out of suggestions
|
||||
|
||||
## Screenshots
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const DEFAULT_SETTINGS = {
|
|||
numBookmarks: 5,
|
||||
maxVisitCount: 2, // Consider "forgotten" if visited 2 or fewer times
|
||||
minAgeDays: 7, // Only show bookmarks older than 7 days
|
||||
notVisitedInDays: 0, // Consider "forgotten" if not visited in X days (0 = disabled)
|
||||
refreshBehavior: "always", // "always", "daily", or "manual"
|
||||
};
|
||||
|
||||
|
|
@ -96,13 +97,18 @@ async function getAllBookmarks(excludedFolderIds = []) {
|
|||
return bookmarks;
|
||||
}
|
||||
|
||||
// Get visit count for a URL
|
||||
async function getVisitCount(url) {
|
||||
// Get visit count and last visit time for a URL
|
||||
async function getVisitInfo(url) {
|
||||
try {
|
||||
const visits = await browser.history.getVisits({ url });
|
||||
return visits.length;
|
||||
const lastVisitTime =
|
||||
visits.length > 0 ? Math.max(...visits.map((v) => v.visitTime)) : null;
|
||||
return {
|
||||
visitCount: visits.length,
|
||||
lastVisitTime: lastVisitTime,
|
||||
};
|
||||
} catch (e) {
|
||||
return 0;
|
||||
return { visitCount: 0, lastVisitTime: null };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +122,7 @@ async function fetchFreshBookmarks() {
|
|||
|
||||
// Filter by age and get visit counts
|
||||
const candidates = [];
|
||||
const notVisitedInMs = settings.notVisitedInDays * 24 * 60 * 60 * 1000;
|
||||
|
||||
for (const bookmark of bookmarks) {
|
||||
// Skip if too new
|
||||
|
|
@ -131,16 +138,29 @@ async function fetchFreshBookmarks() {
|
|||
continue;
|
||||
}
|
||||
|
||||
const visitCount = await getVisitCount(bookmark.url);
|
||||
const { visitCount, lastVisitTime } = await getVisitInfo(bookmark.url);
|
||||
|
||||
if (visitCount <= settings.maxVisitCount) {
|
||||
// Check if bookmark qualifies as "forgotten"
|
||||
// Either: low visit count OR hasn't been visited in X days (if enabled)
|
||||
const isLowVisitCount = visitCount <= settings.maxVisitCount;
|
||||
const isStale =
|
||||
settings.notVisitedInDays > 0 &&
|
||||
(lastVisitTime === null || now - lastVisitTime > notVisitedInMs);
|
||||
|
||||
if (isLowVisitCount || isStale) {
|
||||
// Check if dateAdded is valid (not corrupted/too old)
|
||||
const hasValidDate =
|
||||
bookmark.dateAdded && bookmark.dateAdded >= MIN_VALID_TIMESTAMP;
|
||||
|
||||
const daysSinceLastVisit = lastVisitTime
|
||||
? Math.floor((now - lastVisitTime) / (24 * 60 * 60 * 1000))
|
||||
: null;
|
||||
|
||||
candidates.push({
|
||||
...bookmark,
|
||||
visitCount,
|
||||
lastVisitTime,
|
||||
daysSinceLastVisit,
|
||||
daysSinceAdded: hasValidDate
|
||||
? Math.floor((now - bookmark.dateAdded) / (24 * 60 * 60 * 1000))
|
||||
: null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Embermarks",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"description": "Rediscover your forgotten bookmarks. Surface the ones you never visit.",
|
||||
"author": "Bastian Gruber",
|
||||
"homepage_url": "https://github.com/gruberb/embermarks",
|
||||
|
|
|
|||
|
|
@ -277,6 +277,23 @@
|
|||
value="7"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="setting-row">
|
||||
<div class="setting-label">
|
||||
Not visited in (days)
|
||||
<span
|
||||
>Also show bookmarks not visited in this many days,
|
||||
even if visited before (0 = disabled)</span
|
||||
>
|
||||
</div>
|
||||
<input
|
||||
type="number"
|
||||
id="notVisitedInDays"
|
||||
min="0"
|
||||
max="3650"
|
||||
value="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
const refreshBehaviorSelect = document.getElementById("refreshBehavior");
|
||||
const maxVisitCountInput = document.getElementById("maxVisitCount");
|
||||
const minAgeDaysInput = document.getElementById("minAgeDays");
|
||||
const notVisitedInDaysInput = document.getElementById("notVisitedInDays");
|
||||
const folderList = document.getElementById("folderList");
|
||||
const saveBtn = document.getElementById("saveBtn");
|
||||
const saveStatus = document.getElementById("saveStatus");
|
||||
|
|
@ -16,6 +17,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
refreshBehaviorSelect.value = settings.refreshBehavior || "always";
|
||||
maxVisitCountInput.value = settings.maxVisitCount;
|
||||
minAgeDaysInput.value = settings.minAgeDays;
|
||||
notVisitedInDaysInput.value = settings.notVisitedInDays || 0;
|
||||
|
||||
// Load folder list
|
||||
const folders = await browser.runtime.sendMessage({
|
||||
|
|
@ -60,6 +62,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
refreshBehavior: refreshBehaviorSelect.value,
|
||||
maxVisitCount: parseInt(maxVisitCountInput.value, 10),
|
||||
minAgeDays: parseInt(minAgeDaysInput.value, 10),
|
||||
notVisitedInDays: parseInt(notVisitedInDaysInput.value, 10),
|
||||
excludedFolders,
|
||||
};
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 KiB |
10
shared/ui.js
10
shared/ui.js
|
|
@ -55,7 +55,15 @@ function createBookmarkCard(bookmark) {
|
|||
meta.className = "bookmark-meta";
|
||||
const visitText =
|
||||
bookmark.visitCount === 1 ? "1 visit" : `${bookmark.visitCount} visits`;
|
||||
meta.textContent = `${visitText} · Added ${formatDaysAgo(bookmark.daysSinceAdded)}`;
|
||||
|
||||
let metaText = `${visitText} · Added ${formatDaysAgo(bookmark.daysSinceAdded)}`;
|
||||
|
||||
// Show last visited info if the bookmark has been visited
|
||||
if (bookmark.daysSinceLastVisit !== null && bookmark.visitCount > 0) {
|
||||
metaText += ` · Last visit ${formatDaysAgo(bookmark.daysSinceLastVisit)}`;
|
||||
}
|
||||
|
||||
meta.textContent = metaText;
|
||||
|
||||
info.appendChild(title);
|
||||
info.appendChild(meta);
|
||||
|
|
|
|||
Loading…
Reference in a new issue