-
-
Notifications
You must be signed in to change notification settings - Fork 274
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
Add media support in ZT #1058
Add media support in ZT #1058
Conversation
Hello @Ezio-Sarthak, it seems like you have referenced #764 in your pull request description, but you have not referenced them in your commit message description(s). When you reference an issue in a commit message, it automatically closes the corresponding issue when the commit is merged. Please run An example of a correctly-formatted commit:
Thank you for your contributions to Zulip! |
21379ec
to
a09e8fa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ezio-Sarthak It's good to see more work on this 👍
I've not looked at all the tests in detail, but this is some feedback for this version of the PR - have you checked my/others comments from the previous PRs?
There seem to be some changes from the previous iteration in terms of eg. subprocess, so although I've noted some reasons you may want to check how up to date your PR is with that?
zulipterminal/helper.py
Outdated
" The tool ", | ||
("bold", tool), | ||
" did not run successfully" ". Exited with ", | ||
("bold", str(exit_status)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"bold"
as a style doesn't exist - we have footer_contrast now.
zulipterminal/helper.py
Outdated
elif LINUX: | ||
command = f"xdg-open {media_path}" | ||
elif MACOS: | ||
command = f"open {media_path}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should really be List[str]
. There is discussion elsewhere, though I can't seem to dig it up on github right now.
zulipterminal/helper.py
Outdated
f.write(chunk) | ||
|
||
if WSL: | ||
command = f'explorer.exe `wslpath -w "{media_path}"`' # Needs testing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave this out until we know we have a version that works, and we're sure is good, particularly with that quoting.
While we support only these three, we should handle the else
case (or equivalent) in any case, so we'll need command
to be defined, or have some meaning, and perhaps pop up an 'unsupported' notice or report an error. That means it can apply to the WSL case for now too.
zulipterminal/helper.py
Outdated
error = [] | ||
try: | ||
process = subprocess.run( | ||
command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to avoid shell=True
for security reasons (eg. https://docs.python.org/3/library/subprocess.html#security-considerations)
zulipterminal/helper.py
Outdated
with requests.get(media_link, auth=auth, stream=True) as r: | ||
r.raise_for_status() | ||
with NamedTemporaryFile( | ||
mode="wb", delete=False, prefix="zt-", suffix="-{}".format(media_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can now be an f-string.
zulipterminal/helper.py
Outdated
|
||
|
||
@asynch | ||
def open_media(controller: Any, command: str, tool: str) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is open_media, so it's surprising that the open-command selection is not present here.
It's been a while since I've looked at this code, but it may be clearer not having one function call the other, ie. download_media(url) -> local_path, open_media(local_path) ?
zulipterminal/ui_tools/buttons.py
Outdated
@@ -370,6 +370,11 @@ def handle_link(self, *_: Any) -> None: | |||
server_url = self.model.server_url | |||
if self.link.startswith(urljoin(server_url, "/#narrow/")): | |||
self.handle_narrow_link() | |||
elif self.link.startswith(urljoin(server_url, "/user_uploads/")): | |||
# Exit pop-up promptly, let the media download in the background. | |||
if isinstance(self.controller.loop.widget, urwid.Overlay): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably refactor this to be a controller method - we already have one case of this style.
zulipterminal/helper.py
Outdated
@@ -737,7 +737,9 @@ def suppress_output() -> Iterator[None]: | |||
|
|||
|
|||
@asynch | |||
def process_media(controller: Any, media_link: str) -> None: | |||
def process_media( | |||
controller: Any, media_link: str, callback: Callable[..., None] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
callback is a very general name - it's worth clarifying when it's called in the name. This could be after downloading, during downloading...
zulipterminal/helper.py
Outdated
controller.view.set_footer_text( | ||
[" Downloading ", ("bold", media_name)] | ||
) | ||
callback([" Downloading ", ("bold", media_name)]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not coupled to the controller etc, but you need to know that it's an urwid styled-text being passed in. You could specify the parameter in the calling function, and have this just be callback()
. A different name would help too - see elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I just passed in the params to show the media name as well. But I think showing just Downloading your media ...
is good, since I'm prompting the user the filename while opening it in any case 👍
) | ||
) | ||
widgets = [question, urwid.Divider(), wrapped_widget] | ||
prompt = urwid.LineBox(urwid.ListBox(urwid.SimpleFocusListWalker(widgets))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good follow-up to this would be to improve the styling and unify it with the general popup - the border is not that clear compared to those, in retrospect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bringing this work up to speed @Ezio-Sarthak!
I've tested this on WSL2 (Ubuntu), and it works well for the file formats I've tried: JPEG, PNG, PDF, and MP4. There's a slight issue as it stands, the footer notification for the tool not running successfully is triggered every time I open something. I presume there's a different exit code being returned on Windows or something of the like. You might have to handle that based on the platform.
I notice Neil has also just reviewed, I wanted to quickly put in a suggestion regarding this while you're still working on it so it's easier to accommodate.
zulipterminal/helper.py
Outdated
client = controller.client | ||
auth = requests.auth.HTTPBasicAuth(client.email, client.api_key) | ||
|
||
with requests.get(media_link, auth=auth, stream=True) as r: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: I understand that the r
and f
aliases come from the previous PRs but can we use more explicit aliases (maybe file
and response
)? Since we use variables with explanatory names everywhere else, it would be consistent here.
a09e8fa
to
3c0057b
Compare
zulipterminal/helper.py
Outdated
if PLATFORM == "WSL": | ||
tool = "explorer.exe" | ||
# Converting absolute path to WSL path | ||
media_path = f'`wslpath "{media_path}"`' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is interpreting these backticks? What else is it interpreting? Something is definitely wrong here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. It is a bad way of nesting bash commands. One should instead use $()
I think. As I said in the stream, we'd potentially not need this now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, my point is there should not be a Bash. Backticks should not be interpreted here. If they were being interpreted here—even if we’re no longer using them—that indicates a deep problem that we need to investigate, because media_path
could itself contain backticks or other characters that we really don’t want to be interpreted.
The same problem applies to $()
, ""
, or any other kind of “quote” construct. The first rule of quoting is that you need to ask, what if the quoting characters are present inside the string you’re quoting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Thanks for clarifying 👍
6b5130c
to
b13cb72
Compare
eff57ba
to
59e3f37
Compare
Tests added and amendments made by Preet Mishra to make it usable for MessageLinkButton and PopUpConfirmationView later. Tests and code further amended by Sarthak Garg to support using report_* methods for UI calls, and refactoring *_media() methods. Co-authored-by: Preet Mishra <[email protected]> Co-authored-by: Sarthak Garg <[email protected]>
…des. The return codes for GUI commands, which were to be interpreted as 1 for WSL and 0 for others, were validated as 0 for all before.This commit extracts the return codes to a helper in `platform_code`, such that the OS-specific successful GUI return codes are handy. Tests added.
There is a difference in path types for Windows and Unix systems. Windows uses backward slashes, whereas other systems use forward slashes. Since a media link in WSL needs an absolute path, such normalization is required. This commit extracts the logic to normalize a file path to a helper in `platform_code`. Tests added.
This commit adds a method `process_media` to handle media links, i.e., it Downloads and Shows the media in the default OS-sepecific explorer. Tests added and amended.
Amendment made by Sarthak Garg to use new `report_*` methods for footer notifications. These are to show download status in footer. Co-authored by: Sarthak Garg <[email protected]>
The parameter is useful for prompts that have long descriptions.
Used 'center' location for show_media_confirmation_popup() for better visibilty of the popup message. Test amended.
59e3f37
to
613a811
Compare
Merged with slight adjustments in #1223 🎉 Thanks @amanagr, @preetmishra and @Ezio-Sarthak 👍 |
Thanks to @preetmishra and @amanagr for their substantial work in #740 and #359, that helped wrapping this PR up with a sober feature version easily.
Partially fixes #764.
Commit flow:
Screenshots/GIFs