YourSelfLearning is an educational intervention browser extension that transforms social media scrolling into learning opportunities. This Phase 1 implementation provides the core tracking functionality that monitors user behavior on social media platforms (TikTok, Instagram, YouTube Shorts) and tracks scrolling actions and time spent, organizing data into 8-hour intervals for daily analysis.
-
Storage Structure & Time Period Utilities
- TypeScript interfaces for data organization (
src/types/storage.ts) - 8-hour period calculations (morning: 0-8, afternoon: 8-16, night: 16-24) (
src/utils/time-periods.ts) - Atomic storage operations with race condition prevention (
src/entrypoints/content/storage-utils.ts)
- TypeScript interfaces for data organization (
-
Background Script for Tab Coordination
- Service worker managing timer state across multiple tabs (
src/entrypoints/background.ts) - Platform detection for TikTok, Instagram, and YouTube Shorts
- Message passing coordination between background and content scripts
- Window focus/blur handling
- Service worker managing timer state across multiple tabs (
-
Scroll Detection with Cooldown
- Mouse wheel event detection for downward scrolling
- Keyboard event detection for down arrow key
- 2-second cooldown timer to prevent overcounting
- Anti-spam protection for rapid scroll events
-
Time Tracking System
- Second-by-second time tracking when on tracked platforms
- Automatic start/stop based on tab activity
- Pause/resume on page visibility changes
- Proper cleanup on page unload
-
Race Condition Prevention
- Atomic storage operations using browser storage API
- Simple mutex locking mechanism
- Data validation and error recovery
- Concurrent access handling across multiple tabs
src/
├── entrypoints/
│ ├── background.ts # Service worker for tab coordination
│ ├── content.ts # Core script for user interaction tracking
│ ├── content/
│ │ └── storage-utils.ts # Storage management utilities
│ └── popup/ # Extension popup (existing)
├── types/
│ └── storage.ts # TypeScript interfaces
├── utils/
│ └── time-periods.ts # Time period calculation utilities
└── wxt.config.ts # Configuration for storage and activeTab
The extension stores data in browser local storage with the following structure:
{
today: {
morning: { scrollCount: number, timeWasted: number },
afternoon: { scrollCount: number, timeWasted: number },
night: { scrollCount: number, timeWasted: number },
date: string
},
yesterday: { /* same structure */ },
settings: {
enabledSites: string[],
lessonFrequency: number,
frequencyMode: 'scrolls' | 'time'
}
}Phase 2 implements an educational intervention system that displays quiz lessons when users reach scroll thresholds on tracked social media platforms. The system features a three-state UI progression (lesson-begin → lesson-choice-selected → lesson-after-countdown) that temporarily interrupts browsing to present educational content.
-
Extended Storage System
- Added lesson tracking fields:
lessonCount,nextLessonAt,lessonActive - Updated storage initialization and daily rollover logic
- Implemented lesson state management methods in
StorageUtils - Modified lesson frequency from 10 to 3 scrolls (as specified)
- Added lesson tracking fields:
-
Lesson Parser Utility (
src/utils/lesson-parser.ts)- TSV parsing for lesson content from
public/lessons/how-to-control.tsv - Random lesson selection with answer shuffling
- Support for question, correct answer, wrong answer, explanation, and reference fields
- Error handling for malformed content
- TSV parsing for lesson content from
-
Lesson Overlay Component (
src/entrypoints/content/lesson-overlay.ts)- Three-state UI progression: BEGIN → CHOICE_SELECTED → AFTER_COUNTDOWN
- Visual feedback with green/red highlighting for correct/incorrect answers
- Confetti animation for correct answers
- 5-second countdown before close button activation
- Responsive design with smooth animations
-
Lesson Manager (
src/entrypoints/content/lesson-manager.ts)- Coordinates lesson display with scroll tracking
- Page state management (freeze/unfreeze during lessons)
- Audio muting and scroll/keyboard disabling during lessons
- Direct trigger check after scroll increment (storage listener removed to avoid race conditions)
- Proper cleanup and state restoration
-
Content Script Integration
- Lesson active checks prevent scroll/time tracking during lessons
- Integrated lesson manager with existing tracking system
- Multi-tab independence (lessons don't interfere across tabs)
- Event listener management during lesson display
-
Background Script Coordination
- Added lesson state tracking per tab (
hasActiveLessonfield) - Timer pause/resume coordination during lessons
- Message handling for
LESSON_STARTEDandLESSON_ENDEDevents - Prevents timer conflicts when lessons are active
- Added lesson state tracking per tab (
-
Lesson Styles (inline in
lesson-overlay.ts)- All overlay styles are inline to avoid CSS injection conflicts
- Centered white panel, button states, and confetti animations included
- Mobile-responsive layout
src/
├── entrypoints/
│ ├── background.ts # Extended with lesson state coordination
│ ├── content.ts # Integrated with lesson system
│ └── content/
│ ├── lesson-overlay.ts # Three-state lesson UI component (with inline styles)
│ ├── lesson-manager.ts # Lesson display coordination
│ └── storage-utils.ts # Extended with lesson tracking, simplified methods
├── types/
│ └── storage.ts # Extended with lesson fields
└── utils/
├── browser-api.ts # Centralized cross-browser API compatibility
├── lesson-parser.ts # TSV parsing and lesson management
└── time-periods.ts # Existing time utilities
public/
└── lessons/
└── how-to-control.tsv # Sample lesson content (10 lessons)
The storage structure now includes lesson tracking:
{
today: {
morning: { scrollCount: number, timeWasted: number, lessonCount: number },
afternoon: { scrollCount: number, timeWasted: number, lessonCount: number },
night: { scrollCount: number, timeWasted: number, lessonCount: number },
date: string
},
yesterday: { /* same structure */ },
settings: {
enabledSites: string[],
lessonFrequency: 3, // Triggers every 3 scrolls
frequencyMode: 'scrolls'
},
nextLessonAt: number, // Next scroll count to trigger lesson
lessonActive: boolean // Prevents tracking when lesson displayed
}- Lessons trigger every 3 scrolls (configurable via
lessonFrequency) - Storage listener automatically detects when threshold is reached
- Prevents multiple simultaneous lessons per tab
- BEGIN: Display question with two randomized answer buttons
- CHOICE_SELECTED: Show visual feedback (green/red), confetti for correct answers, explanation text, and start 5-second countdown
- AFTER_COUNTDOWN: Enable close button, allow lesson dismissal
- Freeze Page: Mute audio/video, disable scrolling, block arrow keys
- Tracking Pause: Stop scroll and time counting during lessons
- Multi-tab Independence: Each tab manages lessons independently
- Restore State: Unmute audio, re-enable interactions after lesson
- Mobile-friendly layout with appropriate sizing
- Smooth animations and transitions
- High z-index ensures overlay appears above all content
- Accessible button states and visual feedback
Phase 2.1 focused on reducing codebase complexity and removing redundant components to create a cleaner, more maintainable architecture for future development phases.
-
Removed Redundant CSS System
- Deleted
src/entrypoints/style.css(empty/unused file) - All styles now inline in
lesson-overlay.tsfor better compatibility - Removed unused CSS import from
content.ts
- Deleted
-
Centralized Browser API Compatibility
- Created
src/utils/browser-api.tswith single browser fallback - Replaced 6+ individual browser API fallback declarations across files
- Improved code maintainability and reduced duplication
- Created
-
Storage Utils Simplification
- Consolidated
getTotalScrollCount(),getTotalTimeWasted(),getTotalLessonCount()into singlegetTotals()method - Simplified
incrementLessonCount()calculation logic - Removed excessive debug logging from storage operations
- Consolidated
-
Lesson Manager Optimization
- Removed redundant state checks and verbose logging
- Consolidated media muting logic
- Simplified initialization and error handling
-
Content Script Optimization
- Cleaned up timer management logging
- Simplified event listener setup
- Removed verbose debug output
Phase 3 implements the primary user interface for the YourSelfLearning browser extension, providing users with a visual dashboard that displays their scrolling metrics, time wasted, and lessons completed. The interface features a minimalist black-and-white design with three metric slots styled like casino slot machines, a brain battery indicator showing remaining cognitive capacity, a reset timer countdown, and navigation to placeholder pages.
-
Extended Storage System with Brain Battery
StorageDatanow includes a numericbrainBatteryfield- Battery is updated via
StorageUtils.incrementTimeWasted(),incrementScrollCount(),incrementLessonCount(), andincrementBrainBattery() - Daily rollover resets
brainBatteryto 100% at midnight - Tracking pauses at 0% battery (time/scroll increments and lesson triggers are blocked until recovery)
-
Utility Functions for UI Formatting
- Created
formatters.tswith time, scroll count, and lesson count formatting - Implemented
getTimeUntilMidnight()for reset timer countdown - Added proper time format switching ("Xm Ys" → "Xhr Ym" after 1 hour)
- Implemented clean metric value highlighting in place of emoji images
- Created
-
Casino Slot Machine UI Components
- Built
MetricSlot.tsxwith slot machine styling (black borders, white background) - Replaced emoji containers with prominent metric value display
- Implemented consistent 120px × 160px slot dimensions
- Added proper spacing and visual hierarchy with inset shadows
- Built
-
Brain Battery Indicator with Tooltip
BrainBattery.tsxdisplays percentage and shows calculation parameters in a tooltip- Color-coded progress bar (green > 60%, orange 20-60%, red < 20%)
- Storage-driven updates: -1.0%/min time, -0.2%/scroll, +0.5%/lesson
- Tooltip documents base recharge: +0.5% per minute when away from tracked sites
-
Real-time UI Updates and Navigation
- Built
ResetTimer.tsxwith live countdown to midnight reset - Created
NavigationBar.tsxwith placeholder functionality for future pages - Implemented storage change listeners for instant UI updates
- UI stays in sync reactively via storage change events (no periodic recalculation in UI)
- Built
-
Main App Integration
- Replaced template
App.tsxwith complete Phase 3 implementation - Added React hooks for state management and storage listeners
- Implemented proper cleanup and memory leak prevention
- Popup container sized to 480px × 550px
- Replaced template
-
Wireframe Layout Adjustments
- Repositioned reset timer to top-left corner; brain battery to top-right corner
- Compacted brain battery UI (24px icon, ~60px bar), right-aligned tooltip
- Reduced vertical spacing between metric slots and navigation bar
- Updated component positioning to match wireframe specifications
-
Tooltip System Reorganization
- ResetTimer tooltip simplified to show all three time periods (Morning 12AM–8AM, Afternoon 8AM–4PM, Evening 4PM–12AM), with the current period bolded
- MetricSlot components now include hover tooltips with session breakdowns: "Morning + Afternoon + Night = Total"
- Session data logic centralized in
App.tsx; tooltips update in real time - Time tooltip values use clean HH:MM:SS formatting (e.g.,
00:02:03) viaformatTimeClean() - Explicit single-period bolding guarantee with
isCurrentTimePeriod()helper
-
Brain Battery Pause/Resume + Base Recharge
- All tracking operations pause when battery reaches 0% (scroll, time, and lesson triggering); lessons can still recharge
- Base recharge handled in content script: +0.5% per minute when timer is not running (i.e., away from tracked sites)
- 100% cap enforced; tooltip documents recharge rule
src/
├── entrypoints/
│ ├── background.ts # Service worker for tab/timer coordination during tracked usage
│ ├── content.ts # Content script: scroll/time tracking, lesson integration, base recharge
│ ├── content/
│ │ ├── storage-utils.ts # Extended with brain battery methods
│ │ ├── lesson-manager.ts # Lesson coordination (unchanged)
│ │ └── lesson-overlay.ts # UI component (unchanged)
│ └── popup/
│ ├── App.tsx # Complete Phase 3 main UI
│ ├── index.html # Popup frame (base 480×450 viewport) and bootstrapping
│ ├── components/
│ │ ├── MetricSlot.tsx # Casino slot display + session tooltips
│ │ ├── BrainBattery.tsx # Battery indicator + base recharge tooltip
│ │ ├── ResetTimer.tsx # Midnight countdown + static period tooltip
│ │ └── NavigationBar.tsx # Bottom navigation bar
│ └── utils/
│ └── formatters.ts # Time and metric formatting utilities
├── types/
│ └── storage.ts # Extended with BrainBatteryState
└── utils/
├── browser-api.ts # Browser compatibility (unchanged)
├── lesson-parser.ts # TSV parsing (unchanged)
└── time-periods.ts # Time utilities (unchanged)
The brain battery implements a gamified cognitive capacity system:
// Battery drains with usage:
- Time drain: 1.0 unit per minute of browsing
- Scroll drain: 0.2 units per scroll action
// Battery recharges with learning:
+ Lesson recharge: 0.5 unit per completed lesson
// Daily reset: 100% at midnightPhase 4 implements date selection functionality allowing users to view their daily metrics for both "Today" and "Yesterday". This builds on the existing Phase 3 UI by adding a toggle component above the metric slots and modifying the display logic to show historical data. The implementation maintains all existing functionality while providing users with comparison capabilities between their current and previous day's performance.
-
Date Selector Component (
src/entrypoints/popup/components/DateSelector.tsx)- Clean toggle UI with "Today" and "Yesterday" buttons
- Casino slot styling matching existing aesthetic (black border, white background)
- Active state highlighting with darker background (#e0e0e0)
- Smooth 0.2s transition animations between states
- Hover effects for inactive buttons (#f5f5f5)
-
Extended Storage Utils (
src/entrypoints/content/storage-utils.ts)- Added
getTotalsByDate(date: 'today' | 'yesterday')method for date-aware queries - Added
getDataByDate(date: 'today' | 'yesterday')for retrieving full daily data - Graceful fallback for missing yesterday data (returns zeros)
- Maintains backward compatibility with existing
getTotals()method
- Added
-
App State Management (
src/entrypoints/popup/App.tsx)- Single
selectedDatestate variable managing date selection loadDataForDate()function for fetching date-specific metrics- Real-time updates only apply to "today" selection
- Brain battery and reset timer remain "today" only features
- Integrated DateSelector component above metric slots
- Single
-
Updated MetricSlot Component (
src/entrypoints/popup/components/MetricSlot.tsx)- Accepts
selectedDateprop for context-aware display - Tooltips show "Today's Sessions" or "Yesterday's Sessions" headers
- "No data available for yesterday" message when appropriate
- Maintains consistent metric value display formatting for both dates
- Preserves all existing styling and animations
- Accepts
-
Brain Fried State Logic
- "BRAIN FRIED!" message only shows for "today" with 0% battery
- Yesterday view always shows normal metric slots regardless of battery
- Consistent user experience across date selections
src/
├── entrypoints/
│ ├── background.ts # No changes needed
│ ├── content.ts # Fixed TypeScript errors in catch blocks
│ ├── content/
│ │ ├── storage-utils.ts # Extended with date-aware methods
│ │ ├── lesson-manager.ts # No changes needed
│ │ └── lesson-overlay.ts # No changes needed
│ └── popup/
│ ├── App.tsx # Added date selection state management
│ ├── components/
│ │ ├── DateSelector.tsx # NEW: Date toggle component
│ │ ├── MetricSlot.tsx # Updated with selectedDate prop
│ │ ├── BrainBattery.tsx # No changes needed
│ │ ├── ResetTimer.tsx # No changes needed
│ │ └── NavigationBar.tsx # No changes needed
│ └── utils/
│ └── formatters.ts # No changes needed
├── types/
│ └── storage.ts # No changes needed
└── utils/
├── browser-api.ts # No changes needed
├── lesson-parser.ts # No changes needed
└── time-periods.ts # No changes needed
Phase 5 implements a comprehensive Settings page that allows users to configure lesson frequency and platform selection. The Settings page seamlessly integrates with the existing navigation system, providing real-time configuration options while maintaining the consistent black-and-white casino aesthetic. This implementation introduces proper page routing between Home and Settings pages while preserving all existing functionality from previous phases.
-
Page Routing Infrastructure
- Modified App.tsx to handle page navigation state management
- Implemented conditional rendering between HomePage, SettingsPage, and Library placeholder
- Created smooth transitions between pages with proper state preservation
- Brain battery remains always visible and updates in real-time across all pages
-
HomePage Component Extraction
- Extracted existing main UI logic from App.tsx into dedicated HomePage component
- Maintained all existing functionality including DateSelector, MetricSlots, BrainBattery, and ResetTimer
- Preserved real-time storage listeners and "BRAIN FRIED" state logic
- Proper prop passing for brain battery percentage from App component
-
Enhanced Navigation Bar System
- Updated NavigationBar to accept currentPage and onNavigate props
- Navigation correctly highlights active page with visual feedback
- Settings and Home navigation fully functional, Library remains placeholder
- Proper event handling and state management integration
-
Settings Page Layout & Design
- Created SettingsPage with professional header and two main sections
- Implemented loading states and error handling for storage operations
- Container sized appropriately (480px × 490px accounting for navigation bar)
- Consistent typography and spacing matching existing design system
-
Lesson Frequency Selector Component
- Three pill-shaped option buttons: Often (1-3), Sometimes (4-6), Barely (7-9)
- Casino aesthetic with black borders, white backgrounds, and active state highlighting
- Smooth hover effects and visual feedback on selection changes
- Real-time storage updates with immediate application to lesson trigger system
-
Platform Selector with Horizontal Scrolling
- Multi-selection interface for Instagram, TikTok, and YouTube platforms
- Horizontal scrolling navigation with left/right arrow controls
- Platform cards with SVG icons, selection indicators, and proper hover states
- Arrow states properly disabled at scroll boundaries for intuitive navigation
-
Extended Storage Utilities
- Enhanced updateSettings method to recalculate nextLessonAt when frequency changes
- Proper atomic storage operations with existing lock mechanism
- Real-time synchronization ensures settings apply immediately across all extension contexts
- Maintains backward compatibility with existing storage structure
-
Platform Icon System
- Created inline SVG components for Instagram, TikTok, and YouTube
- Black outline style icons using currentColor for consistent theming
- 24×24 viewBox dimensions optimized for display in platform cards
- Scalable vector graphics ensure crisp rendering at all sizes
src/
├── entrypoints/
│ ├── background.ts # Fixed: Uses storage-based URL filtering (not hardcoded)
│ ├── content.ts # Modified: Enhanced error handling
│ ├── content/
│ │ ├── storage-utils.ts # Extended: updateSettings method with nextLessonAt recalc
│ │ ├── lesson-manager.ts # No changes needed
│ │ └── lesson-overlay.ts # Modified: Enhanced styling and animations
│ └── popup/
│ ├── App.tsx # Simplified: Uses Layout component pattern
│ ├── pages/ # NEW: Page components directory
│ │ ├── HomePage.tsx # NEW: Main dashboard with date selection
│ │ └── SettingsPage.tsx # NEW: Settings interface with frequency/platform config
│ ├── components/
│ │ ├── Layout.tsx # NEW: Shared layout with brain battery & navigation
│ │ ├── NavigationBar.tsx # Modified: Added page routing functionality
│ │ ├── BrainBattery.tsx # Modified: Tooltip improvements
│ │ ├── ResetTimer.tsx # Modified: Enhanced styling
│ │ ├── home/ # NEW: Home page specific components
│ │ │ ├── DateSelector.tsx # Moved: From components/ to home/
│ │ │ └── MetricSlot.tsx # Moved: From components/ to home/
│ │ └── settings/ # NEW: Settings-specific components
│ │ ├── LessonFrequency.tsx # NEW: Three-option frequency selector
│ │ └── PlatformSelector.tsx # NEW: Multi-platform selector with icons
│ └── utils/
│ └── formatters.ts # No changes needed
├── types/
│ └── storage.ts # No changes needed
├── utils/
│ ├── browser-api.ts # No changes needed
│ ├── lesson-parser.ts # No changes needed
│ └── time-periods.ts # No changes needed
└── assets/ # NEW: Platform icons directory
└── platform-icons/
├── instagram.svg # NEW: Instagram SVG icon
├── tiktok.svg # NEW: TikTok SVG icon
└── youtube-shorts.svg # NEW: YouTube SVG icon
Phase 5.1 introduces significant architecture improvements and UI polish to the existing Phase 5 implementation. This phase focuses on better code organization, improved component reusability, enhanced responsive design, and addressing critical bugs discovered in the time tracking system.
-
Layout Component Architecture
- Created centralized
Layout.tsxcomponent managing shared data and UI structure - Consolidated brain battery and reset timer positioning across all pages
- Simplified App.tsx to focus solely on page routing logic
- Improved state management with single source of truth for shared data
- Created centralized
-
Component Organization Restructure
- Moved
DateSelectorandMetricSlottocomponents/home/directory - Maintained settings components in dedicated
components/settings/directory - Created logical separation between page-specific and shared components
- Enhanced maintainability through better file organization
- Moved
-
Enhanced HomePage UI & Responsiveness
- Replaced flex layout with CSS grid for metric slots (3-column responsive layout)
- Improved spacing consistency with standardized gap values (12px throughout)
- Enhanced responsive design with proper width constraints and flexible containers
- Better vertical layout management with justify-content: flex-start
-
Settings Page UI Polish
- Removed unnecessary headers for cleaner, focused interface
- Centered content containers with consistent max-width constraints
- Improved visual hierarchy with refined typography and spacing
- Enhanced section headings with better color contrast and letter-spacing
-
Critical Time Tracking Bug Fix
- Issue: Time tracking only worked on TikTok/Instagram/YouTube Shorts, not other YouTube pages
- Root Cause: Background script used hardcoded site list instead of storage settings
- Solution: Updated
background.tsto use storage-basedshouldTrackUrl()logic - Result: ✅ Time tracking now works on ALL enabled sites including all YouTube pages
-
UI Polish & Visual Improvements
- Enhanced MetricSlot styling with improved padding and proportions
- Refined DateSelector with better button states and hover effects
- Improved BrainBattery tooltip positioning and content formatting
- Enhanced ResetTimer styling and tooltip information display
-
Performance & State Management Optimizations
- Centralized storage listeners in Layout component for better efficiency
- Reduced unnecessary re-renders through improved state management
- Better memory management with proper cleanup in useEffect hooks
- Optimized data fetching patterns to minimize storage API calls
Before (Phase 5): HomePage managed its own brain battery state, duplicated storage listeners across components, props drilling for shared data.
After (Phase 5.1):
- Layout component handles all shared data (brain battery, metrics for tooltips)
- Single storage listener managing all real-time updates
- Pages focus on their specific functionality without duplicating shared logic
- Better separation of concerns and improved maintainability
- Grid-Based Metric Layout: More balanced and responsive metric slot positioning
- Consistent Spacing: Standardized 12px gaps throughout all interfaces
- Better Typography: Enhanced headings, labels, and content hierarchy
- Improved Hover States: More intuitive interactive feedback across all components
- Responsive Containers: Better adaptation to different popup sizes and screen constraints
- Page routing between Home, Settings, Library (placeholder)
- Date selection with Today/Yesterday historical comparison
- Brain battery system with drain/recharge mechanics
- Lesson frequency configuration (Often/Sometimes/Barely)
- Platform selection with multi-select interface
- Real-time metric tracking and display
- Settings persistence across browser sessions
- Lesson overlay system with 3-state progression
- Multi-tab independent lesson management
Phase 6 implements the Library page with a two-tier selection system: themes (single-select) and topics (multi-select). Selections persist and update lesson content in real time across tabs, aligning UI patterns with Settings for a consistent experience.
-
Extended Storage System
- Added
selectedThemeandselectedTopicsto settings - Defaults: theme
how-to, topics['control'] - Methods:
updateSelectedTheme,updateSelectedTopics,getSelectedLessons() - Files:
src/types/storage.ts,src/entrypoints/content/storage-utils.ts
- Added
-
Lesson Parser Enhancements
- Added
THEME_TOPIC_MAP,TOPIC_DESCRIPTIONS loadLessons({ theme, topics })for selective loading and caching- Fallback to default TSV if none loaded
- File:
src/utils/lesson-parser.ts
- Added
-
Library UI Components
ThemeSelector: pill buttons mirroringLessonFrequencysizingTopicSelector: horizontal scrollable cards mirroringPlatformSelector- Files:
src/entrypoints/popup/components/library/ThemeSelector.tsx,TopicSelector.tsx
-
Library Page Integration
- Real-time sync with storage changes using
browser.storage.onChanged - Smooth navigation via
App.tsxroute - File:
src/entrypoints/popup/pages/LibraryPage.tsx,src/entrypoints/popup/App.tsx
- Real-time sync with storage changes using
-
Content System Connection
lesson-managerloads lessons per current selection and reacts to updates- File:
src/entrypoints/content/lesson-manager.ts
-
Lesson Files
- Added TSVs for all topics across themes
- Directory:
public/lessons/
src/
├── entrypoints/
│ ├── content/
│ │ ├── lesson-manager.ts # Loads per selection; listens for changes
│ │ └── storage-utils.ts # Selection fields + helpers
│ └── popup/
│ ├── App.tsx # Library route
│ ├── components/
│ │ └── library/
│ │ ├── ThemeSelector.tsx
│ │ └── TopicSelector.tsx
│ └── pages/
│ └── LibraryPage.tsx # Real-time synced UI
├── types/
│ └── storage.ts # selectedTheme, selectedTopics
└── utils/
└── lesson-parser.ts # Selective loading, maps, caching
public/
└── lessons/
├── how-to-control.tsv
├── how-to-learn.tsv
├── how-to-speak.tsv
├── what-is-money.tsv
├── what-is-relationship.tsv
├── what-is-life.tsv
├── why-survive.tsv
├── why-love.tsv
└── why-hate.tsv
Phase 6.1 replaces hardcoded lesson mappings with dynamic discovery, fixes daily rollover to use local midnight, tightens selection storage and migrations, and polishes the Library and Settings UX (smooth topic scrolling and select‑all toggles). Brain Battery UI/behavior is clarified: show 1% when 0 < x < 1, and trigger the brain‑fried overlay only at true 0%.
-
Dynamic lessons index (no hardcoding)
- New
src/utils/lessons-index.tsbuildsTHEME_TOPIC_MAP,FILE_MAP, andTHEMESat build time viaimport.meta.glob('../../public/lessons/*.tsv', { eager: true, query: '?url', import: 'default' }). - Filenames define mapping: last hyphen segment = topic; prefix = theme (e.g.,
why-love.tsv→ theme:why, topic:love;what-is-life.tsv→ theme:what-is, topic:life). getLessonFile(theme, topic)returns the resolved asset URL path (lessons/<filename>.tsv) forbrowser.runtime.getURL().
- New
-
Lesson parser robustness and caching
src/utils/lesson-parser.tsnow loads TSV viagetLessonFilefrom the dynamic index.- TSV format: first line header; subsequent lines must contain exactly 5 tab‑separated fields: question, correctAnswer, wrongAnswer, explanation, reference.
- Multiple topics merged into a single lesson pool; fallback to first topic of theme if selected topics resolve to no data.
- Simple cache key (
theme|sortedTopics) prevents redundant reloads.
-
Storage defaults, migrations, and normalization
- Defaults select all topics across all themes by design for maximum content coverage.
settings.selectedTopicsByTheme: Record<string, string[]>is the new source of truth; legacysettings.selectedTopicsis kept in sync for compatibility.- Migrations: materialize
selectedTheme,selectedTopics, andselectedTopicsByThemeif missing; normalize any topic stored under the wrong theme by moving it to the correct theme, removing unknown topics. StorageUtils.getSelectedLessons()returns{ theme, topics }usingselectedTopicsByThemefor the current theme.
-
Daily rollover correctness (local midnight)
getTodayDateString()andgetYesterdayDateString()use local time;performDailyRollover()resetstodayand setsyesterdaywith normalized local dates.- Resets
brainBatteryto 100% daily; recalculatesnextLessonAtbased on current frequency.
-
Brain Battery behavior and display
- UI shows “1%” for 0 < battery < 1%; shows “0%” only at exactly 0.
- Overlay triggers at battery <= 0 (content script monitors and displays brain‑fried overlay).
- Base recharge runs when away from enabled sites via background script: +0.5% per minute.
- Drains: −0.2%/scroll, −1.0%/minute of time wasted; “Learn More” rewards +1% (+2% for fast click).
-
Library UX polish
- TopicSelector: vertical wheel mapped to horizontal scrolling with kinetic smoothing; preserves native horizontal trackpad swipes; supports mouse‑drag and left/right arrow keys.
- Topic select‑all toggle next to “Topics”: selects/deselects all in current theme, but never allows zero topics globally (keeps at least one topic selected across all themes).
- Defaults: all topics selected across all themes; selectedTheme defaults to the first discovered theme.
-
Settings Platforms improvements
- Added “select all” toggle for platforms; allows deselect all.
PlatformSelectorexposesALL_PLATFORMSfor SettingsPage.- Enabled sites remain the source for tracking decisions across background/content.
-
Build and Vite glob integration
- TSVs imported as asset URLs with
?urlandimport: 'default'to include them in dist; the Library page works with the generated asset paths. - Note: Vite may warn about duplicate
browserimports; functionality unaffected.
- TSVs imported as asset URLs with
- Lesson triggering remains per‑tab.
shouldTriggerLesson()does not use a global lessonActive gate; theLessonManagerin each tab guards against concurrent lesson states locally. - Topic deselection safety is global: the last remaining topic across all themes cannot be deselected by per‑topic clicks or the theme toggle.
- LibraryPage computes “all selected topics” locally from
selectedTopicsByThemeto avoid redundant storage reads.
{
today: {
morning: { scrollCount: number, timeWasted: number, lessonCount: number },
afternoon: { scrollCount: number, timeWasted: number, lessonCount: number },
night: { scrollCount: number, timeWasted: number, lessonCount: number },
date: string
},
yesterday: { /* same structure */ },
settings: {
enabledSites: string[],
lessonFrequency: number,
frequencyMode: 'scrolls' | 'time',
selectedTheme: string,
selectedTopics: string[], // legacy mirror of current theme’s topics
selectedTopicsByTheme?: Record<string, string[]>
},
nextLessonAt: number,
lessonActive: boolean,
brainBattery: number
}src/
├── utils/
│ ├── lessons-index.ts # NEW: dynamic theme/topic/file index via Vite glob
│ └── lesson-parser.ts # Revised: loads from FILE_MAP and merges topics
├── entrypoints/
│ ├── popup/
│ │ ├── pages/LibraryPage.tsx # Revised: select‑all toggle, local aggregation
│ │ └── components/library/
│ │ ├── ThemeSelector.tsx # Uses dynamic THEMES
│ │ └── TopicSelector.tsx # Kinetic scroll, keyboard support, global safety
│ ├── background.ts # Base recharge when away from enabled sites
│ └── content/
│ └── storage-utils.ts # Migrations, normalization, local‑midnight rollover
public/
└── lessons/* # Source of truth for themes/topics
- Removed hardcoded
THEME_TOPIC_MAPandTOPIC_DESCRIPTIONSfrom Phase 6 in favor of dynamic discovery from lesson filenames. - Revised storage to prefer
selectedTopicsByTheme; keepselectedTopicsfor backward compatibility only. - Corrected daily rollover to local midnight and now reset battery to 100% on each new day.
- Adjusted background/content coordination for base battery recharge and clarified overlay trigger conditions.
- Library: dynamic themes/topics from TSV filenames; selection persists; lessons load per current selection in real time.
- Rollover: verified at local midnight; yesterday/today normalized; nextLessonAt recalculated.
- Brain Battery: UI display rules improved; overlay only at 0%; base recharge away from enabled sites.
- UX: Topic selector smooth scrolling; topic/ platform select‑all toggles implemented with correct safety rules.
- Vite's duplicate
browserimport warning appears during build; it is non‑blocking. - TSVs must follow the 5‑column format; malformed rows are skipped with error handling in parser.
Phase 6.2 fixes critical bugs in the bonus notification system and implements a psychological "valuable opportunity" system where quick-click bonuses appear at random intervals instead of every lesson. This enhancement includes comprehensive debugging tools and improved UX positioning to prevent interface interference.
-
Enhanced Storage System for Bonus Tracking
- Added
bonusTrackerfield toStorageDatawithlessonsCompletedandnextBonusAtcounters - Automatic migration for existing users without data loss
- Random interval generation (2-5 lessons) for psychological value perception
- Files:
src/types/storage.ts,src/entrypoints/content/storage-utils.ts
- Added
-
Fixed Critical Off-By-One Logic Error
- Root Cause: Bonus threshold check happened before incrementing counter, but reset happened after
- Impact: Bonus notifications never appeared despite completing lessons
- Solution: Modified
shouldShowTimeBonusNotification()to check(lessonsCompleted + 1) >= nextBonusAt - Result: ✅ Bonus notifications now appear correctly at random intervals
-
Improved Notification Positioning & UX
- Fixed: Moved time bonus notification from
top: -40pxtobottom: -45px - Impact: No longer hides explanation panel text during lessons
- Enhanced: Better visual hierarchy and user experience flow
- File:
src/entrypoints/content/lesson-overlay.ts
- Fixed: Moved time bonus notification from
-
Random Interval Psychology System
- Bonuses now appear randomly every 2-5 completed lessons (vs every lesson)
- Creates "lucky lesson" perception when notification appears
- Maintains fast-click reward functionality (+2% battery within 3 seconds)
- Users perceive bonuses as valuable opportunities rather than routine interruptions
-
Comprehensive Debug System
- Added extensive logging throughout bonus logic flow
- Global console testing methods:
debugBonusTracker(),resetBonusTracker() - Real-time state inspection for troubleshooting
- Migration tracking and storage operation visibility
-
New Storage Methods
shouldShowTimeBonusNotification(): Checks if bonus should appear for current lessonincrementLessonCompletedAndCheckBonus(): Tracks completion and manages threshold resetsgetRandomBonusInterval(): Generates 2-5 lesson random intervalsdebugBonusTracker()/resetBonusTracker(): Debug utilities for console testing
src/
├── entrypoints/
│ ├── content/
│ │ ├── lesson-overlay.ts # Enhanced: Fixed positioning, conditional bonus logic, debug integration
│ │ └── storage-utils.ts # Extended: Bonus tracking methods, migration logic, debug utilities
├── types/
│ └── storage.ts # Extended: bonusTracker field with lessonsCompleted/nextBonusAt
{
today: {
morning: { scrollCount: number, timeWasted: number, lessonCount: number },
afternoon: { scrollCount: number, timeWasted: number, lessonCount: number },
night: { scrollCount: number, timeWasted: number, lessonCount: number },
date: string
},
yesterday: { /* same structure */ },
settings: {
enabledSites: string[],
lessonFrequency: number,
frequencyMode: 'scrolls' | 'time',
selectedTheme: string,
selectedTopics: string[],
selectedTopicsByTheme?: Record<string, string[]>
},
nextLessonAt: number,
lessonActive: boolean,
brainBattery: number,
// NEW: Bonus notification tracking
bonusTracker: {
lessonsCompleted: number, // Counter of completed lessons
nextBonusAt: number // Random threshold (2-5) for next bonus appearance
}
}Console Testing Commands:
debugBonusTracker() // Inspect current bonus tracker state
resetBonusTracker() // Reset to completed=0, nextAt=2 for testingExpected Flow (with nextBonusAt = 2):
Lesson 1: Check (0+1) >= 2? ❌ → No notification, increment to 1
Lesson 2: Check (1+1) >= 2? ✅ → BONUS NOTIFICATION! ⚡ → Reset to 0, new interval
Before: Bonus notifications appeared every lesson → felt routine and annoying After: Random intervals (2-5 lessons) → creates anticipation and perceived value
Users now think "This is my lucky lesson!" when bonuses appear, enhancing engagement rather than causing interruption fatigue.
- ✅ Critical off-by-one bug fixed - bonus notifications work correctly
- ✅ Notification positioning improved - no longer hides explanation text
- ✅ Random interval psychology system implemented - bonuses feel valuable
- ✅ Comprehensive debug system added - easy troubleshooting and testing
- ✅ Backward compatibility maintained - existing users seamlessly migrated
- ✅ Fast-click rewards preserved - +2% battery for quick clicks still functional
- Off-by-one threshold checking: Bonus notifications now appear correctly
- UI positioning conflict: Notification positioned below button, not above explanation
- Psychological fatigue: Random intervals prevent bonus notification burnout
- Debug visibility: Complete logging system for troubleshooting bonus logic