Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: add sys:// ios images #10555

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

Merged
merged 5 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion apps/toolbox/src/pages/image-handling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Observable, EventData, Page, ImageSource, knownFolders, path } from '@nativescript/core';
import { Observable, EventData, Page, ImageSource, knownFolders, path, ImageSymbolEffects } from '@nativescript/core';
import { create, ImagePickerMediaType } from '@nativescript/imagepicker';

let page: Page;
Expand All @@ -10,6 +10,10 @@ export function navigatingTo(args: EventData) {

export class DemoModel extends Observable {
addingPhoto = false;
symbolWiggleEffect: ImageSymbolEffects.Wiggle;
symbolBounceEffect: ImageSymbolEffects.Bounce;
symbolBreathEffect: ImageSymbolEffects.Breathe;
symbolRotateEffect: ImageSymbolEffects.Rotate;

pickImage() {
const context = create({
Expand Down
18 changes: 18 additions & 0 deletions apps/toolbox/src/pages/image-handling.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@
</Page.actionBar>

<StackLayout class="p-20">

<Label text="Test Memory leaks with image picking and saving to device. Best to profile from platform IDE like Xcode." textWrap="true" />

<Button text="Pick and Save Image" tap="{{ pickImage }}" />

<ios>
<!-- SF Symbols with Effects -->
<ContentView height="1" width="100%" backgroundColor="#efefef" margin="10"></ContentView>
<GridLayout rows="auto,auto,auto" columns="*,*">
<Image src="sys://photo.on.rectangle.angled" width="100" tintColor="green" symbolEffect="{{symbolWiggleEffect}}" padding="8"/>
<Image col="1" src="sys://steeringwheel.and.hands" width="100" tintColor="black" symbolEffect="{{symbolWiggleEffect}}" padding="8" />

<Image row="1" src="sys://airpods.pro.chargingcase.wireless.radiowaves.left.and.right.fill" width="100" symbolEffect="{{symbolBounceEffect}}" padding="8" />
<Image row="1" col="1" src="sys://lungs.fill" width="100" symbolEffect="{{symbolBreathEffect}}" padding="8" />


<Image row="2" src="sys://clock.arrow.trianglehead.2.counterclockwise.rotate.90" width="100" symbolEffect="{{symbolRotateEffect}}" padding="8" />
<Image row="2" col="1" src="sys://square.and.arrow.up" width="100" symbolEffect="{{symbolWiggleEffect}}" padding="8" />
</GridLayout>
</ios>


</StackLayout>
</Page>
14 changes: 11 additions & 3 deletions packages/core/image-source/index.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ export class ImageSource implements ImageSourceDefinition {
return ImageSource.fromFileSync(path);
}

static fromSystemImageSync(name: string): ImageSource {
return ImageSource.fromResourceSync(name);
}

static fromSystemImage(name: string): Promise<ImageSource> {
return ImageSource.fromResource(name);
}

static fromDataSync(data: any): ImageSource {
const bitmap = android.graphics.BitmapFactory.decodeStream(data);

Expand Down Expand Up @@ -335,7 +343,7 @@ export class ImageSource implements ImageSourceDefinition {
reject();
}
},
})
}),
);
});
}
Expand Down Expand Up @@ -375,7 +383,7 @@ export class ImageSource implements ImageSourceDefinition {
reject();
}
},
})
}),
);
});
}
Expand Down Expand Up @@ -404,7 +412,7 @@ export class ImageSource implements ImageSourceDefinition {
reject();
}
},
})
}),
);
});
}
Expand Down
12 changes: 12 additions & 0 deletions packages/core/image-source/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ export class ImageSource {
*/
static fromResource(name: string): Promise<ImageSource>;

/**
* Loads this instance from the specified system image name.
* @param name the name of the system image
*/
static fromSystemImageSync(name: string): ImageSource;

/**
* Loads this instance from the specified system image name asynchronously.
* @param name the name of the system image
*/
static fromSystemImage(name: string): Promise<ImageSource>;

/**
* Loads this instance from the specified file.
* @param path The location of the file on the file system.
Expand Down
28 changes: 26 additions & 2 deletions packages/core/image-source/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Trace } from '../trace';

// Types.
import { path as fsPath, knownFolders } from '../file-system';
import { isFileOrResourcePath, RESOURCE_PREFIX, layout, releaseNativeObject } from '../utils';
import { isFileOrResourcePath, RESOURCE_PREFIX, layout, releaseNativeObject, SYSTEM_PREFIX } from '../utils';

import { getScaledDimensions } from './image-source-common';

Expand Down Expand Up @@ -73,6 +73,27 @@ export class ImageSource implements ImageSourceDefinition {
return http.getImage(url);
}

static fromSystemImageSync(name: string): ImageSource {
const image = UIImage.systemImageNamed(name);

return image ? new ImageSource(image) : null;
}

static fromSystemImage(name: string): Promise<ImageSource> {
return new Promise<ImageSource>((resolve, reject) => {
try {
const image = UIImage.systemImageNamed(name);
if (image) {
resolve(new ImageSource(image));
} else {
reject(new Error(`Failed to load system icon with name: ${name}`));
}
} catch (ex) {
reject(ex);
}
});
}

static fromResourceSync(name: string): ImageSource {
const nativeSource = (<any>UIImage).tns_safeImageNamed(name) || (<any>UIImage).tns_safeImageNamed(`${name}.jpg`);

Expand Down Expand Up @@ -126,7 +147,10 @@ export class ImageSource implements ImageSourceDefinition {
}

if (path.indexOf(RESOURCE_PREFIX) === 0) {
return ImageSource.fromResourceSync(path.substr(RESOURCE_PREFIX.length));
return ImageSource.fromResourceSync(path.slice(RESOURCE_PREFIX.length));
}
if (path.indexOf(SYSTEM_PREFIX) === 0) {
return ImageSource.fromSystemImageSync(path.slice(SYSTEM_PREFIX.length));
}

return ImageSource.fromFileSync(path);
Expand Down
1 change: 1 addition & 0 deletions packages/core/references.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!CFNetwork.d.ts" />
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!CoreText.d.ts" />
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Darwin.d.ts" />
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Symbols.d.ts" />
/// <reference path="../types-android/src/lib/android-29.d.ts" />
/// <reference path="./platforms/ios/typings/objc!MaterialComponents.d.ts" />
/// <reference path="./platforms/ios/typings/objc!NativeScriptUtils.d.ts" />
Expand Down
23 changes: 21 additions & 2 deletions packages/core/ui/image/image-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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 change: 1 addition & 0 deletions packages/core/ui/image/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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).
*/
Expand Down
15 changes: 14 additions & 1 deletion packages/core/ui/image/index.ios.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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 changes: 37 additions & 0 deletions packages/core/ui/image/symbol-effects-common.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions packages/core/ui/image/symbol-effects.android.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions packages/core/ui/image/symbol-effects.d.ts
Original file line number Diff line number Diff line change
@@ -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;
}
Loading
Loading