Added basic comment viewer. It is possible to do likes and remove likes to comments. Pressing enter in a comment will open the experimental viewer

This commit is contained in:
Manuel Cortez 2019-01-08 17:56:51 -06:00
parent 67f2eec4eb
commit 7168b874aa
8 changed files with 116 additions and 562 deletions

View File

@ -14,7 +14,6 @@ import widgetUtils
from presenters import player from presenters import player
import output import output
from . import selector from . import selector
from . import posts
from pubsub import pub from pubsub import pub
from vk_api.exceptions import VkApiError from vk_api.exceptions import VkApiError
from vk_api import upload from vk_api import upload
@ -24,7 +23,6 @@ from sessionmanager import session, renderers, utils
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from wxUI import commonMessages, menus from wxUI import commonMessages, menus
from sessionmanager.renderers import add_attachment from sessionmanager.renderers import add_attachment
from wxUI.dialogs import postDialogs
log = logging.getLogger("controller.buffers") log = logging.getLogger("controller.buffers")
@ -342,11 +340,11 @@ class baseBuffer(object):
if post == None: if post == None:
return return
if "type" in post and post["type"] == "audio": if "type" in post and post["type"] == "audio":
a = presenters.displayAudioPresenter(session=self.session, postObject=post["audio"]["items"], interactor=interactors.displayAudioInteractor(), view=postDialogs.audio()) a = presenters.displayAudioPresenter(session=self.session, postObject=post["audio"]["items"], interactor=interactors.displayAudioInteractor(), view=views.displayAudio())
elif "type" in post and post["type"] == "friend": elif "type" in post and post["type"] == "friend":
pub.sendMessage("open-post", post_object=post, controller_="friendship") pub.sendMessage("open-post", post_object=post, controller_="displayFriendship")
else: else:
pub.sendMessage("open-post", post_object=post, controller_="displayPostPresenter") pub.sendMessage("open-post", post_object=post, controller_="displayPost")
def pause_audio(self, *args, **kwargs): def pause_audio(self, *args, **kwargs):
""" pauses audio playback.""" """ pauses audio playback."""
@ -513,7 +511,7 @@ class audioBuffer(feedBuffer):
if selected == -1: if selected == -1:
return return
audios = [self.session.db[self.name]["items"][selected]] audios = [self.session.db[self.name]["items"][selected]]
a = presenters.displayAudioPresenter(session=self.session, postObject=audios, interactor=interactors.displayAudioInteractor(), view=postDialogs.audio()) a = presenters.displayAudioPresenter(session=self.session, postObject=audios, interactor=interactors.displayAudioInteractor(), view=views.displayAudio())
def play_all(self, *args, **kwargs): def play_all(self, *args, **kwargs):
selected = self.tab.list.get_selected() selected = self.tab.list.get_selected()
@ -968,9 +966,7 @@ class chatBuffer(baseBuffer):
index = self.tab.attachments.get_selected() index = self.tab.attachments.get_selected()
attachment = self.attachments[index] attachment = self.attachments[index]
if attachment["type"] == "audio": if attachment["type"] == "audio":
a = posts.audio(session=self.session, postObject=[attachment["audio"]]) a = presenters.displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio())
a.dialog.get_response()
a.dialog.Destroy()
elif attachment["type"] == "audio_message": elif attachment["type"] == "audio_message":
link = attachment["audio_message"]["link_mp3"] link = attachment["audio_message"]["link_mp3"]
output.speak(_("Playing...")) output.speak(_("Playing..."))

View File

@ -20,12 +20,10 @@ from mysc import localization
from sessionmanager import session, utils, renderers from sessionmanager import session, utils, renderers
from wxUI import (mainWindow, commonMessages) from wxUI import (mainWindow, commonMessages)
from wxUI.dialogs import search as searchDialogs from wxUI.dialogs import search as searchDialogs
from wxUI.dialogs import timeline, creation, postDialogs
from update import updater from update import updater
from issueReporter import issueReporter from issueReporter import issueReporter
from . import buffers from . import buffers
from presenters import player from presenters import player
from . import posts
from presenters import longpollthread from presenters import longpollthread
from . import selector from . import selector
@ -253,9 +251,7 @@ class Controller(object):
player.player.play_all(audios, shuffle=self.window.player_shuffle.IsChecked()) player.player.play_all(audios, shuffle=self.window.player_shuffle.IsChecked())
def view_post(self, post_object, controller_): def view_post(self, post_object, controller_):
p = getattr(presenters, controller_)(session=self.session, postObject=post_object, interactor=interactors.displayPostInteractor(), view=postDialogs.post()) p = getattr(presenters, controller_+"Presenter")(session=self.session, postObject=post_object, interactor=getattr(interactors, controller_+"Interactor")(), view=getattr(views, controller_)())
p.dialog.get_response()
p.dialog.Destroy()
def exit(self, *args, **kwargs): def exit(self, *args, **kwargs):
log.debug("Receibed an exit signal. closing...") log.debug("Receibed an exit signal. closing...")

