added actions, following, followers and posts button to show user profile dialog

This commit is contained in:
Abdulqadir Ahmad 2023-08-27 17:56:39 +01:00
parent 15e2032afb
commit f4ec03099a
3 changed files with 170 additions and 93 deletions

View File

@ -986,9 +986,9 @@ class Controller(object):
def repeat_item(self, *args, **kwargs): def repeat_item(self, *args, **kwargs):
output.speak(self.get_current_buffer().get_message()) output.speak(self.get_current_buffer().get_message())
def execute_action(self, action): def execute_action(self, action, kwargs={}):
if hasattr(self, action): if hasattr(self, action):
getattr(self, action)() getattr(self, action)(**kwargs)
def update_buffers(self): def update_buffers(self):
for i in self.buffers[:]: for i in self.buffers[:]:
@ -1102,4 +1102,37 @@ class Controller(object):
buffer = self.get_best_buffer() buffer = self.get_best_buffer()
handler = self.get_handler(type=buffer.session.type) handler = self.get_handler(type=buffer.session.type)
if handler and hasattr(handler, 'showUserProfile'): if handler and hasattr(handler, 'showUserProfile'):
handler.showUserProfile(buffer=buffer) handler.showUserProfile(buffer)
def openPostTimeline(self, *args, user=None):
"""Opens selected user's posts timeline
Parameters:
args: Other argument. Useful when binding to widgets.
user: if specified, open this user timeline. It is currently mandatory, but could be optional when user selection is implemented in handler
"""
buffer = self.get_best_buffer()
handler = self.get_handler(type=buffer.session.type)
if handler and hasattr(handler, 'openPostTimeline'):
handler.openPostTimeline(self, buffer, user)
def openFollowersTimeline(self, *args, user=None):
"""Opens selected user's followers timeline
Parameters:
args: Other argument. Useful when binding to widgets.
user: if specified, open this user timeline. It is currently mandatory, but could be optional when user selection is implemented in handler
"""
buffer = self.get_best_buffer()
handler = self.get_handler(type=buffer.session.type)
if handler and hasattr(handler, 'openFollowersTimeline'):
handler.openFollowersTimeline(self, buffer, user)
def openFollowingTimeline(self, *args, user=None):
"""Opens selected user's following timeline
Parameters:
args: Other argument. Useful when binding to widgets.
user: if specified, open this user timeline. It is currently mandatory, but could be optional when user selection is implemented in handler
"""
buffer = self.get_best_buffer()
handler = self.get_handler(type=buffer.session.type)
if handler and hasattr(handler, 'openFollowingTimeline'):
handler.openFollowingTimeline(self, buffer, user)

View File

