diff --git a/doc/changelog.md b/doc/changelog.md index 4192a284..4207fbed 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -5,6 +5,7 @@ TWBlue Changelog * Core: * Expanded the keystroke editor actions list. Now, many previously hidden or unassignable actions are available to be mapped to custom keyboard shortcuts. * Mastodon: + * Added the ability to pin and unpin your own posts directly from TWBlue. This action acts as a toggle and can be accessed from the post's context menu or by assigning a keyboard shortcut in the keystroke editor. * Fixed an issue where pinned posts could cause the retrieval of large amounts of old content during buffer updates or when loading more items. * Added support for sending quoted posts! You can now quote other users' posts from the context menu or the new Boost dialog. ([#860](https://github.com/mcv-software/twblue/issues/860)) * Fixed an issue where HTML entities were not decoded when editing a post. ([#893](https://github.com/mcv-software/twblue/issues/893)) diff --git a/src/controller/buffers/mastodon/base.py b/src/controller/buffers/mastodon/base.py index 1ca21ac1..63b24247 100644 --- a/src/controller/buffers/mastodon/base.py +++ b/src/controller/buffers/mastodon/base.py @@ -328,6 +328,15 @@ class BaseBuffer(base.Buffer): widgetUtils.connect_event(menu, widgetUtils.MENU, self.edit_status, menuitem=menu.edit) else: menu.edit.Enable(False) + # Enable/disable pin based on whether the post belongs to the user + if item and item.account.id == self.session.db["user_id"] and item.reblog == None and item.visibility in ["public", "unlisted"]: + widgetUtils.connect_event(menu, widgetUtils.MENU, self.pin_status, menuitem=menu.pin) + if item.pinned: + menu.pin.SetItemLabel(_("Unpin")) + else: + menu.pin.SetItemLabel(_("Pin")) + else: + menu.pin.Enable(False) widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions) if self.can_share() == True: widgetUtils.connect_event(menu, widgetUtils.MENU, self.share_item, menuitem=menu.boost) @@ -614,6 +623,25 @@ class BaseBuffer(base.Buffer): if hasattr(post.message, "destroy"): post.message.destroy() + def pin_status(self, event=None, item=None, *args, **kwargs): + if item == None: + item = self.get_item() + # Check if the post belongs to the current user + if item.account.id != self.session.db["user_id"] or item.reblog != None: + output.speak(_("You can only pin your own posts.")) + return + + try: + item = self.session.api.status(item.id) + except MastodonNotFoundError: + output.speak(_("No status found with that ID")) + return + + if item.pinned: + call_threaded(self.session.unpin_post, post_id=item.id) + else: + call_threaded(self.session.pin_post, post_id=item.id) + def user_details(self): item = self.get_item() pass diff --git a/src/controller/mainController.py b/src/controller/mainController.py index fef23b5c..4a68ba53 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -458,6 +458,14 @@ class Controller(object): if hasattr(buffer, "edit_status"): buffer.edit_status() + def pin_post(self, *args, **kwargs): + """ Pins or unpins a post in the current buffer. """ + buffer = self.view.get_current_buffer() + if hasattr(buffer, "account"): + buffer = self.search_buffer(buffer.name, buffer.account) + if hasattr(buffer, "pin_status"): + buffer.pin_status() + def exit(self, *args, **kwargs): if config.app["app-settings"]["ask_at_exit"] == True: answer = commonMessageDialogs.exit_dialog(self.view) diff --git a/src/keymaps/Chicken Nugget.keymap b/src/keymaps/Chicken Nugget.keymap index 29832008..29fae397 100644 --- a/src/keymaps/Chicken Nugget.keymap +++ b/src/keymaps/Chicken Nugget.keymap @@ -38,6 +38,7 @@ open_in_browser = string(default="alt+control+win+return") add_alias=string(default="") vote=string(default="alt+win+shift+v") edit_post=string(default="") +pin_post=string(default="") open_favs_timeline=string(default="") community_timeline=string(default="") seekLeft=string(default="") diff --git a/src/keymaps/Qwitter.keymap b/src/keymaps/Qwitter.keymap index ddd1fe6d..540b0199 100644 --- a/src/keymaps/Qwitter.keymap +++ b/src/keymaps/Qwitter.keymap @@ -57,6 +57,7 @@ open_in_browser = string(default="alt+control+win+return") add_alias=string(default="") vote=string(default="alt+win+shift+v") edit_post=string(default="") +pin_post=string(default="") open_favs_timeline=string(default="") community_timeline=string(default="") seekLeft=string(default="") diff --git a/src/keymaps/Windows 10.keymap b/src/keymaps/Windows 10.keymap index 3e969518..790fa2fd 100644 --- a/src/keymaps/Windows 10.keymap +++ b/src/keymaps/Windows 10.keymap @@ -60,6 +60,7 @@ mute_conversation=string(default="control+alt+win+back") find = string(default="control+win+{") vote=string(default="alt+win+shift+v") edit_post=string(default="") +pin_post=string(default="") open_favs_timeline=string(default="") community_timeline=string(default="") seekLeft=string(default="") diff --git a/src/keymaps/Windows11.keymap b/src/keymaps/Windows11.keymap index 779c3b3b..a14c2b30 100644 --- a/src/keymaps/Windows11.keymap +++ b/src/keymaps/Windows11.keymap @@ -60,6 +60,7 @@ mute_conversation=string(default="control+alt+win+back") find = string(default="control+win+{") vote=string(default="alt+win+shift+v") edit_post=string(default="") +pin_post=string(default="") open_favs_timeline=string(default="") community_timeline=string(default="") seekLeft=string(default="") diff --git a/src/keymaps/base.template b/src/keymaps/base.template index ad514d8d..df894e1e 100644 --- a/src/keymaps/base.template +++ b/src/keymaps/base.template @@ -60,6 +60,7 @@ add_alias=string(default="") mute_conversation=string(default="alt+win+shift+delete") vote=string(default="alt+win+shift+v") edit_post=string(default="") +pin_post=string(default="") open_favs_timeline=string(default="") community_timeline=string(default="") seekLeft=string(default="") diff --git a/src/keymaps/default.keymap b/src/keymaps/default.keymap index fa70c756..d4ebf254 100644 --- a/src/keymaps/default.keymap +++ b/src/keymaps/default.keymap @@ -61,6 +61,7 @@ add_alias=string(default="") mute_conversation=string(default="alt+win+shift+delete") vote=string(default="alt+win+shift+v") edit_post=string(default="") +pin_post=string(default="") open_favs_timeline=string(default="") community_timeline=string(default="") seekLeft=string(default="") diff --git a/src/keystrokeEditor/actions/mastodon.py b/src/keystrokeEditor/actions/mastodon.py index 613687c3..115ddf75 100644 --- a/src/keystrokeEditor/actions/mastodon.py +++ b/src/keystrokeEditor/actions/mastodon.py @@ -56,6 +56,7 @@ actions = { "add_alias": _("Adds an alias to an user"), "mute_conversation": _("Mute/Unmute conversation"), "edit_post": _(u"Edit the selected post"), + "pin_post": _(u"Pin/Unpin the selected post"), "vote": _(u"Vote in the selected poll"), "open_favs_timeline": _(u"Open favorites timeline"), "community_timeline": _(u"Open local/federated timeline"), diff --git a/src/sessions/mastodon/session.py b/src/sessions/mastodon/session.py index ab0dd1b2..b0dfbc42 100644 --- a/src/sessions/mastodon/session.py +++ b/src/sessions/mastodon/session.py @@ -411,6 +411,24 @@ class Session(base.baseSession): output.speak(_("Error editing post: {}").format(str(e))) return None + def pin_post(self, post_id): + """ Pins a post. """ + try: + item = self.api_call(call_name="status_pin", id=post_id, _sound="pin.ogg", report_success=True, action=_("Pin")) + return item + except MastodonAPIError as e: + output.speak(_("Error pinning post: {}").format(str(e))) + return None + + def unpin_post(self, post_id): + """ Unpins a post. """ + try: + item = self.api_call(call_name="status_unpin", id=post_id, _sound="unpin.ogg", report_success=True, action=_("Unpin")) + return item + except MastodonAPIError as e: + output.speak(_("Error unpinning post: {}").format(str(e))) + return None + def get_name(self): instance = self.settings["mastodon"]["instance"] instance = instance.replace("https://", "") diff --git a/src/wxUI/dialogs/mastodon/menus.py b/src/wxUI/dialogs/mastodon/menus.py index b7277ab4..28d2a5b6 100644 --- a/src/wxUI/dialogs/mastodon/menus.py +++ b/src/wxUI/dialogs/mastodon/menus.py @@ -12,6 +12,8 @@ class base(wx.Menu): self.Append(self.reply) self.edit = wx.MenuItem(self, wx.ID_ANY, _(u"&Edit")) self.Append(self.edit) + self.pin = wx.MenuItem(self, wx.ID_ANY, _("&Pin/Unpin")) + self.Append(self.pin) self.fav = wx.MenuItem(self, wx.ID_ANY, _(u"&Add to favorites")) self.Append(self.fav) self.unfav = wx.MenuItem(self, wx.ID_ANY, _(u"R&emove from favorites")) @@ -46,6 +48,8 @@ class notification(wx.Menu): self.Append(self.reply) self.edit = wx.MenuItem(self, wx.ID_ANY, _(u"&Edit")) self.Append(self.edit) + self.pin = wx.MenuItem(self, wx.ID_ANY, _("&Pin/Unpin")) + self.Append(self.pin) self.fav = wx.MenuItem(self, wx.ID_ANY, _(u"&Add to favorites")) self.Append(self.fav) self.unfav = wx.MenuItem(self, wx.ID_ANY, _(u"R&emove from favorites"))