From 55a7f77a3370e23b0a83c816b62d5641c432dc1c Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Tue, 13 Jan 2026 14:29:37 +0500 Subject: [PATCH] fix(detail_pages): handle RuntimeError on detail page exit animation Signed-off-by: Boris Yumankulov --- portprotonqt/animations.py | 41 +++++++++++++++++++++++------------- portprotonqt/detail_pages.py | 4 +++- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/portprotonqt/animations.py b/portprotonqt/animations.py index 99f9244c..372ed27e 100644 --- a/portprotonqt/animations.py +++ b/portprotonqt/animations.py @@ -556,8 +556,11 @@ class DetailPageAnimations: if detail_page and not detail_page.isHidden(): detail_page.setGraphicsEffect(cast(Any, original_effect)) except RuntimeError: - logger.debug("Original effect already deleted") - cleanup_callback() + logger.debug("Detail page or effect already deleted") + try: + cleanup_callback() + except RuntimeError: + logger.debug("Error during cleanup callback") # Check if animation is still valid before starting if animation and not detail_page.isHidden(): @@ -594,10 +597,10 @@ class DetailPageAnimations: animation.setEasingCurve(easing_curve) def slide_cleanup(): - # Check if page is still valid before cleanup - if not detail_page or detail_page.isHidden(): - logger.debug("Detail page already cleaned up") - cleanup_callback() + try: + cleanup_callback() + except RuntimeError: + logger.debug("Error during slide cleanup callback") # Check if animation is still valid before starting if animation and not detail_page.isHidden(): @@ -647,20 +650,28 @@ class DetailPageAnimations: return def bounce_cleanup(): - # Check if page is still valid before cleanup - if not detail_page or detail_page.isHidden(): - logger.debug("Detail page already cleaned up") - cleanup_callback() + try: + cleanup_callback() + except RuntimeError: + logger.debug("Error during bounce cleanup callback") group_anim.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped) self.animations[detail_page] = group_anim group_anim.finished.connect(bounce_cleanup) except RuntimeError: - # Widget was already deleted, which is expected after deleteLater() logger.debug("Detail page already deleted during animation setup") - cleanup_callback() + try: + cleanup_callback() + except RuntimeError: + pass except Exception as e: logger.error(f"Error in animate_detail_page_exit: {e}", exc_info=True) - if detail_page in self.animations: - self.animations.pop(detail_page, None) - cleanup_callback() + try: + if detail_page in self.animations: + self.animations.pop(detail_page, None) + except RuntimeError: + pass + try: + cleanup_callback() + except RuntimeError: + pass diff --git a/portprotonqt/detail_pages.py b/portprotonqt/detail_pages.py index 7501921f..97d107bb 100644 --- a/portprotonqt/detail_pages.py +++ b/portprotonqt/detail_pages.py @@ -863,10 +863,12 @@ class DetailPageManager: logger.warning("Detail page not valid, bypassing animation and cleaning up directly") self._exit_animation_in_progress = False cleanup() + except RuntimeError: + logger.debug("Page deleted before animation could start") + self._exit_animation_in_progress = False except Exception as e: logger.error(f"Error starting exit animation: {e}", exc_info=True) self._exit_animation_in_progress = False - cleanup() # Fallback to cleanup if animation fails def open_portproton_forum_topic(self, name): result = self.portproton_api.get_forum_topic_slug(name)