View File

@ -1,514 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from future import standard_library
standard_library.install_aliases()
import re
import os
import six
import threading
import arrow
import requests
import languageHandler
import widgetUtils
import views
import presenters
import interactors
import output
import wx
import webbrowser
import logging
from sessionmanager import session, renderers, utils # We'll use some functions from there
from pubsub import pub
from wxUI.dialogs import postDialogs, urlList
from extra import SpellChecker, translator
from mysc.thread_utils import call_threaded
from wxUI import menus
log = logging.getLogger("controller.post")
def get_user(id, profiles):
""" Returns an user name and last name based in the id receibed."""
for i in profiles:
if i["id"] == id:
return "{0} {1}".format(i["first_name"], i["last_name"])
# Translators: This string is used when socializer can't find the right user information.
return _("Unknown username")
def get_message(status):
message = ""
if "text" in status:
message = renderers.clean_text(status["text"])
return message
class postController(object):
""" Base class for post representation."""
def __init__(self, session, postObject):
super(postController, self).__init__()
self.session = session
self.post = postObject
# Posts from newsfeed contains this source_id instead from_id in walls. Also it uses post_id and walls use just id.
if "source_id" in self.post:
self.user_identifier = "source_id"
self.post_identifier = "post_id"
else:
# In wall's posts, if someone has posted in user's wall, owner_id should be used instead from_id
# This will help for retrieving comments, do likes, etc.
if "owner_id" not in self.post:
self.user_identifier = "from_id"
else:
self.user_identifier = "owner_id"
self.post_identifier = "id"
self.dialog = postDialogs.post()
# self.dialog.comments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.show_comment)
widgetUtils.connect_event(self.dialog.like, widgetUtils.BUTTON_PRESSED, self.post_like)
widgetUtils.connect_event(self.dialog.comment, widgetUtils.BUTTON_PRESSED, self.add_comment)
widgetUtils.connect_event(self.dialog.tools, widgetUtils.BUTTON_PRESSED, self.show_tools_menu)
widgetUtils.connect_event(self.dialog.repost, widgetUtils.BUTTON_PRESSED, self.post_repost)
# self.dialog.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu, self.dialog.comments.list)
# self.dialog.Bind(wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key, self.dialog.comments.list)
self.worker = threading.Thread(target=self.load_all_components)
self.worker.finished = threading.Event()
self.worker.start()
self.attachments = []
self.load_images = False
# We'll put images here, so it will be easier to work with them.
self.images = []
self.imageIndex = 0
def get_comments(self):
""" Get comments and insert them in a list."""
user = self.post[self.user_identifier]
id = self.post[self.post_identifier]
self.comments = self.session.vk.client.wall.getComments(owner_id=user, post_id=id, need_likes=1, count=100, extended=1, preview_length=0)
comments_ = []
for i in self.comments["items"]:
# If comment has a "deleted" key it should not be displayed, obviously.
if "deleted" in i:
continue
from_ = get_user(i["from_id"], self.comments["profiles"])
if "reply_to_user" in i:
extra_info = get_user(i["reply_to_user"], self.comments["profiles"])
from_ = _("{0} > {1}").format(from_, extra_info)
# As we set the comment reply properly in the from_ field, let's remove the first username from here if it exists.
fixed_text = re.sub("^\[id\d+\|\D+\], ", "", i["text"])
if len(fixed_text) > 140:
text = fixed_text[:141]
else:
text = fixed_text
original_date = arrow.get(i["date"])
created_at = original_date.humanize(locale=languageHandler.curLang[:2])
likes = str(i["likes"]["count"])
comments_.append((from_, text, created_at, likes))
try:
self.dialog.insert_comments(comments_)
except wx.PyDeadObjectError:
pass
def get_post_information(self):
from_ = self.session.get_user_name(self.post[self.user_identifier])
if "copy_history" in self.post:
# Translators: {0} will be replaced with an user.
title = _("repost from {0}").format(from_,)
else:
if ("from_id" in self.post and "owner_id" in self.post) and (self.post["from_id"] != self.post["owner_id"]):
# Translators: {0} will be replaced with the user who is posting, and {1} with the wall owner.
title = _("Post from {0} in the {1}'s wall").format(self.session.get_user_name(self.post["from_id"]), self.session.get_user_name(self.post["owner_id"]))
else:
title = _("Post from {0}").format(from_,)
self.dialog.set_title(title)
message = ""
message = get_message(self.post)
if "copy_history" in self.post:
nm = "\n"
for i in self.post["copy_history"]:
nm += "{0}: {1}\n\n".format(self.session.get_user_name(i["from_id"]), get_message(i))
self.get_attachments(i)
message += nm
self.dialog.set_post(message)
self.get_attachments(self.post)
self.check_image_load()
def get_attachments(self, post):
attachments = []
if "attachments" in post:
for i in post["attachments"]:
# We don't need the photos_list attachment, so skip it.
if i["type"] == "photos_list":
continue
if i["type"] == "photo":
if self.load_images == False: self.load_images = True
self.images.append(i)
attachments.append(renderers.add_attachment(i))
self.attachments.append(i)
# Links in text are not treated like normal attachments, so we'll have to catch and add those to the list without title
# We can't get a title because title is provided by the VK API and it will not work for links as simple text.
urls = utils.find_urls_in_text(self.dialog.get("post_view"))
if len(urls) > 0:
links = []
for i in urls:
links.append({"link": {"title": _("Untitled link"), "url": i}, "type": "link"})
for i in links:
attachments.append(renderers.add_attachment(i))
self.attachments.append(i)
if len(self.attachments) > 0:
self.dialog.attachments.list.Enable(True)
self.dialog.attachments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.open_attachment)
self.dialog.insert_attachments(attachments)
def check_image_load(self):
if self.load_images and len(self.images) > 0 and self.session.settings["general"]["load_images"]:
self.dialog.image.Enable(True)
nav = False # Disable navigation controls in photos
if len(self.images) > 1:
nav = True
widgetUtils.connect_event(self.dialog.previous_photo, widgetUtils.BUTTON_PRESSED, self.set_previous_image)
widgetUtils.connect_event(self.dialog.next_photo, widgetUtils.BUTTON_PRESSED, self.set_next_image)
self.dialog.enable_photo_controls(navigation=nav)
self.set_image(0)
def set_next_image(self, *args, **kwargs):
if self.imageIndex < -1 or self.imageIndex == len(self.images)-1:
self.imageIndex = -1
if len(self.images) <= self.imageIndex+1:
self.imageIndex = 0
else:
self.imageIndex = self.imageIndex + 1
self.set_image(self.imageIndex)
def set_previous_image(self, *args, **kwargs):
if self.imageIndex <= 0:
self.imageIndex = len(self.images)
self.imageIndex = self.imageIndex - 1
self.set_image(self.imageIndex)
def set_image(self, index):
if len(self.images) < index-1:
log.exception("Error in loading image {0} in a list with {1} images".format(index, len(self.images)))
return
# Get's photo URL.
url = self.get_photo_url(self.images[index]["photo"], "x")
if url != "":
img = requests.get(url)
img_data = six.BytesIO(img.content)
image = wx.Image(stream=img_data)
try:
self.dialog.image.SetBitmap(wx.Bitmap(image))
except NameError:
return
self.dialog.SetClientSize(self.dialog.sizer.CalcMin())
# Translators: {0} is the number of the current photo and {1} is the total number of photos.
output.speak(_("Loaded photo {0} of {1}").format(index+1, len(self.images)))
return
def get_photo_url(self, photo, size="x"):
url = ""
for i in photo["sizes"]:
if i["type"] == size:
url = i["url"]
break
return url
def load_all_components(self):
self.get_post_information()
self.get_likes()
self.get_reposts()
self.get_comments()
if self.post["comments"]["can_post"] == 0:
self.dialog.disable("comment")
if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0:
self.dialog.disable("like")
elif self.post["likes"]["user_likes"] == 1:
self.dialog.set("like", _("&Dislike"))
if self.post["likes"]["can_publish"] == 0:
self.dialog.disable("repost")
def post_like(self, *args, **kwargs):
if ("owner_id" in self.post) == False:
user = int(self.post[self.user_identifier])
else:
user = int(self.post["owner_id"])
id = int(self.post[self.post_identifier])
if "type" in self.post:
type_ = self.post["type"]
else:
type_ = "post"
if self.dialog.get("like") == _("&Dislike"):
l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_)
output.speak(_("You don't like this"))
self.post["likes"]["count"] = l["likes"]
self.post["likes"]["user_likes"] = 2
self.get_likes()
self.dialog.set("like", _("&Like"))
else:
l = self.session.vk.client.likes.add(owner_id=user, item_id=id, type=type_)
output.speak(_("You liked this"))
self.dialog.set("like", _("&Dislike"))
self.post["likes"]["count"] = l["likes"]
self.post["likes"]["user_likes"] = 1
self.get_likes()
def post_repost(self, *args, **kwargs):
object_id = "wall{0}_{1}".format(self.post[self.user_identifier], self.post[self.post_identifier])
p = messages.post(session=self.session, title=_("Repost"), caption=_("Add your comment here"), text="")
if p.message.get_response() == widgetUtils.OK:
msg = p.message.get_text().encode("utf-8")
self.session.vk.client.wall.repost(object=object_id, message=msg)
def get_likes(self):
try:
self.dialog.set_likes(self.post["likes"]["count"])
except wx.PyDeadObjectError:
pass
def get_reposts(self):
try:
self.dialog.set_shares(self.post["reposts"]["count"])
except wx.PyDeadObjectError:
pass
def add_comment(self, *args, **kwargs):
comment = presenters.postPresenter(session=self.session, interactor=interactors.postInteractor(), view=views.post(title=_("Add a comment"), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
msg = comment.text
try:
user = self.post[self.user_identifier]
id = self.post[self.post_identifier]
self.session.vk.client.wall.addComment(owner_id=user, post_id=id, text=msg)
output.speak(_("You've posted a comment"))
if self.comments["count"] < 100:
self.clear_comments_list()
self.get_comments()
except Exception as msg:
log.error(msg)
def clear_comments_list(self):
self.dialog.comments.clear()
def show_comment(self, *args, **kwargs):
c = comment(self.session, self.comments["data"][self.dialog.comments.get_selected()])
c.dialog.get_response()
def show_menu(self, *args, **kwargs):
if self.dialog.comments.get_count() == 0: return
menu = menus.commentMenu()
widgetUtils.connect_event(self.dialog, widgetUtils.MENU, self.show_comment, menuitem=menu.open)
widgetUtils.connect_event(self.dialog, widgetUtils.MENU, self.comment_like, menuitem=menu.like)
widgetUtils.connect_event(self.dialog, widgetUtils.MENU, self.comment_unlike, menuitem=menu.unlike)
self.dialog.PopupMenu(menu, self.dialog.comments.list.GetPosition())
def show_menu_by_key(self, ev):
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
self.show_menu()
def show_tools_menu(self, *args, **kwargs):
menu = menus.toolsMenu()
widgetUtils.connect_event(self.dialog, widgetUtils.MENU, self.open_url, menuitem=menu.url)
widgetUtils.connect_event(self.dialog, widgetUtils.MENU, self.translate, menuitem=menu.translate)
widgetUtils.connect_event(self.dialog, widgetUtils.MENU, self.spellcheck, menuitem=menu.CheckSpelling)
self.dialog.PopupMenu(menu, self.dialog.tools.GetPosition())
def comment_like(self, *args, **kwargs):
comment_id = self.comments["data"][self.dialog.comments.get_selected()]["id"]
self.session.like(comment_id)
output.speak(_("You do like this comment"))
def comment_unlike(self, *args, **kwargs):
comment_id = self.comments["data"][self.dialog.comments.get_selected()]["id"]
self.session.unlike(comment_id)
output.speak(_("You don't like this comment"))
def translate(self, *args, **kwargs):
dlg = translator.gui.translateDialog()
if dlg.get_response() == widgetUtils.OK:
text_to_translate = self.dialog.post_view.GetValue().encode("utf-8")
dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")]
msg = translator.translator.translate(text_to_translate, target=dest)
self.dialog.post_view.ChangeValue(msg)
output.speak(_("Translated"))
else:
return
def spellcheck(self, *args, **kwargs):
text = self.dialog.post_view.GetValue()
checker = SpellChecker.spellchecker.spellChecker(text, "")
if hasattr(checker, "fixed_text"):
self.dialog.post_view.ChangeValue(checker.fixed_text)
def open_attachment(self, *args, **kwargs):
index = self.dialog.attachments.get_selected()
attachment = self.attachments[index]
if attachment["type"] == "audio":
a = audio(session=self.session, postObject=[attachment["audio"]])
a.dialog.get_response()
a.dialog.Destroy()
if attachment["type"] == "link":
output.speak(_("Opening URL..."), True)
webbrowser.open_new_tab(attachment["link"]["url"])
elif attachment["type"] == "doc":
output.speak(_("Opening document in web browser..."))
webbrowser.open(attachment["doc"]["url"])
elif attachment["type"] == "video":
# it seems VK doesn't like to attach video links as normal URLS, so we'll have to
# get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video.
# see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get
# However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player.
# For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/
# May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL.
object_id = "{0}_{1}".format(attachment["video"]["owner_id"], attachment["video"]["id"])
video_object = self.session.vk.client.video.get(owner_id=attachment["video"]["owner_id"], videos=object_id)
video_object = video_object["items"][0]
output.speak(_("Opening video in web browser..."), True)
webbrowser.open_new_tab(video_object["player"])
elif attachment["type"] == "photo":
output.speak(_("Opening photo in web browser..."), True)
# Possible photo sizes for looking in the attachment information. Try to use the biggest photo available.
possible_sizes = [1280, 604, 130, 75]
url = ""
for i in possible_sizes:
if "photo_{0}".format(i,) in attachment["photo"]:
url = attachment["photo"]["photo_{0}".format(i,)]
break
if url != "":
webbrowser.open_new_tab(url)
else:
log.debug("Unhandled attachment: %r" % (attachment,))
def __del__(self):
if hasattr(self, "worker"):
self.worker.finished.set()
class comment(object):
def __init__(self, session, comment_object):
super(comment, self).__init__()
self.session = session
self.comment = comment_object
self.dialog = postDialogs.comment()
from_ = self.comment["from"]["name"]
message = self.comment["message"]
original_date = arrow.get(self.comment["created_time"], "YYYY-MM-DTHH:m:sZ", locale="en")
created_at = original_date.humanize(locale=languageHandler.curLang[:2])
self.dialog.set_post(message)
self.dialog.set_title(_("Comment from {0}").format(from_,))
widgetUtils.connect_event(self.dialog.like, widgetUtils.BUTTON_PRESSED, self.post_like)
call_threaded(self.get_likes)
def get_likes(self):
self.likes = self.session.fb.client.get_connections(id=self.comment["id"], connection_name="likes", summary=True)
self.dialog.set_likes(self.likes["summary"]["total_count"])
def post_like(self, *args, **kwargs):
lk = self.session.like(self.comment["id"])
self.get_likes()
class audio(postController):
def __init__(self, session, postObject):
self.added_audios = {}
self.session = session
self.post = postObject
self.dialog = postDialogs.audio()
widgetUtils.connect_event(self.dialog.list, widgetUtils.LISTBOX_CHANGED, self.handle_changes)
self.load_audios()
self.fill_information(0)
widgetUtils.connect_event(self.dialog.download, widgetUtils.BUTTON_PRESSED, self.download)
widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.play)
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_to_library)
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_from_library)
def add_to_library(self, *args, **kwargs):
post = self.post[self.dialog.get_audio()]
args = {}
args["audio_id"] = post["id"]
if "album_id" in post:
args["album_id"] = post["album_id"]
args["owner_id"] = post["owner_id"]
audio = self.session.vk.client.audio.add(**args)
if audio != None and int(audio) > 21:
self.added_audios[post["id"]] = audio
self.dialog.change_state("add", False)
self.dialog.change_state("remove", True)
def remove_from_library(self, *args, **kwargs):
post = self.post[self.dialog.get_audio()]
args = {}
if post["id"] in self.added_audios:
args["audio_id"] = self.added_audios[post["id"]]
args["owner_id"] = self.session.user_id
else:
args["audio_id"] = post["id"]
args["owner_id"] = post["owner_id"]
result = self.session.vk.client.audio.delete(**args)
if int(result) == 1:
self.dialog.change_state("add", True)
self.dialog.change_state("remove", False)
if post["id"] in self.added_audios:
self.added_audios.pop(post["id"])
def fill_information(self, index):
post = self.post[index]
if "artist" in post:
self.dialog.set("artist", post["artist"])
if "title" in post:
self.dialog.set("title", post["title"])
if "duration" in post:
self.dialog.set("duration", utils.seconds_to_string(post["duration"]))
self.dialog.set_title("{0} - {1}".format(post["title"], post["artist"]))
call_threaded(self.get_lyrics)
if post["owner_id"] == self.session.user_id or (post["id"] in self.added_audios) == True:
self.dialog.change_state("remove", True)
self.dialog.change_state("add", False)
else:
self.dialog.change_state("add", True)
self.dialog.change_state("remove", False)
def get_lyrics(self):
post = self.post[self.dialog.get_audio()]
if "lyrics_id" in post:
l = self.session.vk.client.audio.getLyrics(lyrics_id=int(post["lyrics_id"]))
self.dialog.set("lyric", l["text"])
else:
self.dialog.change_state("lyric", False)
def download(self, *args, **kwargs):
post = self.post[self.dialog.get_audio()]
f = "{0} - {1}.mp3".format(post["title"], post["artist"])
path = self.dialog.get_destination_path(f)
if path != None:
pub.sendMessage("download-file", url=post["url"], filename=path)
def play(self, *args, **kwargs):
post = self.post[self.dialog.get_audio()]
pub.sendMessage("play-audio", audio_object=post)
def load_audios(self):
for i in self.post:
s = "{0} - {1}. {2}".format(i["title"], i["artist"], utils.seconds_to_string(i["duration"]))
self.dialog.insert_audio(s)
self.dialog.list.SetSelection(0)
if len(self.post) == 1:
self.dialog.list.Enable(False)
self.dialog.title.SetFocus()
def handle_changes(self, *args, **kwargs):
p = self.dialog.get_audio()
self.fill_information(p)
class friendship(object):
def __init__(self, session, post):
self.session = session
self.post = post
self.dialog = postDialogs.friendship()
list_of_friends = self.get_friend_names()
from_ = self.session.get_user_name(self.post["source_id"])
title = _("{0} added the following friends").format(from_,)
self.dialog.set_title(title)
self.set_friends_list(list_of_friends)
def get_friend_names(self):
self.friends = self.post["friends"]["items"]
return [self.session.get_user_name(i["user_id"]) for i in self.friends]
def set_friends_list(self, friendslist):
for i in friendslist:
self.dialog.friends.insert_item(False, *[i])

