diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0a450f..d2fbcf2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
All notable changes to YT re:Watch will be documented in this file.
+## [5.0.1] - 2026-08-11
+
+### Fixed
+
+- Rebuilt the compact Continue Watching popup from an unfinished-only, timestamp-sorted projection. Live updates can no longer apply an unfiltered history index to a different visible row, so titles, thumbnails, progress, ordering, and completion removal remain consistent.
+- Deferred regular-video saves briefly during YouTube single-page navigation until the route, watch page, and player agree on the active video ID. This prevents a new record from inheriting a previous video's title or channel metadata.
+- Unified the legacy `overlayColor` and v5 `accentColor` settings. Existing color choices are retained, and popup/feed/content-script updates now use one synchronized value.
+- Applied the saved accent when the full feed opens and made the canonical settings color override stale popup-only cache entries.
+- Kept the YouTube-page dynamic overlay stylesheet after its reinjected base rules, so saved accent colors now apply to Viewed badges and progress lines instead of falling back to blue.
+- Restored lazy page navigation in the popup's Continue Watching list. Its page count now derives from the same unfinished-only, timestamp-sorted records it displays.
+- Pending-new-video notices now exclude discoveries removed by feed retention or no longer eligible through an active local subscription, so **Show** never promises inventory that cannot be displayed.
+- Watch Later saves now recover title and channel metadata through YouTube oEmbed when the current page has not mounted a matching video card. Existing incomplete Watch Later records are repaired when the list opens.
+
+### Added
+
+- Added Watch Later to the full re:Watch page, with newest-first records, Open and Remove actions, live updates, and localized empty/count states.
+
## [5.0.0] - 2026-08-09
Version 5 turns YT re:Watch from a popup-centered history tracker into a full local YouTube companion while preserving its local-first privacy boundary. The release adds explicit local channel subscriptions, an RSS-backed feed, channel and history management, richer analytics, durable import/backup contracts, and matching Chromium/Firefox coverage.
diff --git a/README.md b/README.md
index 98e72bb..7e86c34 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@ The full feed page contains:
| --- | --- |
| **Home** | A locally regenerated mix of cached videos using freshness, watch activity, and local feedback |
| **Subscriptions** | Cached uploads from locally followed channels in chronological order |
+| **Watch Later** | Locally saved videos, newest first |
| **Shorts** | Known short-form videos and watched Shorts |
| **Playlists** | Saved YouTube playlist references that open on YouTube |
| **History** | Locally recorded videos, progress, duration, and watched time |
@@ -47,6 +48,8 @@ The full feed page contains:
Home and Subscriptions render stable 50-card pages as you scroll. Checking for new videos is separate from reloading the current local view, so a background scan does not unexpectedly replace or reorder visible cards. When uploads are found, re:Watch offers a deliberate **Show** action.
+Watch Later is independent of YouTube's account playlist. Right-click a recognized video or Short and choose **Save to Watch Later (local)**, or use a re:Watch video menu; the full-page Watch Later view provides newest-first Open and Remove actions.
+
## Local subscriptions and feed
re:Watch subscriptions are independent from YouTube account subscriptions.
@@ -85,6 +88,7 @@ Direct YouTube requests used by the local feed:
- public channel RSS checks;
- public channel or handle pages when identity or presentation metadata is needed;
- YouTube-hosted thumbnails, avatars, and banners displayed by the UI.
+- YouTube oEmbed metadata only when a locally saved Watch Later item is missing its title or channel.
Feed metadata requests omit browser credentials. Local search does not contact YouTube. The extension does not subscribe, unsubscribe, like, comment, or modify a YouTube account.
diff --git a/build.sh b/build.sh
index 4eaa512..175bc9e 100755
--- a/build.sh
+++ b/build.sh
@@ -77,6 +77,7 @@ copy_common_files() {
"$PROJECT_ROOT/src/feed-playlist-import.js" \
"$PROJECT_ROOT/src/feed-playlists-view.js" \
"$PROJECT_ROOT/src/feed-history-view.js" \
+ "$PROJECT_ROOT/src/feed-watchlater-view.js" \
"$PROJECT_ROOT/src/feed-settings.js" \
"$PROJECT_ROOT/src/feed-localization.js" \
"$PROJECT_ROOT/src/feed-backup.js" \
diff --git a/docs/assets/guide/feed-watch-later.png b/docs/assets/guide/feed-watch-later.png
new file mode 100644
index 0000000..a3aa424
Binary files /dev/null and b/docs/assets/guide/feed-watch-later.png differ
diff --git a/docs/changelog.md b/docs/changelog.md
index 0fccfff..6291915 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,12 @@
# Changelog
+## v5.0.1 — 11 August 2026
+
+- Fixed Continue Watching to use one unfinished-only, timestamp-sorted projection for its rows and popup pagination; live updates no longer mix visible rows with unfiltered history indexes.
+- Restored the saved appearance color across the popup, full re:Watch page, and existing YouTube tabs, including Viewed badges and progress bars.
+- Added the full-page **Watch Later** view, including newest-first ordering, open/remove actions, localization, and automatic repair of incomplete saved title/channel metadata.
+- Made **Show** advertise only subscription discoveries that remain in local inventory after retention and active-subscription filtering.
+
## v5.0.0 — 9 August 2026
v5 turns re:Watch from a local progress tracker into a complete local browsing companion while keeping its account-independent storage model.
diff --git a/docs/detailed_guide.md b/docs/detailed_guide.md
index 08551c7..5015491 100644
--- a/docs/detailed_guide.md
+++ b/docs/detailed_guide.md
@@ -27,6 +27,7 @@ The toolbar popup is a compact resume surface. The full-page interface contains
| Home | Locally arranged videos from followed channels |
| Subscriptions | Complete chronological cached subscription inventory |
| Shorts | Locally watched YouTube Shorts |
+| Watch Later | Videos explicitly saved for later in this browser profile |
| Playlists | References that open the original YouTube playlist |
| History | Ordinary watched videos and progress |
| Channels | Local follows and, when present, ignored import records |
@@ -35,10 +36,9 @@ The toolbar popup is a compact resume surface. The full-page interface contains
### Popup { #popup }
-
- { width="600" height="480" }
- Resume unfinished videos or open the full re:Watch interface.
-
+
+
+*Resume unfinished videos or open the full re:Watch interface.*
The popup also reports subscription-import results. If an import skipped previously removed channels, its action opens **Channels → Ignored** so you can review them.
@@ -46,10 +46,9 @@ The popup also reports subscription-import results. If an import skipped previou
### Home { #home }
-
- { width="1440" height="960" loading="lazy" }
- Home arranges cached uploads using local viewing and feedback signals.
-
+
+
+*Home arranges cached uploads using local viewing and feedback signals.*
Home is not a copy of the YouTube recommendation service. It ranks locally cached uploads from channels followed in re:Watch. Opening Home regenerates that local view and does not start a Home-owned network request.
@@ -57,10 +56,9 @@ Home uses stable 50-card pages. Moving between pages does not duplicate cards or
### Subscriptions { #subscriptions }
-
- { width="1440" height="960" loading="lazy" }
- Subscriptions lists cached uploads in chronological order.
-
+
+
+*Subscriptions lists cached uploads in chronological order.*
Subscriptions is the complete chronological inventory of regular cached uploads. It also uses stable 50-card pages.
@@ -84,10 +82,9 @@ Video menus provide local actions such as more or less from a channel, hide, sub
### History { #history }
-
- { width="1440" height="960" loading="lazy" }
- History keeps ordinary viewing activity and resume progress local.
-
+
+
+*History keeps ordinary viewing activity and resume progress local.*
History cards show the available channel, progress, and video duration. When metadata or progress changes, re:Watch updates the video-specific portion of the card while preserving its **Remove** control and three-dot menu.
@@ -95,19 +92,17 @@ Removing a history record also creates a temporary deletion marker so an older a
### Shorts { #shorts }
-
- { width="1440" height="960" loading="lazy" }
- Shorts separates locally watched short-form videos from ordinary history.
-
+
+
+*Shorts separates locally watched short-form videos from ordinary history.*
re:Watch follows Shorts navigation inside YouTube's single-page interface and records the active Short's video and channel identity. The Shorts tab updates from local history without requiring a feed reload.
## Playlist references { #playlists }
-
- { width="1440" height="960" loading="lazy" }
- A saved reference opens its original playlist on YouTube.
-
+
+
+*A saved reference opens its original playlist on YouTube.*
v5 stores YouTube playlists as references with available title, artwork, and source link. It does not fetch the playlist's member videos in the background.
@@ -115,12 +110,21 @@ The per-playlist **Ignore videos** toggle prevents history saves while viewing t
Creating and managing extension-owned local playlists is planned separately and is not part of stable v5.
+## Watch Later { #watch-later }
+
+
+
+*Watch Later keeps explicitly saved videos in a local, newest-first list.*
+
+Watch Later is a small local list, separate from YouTube's account-based Watch Later playlist. Save a recognized video or Short by right-clicking it on YouTube and choosing **Save to Watch Later (local)**, or choose **Save to Watch Later** from a re:Watch card menu.
+
+The **Watch Later** sidebar view orders saved videos newest first. Each row opens the original YouTube video and has a **Remove** action. re:Watch stores the video ID, link, title, and channel locally; if a page did not expose title or channel data when it was saved, the list repairs that metadata when it is next opened.
+
## Channels { #channels }
-
- { width="1440" height="960" loading="lazy" }
- Channels manages follows owned by re:Watch, not by the YouTube account.
-
+
+
+*Channels manages follows owned by re:Watch, not by the YouTube account.*
Follow a channel from a supported YouTube channel/watch surface, a re:Watch video menu, or the Channels controls. You can also import subscriptions in Settings. re:Watch canonicalizes channel IDs and avoids duplicate follows.
@@ -137,10 +141,9 @@ When no tombstones exist, the Ignored tab is hidden instead of showing an empty
## Analytics { #analytics }
-
- { width="1440" height="960" loading="lazy" }
- Analytics derives viewing patterns from local extension data.
-
+
+
+*Analytics derives viewing patterns from local extension data.*
Analytics includes total watch time, videos and Shorts watched, average duration, completion rate, saved playlist references, weekly activity, and watch time by hour. Hourly bars share a consistent baseline so selected or low-activity hours remain visually comparable.
@@ -148,10 +151,9 @@ Additional insights include unfinished videos and skipped, watched, and completi
## Settings { #settings }
-
- { width="1440" height="960" loading="lazy" }
- Settings contains appearance, import, backup, and data-management controls.
-
+
+
+*Settings contains appearance, import, backup, and data-management controls.*
### Appearance and overlays
diff --git a/docs/index.md b/docs/index.md
index b217d5a..70911a8 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -13,6 +13,7 @@ YT re:Watch keeps a private, account-independent YouTube history in your browser
| Home | Builds a mixed local feed from followed channels |
| Subscriptions | Shows a chronological inventory of cached subscription videos |
| Shorts | Separates watched Shorts from ordinary history |
+| Watch Later | Keeps videos explicitly saved for later, independently of a YouTube account |
| Channels | Manages local follows and reviewable ignored-channel records |
| Analytics | Summarizes local activity, watch time, completion, and channel patterns |
| Playlist references | Saves links to YouTube playlists without importing their members |
@@ -26,7 +27,7 @@ The feed's Home and Subscriptions views use stable 50-card pages. Search is loca
2. Watch a video. re:Watch records meaningful playback and updates the local resume point.
3. Follow channels from supported YouTube surfaces, add them in **Channels**, or import a subscriptions file in **Settings**.
-Click the extension button for quick actions. Open the full re:Watch page for Home, Subscriptions, Shorts, playlist references, History, Channels, Analytics, and Settings.
+Click the extension button for quick actions. Open the full re:Watch page for Home, Subscriptions, Shorts, Watch Later, playlist references, History, Channels, Analytics, and Settings.
## Feed refresh controls
@@ -48,6 +49,10 @@ When an imported channel was previously removed, re:Watch keeps a tombstone so l
v5 saves YouTube playlists as outbound references: title, available metadata, and the original YouTube link. It does not hydrate playlist members in the background and does not yet provide extension-managed local playlists.
+## Watch Later
+
+Right-click a recognized YouTube video or Short and choose **Save to Watch Later (local)**, or use **Save to Watch Later** from a re:Watch video menu. The **Watch Later** sidebar view lists these local saves newest first and provides Open and Remove actions. This list is independent of YouTube's account-based Watch Later playlist.
+
## Privacy boundaries
History, progress, settings, local subscriptions, feed state, and analytics remain in extension storage in the current browser profile. re:Watch has no account system or cloud-sync service.
diff --git a/helpers/chrome-marketplace-v5.txt b/helpers/chrome-marketplace-v5.txt
index 883883e..cffeca0 100644
--- a/helpers/chrome-marketplace-v5.txt
+++ b/helpers/chrome-marketplace-v5.txt
@@ -58,6 +58,14 @@ Version 5 introduces the full local feed experience: local channel subscriptions
It also improves SPA resume and Shorts identity tracking, keeps History card actions stable during metadata updates, shows available video durations, and makes feed scan, reload, and chronological-inventory actions explicit.
+PROMOTIONAL ASSET
+
+chrome_small_promo_tile.png
+Small promo tile: 440 x 280 px.
+
+chrome_marquee_promo_tile.png
+Marquee promo tile: 1400 x 560 px.
+
SCREENSHOT UPLOAD ORDER AND CAPTIONS
1. chrome_home.png
@@ -83,6 +91,8 @@ Data handling: Extension feature data is stored locally in the browser profile.
Host access: Required for YouTube content-script integration and public channel feed/metadata retrieval. Direct feed and metadata requests use credentials omitted.
+Context menus: Required to add user-invoked re:Watch actions to YouTube's right-click menu. A user can explicitly save the selected YouTube video to the extension's local Watch Later list or locally follow or unfollow the selected channel. These actions run only when the user chooses the corresponding re:Watch menu item.
+
Remote code: None.
Authentication: No OAuth or re:Watch account in version 5.
diff --git a/package-lock.json b/package-lock.json
index 91ec600..64d0c54 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "youtube-local-history",
- "version": "5.0.0",
+ "version": "5.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "youtube-local-history",
- "version": "5.0.0",
+ "version": "5.0.1",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.24.0",
diff --git a/package.json b/package.json
index b5b3c43..9056cb9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "youtube-local-history",
- "version": "5.0.0",
+ "version": "5.0.1",
"description": "Private local YouTube history, progress tracking, channel subscriptions, analytics, and an in-browser feed.",
"main": "src/content.js",
"scripts": {
diff --git a/scripts/docs-screenshot-catalog.json b/scripts/docs-screenshot-catalog.json
index ab33f24..3a29c96 100644
--- a/scripts/docs-screenshot-catalog.json
+++ b/scripts/docs-screenshot-catalog.json
@@ -92,6 +92,20 @@
"alt": "The re:Watch History tab listing locally stored viewing activity and progress.",
"caption": "History provides a dedicated view of locally recorded viewing activity."
},
+ {
+ "id": "feed-watch-later",
+ "page": "feed.html",
+ "view": "feed-watch-later",
+ "output": "docs/assets/guide/feed-watch-later.png",
+ "guidePage": "detailed_guide.md",
+ "guideAnchor": "watch-later",
+ "viewport": { "width": 1440, "height": 960 },
+ "capture": { "type": "viewport" },
+ "readySelector": "#watchLaterList .history-row",
+ "display": { "width": 1440, "height": 960 },
+ "alt": "The re:Watch Watch Later tab showing locally saved videos.",
+ "caption": "Watch Later keeps explicitly saved videos in a local, newest-first list."
+ },
{
"id": "feed-channels",
"page": "feed.html",
diff --git a/scripts/generate-docs-screenshots.js b/scripts/generate-docs-screenshots.js
index 9feb21d..9e195c4 100644
--- a/scripts/generate-docs-screenshots.js
+++ b/scripts/generate-docs-screenshots.js
@@ -269,6 +269,7 @@ async function activateView(page, entry) {
'feed-shorts': '#navShorts',
'feed-playlists': '#navPlaylists',
'feed-history': '#navHistory',
+ 'feed-watch-later': '#navWatchLater',
'feed-channels': '#manage',
'feed-analytics': '#analyticsToggle',
'feed-settings': '#navSettings',
diff --git a/scripts/generate-marketplace-screenshots.js b/scripts/generate-marketplace-screenshots.js
index 95f5608..6e17e62 100644
--- a/scripts/generate-marketplace-screenshots.js
+++ b/scripts/generate-marketplace-screenshots.js
@@ -134,15 +134,18 @@ async function seedInExtensionPage(pageEvaluate, fixture) {
});
}
-function assertPng(file) {
+function assertPng(file, expectedWidth = WIDTH, expectedHeight = HEIGHT, requireOpaque = false) {
const data = fs.readFileSync(file);
if (data.length < 24 || data.toString('ascii', 1, 4) !== 'PNG') {
throw new Error(`Screenshot is not a PNG: ${file}`);
}
const width = data.readUInt32BE(16);
const height = data.readUInt32BE(20);
- if (width !== WIDTH || height !== HEIGHT) {
- throw new Error(`${path.basename(file)} is ${width}x${height}; expected ${WIDTH}x${HEIGHT}`);
+ if (width !== expectedWidth || height !== expectedHeight) {
+ throw new Error(`${path.basename(file)} is ${width}x${height}; expected ${expectedWidth}x${expectedHeight}`);
+ }
+ if (requireOpaque && (data.readUInt8(24) !== 8 || data.readUInt8(25) !== 2)) {
+ throw new Error(`${path.basename(file)} must be an opaque 24-bit PNG`);
}
}
@@ -159,6 +162,110 @@ async function waitForChromeImages(page) {
.every((image) => image.complete && image.naturalWidth > 0), null, { timeout: 10000 });
}
+function promoDestination(name) {
+ const file = path.join(OUTPUT_DIR, `chrome_${name}.png`);
+ const expectedRoot = `${OUTPUT_DIR}${path.sep}`;
+ if (!file.startsWith(expectedRoot)) throw new Error('Unsafe Chrome promotional asset destination');
+ return file;
+}
+
+function promoDocument(body, styles) {
+ return `
+
+