Basic static card component with swipeable rows

This commit is contained in:
Bruno Lemos
2017-12-13 16:29:36 -02:00
parent a557031619
commit 58896ae0fa
50 changed files with 1756 additions and 97 deletions

17
android/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>devhub</name>
<comment>Project devhub created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
#Wed Dec 13 00:16:04 BRST 2017
connection.project.dir=

6
android/app/.classpath Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin"/>
</classpath>

23
android/app/.project Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,2 @@
#Wed Dec 13 00:16:04 BRST 2017
connection.project.dir=..

View File

@@ -137,6 +137,8 @@ android {
}
dependencies {
compile project(':react-native-gesture-handler')
compile project(':react-native-vector-icons')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,9 @@
package com.devhub;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
public class MainActivity extends ReactActivity {
@@ -12,4 +15,14 @@ public class MainActivity extends ReactActivity {
protected String getMainComponentName() {
return "devhub";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
};
}
}

View File

@@ -3,6 +3,8 @@ package com.devhub;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
@@ -22,7 +24,9 @@ public class MainApplication extends Application implements ReactApplication {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
new MainReactPackage(),
new RNGestureHandlerPackage(),
new VectorIconsPackage()
);
}

View File

@@ -1,3 +1,7 @@
rootProject.name = 'devhub'
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':app'

View File

@@ -1,5 +1,13 @@
import React from 'react'
import { AppRegistry } from 'react-native'
if (process.env.NODE_ENV !== 'production') {
const { whyDidYouUpdate } = require('why-did-you-update')
whyDidYouUpdate(React, {
exclude: /^Icon|Swipeable/,
})
}
import App from './src'
AppRegistry.registerComponent('devhub', () => App)

View File