View File

@ -4,7 +4,6 @@ import six
import widgetUtils import widgetUtils
import wx import wx
from pubsub import pub from pubsub import pub
from wxUI.dialogs import postDialogs, urlList
from wxUI import menus from wxUI import menus
from .import base from .import base
@ -57,6 +56,7 @@ class displayPostInteractor(base.baseInteractor):
pub.subscribe(self.enable_photo_controls, self.modulename+"_enable_photo_controls") pub.subscribe(self.enable_photo_controls, self.modulename+"_enable_photo_controls")
def uninstall(self): def uninstall(self):
super(displayPostInteractor, self).uninstall()
pub.unsubscribe(self.set, self.modulename+"_set") pub.unsubscribe(self.set, self.modulename+"_set")
pub.unsubscribe(self.load_image, self.modulename+"_load_image") pub.unsubscribe(self.load_image, self.modulename+"_load_image")
pub.unsubscribe(self.add_items, self.modulename+"_add_items") pub.unsubscribe(self.add_items, self.modulename+"_add_items")
@ -127,6 +127,7 @@ class displayAudioInteractor(base.baseInteractor):
pub.subscribe(self.add_items, self.modulename+"_add_items") pub.subscribe(self.add_items, self.modulename+"_add_items")
def uninstall(self): def uninstall(self):
super(displayAudioInteractor, self).uninstall()
pub.unsubscribe(self.set, self.modulename+"_set") pub.unsubscribe(self.set, self.modulename+"_set")
pub.unsubscribe(self.add_items, self.modulename+"_add_items") pub.unsubscribe(self.add_items, self.modulename+"_add_items")
@ -150,4 +151,21 @@ class displayAudioInteractor(base.baseInteractor):
def on_remove_from_library(self, *args, **kwargs): def on_remove_from_library(self, *args, **kwargs):
post = self.view.get_audio() post = self.view.get_audio()
self.presenter.remove_from_library(post) self.presenter.remove_from_library(post)
class displayFriendshipInteractor(base.baseInteractor):
def add_items(self, control, items):
if not hasattr(self.view, control):
raise AttributeError("The control is not present in the view.")
for i in items:
getattr(self.view, control).insert_item(False, *[i])
def install(self, *args, **kwargs):
super(displayFriendshipInteractor, self).install(*args, **kwargs)
pub.subscribe(self.add_items, self.modulename+"_add_items")
def uninstall(self):
super(displayFriendshipInteractor, self).install()
pub.unsubscribe(self.add_items, self.modulename+"_add_items")

