Skip to content

Commit bebcba4

Browse files
authored
Merge pull request #18 from ChrisDuffley/master
Fix Boost/Favorite State mismatches
2 parents 8458ab7 + c41ebb7 commit bebcba4

2 files changed

Lines changed: 120 additions & 15 deletions

File tree

GUI/main.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,16 @@ def _sync_status_state_across_buffers(self, account, status_id, **state_updates)
570570
except (AttributeError, TypeError):
571571
pass
572572

573+
def _get_status_state_for_menu(self, status):
574+
"""Return status to check and state flags for menu labels."""
575+
if not status:
576+
return None, False, False, False
577+
status_to_check = status.reblog if hasattr(status, 'reblog') and status.reblog else status
578+
is_favourited = getattr(status_to_check, 'favourited', False) or getattr(status, 'favourited', False)
579+
is_reblogged = getattr(status_to_check, 'reblogged', False) or getattr(status, 'reblogged', False)
580+
is_bookmarked = getattr(status_to_check, 'bookmarked', False) or getattr(status, 'bookmarked', False)
581+
return status_to_check, is_favourited, is_reblogged, is_bookmarked
582+
573583
def OnHideWindow(self, event=None):
574584
"""Hide the window (menu handler)."""
575585
self.ToggleWindow()
@@ -1314,9 +1324,7 @@ def OnPostContextMenu(self, event=None):
13141324
else:
13151325
# Notifications with posts (favourite, reblog, mention, etc.)
13161326
notif_status = getattr(item, 'status', None)
1317-
is_favourited = getattr(notif_status, 'favourited', False) if notif_status else False
1318-
is_reblogged = getattr(notif_status, 'reblogged', False) if notif_status else False
1319-
is_bookmarked = getattr(notif_status, 'bookmarked', False) if notif_status else False
1327+
status_to_check, is_favourited, is_reblogged, is_bookmarked = self._get_status_state_for_menu(notif_status)
13201328
platform_type = getattr(get_app().currentAccount.prefs, 'platform_type', 'mastodon')
13211329

13221330
# View Image - only show if notification post has image attachments (at top of menu)
@@ -1460,10 +1468,7 @@ def OnPostContextMenu(self, event=None):
14601468

14611469
else:
14621470
# Standard post menu for all other timelines
1463-
status_to_check = item.reblog if hasattr(item, 'reblog') and item.reblog else item
1464-
is_favourited = getattr(status_to_check, 'favourited', False)
1465-
is_reblogged = getattr(status_to_check, 'reblogged', False)
1466-
is_bookmarked = getattr(status_to_check, 'bookmarked', False)
1471+
status_to_check, is_favourited, is_reblogged, is_bookmarked = self._get_status_state_for_menu(item)
14671472
platform_type = getattr(get_app().currentAccount.prefs, 'platform_type', 'mastodon')
14681473

14691474
# View Image - only show if post has image attachments (at top of menu)

GUI/view.py

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ def __init__(self, account, status):
272272
self.favourite.Bind(wx.EVT_BUTTON, self.OnFavourite)
273273
self.main_box.Add(self.favourite, 0, wx.ALL, 10)
274274

275+
self._update_action_labels()
276+
275277
if is_scheduled:
276278
# For scheduled posts, use own account name
277279
display_name = getattr(self.account.me, 'display_name', '') or self.account.me.acct
@@ -344,16 +346,55 @@ def __init__(self, account, status):
344346
self.panel.Layout()
345347
theme.apply_theme(self)
346348

