Fix real-time unclaim updates for task workflow

Add deletion event handling to enable real-time UI updates when tasks are unclaimed. Previously, unclaiming a task required manual refresh to see the update.

Changes:
- Add handleDeletionEvent() to ScheduledEventService to process kind 5 deletion events
- Update FeedService to route kind 31925 deletions to ScheduledEventService
- Implement NIP-09 validation (only author can delete their own events)
- Remove completions from reactive Map to trigger Vue reactivity

Technical details:
- Subscription to kind 5 events was already in place
- Issue was lack of routing for kind 31925 (RSVP/completion) deletions
- Now follows same pattern as reaction and post deletions
- Deletion events properly update the _completions reactive Map
- UI automatically reflects unclaimed state through Vue reactivity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
padreug 2025-11-16 17:01:22 +01:00
parent d497cfa4d9
commit d8e67984b0
2 changed files with 51 additions and 0 deletions

View file

@ -383,6 +383,17 @@ export class FeedService extends BaseService {
return
}
// Route to ScheduledEventService for completion/RSVP deletions (kind 31925)
if (deletedKind === '31925') {
console.log('🔀 FeedService: Routing kind 5 (deletion of kind 31925) to ScheduledEventService')
if (this.scheduledEventService) {
this.scheduledEventService.handleDeletionEvent(event)
} else {
console.warn('⚠️ FeedService: ScheduledEventService not available')
}
return
}
// Handle post deletions (kind 1) in FeedService
if (deletedKind === '1' || !deletedKind) {
// Extract event IDs to delete from 'e' tags

View file

@ -213,6 +213,46 @@ export class ScheduledEventService extends BaseService {
}
}
/**
* Handle deletion event (kind 5) for completion events
* Made public so FeedService can route deletion events to this service
*/
public handleDeletionEvent(event: NostrEvent): void {
console.log('🗑️ ScheduledEventService: Received deletion event (kind 5)', event.id)
try {
// Extract event IDs to delete from 'e' tags
const eventIdsToDelete = event.tags
?.filter((tag: string[]) => tag[0] === 'e')
.map((tag: string[]) => tag[1]) || []
if (eventIdsToDelete.length === 0) {
console.warn('Deletion event missing e tags:', event.id)
return
}
console.log('🔍 Looking for completions to delete:', eventIdsToDelete)
// Find and remove completions that match the deleted event IDs
let deletedCount = 0
for (const [completionKey, completion] of this._completions.entries()) {
// Only delete if:
// 1. The completion event ID matches one being deleted
// 2. The deletion request comes from the same author (NIP-09 validation)
if (eventIdsToDelete.includes(completion.id) && completion.pubkey === event.pubkey) {
this._completions.delete(completionKey)
console.log('✅ Deleted completion:', completionKey, 'event ID:', completion.id)
deletedCount++
}
}
console.log(`🗑️ Deleted ${deletedCount} completion(s) from deletion event`)
} catch (error) {
console.error('Failed to handle deletion event:', error)
}
}
/**
* Get all scheduled events
*/