View File

@ -12,7 +12,6 @@ import interactors
import output import output
import webbrowser import webbrowser
import logging import logging
from wxUI.dialogs import postDialogs
from sessionmanager import session, renderers, utils # We'll use some functions from there from sessionmanager import session, renderers, utils # We'll use some functions from there
from pubsub import pub from pubsub import pub
from extra import SpellChecker, translator from extra import SpellChecker, translator
@ -20,6 +19,8 @@ from mysc.thread_utils import call_threaded
from .import base from .import base
from .postCreation import createPostPresenter from .postCreation import createPostPresenter
log = logging.getLogger(__file__)
def get_user(id, profiles): def get_user(id, profiles):
""" Returns an user name and last name based in the id receibed.""" """ Returns an user name and last name based in the id receibed."""
for i in profiles: for i in profiles:
@ -39,6 +40,7 @@ class displayPostPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor): def __init__(self, session, postObject, view, interactor):
super(displayPostPresenter, self).__init__(view=view, interactor=interactor, modulename="display_post") super(displayPostPresenter, self).__init__(view=view, interactor=interactor, modulename="display_post")
self.type = "post"
self.session = session self.session = session
self.post = postObject self.post = postObject
# Posts from newsfeed contains this source_id instead from_id in walls. Also it uses post_id and walls use just id. # Posts from newsfeed contains this source_id instead from_id in walls. Also it uses post_id and walls use just id.
@ -206,7 +208,7 @@ class displayPostPresenter(base.basePresenter):
if "type" in self.post: if "type" in self.post:
type_ = self.post["type"] type_ = self.post["type"]
else: else:
type_ = "post" type_ = self.type
if self.post["likes"]["user_likes"] == 1: if self.post["likes"]["user_likes"] == 1:
l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_) l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_)
output.speak(_("You don't like this")) output.speak(_("You don't like this"))
@ -254,18 +256,8 @@ class displayPostPresenter(base.basePresenter):
self.send_message("clear_list", list="comments") self.send_message("clear_list", list="comments")
def show_comment(self, comment_index): def show_comment(self, comment_index):
c = comment(self.session, self.comments["items"][comment_index]) c = self.comments["items"][comment_index]
c.dialog.get_response() a = displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayPost())
def comment_like(self, comment):
comment_id = self.comments["data"][comment]["id"]
self.session.like(comment_id)
output.speak(_("You do like this comment"))
def comment_dislike(self, comment):
comment_id = self.comments["data"][comment]["id"]
self.session.unlike(comment_id)
output.speak(_("You don't like this comment"))
def translate(self, text, language): def translate(self, text, language):
msg = translator.translator.translate(text, language) msg = translator.translator.translate(text, language)
@ -283,8 +275,8 @@ class displayPostPresenter(base.basePresenter):
def open_attachment(self, index): def open_attachment(self, index):
attachment = self.attachments[index] attachment = self.attachments[index]
if attachment["type"] == "audio": if attachment["type"] == "audio":
a = displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=postDialogs.audio()) a = displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio())
if attachment["type"] == "link": elif attachment["type"] == "link":
output.speak(_("Opening URL..."), True) output.speak(_("Opening URL..."), True)
webbrowser.open_new_tab(attachment["link"]["url"]) webbrowser.open_new_tab(attachment["link"]["url"])
elif attachment["type"] == "doc": elif attachment["type"] == "doc":
@ -320,6 +312,51 @@ class displayPostPresenter(base.basePresenter):
if hasattr(self, "worker"): if hasattr(self, "worker"):
self.worker.finished.set() self.worker.finished.set()
class displayCommentPresenter(displayPostPresenter):
def __init__(self, session, postObject, view, interactor):
self.type = "comment"
self.modulename = "display_comment"
self.interactor = interactor
self.view = view
self.interactor.install(view=view, presenter=self, modulename=self.modulename)
self.session = session
self.post = postObject
self.user_identifier = "from_id"
self.post_identifier = "id"
self.worker = threading.Thread(target=self.load_all_components)
self.worker.finished = threading.Event()
self.worker.start()
self.attachments = []
self.load_images = False
# We'll put images here, so it will be easier to work with them.
self.images = []
self.imageIndex = 0
self.run()
def load_all_components(self):
self.get_post_information()
self.get_likes()
self.send_message("disable_control", control="shares")
self.send_message("disable_control", control="comment")
if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0:
self.send_message("disable_control", "like")
elif self.post["likes"]["user_likes"] == 1:
self.send_message("set_label", control="like", label=_("&Dislike"))
self.send_message("disable_control", control="repost")
def get_post_information(self):
from_ = self.session.get_user_name(self.post[self.user_identifier])
if ("from_id" in self.post and "owner_id" in self.post):
# Translators: {0} will be replaced with the user who is posting, and {1} with the wall owner.
title = _("Post from {0} in the {1}'s post").format(self.session.get_user_name(self.post["from_id"]), self.session.get_user_name(self.post["owner_id"]))
self.send_message("set_title", value=title)
message = ""
message = get_message(self.post)
self.send_message("set", control="post_view", value=message)
self.get_attachments(self.post, message)
self.check_image_load()
class displayAudioPresenter(base.basePresenter): class displayAudioPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor): def __init__(self, session, postObject, view, interactor):
super(displayAudioPresenter, self).__init__(view=view, interactor=interactor, modulename="display_audio") super(displayAudioPresenter, self).__init__(view=view, interactor=interactor, modulename="display_audio")
@ -409,3 +446,23 @@ class displayAudioPresenter(base.basePresenter):
def handle_changes(self, audio_index): def handle_changes(self, audio_index):
self.fill_information(audio_index) self.fill_information(audio_index)
class displayFriendshipPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor):
self.session = session
self.post = postObject
super(displayFriendshipPresenter, self).__init__(view=view, interactor=interactor, modulename="display_friendship")
list_of_friends = self.get_friend_names()
from_ = self.session.get_user_name(self.post["source_id"])
title = _("{0} added the following friends").format(from_,)
self.send_message("set_title", value=title)
self.set_friends_list(list_of_friends)
self.run()
def get_friend_names(self):
self.friends = self.post["friends"]["items"]
return [self.session.get_user_name(i["user_id"]) for i in self.friends]
def set_friends_list(self, friendslist):
self.send_message("add_items", control="friends", items=friendslist)

