From 2c886cb783e22e422da1861cda85f78116e8750d Mon Sep 17 00:00:00 2001 From: Vladimir Enchev Date: Wed, 22 Jul 2015 11:02:31 +0300 Subject: [PATCH] Common UI module implemented & used in cuteness.io --- CrossPlatformModules.csproj | 3 + apps/cuteness.io/details-page.ts | 8 +-- apps/cuteness.io/main-page.ts | 25 ++++---- apps/cuteness.io/reddit-app-view-model.ts | 66 ++++++++++------------ apps/cuteness.io/reddit-item-view-model.ts | 46 +++++++-------- ui/package.json | 2 + ui/ui.d.ts | 56 ++++++++++++++++++ ui/ui.ts | 51 +++++++++++++++++ 8 files changed, 181 insertions(+), 76 deletions(-) create mode 100644 ui/package.json create mode 100644 ui/ui.d.ts create mode 100644 ui/ui.ts diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj index eee46e931..403ce38ef 100644 --- a/CrossPlatformModules.csproj +++ b/CrossPlatformModules.csproj @@ -473,6 +473,7 @@ action-bar.d.ts + @@ -688,6 +689,7 @@ text-field.d.ts + @@ -1746,6 +1748,7 @@ PreserveNewest + diff --git a/apps/cuteness.io/details-page.ts b/apps/cuteness.io/details-page.ts index 0e71a4e76..6955f1394 100644 --- a/apps/cuteness.io/details-page.ts +++ b/apps/cuteness.io/details-page.ts @@ -1,10 +1,10 @@ -import pages = require("ui/page"); -import observable = require("data/observable"); +import {Page} from "ui"; +import {EventData as ObservableEventData} from "data/observable"; // Event handler for Page "navigatedTo" event attached in details-page.xml -export function pageNavigatedTo(args: observable.EventData) { +export function pageNavigatedTo(args: ObservableEventData) { // Get the event sender - var page = args.object; + var page = args.object; page.bindingContext = page.navigationContext; } diff --git a/apps/cuteness.io/main-page.ts b/apps/cuteness.io/main-page.ts index ea33764a7..c2690badf 100644 --- a/apps/cuteness.io/main-page.ts +++ b/apps/cuteness.io/main-page.ts @@ -1,34 +1,31 @@ -import observable = require("data/observable"); -import pages = require("ui/page"); -import frames = require("ui/frame"); -import listView = require("ui/list-view"); +import {EventData as ObservableEventData} from "data/observable"; +import {Page, ItemEventData, topmost as topmostFrame, ItemEventData as ListViewItemEventData} from "ui"; +import {AppViewModel} from "./reddit-app-view-model"; -import redditAppViewModel = require("./reddit-app-view-model"); - -var appViewModel = new redditAppViewModel.AppViewModel(); +var appViewModel = new AppViewModel(); // Event handler for Page "loaded" event attached in main-page.xml -export function pageLoaded(args: observable.EventData) { +export function pageLoaded(args: ObservableEventData) { // Get the event sender - var page = args.object; + var page = args.object; page.bindingContext = appViewModel; // Enable platform specific feature (in this case Android page caching) - if (frames.topmost().android) { - frames.topmost().android.cachePagesOnNavigate = true; + if (topmostFrame().android) { + topmostFrame().android.cachePagesOnNavigate = true; } } -export function listViewItemTap(args: listView.ItemEventData) { +export function listViewItemTap(args: ListViewItemEventData) { // Navigate to the details page with context set to the data item for specified index - frames.topmost().navigate({ + topmostFrame().navigate({ moduleName: "./details-page", context: appViewModel.redditItems.getItem(args.index) }); } -export function listViewLoadMoreItems(args: observable.EventData) { +export function listViewLoadMoreItems(args: ObservableEventData) { // Increase model items length with model items loadSize property value appViewModel.redditItems.length += appViewModel.redditItems.loadSize; } diff --git a/apps/cuteness.io/reddit-app-view-model.ts b/apps/cuteness.io/reddit-app-view-model.ts index 0d9db30b8..7a9cd7c5f 100644 --- a/apps/cuteness.io/reddit-app-view-model.ts +++ b/apps/cuteness.io/reddit-app-view-model.ts @@ -1,53 +1,49 @@ -import imageSource = require("image-source"); -import virtualArray = require("data/virtual-array"); -import http = require("http"); -import observable = require("data/observable"); -import imageCache = require("ui/image-cache"); +import {ImageSource, fromFile as imageSourceFromFile} from "image-source"; +import {VirtualArray, ItemsLoading as virtualArrayItemsLoadingData} from "data/virtual-array"; +import {Observable} from "data/observable"; +import {Cache as ImageCache} from "ui/image-cache"; -import redditModel = require("./reddit-model"); -import redditViewModel = require("./reddit-item-view-model"); +import {Data as RedditData} from "./reddit-model"; +import {RedditViewModel} from "./reddit-item-view-model"; var aboutText = "Cuteness is a proof of concept app demonstrating the Telerik's NativeScript for writing native mobile applications using JavaScript."; -export var defaultThumbnailImageSource = imageSource.fromFile("~/res/reddit-logo.png"); -export var defaultNoThumbnailImageSource = imageSource.fromFile("~/res/no-image.png"); +export var defaultThumbnailImageSource = imageSourceFromFile("~/res/reddit-logo.png"); +export var defaultNoThumbnailImageSource = imageSourceFromFile("~/res/no-image.png"); var redditUrl = "http://www.reddit.com/r/aww.json?limit="; var after: string; var ISSCROLLING = "isLoading"; // initialize the image cache for the main list -export var cache = new imageCache.Cache(); +export var cache = new ImageCache(); cache.placeholder = defaultThumbnailImageSource; cache.maxRequests = 5; -export class AppViewModel extends observable.Observable { +export class AppViewModel extends Observable { - private _redditItems: virtualArray.VirtualArray; - get redditItems(): virtualArray.VirtualArray { + private _redditItems: VirtualArray; + get redditItems(): VirtualArray { if (!this._redditItems) { - this._redditItems = new virtualArray.VirtualArray(1000); + this._redditItems = new VirtualArray(1000); this._redditItems.loadSize = 50; - this._redditItems.on(virtualArray.VirtualArray.itemsLoadingEvent, (args: virtualArray.ItemsLoading) => { + this._redditItems.on(VirtualArray.itemsLoadingEvent, (args: virtualArrayItemsLoadingData) => { - http.getJSON(redditUrl + args.count + - (after ? "&after=" + after : "")).then(result => { + fetch(redditUrl + args.count + (after ? "&after=" + after : "")).then(response=> response.json()).then(result => { - var itemsToLoad = result.data.children.map(i=> { - return new redditViewModel.RedditViewModel(i.data); - }); - - this._redditItems.load(args.index, itemsToLoad); - - var lastItem = itemsToLoad[itemsToLoad.length - 1]; - if (lastItem) { - after = itemsToLoad[itemsToLoad.length - 1].source.name; - } - - }, (e) => { console.log(e.message) }) - .catch(function(e) { - setTimeout(function() { throw e; }); + var itemsToLoad = result.data.children.map(i=> { + return new RedditViewModel(i.data); }); -; + + this._redditItems.load(args.index, itemsToLoad); + + var lastItem = itemsToLoad[itemsToLoad.length - 1]; + if (lastItem) { + after = itemsToLoad[itemsToLoad.length - 1].source.name; + } + + }).catch(e => { + setTimeout(() => { throw e; }); + }); }); } @@ -69,7 +65,7 @@ export class AppViewModel extends observable.Observable { cache.enableDownload(); } - this.notify({ object: this, eventName: observable.Observable.propertyChangeEvent, propertyName: ISSCROLLING, value: value }); + this.notify({ object: this, eventName: Observable.propertyChangeEvent, propertyName: ISSCROLLING, value: value }); } } @@ -77,11 +73,11 @@ export class AppViewModel extends observable.Observable { return aboutText; } - get defaultThumbnailImageSource(): imageSource.ImageSource { + get defaultThumbnailImageSource(): ImageSource { return defaultThumbnailImageSource; } - get defaultNoThumbnailImageSource(): imageSource.ImageSource { + get defaultNoThumbnailImageSource(): ImageSource { return defaultNoThumbnailImageSource; } } diff --git a/apps/cuteness.io/reddit-item-view-model.ts b/apps/cuteness.io/reddit-item-view-model.ts index d7dc9fca9..8a93b2aef 100644 --- a/apps/cuteness.io/reddit-item-view-model.ts +++ b/apps/cuteness.io/reddit-item-view-model.ts @@ -1,20 +1,20 @@ -import observable = require("data/observable"); -import imageSource = require("image-source"); +import {Observable} from "data/observable"; +import {ImageSource, fromFile as imageSourceFromFile, fromUrl as imageSourceFromUrl} from "image-source"; -import redditModel = require("./reddit-model"); -import redditAppViewModel = require("./reddit-app-view-model"); +import {ItemData} from "./reddit-model"; +import {defaultThumbnailImageSource, defaultNoThumbnailImageSource, cache} from "./reddit-app-view-model"; -var firstThumbnailImageSource = imageSource.fromFile("~/res/first-image.png"); -var defaultImageSource = imageSource.fromFile("~/res/reddit-logo-transparent.png"); +var firstThumbnailImageSource = imageSourceFromFile("~/res/first-image.png"); +var defaultImageSource = imageSourceFromFile("~/res/reddit-logo-transparent.png"); var ISLOADING = "isLoading"; var THUMBNAIL_IMAGE = "thumbnailImage"; var IMAGE_SOURCE = "imageSource"; -export class RedditViewModel extends observable.Observable { +export class RedditViewModel extends Observable { - private _source: redditModel.ItemData; - constructor(source: redditModel.ItemData) { + private _source: ItemData; + constructor(source: ItemData) { super(); this._source = source; @@ -27,7 +27,7 @@ export class RedditViewModel extends observable.Observable { } } - get source(): redditModel.ItemData { + get source(): ItemData { return this._source; } @@ -38,13 +38,13 @@ export class RedditViewModel extends observable.Observable { set isLoading(value: boolean) { if (this._isLoading !== value) { this._isLoading = value; - this.notify({ object: this, eventName: observable.Observable.propertyChangeEvent, propertyName: ISLOADING, value: value }); + this.notify({ object: this, eventName: Observable.propertyChangeEvent, propertyName: ISLOADING, value: value }); } } - get thumbnailImage(): imageSource.ImageSource { + get thumbnailImage(): ImageSource { if (!this._source) { - return redditAppViewModel.defaultThumbnailImageSource; + return defaultThumbnailImageSource; } if (this._source.title === "reddit 101") { @@ -52,32 +52,32 @@ export class RedditViewModel extends observable.Observable { } var url = this._source.thumbnail; - - if (!_isValidImageUrl(url)) { - return redditAppViewModel.defaultNoThumbnailImageSource + + if (!_isValidImageUrl(url)) { + return defaultNoThumbnailImageSource } - var image = redditAppViewModel.cache.get(url); + var image = cache.get(url); if (image) { return image; } this.isLoading = true; - redditAppViewModel.cache.push({ + cache.push({ key: url, url: url, completed: (image: any, key: string) => { if (url === key) { this.isLoading = false; - this.notify({ object: this, eventName: observable.Observable.propertyChangeEvent, propertyName: THUMBNAIL_IMAGE, value: image }); + this.notify({ object: this, eventName: Observable.propertyChangeEvent, propertyName: THUMBNAIL_IMAGE, value: image }); } } }); - return redditAppViewModel.defaultThumbnailImageSource; + return defaultThumbnailImageSource; } - get imageSource(): imageSource.ImageSource { + get imageSource(): ImageSource { if (this._source) { var url; try { @@ -91,9 +91,9 @@ export class RedditViewModel extends observable.Observable { this.isLoading = true; - imageSource.fromUrl(url).then(result => { + imageSourceFromUrl(url).then(result => { this.isLoading = false; - this.notify({ object: this, eventName: observable.Observable.propertyChangeEvent, propertyName: IMAGE_SOURCE, value: result }); + this.notify({ object: this, eventName: Observable.propertyChangeEvent, propertyName: IMAGE_SOURCE, value: result }); }); } } diff --git a/ui/package.json b/ui/package.json new file mode 100644 index 000000000..428789088 --- /dev/null +++ b/ui/package.json @@ -0,0 +1,2 @@ +{ "name" : "ui", + "main" : "ui.js" } \ No newline at end of file diff --git a/ui/ui.d.ts b/ui/ui.d.ts new file mode 100644 index 000000000..2e2ef2d6c --- /dev/null +++ b/ui/ui.d.ts @@ -0,0 +1,56 @@ +/** + * Contains the all UI classes. + */ +declare module "ui" { + export * from "ui/action-bar"; + export * from "ui/activity-indicator"; + export * from "ui/builder"; + export * from "ui/button"; + export * from "ui/content-view"; + export * from "ui/core/bindable"; + export * from "ui/core/control-state-change"; + export * from "ui/core/dependency-observable"; + export * from "ui/core/proxy"; + export * from "ui/core/view"; + export * from "ui/core/weak-event-listener"; + export * from "ui/dialogs"; + export * from "ui/date-picker"; + export * from "ui/editable-text-base"; + export * from "ui/enums"; + export * from "ui/frame"; + export * from "ui/gestures"; + export * from "ui/html-view"; + export * from "ui/image"; + export * from "ui/image-cache"; + export * from "ui/label"; + export * from "ui/layouts/layout"; + export * from "ui/layouts/absolute-layout"; + export * from "ui/layouts/dock-layout"; + export * from "ui/layouts/grid-layout"; + export * from "ui/layouts/stack-layout"; + export * from "ui/layouts/wrap-layout"; + export * from "ui/list-picker"; + export * from "ui/list-view"; + export * from "ui/page"; + export * from "ui/placeholder"; + export * from "ui/progress"; + export * from "ui/repeater"; + export * from "ui/scroll-view"; + export * from "ui/search-bar"; + export * from "ui/segmented-bar"; + export * from "ui/slider"; + export * from "ui/styling"; + export * from "ui/styling/background"; + export * from "ui/styling/css-selector"; + export * from "ui/styling/font"; + export * from "ui/styling/style-property"; + export * from "ui/styling/stylers"; + export * from "ui/styling/visual-state-constants"; + export * from "ui/switch"; + export * from "ui/tab-view"; + export * from "ui/text-base"; + export * from "ui/text-field"; + export * from "ui/text-view"; + export * from "ui/time-picker"; + export * from "ui/web-view"; +} \ No newline at end of file diff --git a/ui/ui.ts b/ui/ui.ts new file mode 100644 index 000000000..4424c361d --- /dev/null +++ b/ui/ui.ts @@ -0,0 +1,51 @@ +export * from "ui/action-bar"; +export * from "ui/activity-indicator"; +export * from "ui/builder"; +export * from "ui/button"; +export * from "ui/content-view"; +export * from "ui/core/bindable"; +export * from "ui/core/control-state-change"; +export * from "ui/core/dependency-observable"; +export * from "ui/core/proxy"; +export * from "ui/core/view"; +export * from "ui/core/weak-event-listener"; +export * from "ui/dialogs"; +export * from "ui/date-picker"; +export * from "ui/editable-text-base"; +export * from "ui/enums"; +export * from "ui/frame"; +export * from "ui/gestures"; +export * from "ui/html-view"; +export * from "ui/image"; +export * from "ui/image-cache"; +export * from "ui/label"; +export * from "ui/layouts/layout"; +export * from "ui/layouts/absolute-layout"; +export * from "ui/layouts/dock-layout"; +export * from "ui/layouts/grid-layout"; +export * from "ui/layouts/stack-layout"; +export * from "ui/layouts/wrap-layout"; +export * from "ui/list-picker"; +export * from "ui/list-view"; +export * from "ui/page"; +export * from "ui/placeholder"; +export * from "ui/progress"; +export * from "ui/repeater"; +export * from "ui/scroll-view"; +export * from "ui/search-bar"; +export * from "ui/segmented-bar"; +export * from "ui/slider"; +export * from "ui/styling"; +export * from "ui/styling/background"; +export * from "ui/styling/css-selector"; +export * from "ui/styling/font"; +export * from "ui/styling/style-property"; +export * from "ui/styling/stylers"; +export * from "ui/styling/visual-state-constants"; +export * from "ui/switch"; +export * from "ui/tab-view"; +export * from "ui/text-base"; +export * from "ui/text-field"; +export * from "ui/text-view"; +export * from "ui/time-picker"; +export * from "ui/web-view";