Streambert Watch History Tracking Implementation: A Technical Deep Dive

Streambert persists watch history using a structured localStorage schema that tracks playback progress, completed episodes, and chronological history through four specific keys managed by a centralized storage utility.

Streambert implements a lightweight yet robust watch history tracking system using the browser's localStorage API. The implementation centers around a key registry defined in src/utils/storage.js that coordinates data persistence across the Electron main and renderer processes. This architecture enables real-time progress updates, automatic "watched" status detection, and seamless backup functionality without external database dependencies.

Core Storage Schema and Architecture

The STORAGE_KEYS Registry

All watch-related data keys are centrally declared in src/utils/storage.js (lines 35-50) within the exported STORAGE_KEYS object. This registry prevents key collisions and provides a single source of truth for storage identifiers throughout the application.

// src/utils/storage.js – central key registry
export const STORAGE_KEYS = {
  WATCH_PROGRESS: "progress",
  WATCHED: "watched",
  HISTORY: "history",
  WATCHED_THRESHOLD: "watchedThreshold",
  // …other unrelated keys
};

Data Structure Overview

The system utilizes four primary keys to maintain comprehensive watch state:

  • WATCH_PROGRESS ("progress"): Stores the current playback position in seconds for the active episode
  • WATCHED ("watched"): Maintains an object mapping episode IDs to boolean true values for completed content
  • HISTORY ("history"): Contains a chronological array of episode IDs in reverse order (most recent first)
  • WATCHED_THRESHOLD ("watchedThreshold"): Defines the percentage (default 95%) of an episode that must be viewed to trigger automatic "watched" status

Real-Time Progress Tracking

IPC Communication Flow

When the video player reports a new playback position, the main process sends updates via the "update-progress" IPC channel. According to src/ipc/player.js, the main window emits progress events containing the current percentage and download status:

// src/ipc/player.js – update-progress handler (excerpt)
mw.webContents.send("update-progress", {
  percent,
  label: `Downloading… ${mb} MB ${totalMb}`,
});

The renderer-side listener in src/preload.js forwards these events to the UI layer, enabling the storage utility to persist positions using storage.set(STORAGE_KEYS.WATCH_PROGRESS, currentSeconds).

Automatic Watched Status Detection

When playback reaches the WATCHED_THRESHOLD (default 95% of total duration), Streambert automatically marks the episode as fully watched. The implementation updates both the WATCHED object and the HISTORY array:

// Mark as watched when threshold reached
storage.set(STORAGE_KEYS.WATCHED, {
  ...storage.get(STORAGE_KEYS.WATCHED),
  [episodeId]: true,
});

// Update chronological history
const hist = storage.get(STORAGE_KEYS.HISTORY) || [];
hist.unshift(episodeId);
storage.set(STORAGE_KEYS.HISTORY, hist);

Managing Watch History Data

Retrieving Watch History

To display a "Recently Watched" list, UI components import the storage utility and retrieve the chronological history array. The most recent entries appear at the beginning of the array due to the unshift operation used during updates.

import { storage, STORAGE_KEYS } from "./utils/storage";

// Get the chronological watch history
const history = storage.get(STORAGE_KEYS.HISTORY) || [];

// Show the last 5 entries
history.slice(0, 5).forEach((episodeId) => {
  console.log("Recently watched:", episodeId);
});

Manually Marking Episodes as Watched

Applications can programmatically mark content as watched using the same pattern as the automatic threshold detection:

import { storage, STORAGE_KEYS } from "./utils/storage";

function markAsWatched(episodeId) {
  const watched = storage.get(STORAGE_KEYS.WATCHED) || {};
  watched[episodeId] = true;
  storage.set(STORAGE_KEYS.WATCHED, watched);

  // Also add to history
  const history = storage.get(STORAGE_KEYS.HISTORY) || [];
  history.unshift(episodeId);
  storage.set(STORAGE_KEYS.HISTORY, history);
}

Clearing and Resetting Watch Data

Streambert provides a complete data purge mechanism through the IPC handler clear-watch-data implemented in src/ipc/downloads.js at line 909. This handler iterates through all watch-related keys and removes them from localStorage:

ipcMain.handle("clear-watch-data", async () => {
  for (const key of ["progress", "watched", "history", "watchedThreshold"]) {
    storage.remove(key);
  }
});

The frontend invokes this handler through the preload bridge exposed in src/preload.js:

// src/preload.js – expose clearWatchData to the renderer
clearWatchData: () => ipcRenderer.invoke("clear-watch-data"),

Settings UI components call window.electron.clearWatchData() when users request to clear their history:

// From a Settings component
window.electron.clearWatchData().then(() => {
  alert("Watch history cleared!");
});

Backup and Restore Integration

Watch history survives application reinstalls through the backup system defined in src/utils/backup.js (lines 8-28). This file explicitly includes the watch-related keys—"watched", "progress", and "history"—in the exportable data set, ensuring user progress continuity across devices or application migrations. When users export their Streambert configuration, these keys serialize to JSON and restore cleanly on import.

Summary

  • Centralized key registry: src/utils/storage.js defines STORAGE_KEYS to maintain consistent localStorage identifiers for watch data
  • Real-time IPC updates: The "update-progress" channel in src/ipc/player.js coordinates playback position tracking between main and renderer processes
  • Threshold-based completion: Episodes automatically mark as watched at 95% completion, updating both the watched set and chronological history
  • Complete data management: The clear-watch-data handler in src/ipc/downloads.js provides atomic deletion of all watch-related entries
  • Persistence across installs: src/utils/backup.js includes watch data in export/import operations, ensuring state survival through reinstalls

Frequently Asked Questions

Where does Streambert store watch history data?

Streambert stores all watch history data in the browser's localStorage under specific keys defined in src/utils/storage.js. The data includes playback progress (seconds), watched episode IDs, chronological history arrays, and the completion threshold percentage. This design ensures data persistence without requiring external database infrastructure.

What percentage of an episode must be watched to mark it as complete?

By default, Streambert marks an episode as watched when the user reaches 95% of the total duration. This threshold is configurable via the WATCHED_THRESHOLD key in localStorage, allowing users or developers to adjust the completion criteria between 0-100%.

How can I programmatically clear watch history in Streambert?

Invoke the clear-watch-data IPC handler exposed through the Electron context bridge. The frontend calls window.electron.clearWatchData(), which triggers the handler in src/ipc/downloads.js to delete the "progress", "watched", "history", and "watchedThreshold" keys from localStorage, effectively resetting all watch-related data.

Is watch history included when backing up Streambert data?

Yes. The backup utility in src/utils/backup.js explicitly includes the watch-related keys ("watched", "progress", "history") in the export schema (lines 8-28). This ensures that when users export their settings and data, their watch progress and history serialize to the backup file and restore correctly on import.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →