Permalink
Browse files

sample(android): add APIs

  • Loading branch information...
1 parent f0314a7 commit a289840d874f4f7003e17e69917a91bd36b014c4 @mlaval mlaval committed with mlaval Jan 21, 2016
Showing with 293 additions and 39 deletions.
  1. +21 −1 gulpfile.js
  2. +69 −0 notes.md
  3. +131 −0 sample/apis.ts
  4. +1 −1 sample/hello.ts
  5. +33 −6 sample/kitchensink.android.ts
  6. +16 −1 sample/todomvc.ts
  7. +2 −2 sample/widgets.ts
  8. +16 −3 src/bootstrap.ts
  9. +4 −25 src/wrapper_impl.ts
View
@@ -38,10 +38,17 @@ gulp.task('clean', function (done) {
gulp.task('!create', ['clean'], function(done) {
executeInAppDir('react-native init ' + APP_NAME, done, true);
});
-gulp.task('init', ['!create'], function() {
+gulp.task('!postcreate', function() {
+ return gulp.src(PATHS.app + '/' + APP_NAME + '/android/app/src/main/AndroidManifest.xml')
+ .pipe(transformAndroidManifest())
+ .pipe(gulp.dest(PATHS.app + '/' + APP_NAME + '/android/app/src/main/'));
+
+});
+gulp.task('init', ['!postcreate'], function() {
return gulp.src(PATHS.modules, { base: './node_modules/' }).pipe(gulp.dest(PATHS.app + '/' + APP_NAME + '/node_modules'));
});
+
gulp.task('!assets', function () {
return gulp.src(PATHS.sources.sampleAssets).pipe(gulp.dest(PATHS.app + '/' + APP_NAME));
});
@@ -206,3 +213,16 @@ function transformCommonJSTests() {
done();
});
}
+
+function transformAndroidManifest() {
+ return through2.obj(function (file, encoding, done) {
+ var content = String(file.contents);
+ content = content.replace('<uses-permission android:name="android.permission.INTERNET" />',
+ `<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />`);
+ file.contents = new Buffer(content);
+ this.push(file);
+ done();
+ });
+}
View
@@ -0,0 +1,69 @@
+### Todo
+- Http
+- Router
+- query selector on nodes
+- measure & measureLayout on Nodes
+- Refactor source
+- Clarify the needed polyfill and remove es6-shim if possible
+- High-level Components
+- Mac
+- iOS
+- documentation
+- typings
+- testability (unit & e2e tests)
+
+### APIs
+
+Info APIs (see details at https://facebook.github.io/react-native/docs ):
+ Platform -> Object {OS: "android", Version: 22}
+ NetInfo
+ PixelRatio
+
+Useful APIs:
+ Alert
+ AsyncStorage
+ BackAndroid
+ Clipboard
+ GeoLocation
+ IntentAndroid
+ ToastAndroid
+ StyleSheet
+
+ CameraRoll
+
+
+Animation APIs:
+ Animated
+ Dimensions
+ InteractionManager
+ LayoutAnimation
+
+iOS APIs:
+ ActionSheetIOS
+ AdSupportIOS
+ AlertIOS
+ AppStateIOS
+ ImagePickerIOS
+ LinkingIOS
+ PushNotificationIOS
+ Settings
+ StatusBarIOS
+ VibrationIOS
+
+Low level APIs:
+ NativeMethodsMixin: to be done in Node
+ PanResponder: gestures already done with hammer.js
+ AppRegistry: for renderer only
+ UIManager: for renderer only
+ Dimensions: ???
+
+### Misc
+
+At run time:
+```
+ NativeModules.UIManager.RCTText.NativeProps =
+ {"opacity":"number","renderToHardwareTextureAndroid":"boolean","numberOfLines":"number","borderBottomWidth":"number","scaleY":"number","position":"String","paddingTop":"number","borderWidth":"number","color":"number","marginLeft":"number","fontFamily":"String","marginHorizontal":"number","fontStyle":"String","paddingBottom":"number","paddingHorizontal":"number","scaleX":"number","onLayout":"boolean","flexWrap":"String","borderTopWidth":"number","borderRightWidth":"number","marginTop":"number","translateX":"number","rotation":"number","accessibilityLiveRegion":"String","alignItems":"String","accessibilityComponentType":"String","paddingVertical":"number","flex":"number","marginBottom":"number","bottom":"number","textAlign":"String","justifyContent":"String","fontWeight":"String","padding":"number","alignSelf":"String","backgroundColor":"number","right":"number","borderLeftWidth":"number","height":"number","left":"number","translateY":"number","paddingRight":"number","lineHeight":"number","flexDirection":"String","importantForAccessibility":"String","marginVertical":"number","fontSize":"number","accessibilityLabel":"String","width":"number","paddingLeft":"number","text":"String","top":"number","margin":"number","decomposedMatrix":"Map","marginRight":"number","testID":"String"}
+```
+
+Style:
+`ReactNativeViewAttributes.RCTView`
View
@@ -0,0 +1,131 @@
+import {Component, ElementRef, NgZone} from 'angular2/core';
+import {StyleSheet, Alert, IntentAndroid, ToastAndroid, Clipboard, Platform, PixelRatio, NetInfo} from 'react-native';
+import {NativeFeedback} from './common';
+
+@Component({
+ selector: 'apis-list',
+ host: {flex: '1'},
+ directives: [NativeFeedback],
+ template: `
+<PagerLayout flex="1" justifyContent="center" alignItems="center" selectedPage="0">
+ <View [style]="styles.container">
+ <Text [style]="styles.title">Actionable</Text>
+ <View [style]="styles.button" nativeFeedback (tap)="showAlert()">
+ <Text [style]="styles.buttonText">Alert</Text>
+ </View>
+ <View [style]="styles.button" nativeFeedback (tap)="showToast()">
+ <Text [style]="styles.buttonText">Toast</Text>
+ </View>
+ <View [style]="styles.button" nativeFeedback (tap)="launchIntent()">
+ <Text [style]="styles.buttonText">Intent</Text>
+ </View>
+ <View [style]="styles.button" nativeFeedback (tap)="setClipboard()">
+ <Text [style]="styles.buttonText">Clipboard</Text>
+ </View>
+ <Text>Current clipboard value: {{clipcoardContent}}</Text>
+ </View>
+ <View [style]="styles.container">
+ <Text [style]="styles.title">Infos</Text>
+ <Text [style]="styles.subtitle">Platform</Text>
+ <Text>{{platform}}</Text>
+ <Text [style]="styles.subtitle">PixelRatio</Text>
+ <Text>{{ratio}}</Text>
+ <Text [style]="styles.subtitle">Geoloation</Text>
+ <Text>{{location}}</Text>
+ <Text [style]="styles.subtitle">NetInfo</Text>
+ <Text>{{connectionType}} connection is {{isConnected ? 'on' : 'off'}} and {{isConnectionExpensive ? 'expensive' : 'not expensive'}}</Text>
+ </View>
+</PagerLayout>
+`
+})
+export class APIsList {
+ styles: any;
+ clipcoardContent: string = '';
+ platform: string = '';
+ ratio: string = '';
+ location: string = 'Fetching ...';
+ connectionType: string = 'Unknown';
+ isConnectionExpensive: boolean = false;
+ isConnected: boolean = false;
+ constructor(private zone: NgZone) {
+ this.styles = this._getStyles();
+ this.platform = `OS: ${Platform.OS}, version: ${Platform.Version}`;
+ this.ratio = PixelRatio.get();
+ Clipboard.getString((content) => this.zone.run(() => this.clipcoardContent = content));
+ navigator.geolocation.getCurrentPosition(
+ (position) => this.zone.run(() => this.location = JSON.stringify(position)),
+ (error) => alert(error.message),
+ {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
+ );
+ NetInfo.fetch().then((reach) => { this.connectionType = reach });
+ NetInfo.isConnectionExpensive((isConnectionExpensive) => { this.isConnectionExpensive = isConnectionExpensive });
+ NetInfo.isConnected.fetch().then((isConnected) => { this.isConnected = isConnected });
+ }
+
+ showAlert() {
+ Alert.alert(
+ 'Alert Title',
+ 'My Alert Msg',
+ [
+ {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
+ {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
+ {text: 'OK', onPress: () => console.log('OK Pressed')},
+ ]
+ );
+ }
+
+ showToast() {
+ ToastAndroid.show('This is a toast with short duration', ToastAndroid.SHORT);
+ }
+
+ launchIntent() {
+ var url = 'https://www.angular.io';
+ IntentAndroid.canOpenURL(url, (supported) => {
+ if (!supported) {
+ console.log('Can\'t handle url: ' + url);
+ } else {
+ IntentAndroid.openURL(url);
+ }
+ });
+ }
+
+ setClipboard() {
+ var newValue = this.clipcoardContent == 'foo' ? 'bar' : 'foo';
+ Clipboard.setString(newValue);
+ Clipboard.getString((content) => this.zone.run(() => this.clipcoardContent = content));
+ }
+
+ _getStyles() {
+ return StyleSheet.create({
+ container: {
+ position: "absolute",
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ backgroundColor: '#F5FCFF'
+ },
+ title: {
+ fontSize: 20,
+ textAlign: 'center',
+ margin: 10,
+ },
+ subtitle: {
+ fontSize: 15,
+ textAlign: 'left',
+ color: '#005eb8'
+ },
+ button: {
+ padding: 10,
+ margin: 20,
+ height: 50,
+ backgroundColor: '#005eb8'
+ },
+ buttonText: {
+ color: '#FFFFFF',
+ textAlign: 'center',
+ fontSize: 20
+ }
+ });
+ }
+}
View
@@ -51,7 +51,7 @@ export class HelloApp {
}
});
}
- handleRefresh(evt) {
+ handleRefresh(evt: any) {
evt.target.setProperty('refreshing', false)
}
}
@@ -1,18 +1,20 @@
import {Component, ElementRef, ViewChild} from 'angular2/core';
import {NgSwitch, NgSwitchWhen} from 'angular2/common';
-import {StyleSheet} from 'react-native';
+import {StyleSheet, BackAndroid, Alert} from 'react-native';
var resolveAssetSource = require('resolveAssetSource');
+
import {HelloApp} from "./hello";
import {TodoMVC} from "./todomvc";
import {GesturesApp} from "./gestures";
-import {ComponentsList} from "./widgets";
+import {WidgetsList} from "./widgets";
import {WebViewApp} from './webview';
+import {APIsList} from "./apis";
import {NativeFeedback} from "./common";
@Component({
selector: 'kitchensink-app',
host: {position: 'absolute', top: '0', left: '0', bottom: '0', right: '0'},
- directives: [NgSwitch, NgSwitchWhen, NativeFeedback, HelloApp, TodoMVC, GesturesApp, ComponentsList, WebViewApp],
+ directives: [NgSwitch, NgSwitchWhen, NativeFeedback, HelloApp, TodoMVC, GesturesApp, WidgetsList, WebViewApp, APIsList],
template: `
<DrawerLayout drawerWidth="300" drawerPosition="8388611" flex="1">
<View position="absolute" top="0" left="0" right="0" bottom="0" collapsable="false">
@@ -21,8 +23,9 @@ import {NativeFeedback} from "./common";
<hello-app *ngSwitchWhen="0"></hello-app>
<todo-mvc *ngSwitchWhen="1"></todo-mvc>
<gestures-app *ngSwitchWhen="2"></gestures-app>
- <cpt-list *ngSwitchWhen="3"></cpt-list>
+ <widgets-list *ngSwitchWhen="3"></widgets-list>
<webview-app *ngSwitchWhen="4"></webview-app>
+ <apis-list *ngSwitchWhen="5"></apis-list>
</View>
</View>
<View position="absolute" top="0" bottom="0" width="300" collapsable="false">
@@ -42,6 +45,9 @@ import {NativeFeedback} from "./common";
<View [style]="styles.menuItem" (tap)="switchContent(4)" nativeFeedback="#00a9e0">
<Text [style]="styles.menuText">WebView</Text>
</View>
+ <View [style]="styles.menuItem" (tap)="switchContent(5)" nativeFeedback="#00a9e0">
+ <Text [style]="styles.menuText">APIs</Text>
+ </View>
</View>
</View>
</DrawerLayout>
@@ -55,6 +61,17 @@ export class KitchenSinkApp {
styles: any;
_el : any = null;
constructor(el: ElementRef) {
+ BackAndroid.addEventListener('hardwareBackPress', function() {
+ Alert.alert(
+ 'Close App',
+ 'Are you sure you want to close the app?',
+ [
+ {text: 'Cancel', onPress: () => {}, style: 'cancel'},
+ {text: 'OK', onPress: () => BackAndroid.exitApp()},
+ ]
+ );
+ return true;
+ });
this._el = el.nativeElement;
this.styles = StyleSheet.create({
toolbar: {
@@ -98,13 +115,23 @@ export class KitchenSinkApp {
this.viewChild.reset();
} else if (position == 1 && this.viewChild) {
this.viewChild.empty();
- }else if (position == 2 && this.viewChild) {
+ } else if (position == 2 && this.viewChild) {
this.viewChild.full();
+ } else if (position == 3 && this.viewChild) {
+ this.viewChild.save();
+ } else if (position == 4 && this.viewChild) {
+ this.viewChild.load();
}
}
private _addMoreInToolbar():void {
- this._el.children[1].children[1].children[1].setProperty('nativeActions', [{title: 'Reset list', show: 0}, {title: 'Empty list', show: 0}, {title: 'Fill list with 100 items', show: 0}]);
+ this._el.children[1].children[1].children[1].setProperty('nativeActions', [
+ {title: 'Reset list', show: 0},
+ {title: 'Empty list', show: 0},
+ {title: 'Fill list with 100 items', show: 0},
+ {title: 'Save', show: 0},
+ {title: 'Load', show: 0}
+ ]);
}
private _removeMoreInToolbar():void {
View
@@ -1,7 +1,7 @@
import {Component, Input, Output, EventEmitter} from 'angular2/core';
import {NgIf, NgFor} from 'angular2/common';
import {HighLight} from './common';
-import {StyleSheet} from 'react-native';
+import {StyleSheet, AsyncStorage} from 'react-native';
class Palette {
static background: string = '#005eb8';
@@ -241,6 +241,21 @@ export class TodoMVC {
this.todos = this.filteredTodos = res;
}
+ save() {
+ AsyncStorage.setItem('todos:key', JSON.stringify({todos: this.todos, left: this.leftCount, filter: this.filter}));
+ }
+
+ load() {
+ this.empty();
+ AsyncStorage.getItem('todos:key').then((jsonString) => {
+ var json = JSON.parse(jsonString);
+ this.todos = json.todos;
+ this.leftCount = json.left;
+ this.filter = json.filter;
+ this.filterTodos();
+ });
+ }
+
_getStyles() {
return StyleSheet.create({
all: {
View
@@ -2,7 +2,7 @@ import {Component, ElementRef} from 'angular2/core';
import {StyleSheet} from 'react-native';
@Component({
- selector: 'cpt-list',
+ selector: 'widgets-list',
host: {flex: '1'},
template: `
<PagerLayout flex="1" justifyContent="center" alignItems="center" selectedPage="0">
@@ -46,7 +46,7 @@ import {StyleSheet} from 'react-native';
</PagerLayout>
`
})
-export class ComponentsList {
+export class WidgetsList {
styles: any;
typed: string = "";
switched: boolean = false;
Oops, something went wrong.

0 comments on commit a289840

Please sign in to comment.