Skip to content

WIP: Support displaying of images in msg in the default viewer. #359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions zulipterminal/config/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@
'keys': {'ctrl c'},
'help_text': 'Quit',
}),
('OPEN_MEDIA', {
'keys': {'v'},
'help_text': 'Open Media in the current highlighted message',
}),
]) # type: OrderedDict[str, KeyBinding]


Expand Down
42 changes: 41 additions & 1 deletion zulipterminal/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
Any, Dict, List, Set, Tuple, Optional, DefaultDict, FrozenSet, Union
)
from mypy_extensions import TypedDict

import os
import requests
import tempfile
import subprocess
import sys

Message = Dict[str, Any]

Expand Down Expand Up @@ -347,3 +350,40 @@ def match_user(user: Any, text: str) -> bool:
if keyword.startswith(text.lower()):
return True
return False


# Plan to open all the images/gifs in a msg
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@neiljp I have mentioned the plan here. Please go through it.

# A message contains n images/gifs
# download all the images/gifs first in /tmp/MSGID folder
# Open the first image in the default viewer of the os.
# user can click next in the viewer for viewing rest of the media
def open_media(urls: List[str], msg_id: int, server_url: str, client: Any):
first_media = None
for url in urls:
# Capture 2 different type of `user_upload` links
if url.startswith('user_uploads'):
url = server_url + url
if url.startswith('/user_uploads'):
url = server_url + url[1:]
img_name = url.split("/")[-1]
img_dir_path = os.path.join(tempfile.gettempdir(), str(msg_id))
img_path = os.path.join(img_dir_path, img_name)
if not first_media:
first_media = img_path
try:
os.mkdir(img_dir_path)
except FileExistsError:
pass
with requests.get(url,
auth=requests.auth.HTTPBasicAuth(client.email,
client.api_key),
stream=True) as r:
r.raise_for_status()
with open(img_path, 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
imageViewerFromCommandLine = {'linux': 'xdg-open',
'win32': 'explorer',
'darwin': 'open'}[sys.platform]
subprocess.run([imageViewerFromCommandLine, img_path])
13 changes: 12 additions & 1 deletion zulipterminal/ui_tools/boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from bs4.element import NavigableString, Tag

from zulipterminal.config.keys import is_command_key
from zulipterminal.helper import open_media


class WriteBox(urwid.Pile):
Expand Down Expand Up @@ -127,6 +128,8 @@ def __init__(self, message: Dict[str, Any], model: Any,
self.email = ''
self.user_id = None # type: Union[int, None]
self.last_message = last_message
# collect all the media links with their name in one place.
self.media = list() # type: List[str]
# if this is the first message
if self.last_message is None:
self.last_message = defaultdict(dict)
Expand Down Expand Up @@ -302,6 +305,8 @@ def soup2markup(self, soup: Any) -> List[Any]:
elif element.name == 'a':
# LINKS
link = element.attrs['href']
if element.img:
self.media.append(element.img['src'])
text = element.img['src'] if element.img else element.text
if link == text:
# If the link and text are same
Expand All @@ -312,7 +317,7 @@ def soup2markup(self, soup: Any) -> List[Any]:
if link.startswith('/user_uploads/'):
# Append org url to before user_uploads to convert it
# into a link.
link = self.model.server_url + link
link = self.model.server_url + link[1:]
markup.append(
('link', '[' + text + ']' + '(' + link + ')'))
elif element.name == 'blockquote':
Expand Down Expand Up @@ -529,6 +534,12 @@ def keypress(self, size: Tuple[int, int], key: str) -> str:
self.model.controller.view.write_box.msg_write_box.set_edit_pos(
len(quote))
self.model.controller.view.middle_column.set_focus('footer')
elif is_command_key('OPEN_MEDIA', key) and len(self.media):
# TODO: Block multiple pressing of this key
# TODO: Make this function async
# TODO: Show `Downloading/Loading...` msg in footer via #T339.
open_media(self.media, self.message['id'], self.model.server_url,
self.model.controller.client)
return key


Expand Down