View File

@ -6,5 +6,6 @@
from .dialogs.attach import * from .dialogs.attach import *
from .dialogs.audioRecorder import * from .dialogs.audioRecorder import *
from .dialogs.postCreation import * from .dialogs.postCreation import *
from .dialogs.postDisplay import *
from .dialogs.configuration import * from .dialogs.configuration import *
from .dialogs.profiles import * from .dialogs.profiles import *

View File

@ -3,9 +3,9 @@ from __future__ import unicode_literals
import wx import wx
import widgetUtils import widgetUtils
class textMessage(widgetUtils.BaseDialog): class createTextMessage(widgetUtils.BaseDialog):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(textMessage, self).__init__(parent=None, *args, **kwargs) super(createTextMessage, self).__init__(parent=None, *args, **kwargs)
def createTextArea(self, message="", text=""): def createTextArea(self, message="", text=""):
self.panel = wx.Panel(self) self.panel = wx.Panel(self)
@ -52,7 +52,7 @@ class textMessage(widgetUtils.BaseDialog):
def get_position(self): def get_position(self):
return self.text.GetInsertionPoint() return self.text.GetInsertionPoint()
class post(textMessage): class createPostDialog(createTextMessage):
def createControls(self, title, message, text, mode): def createControls(self, title, message, text, mode):
self.mainBox = wx.BoxSizer(wx.VERTICAL) self.mainBox = wx.BoxSizer(wx.VERTICAL)
self.createTextArea(message, text) self.createTextArea(message, text)
@ -86,11 +86,11 @@ class post(textMessage):
self.SetTitle(title) self.SetTitle(title)
def __init__(self, title, message, text, mode="post"): def __init__(self, title, message, text, mode="post"):
super(post, self).__init__() super(createPostDialog, self).__init__()
self.createControls(title, message, text, mode) self.createControls(title, message, text, mode)
self.SetClientSize(self.mainBox.CalcMin()) self.SetClientSize(self.mainBox.CalcMin())
class comment(textMessage): class createCommentDialog(createTextMessage):
def createControls(self, title, message, text): def createControls(self, title, message, text):
self.mainBox = wx.BoxSizer(wx.VERTICAL) self.mainBox = wx.BoxSizer(wx.VERTICAL)
self.createTextArea(message, text) self.createTextArea(message, text)
@ -118,6 +118,6 @@ class comment(textMessage):
self.SetTitle(title) self.SetTitle(title)
def __init__(self, title, message, text): def __init__(self, title, message, text):
super(comment, self).__init__() super(createCommentDialog, self).__init__()
self.createControls(message, title, text) self.createControls(message, title, text)
self.SetClientSize(self.mainBox.CalcMin()) self.SetClientSize(self.mainBox.CalcMin())

