feat: improve reading progress with validation and auto-mark

- Add autoMarkAsReadOnCompletion setting (opt-in, default: false)
- Implement auto-mark as read when reaching 95%+ completion
- Add validation for progress bounds (0-1) per NIP-39802 spec
- Align completion threshold to 95% to match filter behavior
- Skip invalid progress events with warning log

Improvements ensure consistency between completion detection and
filtering, while adding safety validation per the NIP spec.
This commit is contained in:
Gigi
2025-10-19 10:34:53 +02:00
parent 442c138d6a
commit 3b31eceeab
4 changed files with 14 additions and 5 deletions

View File

@@ -189,9 +189,10 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
syncEnabled: settings?.syncReadingPosition,
onSave: handleSavePosition,
onReadingComplete: () => {
// Optional: Auto-mark as read when reading is complete
if (activeAccount && !isMarkedAsRead) {
// Could trigger auto-mark as read here if desired
// Auto-mark as read when reading is complete (if enabled in settings)
if (activeAccount && !isMarkedAsRead && settings?.autoMarkAsReadOnCompletion) {
console.log('📖 [ContentPanel] Auto-marking as read on completion')
handleMarkAsRead()
}
}
})

View File

@@ -4,7 +4,7 @@ interface UseReadingPositionOptions {
enabled?: boolean
onPositionChange?: (position: number) => void
onReadingComplete?: () => void
readingCompleteThreshold?: number // Default 0.9 (90%)
readingCompleteThreshold?: number // Default 0.95 (95%) - matches filter threshold
syncEnabled?: boolean // Whether to sync positions to Nostr
onSave?: (position: number) => void // Callback for saving position
autoSaveInterval?: number // Auto-save interval in ms (default 5000)
@@ -14,7 +14,7 @@ export const useReadingPosition = ({
enabled = true,
onPositionChange,
onReadingComplete,
readingCompleteThreshold = 0.9,
readingCompleteThreshold = 0.95, // Match filter threshold for consistency
syncEnabled = false,
onSave,
autoSaveInterval = 5000

View File

@@ -36,6 +36,13 @@ export function processReadingProgress(
try {
const content = JSON.parse(event.content)
const position = content.progress || 0
// Validate progress is between 0 and 1 (NIP-39802 requirement)
if (position < 0 || position > 1) {
console.warn('Invalid progress value (must be 0-1):', position, 'event:', event.id.slice(0, 8))
continue
}
// Use event.created_at as authoritative timestamp (NIP-39802 spec)
const timestamp = event.created_at

View File

@@ -60,6 +60,7 @@ export interface UserSettings {
paragraphAlignment?: 'left' | 'justify' // default: justify
// Reading position sync
syncReadingPosition?: boolean // default: false (opt-in)
autoMarkAsReadOnCompletion?: boolean // default: false (opt-in)
}
export async function loadSettings(