@nativescript-community/ui-image
Version:
Advanced and efficient image display plugin which uses Fresco (Android) and SDWebImage (iOS) to implement caching, placeholders, image effects, and much more.
422 lines • 16.7 kB
JavaScript
export * from './image-common';
import { ImageAsset, ImageSource, Screen, Trace, knownFolders, path } from '@nativescript/core';
import { isString } from '@nativescript/core/utils/types';
import { RESOURCE_PREFIX, isFileOrResourcePath, isFontIconURI, layout } from '@nativescript/core/utils/utils';
import { CLog, CLogTypes, ImageBase, ScaleType } from './image-common';
var SDImageRoundAsCircleTransformer = /** @class */ (function (_super) {
__extends(SDImageRoundAsCircleTransformer, _super);
function SDImageRoundAsCircleTransformer() {
return _super !== null && _super.apply(this, arguments) || this;
}
SDImageRoundAsCircleTransformer.transformer = function () {
var transformer = SDImageRoundAsCircleTransformer.alloc().init();
return transformer;
};
Object.defineProperty(SDImageRoundAsCircleTransformer.prototype, "transformerKey", {
get: function () {
return 'SDImageRoundAsCircleTransformer';
},
enumerable: true,
configurable: true
});
SDImageRoundAsCircleTransformer.prototype.transformedImageWithImageForKey = function (image, key) {
if (!image) {
return null;
}
var width = image.size.width;
var height = image.size.height;
var minwidth = Math.min(width, height);
var cornerRadius = minwidth / 2;
var result = image
.sd_resizedImageWithSizeScaleMode(CGSizeMake(minwidth, minwidth), SDImageScaleMode.AspectFill)
.sd_roundedCornerImageWithRadiusCornersBorderWidthBorderColor(cornerRadius, UIRectCorner.BottomLeft | UIRectCorner.BottomRight | UIRectCorner.TopLeft | UIRectCorner.TopRight, 0, null)
.sd_resizedImageWithSizeScaleMode(CGSizeMake(width, height), SDImageScaleMode.AspectFit);
return result;
};
SDImageRoundAsCircleTransformer.ObjCProtocols = [SDImageTransformer];
return SDImageRoundAsCircleTransformer;
}(NSObject));
export class ImageInfo {
constructor(width, height) {
this.width = width;
this.height = height;
}
getHeight() {
return this.height;
}
getWidth() {
return this.width;
}
}
const supportedLocalFormats = ['png', 'jpg', 'gif', 'jpeg', 'webp'];
let screenScale = -1;
function getScaleType(scaleType) {
if (isString(scaleType)) {
switch (scaleType) {
case ScaleType.Center:
case ScaleType.CenterCrop:
case ScaleType.AspectFill:
return 2;
case ScaleType.CenterInside:
case ScaleType.FitCenter:
case ScaleType.FitEnd:
case ScaleType.FitStart:
case ScaleType.AspectFit:
return 1;
case ScaleType.FitXY:
case ScaleType.FocusCrop:
case ScaleType.Fill:
return 0;
default:
break;
}
}
return null;
}
function getUIImageScaleType(scaleType) {
if (isString(scaleType)) {
switch (scaleType) {
case ScaleType.Center:
return 4;
case ScaleType.FocusCrop:
case ScaleType.CenterCrop:
case ScaleType.AspectFill:
return 2;
case ScaleType.AspectFit:
case ScaleType.CenterInside:
case ScaleType.FitCenter:
return 1;
case ScaleType.FitEnd:
return 8;
case ScaleType.FitStart:
return 7;
case ScaleType.Fill:
case ScaleType.FitXY:
return 0;
case ScaleType.None:
return 9;
default:
break;
}
}
return null;
}
export function initialize(config) {
SDImageLoadersManager.sharedManager.loaders = NSArray.arrayWithArray([SDWebImageDownloader.sharedDownloader, SDImagePhotosLoader.sharedLoader]);
}
export function shutDown() { }
export class ImagePipeline {
constructor() {
this._ios = SDImageCache.sharedImageCache;
}
isInDiskCache(uri) {
return this._ios.diskImageDataExistsWithKey(getUri(uri).absoluteString);
}
isInBitmapMemoryCache(uri) {
return this._ios.imageFromMemoryCacheForKey(getUri(uri).absoluteString) !== null;
}
evictFromMemoryCache(uri) {
this._ios.removeImageFromMemoryForKey(getUri(uri).absoluteString);
}
evictFromDiskCache(uri) {
this._ios.removeImageFromDiskForKey(getUri(uri).absoluteString);
}
evictFromCache(uri) {
this._ios.removeImageForKeyWithCompletion(getUri(uri).absoluteString, null);
}
clearCaches() {
this._ios.clearMemory();
this._ios.clearDiskOnCompletion(null);
}
clearMemoryCaches() {
this._ios.clearMemory();
}
clearDiskCaches() {
this._ios.clearDiskOnCompletion(null);
}
prefetchToDiskCache(uri) {
return this.prefetchToCacheType(uri, 1);
}
prefetchToMemoryCache(uri) {
return this.prefetchToCacheType(uri, 2);
}
prefetchToCacheType(uri, cacheType) {
return new Promise((resolve, reject) => {
const context = NSMutableDictionary.alloc().initWithCapacity(1);
context.setObjectForKey(cacheType, SDWebImageContextStoreCacheType);
SDWebImagePrefetcher.sharedImagePrefetcher.context = context;
SDWebImagePrefetcher.sharedImagePrefetcher.prefetchURLsProgressCompleted([getUri(uri)], null, (finished, skipped) => {
if (finished && !skipped) {
resolve();
}
else {
reject(`prefetch failed for URI: ${uri}`);
}
});
});
}
get ios() {
return this._ios;
}
}
export function getImagePipeline() {
const imagePineLine = new ImagePipeline();
return imagePineLine;
}
function getUri(src) {
let uri = src;
if (src instanceof ImageAsset) {
return NSURL.sd_URLWithAsset(src.ios);
}
if (uri.indexOf(RESOURCE_PREFIX) === 0) {
const resName = uri.substr(RESOURCE_PREFIX.length);
if (screenScale === -1) {
screenScale = Screen.mainScreen.scale;
}
const found = supportedLocalFormats.some((v) => {
for (let i = screenScale; i >= 1; i--) {
uri = NSBundle.mainBundle.URLForResourceWithExtension(i > 1 ? `${resName}@${i}x` : resName, v);
if (uri) {
return true;
}
}
return false;
});
if (found) {
return uri;
}
}
else if (uri.indexOf('~/') === 0) {
return NSURL.fileURLWithPath(`${path.join(knownFolders.currentApp().path, uri.replace('~/', ''))}`);
}
else if (uri.indexOf('/') === 0) {
return NSURL.fileURLWithPath(uri);
}
return NSURL.URLWithString(uri);
}
export class Img extends ImageBase {
constructor() {
super(...arguments);
this.isLoading = false;
this._imageSourceAffectsLayout = true;
this.handleImageLoaded = (image, error, cacheType) => {
this.isLoading = false;
const animate = (this.alwaysFade || cacheType !== 2) && this.fadeDuration > 0;
if (image) {
this._setNativeImage(image, animate);
}
if (!this.autoPlayAnimations) {
this.nativeViewProtected.stopAnimating();
}
if (error) {
const args = {
eventName: Img.failureEvent,
object: this,
error,
};
this.notify(args);
if (this.failureImageUri) {
image = this.getUIImage(this.failureImageUri);
this._setNativeImage(image, animate);
}
}
else if (image) {
const args = {
eventName: ImageBase.finalImageSetEvent,
object: this,
imageInfo: new ImageInfo(image.size.width, image.size.height),
ios: image,
};
this.notify(args);
}
this.handleImageProgress(1);
};
this.onLoadProgress = (currentSize, totalSize) => {
this.handleImageProgress(totalSize > 0 ? currentSize / totalSize : -1, totalSize);
};
}
createNativeView() {
const result = SDAnimatedImageView.new();
result.contentMode = 1;
result.clipsToBounds = true;
result.userInteractionEnabled = true;
result.tintColor = null;
return result;
}
_setNativeClipToBounds() {
this.nativeViewProtected.clipsToBounds = true;
}
onMeasure(widthMeasureSpec, heightMeasureSpec) {
const width = layout.getMeasureSpecSize(widthMeasureSpec);
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
const height = layout.getMeasureSpecSize(heightMeasureSpec);
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
const image = this.nativeViewProtected.image;
const finiteWidth = widthMode === layout.EXACTLY;
const finiteHeight = heightMode === layout.EXACTLY;
this._imageSourceAffectsLayout = !finiteWidth || !finiteHeight;
if (Trace.isEnabled()) {
CLog(CLogTypes.info, 'onMeasure', this.src, widthMeasureSpec, heightMeasureSpec, width, height, this.aspectRatio, image && image.imageOrientation);
}
if (image || this.aspectRatio > 0) {
const nativeWidth = image ? layout.toDevicePixels(image.size.width) : 0;
const nativeHeight = image ? layout.toDevicePixels(image.size.height) : 0;
const imgRatio = nativeWidth / nativeHeight;
const ratio = this.aspectRatio || imgRatio;
if (!finiteWidth) {
widthMeasureSpec = layout.makeMeasureSpec(height * ratio, layout.EXACTLY);
}
if (!finiteHeight) {
heightMeasureSpec = layout.makeMeasureSpec(width / ratio, layout.EXACTLY);
}
if (Trace.isEnabled()) {
CLog(CLogTypes.info, 'onMeasure scale', this.src, this.aspectRatio, finiteWidth, finiteHeight, width, height, nativeWidth, nativeHeight, widthMeasureSpec, heightMeasureSpec);
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
updateImageUri() {
const imagePipeLine = getImagePipeline();
const src = this.src;
if (!(src instanceof ImageSource)) {
const uri = getUri(src).absoluteString;
const isInCache = imagePipeLine.isInBitmapMemoryCache(uri);
if (isInCache) {
imagePipeLine.evictFromCache(uri);
}
}
this.src = null;
this.src = src;
}
_setNativeImage(nativeImage, animated = true) {
if (animated) {
this.nativeViewProtected.alpha = 0.0;
this.nativeViewProtected.image = nativeImage;
UIView.animateWithDurationAnimations(this.fadeDuration / 1000, () => {
this.nativeViewProtected.alpha = this.opacity;
});
}
else {
this.nativeViewProtected.image = nativeImage;
}
if (this._imageSourceAffectsLayout) {
this._imageSourceAffectsLayout = false;
this.requestLayout();
}
}
getUIImage(imagePath) {
if (!path) {
return null;
}
let image;
if (typeof imagePath === 'string') {
if (isFontIconURI(imagePath)) {
const fontIconCode = (imagePath).split('//')[1];
if (fontIconCode !== undefined) {
const font = this.style.fontInternal;
const color = this.style.color;
image = (ImageSource.fromFontIconCodeSync(fontIconCode, font, color).ios);
}
}
if (!image && isFileOrResourcePath(imagePath)) {
image = ImageSource.fromFileOrResourceSync(imagePath);
}
}
else {
image = imagePath;
}
if (image) {
image = image.ios;
}
return image;
}
initImage() {
if (this.nativeViewProtected) {
const src = this.src;
if (src) {
const animate = this.fadeDuration > 0;
if (src instanceof ImageSource) {
this._setNativeImage(src.ios, animate);
return;
}
else if (typeof src === 'string') {
if (isFontIconURI(src)) {
const fontIconCode = (src).split('//')[1];
if (fontIconCode !== undefined) {
const font = this.style.fontInternal;
const color = this.style.color;
this._setNativeImage(ImageSource.fromFontIconCodeSync(fontIconCode, font, color).ios, animate);
}
return;
}
}
const uri = getUri(src);
if (this.noCache) {
const key = uri.absoluteString;
const imagePipeLine = getImagePipeline();
const isInCache = imagePipeLine.isInBitmapMemoryCache(key);
if (isInCache) {
imagePipeLine.evictFromCache(key);
}
}
this.isLoading = true;
let options = 2048 | 1024;
if (this.alwaysFade === true) {
options |= 131072;
}
const context = NSMutableDictionary.dictionary();
const transformers = [];
if (this.progressiveRenderingEnabled === true) {
options = options | 4;
}
if (this.decodeWidth && this.decodeHeight) {
transformers.push(NSImageDecodeSizeTransformer.transformerWithDecodeWidthDecodeHeight(this.decodeWidth, this.decodeHeight));
}
if (this.tintColor) {
transformers.push(SDImageTintTransformer.transformerWithColor(this.tintColor.ios));
}
if (this.blurRadius) {
transformers.push(SDImageBlurTransformer.transformerWithRadius(this.blurRadius));
}
if (this.roundAsCircle === true) {
transformers.push(SDImageRoundAsCircleTransformer.new());
}
if (this.roundBottomLeftRadius || this.roundBottomRightRadius || this.roundTopLeftRadius || this.roundTopRightRadius) {
transformers.push(NSImageRoundCornerTransformer.transformerWithTopLefRadiusTopRightRadiusBottomRightRadiusBottomLeftRadius(layout.toDeviceIndependentPixels(this.roundTopLeftRadius), layout.toDeviceIndependentPixels(this.roundTopRightRadius), layout.toDeviceIndependentPixels(this.roundBottomRightRadius), layout.toDeviceIndependentPixels(this.roundBottomLeftRadius)));
}
if (transformers.length > 0) {
context.setValueForKey(SDImagePipelineTransformer.transformerWithTransformers(transformers), SDWebImageContextImageTransformer);
}
this.nativeViewProtected.sd_setImageWithURLPlaceholderImageOptionsContextProgressCompleted(uri, this.placeholderImage, options, context, this.onLoadProgress, this.handleImageLoaded);
}
else if (this.placeholderImage) {
this._setNativeImage(this.placeholderImage);
}
else {
this._setNativeImage(null);
}
}
}
[ImageBase.srcProperty.setNative](value) {
this.initImage();
}
[ImageBase.placeholderImageUriProperty.setNative]() {
this.placeholderImage = this.getUIImage(this.placeholderImageUri);
this.initImage();
}
[ImageBase.failureImageUriProperty.setNative]() {
}
[ImageBase.stretchProperty.setNative](value) {
if (!this.nativeView) {
return;
}
this.nativeViewProtected.contentMode = getUIImageScaleType(value);
}
startAnimating() {
this.nativeViewProtected.startAnimating();
}
stopAnimating() {
this.nativeViewProtected.stopAnimating();
}
}
//# sourceMappingURL=image.ios.js.map