mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
feat: add font icons to image actionbar and tab navigation (#7498)
This commit is contained in:

committed by
Manol Donev

parent
aa1c160465
commit
d8262a624e
11
e2e/ui-tests-app/app/action-bar/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/action-bar/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.font-awesome {
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-size {
|
||||||
|
font-size: 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color {
|
||||||
|
color: blue;
|
||||||
|
}
|
17
e2e/ui-tests-app/app/action-bar/font-icons-page.ts
Normal file
17
e2e/ui-tests-app/app/action-bar/font-icons-page.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import * as frame from "tns-core-modules/ui/frame";
|
||||||
|
import { EventData } from "tns-core-modules/ui/frame";
|
||||||
|
import { Button } from "tns-core-modules/ui/button";
|
||||||
|
import { ActionBar } from "tns-core-modules/ui/action-bar";
|
||||||
|
|
||||||
|
const iconModes = ["automatic", "alwaysOriginal", "alwaysTemplate", undefined];
|
||||||
|
|
||||||
|
export function navigate(args) {
|
||||||
|
frame.topmost().navigate("ui-tests-app/action-bar/clean");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onChangeRenderingMode(args: EventData) {
|
||||||
|
const button = <Button>args.object;
|
||||||
|
const actionBar = <ActionBar>button.page.actionBar;
|
||||||
|
actionBar.iosIconRenderingMode = <"automatic" | "alwaysOriginal" | "alwaysTemplate">iconModes[(iconModes.indexOf(actionBar.iosIconRenderingMode) + 1) % iconModes.length];
|
||||||
|
button.text = "" + actionBar.iosIconRenderingMode;
|
||||||
|
}
|
19
e2e/ui-tests-app/app/action-bar/font-icons-page.xml
Normal file
19
e2e/ui-tests-app/app/action-bar/font-icons-page.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<Page>
|
||||||
|
<Page.actionBar>
|
||||||
|
<ActionBar>
|
||||||
|
<ActionBar.actionItems>
|
||||||
|
<!-- font family + font size + color -->
|
||||||
|
<ActionItem icon="font://" class="font-awesome font-size color" tap="navigate"/>
|
||||||
|
<!-- default font + valid char code -->
|
||||||
|
<ActionItem icon="font://" tap="navigate"/>
|
||||||
|
<!-- font family + invalid char code -->
|
||||||
|
<ActionItem icon="font://" class="font-awesome font-size" tap="navigate"/>
|
||||||
|
</ActionBar.actionItems>
|
||||||
|
</ActionBar>
|
||||||
|
</Page.actionBar>
|
||||||
|
|
||||||
|
<StackLayout>
|
||||||
|
<Button text="go to cleared page" tap="navigate"/>
|
||||||
|
<Button text="undefined" tap="onChangeRenderingMode"/>
|
||||||
|
</StackLayout>
|
||||||
|
</Page>
|
@ -23,6 +23,7 @@ export function loadExamples() {
|
|||||||
examples.set("actTransparentBgCss", "action-bar/transparent-bg-css-page");
|
examples.set("actTransparentBgCss", "action-bar/transparent-bg-css-page");
|
||||||
examples.set("modalHiddenActBar", "action-bar/modal-test-hidden-action-bar-page");
|
examples.set("modalHiddenActBar", "action-bar/modal-test-hidden-action-bar-page");
|
||||||
examples.set("modalShownActBar", "action-bar/modal-test-with-action-bar-page");
|
examples.set("modalShownActBar", "action-bar/modal-test-with-action-bar-page");
|
||||||
|
examples.set("font-icons", "action-bar/font-icons-page");
|
||||||
examples.set("flat", "action-bar/flat-page");
|
examples.set("flat", "action-bar/flat-page");
|
||||||
examples.set("flat-tab", "action-bar/flat-tab-page");
|
examples.set("flat-tab", "action-bar/flat-tab-page");
|
||||||
examples.set("flat-tab-opaque-bar", "action-bar/flat-tab-opaque-bar-page");
|
examples.set("flat-tab-opaque-bar", "action-bar/flat-tab-opaque-bar-page");
|
||||||
|
11
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.font-awesome {
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-size {
|
||||||
|
font-size: 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color {
|
||||||
|
color: blue;
|
||||||
|
}
|
34
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml
Normal file
34
e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<Page class="page">
|
||||||
|
|
||||||
|
<ActionBar title="BottomNavigation font icons" icon="" class="action-bar">
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<BottomNavigation class="font-awesome"> <!-- TODO: The font-awesome class here should be removed -->
|
||||||
|
<TabStrip>
|
||||||
|
<!-- font family + font size + color -->
|
||||||
|
<TabStripItem title="First" iconSource="font://" class="special font-awesome font-size color"></TabStripItem>
|
||||||
|
<!-- default font + valid char code -->
|
||||||
|
<TabStripItem title="Second" iconSource="font://"></TabStripItem>
|
||||||
|
<!-- font family + invalid char code -->
|
||||||
|
<TabStripItem title="Third" iconSource="font://" class="font-awesome font-size"></TabStripItem>
|
||||||
|
</TabStrip>
|
||||||
|
|
||||||
|
<TabContentItem class="special">
|
||||||
|
<GridLayout>
|
||||||
|
<Label text="First View" />
|
||||||
|
</GridLayout>
|
||||||
|
</TabContentItem>
|
||||||
|
|
||||||
|
<TabContentItem>
|
||||||
|
<GridLayout>
|
||||||
|
<Label text="Second View" />
|
||||||
|
</GridLayout>
|
||||||
|
</TabContentItem>
|
||||||
|
|
||||||
|
<TabContentItem>
|
||||||
|
<GridLayout>
|
||||||
|
<Label text="Third View" />
|
||||||
|
</GridLayout>
|
||||||
|
</TabContentItem>
|
||||||
|
</BottomNavigation>
|
||||||
|
</Page>
|
@ -20,6 +20,7 @@ export function loadExamples() {
|
|||||||
examples.set("icon-title-placement", "bottom-navigation/icon-title-placement-page");
|
examples.set("icon-title-placement", "bottom-navigation/icon-title-placement-page");
|
||||||
examples.set("icon-change", "bottom-navigation/icon-change-page");
|
examples.set("icon-change", "bottom-navigation/icon-change-page");
|
||||||
examples.set("binding", "bottom-navigation/binding-page");
|
examples.set("binding", "bottom-navigation/binding-page");
|
||||||
|
examples.set("font-icons", "bottom-navigation/font-icons-page");
|
||||||
|
|
||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
||||||
|
11
e2e/ui-tests-app/app/image-view/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/image-view/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.font-awesome {
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-size {
|
||||||
|
font-size: 96;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color {
|
||||||
|
color: blue;
|
||||||
|
}
|
16
e2e/ui-tests-app/app/image-view/font-icons-page.xml
Normal file
16
e2e/ui-tests-app/app/image-view/font-icons-page.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<Page navigatingTo="navigatingTo">
|
||||||
|
<GridLayout rows="*, *, *" columns="*, *" height="200">
|
||||||
|
<!-- font family only -->
|
||||||
|
<Image row="0" col="0" src="font://" class="font-awesome"/>
|
||||||
|
<!-- font family + font size -->
|
||||||
|
<Image row="0" col="1" src="font://" class="font-awesome font-size"/>
|
||||||
|
<!-- font family + color -->
|
||||||
|
<Image row="1" col="0" src="font://" class="font-awesome color"/>
|
||||||
|
<!-- font family + font size + color -->
|
||||||
|
<Image row="1" col="1" src="font://" class="font-awesome font-size color"/>
|
||||||
|
<!-- default font + valid char code -->
|
||||||
|
<Image row="2" col="0" src="font://" />
|
||||||
|
<!-- font family + invalid char code -->
|
||||||
|
<Image row="2" col="1" src="font://" class="font-awesome"/>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
@ -17,6 +17,7 @@ export function loadExamples() {
|
|||||||
examples.set("stretch-modes", "image-view/stretch-modes-page");
|
examples.set("stretch-modes", "image-view/stretch-modes-page");
|
||||||
examples.set("missing-image", "image-view/missing-image-page");
|
examples.set("missing-image", "image-view/missing-image-page");
|
||||||
examples.set("image-asset", "image-view/image-asset/image-asset-page");
|
examples.set("image-asset", "image-view/image-asset/image-asset-page");
|
||||||
|
examples.set("font-icons", "image-view/font-icons-page");
|
||||||
|
|
||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
||||||
|
11
e2e/ui-tests-app/app/tabs/font-icons-page.css
Normal file
11
e2e/ui-tests-app/app/tabs/font-icons-page.css
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.font-awesome {
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-size {
|
||||||
|
font-size: 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color {
|
||||||
|
color: blue;
|
||||||
|
}
|
34
e2e/ui-tests-app/app/tabs/font-icons-page.xml
Normal file
34
e2e/ui-tests-app/app/tabs/font-icons-page.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<Page class="page">
|
||||||
|
|
||||||
|
<ActionBar title="Tabs font icons" icon="" class="action-bar">
|
||||||
|
</ActionBar>
|
||||||
|
|
||||||
|
<Tabs class="font-awesome"> <!-- TODO: The font-awesome class here should be removed -->
|
||||||
|
<TabStrip>
|
||||||
|
<!-- font family + font size + color -->
|
||||||
|
<TabStripItem title="First" iconSource="font://" class="special font-awesome font-size color"></TabStripItem>
|
||||||
|
<!-- default font + valid char code -->
|
||||||
|
<TabStripItem title="Second" iconSource="font://"></TabStripItem>
|
||||||
|
<!-- font family + invalid char code -->
|
||||||
|
<TabStripItem title="Third" iconSource="font://" class="font-awesome font-size"></TabStripItem>
|
||||||
|
</TabStrip>
|
||||||
|
|
||||||
|
<TabContentItem class="special">
|
||||||
|
<GridLayout>
|
||||||
|
<Label text="First View" />
|
||||||
|
</GridLayout>
|
||||||
|
</TabContentItem>
|
||||||
|
|
||||||
|
<TabContentItem>
|
||||||
|
<GridLayout>
|
||||||
|
<Label text="Second View" />
|
||||||
|
</GridLayout>
|
||||||
|
</TabContentItem>
|
||||||
|
|
||||||
|
<TabContentItem>
|
||||||
|
<GridLayout>
|
||||||
|
<Label text="Third View" />
|
||||||
|
</GridLayout>
|
||||||
|
</TabContentItem>
|
||||||
|
</Tabs>
|
||||||
|
</Page>
|
@ -26,6 +26,7 @@ export function loadExamples() {
|
|||||||
examples.set("strip-items", "tabs/tab-strip-items-page");
|
examples.set("strip-items", "tabs/tab-strip-items-page");
|
||||||
examples.set("tabs-position", "tabs/tabs-position-page");
|
examples.set("tabs-position", "tabs/tabs-position-page");
|
||||||
examples.set("tabs-binding", "tabs/tabs-binding-page");
|
examples.set("tabs-binding", "tabs/tabs-binding-page");
|
||||||
|
examples.set("font-icons", "tabs/font-icons-page");
|
||||||
|
|
||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
||||||
|
BIN
tests/app/font/FontAwesome.ttf
Normal file
BIN
tests/app/font/FontAwesome.ttf
Normal file
Binary file not shown.
@ -3,6 +3,8 @@ import * as imageAssetModule from "tns-core-modules/image-asset";
|
|||||||
import * as fs from "tns-core-modules/file-system";
|
import * as fs from "tns-core-modules/file-system";
|
||||||
import * as app from "tns-core-modules/application";
|
import * as app from "tns-core-modules/application";
|
||||||
import * as TKUnit from "../tk-unit";
|
import * as TKUnit from "../tk-unit";
|
||||||
|
import { Font } from "tns-core-modules/ui/styling/font";
|
||||||
|
import { Color } from "tns-core-modules/color";
|
||||||
|
|
||||||
const imagePath = "~/assets/logo.png";
|
const imagePath = "~/assets/logo.png";
|
||||||
const splashscreenPath = "~/assets/splashscreen.png";
|
const splashscreenPath = "~/assets/splashscreen.png";
|
||||||
@ -285,3 +287,12 @@ export function testLoadFromBase64Encode_PNG() {
|
|||||||
TKUnit.assertEqual(img.width, 4, "img.width");
|
TKUnit.assertEqual(img.width, 4, "img.width");
|
||||||
TKUnit.assertEqual(img.height, 4, "img.height");
|
TKUnit.assertEqual(img.height, 4, "img.height");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function testLoadFromFontIconCode() {
|
||||||
|
let img: imageSource.ImageSource;
|
||||||
|
img = imageSource.fromFontIconCode("F10B", Font.default.withFontFamily("FontAwesome"), new Color("red"));
|
||||||
|
|
||||||
|
TKUnit.assert(img !== null, "Actual: " + img);
|
||||||
|
TKUnit.assert(img.width !== null, "img.width");
|
||||||
|
TKUnit.assert(img.height !== null, "img.width");
|
||||||
|
}
|
||||||
|
@ -136,6 +136,14 @@ export const test_SettingImageSrcToDataURI_async = function (done) {
|
|||||||
runImageTestAsync(image, image.src, done);
|
runImageTestAsync(image, image.src, done);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const test_SettingImageSrcToFontIconCode_sync = function () {
|
||||||
|
const image = new ImageModule.Image();
|
||||||
|
image.style.fontFamily = "FontAwesome";
|
||||||
|
image.src = "font://";
|
||||||
|
|
||||||
|
runImageTestSync(image, image.src);
|
||||||
|
};
|
||||||
|
|
||||||
export function test_imageSourceNotResetAfterCreateUI() {
|
export function test_imageSourceNotResetAfterCreateUI() {
|
||||||
let image = new ImageModule.Image();
|
let image = new ImageModule.Image();
|
||||||
let imageSource = ImageSourceModule.fromResource("splashscreen");
|
let imageSource = ImageSourceModule.fromResource("splashscreen");
|
||||||
|
@ -5,8 +5,10 @@ import * as httpModule from "../http";
|
|||||||
|
|
||||||
// Types.
|
// Types.
|
||||||
import { path as fsPath, knownFolders } from "../file-system";
|
import { path as fsPath, knownFolders } from "../file-system";
|
||||||
import { isFileOrResourcePath, RESOURCE_PREFIX } from "../utils/utils";
|
import { isFileOrResourcePath, RESOURCE_PREFIX, layout } from "../utils/utils";
|
||||||
import { getNativeApplication } from "../application";
|
import { getNativeApplication } from "../application";
|
||||||
|
import { Font } from "../ui/styling/font";
|
||||||
|
import { Color } from "../color";
|
||||||
|
|
||||||
export { isFileOrResourcePath };
|
export { isFileOrResourcePath };
|
||||||
|
|
||||||
@ -140,6 +142,43 @@ export class ImageSource implements ImageSourceDefinition {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public loadFromFontIconCode(source: string, font: Font, color: Color): boolean {
|
||||||
|
const paint = new android.graphics.Paint();
|
||||||
|
paint.setTypeface(font.getAndroidTypeface());
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
|
||||||
|
if (color) {
|
||||||
|
paint.setColor(color.android);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fontSize = layout.toDevicePixels(font.fontSize);
|
||||||
|
if (!fontSize) {
|
||||||
|
// TODO: Consider making 36 font size as default for optimal look on TabView and ActionBar
|
||||||
|
fontSize = paint.getTextSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
const density = layout.getDisplayDensity();
|
||||||
|
const scaledFontSize = fontSize * density;
|
||||||
|
paint.setTextSize(scaledFontSize);
|
||||||
|
|
||||||
|
const textBounds = new android.graphics.Rect();
|
||||||
|
paint.getTextBounds(source, 0, source.length, textBounds);
|
||||||
|
|
||||||
|
const bitmap = android.graphics.Bitmap
|
||||||
|
.createBitmap(
|
||||||
|
textBounds.width(),
|
||||||
|
textBounds.height(),
|
||||||
|
android.graphics.Bitmap.Config.ARGB_8888
|
||||||
|
);
|
||||||
|
|
||||||
|
const canvas = new android.graphics.Canvas(bitmap);
|
||||||
|
canvas.drawText(source, -textBounds.left, -textBounds.top, paint);
|
||||||
|
|
||||||
|
this.android = bitmap;
|
||||||
|
|
||||||
|
return this.android != null;
|
||||||
|
}
|
||||||
|
|
||||||
public setNativeSource(source: any): void {
|
public setNativeSource(source: any): void {
|
||||||
if (source && !(source instanceof android.graphics.Bitmap)) {
|
if (source && !(source instanceof android.graphics.Bitmap)) {
|
||||||
throw new Error("The method setNativeSource() expects android.graphics.Bitmap instance.");
|
throw new Error("The method setNativeSource() expects android.graphics.Bitmap instance.");
|
||||||
@ -241,6 +280,12 @@ export function fromData(data: any): ImageSource {
|
|||||||
return image.loadFromData(data) ? image : null;
|
return image.loadFromData(data) ? image : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fromFontIconCode(source: string, font: Font, color: Color): ImageSource {
|
||||||
|
const image = new ImageSource();
|
||||||
|
|
||||||
|
return image.loadFromFontIconCode(source, font, color) ? image : null;
|
||||||
|
}
|
||||||
|
|
||||||
export function fromBase64(source: string): ImageSource {
|
export function fromBase64(source: string): ImageSource {
|
||||||
const image = new ImageSource();
|
const image = new ImageSource();
|
||||||
|
|
||||||
|
18
tns-core-modules/image-source/image-source.d.ts
vendored
18
tns-core-modules/image-source/image-source.d.ts
vendored
@ -4,6 +4,8 @@
|
|||||||
*/ /** */
|
*/ /** */
|
||||||
|
|
||||||
import * as imageAssetModule from "../image-asset";
|
import * as imageAssetModule from "../image-asset";
|
||||||
|
import { Font } from "../ui/styling/font";
|
||||||
|
import { Color } from "../color";
|
||||||
/**
|
/**
|
||||||
* Encapsulates the common abstraction behind a platform specific object (typically a Bitmap) that is used as a source for images.
|
* Encapsulates the common abstraction behind a platform specific object (typically a Bitmap) that is used as a source for images.
|
||||||
*/
|
*/
|
||||||
@ -87,6 +89,14 @@ export class ImageSource {
|
|||||||
*/
|
*/
|
||||||
fromBase64(source: string): Promise<boolean>;
|
fromBase64(source: string): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads this instance from the specified font icon code.
|
||||||
|
* @param source The hex font icon code string
|
||||||
|
* @param font The font for the corresponding font icon code
|
||||||
|
* @param color The color of the generated icon image
|
||||||
|
*/
|
||||||
|
loadFromFontIconCode(source: string, font: Font, color: Color): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the provided native source object (typically a Bitmap or a UIImage).
|
* Sets the provided native source object (typically a Bitmap or a UIImage).
|
||||||
* This will update either the android or ios properties, depending on the target os.
|
* This will update either the android or ios properties, depending on the target os.
|
||||||
@ -147,6 +157,14 @@ export function fromBase64(source: string): ImageSource;
|
|||||||
*/
|
*/
|
||||||
export function fromNativeSource(source: any): ImageSource;
|
export function fromNativeSource(source: any): ImageSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ImageSource instance and loads it from the specified font icon code.
|
||||||
|
* @param source The hex font icon code string
|
||||||
|
* @param font The font for the corresponding font icon code
|
||||||
|
* @param color The color of the generated icon image
|
||||||
|
*/
|
||||||
|
export function fromFontIconCode(source: string, font: Font, color: Color): ImageSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads the image from the provided Url and creates a new ImageSource instance from it.
|
* Downloads the image from the provided Url and creates a new ImageSource instance from it.
|
||||||
* @param url The link to the remote image object. This operation will download and decode the image.
|
* @param url The link to the remote image object. This operation will download and decode the image.
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
import { ImageSource as ImageSourceDefinition } from ".";
|
import { ImageSource as ImageSourceDefinition } from ".";
|
||||||
import { ImageAsset } from "../image-asset";
|
import { ImageAsset } from "../image-asset";
|
||||||
import * as httpModule from "../http";
|
import * as httpModule from "../http";
|
||||||
|
import { Font } from "../ui/styling/font";
|
||||||
|
import { Color } from "../color";
|
||||||
|
|
||||||
// Types.
|
// Types.
|
||||||
import { path as fsPath, knownFolders } from "../file-system";
|
import { path as fsPath, knownFolders } from "../file-system";
|
||||||
import { isFileOrResourcePath, RESOURCE_PREFIX } from "../utils/utils";
|
import { isFileOrResourcePath, RESOURCE_PREFIX, layout } from "../utils/utils";
|
||||||
|
|
||||||
export { isFileOrResourcePath };
|
export { isFileOrResourcePath };
|
||||||
|
|
||||||
@ -121,6 +123,37 @@ export class ImageSource implements ImageSourceDefinition {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public loadFromFontIconCode(source: string, font: Font, color: Color): boolean {
|
||||||
|
let fontSize = layout.toDevicePixels(font.fontSize);
|
||||||
|
if (!fontSize) {
|
||||||
|
// TODO: Consider making 36 font size as default for optimal look on TabView and ActionBar
|
||||||
|
fontSize = UIFont.labelFontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
const density = layout.getDisplayDensity();
|
||||||
|
const scaledFontSize = fontSize * density;
|
||||||
|
|
||||||
|
const attributes = {
|
||||||
|
[NSFontAttributeName]: font.getUIFont(UIFont.systemFontOfSize(scaledFontSize))
|
||||||
|
};
|
||||||
|
|
||||||
|
if (color) {
|
||||||
|
attributes[NSForegroundColorAttributeName] = color.ios;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributedString = NSAttributedString.alloc().initWithStringAttributes(source, <NSDictionary<string, any>>attributes);
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContextWithOptions(attributedString.size(), false, 0.0);
|
||||||
|
attributedString.drawAtPoint(CGPointMake(0, 0));
|
||||||
|
|
||||||
|
const iconImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
|
this.ios = iconImage;
|
||||||
|
|
||||||
|
return this.ios != null;
|
||||||
|
}
|
||||||
|
|
||||||
public setNativeSource(source: any): void {
|
public setNativeSource(source: any): void {
|
||||||
if (source && !(source instanceof UIImage)) {
|
if (source && !(source instanceof UIImage)) {
|
||||||
throw new Error("The method setNativeSource() expects UIImage instance.");
|
throw new Error("The method setNativeSource() expects UIImage instance.");
|
||||||
@ -231,6 +264,12 @@ export function fromFile(path: string): ImageSource {
|
|||||||
return image.loadFromFile(path) ? image : null;
|
return image.loadFromFile(path) ? image : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fromFontIconCode(source: string, font: Font, color: Color): ImageSource {
|
||||||
|
const image = new ImageSource();
|
||||||
|
|
||||||
|
return image.loadFromFontIconCode(source, font, color) ? image : null;
|
||||||
|
}
|
||||||
|
|
||||||
export function fromData(data: any): ImageSource {
|
export function fromData(data: any): ImageSource {
|
||||||
const image = new ImageSource();
|
const image = new ImageSource();
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ import {
|
|||||||
View, layout, colorProperty, flatProperty,
|
View, layout, colorProperty, flatProperty,
|
||||||
Color, traceMissingIcon
|
Color, traceMissingIcon
|
||||||
} from "./action-bar-common";
|
} from "./action-bar-common";
|
||||||
import { RESOURCE_PREFIX } from "../../utils/utils";
|
import { RESOURCE_PREFIX, isFontIconURI } from "../../utils/utils";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource, fromFontIconCode } from "../../image-source";
|
||||||
import * as application from "../../application";
|
import * as application from "../../application";
|
||||||
|
|
||||||
export * from "./action-bar-common";
|
export * from "./action-bar-common";
|
||||||
@ -311,11 +311,23 @@ export class ActionBar extends ActionBarBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item.icon) {
|
else if (item.icon) {
|
||||||
|
if (isFontIconURI(item.icon)) {
|
||||||
|
const fontIconCode = item.icon.split("//")[1];
|
||||||
|
const font = item.style.fontInternal;
|
||||||
|
const color = item.style.color;
|
||||||
|
const is = fromFontIconCode(fontIconCode, font, color);
|
||||||
|
|
||||||
|
if (is && is.android) {
|
||||||
|
const drawable = new android.graphics.drawable.BitmapDrawable(appResources, is.android);
|
||||||
|
menuItem.setIcon(drawable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let drawableOrId = getDrawableOrResourceId(item.icon, appResources);
|
let drawableOrId = getDrawableOrResourceId(item.icon, appResources);
|
||||||
if (drawableOrId) {
|
if (drawableOrId) {
|
||||||
menuItem.setIcon(drawableOrId);
|
menuItem.setIcon(drawableOrId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let showAsAction = getShowAsAction(item);
|
let showAsAction = getShowAsAction(item);
|
||||||
menuItem.setShowAsAction(showAsAction);
|
menuItem.setShowAsAction(showAsAction);
|
||||||
|
@ -4,8 +4,8 @@ import {
|
|||||||
colorProperty, backgroundColorProperty,
|
colorProperty, backgroundColorProperty,
|
||||||
backgroundInternalProperty, flatProperty, iosIconRenderingModeProperty,
|
backgroundInternalProperty, flatProperty, iosIconRenderingModeProperty,
|
||||||
layout, Color, traceMissingIcon } from "./action-bar-common";
|
layout, Color, traceMissingIcon } from "./action-bar-common";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource, fromFontIconCode } from "../../image-source";
|
||||||
import { ios as iosUtils } from "../../utils/utils";
|
import { ios as iosUtils, isFontIconURI } from "../../utils/utils";
|
||||||
|
|
||||||
export * from "./action-bar-common";
|
export * from "./action-bar-common";
|
||||||
|
|
||||||
@ -255,7 +255,23 @@ export class ActionBar extends ActionBarBase {
|
|||||||
|
|
||||||
barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(id, tapHandler, "tap");
|
barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(id, tapHandler, "tap");
|
||||||
} else if (item.icon) {
|
} else if (item.icon) {
|
||||||
const img = loadActionIconFromFileOrResource(item.icon);
|
let img = null;
|
||||||
|
|
||||||
|
if (isFontIconURI(item.icon)) {
|
||||||
|
const fontIconCode = item.icon.split("//")[1];
|
||||||
|
const font = item.style.fontInternal;
|
||||||
|
const color = item.style.color;
|
||||||
|
const is = fromFontIconCode(fontIconCode, font, color);
|
||||||
|
|
||||||
|
if (is && is.ios) {
|
||||||
|
img = is.ios;
|
||||||
|
} else {
|
||||||
|
traceMissingIcon(item.icon);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
img = loadActionIconFromFileOrResource(item.icon);
|
||||||
|
}
|
||||||
|
|
||||||
const image = img.imageWithRenderingMode(this._getIconRenderingMode());
|
const image = img.imageWithRenderingMode(this._getIconRenderingMode());
|
||||||
barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(image, UIBarButtonItemStyle.Plain, tapHandler, "tap");
|
barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(image, UIBarButtonItemStyle.Plain, tapHandler, "tap");
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,8 +10,8 @@ import { Font } from "../styling/font";
|
|||||||
import { getTransformedText } from "../text-base";
|
import { getTransformedText } from "../text-base";
|
||||||
import { CSSType, Color } from "../core/view";
|
import { CSSType, Color } from "../core/view";
|
||||||
import { Frame, View } from "../frame";
|
import { Frame, View } from "../frame";
|
||||||
import { RESOURCE_PREFIX, ad, layout } from "../../utils/utils";
|
import { RESOURCE_PREFIX, ad, layout, isFontIconURI } from "../../utils/utils";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||||
import * as application from "../../application";
|
import * as application from "../../application";
|
||||||
|
|
||||||
// TODO: Impl trace
|
// TODO: Impl trace
|
||||||
@ -177,7 +177,16 @@ function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets
|
|||||||
// traceMissingIcon(iconSource);
|
// traceMissingIcon(iconSource);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const is = fromFileOrResource(tabStripItem.iconSource);
|
let is = new ImageSource();
|
||||||
|
if (isFontIconURI(tabStripItem.iconSource)) {
|
||||||
|
const fontIconCode = tabStripItem.iconSource.split("//")[1];
|
||||||
|
const font = tabStripItem.style.fontInternal;
|
||||||
|
const color = tabStripItem.style.color;
|
||||||
|
is = fromFontIconCode(fontIconCode, font, color);
|
||||||
|
} else {
|
||||||
|
is = fromFileOrResource(tabStripItem.iconSource);
|
||||||
|
}
|
||||||
|
|
||||||
if (is) {
|
if (is) {
|
||||||
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
|
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
|
||||||
// tslint:disable-next-line:deprecation
|
// tslint:disable-next-line:deprecation
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Types
|
// Types
|
||||||
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
|
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
|
||||||
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
||||||
import { TextTransform } from "../text-base";
|
import { TextTransform } from "../text-base";
|
||||||
@ -9,10 +9,10 @@ import { Font } from "../styling/font";
|
|||||||
import { getTransformedText } from "../text-base";
|
import { getTransformedText } from "../text-base";
|
||||||
import { Frame } from "../frame";
|
import { Frame } from "../frame";
|
||||||
import { ios as iosView, View, CSSType } from "../core/view";
|
import { ios as iosView, View, CSSType } from "../core/view";
|
||||||
import { ios as iosUtils, layout } from "../../utils/utils";
|
import { ios as iosUtils, layout, isFontIconURI } from "../../utils/utils";
|
||||||
import { device } from "../../platform";
|
import { device } from "../../platform";
|
||||||
import { Color } from "../../color";
|
import { Color } from "../../color";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||||
// TODO:
|
// TODO:
|
||||||
// import { profile } from "../../profiling";
|
// import { profile } from "../../profiling";
|
||||||
|
|
||||||
@ -526,9 +526,7 @@ export class BottomNavigation extends TabNavigationBase {
|
|||||||
let image: UIImage;
|
let image: UIImage;
|
||||||
let title: string;
|
let title: string;
|
||||||
|
|
||||||
// Image and Label children of TabStripItem
|
image = this._getIcon(item);
|
||||||
// take priority over its `iconSource` and `title` properties
|
|
||||||
image = item.image ? this._getIcon(item.image.src) : this._getIcon(item.iconSource);
|
|
||||||
title = item.label ? item.label.text : item.title;
|
title = item.label ? item.label.text : item.title;
|
||||||
|
|
||||||
const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index);
|
const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index);
|
||||||
@ -540,14 +538,26 @@ export class BottomNavigation extends TabNavigationBase {
|
|||||||
return UIImageRenderingMode.AlwaysOriginal;
|
return UIImageRenderingMode.AlwaysOriginal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public _getIcon(iconSource: string): UIImage {
|
public _getIcon(tabStripItem: TabStripItem): UIImage {
|
||||||
|
// Image and Label children of TabStripItem
|
||||||
|
// take priority over its `iconSource` and `title` properties
|
||||||
|
const iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource;
|
||||||
if (!iconSource) {
|
if (!iconSource) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let image: UIImage = this._iconsCache[iconSource];
|
let image: UIImage = this._iconsCache[iconSource];
|
||||||
if (!image) {
|
if (!image) {
|
||||||
const is = fromFileOrResource(iconSource);
|
let is = new ImageSource;
|
||||||
|
if (isFontIconURI(iconSource)) {
|
||||||
|
const fontIconCode = iconSource.split("//")[1];
|
||||||
|
const font = tabStripItem.style.fontInternal;
|
||||||
|
const color = tabStripItem.style.color;
|
||||||
|
is = fromFontIconCode(fontIconCode, font, color);
|
||||||
|
} else {
|
||||||
|
is = fromFileOrResource(iconSource);
|
||||||
|
}
|
||||||
|
|
||||||
if (is && is.ios) {
|
if (is && is.ios) {
|
||||||
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
||||||
this._iconsCache[iconSource] = originalRenderedImage;
|
this._iconsCache[iconSource] = originalRenderedImage;
|
||||||
|
@ -2,9 +2,9 @@ import { Image as ImageDefinition, Stretch } from ".";
|
|||||||
import { View, Property, InheritedCssProperty, Length, Style, Color, isIOS, booleanConverter, CSSType, traceEnabled, traceWrite, traceCategories } from "../core/view";
|
import { View, Property, InheritedCssProperty, Length, Style, Color, isIOS, booleanConverter, CSSType, traceEnabled, traceWrite, traceCategories } from "../core/view";
|
||||||
import { ImageAsset } from "../../image-asset";
|
import { ImageAsset } from "../../image-asset";
|
||||||
import { ImageSource, fromAsset, fromNativeSource, fromUrl } from "../../image-source";
|
import { ImageSource, fromAsset, fromNativeSource, fromUrl } from "../../image-source";
|
||||||
import { isDataURI, isFileOrResourcePath, RESOURCE_PREFIX } from "../../utils/utils";
|
import { isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX } from "../../utils/utils";
|
||||||
export * from "../core/view";
|
export * from "../core/view";
|
||||||
export { ImageSource, ImageAsset, fromAsset, fromNativeSource, fromUrl, isDataURI, isFileOrResourcePath, RESOURCE_PREFIX };
|
export { ImageSource, ImageAsset, fromAsset, fromNativeSource, fromUrl, isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX };
|
||||||
|
|
||||||
@CSSType("Image")
|
@CSSType("Image")
|
||||||
export abstract class ImageBase extends View implements ImageDefinition {
|
export abstract class ImageBase extends View implements ImageDefinition {
|
||||||
@ -46,7 +46,16 @@ export abstract class ImageBase extends View implements ImageDefinition {
|
|||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isDataURI(value)) {
|
if (isFontIconURI(value)) {
|
||||||
|
const fontIconCode = value.split("//")[1];
|
||||||
|
if (fontIconCode !== undefined) {
|
||||||
|
// support sync mode only
|
||||||
|
const font = this.style.fontInternal;
|
||||||
|
const color = this.style.color;
|
||||||
|
source.loadFromFontIconCode(fontIconCode, font, color);
|
||||||
|
imageLoaded();
|
||||||
|
}
|
||||||
|
} else if (isDataURI(value)) {
|
||||||
const base64Data = value.split(",")[1];
|
const base64Data = value.split(",")[1];
|
||||||
if (base64Data !== undefined) {
|
if (base64Data !== undefined) {
|
||||||
if (sync) {
|
if (sync) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ImageSource, ImageAsset, ImageBase, stretchProperty, imageSourceProperty, srcProperty, tintColorProperty, Color,
|
ImageSource, ImageAsset, ImageBase, stretchProperty, imageSourceProperty, srcProperty, tintColorProperty, Color,
|
||||||
isDataURI, isFileOrResourcePath, RESOURCE_PREFIX, Length
|
isDataURI, isFontIconURI, isFileOrResourcePath, RESOURCE_PREFIX, Length
|
||||||
} from "./image-common";
|
} from "./image-common";
|
||||||
import { knownFolders } from "../../file-system";
|
import { knownFolders } from "../../file-system";
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ export class Image extends ImageBase {
|
|||||||
value = value.trim();
|
value = value.trim();
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
if (isDataURI(value)) {
|
if (isFontIconURI(value) || isDataURI(value)) {
|
||||||
// TODO: Check with runtime what should we do in case of base64 string.
|
// TODO: Check with runtime what should we do in case of base64 string.
|
||||||
super._createImageSourceFromSrc(value);
|
super._createImageSourceFromSrc(value);
|
||||||
} else if (isFileOrResourcePath(value)) {
|
} else if (isFileOrResourcePath(value)) {
|
||||||
|
@ -11,8 +11,8 @@ import { Font } from "../styling/font";
|
|||||||
import { getTransformedText } from "../text-base";
|
import { getTransformedText } from "../text-base";
|
||||||
import { Frame } from "../frame";
|
import { Frame } from "../frame";
|
||||||
import { Color } from "../core/view";
|
import { Color } from "../core/view";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||||
import { RESOURCE_PREFIX, ad, layout } from "../../utils/utils";
|
import { RESOURCE_PREFIX, ad, layout, isFontIconURI } from "../../utils/utils";
|
||||||
import * as application from "../../application";
|
import * as application from "../../application";
|
||||||
|
|
||||||
export * from "./tabs-common";
|
export * from "./tabs-common";
|
||||||
@ -304,7 +304,16 @@ function createTabItemSpec(item: TabStripItem): org.nativescript.widgets.TabItem
|
|||||||
// traceMissingIcon(iconSource);
|
// traceMissingIcon(iconSource);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const is = fromFileOrResource(iconSource);
|
let is = new ImageSource();
|
||||||
|
if (isFontIconURI(item.iconSource)) {
|
||||||
|
const fontIconCode = item.iconSource.split("//")[1];
|
||||||
|
const font = item.style.fontInternal;
|
||||||
|
const color = item.style.color;
|
||||||
|
is = fromFontIconCode(fontIconCode, font, color);
|
||||||
|
} else {
|
||||||
|
is = fromFileOrResource(item.iconSource);
|
||||||
|
}
|
||||||
|
|
||||||
if (is) {
|
if (is) {
|
||||||
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
|
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
|
||||||
tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android);
|
tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android);
|
||||||
|
@ -11,9 +11,9 @@ import { Font } from "../styling/font";
|
|||||||
import { Frame } from "../frame";
|
import { Frame } from "../frame";
|
||||||
import { ios as iosView, View } from "../core/view";
|
import { ios as iosView, View } from "../core/view";
|
||||||
import { Color } from "../../color";
|
import { Color } from "../../color";
|
||||||
import { /*ios as iosUtils,*/ layout } from "../../utils/utils";
|
import { /*ios as iosUtils,*/ layout, isFontIconURI } from "../../utils/utils";
|
||||||
// import { device } from "../../platform";
|
// import { device } from "../../platform";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// import { profile } from "../../profiling";
|
// import { profile } from "../../profiling";
|
||||||
@ -883,9 +883,7 @@ export class Tabs extends TabsBase {
|
|||||||
let image: UIImage;
|
let image: UIImage;
|
||||||
let title: string;
|
let title: string;
|
||||||
|
|
||||||
// Image and Label children of TabStripItem
|
image = this._getIcon(item);
|
||||||
// take priority over its `iconSource` and `title` properties
|
|
||||||
image = item.image ? this._getIcon(item.image.src) : this._getIcon(item.iconSource);
|
|
||||||
title = item.label ? item.label.text : item.title;
|
title = item.label ? item.label.text : item.title;
|
||||||
|
|
||||||
if (!this.tabStrip._hasImage) {
|
if (!this.tabStrip._hasImage) {
|
||||||
@ -918,14 +916,26 @@ export class Tabs extends TabsBase {
|
|||||||
return UIImageRenderingMode.AlwaysOriginal;
|
return UIImageRenderingMode.AlwaysOriginal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public _getIcon(iconSource: string): UIImage {
|
public _getIcon(tabStripItem: TabStripItem): UIImage {
|
||||||
|
// Image and Label children of TabStripItem
|
||||||
|
// take priority over its `iconSource` and `title` properties
|
||||||
|
const iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource;
|
||||||
if (!iconSource) {
|
if (!iconSource) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let image: UIImage = this._iconsCache[iconSource];
|
let image: UIImage = this._iconsCache[iconSource];
|
||||||
if (!image) {
|
if (!image) {
|
||||||
const is = fromFileOrResource(iconSource);
|
let is = new ImageSource;
|
||||||
|
if (isFontIconURI(iconSource)) {
|
||||||
|
const fontIconCode = iconSource.split("//")[1];
|
||||||
|
const font = tabStripItem.style.fontInternal;
|
||||||
|
const color = tabStripItem.style.color;
|
||||||
|
is = fromFontIconCode(fontIconCode, font, color);
|
||||||
|
} else {
|
||||||
|
is = fromFileOrResource(iconSource);
|
||||||
|
}
|
||||||
|
|
||||||
if (is && is.ios) {
|
if (is && is.ios) {
|
||||||
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode());
|
||||||
this._iconsCache[iconSource] = originalRenderedImage;
|
this._iconsCache[iconSource] = originalRenderedImage;
|
||||||
|
@ -113,6 +113,16 @@ export function isFileOrResourcePath(path: string): boolean {
|
|||||||
path.indexOf(RESOURCE_PREFIX) === 0; // resource
|
path.indexOf(RESOURCE_PREFIX) === 0; // resource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFontIconURI(uri: string): boolean {
|
||||||
|
if (!types.isString(uri)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstSegment = uri.trim().split("//")[0];
|
||||||
|
|
||||||
|
return firstSegment && firstSegment.indexOf("font:") === 0;
|
||||||
|
}
|
||||||
|
|
||||||
export function isDataURI(uri: string): boolean {
|
export function isDataURI(uri: string): boolean {
|
||||||
if (!types.isString(uri)) {
|
if (!types.isString(uri)) {
|
||||||
return false;
|
return false;
|
||||||
|
6
tns-core-modules/utils/utils.d.ts
vendored
6
tns-core-modules/utils/utils.d.ts
vendored
@ -278,6 +278,12 @@ export function executeOnMainThread(func: Function);
|
|||||||
*/
|
*/
|
||||||
export function mainThreadify(func: Function): (...args: any[]) => void
|
export function mainThreadify(func: Function): (...args: any[]) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the specified URI is a font icon URI like "fontIcon://".
|
||||||
|
* @param uri The URI.
|
||||||
|
*/
|
||||||
|
export function isFontIconURI(uri: string): boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the specified path points to a resource or local file.
|
* Returns true if the specified path points to a resource or local file.
|
||||||
* @param path The path.
|
* @param path The path.
|
||||||
|
Reference in New Issue
Block a user