349+
def _get_status_for_state(self):
350+
"""Return the status to check for state, plus favourited/reblogged flags."""
351+
status_to_check = self.status.reblog if hasattr(self.status, 'reblog') and self.status.reblog else self.status
352+
is_favourited = getattr(status_to_check, 'favourited', False) or getattr(self.status, 'favourited', False)
353+
is_reblogged = getattr(status_to_check, 'reblogged', False) or getattr(self.status, 'reblogged', False)
354+
return status_to_check, is_favourited, is_reblogged
355+
356+
def _set_status_state(self, status_to_check, attr, value):
357+
"""Apply state to the current status and any wrapped status."""
358+
try:
359+
setattr(status_to_check, attr, value)
360+
except Exception:
361+
pass
362+
if status_to_check is not self.status:
363+
try:
364+
setattr(self.status, attr, value)
365+
except Exception:
366+
pass
367+
if hasattr(self.status, 'reblog') and self.status.reblog and self.status.reblog is not status_to_check:
368+
try:
369+
setattr(self.status.reblog, attr, value)
370+
except Exception:
371+
pass
372+
373+
def _sync_status_state(self, status_id, **state_updates):
374+
from . import main
375+
if hasattr(main, 'window') and main.window:
376+
main.window._sync_status_state_across_buffers(self.account, status_id, **state_updates)
377+
378+
def _update_action_labels(self):
379+
status_to_check, is_favourited, is_reblogged = self._get_status_for_state()
380+
if hasattr(self, 'boost'):
381+
self.boost.SetLabel("Un&boost" if is_reblogged else "&Boost")
382+
if hasattr(self, 'favourite'):
383+
self.favourite.SetLabel("Un&favourite" if is_favourited else "&Favourite")
384+
347385
def OnLike(self, event):
348386
"""Like/favourite the post."""
349387
import speak
350388
try:
351-
status_id = misc.get_interaction_id(self.account, self.status)
352-
if not getattr(self.status, 'favourited', False):
389+
status_to_check, is_favourited, _ = self._get_status_for_state()
390+
status_id = misc.get_interaction_id(self.account, status_to_check)
391+
if not is_favourited:
353392
self.account.favourite(status_id)
354393
self.account.app.prefs.favourites_sent += 1
355-
self.status.favourited = True
394+
self._set_status_state(status_to_check, 'favourited', True)
395+
self._sync_status_state(status_id, favourited=True)
356396
sound.play(self.account, "like")
397+
self._update_action_labels()
357398
else:
358399
speak.speak("Already liked")
359400
except Exception as error:
@@ -363,11 +404,14 @@ def OnUnlike(self, event):
363404
"""Unlike/unfavourite the post."""
364405
import speak
365406
try:
366-
status_id = misc.get_interaction_id(self.account, self.status)
367-
if getattr(self.status, 'favourited', False):
407+
status_to_check, is_favourited, _ = self._get_status_for_state()
408+
status_id = misc.get_interaction_id(self.account, status_to_check)
409+
if is_favourited:
368410
self.account.unfavourite(status_id)
369-
self.status.favourited = False
411+
self._set_status_state(status_to_check, 'favourited', False)
412+
self._sync_status_state(status_id, favourited=False)
370413
sound.play(self.account, "unlike")
414+
self._update_action_labels()
371415
else:
372416
speak.speak("Not liked")
373417
except Exception as error:
@@ -389,7 +433,35 @@ def OnReply(self, event):
389433
misc.reply(self.account, self.status)
390434

391435
def OnBoost(self, event):
392-
misc.boost(self.account, self.status)
436+
try:
437+
status_to_check, _, is_reblogged = self._get_status_for_state()
438+
status_id = misc.get_interaction_id(self.account, status_to_check)
439+
if is_reblogged:
440+
if get_app().prefs.confirm_unboost:
441+
dlg = wx.MessageDialog(self, "Are you sure you want to unboost this post?", "Confirm Unboost", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
442+
if dlg.ShowModal() != wx.ID_YES:
443+
dlg.Destroy()
444+
return
445+
dlg.Destroy()
446+
self.account.unboost(status_id)
447+
new_state = False
448+
sound.play(self.account, "delete")
449+
else:
450+
if get_app().prefs.confirm_boost:
451+
dlg = wx.MessageDialog(self, "Are you sure you want to boost this post?", "Confirm Boost", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
452+
if dlg.ShowModal() != wx.ID_YES:
453+
dlg.Destroy()
454+
return
455+
dlg.Destroy()
456+
self.account.boost(status_id)
457+
self.account.app.prefs.boosts_sent += 1
458+
new_state = True
459+
sound.play(self.account, "send_repost")
460+
self._set_status_state(status_to_check, 'reblogged', new_state)
461+
self._sync_status_state(status_id, reblogged=new_state)
462+
self._update_action_labels()
463+
except Exception as error:
464+
self.account.app.handle_error(error, "toggle boost")
393465

394466
def OnViewBoosters(self, event):
395467
users = []
@@ -461,7 +533,35 @@ def OnViewQuotes(self, event):
461533
self.account.app.handle_error(error, "view quotes")
462534

463535
def OnFavourite(self, event):
464-
misc.favourite(self.account, self.status)
536+
try:
537+
status_to_check, is_favourited, _ = self._get_status_for_state()
538+
status_id = misc.get_interaction_id(self.account, status_to_check)
539+
if is_favourited:
540+
if get_app().prefs.confirm_unfavorite:
541+
dlg = wx.MessageDialog(self, "Are you sure you want to unfavorite this post?", "Confirm Unfavorite", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
542+
if dlg.ShowModal() != wx.ID_YES:
543+
dlg.Destroy()
544+
return
545+
dlg.Destroy()
546+
self.account.unfavourite(status_id)
547+
new_state = False
548+
sound.play(self.account, "unlike")
549+
else:
550+
if get_app().prefs.confirm_favorite:
551+
dlg = wx.MessageDialog(self, "Are you sure you want to favorite this post?", "Confirm Favorite", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
552+
if dlg.ShowModal() != wx.ID_YES:
553+
dlg.Destroy()
554+
return
555+
dlg.Destroy()
556+
self.account.favourite(status_id)
557+
self.account.app.prefs.favourites_sent += 1
558+
new_state = True
559+
sound.play(self.account, "like")
560+
self._set_status_state(status_to_check, 'favourited', new_state)
561+
self._sync_status_state(status_id, favourited=new_state)
562+
self._update_action_labels()
563+
except Exception as error:
564+
self.account.app.handle_error(error, "toggle favourite")
465565

466566
def OnProfile(self, event):
467567
u = [self.status.account]

0 commit comments

Comments
 (0)