@ -186,38 +186,52 @@ class Handler(object):
return return
user = u.user user = u.user
if action == "posts": if action == "posts":
if user.statuses_count == 0: self.openPostTimeline(controller, buffer, user)
dialogs.no_posts()
return
if user.id in buffer.session.settings["other_buffers"]["timelines"]:
commonMessageDialogs.timeline_exist()
return
timelines_position =controller.view.search("timelines", buffer.session.get_name())
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=buffer.session.type, buffer_title=_("Timeline for {}").format(user.username,), parent_tab=timelines_position, start=True, kwargs=dict(parent=controller.view.nb, function="account_statuses", name="%s-timeline" % (user.id,), sessionObject=buffer.session, account=buffer.session.get_name(), sound="tweet_timeline.ogg", id=user.id))
buffer.session.settings["other_buffers"]["timelines"].append(user.id)
buffer.session.sound.play("create_timeline.ogg")
elif action == "followers": elif action == "followers":
if user.followers_count == 0: self.openFollowersTimeline(controller, buffer, user)
dialogs.no_followers()
return
if user.id in buffer.session.settings["other_buffers"]["followers_timelines"]:
commonMessageDialogs.timeline_exist()
return
timelines_position =controller.view.search("timelines", buffer.session.get_name())
pub.sendMessage("createBuffer", buffer_type="UserBuffer", session_type=buffer.session.type, buffer_title=_("Followers for {}").format(user.username,), parent_tab=timelines_position, start=True, kwargs=dict(parent=controller.view.nb, compose_func="compose_user", function="account_followers", name="%s-followers" % (user.id,), sessionObject=buffer.session, account=buffer.session.get_name(), sound="new_event.ogg", id=user.id))
buffer.session.settings["other_buffers"]["followers_timelines"].append(user.id)
buffer.session.sound.play("create_timeline.ogg")
elif action == "following": elif action == "following":
if user.following_count == 0: self.openFollowingTimeline(controller, buffer, user)
dialogs.no_following()
return def openPostTimeline(self, controller, buffer, user):
if user.id in buffer.session.settings["other_buffers"]["following_timelines"]: """Opens post timeline for user"""
commonMessageDialogs.timeline_exist() if user.statuses_count == 0:
return dialogs.no_posts()
timelines_position =controller.view.search("timelines", buffer.session.get_name()) return
pub.sendMessage("createBuffer", buffer_type="UserBuffer", session_type=buffer.session.type, buffer_title=_("Following for {}").format(user.username,), parent_tab=timelines_position, start=True, kwargs=dict(parent=controller.view.nb, compose_func="compose_user", function="account_following", name="%s-followers" % (user.id,), sessionObject=buffer.session, account=buffer.session.get_name(), sound="new_event.ogg", id=user.id)) if user.id in buffer.session.settings["other_buffers"]["timelines"]:
buffer.session.settings["other_buffers"]["following_timelines"].append(user.id) commonMessageDialogs.timeline_exist()
buffer.session.sound.play("create_timeline.ogg") return
timelines_position =controller.view.search("timelines", buffer.session.get_name())
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=buffer.session.type, buffer_title=_("Timeline for {}").format(user.username,), parent_tab=timelines_position, start=True, kwargs=dict(parent=controller.view.nb, function="account_statuses", name="%s-timeline" % (user.id,), sessionObject=buffer.session, account=buffer.session.get_name(), sound="tweet_timeline.ogg", id=user.id))
buffer.session.settings["other_buffers"]["timelines"].append(user.id)
buffer.session.sound.play("create_timeline.ogg")
buffer.session.settings.write()
def openFollowersTimeline(self, controller, buffer, user):
"""Open followers timeline for user"""
if user.followers_count == 0:
dialogs.no_followers()
return
if user.id in buffer.session.settings["other_buffers"]["followers_timelines"]:
commonMessageDialogs.timeline_exist()
return
timelines_position =controller.view.search("timelines", buffer.session.get_name())
pub.sendMessage("createBuffer", buffer_type="UserBuffer", session_type=buffer.session.type, buffer_title=_("Followers for {}").format(user.username,), parent_tab=timelines_position, start=True, kwargs=dict(parent=controller.view.nb, compose_func="compose_user", function="account_followers", name="%s-followers" % (user.id,), sessionObject=buffer.session, account=buffer.session.get_name(), sound="new_event.ogg", id=user.id))
buffer.session.settings["other_buffers"]["followers_timelines"].append(user.id)
buffer.session.sound.play("create_timeline.ogg")
buffer.session.settings.write()
def openFollowingTimeline(self, controller, buffer, user):
"""Open following timeline for user"""
if user.following_count == 0:
dialogs.no_following()
return
if user.id in buffer.session.settings["other_buffers"]["following_timelines"]:
commonMessageDialogs.timeline_exist()
return
timelines_position =controller.view.search("timelines", buffer.session.get_name())
pub.sendMessage("createBuffer", buffer_type="UserBuffer", session_type=buffer.session.type, buffer_title=_("Following for {}").format(user.username,), parent_tab=timelines_position, start=True, kwargs=dict(parent=controller.view.nb, compose_func="compose_user", function="account_following", name="%s-followers" % (user.id,), sessionObject=buffer.session, account=buffer.session.get_name(), sound="new_event.ogg", id=user.id))
buffer.session.settings["other_buffers"]["following_timelines"].append(user.id)
buffer.session.sound.play("create_timeline.ogg")
buffer.session.settings.write() buffer.session.settings.write()
def account_settings(self, buffer, controller): def account_settings(self, buffer, controller):
@ -293,39 +307,38 @@ class Handler(object):
def showUserProfile(self, buffer): def showUserProfile(self, buffer):
"""Displays user profile in a dialog. """Displays user profile in a dialog.
This works as long as the focused item hass a 'account' key.""" This works as long as the focused item hass a 'account' key."""
log.debug("Scraping for users in handler")
if not hasattr(buffer, 'get_item'): if not hasattr(buffer, 'get_item'):
return # Tell user? return # Tell user?
item = buffer.get_item() item = buffer.get_item()
if not item: if not item:
return # empty buffer return # empty buffer
holdUser = item.get('account') log.debug(f"Opening user profile. dictionary: {item}")
users = [holdUser] mentionedUsers = list()
if item.get('mentions'): holdUser = item.account if item.get('account') else None
if item.get('username'): # account dict
holdUser = item
elif isinstance(item.get('mentions'), list):
# mentions in statuses # mentions in statuses
if item.reblog: if item.reblog:
item = item.reblog item = item.reblog
users = [(user.acct, user.id) for user in item.mentions] mentionedUsers = [(user.acct, user.id) for user in item.mentions]
users.insert(0, (item.account.display_name, item.account.username, item.account.id))
holdUser = item.account holdUser = item.account
elif not holdUser: if not holdUser:
dialogs.no_user() dialogs.no_user()
return return
if len(users) == 1: if len(mentionedUsers) == 0:
user = holdUser user = holdUser
else: else:
users = list(set(users)) mentionedUsers.insert(0, (holdUser.display_name, holdUser.username, holdUser.id))
selectedUser = showUserProfile.selectUserDialog(users) mentionedUsers = list(set(mentionedUsers))
selectedUser = showUserProfile.selectUserDialog(mentionedUsers)
if not selectedUser: if not selectedUser:
return # Canceled selection return # Canceled selection
elif selectedUser[-1] == holdUser.id: elif selectedUser[-1] == holdUser.id:
user = holdUser user = holdUser
else: # We don't have this user's dictionary, get it! else: # We don't have this user's dictionary, get it!
user = buffer.session.api.account(selectedUser[-1]) user = buffer.session.api.account(selectedUser[-1])
dlg = showUserProfile.ShowUserProfile( dlg = showUserProfile.ShowUserProfile(user)
user.display_name, user.url, user.created_at, html_filter(user.note), user.header, user.avatar,
[(field.name, html_filter(field.value)) for field in user.fields], user.locked, user.bot, user.discoverable
)
dlg.ShowModal() dlg.ShowModal()