View File

@ -3,9 +3,9 @@ from __future__ import unicode_literals
import wx import wx
import widgetUtils import widgetUtils
class basicPost(widgetUtils.BaseDialog): class displayBasicPost(widgetUtils.BaseDialog):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(basicPost, self).__init__(parent=None, *args, **kwargs) super(displayBasicPost, self).__init__(parent=None, *args, **kwargs)
self.panel = wx.Panel(self, -1) self.panel = wx.Panel(self, -1)
self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer = wx.BoxSizer(wx.VERTICAL)
@ -109,9 +109,9 @@ class basicPost(widgetUtils.BaseDialog):
else: else:
return False return False
class post(basicPost): class displayPost(displayBasicPost):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(post, self).__init__(*args, **kwargs) super(displayPost, self).__init__(*args, **kwargs)
post_view_box = self.create_post_view() post_view_box = self.create_post_view()
self.sizer.Add(post_view_box, 0, wx.ALL, 5) self.sizer.Add(post_view_box, 0, wx.ALL, 5)
attachments_box = self.create_attachments() attachments_box = self.create_attachments()
@ -132,9 +132,9 @@ class post(basicPost):
self.sizer.Add(self.create_dialog_buttons()) self.sizer.Add(self.create_dialog_buttons())
self.done() self.done()
class comment(basicPost): class displayComment(displayBasicPost):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(comment, self).__init__(*args, **kwargs) super(displayComment, self).__init__(*args, **kwargs)
post_view_box = self.create_post_view() post_view_box = self.create_post_view()
self.sizer.Add(post_view_box, 0, wx.ALL, 5) self.sizer.Add(post_view_box, 0, wx.ALL, 5)
self.create_tools_button() self.create_tools_button()
@ -146,9 +146,9 @@ class comment(basicPost):
self.sizer.Add(self.create_dialog_buttons()) self.sizer.Add(self.create_dialog_buttons())
self.done() self.done()
class audio(widgetUtils.BaseDialog): class displayAudio(widgetUtils.BaseDialog):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(audio, self).__init__(parent=None, *args, **kwargs) super(displayAudio, self).__init__(parent=None, *args, **kwargs)
panel = wx.Panel(self) panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
lbl_list = wx.StaticText(panel, wx.NewId(), _("Audio &files")) lbl_list = wx.StaticText(panel, wx.NewId(), _("Audio &files"))
@ -210,9 +210,9 @@ class audio(widgetUtils.BaseDialog):
def get_audio(self): def get_audio(self):
return self.list.GetSelection() return self.list.GetSelection()
class friendship(widgetUtils.BaseDialog): class displayFriendship(widgetUtils.BaseDialog):
def __init__(self): def __init__(self):
super(friendship, self).__init__(parent=None) super(displayFriendship, self).__init__(parent=None)
panel = wx.Panel(self) panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
self.friends = widgetUtils.list(panel, [_("Friend")], style=wx.LC_REPORT) self.friends = widgetUtils.list(panel, [_("Friend")], style=wx.LC_REPORT)