@@ -25,7 +25,7 @@
2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */; };
2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; };
2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; };
2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; };
@@ -34,9 +34,13 @@
2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */; };
2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; };
2DCD954D1E0B4F2C00145EB5 /* devhubTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* devhubTests.m */; };
2EAFF5C21FE0CEA9000A9A11 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2EAFF59C1FE0CEA9000A9A11 /* MaterialIcons.ttf */; };
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
7FC9F95B44E64398A3976B78 /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8888F60F6C304A58BF18E9E8 /* libRNVectorIcons.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; };
C2619E3179B6481FA20E5CEB /* libRNGestureHandler.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B5DF78792708477FB2343101 /* libRNGestureHandler.a */; };
F104E1DDC29047C7B18F01E9 /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FA6EFEAAAEB7487F9CC33B59 /* Octicons.ttf */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -110,6 +114,83 @@
remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7;
remoteInfo = "devhub-tvOS";
};
2EAFEE9B1FDDD3E9000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = ADD01A681E09402E00F6D226;
remoteInfo = "RCTBlob-tvOS";
};
2EAFEEAD1FDDD3E9000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3DBE0D001F3B181A0099AA32;
remoteInfo = fishhook;
};
2EAFEEAF1FDDD3E9000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32;
remoteInfo = "fishhook-tvOS";
};
2EAFEEB41FDDD3EA000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B6BF65C496E44E78BF211275 /* RNVectorIcons.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 5DBEB1501B18CEA900B34395;
remoteInfo = RNVectorIcons;
};
2EAFF54B1FE0AC4F000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7;
remoteInfo = "third-party";
};
2EAFF54D1FE0AC4F000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D383D3C1EBD27B6005632C8;
remoteInfo = "third-party-tvOS";
};
2EAFF54F1FE0AC4F000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 139D7E881E25C6D100323FB7;
remoteInfo = "double-conversion";
};
2EAFF5511FE0AC4F000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D383D621EBD27B9005632C8;
remoteInfo = "double-conversion-tvOS";
};
2EAFF5531FE0AC4F000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F3131F5F2E4B0010BF04;
remoteInfo = privatedata;
};
2EAFF5551FE0AC4F000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04;
remoteInfo = "privatedata-tvOS";
};
2EAFF58C1FE0C469000A9A11 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 1FD65CD116F747ACA2D47E1F /* RNGestureHandler.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNGestureHandler;
};
3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
@@ -258,12 +339,28 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = devhub/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = devhub/main.m; sourceTree = "<group>"; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
1A78E8CA2AB84F5DB5771FD1 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
1FD65CD116F747ACA2D47E1F /* RNGestureHandler.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNGestureHandler.xcodeproj; path = "../node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj"; sourceTree = "<group>"; };
2D02E47B1E0B4A5D006451C7 /* devhub-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "devhub-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
2D02E4901E0B4A5D006451C7 /* devhub-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "devhub-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
2EAFF59C1FE0CEA9000A9A11 /* MaterialIcons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; };
486C758B88E34A52BFB2C474 /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; };
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
5FDB82E9A6994D928FA8EF88 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; };
6BA6B80F6E304DB6AB2249A6 /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
7D47CCDFA76944C0897F14BE /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
862BDE7B078E4A57943ED526 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = "<group>"; };
8888F60F6C304A58BF18E9E8 /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; };
A78BCCD8D80D432B8BE119EB /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; };
ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = "<group>"; };
B5DF78792708477FB2343101 /* libRNGestureHandler.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNGestureHandler.a; sourceTree = "<group>"; };
B6BF65C496E44E78BF211275 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = "<group>"; };
F035D9E85FA74D8CBFBDAE1B /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; };
F1AA246742BC4C2A8C9988F3 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; };
F8A11CE8BDF64CB988CDD71E /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = "<group>"; };
FA6EFEAAAEB7487F9CC33B59 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -292,6 +389,8 @@
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
7FC9F95B44E64398A3976B78 /* libRNVectorIcons.a in Frameworks */,
C2619E3179B6481FA20E5CEB /* libRNGestureHandler.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -300,7 +399,7 @@
buildActionMask = 2147483647;
files = (
2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */,
2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */,
2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */,
2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */,
2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */,
2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */,
@@ -393,6 +492,8 @@
children = (
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */,
2EAFEEAE1FDDD3E9000A9A11 /* libfishhook.a */,
2EAFEEB01FDDD3E9000A9A11 /* libfishhook-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
@@ -422,7 +523,37 @@
3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,
3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,
3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,
3DAD3EA31DF850E9000B6D8A /* libReact-tvOS.a */,
2EAFF54C1FE0AC4F000A9A11 /* libthird-party.a */,
2EAFF54E1FE0AC4F000A9A11 /* libthird-party.a */,
2EAFF5501FE0AC4F000A9A11 /* libdouble-conversion.a */,
2EAFF5521FE0AC4F000A9A11 /* libdouble-conversion.a */,
2EAFF5541FE0AC4F000A9A11 /* libprivatedata.a */,
2EAFF5561FE0AC4F000A9A11 /* libprivatedata-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
};
2EAFEE951FDDD3E8000A9A11 /* Recovered References */ = {
isa = PBXGroup;
children = (
8888F60F6C304A58BF18E9E8 /* libRNVectorIcons.a */,
B5DF78792708477FB2343101 /* libRNGestureHandler.a */,
);
name = "Recovered References";
sourceTree = "<group>";
};
2EAFEEB11FDDD3EA000A9A11 /* Products */ = {
isa = PBXGroup;
children = (
2EAFEEB51FDDD3EA000A9A11 /* libRNVectorIcons.a */,
);
name = Products;
sourceTree = "<group>";
};
2EAFF5891FE0C469000A9A11 /* Products */ = {
isa = PBXGroup;
children = (
2EAFF58D1FE0C469000A9A11 /* libRNGestureHandler.a */,
);
name = Products;
sourceTree = "<group>";
@@ -431,7 +562,7 @@
isa = PBXGroup;
children = (
5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */,
5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */,
5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */,
);
name = Products;
sourceTree = "<group>";
@@ -460,6 +591,8 @@
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
B6BF65C496E44E78BF211275 /* RNVectorIcons.xcodeproj */,
1FD65CD116F747ACA2D47E1F /* RNGestureHandler.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@@ -476,10 +609,13 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
2EAFF59C1FE0CEA9000A9A11 /* MaterialIcons.ttf */,
13B07FAE1A68108700A75B9A /* devhub */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* devhubTests */,
83CBBA001A601CBA00E9B192 /* Products */,
8960E566DB794015B585073C /* Resources */,
2EAFEE951FDDD3E8000A9A11 /* Recovered References */,
);
indentWidth = 2;
sourceTree = "<group>";
@@ -497,10 +633,29 @@
name = Products;
sourceTree = "<group>";
};
8960E566DB794015B585073C /* Resources */ = {
isa = PBXGroup;
children = (
7D47CCDFA76944C0897F14BE /* Entypo.ttf */,
A78BCCD8D80D432B8BE119EB /* EvilIcons.ttf */,
F1AA246742BC4C2A8C9988F3 /* Feather.ttf */,
6BA6B80F6E304DB6AB2249A6 /* FontAwesome.ttf */,
F8A11CE8BDF64CB988CDD71E /* Foundation.ttf */,
5FDB82E9A6994D928FA8EF88 /* Ionicons.ttf */,
862BDE7B078E4A57943ED526 /* MaterialCommunityIcons.ttf */,
486C758B88E34A52BFB2C474 /* MaterialIcons.ttf */,
FA6EFEAAAEB7487F9CC33B59 /* Octicons.ttf */,
F035D9E85FA74D8CBFBDAE1B /* SimpleLineIcons.ttf */,
1A78E8CA2AB84F5DB5771FD1 /* Zocial.ttf */,
);
name = Resources;
sourceTree = "<group>";
};
ADBDB9201DFEBF0600ED6528 /* Products */ = {
isa = PBXGroup;
children = (
ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */,
2EAFEE9C1FDDD3E9000A9A11 /* libRCTBlob-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
@@ -586,13 +741,16 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
LastUpgradeCheck = 610;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
00E356ED1AD99517003FC87E = {
CreatedOnToolsVersion = 6.2;
TestTargetID = 13B07F861A680F5B00A75B9A;
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = JNXGJS86YQ;
};
2D02E47A1E0B4A5D006451C7 = {
CreatedOnToolsVersion = 8.2.1;
ProvisioningStyle = Automatic;
@@ -664,6 +822,14 @@
ProductGroup = 146834001AC3E56700842450 /* Products */;
ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
},
{
ProductGroup = 2EAFF5891FE0C469000A9A11 /* Products */;
ProjectRef = 1FD65CD116F747ACA2D47E1F /* RNGestureHandler.xcodeproj */;
},
{
ProductGroup = 2EAFEEB11FDDD3EA000A9A11 /* Products */;
ProjectRef = B6BF65C496E44E78BF211275 /* RNVectorIcons.xcodeproj */;
},
);
projectRoot = "";
targets = (
@@ -732,6 +898,83 @@
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFEE9C1FDDD3E9000A9A11 /* libRCTBlob-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTBlob-tvOS.a";
remoteRef = 2EAFEE9B1FDDD3E9000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFEEAE1FDDD3E9000A9A11 /* libfishhook.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libfishhook.a;
remoteRef = 2EAFEEAD1FDDD3E9000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFEEB01FDDD3E9000A9A11 /* libfishhook-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libfishhook-tvOS.a";
remoteRef = 2EAFEEAF1FDDD3E9000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFEEB51FDDD3EA000A9A11 /* libRNVectorIcons.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNVectorIcons.a;
remoteRef = 2EAFEEB41FDDD3EA000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF54C1FE0AC4F000A9A11 /* libthird-party.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libthird-party.a";
remoteRef = 2EAFF54B1FE0AC4F000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF54E1FE0AC4F000A9A11 /* libthird-party.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libthird-party.a";
remoteRef = 2EAFF54D1FE0AC4F000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF5501FE0AC4F000A9A11 /* libdouble-conversion.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libdouble-conversion.a";
remoteRef = 2EAFF54F1FE0AC4F000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF5521FE0AC4F000A9A11 /* libdouble-conversion.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libdouble-conversion.a";
remoteRef = 2EAFF5511FE0AC4F000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF5541FE0AC4F000A9A11 /* libprivatedata.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libprivatedata.a;
remoteRef = 2EAFF5531FE0AC4F000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF5561FE0AC4F000A9A11 /* libprivatedata-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libprivatedata-tvOS.a";
remoteRef = 2EAFF5551FE0AC4F000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
2EAFF58D1FE0C469000A9A11 /* libRNGestureHandler.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNGestureHandler.a;
remoteRef = 2EAFF58C1FE0C469000A9A11 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -774,10 +1017,10 @@
remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3DAD3EA31DF850E9000B6D8A /* libReact-tvOS.a */ = {
3DAD3EA31DF850E9000B6D8A /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libReact-tvOS.a";
path = libReact.a;
remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@@ -830,10 +1073,10 @@
remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = {
5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libRCTAnimation-tvOS.a";
path = libRCTAnimation.a;
remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@@ -874,6 +1117,8 @@
files = (
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
F104E1DDC29047C7B18F01E9 /* Octicons.ttf in Resources */,
2EAFF5C21FE0CEA9000A9A11 /* MaterialIcons.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -996,9 +1241,19 @@
"DEBUG=1",
"$(inherited)",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
);
INFOPLIST_FILE = devhubTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
@@ -1013,9 +1268,19 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
COPY_PHASE_STRIP = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
);
INFOPLIST_FILE = devhubTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
@@ -1031,6 +1296,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = JNXGJS86YQ;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
);
INFOPLIST_FILE = devhub/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
@@ -1048,6 +1319,12 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JNXGJS86YQ;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
);
INFOPLIST_FILE = devhub/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
@@ -1072,8 +1349,18 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
);
INFOPLIST_FILE = "devhub-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
@@ -1098,8 +1385,18 @@
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_NO_COMMON_BLOCKS = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
);
INFOPLIST_FILE = "devhub-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
@@ -1125,6 +1422,11 @@
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = "devhub-tvOSTests/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.devhub-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
@@ -1146,6 +1448,11 @@
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = "devhub-tvOSTests/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.devhub-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;

View File

@@ -1,9 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina5_9" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
@@ -11,29 +14,7 @@
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="devhub" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<color key="backgroundColor" red="0.28627450980392155" green="0.82745098039215681" blue="0.70588235294117641" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>

View File

@@ -24,24 +24,7 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
<dict>
<key>NSExceptionDomains</key>
<dict>
@@ -52,5 +35,28 @@
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UIAppFonts</key>
<array>
<string>MaterialIcons.ttf</string>
<string>Octicons.ttf</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View File

@@ -8,10 +8,16 @@
"xcode": "open ios/devhub.xcodeproj"
},
"dependencies": {
"@types/react-native-vector-icons": "^4.4.2",
"gravatar": "^1.6.0",
"react": "^16.2.0",
"react-native": "^0.51.0"
"react-native": "^0.51.0",
"react-native-gesture-handler": "^1.0.0-alpha.35",
"react-native-vector-icons": "^4.4.2",
"warna": "^0.2.4"
},
"devDependencies": {
"@types/gravatar": "^1.4.28",
"@types/jest": "^21.1.5",
"@types/react": "^16.0.21",
"@types/react-native": "^0.50.2",
@@ -25,7 +31,8 @@
"tslint": "^5.8.0",
"tslint-config-airbnb": "^5.3.0",
"tslint-react": "^3.2.0",
"typescript": "^2.6.1"
"typescript": "^2.6.1",
"why-did-you-update": "^0.1.0"
},
"jest": {
"preset": "react-native",
@@ -34,13 +41,22 @@
"useBabelrc": true
}
},
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json"],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json"
],
"transform": {
"^.+\\.(jsx?)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.(tsx?)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"testPathIgnorePatterns": ["<rootDir>/node_modules/", "<rootDir>/.history/"],
"testPathIgnorePatterns": [
"<rootDir>/node_modules/",
"<rootDir>/.history/"
],
"cacheDirectory": ".jest/cache"
}
}

View File

@@ -0,0 +1,11 @@
import React from 'react'
import SwipeableCard, { IProps as ICardProps } from './partials/SwipeableCard'
export interface IProps extends ICardProps {}
export interface IState {}
const NotificationCard = ({ username }: IProps) => <SwipeableCard username={username} />
export default NotificationCard

View File

@@ -0,0 +1,36 @@
import React from 'react'
import { FlatList } from 'react-native'
import { INotification } from '../../utils/types'
import NotificationCard from './NotificationCard'
import CardItemSeparator from './partials/CardItemSeparator'
export interface IProps {
notifications: INotification[]
}
class NotificationCards extends React.PureComponent<IProps> {
keyExtractor(notification: INotification) {
return notification.id
}
renderItem({ item: { actor: { username } } }: { item: INotification }) {
return <NotificationCard username={username} />
}
render() {
const { notifications } = this.props
return (
<FlatList
data={notifications}
ListHeaderComponent={CardItemSeparator}
ListFooterComponent={CardItemSeparator}
ItemSeparatorComponent={CardItemSeparator}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
/>
)
}
}
export default NotificationCards

View File

@@ -0,0 +1,28 @@
import React from 'react'
import { StyleSheet, View, ViewStyle } from 'react-native'
import theme from '../../../styles/themes/light'
import { contentPadding } from '../../../styles/variables'
import CardHeader, { IProps as ICardHeaderProps } from './CardHeader'
import RepositoryRow from './rows/RepositoryRow'
export interface IProps extends ICardHeaderProps {}
export interface IState {}
const styles = StyleSheet.create({
container: {
backgroundColor: theme.cardBackground,
paddingHorizontal: contentPadding,
paddingVertical: 2 * contentPadding,
} as ViewStyle,
})
const Card = ({ username }: IProps) => (
<View style={styles.container}>
<CardHeader username={username} />
<RepositoryRow owner="facebook" repository="react-native" />
</View>
)
export default Card

View File

@@ -0,0 +1,58 @@
import React from 'react'
import { StyleSheet, Text, View, ViewStyle } from 'react-native'
import Avatar from '../../common/Avatar'
import cardStyles from '../styles'
import CardIcon from './CardIcon'
export interface IProps {
username: string
}
export interface IState {}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
flexGrow: 1,
} as ViewStyle,
rightColumnCentered: {
flex: 1,
justifyContent: 'center',
} as ViewStyle,
outerContainer: {
flexDirection: 'row',
justifyContent: 'center',
} as ViewStyle,
innerContainer: {
flex: 1,
} as ViewStyle,
})
const CardHeader = ({ username }: IProps) => (
<View style={styles.container}>
<View style={cardStyles.leftColumn}>
<Avatar username={username} style={cardStyles.avatar} />
</View>
<View style={styles.rightColumnCentered}>
<View style={styles.outerContainer}>
<View style={styles.innerContainer}>
<View style={cardStyles.horizontal}>
<Text style={cardStyles.usernameText}>{username}</Text>
<Text style={cardStyles.timestampText}>&nbsp;&nbsp;2h (13:59)</Text>
</View>
<Text style={cardStyles.descriptionText}>starred a repository</Text>
</View>
<CardIcon name="star" color="#FFC107" />
</View>
</View>
</View>
)
export default CardHeader

View File

@@ -0,0 +1,21 @@
import React from 'react'
import { StyleSheet, ViewStyle } from 'react-native'
import { IconProps } from 'react-native-vector-icons/Icon'
import Icon from 'react-native-vector-icons/Octicons'
import { contentPadding } from '../../../styles/variables'
export interface IProps extends IconProps {}
const styles = StyleSheet.create({
container: {
fontSize: 18,
marginLeft: contentPadding,
} as ViewStyle,
})
const CardIcon = (props: IProps) => {
return <Icon {...props} style={[styles.container, props.style]} />
}
export default CardIcon

View File

@@ -0,0 +1,17 @@
import React from 'react'
import { StyleSheet, View, ViewStyle } from 'react-native'
import theme from '../../../styles/themes/light'
const styles = StyleSheet.create({
separator: {
borderBottomColor: theme.base01,
borderBottomWidth: 1,
flexGrow: 1,
height: 1,
} as ViewStyle,
})
const CardItemSeparator = () => <View style={styles.separator} />
export default CardItemSeparator

View File

@@ -0,0 +1,37 @@
import React from 'react'
import SwipeableRow from '../../../libs/swipeable'
import Card, { IProps as ICardProps } from './Card'
export interface IProps extends ICardProps {}
export interface IState {}
const SwipeableCard = (props: IProps) => (
<SwipeableRow
leftActions={[
{
type: 'FULL',
key: 'archive',
icon: 'archive',
color: '#497AFC',
label: 'Archive',
onPress: () => {},
},
]}
rightActions={[
{
type: 'FULL',
key: 'archive',
icon: 'archive',
color: '#497AFC',
label: 'Archive',
onPress: () => {},
},
]}
>
<Card {...props} />
</SwipeableRow>
)
export default SwipeableCard

View File

@@ -0,0 +1,30 @@
import React from 'react'
import { Text, View } from 'react-native'
import Avatar from '../../../common/Avatar'
import cardStyles from '../../styles'
import rowStyles from './styles'
export interface IProps {
repository: string
owner: string
}
export interface IState {}
const RepositoryRow = ({ owner, repository }: IProps) => (
<View style={rowStyles.container}>
<View style={cardStyles.leftColumn}>
<Avatar username={owner} small style={cardStyles.avatar} />
</View>
<View style={cardStyles.rightColumn}>
<View style={rowStyles.mainContentContainer}>
<Text style={rowStyles.repositoryText}>{repository}</Text>
<Text style={rowStyles.ownerText}>&nbsp;{owner}</Text>
</View>
</View>
</View>
)
export default RepositoryRow

View File

@@ -0,0 +1,32 @@
import { StyleSheet, TextStyle, ViewStyle } from 'react-native'
import theme from '../../../../styles/themes/light'
import { contentPadding, radius, smallTextSize } from '../../../../styles/variables'
export default StyleSheet.create({
container: {
flexDirection: 'row',
flexGrow: 1,
marginTop: contentPadding,
} as ViewStyle,
mainContentContainer: {
alignItems: 'center',
borderColor: theme.base01,
borderRadius: radius,
borderWidth: 1,
flexDirection: 'row',
flexGrow: 1,
paddingHorizontal: contentPadding,
paddingVertical: contentPadding / 2,
} as ViewStyle,
ownerText: {
color: theme.base05,
fontSize: smallTextSize,
} as TextStyle,
repositoryText: {
color: theme.base04,
} as TextStyle,
})

View File

@@ -0,0 +1,46 @@
import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from 'react-native'
import theme from '../../styles/themes/light'
import { avatarSize, contentPadding, smallTextSize } from '../../styles/variables'
export default StyleSheet.create({
horizontal: {
flexDirection: 'row',
} as ViewStyle,
leftColumn: {
justifyContent: 'center',
marginRight: contentPadding,
width: avatarSize,
} as ViewStyle,
avatar: {
alignSelf: 'flex-end',
} as ImageStyle,
rightColumn: {
flex: 1,
} as ViewStyle,
usernameText: {
alignSelf: 'center',
color: theme.base04,
fontWeight: 'bold',
lineHeight: 20,
} as TextStyle,
timestampText: {
alignSelf: 'center',
color: theme.base05,
fontSize: smallTextSize,
} as TextStyle,
mutedText: {
color: theme.base05,
} as TextStyle,
descriptionText: {
color: theme.base05,
lineHeight: 20,
} as TextStyle,
})

View File

@@ -0,0 +1,48 @@
import React from 'react'
import { Image, ImageStyle, StyleSheet, ViewStyle } from 'react-native'
import { avatarSize, radius, smallAvatarSize } from '../../styles/variables'
import { getUserAvatarByEmail, getUserAvatarByUsername } from '../../utils/helpers/github'
export interface IProps {
avatarURL?: string
email?: string
size?: number
small?: boolean
style?: ImageStyle
username?: string
}
export const size = avatarSize
const styles = StyleSheet.create({
image: {
borderRadius: radius,
} as ViewStyle,
})
const Avatar = ({ avatarURL, email, size: _size, small, style, username, ...props }: IProps) => {
const finalSize = _size || (small ? smallAvatarSize : avatarSize)
const uri =
(username && getUserAvatarByUsername(username, { size: finalSize })) ||
avatarURL ||
(email && getUserAvatarByEmail(email, { size: finalSize }))
if (!uri) return null
return (
<Image
{...props}
source={{ uri }}
style={[
styles.image,
{
height: finalSize,
width: finalSize,
},
style,
]}
/>
)
}
export default Avatar

View File

@@ -0,0 +1,24 @@
import React, { ReactNode } from 'react'
import { SafeAreaView, StyleSheet, ViewStyle } from 'react-native'
import theme from '../../styles/themes/light'
export const size = 48
export interface IProps {
children: ReactNode
style?: ViewStyle
}
const styles = StyleSheet.create({
container: {
backgroundColor: theme.base00,
flex: 1,
} as ViewStyle,
})
const Screen = (props: IProps) => (
<SafeAreaView {...props} style={[styles.container, props.style]} />
)
export default Screen

View File

@@ -0,0 +1,12 @@
import React from 'react'
import NotificationCardsContainer from '../../containers/NotificationCardsContainer'
import Screen from '../common/Screen'
const NotificationsScreen = () => (
<Screen>
<NotificationCardsContainer />
</Screen>
)
export default NotificationsScreen

View File

@@ -0,0 +1,15 @@
import React from 'react'
import NotificationCards from '../components/cards/NotificationCards'
import { INotification } from '../utils/types'
const notifications: INotification[] = [
{ id: '0', actor: { id: '0', username: 'sibelius' } },
{ id: '1', actor: { id: '1', username: 'gaearon' } },
{ id: '2', actor: { id: '2', username: 'brunolemos' } },
{ id: '3', actor: { id: '3', username: 'augustolazaro' } },
]
const NotificationCardsContainer = () => <NotificationCards notifications={notifications} />
export default NotificationCardsContainer

View File

@@ -1,39 +1,18 @@
import React, { Component } from 'react'
import { StyleSheet, Text, TextStyle, View, ViewStyle } from 'react-native'
import React from 'react'
import { StatusBar, StyleSheet, View } from 'react-native'
export interface IProps {}
export interface IState {}
export default class App extends Component<IProps, IState> {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native</Text>
<Text style={styles.instructions}>To get started, edit index.js</Text>
<Text style={styles.instructions}>Using Typescript</Text>
</View>
)
}
}
import NotificationsScreen from './components/screens/NotificationsScreen'
import theme from './styles/themes/light'
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex: 1,
justifyContent: 'center',
} as ViewStyle,
welcome: {
fontSize: 20,
margin: 10,
textAlign: 'center',
} as TextStyle,
instructions: {
color: '#333333',
marginBottom: 5,
textAlign: 'center',
} as TextStyle,
},
})
export default () => (
<View style={styles.container}>
<StatusBar barStyle={theme.isDark ? 'light-content' : 'dark-content'} />
<NotificationsScreen />
</View>
)

10
src/libs/platform/index.ts Executable file
View File

@@ -0,0 +1,10 @@
import { Platform as _Platform } from 'react-native'
const Platform = {
..._Platform,
isStandalone: true,
realOS: _Platform.OS,
selectUsingRealOS: _Platform.select,
}
export default Platform

21
src/libs/platform/index.web.ts Executable file
View File

@@ -0,0 +1,21 @@
import { Platform as _Platform } from 'react-native'
function getOSName(): 'android' | 'ios' | 'web' {
const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera
if (/android/i.test(userAgent)) return 'android'
if (/iPad|iPhone|iPod/.test(userAgent) && !(window as any).MSStream) return 'ios'
return 'web'
}
const realOS = getOSName()
const Platform = {
realOS,
..._Platform,
isStandalone: (window.navigator as any).standalone,
selectUsingRealOS: (obj: { android?: any; ios?: any; web?: any; default?: any }) =>
Platform.realOS in obj ? obj[realOS] : 'web' in obj ? obj.web : obj.default,
}
export default Platform

View File

@@ -0,0 +1,140 @@
import React from 'react'
import { Animated, StyleSheet, Text } from 'react-native'
import { RectButton } from 'react-native-gesture-handler'
import Swipeable from 'react-native-gesture-handler/Swipeable'
import BaseSwipeableRow, { IBaseAction, IBaseProps, Placement } from './BaseSwipeableRow'
export { defaultWidth } from './BaseSwipeableRow'
export interface IAction extends IBaseAction {
label: string
}
export interface IProps extends IBaseProps {}
export default class AppleSwipeableRow extends BaseSwipeableRow {
_swipeableRow = null
renderButtonAction = (
action: IAction,
{ x, placement, progress }: { x: number; placement: Placement; progress },
) => {
const transform = {
translateX:
placement === 'LEFT'
? progress.interpolate({
inputRange: [0, 1],
outputRange: [-x, 0],
})
: progress.interpolate({
inputRange: [0, 1],
outputRange: [x, 0],
}),
}
const pressHandler = () => {
action.onPress()
this.close()
alert(action.label)
}
return (
<Animated.View
key={`swipeable-button-action-${action.key}`}
style={{ flex: 1, transform: [transform] }}
>
<RectButton
style={[
styles.baseActionContainer,
{ backgroundColor: action.color, width: action.width },
]}
onPress={pressHandler}
>
<Text
style={[
styles.actionText,
{ alignSelf: 'center', color: action.textColor || '#FFFFFF' },
]}
>
{action.label}
</Text>
</RectButton>
</Animated.View>
)
}
renderFullAction = (action: IAction, { dragX, placement }: { placement: Placement }) => {
const transform = {
translateX:
placement === 'LEFT'
? dragX.interpolate({
inputRange: [0, 50, 100, 101],
outputRange: [-20, 0, 0, 1],
})
: dragX.interpolate({
inputRange: [-101, -100, -50, 0],
outputRange: [-1, 0, 0, 20],
}),
}
const pressHandler = () => {
action.onPress()
this.close()
}
return (
<RectButton
key={`swipeable-full-action-${action.key}`}
style={[
styles.baseActionContainer,
{ backgroundColor: action.color, minWidth: action.width },
]}
onPress={pressHandler}
>
<Animated.Text
style={[
styles.actionText,
{
alignSelf: placement === 'LEFT' ? 'flex-start' : 'flex-end',
color: action.textColor || '#FFFFFF',
transform: [transform],
},
]}
>
{action.label}
</Animated.Text>
</RectButton>
)
}
render() {
const { children, ...props } = this.props
return (
<Swipeable
{...props}
ref={this.updateRef}
friction={2}
leftThreshold={30}
renderLeftActions={this.renderLeftActions}
renderRightActions={this.renderRightActions}
rightThreshold={40}
>
{children}
</Swipeable>
)
}
}
const styles = StyleSheet.create({
actionText: {
backgroundColor: 'transparent',
fontSize: 16,
padding: 10,
},
baseActionContainer: {
flex: 1,
justifyContent: 'center',
},
})

View File

@@ -0,0 +1,109 @@
import React, { PureComponent } from 'react'
import { View } from 'react-native'
enum BaseActionType {
BUTTON = 'BUTTON',
FULL = 'FULL',
}
export interface IBaseAction {
color: string
key: string
onPress: () => void
textColor?: string
type?: BaseActionType
width?: number
}
export interface IBaseProps {
leftActions: IBaseAction[]
rightActions: IBaseAction[]
}
export interface IBaseState {}
export enum Placement {
LEFT = 'LEFT',
RIGHT = 'RIGHT',
}
export const defaultWidth = 64
export default class BaseSwipeableRow extends PureComponent<IBaseProps, IBaseState> {
_swipeableRow = null
renderButtonAction = (
action: IBaseAction,
{ dragX, placement, progress, x }: { x: number; placement: Placement; progress: number },
) => {
throw new Error('Not implemented: renderButtonAction')
}
renderFullAction = (
action: IBaseAction,
{ dragX, placement, progress }: { placement: Placement },
) => {
throw new Error('Not implemented: renderFullAction')
}
renderLeftActions = (progress: number, dragX) => {
const { leftActions: actions } = this.props
const fullAction = actions.find(action => action.type === 'FULL')
const buttonActions = actions.filter(action => action.type !== 'FULL')
if (fullAction) return this.renderFullAction(fullAction, { dragX, placement: 'LEFT', progress })
const width = buttonActions.reduce((total, action) => total + (action.width || defaultWidth), 0)
let x = 0
return (
<View style={{ width, flexDirection: 'row' }}>
{buttonActions.map(action => {
x += action.width || defaultWidth
return this.renderButtonAction(action, { placement: 'LEFT', progress, x })
})}
</View>
)
}
renderRightActions = (progress: number, dragX) => {
const { rightActions: actions } = this.props
const fullAction = actions.find(action => action.type === 'FULL')
const buttonActions = actions.filter(action => action.type !== 'FULL')
if (fullAction)
return this.renderFullAction(fullAction, { dragX, placement: 'RIGHT', progress })
const width = buttonActions.reduce((total, action) => total + (action.width || defaultWidth), 0)
let x = width
return (
<View style={{ width, flexDirection: 'row' }}>
{buttonActions.map(action => {
const component = this.renderButtonAction(action, {
dragX,
placement: 'RIGHT',
progress,
x,
})
x -= action.width || defaultWidth
return component
})}
</View>
)
}
updateRef = ref => {
this._swipeableRow = ref
}
close = () => {
this._swipeableRow.close()
}
render() {
throw new Error('Not implemented: render')
}
}

View File

@@ -0,0 +1,138 @@
import React from 'react'
import { Animated, StyleSheet, Text } from 'react-native'
import { RectButton } from 'react-native-gesture-handler'
import Swipeable from 'react-native-gesture-handler/Swipeable'
import Icon from 'react-native-vector-icons/MaterialIcons'
import BaseSwipeableRow, { IBaseAction, IBaseProps, Placement } from './BaseSwipeableRow'
export { defaultWidth } from './BaseSwipeableRow'
export interface IAction extends IBaseAction {
icon: string
}
export interface IProps extends IBaseProps {}
const AnimatedIcon = Animated.createAnimatedComponent(Icon)
export default class GoogleSwipeableRow extends BaseSwipeableRow {
_swipeableRow = null
renderButtonAction = (
action: IAction,
{ dragX, x, placement }: { x: number; placement: Placement },
) => {
const transform = {
scale:
placement === 'LEFT'
? dragX.interpolate({
inputRange: [x - 80, x],
outputRange: [0, 1],
extrapolate: 'clamp',
})
: dragX.interpolate({
inputRange: [-x, -x + 80],
outputRange: [1, 0],
extrapolate: 'clamp',
}),
}
const pressHandler = () => {
action.onPress()
this.close()
alert(action.label)
}
return (
<RectButton
key={`swipeable-button-action-${action.key}`}
style={[
styles.baseActionContainer,
{ alignItems: 'center', backgroundColor: action.color },
]}
onPress={pressHandler}
>
<AnimatedIcon
name={action.icon}
size={30}
color={action.textColor || '#FFFFFF'}
style={[styles.actionIcon, { transform: [transform] }]}
/>
</RectButton>
)
}
renderFullAction = (action: IAction, { dragX, placement }: { placement: Placement }) => {
const transform = {
scale:
placement === 'LEFT'
? dragX.interpolate({
inputRange: [0, 80],
outputRange: [0, 1],
extrapolate: 'clamp',
})
: dragX.interpolate({
inputRange: [-80, 0],
outputRange: [1, 0],
extrapolate: 'clamp',
}),
}
const pressHandler = () => {
action.onPress()
this.close()
}
return (
<RectButton
key={`swipeable-full-action-${action.key}`}
style={[
styles.baseActionContainer,
{
alignItems: placement === 'LEFT' ? 'flex-start' : 'flex-end',
backgroundColor: action.color,
},
]}
onPress={pressHandler}
>
<AnimatedIcon
name={action.icon}
size={30}
color={action.textColor || '#FFFFFF'}
style={[styles.actionIcon, { transform: [transform] }]}
/>
</RectButton>
)
}
render() {
const { children, ...props } = this.props
return (
<Swipeable
{...props}
ref={this.updateRef}
friction={2}
leftThreshold={80}
renderLeftActions={this.renderLeftActions}
renderRightActions={this.renderRightActions}
rightThreshold={40}
>
{children}
</Swipeable>
)
}
}
const styles = StyleSheet.create({
actionIcon: {
backgroundColor: 'transparent',
marginHorizontal: 10,
width: 30,
},
baseActionContainer: {
flex: 1,
justifyContent: 'center',
},
})

View File

@@ -0,0 +1,3 @@
import GoogleSwipeableRow from './GoogleSwipeableRow'
export default GoogleSwipeableRow

View File

@@ -0,0 +1,3 @@
import AppleSwipeableRow from './AppleSwipeableRow'
export default AppleSwipeableRow

20
src/styles/themes/base.ts Executable file
View File

@@ -0,0 +1,20 @@
export const lightBlue = '#49d3b4'
export const purple = '#6e5494'
export const brand = lightBlue
export const brandSecondary = purple
export const star = '#edb800'
export const blue = '#2196F3'
export const blueGray = '#607D8B'
export const brown = '#795548'
export const darkGray = '#444444'
export const gray = '#9E9E9E'
export const green = '#2cbe4e'
export const indigo = '#3F51B5'
export const orange = '#FF9800'
export const pink = '#E91E63'
export const lightRed = '#F44336'
export const red = '#cb2431'
export const teal = '#009688'
export const yellow = '#FFC107'

60
src/styles/themes/dark-blue.ts Executable file
View File

@@ -0,0 +1,60 @@
import Platform from '../../libs/platform'
import * as base from './base'
export const base00 = '#141c26' // page background
export const base01 = '#141c26' // card background -1
export const base02 = '#1b2936' // card background 0
export const base03 = '#243447' // card background +1
export const base04 = '#dddddd' // color (to mute, use opacity 0.9 = #666666, #888888)
export const base05 = '#6b7d8c' // muted color
export const base06 = '#ffffff' // color high contrast
export const base07 = base.brand // brand 1
export const base08 = base.brandSecondary // brand 2
export const base09 = undefined
export const base0A = undefined
export const base0B = undefined
export const base0C = undefined
export const base0D = undefined
export const base0E = undefined
export const base0F = undefined
export const base16 = {
base00,
base01,
base02,
base03,
base04,
base05,
base06,
base07,
base08,
base09,
base0A,
base0B,
base0C,
base0D,
base0E,
base0F,
}
export const cardBackground = base02
export const tabBarBackground = Platform.select({
android: base01,
default: base02,
})
export const statusBarBackground = Platform.select({
android: tabBarBackground,
default: base01,
})
export default {
...base,
...base16,
cardBackground,
statusBarBackground,
tabBarBackground,
invert: () => require('./light').default, // tslint:disable-line
isDark: true,
name: 'dark-blue',
}

62
src/styles/themes/dark.ts Executable file
View File

@@ -0,0 +1,62 @@
import { Platform } from 'react-native'
import { fade } from '../../utils/helpers/color'
import { mutedOpacity } from '../variables'
import * as base from './base'
export const base00 = '#1c1c1c' // page background
export const base01 = '#111111' // card background -1
export const base02 = '#1c1c1c' // card background 0
export const base03 = '#353535' // card background +1
export const base04 = '#dddddd' // color (to mute, use opacity 0.9 = #666666, #888888)
export const base05 = fade(base04, mutedOpacity) // muted color
export const base06 = '#ffffff' // color high contrast
export const base07 = base.brand // brand 1
export const base08 = base.brandSecondary // brand 2
export const base09 = undefined // unread card background
export const base0A = undefined
export const base0B = undefined
export const base0C = undefined
export const base0D = undefined
export const base0E = undefined
export const base0F = undefined
export const base16 = {
base00,
base01,
base02,
base03,
base04,
base05,
base06,
base07,
base08,
base09,
base0A,
base0B,
base0C,
base0D,
base0E,
base0F,
}
export const cardBackground = base03
export const tabBarBackground = Platform.select({
android: base01,
default: base02,
})
export const statusBarBackground = Platform.select({
android: tabBarBackground,
default: base01,
})
export default {
...base,
...base16,
cardBackground,
statusBarBackground,
tabBarBackground,
invert: () => require('./light').default, // tslint:disable-line
isDark: true,
name: 'dark',
}

13
src/styles/themes/index.ts Executable file
View File

@@ -0,0 +1,13 @@
import darkTheme from './dark'
import darkBlueTheme from './dark-blue'
import lightTheme from './light'
export const DARK_THEME = darkTheme
export const DARK_BLUE_THEME = darkBlueTheme
export const LIGHT_THEME = lightTheme
export default {
[DARK_THEME.name]: DARK_THEME,
[DARK_BLUE_THEME.name]: DARK_BLUE_THEME,
[LIGHT_THEME.name]: LIGHT_THEME,
}

59
src/styles/themes/light.ts Executable file
View File

@@ -0,0 +1,59 @@
import { Platform } from 'react-native'
import { lighten } from '../../utils/helpers/color'
import { mutedOpacity } from '../variables'
import * as base from './base'
export const base00 = '#ffffff' // page background
export const base01 = '#ededed' // card background -1
export const base02 = '#ffffff' // card background 0
export const base03 = '#f0f0f0' // card background +1
export const base04 = '#222222' // color
export const base05 = lighten('#222222', mutedOpacity).hex // muted color
export const base06 = '#000000' // color high contrast
export const base07 = base.brand // brand 1
export const base08 = base.brandSecondary // brand 2
export const base09 = undefined
export const base0A = undefined
export const base0B = undefined
export const base0C = undefined
export const base0D = undefined
export const base0E = undefined
export const base0F = undefined
export const base16 = {
base00,
base01,
base02,
base03,
base04,
base05,
base06,
base07,
base08,
base09,
base0A,
base0B,
base0C,
base0D,
base0E,
base0F,
}
export const cardBackground = base02
export const tabBarBackground = base02
export const statusBarBackground = Platform.select({
android: tabBarBackground,
default: base01,
})
export default {
...base,
...base16,
cardBackground,
statusBarBackground,
tabBarBackground,
invert: () => require('./dark').default, // tslint:disable-line
isDark: false,
name: 'light',
}

6
src/styles/variables.ts Normal file
View File

@@ -0,0 +1,6 @@
export const avatarSize = 48
export const contentPadding = 12
export const mutedOpacity = 0.5
export const radius = 4
export const smallAvatarSize = avatarSize / 2
export const smallTextSize = 12

View File

@@ -0,0 +1,8 @@
import warna from 'warna'
export const { darken, lighten } = warna
export function fade(color: string, opacity: number = 1) {
const { rgb } = warna.parse(color)
return `rgba(${rgb.red}, ${rgb.green}, ${rgb.blue}, ${opacity})`
}

View File

@@ -0,0 +1,28 @@
import gravatar from 'gravatar'
import { getSteppedSize } from './shared'
export function getUserAvatarByUsername(username: string, { size }: { size?: number } = {}) {
return username ? `https://github.com/${username}.png?size=${getSteppedSize(size)}` : ''
}
export function tryGetUsernameFromGithubEmail(email: string) {
if (!email) return ''
const emailSplit = email.split('@')
if (emailSplit.length === 2 && emailSplit[1] === 'users.noreply.github.com') return emailSplit[0]
return ''
}
export function getUserAvatarByEmail(
email: string,
{ size, ...otherOptions }: { size?: number } = {},
) {
const steppedSize = getSteppedSize(size)
const username = tryGetUsernameFromGithubEmail(email)
if (username) return getUserAvatarByUsername(username, { size: steppedSize })
const options = { size: `${steppedSize || ''}`, d: 'retro', ...otherOptions }
return `https:${gravatar.url(email, options)}`.replace('??', '?')
}

View File

@@ -0,0 +1,13 @@
import { PixelRatio } from 'react-native'
// sizes will be multiples of 50 for caching (e.g 50, 100, 150, ...)
export function getSteppedSize(size?: number, sizeSteps = 50) {
const steppedSize =
typeof size === 'number' ? sizeSteps * Math.max(1, Math.ceil(size / sizeSteps)) : sizeSteps
return PixelRatio.getPixelSizeForLayoutSize(steppedSize)
}
export function randomBetween(minNumber: number, maxNumber: number) {
return Math.floor(Math.random() * maxNumber) + minNumber
}

9
src/utils/types.ts Normal file
View File

@@ -0,0 +1,9 @@
export interface IUser {
id: string
username: string
}
export interface INotification {
id: string
actor: IUser
}

View File

@@ -3,12 +3,21 @@
"extends": ["tslint:recommended", "tslint-config-airbnb", "tslint-react"],
"jsRules": {},
"rules": {
"semicolon": false,
"curly": false,
"import-name": false,
"jsx-boolean-value": false,
"jsx-no-multiline-js": false,
"member-access": false,
"no-empty-interface": false,
"import-name": false,
"curly": false,
"ter-arrow-parens": false
"semicolon": false,
"ter-arrow-parens": false,
"variable-name": [
true,
"allow-leading-underscore",
"allow-pascal-case",
"ban-keywords",
"check-format"
]
},
"rulesDirectory": []
}

167
yarn.lock
View File

@@ -2,10 +2,27 @@
# yarn lockfile v1
"@types/gravatar@^1.4.28":
version "1.4.28"
resolved "https://registry.yarnpkg.com/@types/gravatar/-/gravatar-1.4.28.tgz#a83527c354b3bce265ef489facfbed34971f9b16"
"@types/jest@^21.1.5":
version "21.1.6"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-21.1.6.tgz#9467945ce33261e4fdd14276576951aa130515aa"
"@types/react-native-vector-icons@^4.4.2":
version "4.4.2"
resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-4.4.2.tgz#dd6b6a4d9dee7c85e3246f6c67905dbc1faee3d5"
dependencies:
"@types/react" "*"
"@types/react-native" "*"
"@types/react-native@*":
version "0.51.0"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.51.0.tgz#322caad4224c258365a5afb17d8669939ee6d074"
dependencies:
"@types/react" "*"
"@types/react-native@^0.50.2":
version "0.50.5"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.50.5.tgz#d56742243851f4f55b0a55e460b94e605f9b38dd"
@@ -887,6 +904,10 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
blueimp-md5@^2.3.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.10.0.tgz#02f0843921f90dca14f5b8920a38593201d6964d"
body-parser@~1.13.3:
version "1.13.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97"
@@ -979,6 +1000,10 @@ camelcase@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -1373,6 +1398,10 @@ ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
email-validator@^1.0.7:
version "1.1.1"
resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-1.1.1.tgz#b07f3be7bac1dc099bc43e75f6ae399f552d5a80"
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
@@ -1795,6 +1824,15 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6,
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
gravatar@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/gravatar/-/gravatar-1.6.0.tgz#8bdc9b786ca725a8e7076416d1731f8d3331c976"
dependencies:
blueimp-md5 "^2.3.0"
email-validator "^1.0.7"
querystring "0.2.0"
yargs "^6.0.0"
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -2644,6 +2682,14 @@ lodash.escape@^3.0.0:
dependencies:
lodash._root "^3.0.0"
lodash.every@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.every/-/lodash.every-4.6.0.tgz#eb89984bebc4364279bb3aefbbd1ca19bfa6c6a7"
lodash.filter@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace"
lodash.isarguments@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
@@ -2652,6 +2698,18 @@ lodash.isarray@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
lodash.isfunction@^3.0.8:
version "3.0.8"
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.8.tgz#4db709fc81bc4a8fd7127a458a5346c5cdce2c6b"
lodash.isstring@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
lodash.keys@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
@@ -2660,6 +2718,10 @@ lodash.keys@^3.0.0:
lodash.isarguments "^3.0.0"
lodash.isarray "^3.0.0"
lodash.keys@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205"
lodash.pad@^4.1.0:
version "4.5.1"
resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70"
@@ -2672,10 +2734,18 @@ lodash.padstart@^4.1.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"
lodash.pick@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
lodash.restparam@^3.0.0:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
lodash.some@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
lodash.template@^3.0.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f"
@@ -2697,11 +2767,15 @@ lodash.templatesettings@^3.0.0:
lodash._reinterpolate "^3.0.0"
lodash.escape "^3.0.0"
lodash.union@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
lodash@^3.5.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
lodash@^4.14.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1:
lodash@^4.0.0, lodash@^4.14.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -3107,6 +3181,12 @@ os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
os-locale@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
dependencies:
lcid "^1.0.0"
os-locale@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
@@ -3304,7 +3384,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
prop-types@^15.5.8, prop-types@^15.6.0:
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
dependencies:
@@ -3336,6 +3416,10 @@ qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
random-bytes@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
@@ -3383,6 +3467,13 @@ react-devtools-core@^2.5.0:
shell-quote "^1.6.1"
ws "^2.0.3"
react-native-gesture-handler@^1.0.0-alpha.35:
version "1.0.0-alpha.35"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.0-alpha.35.tgz#c16cf97151223cb8d4902d6dd597dc1612d8cb33"
dependencies:
invariant "^2.2.2"
prop-types "^15.5.10"
react-native-typescript-transformer@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/react-native-typescript-transformer/-/react-native-typescript-transformer-1.1.4.tgz#88bb6d2ccd63f0b4b3cbce99e96c0e9c9e83cabc"
@@ -3391,6 +3482,14 @@ react-native-typescript-transformer@^1.1.4:
jju "^1.3.0"
source-map "^0.5.6"
react-native-vector-icons@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.4.2.tgz#090f42ee0396c4cc4eae0ddaa518028ba8df40c7"
dependencies:
lodash "^4.0.0"
prop-types "^15.5.10"
yargs "^8.0.2"
react-native@^0.51.0:
version "0.51.0"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.51.0.tgz#fe25934b3030fd323f3ca1a70f034133465955ed"
@@ -4356,6 +4455,10 @@ walker@~1.0.5:
dependencies:
makeerror "1.0.x"
warna@^0.2.4:
version "0.2.4"
resolved "https://registry.yarnpkg.com/warna/-/warna-0.2.4.tgz#4c63e3db188f8b5176299526e5f95fc5c2e0dfb0"
watch@~0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
@@ -4392,6 +4495,10 @@ whatwg-url@^4.3.0:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
which-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
@@ -4402,6 +4509,20 @@ which@^1.2.12, which@^1.2.14, which@^1.2.9:
dependencies:
isexe "^2.0.0"
why-did-you-update@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/why-did-you-update/-/why-did-you-update-0.1.0.tgz#e523ff89d879bee4f4a4f7644a0621df9e2e7b76"
dependencies:
lodash.every "^4.6.0"
lodash.filter "^4.6.0"
lodash.isequal "^4.5.0"
lodash.isfunction "^3.0.8"
lodash.isstring "^4.0.1"
lodash.keys "^4.2.0"
lodash.pick "^4.4.0"
lodash.some "^4.6.0"
lodash.union "^4.6.0"
wide-align@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
@@ -4526,6 +4647,12 @@ yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
yargs-parser@^4.2.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
dependencies:
camelcase "^3.0.0"
yargs-parser@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"
@@ -4555,6 +4682,42 @@ yargs@^10.0.3:
y18n "^3.2.1"
yargs-parser "^8.0.0"
yargs@^6.0.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
dependencies:
camelcase "^3.0.0"
cliui "^3.2.0"
decamelize "^1.1.1"
get-caller-file "^1.0.1"
os-locale "^1.4.0"
read-pkg-up "^1.0.1"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^1.0.2"
which-module "^1.0.0"
y18n "^3.2.1"
yargs-parser "^4.2.0"
yargs@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360"
dependencies:
camelcase "^4.1.0"
cliui "^3.2.0"
decamelize "^1.1.1"
get-caller-file "^1.0.1"
os-locale "^2.0.0"
read-pkg-up "^2.0.0"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^2.0.0"
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^7.0.0"
yargs@^9.0.0:
version "9.0.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c"