Fix notification and sound system issues with comprehensive improvements
- **Fixed duplicate sound events**: Prevent success/shutdown sounds from playing multiple times during timeline switches and app quit - **Added event coordination patterns**: Implemented flags and source tracking to prevent circular UI event chains - **Completed sound event coverage**: Added missing sound methods (play_favorite, play_follow, play_unfollow, play_direct_message, play_post) and wired them to user actions - **Enhanced notification system**: Fixed desktop notifications ignoring enable/disable settings by adding missing notifications section to default config - **Improved timeline-specific sounds**: Conversations now use direct_message sound instead of generic timeline_update sound - **Added duplicate code prevention guidelines**: Comprehensive CLAUDE.md section with patterns, checklist, and testing requirements to prevent future duplicate implementations - **Sound pack compatibility**: Full support for both default pack (private_message, post_sent) and Doom pack (direct_message, post) naming conventions with intelligent fallback All sound events now properly trigger on user actions: boost/favorite posts, follow/unfollow users, notifications, timeline updates, and lifecycle events. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -446,9 +446,9 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def on_timeline_tab_changed(self, index):
|
||||
"""Handle timeline tab change"""
|
||||
self.switch_timeline(index)
|
||||
self.switch_timeline(index, from_tab_change=True)
|
||||
|
||||
def switch_timeline(self, index):
|
||||
def switch_timeline(self, index, from_tab_change=False):
|
||||
"""Switch to timeline by index with loading feedback"""
|
||||
timeline_names = ["Home", "Messages", "Mentions", "Local", "Federated", "Bookmarks", "Followers", "Following"]
|
||||
timeline_types = ["home", "conversations", "notifications", "local", "federated", "bookmarks", "followers", "following"]
|
||||
@ -457,8 +457,13 @@ class MainWindow(QMainWindow):
|
||||
timeline_name = timeline_names[index]
|
||||
timeline_type = timeline_types[index]
|
||||
|
||||
# Set tab to match if called from keyboard shortcut
|
||||
if self.timeline_tabs.currentIndex() != index:
|
||||
# Prevent duplicate calls for the same timeline
|
||||
if hasattr(self, '_current_timeline_switching') and self._current_timeline_switching:
|
||||
return
|
||||
self._current_timeline_switching = True
|
||||
|
||||
# Set tab to match if called from keyboard shortcut (but not if already from tab change)
|
||||
if not from_tab_change and self.timeline_tabs.currentIndex() != index:
|
||||
self.timeline_tabs.setCurrentIndex(index)
|
||||
|
||||
# Announce loading
|
||||
@ -478,6 +483,10 @@ class MainWindow(QMainWindow):
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_error()
|
||||
self.status_bar.showMessage(f"Failed to load {timeline_name} timeline: {str(e)}", 3000)
|
||||
finally:
|
||||
# Reset the flag after a brief delay to allow the operation to complete
|
||||
from PySide6.QtCore import QTimer
|
||||
QTimer.singleShot(100, lambda: setattr(self, '_current_timeline_switching', False))
|
||||
|
||||
def get_selected_post(self):
|
||||
"""Get the currently selected post from timeline"""
|
||||
@ -591,6 +600,9 @@ class MainWindow(QMainWindow):
|
||||
else:
|
||||
client.reblog_status(post.id)
|
||||
self.status_bar.showMessage("Post boosted", 2000)
|
||||
# Play boost sound for successful boost
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_boost()
|
||||
# Refresh timeline to show updated state
|
||||
self.timeline.refresh()
|
||||
except Exception as e:
|
||||
@ -610,6 +622,9 @@ class MainWindow(QMainWindow):
|
||||
else:
|
||||
client.favourite_status(post.id)
|
||||
self.status_bar.showMessage("Post favorited", 2000)
|
||||
# Play favorite sound for successful favorite
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_favorite()
|
||||
# Refresh timeline to show updated state
|
||||
self.timeline.refresh()
|
||||
except Exception as e:
|
||||
@ -630,6 +645,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def quit_application(self):
|
||||
"""Quit the application with shutdown sound"""
|
||||
self._shutdown_sound_played = True # Mark that we're handling the shutdown sound
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_shutdown()
|
||||
# Wait briefly for sound to start playing
|
||||
@ -761,6 +777,9 @@ class MainWindow(QMainWindow):
|
||||
client.follow_account(post.account.id)
|
||||
username = post.account.display_name or post.account.username
|
||||
self.status_bar.showMessage(f"Followed {username}", 2000)
|
||||
# Play follow sound for successful follow
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_follow()
|
||||
except Exception as e:
|
||||
self.status_bar.showMessage(f"Follow failed: {str(e)}", 3000)
|
||||
|
||||
@ -776,6 +795,9 @@ class MainWindow(QMainWindow):
|
||||
client.unfollow_account(post.account.id)
|
||||
username = post.account.display_name or post.account.username
|
||||
self.status_bar.showMessage(f"Unfollowed {username}", 2000)
|
||||
# Play unfollow sound for successful unfollow
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_unfollow()
|
||||
except Exception as e:
|
||||
self.status_bar.showMessage(f"Unfollow failed: {str(e)}", 3000)
|
||||
|
||||
@ -858,14 +880,17 @@ class MainWindow(QMainWindow):
|
||||
client.follow_account(target_account['id'])
|
||||
display_name = target_account.get('display_name') or target_account['username']
|
||||
self.status_bar.showMessage(f"Followed {display_name}", 2000)
|
||||
# Play follow sound for successful follow
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_follow()
|
||||
|
||||
except Exception as e:
|
||||
self.status_bar.showMessage(f"Follow failed: {str(e)}", 3000)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle window close event"""
|
||||
# Play shutdown sound if not already played through quit_application
|
||||
if hasattr(self.timeline, 'sound_manager'):
|
||||
# Only play shutdown sound if not already played through quit_application
|
||||
if not hasattr(self, '_shutdown_sound_played') and hasattr(self.timeline, 'sound_manager'):
|
||||
self.timeline.sound_manager.play_shutdown()
|
||||
# Wait briefly for sound to complete
|
||||
from PySide6.QtCore import QTimer, QEventLoop
|
||||
|
Reference in New Issue
Block a user