mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-26 03:01:51 +08:00
feat(core): add sys://
support for SF Symbol usage on images with effects (#10555)
This commit is contained in:
@ -4,12 +4,13 @@ import { booleanConverter } from '../core/view-base';
|
||||
import { CoreTypes } from '../../core-types';
|
||||
import { ImageAsset } from '../../image-asset';
|
||||
import { ImageSource } from '../../image-source';
|
||||
import { isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX } from '../../utils';
|
||||
import { isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX, SYSTEM_PREFIX } from '../../utils';
|
||||
import { Color } from '../../color';
|
||||
import { Style } from '../styling/style';
|
||||
import { Length } from '../styling/style-properties';
|
||||
import { Property, InheritedCssProperty } from '../core/properties';
|
||||
import { Trace } from '../../trace';
|
||||
import { ImageSymbolEffect, ImageSymbolEffects } from './symbol-effects';
|
||||
|
||||
@CSSType('Image')
|
||||
export abstract class ImageBase extends View implements ImageDefinition {
|
||||
@ -75,13 +76,21 @@ export abstract class ImageBase extends View implements ImageDefinition {
|
||||
}
|
||||
} else if (isFileOrResourcePath(value)) {
|
||||
if (value.indexOf(RESOURCE_PREFIX) === 0) {
|
||||
const resPath = value.substr(RESOURCE_PREFIX.length);
|
||||
const resPath = value.slice(RESOURCE_PREFIX.length);
|
||||
if (sync) {
|
||||
imageLoaded(ImageSource.fromResourceSync(resPath));
|
||||
} else {
|
||||
this.imageSource = null;
|
||||
ImageSource.fromResource(resPath).then(imageLoaded);
|
||||
}
|
||||
} else if (value.indexOf(SYSTEM_PREFIX) === 0) {
|
||||
const sysPath = value.slice(SYSTEM_PREFIX.length);
|
||||
if (sync) {
|
||||
imageLoaded(ImageSource.fromSystemImageSync(sysPath));
|
||||
} else {
|
||||
this.imageSource = null;
|
||||
ImageSource.fromSystemImage(sysPath).then(imageLoaded);
|
||||
}
|
||||
} else {
|
||||
if (sync) {
|
||||
imageLoaded(ImageSource.fromFileSync(value));
|
||||
@ -178,3 +187,13 @@ export const decodeWidthProperty = new Property<ImageBase, CoreTypes.LengthType>
|
||||
valueConverter: Length.parse,
|
||||
});
|
||||
decodeWidthProperty.register(ImageBase);
|
||||
|
||||
/**
|
||||
* iOS only
|
||||
*/
|
||||
export const iosSymbolEffectProperty = new Property<ImageBase, ImageSymbolEffect | ImageSymbolEffects>({
|
||||
name: 'iosSymbolEffect',
|
||||
});
|
||||
iosSymbolEffectProperty.register(ImageBase);
|
||||
|
||||
export { ImageSymbolEffect, ImageSymbolEffects };
|
||||
|
1
packages/core/ui/image/index.d.ts
vendored
1
packages/core/ui/image/index.d.ts
vendored
@ -6,6 +6,7 @@ import { Color } from '../../color';
|
||||
import { Property, InheritedCssProperty } from '../core/properties';
|
||||
import { CoreTypes } from '../../core-types';
|
||||
|
||||
export { ImageSymbolEffect, ImageSymbolEffects } from './image-common';
|
||||
/**
|
||||
* Represents a class that provides functionality for loading and streching image(s).
|
||||
*/
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { ImageBase, stretchProperty, imageSourceProperty, tintColorProperty, srcProperty } from './image-common';
|
||||
import { ImageBase, stretchProperty, imageSourceProperty, tintColorProperty, srcProperty, iosSymbolEffectProperty, ImageSymbolEffect, ImageSymbolEffects } from './image-common';
|
||||
import { ImageSource } from '../../image-source';
|
||||
import { ImageAsset } from '../../image-asset';
|
||||
import { Color } from '../../color';
|
||||
import { Trace } from '../../trace';
|
||||
import { layout, queueGC } from '../../utils';
|
||||
import { SDK_VERSION } from '../../utils/constants';
|
||||
|
||||
export * from './image-common';
|
||||
|
||||
@ -194,4 +195,16 @@ export class Image extends ImageBase {
|
||||
[srcProperty.setNative](value: string | ImageSource | ImageAsset) {
|
||||
this._createImageSourceFromSrc(value);
|
||||
}
|
||||
|
||||
[iosSymbolEffectProperty.setNative](value: ImageSymbolEffect | ImageSymbolEffects) {
|
||||
if (SDK_VERSION < 17) {
|
||||
return;
|
||||
}
|
||||
const symbol = typeof value === 'string' ? ImageSymbolEffect.fromSymbol(value) : value;
|
||||
if (symbol && symbol.effect) {
|
||||
this.nativeViewProtected.addSymbolEffectOptionsAnimatedCompletion(symbol.effect, symbol.options || NSSymbolEffectOptions.optionsWithRepeating(), true, symbol.completion || null);
|
||||
} else {
|
||||
this.nativeViewProtected.removeAllSymbolEffects();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
37
packages/core/ui/image/symbol-effects-common.ts
Normal file
37
packages/core/ui/image/symbol-effects-common.ts
Normal file
@ -0,0 +1,37 @@
|
||||
export enum ImageSymbolEffects {
|
||||
Appear = 'appear',
|
||||
AppearUp = 'appearUp',
|
||||
AppearDown = 'appearDown',
|
||||
Bounce = 'bounce',
|
||||
BounceUp = 'bounceUp',
|
||||
BounceDown = 'bounceDown',
|
||||
Disappear = 'disappear',
|
||||
DisappearDown = 'disappearDown',
|
||||
DisappearUp = 'disappearUp',
|
||||
Pulse = 'pulse',
|
||||
Scale = 'scale',
|
||||
ScaleDown = 'scaleDown',
|
||||
ScaleUp = 'scaleUp',
|
||||
VariableColor = 'variableColor',
|
||||
Breathe = 'breathe',
|
||||
BreathePlain = 'breathePlain',
|
||||
BreathePulse = 'breathePulse',
|
||||
Rotate = 'rotate',
|
||||
RotateClockwise = 'rotateClockwise',
|
||||
RotateCounterClockwise = 'rotateCounterClockwise',
|
||||
Wiggle = 'wiggle',
|
||||
WiggleBackward = 'wiggleBackward',
|
||||
WiggleClockwise = 'wiggleClockwise',
|
||||
WiggleCounterClockwise = 'wiggleCounterClockwise',
|
||||
WiggleDown = 'wiggleDown',
|
||||
WiggleForward = 'wiggleForward',
|
||||
WiggleUp = 'wiggleUp',
|
||||
WiggleLeft = 'wiggleLeft',
|
||||
WiggleRight = 'wiggleRight',
|
||||
}
|
||||
|
||||
export class ImageSymbolEffectCommon {
|
||||
effect?: NSSymbolEffect;
|
||||
options?: NSSymbolEffectOptions;
|
||||
completion?: (context: UISymbolEffectCompletionContext) => void;
|
||||
}
|
9
packages/core/ui/image/symbol-effects.android.ts
Normal file
9
packages/core/ui/image/symbol-effects.android.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ImageSymbolEffectCommon, ImageSymbolEffects } from './symbol-effects-common';
|
||||
import type { ImageSymbolEffect as ImageSymbolEffectDefinition } from './symbol-effects.d.ts';
|
||||
export { ImageSymbolEffects };
|
||||
|
||||
export const ImageSymbolEffect: typeof ImageSymbolEffectDefinition = class ImageSymbolEffect extends ImageSymbolEffectCommon implements ImageSymbolEffectDefinition {
|
||||
static fromSymbol(symbol: string): ImageSymbolEffectDefinition {
|
||||
return new ImageSymbolEffect();
|
||||
}
|
||||
};
|
13
packages/core/ui/image/symbol-effects.d.ts
vendored
Normal file
13
packages/core/ui/image/symbol-effects.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
export { ImageSymbolEffects } from './symbol-effects-common';
|
||||
|
||||
/**
|
||||
* iOS only
|
||||
* Symbol effects: https://developer.apple.com/documentation/symbols?language=objc
|
||||
*/
|
||||
export class ImageSymbolEffect {
|
||||
effect?: NSSymbolEffect;
|
||||
options?: NSSymbolEffectOptions;
|
||||
completion?: (context: UISymbolEffectCompletionContext) => void;
|
||||
constructor(symbol: NSSymbolEffect);
|
||||
static fromSymbol(symbol: string): ImageSymbolEffect | null;
|
||||
}
|
95
packages/core/ui/image/symbol-effects.ios.ts
Normal file
95
packages/core/ui/image/symbol-effects.ios.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { SDK_VERSION } from '../../utils/constants';
|
||||
import { ImageSymbolEffectCommon, ImageSymbolEffects } from './symbol-effects-common';
|
||||
import type { ImageSymbolEffect as ImageSymbolEffectDefinition } from './symbol-effects.d.ts';
|
||||
|
||||
export const ImageSymbolEffect: typeof ImageSymbolEffectDefinition = class ImageSymbolEffect extends ImageSymbolEffectCommon implements ImageSymbolEffectDefinition {
|
||||
constructor(symbol: NSSymbolEffect) {
|
||||
super();
|
||||
this.effect = symbol;
|
||||
}
|
||||
static fromSymbol(symbol: string): ImageSymbolEffectDefinition | null {
|
||||
if (SDK_VERSION < 17) {
|
||||
return null;
|
||||
}
|
||||
switch (symbol) {
|
||||
case ImageSymbolEffects.Appear:
|
||||
return new ImageSymbolEffect(NSSymbolAppearEffect.effect());
|
||||
case ImageSymbolEffects.AppearUp:
|
||||
return new ImageSymbolEffect(NSSymbolAppearEffect.appearUpEffect());
|
||||
case ImageSymbolEffects.AppearDown:
|
||||
return new ImageSymbolEffect(NSSymbolAppearEffect.appearDownEffect());
|
||||
case ImageSymbolEffects.Bounce:
|
||||
return new ImageSymbolEffect(NSSymbolBounceEffect.effect());
|
||||
case ImageSymbolEffects.BounceUp:
|
||||
return new ImageSymbolEffect(NSSymbolBounceEffect.bounceUpEffect());
|
||||
case ImageSymbolEffects.BounceDown:
|
||||
return new ImageSymbolEffect(NSSymbolBounceEffect.bounceDownEffect());
|
||||
case ImageSymbolEffects.Disappear:
|
||||
return new ImageSymbolEffect(NSSymbolDisappearEffect.effect());
|
||||
case ImageSymbolEffects.DisappearDown:
|
||||
return new ImageSymbolEffect(NSSymbolDisappearEffect.disappearDownEffect());
|
||||
case ImageSymbolEffects.DisappearUp:
|
||||
return new ImageSymbolEffect(NSSymbolDisappearEffect.disappearUpEffect());
|
||||
case ImageSymbolEffects.Pulse:
|
||||
return new ImageSymbolEffect(NSSymbolPulseEffect.effect());
|
||||
case ImageSymbolEffects.Scale:
|
||||
return new ImageSymbolEffect(NSSymbolScaleEffect.effect());
|
||||
case ImageSymbolEffects.ScaleDown:
|
||||
return new ImageSymbolEffect(NSSymbolScaleEffect.scaleDownEffect());
|
||||
case ImageSymbolEffects.ScaleUp:
|
||||
return new ImageSymbolEffect(NSSymbolScaleEffect.scaleUpEffect());
|
||||
case ImageSymbolEffects.VariableColor:
|
||||
return new ImageSymbolEffect(NSSymbolVariableColorEffect.effect());
|
||||
}
|
||||
if (SDK_VERSION < 18) {
|
||||
return null;
|
||||
}
|
||||
// TODO: remove ts-expect-error once we bump the types package
|
||||
switch (symbol) {
|
||||
case ImageSymbolEffects.Breathe:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolBreatheEffect.effect());
|
||||
case ImageSymbolEffects.BreathePlain:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolBreatheEffect.breathePlainEffect());
|
||||
case ImageSymbolEffects.Rotate:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolRotateEffect.effect());
|
||||
case ImageSymbolEffects.RotateClockwise:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolRotateEffect.rotateClockwiseEffect());
|
||||
case ImageSymbolEffects.RotateCounterClockwise:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolRotateEffect.rotateCounterClockwiseEffect());
|
||||
case ImageSymbolEffects.Wiggle:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.effect());
|
||||
case ImageSymbolEffects.WiggleBackward:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleBackwardEffect());
|
||||
case ImageSymbolEffects.WiggleClockwise:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleClockwiseEffect());
|
||||
case ImageSymbolEffects.WiggleCounterClockwise:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleCounterClockwiseEffect());
|
||||
case ImageSymbolEffects.WiggleDown:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleDownEffect());
|
||||
case ImageSymbolEffects.WiggleForward:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleForwardEffect());
|
||||
case ImageSymbolEffects.WiggleUp:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleUpEffect());
|
||||
case ImageSymbolEffects.WiggleLeft:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleLeftEffect());
|
||||
case ImageSymbolEffects.WiggleRight:
|
||||
// @ts-expect-error added on iOS 18
|
||||
return new ImageSymbolEffect(NSSymbolWiggleEffect.wiggleRightEffect());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
@ -31,7 +31,7 @@ export { GesturesObserver, TouchAction, GestureTypes, GestureStateTypes, SwipeDi
|
||||
export type { GestureEventData, GestureEventDataWithState, TapGestureEventData, PanGestureEventData, PinchGestureEventData, RotationGestureEventData, SwipeGestureEventData, TouchGestureEventData, TouchAnimationOptions, VisionHoverOptions } from './gestures';
|
||||
|
||||
export { HtmlView } from './html-view';
|
||||
export { Image } from './image';
|
||||
export { Image, ImageSymbolEffect, ImageSymbolEffects } from './image';
|
||||
export { Cache as ImageCache } from './image-cache';
|
||||
export type { DownloadError, DownloadRequest, DownloadedData } from './image-cache';
|
||||
export { Label } from './label';
|
||||
|
Reference in New Issue
Block a user