View File

@ -2,10 +2,14 @@
"""Wx dialogs for showing a user's profile.""" """Wx dialogs for showing a user's profile."""
from io import BytesIO from io import BytesIO
from pubsub import pub
from typing import Tuple from typing import Tuple
import requests import requests
import wx import wx
from sessions.mastodon.utils import html_filter
def _(s): def _(s):
return s return s
@ -58,46 +62,47 @@ class ShowUserProfile(wx.Dialog):
``` ```
""" """
def __init__(self, display_name: str, url: str, created_at, note: str, header: str, avatar: str, fields: list, locked: bool, bot: bool, discoverable: bool): def __init__(self, user):
"""Initialize update profile dialog """Initialize update profile dialog
Parameters: Parameters:
- display_name: The user's display name to show in the display name field - user: user dictionary
- url: The user's url
- note: The users bio to show in the bio field
- header: the users header pic link
- avatar: The users avatar pic link
""" """
super().__init__(parent=None) super().__init__(parent=None)
self.SetTitle(_("{}'s Profile").format(display_name)) self.user = user
self.SetTitle(_("{}'s Profile").format(user.display_name))
self.panel = wx.Panel(self) self.panel = wx.Panel(self)
wrapperSizer = wx.BoxSizer(wx.VERTICAL) wrapperSizer = wx.BoxSizer(wx.VERTICAL)
topSizer = wx.GridSizer(2, 10, 5, 5) mainSizer = wx.GridSizer(12, 2, 5, 5)
# create widgets # create widgets
nameLabel = wx.StaticText(self.panel, label=_("Name: ")) nameLabel = wx.StaticText(self.panel, label=_("Name: "))
name = self.createTextCtrl(display_name, size=(200, 30)) name = self.createTextCtrl(user.display_name, size=(200, 30))
topSizer.Add(nameLabel, wx.SizerFlags().Center()) mainSizer.Add(nameLabel, wx.SizerFlags().Center())
topSizer.Add(name, wx.SizerFlags().Center()) mainSizer.Add(name, wx.SizerFlags().Center())
urlLabel = wx.StaticText(self.panel, label=_("URL: ")) urlLabel = wx.StaticText(self.panel, label=_("URL: "))
url = self.createTextCtrl(url, size=(200, 30)) url = self.createTextCtrl(user.url, size=(200, 30))
topSizer.Add(urlLabel, wx.SizerFlags().Center()) mainSizer.Add(urlLabel, wx.SizerFlags().Center())
topSizer.Add(url, wx.SizerFlags().Center()) mainSizer.Add(url, wx.SizerFlags().Center())
joinLabel = wx.StaticText(self.panel, label=_("Joined at: "))
joinText = self.createTextCtrl(created_at.strftime('%d %B, %Y'), (80, 30))
topSizer.Add(joinLabel, wx.SizerFlags().Center())
topSizer.Add(joinText, wx.SizerFlags().Center())
bioLabel = wx.StaticText(self.panel, label=_("Bio: ")) bioLabel = wx.StaticText(self.panel, label=_("Bio: "))
bio = self.createTextCtrl(note, (400, 60)) bio = self.createTextCtrl(html_filter(user.note), (400, 60))
topSizer.Add(bioLabel, wx.SizerFlags().Center()) mainSizer.Add(bioLabel, wx.SizerFlags().Center())
topSizer.Add(bio, wx.SizerFlags().Center()) mainSizer.Add(bio, wx.SizerFlags().Center())
joinLabel = wx.StaticText(self.panel, label=_("Joined at: "))
joinText = self.createTextCtrl(user.created_at.strftime('%d %B, %Y'), (80, 30))
mainSizer.Add(joinLabel, wx.SizerFlags().Center())
mainSizer.Add(joinText, wx.SizerFlags().Center())
actions = wx.Button(self.panel, label=_("Actions"))
actions.Bind(wx.EVT_BUTTON, self.onAction)
mainSizer.Add(actions, wx.SizerFlags().Center())
# header # header
headerLabel = wx.StaticText(self.panel, label=_("Header: ")) headerLabel = wx.StaticText(self.panel, label=_("Header: "))
try: try:
response = requests.get(header) response = requests.get(user.header)
except requests.exceptions.RequestException: except requests.exceptions.RequestException:
# Create empty image # Create empty image
headerImage = wx.StaticBitmap() headerImage = wx.StaticBitmap()
@ -108,13 +113,13 @@ class ShowUserProfile(wx.Dialog):
headerImage = wx.StaticBitmap(self.panel, bitmap=image.ConvertToBitmap()) headerImage = wx.StaticBitmap(self.panel, bitmap=image.ConvertToBitmap())
headerImage.AcceptsFocusFromKeyboard = returnTrue headerImage.AcceptsFocusFromKeyboard = returnTrue
topSizer.Add(headerLabel, wx.SizerFlags().Center()) mainSizer.Add(headerLabel, wx.SizerFlags().Center())
topSizer.Add(headerImage, wx.SizerFlags().Center()) mainSizer.Add(headerImage, wx.SizerFlags().Center())
# avatar # avatar
avatarLabel = wx.StaticText(self.panel, label=_("Avatar: ")) avatarLabel = wx.StaticText(self.panel, label=_("Avatar: "))
try: try:
response = requests.get(avatar) response = requests.get(user.avatar)
except requests.exceptions.RequestException: except requests.exceptions.RequestException:
# Create empty image # Create empty image
avatarImage = wx.StaticBitmap() avatarImage = wx.StaticBitmap()
@ -125,59 +130,69 @@ class ShowUserProfile(wx.Dialog):
avatarImage = wx.StaticBitmap(self.panel, bitmap=image.ConvertToBitmap()) avatarImage = wx.StaticBitmap(self.panel, bitmap=image.ConvertToBitmap())
avatarImage.AcceptsFocusFromKeyboard = returnTrue avatarImage.AcceptsFocusFromKeyboard = returnTrue
topSizer.Add(avatarLabel, wx.SizerFlags().Center()) mainSizer.Add(avatarLabel, wx.SizerFlags().Center())
topSizer.Add(avatarImage, wx.SizerFlags().Center()) mainSizer.Add(avatarImage, wx.SizerFlags().Center())
self.fields = [] self.fields = []
for num, (label, content) in enumerate(fields): for num, field in enumerate(user.fields):
labelSizer = wx.BoxSizer(wx.HORIZONTAL) labelSizer = wx.BoxSizer(wx.HORIZONTAL)
labelLabel = wx.StaticText(self.panel, label=_("Field {} - Label: ").format(num + 1)) labelLabel = wx.StaticText(self.panel, label=_("Field {} - Label: ").format(num + 1))
labelSizer.Add(labelLabel, wx.SizerFlags().Center().Border(wx.ALL, 5)) labelSizer.Add(labelLabel, wx.SizerFlags().Center().Border(wx.ALL, 5))
labelText = self.createTextCtrl(label, (230, 30), True) labelText = self.createTextCtrl(html_filter(field.name), (230, 30), True)
labelSizer.Add(labelText, wx.SizerFlags().Expand().Border(wx.ALL, 5)) labelSizer.Add(labelText, wx.SizerFlags().Expand().Border(wx.ALL, 5))
topSizer.Add(labelSizer, 0, wx.CENTER) mainSizer.Add(labelSizer, 0, wx.CENTER)
contentSizer = wx.BoxSizer(wx.HORIZONTAL) contentSizer = wx.BoxSizer(wx.HORIZONTAL)
contentLabel = wx.StaticText(self.panel, label=_("Content: ")) contentLabel = wx.StaticText(self.panel, label=_("Content: "))
contentSizer.Add(contentLabel, wx.SizerFlags().Center()) contentSizer.Add(contentLabel, wx.SizerFlags().Center())
contentText = self.createTextCtrl(content, (400, 60), True) contentText = self.createTextCtrl(html_filter(field.value), (400, 60), True)
contentSizer.Add(contentText, wx.SizerFlags().Center()) contentSizer.Add(contentText, wx.SizerFlags().Center())
topSizer.Add(contentSizer, 0, wx.CENTER | wx.LEFT, 10) mainSizer.Add(contentSizer, 0, wx.CENTER | wx.LEFT, 10)
# 3 X 2 grid sizer
bottomSizer = wx.GridSizer(3, 2, 10, 5)
bullSwitch = {True: _('Yes'), False: _('No'), None: _('No')} bullSwitch = {True: _('Yes'), False: _('No'), None: _('No')}
privateSizer = wx.BoxSizer(wx.HORIZONTAL) privateSizer = wx.BoxSizer(wx.HORIZONTAL)
privateLabel = wx.StaticText(self.panel, label=_("Private account: ")) privateLabel = wx.StaticText(self.panel, label=_("Private account: "))
private = self.createTextCtrl(bullSwitch[locked], (30, 30)) private = self.createTextCtrl(bullSwitch[user.locked], (30, 30))
privateSizer.Add(privateLabel, wx.SizerFlags().Center()) privateSizer.Add(privateLabel, wx.SizerFlags().Center())
privateSizer.Add(private, wx.SizerFlags().Center()) privateSizer.Add(private, wx.SizerFlags().Center())
bottomSizer.Add(privateSizer, 0, wx.ALL | wx.CENTER) mainSizer.Add(privateSizer, 0, wx.ALL | wx.CENTER)
botSizer = wx.BoxSizer(wx.HORIZONTAL) botSizer = wx.BoxSizer(wx.HORIZONTAL)
botLabel = wx.StaticText(self.panel, label=_("Bot account: ")) botLabel = wx.StaticText(self.panel, label=_("Bot account: "))
botText = self.createTextCtrl(bullSwitch[bot], (30, 30)) botText = self.createTextCtrl(bullSwitch[user.bot], (30, 30))
botSizer.Add(botLabel, wx.SizerFlags().Center()) botSizer.Add(botLabel, wx.SizerFlags().Center())
botSizer.Add(botText, wx.SizerFlags().Center()) botSizer.Add(botText, wx.SizerFlags().Center())
bottomSizer.Add(botSizer, 0, wx.ALL | wx.CENTER) mainSizer.Add(botSizer, 0, wx.ALL | wx.CENTER)
discoverSizer = wx.BoxSizer(wx.HORIZONTAL) discoverSizer = wx.BoxSizer(wx.HORIZONTAL)
discoverLabel = wx.StaticText(self.panel, label=_("Discoverable account: ")) discoverLabel = wx.StaticText(self.panel, label=_("Discoverable account: "))
discoverText = self.createTextCtrl(bullSwitch[discoverable], (30, 30)) discoverText = self.createTextCtrl(bullSwitch[user.discoverable], (30, 30))
discoverSizer.Add(discoverLabel, wx.SizerFlags().Center()) discoverSizer.Add(discoverLabel, wx.SizerFlags().Center())
discoverSizer.Add(discoverText, wx.SizerFlags().Center()) discoverSizer.Add(discoverText, wx.SizerFlags().Center())
bottomSizer.Add(discoverSizer, 0, wx.ALL | wx.CENTER) mainSizer.Add(discoverSizer, 0, wx.ALL | wx.CENTER)
posts = wx.Button(self.panel, label=_("{} posts. Click to open posts timeline").format(user.statuses_count))
# posts.SetToolTip(_("Click to open {}'s posts").format(user.display_name))
posts.Bind(wx.EVT_BUTTON, self.onPost)
mainSizer.Add(posts, wx.SizerFlags().Center())
following = wx.Button(self.panel, label=_("{} following. Click to open Following timeline").format(user.following_count))
mainSizer.Add(following, wx.SizerFlags().Center())
following.Bind(wx.EVT_BUTTON, self.onFollowing)
followers = wx.Button(self.panel, label=_("{} followers. Click to open followers timeline").format(user.followers_count))
mainSizer.Add(followers, wx.SizerFlags().Center())
followers.Bind(wx.EVT_BUTTON, self.onFollowers)
close = wx.Button(self.panel, wx.ID_CLOSE, _("Close")) close = wx.Button(self.panel, wx.ID_CLOSE, _("Close"))
self.SetEscapeId(close.GetId()) self.SetEscapeId(close.GetId())
close.SetDefault() close.SetDefault()
wrapperSizer.Add(topSizer, 0, wx.CENTER) wrapperSizer.Add(mainSizer, 0, wx.CENTER)
wrapperSizer.Add(bottomSizer, 0, wx.CENTER)
wrapperSizer.Add(close, wx.SizerFlags().Center()) wrapperSizer.Add(close, wx.SizerFlags().Center())
self.panel.SetSizerAndFit(wrapperSizer) self.panel.SetSizer(wrapperSizer)
topSizer.Fit(self) wrapperSizer.Fit(self.panel)
self.panel.Center()
mainSizer.Fit(self)
self.Center() self.Center()
@ -195,3 +210,19 @@ class ShowUserProfile(wx.Dialog):
textCtrl = wx.TextCtrl(self.panel, value=text, size=size, style=style) textCtrl = wx.TextCtrl(self.panel, value=text, size=size, style=style)
textCtrl.AcceptsFocusFromKeyboard = returnTrue textCtrl.AcceptsFocusFromKeyboard = returnTrue
return textCtrl return textCtrl
def onAction(self, *args):
"""Opens the Open timeline dialog"""
pub.sendMessage('execute-action', action='follow')
def onPost(self, *args):
"""Open this user's timeline"""
pub.sendMessage('execute-action', action='openPostTimeline', kwargs=dict(user=self.user))
def onFollowing(self, *args):
"""Open following timeline for this user"""
pub.sendMessage('execute-action', action='openFollowingTimeline', kwargs=dict(user=self.user))
def onFollowers(self, *args):
"""Open followers timeline for this user"""
pub.sendMessage('execute-action', action='openFollowersTimeline', kwargs=dict(user=self.user))