* Fix image cancellation to be stream-scoped instead of widget-scoped
* fix(OneFramePlaceholderImageStreamCompleter): make onLastListenerRemoved callback synchronous with removing the last listener
* fix(OneFrameMultiImageStreamCompleter): remove unnecessary blank line in code
* fix(OneFramePlaceholderImageStreamCompleter): cancel pending requests when only cache listener remains
* fix(OneFrameMultiImageStreamCompleter): ensure onLastListenerRemoved callback is invoked only once
* platform image providers
* use key
* fix cache manager
* more logs, cancel on dispose instead
* split into separate files
* fix saving to cache
* cancel multi-stage provider
* refactored `getInitialImage`
* only wait for disposal for full images
* cached image works
* formatting
* lower asset viewer ram usage
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>