The 1st decentralized social network for sharing when you're on the toilet. Post a "flush" today! Powered by the AT Protocol.

Edit & Delete Flush Feature#

Overview#

This feature allows users to edit and delete their own flush records directly from their profile page. The implementation includes a modal interface for editing, client-side validation, and proper handling through the AT Protocol and Jetstream firehose.

What Was Added#

1. API Client Functions (src/lib/api-client.ts)#

Added two new functions to handle record management:

  • deleteFlushRecord(session, recordUri): Deletes a flush record using the AT Protocol's deleteRecord method
  • updateFlushRecord(session, recordUri, text, emoji, originalCreatedAt): Updates a flush record using the AT Protocol's putRecord method

Both functions:

  • Parse AT URIs correctly (format: at://did:plc:xxx/collection.name/rkey)
  • Use the OAuth session's Agent for authenticated requests
  • Include proper error handling and logging
  • Preserve the original createdAt timestamp on updates

2. Edit Modal Component (src/components/EditFlushModal.tsx)#

A beautiful modal dialog that provides:

  • Pre-populated form with the flush's current text and emoji
  • Character counter (59 character limit)
  • Emoji selector with all approved emojis
  • Content validation (banned words, character limits)
  • Delete confirmation workflow
  • Loading states for all async operations
  • Error handling with user-friendly messages
  • Backdrop click to close
  • Responsive design for mobile devices

3. Profile Page Updates (src/app/profile/[handle]/page.tsx)#

Enhanced the profile page with:

  • Edit button on each flush (only visible to the flush owner)
  • Authentication check using useAuth() hook to compare DIDs
  • Integration with EditFlushModal component
  • State management for editing operations
  • Success/error message display
  • Optimistic UI updates (updates local state immediately)

New state variables:

  • editingFlush: Tracks which flush is being edited
  • actionError: Displays error messages
  • actionSuccess: Displays success messages

New functions:

  • isOwnProfile(): Checks if the logged-in user owns the profile
  • handleUpdateFlush(): Handles the update operation
  • handleDeleteFlush(): Handles the delete operation

4. Profile Styles (src/app/profile/[handle]/profile.module.css)#

Added styles for:

  • .contentRight: Container for timestamp and edit button
  • .editButton: Pencil icon button with hover effects
  • .actionError: Error message styling
  • .actionSuccess: Success message styling

5. Edit Modal Styles (src/components/EditFlushModal.module.css)#

Complete styling for the modal including:

  • Dark backdrop overlay
  • Centered modal with max-width
  • Form inputs and emoji grid
  • Action buttons (Save, Cancel, Delete)
  • Delete confirmation UI
  • Responsive mobile layout
  • Smooth transitions and hover effects

6. Jetstream Consumer (scripts/firehose-worker.js)#

Updated to properly handle:

  • Delete operations: Removes records from Supabase when deleted from the network
  • Update operations: Updates existing records with new content
  • URI construction for record matching
  • Proper error handling for database operations

How It Works#

User Flow#

  1. User navigates to their own profile

    • Edit buttons appear next to each of their flushes
    • Buttons are hidden for other users' profiles
  2. User clicks edit button

    • Modal opens with pre-filled form
    • Current text and emoji are displayed
    • User can modify text and/or emoji
    • Character counter shows remaining characters
  3. User saves changes

    • Validation runs (banned words, character limits)
    • API call made to update the record via AT Protocol
    • Local state updates immediately (optimistic UI)
    • Success message displayed
    • Modal closes automatically
  4. User deletes a flush

    • Clicks "Delete Flush" button
    • Confirmation prompt appears
    • On confirmation, record is deleted via AT Protocol
    • Record removed from local state
    • Success message displayed
    • Modal closes

Technical Flow#

Update Operation#

User clicks Save
  → Validation (client-side)
  → updateFlushRecord(session, uri, text, emoji, createdAt)
  → Agent.api.com.atproto.repo.putRecord()
  → PDS updates the record
  → Jetstream firehose emits 'update' event
  → Worker processes event
  → Supabase record updated
  → UI updates optimistically

Delete Operation#

User confirms delete
  → deleteFlushRecord(session, uri)
  → Agent.api.com.atproto.repo.deleteRecord()
  → PDS deletes the record
  → Jetstream firehose emits 'delete' event
  → Worker processes event
  → Supabase record deleted
  → UI updates optimistically

Authorization#

  • Uses OAuth session from @atproto/oauth-client-browser
  • Compares session.sub (user's DID) with profileData.did
  • Edit buttons only visible when DIDs match
  • AT Protocol handles authorization at the PDS level
  • Users can only edit/delete their own records

Validation#

All validation from the original flush creation is preserved:

  • Character limit: 59 characters
  • Banned words: Content filtering via containsBannedWords()
  • Text sanitization: via sanitizeText()
  • Emoji validation: Only approved emojis from the list
  • Authentication: Must be logged in

Error Handling#

Comprehensive error handling at every level:

  • Network failures
  • Authorization errors
  • Validation errors
  • User-friendly error messages
  • Console logging for debugging
  • Graceful degradation

Responsive Design#

The modal and edit buttons work beautifully on:

  • Desktop screens
  • Tablets
  • Mobile devices

Features:

  • Touch-friendly button sizes
  • Readable text at all sizes
  • Scrollable modal content
  • Proper spacing and padding

Future Enhancements#

Potential improvements:

  1. Edit history: Track when records were edited
  2. Undo functionality: Allow users to revert changes
  3. Bulk operations: Edit/delete multiple flushes at once
  4. Keyboard shortcuts: Quick access to edit/delete
  5. Inline editing: Edit directly in the feed without modal
  6. Draft saving: Save edits as drafts before publishing

Testing Checklist#

To verify the feature works correctly:

  • Edit button appears on own profile only
  • Edit button hidden on other users' profiles
  • Modal opens when edit button clicked
  • Form pre-populates with current values
  • Text changes are validated
  • Emoji selection works
  • Character counter updates correctly
  • Save button updates the record
  • Delete button shows confirmation
  • Delete confirmation works
  • Cancel buttons close modal
  • Success messages display
  • Error messages display
  • Local state updates optimistically
  • Jetstream updates Supabase correctly
  • Mobile layout works properly

Notes#

  • Records maintain their original createdAt timestamp when updated
  • Updates create a new CID (Content Identifier) for the record
  • The URI remains the same (same rkey)
  • Deletes are permanent and cannot be undone
  • All operations respect AT Protocol's distributed architecture