Files
bifrost/CLAUDE.md
Storm Dragon 684919f4ca Add comprehensive user profile viewer with full accessibility support
- Create ProfileDialog with threaded loading and tabbed interface
- Display user bio, profile fields, stats, and recent posts
- Implement Follow/Unfollow, Block/Unblock, Mute/Unmute actions
- Add ActivityPub API methods for social actions and account management
- Enable keyboard navigation in read-only bio text with TextInteractionFlags
- Replace TODO profile viewing with fully functional dialog
- Update documentation to reflect completed profile features

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 10:39:07 -04:00

19 KiB

Bifrost Fediverse Client - Development Plan

Project Overview

Bifrost is a fully accessible fediverse client built with PySide6, designed specifically for screen reader users. The application uses "post/posts" terminology instead of "toot" and focuses on excellent keyboard navigation and audio feedback.

Development Workflow

  • Check for any changes in git project before doing anything else. Make sure the latest changes have been pulled
  • See what has changed, use git commands and examine the code to make sure you are up to date with the latest code

Duplicate Code Prevention Guidelines

Critical Areas Requiring Attention

  1. Sound/Audio Events: Never add multiple paths that trigger the same sound event
  2. UI Event Handlers: Avoid circular event chains (A triggers B which triggers A)
  3. Timeline Operations: Coordinate refresh calls and state changes to prevent conflicts
  4. Lifecycle Events: Ensure shutdown, close, and quit events don't overlap

Required Patterns for Event-Heavy Operations

Event Coordination Pattern

def operation_method(self):
    if hasattr(self, '_operation_in_progress') and self._operation_in_progress:
        return
    self._operation_in_progress = True
    try:
        # perform operation
        self.sound_manager.play_success()
    finally:
        # Reset flag after brief delay to prevent rapid-fire calls
        QTimer.singleShot(100, lambda: setattr(self, '_operation_in_progress', False))

Event Source Tracking Pattern

def ui_triggered_method(self, index, from_source="unknown"):
    # Handle differently based on source: "tab_change", "keyboard", "menu"
    if from_source == "tab_change":
        # Skip certain UI updates to prevent circular calls
        pass

Lifecycle Event Coordination Pattern

def quit_application(self):
    self._shutdown_handled = True  # Mark that shutdown is being handled
    self.sound_manager.play_shutdown()
    
def closeEvent(self, event):
    # Only handle if not already handled by explicit quit
    if not hasattr(self, '_shutdown_handled'):
        self.sound_manager.play_shutdown()

Development Review Checklist

Before implementing any sound, notification, or UI event:

  1. Is there already another code path that triggers this same feedback?
  2. Could this create an event loop (A calls B which calls A)?
  3. Can rapid user actions (keyboard shortcuts) trigger this multiple times?
  4. Does this operation need coordination with other similar operations?
  5. Are there multiple UI elements (menu + button + shortcut) that trigger this?

Common Patterns to Avoid

  • Multiple event handlers calling the same sound method
  • UI updates that trigger their own event handlers
  • Shutdown/close/quit events without coordination
  • Timeline refresh without checking if already refreshing
  • Direct sound calls in multiple places for the same user action

Testing Requirements

When adding event-driven features, always test:

  • Rapid keyboard shortcut usage
  • Multiple quick UI interactions
  • Combinations of keyboard shortcuts + UI clicks
  • Window closing during operations
  • Tab switching with keyboard vs mouse

Documentation and Dependencies

  • README Updates: When adding new functionality or sound events, update README.md with detailed descriptions
  • Requirements Management: Check and update requirements.txt when new dependencies are added
  • Sound Pack Documentation: Document new sound events in both CLAUDE.md and user-facing documentation
  • Version Tracking: Update version numbers and changelog when significant features are added

Core Features

  • Full ActivityPub protocol support (Pleroma and GoToSocial primary targets)
  • Threaded conversation navigation with collapsible tree view
  • Comprehensive soundpack management system with secure repository support
  • Smart autocomplete for mentions (@user@instance.com) and emojis (5,000+ Unicode)
  • Auto-refresh with intelligent activity-based timing
  • Screen reader optimized interface with Orca compatibility fixes
  • XDG Base Directory specification compliance

Technology Stack

  • PySide6: Main GUI framework (proven accessibility with existing doom launcher)
  • requests: HTTP client for ActivityPub APIs
  • simpleaudio: Cross-platform audio with subprocess fallback
  • emoji: Comprehensive Unicode emoji library (5,000+ emojis with keyword search)
  • plyer: Cross-platform desktop notifications
  • XDG directories: Configuration and data storage

Architecture

Directory Structure

bifrost/
├── bifrost/
│   ├── __init__.py
│   ├── main.py                 # Application entry point
│   ├── accessibility/          # Accessibility widgets and helpers
│   │   ├── __init__.py
│   │   ├── accessible_tree.py  # AccessibleTreeWidget for conversations
│   │   └── accessible_combo.py # Enhanced ComboBox from doom launcher
│   ├── activitypub/            # Federation protocol handling
│   │   ├── __init__.py
│   │   ├── client.py           # Main ActivityPub client
│   │   ├── pleroma.py          # Pleroma-specific implementation
│   │   └── gotosocial.py       # GoToSocial-specific implementation
│   ├── models/                 # Data models
│   │   ├── __init__.py
│   │   ├── post.py             # Post data structure
│   │   ├── user.py             # User profiles
│   │   ├── timeline.py         # Timeline model for QTreeView
│   │   └── thread.py           # Conversation threading
│   ├── widgets/                # Custom UI components
│   │   ├── __init__.py
│   │   ├── timeline_view.py    # Main timeline widget with auto-refresh
│   │   ├── compose_dialog.py   # Post composition with smart autocomplete
│   │   ├── autocomplete_textedit.py # Mention and emoji autocomplete system
│   │   ├── settings_dialog.py  # Application settings
│   │   ├── soundpack_manager_dialog.py # Soundpack repository management
│   │   └── login_dialog.py     # Instance login
│   ├── audio/                  # Sound system
│   │   ├── __init__.py
│   │   ├── sound_manager.py    # Audio notification handler
│   │   └── soundpack_manager.py # Secure soundpack installation system
│   │   └── sound_pack.py       # Sound pack management
│   └── config/                 # Configuration management
│       ├── __init__.py
│       ├── settings.py         # Settings handler with XDG compliance
│       └── accounts.py         # Account management
├── sounds/                     # Sound packs directory
│   ├── default/
│   │   ├── pack.json
│   │   ├── private_message.wav
│   │   ├── mention.wav
│   │   ├── boost.wav
│   │   ├── reply.wav
│   │   ├── post_sent.wav
│   │   ├── timeline_update.wav
│   │   └── notification.wav
│   └── doom/                   # Example themed sound pack
│       ├── pack.json
│       └── *.wav files
├── tests/
│   ├── __init__.py
│   ├── test_accessibility.py
│   ├── test_activitypub.py
│   └── test_audio.py
├── requirements.txt
├── setup.py
└── README.md

XDG Directory Usage

  • Config: ~/.config/bifrost/ - Settings, accounts, current sound pack
  • Data: ~/.local/share/bifrost/ - Sound packs, cached data
  • Cache: ~/.cache/bifrost/ - Temporary files, avatar cache

Accessibility Implementation

From Doom Launcher Success

  • AccessibleComboBox: Enhanced keyboard navigation (Page Up/Down, Home/End)
  • Proper Accessible Names: All widgets get descriptive setAccessibleName()
  • Focus Management: Clear tab order and focus indicators
  • No Custom Speech: Screen reader handles all announcements

Threaded Conversation Navigation

Navigation Pattern:

Timeline Item: "Alice posted: Hello world (3 replies, collapsed)"
[Right Arrow] → "Alice posted: Hello world (3 replies, expanded)"
[Down Arrow] → "    Bob replied: Hi there"
[Down Arrow] → "    Carol replied: How's it going?"
[Down Arrow] → "David posted: Another topic"

Key Behaviors:

  • Right Arrow: Expand thread, announce "expanded" / Move to first child when expanded
  • Left Arrow: Collapse thread, announce "collapsed" / Move to parent
  • Shift+Left Arrow: Navigate to thread root from any reply
  • Down Arrow: Next item (skip collapsed children)
  • Up Arrow: Previous item
  • Page Down/Up: Jump 5 items
  • Home/End: First/last item

Known Qt Tree Widget Display Quirk

Due to Qt's visual display synchronization, thread collapse may require double-operation:

  • Navigation logic works correctly after first collapse (skips collapsed items)
  • Visual display may need expand→collapse cycle to fully sync
  • Workaround: Navigate to root with Shift+Left, then Left→Right→Left if needed

AccessibleTreeWidget Requirements

  • Inherit from QTreeWidget
  • Override keyPressEvent for custom navigation
  • Proper accessibility roles and states
  • Focus management for nested items
  • Status announcements via Qt accessibility

Sound System Design

