diff --git a/tns-core-modules/ui/action-bar/action-bar-common.ts b/tns-core-modules/ui/action-bar/action-bar-common.ts index 79d011de8..4aef3073a 100644 --- a/tns-core-modules/ui/action-bar/action-bar-common.ts +++ b/tns-core-modules/ui/action-bar/action-bar-common.ts @@ -9,7 +9,13 @@ import { profile } from "../../profiling"; export * from "../core/view"; -import { View, ViewBase, Property, unsetValue, booleanConverter, horizontalAlignmentProperty, verticalAlignmentProperty, CSSType } from "../core/view"; +import { + View, ViewBase, Property, + unsetValue, booleanConverter, + horizontalAlignmentProperty, + verticalAlignmentProperty, CSSType, + traceWrite, traceCategories, traceMessageType +} from "../core/view"; export module knownCollections { export var actionItems = "actionItems"; @@ -334,6 +340,12 @@ function onVisibilityChanged(item: ActionItemBase, oldValue: string, newValue: s item._onVisibilityChanged(newValue); } +export function traceMissingIcon(icon: string) { + traceWrite("Could not load action bar icon: " + icon, + traceCategories.Error, + traceMessageType.error); +} + export const textProperty = new Property({ name: "text", defaultValue: "", valueChanged: onItemChanged }); textProperty.register(ActionItemBase); diff --git a/tns-core-modules/ui/action-bar/action-bar.android.ts b/tns-core-modules/ui/action-bar/action-bar.android.ts index c8e435c12..065964ec5 100644 --- a/tns-core-modules/ui/action-bar/action-bar.android.ts +++ b/tns-core-modules/ui/action-bar/action-bar.android.ts @@ -1,5 +1,9 @@ import { AndroidActionBarSettings as AndroidActionBarSettingsDefinition, AndroidActionItemSettings } from "."; -import { ActionItemBase, ActionBarBase, isVisible, View, layout, colorProperty, flatProperty, Color } from "./action-bar-common"; +import { + ActionItemBase, ActionBarBase, isVisible, + View, layout, colorProperty, flatProperty, + Color, traceMissingIcon +} from "./action-bar-common"; import { RESOURCE_PREFIX } from "../../utils/utils"; import { fromFileOrResource } from "../../image-source"; import * as application from "../../application"; @@ -18,7 +22,7 @@ function generateItemId(): number { } interface MenuItemClickListener { - new (owner: ActionBar): android.support.v7.widget.Toolbar.OnMenuItemClickListener; + new(owner: ActionBar): android.support.v7.widget.Toolbar.OnMenuItemClickListener; } let appResources: android.content.res.Resources; @@ -219,7 +223,9 @@ export class ActionBar extends ActionBarBase { } else if (navButton.icon) { let drawableOrId = getDrawableOrResourceId(navButton.icon, appResources); - this.nativeViewProtected.setNavigationIcon(drawableOrId); + if (drawableOrId) { + this.nativeViewProtected.setNavigationIcon(drawableOrId); + } } // Set navigation content descripion, used by screen readers for the vision-impaired users @@ -304,9 +310,6 @@ export class ActionBar extends ActionBarBase { if (drawableOrId) { menuItem.setIcon(drawableOrId); } - else { - throw new Error("Error loading icon from " + item.icon); - } } let showAsAction = getShowAsAction(item); @@ -422,10 +425,11 @@ function getDrawableOrResourceId(icon: string, resources: android.content.res.Re return undefined; } + let result = undefined; if (icon.indexOf(RESOURCE_PREFIX) === 0) { let resourceId: number = resources.getIdentifier(icon.substr(RESOURCE_PREFIX.length), "drawable", application.android.packageName); if (resourceId > 0) { - return resourceId; + result = resourceId; } } else { @@ -436,10 +440,14 @@ function getDrawableOrResourceId(icon: string, resources: android.content.res.Re drawable = new android.graphics.drawable.BitmapDrawable(is.android); } - return drawable; + result = drawable; } - return undefined; + if (!result) { + traceMissingIcon(icon); + } + + return result; } function getShowAsAction(menuItem: ActionItem): number { diff --git a/tns-core-modules/ui/action-bar/action-bar.ios.ts b/tns-core-modules/ui/action-bar/action-bar.ios.ts index bc33b1755..b95b57301 100644 --- a/tns-core-modules/ui/action-bar/action-bar.ios.ts +++ b/tns-core-modules/ui/action-bar/action-bar.ios.ts @@ -1,13 +1,28 @@ import { IOSActionItemSettings, ActionItem as ActionItemDefinition } from "."; -import { ActionItemBase, ActionBarBase, isVisible, View, colorProperty, backgroundColorProperty, backgroundInternalProperty, flatProperty, layout, Color } from "./action-bar-common"; -import { ImageSource, fromFileOrResource } from "../../image-source"; +import { + ActionItemBase, ActionBarBase, isVisible, View, + colorProperty, backgroundColorProperty, + backgroundInternalProperty, flatProperty, + layout, Color, traceMissingIcon } from "./action-bar-common"; +import { fromFileOrResource } from "../../image-source"; import { ios as iosUtils } from "../../utils/utils"; +import { write as traceWrite, categories, messageType } from "../../trace"; export * from "./action-bar-common"; const majorVersion = iosUtils.MajorVersion; const UNSPECIFIED = layout.makeMeasureSpec(0, layout.UNSPECIFIED); +function loadActionIconFromFileOrResource(icon: string): UIImage { + const img = fromFileOrResource(icon); + if (img && img.ios) { + return img.ios; + } else { + traceMissingIcon(icon); + return null; + } +} + class TapBarItemHandlerImpl extends NSObject { private _owner: WeakRef; @@ -151,16 +166,16 @@ export class ActionBar extends ActionBarBase { } // Set back button image - let img: ImageSource; + let img: UIImage; if (this.navigationButton && isVisible(this.navigationButton) && this.navigationButton.icon) { - img = fromFileOrResource(this.navigationButton.icon); + img = loadActionIconFromFileOrResource(this.navigationButton.icon); } // TODO: This could cause issue when canceling BackEdge gesture - we will change the backIndicator to // show the one from the old page but the new page will still be visible (because we canceled EdgeBackSwipe gesutre) // Consider moving this to new method and call it from - navigationControllerDidShowViewControllerAnimated. - if (img && img.ios) { - let image = img.ios.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal); + if (img) { + let image = img.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal); navigationBar.backIndicatorImage = image; navigationBar.backIndicatorTransitionMaskImage = image; } else { @@ -226,12 +241,8 @@ export class ActionBar extends ActionBarBase { barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(id, tapHandler, "tap"); } else if (item.icon) { - const img = fromFileOrResource(item.icon); - if (img && img.ios) { - barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(img.ios, UIBarButtonItemStyle.Plain, tapHandler, "tap"); - } else { - throw new Error("Error loading icon from " + item.icon); - } + const img = loadActionIconFromFileOrResource(item.icon); + barButtonItem = UIBarButtonItem.alloc().initWithImageStyleTargetAction(img, UIBarButtonItemStyle.Plain, tapHandler, "tap"); } else { barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(item.text + "", UIBarButtonItemStyle.Plain, tapHandler, "tap"); } diff --git a/tns-core-modules/ui/tab-view/tab-view-common.ts b/tns-core-modules/ui/tab-view/tab-view-common.ts index b8a1251ed..53eacbad9 100644 --- a/tns-core-modules/ui/tab-view/tab-view-common.ts +++ b/tns-core-modules/ui/tab-view/tab-view-common.ts @@ -1,7 +1,8 @@ import { TabView as TabViewDefinition, TabViewItem as TabViewItemDefinition, SelectedIndexChangedEventData } from "."; import { View, ViewBase, Style, Property, CssProperty, CoercibleProperty, - Color, isIOS, AddArrayFromBuilder, AddChildFromBuilder, EventData, CSSType + Color, isIOS, AddArrayFromBuilder, AddChildFromBuilder, EventData, CSSType, + traceWrite, traceCategories, traceMessageType } from "../core/view"; export * from "../core/view"; @@ -203,6 +204,10 @@ export interface TabViewBase { on(event: "selectedIndexChanged", callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); } +export function traceMissingIcon(icon: string) { + traceWrite("Could not load tab bar icon: " + icon, traceCategories.Error, traceMessageType.error); +} + export const selectedIndexProperty = new CoercibleProperty({ name: "selectedIndex", defaultValue: -1, affectsLayout: isIOS, valueChanged: (target, oldValue, newValue) => { diff --git a/tns-core-modules/ui/tab-view/tab-view.android.ts b/tns-core-modules/ui/tab-view/tab-view.android.ts index 91bf8c989..f12e115ac 100644 --- a/tns-core-modules/ui/tab-view/tab-view.android.ts +++ b/tns-core-modules/ui/tab-view/tab-view.android.ts @@ -6,7 +6,7 @@ import { tabTextColorProperty, tabBackgroundColorProperty, tabTextFontSizeProperty, selectedTabTextColorProperty, androidSelectedTabHighlightColorProperty, androidOffscreenTabLimitProperty, fontSizeProperty, fontInternalProperty, layout, traceCategory, traceEnabled, - traceWrite, Color + traceWrite, Color, traceMissingIcon } from "./tab-view-common" import { textTransformProperty, TextTransform, getTransformedText } from "../text-base"; import { fromFileOrResource } from "../../image-source"; @@ -233,11 +233,16 @@ function createTabItemSpec(item: TabViewItem): org.nativescript.widgets.TabItemS if (item.iconSource) { if (item.iconSource.indexOf(RESOURCE_PREFIX) === 0) { result.iconId = ad.resources.getDrawableId(item.iconSource.substr(RESOURCE_PREFIX.length)); + if (result.iconId === 0) { + traceMissingIcon(item.iconSource); + } } else { const is = fromFileOrResource(item.iconSource); if (is) { // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. result.iconDrawable = new android.graphics.drawable.BitmapDrawable(is.android); + } else { + traceMissingIcon(item.iconSource); } } } diff --git a/tns-core-modules/ui/tab-view/tab-view.ios.ts b/tns-core-modules/ui/tab-view/tab-view.ios.ts index 49c02f946..a7baebce1 100644 --- a/tns-core-modules/ui/tab-view/tab-view.ios.ts +++ b/tns-core-modules/ui/tab-view/tab-view.ios.ts @@ -5,7 +5,7 @@ import { ios as iosView, ViewBase } from "../core/view"; import { TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty, tabTextColorProperty, tabTextFontSizeProperty, tabBackgroundColorProperty, selectedTabTextColorProperty, iosIconRenderingModeProperty, - View, fontInternalProperty, layout, traceEnabled, traceWrite, traceCategories, Color + View, fontInternalProperty, layout, traceEnabled, traceWrite, traceCategories, Color, traceMissingIcon } from "./tab-view-common" import { textTransformProperty, TextTransform, getTransformedText } from "../text-base"; import { fromFileOrResource } from "../../image-source"; @@ -451,6 +451,8 @@ export class TabView extends TabViewBase { const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode()); this._iconsCache[iconSource] = originalRenderedImage; image = originalRenderedImage; + } else { + traceMissingIcon(iconSource); } }