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

Some images load, some show load icon, some doesn't #90

Closed
maifeeulasad opened this issue Oct 25, 2019 · 7 comments
Closed

Some images load, some show load icon, some doesn't #90

maifeeulasad opened this issue Oct 25, 2019 · 7 comments
Milestone

Comments

@maifeeulasad
Copy link

I was reading codes from a project. Then for some reasons, I thought I should be reading .md file offline. Then I came to know about this - MarkdownLivePreview.

Now, when I started reading the .md file I had, I noticed something different.

One picture is being rendered, other is not.

But the link is fresh and live, here

Here is a snap :

partial render)

And sometimes it shows a loading like image:

loading for more than 5 minutes

@math2001
Copy link
Owner

The code fetching the images is a bit dodgy... It would need to be re-written. Basically, the image is only updated when the whole preview is updated (basically when you press a key). There is currently no callback which re-renders the preview as soon as the image has finished loading. So, if you wanna see the pictures, you have to type in things (space backspace in repeat would work).

Having a callback is technically possible though, it's just not implemented yet, mainly because the code is quite messy and I don't have a hip of free time right now (I'm passing the HSC), but that should change soon 🙂

@math2001 math2001 added this to the v3 milestone Oct 25, 2019
@maifeeulasad
Copy link
Author

@math2001 can you assign me into this issue ?

I'm interested.

@math2001
Copy link
Owner

math2001 commented Oct 26, 2019

Hey, thank you for wanting to contribute ❤️!

Here's probably where you wanna start:

class ImageManager(object):
"""
Usage:
>>> image = ImageManager.get('http://domain.com/image.png')
>>> image = ImageManager.get('http://domain.com/image.png')
# still loading (this is a comment, no an outputed text), it doesn't
# run an other request
>>> image = ImageManager.get('http://domain.com/image.png')
'data:image/png;base64,....'
"""

Just to give you my personal opinion: this package is just a stack of bad code, disorganized and unclear. I think everything should be re-written, properly. It's still possible to add in this feature, but don't feel bad if you don't feel like it's going to be worth the effort 🙂

@maifeeulasad
Copy link
Author

Thanks a lot for assigning me.

My opinion is - why don't we try to fix this thing,
meanwhile we re-write from scratch.

@math2001
Copy link
Owner

I've unassigned you because I have rewritten MarkdownLivePreview, and this issue is now fixed really cleanly. It turned out to be a lot easier to implement than I original thought, and I probably could now do it in the current code base. The whole package needed to be re-written anyway, just to make it easier for people to contribute.

It's only on my computer for now, but it should arrive soon 🙂

@maifeeulasad
Copy link
Author

Its awesome.

@math2001
Copy link
Owner

This is fixed by v3.0.0 🙂

This is how the "image manager" (just a function) is used:

try:
base64 = get_base64_image(path, re_render)
except FileNotFoundError as e:
base64 = resources["base64_404_image"]
except LoadingError:
base64 = resources["base64_loading_image"]

And this is the "image manager"

def get_base64_image(path, re_render):
""" Gets the base64 for the image (local and remote images). re_render is a
callback which is called when we finish loading an image from the internet
to trigger an update of the preview (the image will then be loaded from the cache)
"""
def callback(path, future):
# altering image_cache is "safe" to do because callback is called in the same
# thread as add_done_callback:
# > Added callables are called in the order that they were added and are always
# > called in a thread belonging to the process that added them
# > --- Python docs
images_cache[path] = future.result()
# we render, which means this function will be called again, but this time, we
# will read from the cache
re_render()
if path in images_cache:
return images_cache[path]
if path.startswith("http://") or path.startswith("https://"):
executor.submit(load_image, path).add_done_callback(partial(callback, path))
raise LoadingError()
with open(path, "rb") as fp:
image = "data:image/png;base64," + base64.b64encode(fp.read()).decode("utf-8")
images_cache[path] = image
return image
def load_image(url):
with urllib.request.urlopen(url, timeout=60) as conn:
content_type = conn.info().get_content_type()
if "image" not in content_type:
raise ValueError(
"{!r} doesn't point to an image, but to a {!r}".format(
url, content_type
)
)
return "data:image/png;base64," + base64.b64encode(conn.read()).decode("utf-8")

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

No branches or pull requests

2 participants