Sound Events

  • startup: Application started
  • shutdown: Application closing
  • private_message: Direct message received
  • mention: User mentioned in post
  • boost: Post boosted/reblogged
  • reply: Reply to user's post
  • post_sent: User successfully posted
  • timeline_update: New posts in timeline
  • notification: General notification
  • expand: Thread expanded
  • collapse: Thread collapsed
  • success: General success feedback
  • error: Error occurred
  • autocomplete: Autocomplete suggestions available
  • autocomplete_end: Autocomplete interaction ended

Sound System Policy

  • No Sound Generation: The application should never generate sounds programmatically
  • Sound Pack Reliance: All audio feedback must come from sound pack files
  • Default Pack Requirement: A complete default sound pack must ship with the project
  • Themed Packs: Users can install additional themed sound packs (like Doom)
  • If someone requests sound generation, gently remind them that all sounds should be covered by sound packs

Sound Pack Structure

pack.json Format:

{
  "name": "Pack Display Name",
  "description": "Pack description",
  "author": "Creator name",
  "version": "1.0",
  "sounds": {
    "private_message": "filename.wav",
    "mention": "filename.wav",
    "boost": "filename.wav",
    "reply": "filename.wav",
    "post_sent": "filename.wav",
    "timeline_update": "filename.wav",
    "notification": "filename.wav"
  }
}

SoundManager Features

  • simpleaudio for cross-platform WAV playback with volume control
  • Subprocess fallback (sox/play on Linux, afplay on macOS, PowerShell on Windows)
  • Fallback to default pack if sound missing
  • Single volume control for all sound pack audio
  • "None" sound pack option to disable all sounds
  • Pack discovery and validation
  • Smart threading (direct calls for simpleaudio, threaded for subprocess)

ActivityPub Implementation

Core Client Features

  • Timeline Streaming: Real-time updates via WebSocket/polling
  • Post Composition: Text, media attachments, visibility settings
  • Thread Resolution: Fetch complete conversation trees
  • User Profiles: Following, followers, profile viewing
  • Notifications: Mentions, boosts, follows, favorites

Server Compatibility

Primary Targets:

  • Pleroma: Full feature support
  • GoToSocial: Full feature support

Extended Support:

  • Mastodon: Best effort compatibility
  • Other ActivityPub servers: Basic functionality

API Endpoints Usage

  • /api/v1/timelines/home - Home timeline
  • /api/v1/statuses - Post creation
  • /api/v1/statuses/:id/context - Thread fetching
  • /api/v1/streaming - Real-time updates
  • /api/v1/notifications - Notification management

User Interface Design

Main Window Layout

[Menu Bar]
[Instance/Account Selector]
[Timeline Tree View - Main Focus]
[Compose Box]
[Status Bar]

Key UI Components

  • Timeline View: AccessibleTreeWidget showing posts and threads with pagination
  • Timeline Tabs: Home, Mentions, Local, Federated timeline switching
  • Compose Dialog: Modal for creating posts with accessibility
  • Settings Dialog: Sound pack, desktop notifications, accessibility options
  • Login Dialog: Instance selection and authentication
  • URL Selection Dialog: Choose from multiple URLs in posts
  • Context Menu: Copy, URL opening, reply, boost, favorite actions

Keyboard Shortcuts

  • Ctrl+N: New post
  • Ctrl+R: Reply to selected post
  • Ctrl+B: Boost selected post
  • Ctrl+F: Favorite selected post
  • Ctrl+C: Copy selected post to clipboard
  • Ctrl+U: Open URLs from selected post in browser
  • F5: Refresh timeline
  • Ctrl+,: Settings
  • Escape: Close dialogs

Development Phases

Phase 1: Foundation

  1. Project structure setup
  2. XDG configuration system
  3. Basic PySide6 window with accessibility
  4. AccessibleTreeWidget implementation
  5. Sound system foundation

Phase 2: ActivityPub Core

  1. Basic HTTP client
  2. Authentication (OAuth2)
  3. Timeline fetching and display
  4. Post composition and sending
  5. Basic thread display

Phase 3: Advanced Features

  1. Thread expansion/collapse
  2. Real-time updates
  3. Notifications system
  4. Sound pack system
  5. Settings interface

Phase 4: Polish

  1. Comprehensive accessibility testing
  2. Screen reader testing (Orca, NVDA, JAWS)
  3. Performance optimization
  4. Error handling
  5. Documentation

Testing Strategy

Accessibility Testing

  • Automated testing with screen reader APIs
  • Manual testing with Orca, NVDA (via Wine)
  • Keyboard-only navigation testing
  • Focus management verification

