diff --git a/src/controller/mastodon/handler.py b/src/controller/mastodon/handler.py index b4742448..38aff188 100644 --- a/src/controller/mastodon/handler.py +++ b/src/controller/mastodon/handler.py @@ -265,10 +265,19 @@ class Handler(object): data = { 'display_name': profile.display_name, 'note': html_filter(profile.note), + 'header': profile.header, + 'avatar': profile.avatar, + 'fields': [(field.name, html_filter(field.value)) for field in profile.fields], } + log.debug(f"arafat {data['fields']}") dialog = update_profile_dialogs.UpdateProfileDialog(**data) - if dialog.ShowModal() != wx.ID_OK: return + if dialog.ShowModal() != wx.ID_OK: + log.debug("User canceled dialog") + return updated_data = dialog.data + if updated_data == data: + log.debug("No profile info was changed.") + return # remove data that hasn't been updated for key in data: if data[key] == updated_data[key]: diff --git a/src/wxUI/dialogs/mastodon/updateProfile.py b/src/wxUI/dialogs/mastodon/updateProfile.py index 2e8f4426..d6e2a81b 100644 --- a/src/wxUI/dialogs/mastodon/updateProfile.py +++ b/src/wxUI/dialogs/mastodon/updateProfile.py @@ -1,6 +1,15 @@ +import os +import requests +from io import BytesIO + import wx +from logging import getLogger;log = getLogger() +def return_true(): + return True + + class UpdateProfileDialog(wx.Dialog): """ A dialog for user to update his / her profile details. @@ -14,14 +23,20 @@ class UpdateProfileDialog(wx.Dialog): ``` """ - def __init__(self, display_name: str="", note: str=""): + def __init__(self, display_name: str="", note: str="", header: str="", + avatar: str="", fields: list=[]): """Initialize update profile dialog Parameters: - display_name: The user's display name to show in the display name field - 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) self.SetTitle(_("Update Profile")) + self.header = header + self.avatar = avatar + panel = wx.Panel(self) sizer = wx.BoxSizer(wx.VERTICAL) @@ -31,27 +46,155 @@ class UpdateProfileDialog(wx.Dialog): wx.TE_PROCESS_ENTER) bio_label = wx.StaticText(panel, label=_("Bio")) self.bio = wx.TextCtrl(panel, value=note, style=wx.TE_PROCESS_ENTER) + + # header + header_label = wx.StaticText(panel, label=_("Header")) + try: + response = requests.get(self.header) + except requests.exceptions.RequestException: + # Create empty image + self.header_image = wx.StaticBitmap() + else: + image_bytes = BytesIO(response.content) + image = wx.Image(image_bytes, wx.BITMAP_TYPE_ANY) + image.Rescale(300, 100, wx.IMAGE_QUALITY_HIGH) + self.header_image = wx.StaticBitmap(panel, bitmap=image.ConvertToBitmap()) + + self.header_image.AcceptsFocusFromKeyboard = return_true + self.change_header = wx.Button(panel, label=_("Change header")) + + # avatar + avatar_label = wx.StaticText(panel, label=_("Avatar")) + try: + response = requests.get(self.avatar) + except requests.exceptions.RequestException: + # Create empty image + self.avatar_image = wx.StaticBitmap() + else: + image_bytes = BytesIO(response.content) + image = wx.Image(image_bytes, wx.BITMAP_TYPE_ANY) + image.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH) + self.avatar_image = wx.StaticBitmap(panel, bitmap=image.ConvertToBitmap()) + + self.avatar_image.AcceptsFocusFromKeyboard = return_true + self.change_avatar = wx.Button(panel, label=_("Change avatar")) + + self.fields = [] + for i in range(1, 5): + field_sizer = wx.BoxSizer(wx.HORIZONTAL) + field_label = wx.StaticText(panel, label=_("Field {}: Label").format(i)) + field_sizer.Add(field_label, wx.SizerFlags().Center().Border(wx.ALL, 5)) + + label_textctrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER) + if i <= len(fields): + label_textctrl.SetValue(fields[i-1][0]) + log.debug(f"Field {i}: label = {fields[i-1][0]}") + field_sizer.Add(label_textctrl, wx.SizerFlags().Expand().Border(wx.ALL, 5)) + + content_label = wx.StaticText(panel, label=_("Content")) + field_sizer.Add(content_label, wx.SizerFlags().Center().Border(wx.ALL, 5)) + + content_textctrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER) + if i <= len(fields): + content_textctrl.SetValue(fields[i-1][1]) + log.debug(f"content: {fields[i-1][1]}") + field_sizer.Add(content_textctrl, wx.SizerFlags().Expand().Border(wx.ALL, 5)) + sizer.Add(field_sizer, 0, wx.CENTER) + self.fields.append((label_textctrl, content_textctrl)) + ok = wx.Button(panel, wx.ID_OK, _(u"&OK")) ok.SetDefault() cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) self.SetEscapeId(cancel.GetId()) # manage sizers - sizer.Add(display_name_label, wx.SizerFlags().Center()) - sizer.Add(self.display_name, wx.SizerFlags().Center()) - sizer.Add(cancel, wx.SizerFlags().Center()) - sizer.Add(ok, wx.SizerFlags().Center()) - sizer.Add(self.bio, wx.SizerFlags().Center()) + name_sizer = wx.BoxSizer(wx.HORIZONTAL) + name_sizer.Add(display_name_label, wx.SizerFlags().Center()) + name_sizer.Add(self.display_name, wx.SizerFlags().Center()) + sizer.Add(name_sizer, wx.CENTER) + + bio_sizer = wx.BoxSizer(wx.HORIZONTAL) + bio_sizer.Add(bio_label, wx.SizerFlags().Center()) + bio_sizer.Add(self.bio, wx.SizerFlags().Center()) + sizer.Add(bio_sizer, wx.CENTER) + + header_sizer = wx.BoxSizer(wx.HORIZONTAL) + header_sizer.Add(header_label, wx.SizerFlags().Center()) + header_sizer.Add(self.header_image, wx.SizerFlags().Center()) + header_sizer.Add(self.change_header, wx.SizerFlags().Center()) + sizer.Add(header_sizer, wx.CENTER) + + avatar_sizer = wx.BoxSizer(wx.HORIZONTAL) + avatar_sizer.Add(avatar_label, wx.SizerFlags().Center()) + avatar_sizer.Add(self.avatar_image, wx.SizerFlags().Center()) + avatar_sizer.Add(self.change_avatar, wx.SizerFlags().Center()) + sizer.Add(avatar_sizer, wx.CENTER) + + action_sizer = wx.BoxSizer(wx.HORIZONTAL) + action_sizer.Add(ok, wx.SizerFlags().Center()) + action_sizer.Add(cancel, wx.SizerFlags().Center()) + sizer.Add(action_sizer, wx.CENTER) panel.SetSizer(sizer) panel.Fit() # manage events ok.Bind(wx.EVT_BUTTON, self.on_ok) + self.change_header.Bind(wx.EVT_BUTTON, self.on_change_header) + self.change_avatar.Bind(wx.EVT_BUTTON, self.on_change_avatar) + + self.AutoLayout = True def on_ok(self, *args): """Method called when user clicks ok in dialog""" self.data = { 'display_name': self.display_name.GetValue(), - 'note': self.bio.GetValue() + 'note': self.bio.GetValue(), + 'header': self.header, + 'avatar': self.avatar, + 'fields': [(label.GetValue(), content.GetValue()) for label, content in self.fields if label.GetValue() and content.GetValue()] } self.EndModal(wx.ID_OK) + + def on_change_header(self, *args): + """Display a dialog for the user to choose a picture and update the + appropriate attribute""" + wildcard = "Images (*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif" + dlg = wx.FileDialog(self, _("Select header image - max 2MB"), wildcard=wildcard) + if dlg.ShowModal() == wx.CLOSE: + return + if os.path.getsize(dlg.GetPath()) > 2097152: + # File size exceeds the limit + message = _("The selected file is larger than 2MB. Do you want to select another file?") + caption = _("File more than 2MB") + style = wx.YES_NO | wx.ICON_WARNING + + # Display the message box + result = wx.MessageBox(message, caption, style) + return self.on_change_header() if result == wx.YES else None + + self.header = dlg.GetPath() + image = wx.Image(self.header, wx.BITMAP_TYPE_ANY) + image.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH) + self.header_image.SetBitmap(image.ConvertToBitmap()) + + def on_change_avatar(self, *args): + """Display a dialog for the user to choose a picture and update the + appropriate attribute""" + wildcard = "Images (*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif" + dlg = wx.FileDialog(self, _("Select avatar image - max 2MB"), wildcard=wildcard) + if dlg.ShowModal() == wx.CLOSE: + return + if os.path.getsize(dlg.GetPath()) > 2097152: + # File size exceeds the limit + message = _("The selected file is larger than 2MB. Do you want to select another file?") + caption = _("File more than 2MB") + style = wx.YES_NO | wx.ICON_WARNING + + # Display the message box + result = wx.MessageBox(message, caption, style) + return self.on_change_avatar() if result == wx.YES else None + + self.avatar = dlg.GetPath() + image = wx.Image(self.avatar, wx.BITMAP_TYPE_ANY) + image.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH) + self.avatar_image.SetBitmap(image.ConvertToBitmap())