Add comprehensive social features with accessibility-first design

Implements complete post management and social interaction capabilities:

**Post Management:**
- Delete posts with confirmation dialog (owned posts only)
- Edit posts using existing compose dialog (owned posts only)
- Robust ownership validation and error handling

**Follow System:**
- Follow/unfollow users from context menus and keyboard shortcuts
- Manual follow dialog for @user@instance lookups
- Account search and validation before following
- Smart context menu options based on post ownership

**Timeline Extensions:**
- Followers tab showing accounts following you
- Following tab showing accounts you follow
- Seamless integration with existing timeline system
- Account list display for social relationship viewing

**Keyboard Shortcuts:**
- Ctrl+Shift+E: Edit post
- Shift+Delete: Delete post (with confirmation)
- Ctrl+Shift+F: Follow user
- Ctrl+Shift+U: Unfollow user
- Ctrl+Shift+M: Manual follow dialog

**ActivityPub API Extensions:**
- edit_status() method for post editing
- get_relationship() method for follow status checking
- Enhanced followers/following pagination support

**Critical Accessibility Fix:**
- Eliminated ALL text truncation throughout the application
- Added explicit no-truncation rule to development guidelines
- Full content accessibility for screen reader users

All features maintain Bifrost's accessibility-first principles with proper error handling, user feedback, and complete information display.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Storm Dragon
2025-07-20 19:46:31 -04:00
parent b936e4994d
commit 037fcbf7e0
5 changed files with 439 additions and 18 deletions

View File

@@ -244,6 +244,33 @@ class ActivityPubClient:
def get_custom_emojis(self) -> List[Dict]:
"""Get custom emojis for this instance"""
return self._make_request('GET', '/api/v1/custom_emojis')
def edit_status(self, status_id: str, content: str, visibility: str = 'public',
content_warning: Optional[str] = None,
media_ids: Optional[List[str]] = None,
content_type: str = 'text/plain') -> Dict:
"""Edit an existing status"""
data = {
'status': content,
'visibility': visibility
}
if content_type == 'text/markdown':
data['content_type'] = 'text/markdown'
if content_warning:
data['spoiler_text'] = content_warning
if media_ids:
data['media_ids'] = media_ids
endpoint = f'/api/v1/statuses/{status_id}'
return self._make_request('PUT', endpoint, data=data)
def get_relationship(self, account_id: str) -> Dict:
"""Get relationship with an account"""
params = {'id': account_id}
result = self._make_request('GET', '/api/v1/accounts/relationships', params=params)
return result[0] if result else {}
class AuthenticationError(Exception):