Functional Testing

  • ActivityPub protocol compliance
  • Thread navigation accuracy
  • Sound system reliability
  • Configuration persistence

Test Instances

  • Pleroma test server
  • GoToSocial test server
  • Mock ActivityPub server for edge cases

Configuration Management

Settings Structure

[general]
instance_url = https://example.social
username = user
timeline_refresh_interval = 60
auto_refresh_enabled = true

[audio]
sound_pack = default
volume = 100

[notifications]
enabled = true
direct_messages = true
mentions = true
boosts = false
favorites = false
follows = true

[timeline]
posts_per_page = 40

[accessibility]
announce_thread_state = true
auto_expand_mentions = false
keyboard_navigation_wrap = true
page_step_size = 5
verbose_announcements = true

Account Storage

  • Secure credential storage
  • Multiple account support
  • Instance-specific settings

Known Challenges and Solutions

ActivityPub Complexity

  • Challenge: Different server implementations vary
  • Solution: Modular client design with server-specific adapters

Screen Reader Performance

  • Challenge: Large timelines may impact performance
  • Solution: Virtual scrolling, lazy loading, efficient tree models

Thread Visualization

  • Challenge: Complex thread structures hard to navigate
  • Solution: Clear indentation, status announcements, skip collapsed

Sound Customization

  • Challenge: Users want different audio feedback
  • Solution: Comprehensive sound pack system with easy installation

Recently Implemented Features

Completed Features

  • Direct Message Interface: Dedicated Messages tab with conversation threading
  • Bookmarks Tab: Timeline tab for viewing saved/bookmarked posts
  • Poll Support: Create and vote on polls with accessible interface
  • Poll Creation: Add poll options to compose dialog with expiration times
  • Poll Voting: Accessible poll interaction with keyboard navigation
  • User Profile Viewer: Comprehensive profile dialog with bio, fields, recent posts
  • Social Actions: Follow/unfollow, block/unblock, mute/unmute from profile viewer

Remaining High Priority Features

  • User Blocking Management: Block/unblock users with dedicated management interface
  • User Muting Management: Mute/unmute users with management interface
  • Blocked Users Management: Tab/dialog to view and manage blocked users

Implementation Status

  • Timeline tabs completed: Home, Messages, Mentions, Local, Federated, Bookmarks, Followers, Following
  • Profile viewer includes all social actions (follow, block, mute) with API integration
  • Poll accessibility fully implemented with screen reader announcements
  • DM interface shows conversation threads with proper threading

Future Enhancements

Advanced Features

  • Custom timeline filters
  • Multiple column support
  • List management
  • Advanced search

Accessibility Extensions

  • Braille display optimization
  • Voice control integration
  • High contrast themes
  • Font size scaling

Federation Features

  • Cross-instance thread following
  • Server switching
  • Federation status monitoring
  • Custom emoji support

Dependencies

Core Requirements

PySide6>=6.0.0
requests>=2.25.0
simpleaudio>=1.0.4
plyer>=2.1.0
emoji>=2.0.0

Optional Dependencies

pytest (testing)
coverage (test coverage)
black (code formatting)
mypy (type checking)

Installation and Distribution

Development Setup

git clone <repository>
cd bifrost
pip install -r requirements.txt
# Run with proper display
DISPLAY=:0 ./bifrost.py
# Or
python bifrost.py

Packaging

  • Python wheel distribution
  • AppImage for Linux
  • Consideration for distro packages

Accessibility Compliance

Standards Adherence

  • WCAG 2.1 AA compliance
  • Qt Accessibility framework usage
  • AT-SPI2 protocol support (Linux)
  • Platform accessibility APIs

Screen Reader Testing Matrix

  • Orca (Linux): Primary target
  • NVDA (Windows via Wine): Secondary
  • JAWS (Windows via Wine): Basic compatibility
  • VoiceOver (macOS): Future consideration

Critical Accessibility Rules

Text Truncation Is Forbidden

NEVER TRUNCATE TEXT: Bifrost is an accessibility-first client. Text truncation (using "..." or limiting character counts) is strictly forbidden as it prevents screen reader users from accessing complete information. Always display full content, descriptions, usernames, profiles, and any other text in its entirety.

Examples of forbidden practices:

  • content[:100] + "..."
  • Character limits on display text
  • Shortened usernames or descriptions
  • Abbreviated profile information

This document serves as the comprehensive development guide for Bifrost, ensuring all accessibility, functionality, and architectural decisions are preserved and can be referenced throughout development.