Skip to content
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 a non-blocking variant of hs.image.imageFromURL #2224

Closed
andweeb opened this issue Oct 31, 2019 · 5 comments
Closed

Add a non-blocking variant of hs.image.imageFromURL #2224

andweeb opened this issue Oct 31, 2019 · 5 comments

Comments

@andweeb
Copy link

andweeb commented Oct 31, 2019

My use case in particular falls within the context of hs.chooser choices, each choice item needing an icon image from an external URL as shown in the gif below.

test

Due to the blocking nature of hs.image.imageFromURL, using it blocks not only the chooser modal itself but the entire application in general, which isn't a great experience. For example attempting to load http://deelay.me/20000/https://i.imgur.com/2lrs7zF.jpg (simulated delay of 20s) blocks the whole app for the full 20 seconds.

It'd be awesome if there were a way to fetch images from URLs without blocking the main application thread.

@latenitefilms
Copy link
Contributor

@andweeb - I've added an optional callback in #2227. Let me know if that works as you intended.

@andweeb
Copy link
Author

andweeb commented Oct 31, 2019

Wow thanks so much for the help! I'll try that as soon as I have time today and report back. :)

Edit: Works perfectly, thank you!

@cmsj cmsj closed this as completed in ca1c353 Nov 1, 2019
andweeb added a commit to andweeb/Ki that referenced this issue Nov 1, 2019
- Fix blocking nature of URL entity selection modal by using the
  `hs.image.imageFromURL` callback API (Hammerspoon/hammerspoon#2224)
- Fix `URL.getDomain` to get domains from URLs without a www subdomain
@idr4n
Copy link

idr4n commented Aug 4, 2022

Wow thanks so much for the help! I'll try that as soon as I have time today and report back. :)

Edit: Works perfectly, thank you!

@andweeb @latenitefilms Do you guys mind telling me how to use the callback in this case so I can get the icons of the URL asynchronously?

Basically, I'm pulling the tabs from Safari and their URL's into a chooser, pretty much looks like the gif above. As mentioned by @andweeb, user experience is not great if using hs.image.imageFromURL without a callback. However, as mentioned in the docs, when using the callback, the function returns nil right away, and so the images don't show when I trigger the chooser.

This is a sample code of the chooser:

tabs_chooser:choices(function()
	local _, result = hs.osascript.applescript(tabsScript)
	local lines = {}
	for line in string.gmatch(result, "(.-)\n") do
		table.insert(lines, line)
	end
	local tabs = {}
	for _, tab in pairs(lines) do
		local winID, tabNumber, tabTitle, url = string.match(tab, "(.*);(.*);(.*);(.*)")
		-- local img = hs.image.imageFromURL("https://www.google.com/s2/favicons?sz=64&domain_url=" .. url)
		local img = hs.image.imageFromURL("https://www.google.com/s2/favicons?sz=64&domain_url=" .. url, function() end)
		table.insert(tabs, {
			text = tabTitle,
			subText = url,
			win = winID,
			tab = tabNumber,
			image = img,
		})
	end
	return tabs
end)

hs.hotkey.bind("alt", "'", function()
	tabs_chooser:refreshChoicesCallback(true)
	tabs_chooser:show()
end)

Thanks in advance!

@latenitefilms
Copy link
Contributor

Here's an example:

print("before")
hs.image.imageFromURL("https://latenitefilms.com/media/2013/09/latenitefilms_text.png", function(img)
    print(string.format("Here's your image: %s", img))
end)
print("after")

This will output:

2022-08-05 11:50:09: before
2022-08-05 11:50:09: after
2022-08-05 11:50:09: Here's your image: hs.image:  (0x600000b9ddb8)

Callback's obviously happen asynchronously, so you'd need to update your chooser results AFTER the image callback is triggered.

@idr4n
Copy link

idr4n commented Aug 5, 2022

Thanks for your reply @latenitefilms. OK, so I can use the fetched image in the callback as a parameter. Great! However, how can I update the chooser results while the chooser is visible (i.e, after being triggered with chooser:show())?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants