WIP: New: lazily load images

Authored by Niedzielski on Jul 16 2017, 7:17 PM.

Description

WIP: New: lazily load images

Replace WebView images with placeholders and don't download images until
they're needed.

Notes:

  • Placeholders are evaluated for loading on page load, table collapse and expand toggling, and resizing / orientation change and scrolling (each throttled to 100 ms). Eligibility is conditional on placeholders within the current screen or up to one screen ahead and affecting the layout; placeholders within collapsed tables will not be loaded. This differs from MobileFrontend which only loads up to a half screen ahead. The deviation was made to avoid considering the native component offsets on both Android and iOS apps.
  • Only images are transformed. Videos with poster attributes and elements with downloaded resources in their styles among others are not considered.
  • Lazy loading strives to avoid unnecessary layout changes, particularly when transitioning from placeholder to image, but they do occur when an image's width or height styles or attributes mismatch the actual dimensions of the image. e.g., see the image captioned "Obama and his wife Michelle at the Civil Rights Summit..." on the "Barack Obama" article. MobileFrontend has this same limitation. Image widening transforms must occur prior to the lazy load transform. srcset was not easily maintainable with lazy loading, and is expected to be removed soon, so this patch removes just removes it.

    https://en.m.wikipedia.org/wiki/Barack_Obama?oldid=789232530
  • An example of the transformation lifecycle is:
    • Original: <img class=foo style='width: 100px; height: 200px' width=3 height=4 src=/ srcset=/ alt=bar>
    • Pending: <span class='foo pagelib-lazy-load-placeholder pagelib-lazy-load-placeholder-pending' style='width: 100px' data-class=foo data-style='width: 100px; height: 200px' data-width=3 data-height=4 data-src=/ data-srcset=/ data-alt=bar> <span style='padding-top: 200%'></span> </span>
    • Loading: <span class='foo pagelib-lazy-load-placeholder pagelib-lazy-load-placeholder-loading' style='width: 100px' data-class=foo data-style='width: 100px; height: 200px' data-width=3 data-height=4 data-src=/ data-srcset=/ data-alt=bar> <span style='padding-top: 200%'></span> </span>

      <!-- Detached. --> <img class='foo pagelib-lazy-load-image-loading' style='width: 100px; height: 200px' width=3 height=4 src=/ srcset=/ alt=bar>
    • Error: <span class='foo pagelib-lazy-load-placeholder pagelib-lazy-load-placeholder-error' style='width: 100px' data-class=foo data-style='width: 100px; height: 200px' data-width=3 data-height=4 data-src=/ data-srcset=/ data-alt=bar> <span style='padding-top: 200%'></span> </span>
    • Loaded: <img class='foo pagelib-lazy-load-image-loaded' style='width: 100px; height: 200px' width=3 height=4 src=/ srcset=/ alt=bar>

      The presentation of each state (except original) is styleable with CSS.

      The original blobs of HTML are delivered a section at a time as text and then inflated into a DOM just as they were before. However, since images will begin downloading as soon as their source attribute is set, a new Document is now used to prevent images from downloading before the lazy load transform can run. When the new Document is attached to the Window, image resources are able to start downloading.
  • Resource loading functionality may be verified using the Chrome DevTools network tab for modern devices or OkHttp logcat. All small images and large images within the first two screens forwards or backwards should load but those in the remaining sections should not.

    If you're confident that OkHttp offline caching is working properly, the easiest way to test is:
      1. Clear your app cache.
      2. Visit the "List of works by Vincent van Gogh" article.
      3. Wait for the article to finish loading.
      4. Enable airplane mode.
      5. Expand the first collapsed table.
      6. Verify that no large images are shown in the first 50 or so images. Note: these images have now been attempted to load and will not be retried. They will always appear as placeholders until the page is refreshed.
      7. Disable airplane mode.
      8. Wait until a data connection is established.
      9. Start scrolling and verify that placeholders more than a screen away start loading images (lazy loading works).
    1. Enable airplane mode.
    2. Refresh the page.
    3. Verify that images previously loaded appear (offline caching works).

      https://en.m.wikipedia.org/wiki/List_of_works_by_Vincent_van_Gogh?oldid=781965885
  • A demo for desktop is available in demo/LazyLoadTransform.html in the wikimedia-page-library repo. It's focused and free of some of the complexity concerns of the app.

References:

Depends on: https://github.com/wikimedia/wikimedia-page-library/pull/33
Depends on: https://github.com/wikimedia/wikimedia-page-library/pull/56
Bug: T164429
Change-Id: Icf623c6f1e77f52db39a11e1c5de4748850a7100