From 58896ae0fa87208d30b96d56cf5bb9bfc1bf952e Mon Sep 17 00:00:00 2001 From: Bruno Lemos Date: Wed, 13 Dec 2017 16:29:36 -0200 Subject: [PATCH] Basic static card component with swipeable rows --- android/.project | 17 + .../org.eclipse.buildship.core.prefs | 2 + android/app/.classpath | 6 + android/app/.project | 23 ++ .../org.eclipse.buildship.core.prefs | 2 + android/app/build.gradle | 2 + .../src/main/assets/fonts/MaterialIcons.ttf | Bin 0 -> 128180 bytes .../app/src/main/assets/fonts/Octicons.ttf | Bin 0 -> 27512 bytes .../main/java/com/devhub/MainActivity.java | 13 + .../main/java/com/devhub/MainApplication.java | 6 +- android/settings.gradle | 4 + index.js | 8 + ios/devhub.xcodeproj/project.pbxproj | 325 +++++++++++++++++- ios/devhub/Base.lproj/LaunchScreen.xib | 35 +- ios/devhub/Info.plist | 40 ++- package.json | 24 +- src/components/cards/NotificationCard.tsx | 11 + src/components/cards/NotificationCards.tsx | 36 ++ src/components/cards/partials/Card.tsx | 28 ++ src/components/cards/partials/CardHeader.tsx | 58 ++++ src/components/cards/partials/CardIcon.tsx | 21 ++ .../cards/partials/CardItemSeparator.tsx | 17 + .../cards/partials/SwipeableCard.tsx | 37 ++ .../cards/partials/rows/RepositoryRow.tsx | 30 ++ src/components/cards/partials/rows/styles.ts | 32 ++ src/components/cards/styles.ts | 46 +++ src/components/common/Avatar.tsx | 48 +++ src/components/common/Screen.tsx | 24 ++ .../screens/NotificationsScreen.tsx | 12 + src/containers/NotificationCardsContainer.tsx | 15 + src/index.tsx | 45 +-- src/libs/platform/index.ts | 10 + src/libs/platform/index.web.ts | 21 ++ src/libs/swipeable/AppleSwipeableRow.tsx | 140 ++++++++ src/libs/swipeable/BaseSwipeableRow.tsx | 109 ++++++ src/libs/swipeable/GoogleSwipeableRow.tsx | 138 ++++++++ src/libs/swipeable/index.android.tsx | 3 + src/libs/swipeable/index.ios.tsx | 3 + src/styles/themes/base.ts | 20 ++ src/styles/themes/dark-blue.ts | 60 ++++ src/styles/themes/dark.ts | 62 ++++ src/styles/themes/index.ts | 13 + src/styles/themes/light.ts | 59 ++++ src/styles/variables.ts | 6 + src/utils/helpers/color.ts | 8 + src/utils/helpers/github.ts | 28 ++ src/utils/helpers/shared.ts | 13 + src/utils/types.ts | 9 + tslint.json | 17 +- yarn.lock | 167 ++++++++- 50 files changed, 1756 insertions(+), 97 deletions(-) create mode 100644 android/.project create mode 100644 android/.settings/org.eclipse.buildship.core.prefs create mode 100644 android/app/.classpath create mode 100644 android/app/.project create mode 100644 android/app/.settings/org.eclipse.buildship.core.prefs create mode 100644 android/app/src/main/assets/fonts/MaterialIcons.ttf create mode 100644 android/app/src/main/assets/fonts/Octicons.ttf create mode 100644 src/components/cards/NotificationCard.tsx create mode 100644 src/components/cards/NotificationCards.tsx create mode 100644 src/components/cards/partials/Card.tsx create mode 100644 src/components/cards/partials/CardHeader.tsx create mode 100644 src/components/cards/partials/CardIcon.tsx create mode 100644 src/components/cards/partials/CardItemSeparator.tsx create mode 100644 src/components/cards/partials/SwipeableCard.tsx create mode 100644 src/components/cards/partials/rows/RepositoryRow.tsx create mode 100644 src/components/cards/partials/rows/styles.ts create mode 100644 src/components/cards/styles.ts create mode 100644 src/components/common/Avatar.tsx create mode 100644 src/components/common/Screen.tsx create mode 100644 src/components/screens/NotificationsScreen.tsx create mode 100644 src/containers/NotificationCardsContainer.tsx create mode 100755 src/libs/platform/index.ts create mode 100755 src/libs/platform/index.web.ts create mode 100644 src/libs/swipeable/AppleSwipeableRow.tsx create mode 100644 src/libs/swipeable/BaseSwipeableRow.tsx create mode 100644 src/libs/swipeable/GoogleSwipeableRow.tsx create mode 100644 src/libs/swipeable/index.android.tsx create mode 100644 src/libs/swipeable/index.ios.tsx create mode 100755 src/styles/themes/base.ts create mode 100755 src/styles/themes/dark-blue.ts create mode 100755 src/styles/themes/dark.ts create mode 100755 src/styles/themes/index.ts create mode 100755 src/styles/themes/light.ts create mode 100644 src/styles/variables.ts create mode 100644 src/utils/helpers/color.ts create mode 100644 src/utils/helpers/github.ts create mode 100644 src/utils/helpers/shared.ts create mode 100644 src/utils/types.ts diff --git a/android/.project b/android/.project new file mode 100644 index 00000000..e2c3953d --- /dev/null +++ b/android/.project @@ -0,0 +1,17 @@ + + + devhub + Project devhub created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..226c8b48 --- /dev/null +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +#Wed Dec 13 00:16:04 BRST 2017 +connection.project.dir= diff --git a/android/app/.classpath b/android/app/.classpath new file mode 100644 index 00000000..c93a0ddb --- /dev/null +++ b/android/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/app/.project b/android/app/.project new file mode 100644 index 00000000..ac485d7c --- /dev/null +++ b/android/app/.project @@ -0,0 +1,23 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/app/.settings/org.eclipse.buildship.core.prefs b/android/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..c82c70a2 --- /dev/null +++ b/android/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +#Wed Dec 13 00:16:04 BRST 2017 +connection.project.dir=.. diff --git a/android/app/build.gradle b/android/app/build.gradle index ec801946..48a497d9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -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 diff --git a/android/app/src/main/assets/fonts/MaterialIcons.ttf b/android/app/src/main/assets/fonts/MaterialIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7015564ad166a3e9d88c82f17829f0cc01ebe29a GIT binary patch literal 128180 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 ohyj3!`#ee%L;DTjx@8!5k5~VH0QmdE^#A|> literal 0 HcmV?d00001 diff --git a/android/app/src/main/assets/fonts/Octicons.ttf b/android/app/src/main/assets/fonts/Octicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..09e2b2d79c370d9370a772b3542acdfca66ed634 GIT binary patch literal 27512 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 getPackages() { return Arrays.asList( - new MainReactPackage() + new MainReactPackage(), + new RNGestureHandlerPackage(), + new VectorIconsPackage() ); } diff --git a/android/settings.gradle b/android/settings.gradle index 21c2ce3a..6a1901f3 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -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' diff --git a/index.js b/index.js index 4f753ce4..e6a938a6 100644 --- a/index.js +++ b/index.js @@ -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) diff --git a/ios/devhub.xcodeproj/project.pbxproj b/ios/devhub.xcodeproj/project.pbxproj index bdddb3c4..17be48b5 100644 --- a/ios/devhub.xcodeproj/project.pbxproj +++ b/ios/devhub.xcodeproj/project.pbxproj @@ -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 = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = devhub/main.m; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; 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 = ""; }; + 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 = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 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 = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + 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 = ""; }; + 8888F60F6C304A58BF18E9E8 /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = ""; }; + 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 = ""; }; ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; + B5DF78792708477FB2343101 /* libRNGestureHandler.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNGestureHandler.a; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; + 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 = ""; }; /* 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 = ""; @@ -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 = ""; + }; + 2EAFEE951FDDD3E8000A9A11 /* Recovered References */ = { + isa = PBXGroup; + children = ( + 8888F60F6C304A58BF18E9E8 /* libRNVectorIcons.a */, + B5DF78792708477FB2343101 /* libRNGestureHandler.a */, + ); + name = "Recovered References"; + sourceTree = ""; + }; + 2EAFEEB11FDDD3EA000A9A11 /* Products */ = { + isa = PBXGroup; + children = ( + 2EAFEEB51FDDD3EA000A9A11 /* libRNVectorIcons.a */, + ); + name = Products; + sourceTree = ""; + }; + 2EAFF5891FE0C469000A9A11 /* Products */ = { + isa = PBXGroup; + children = ( + 2EAFF58D1FE0C469000A9A11 /* libRNGestureHandler.a */, ); name = Products; sourceTree = ""; @@ -431,7 +562,7 @@ isa = PBXGroup; children = ( 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */, + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, ); name = Products; sourceTree = ""; @@ -460,6 +591,8 @@ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, + B6BF65C496E44E78BF211275 /* RNVectorIcons.xcodeproj */, + 1FD65CD116F747ACA2D47E1F /* RNGestureHandler.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -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 = ""; @@ -497,10 +633,29 @@ name = Products; sourceTree = ""; }; + 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 = ""; + }; ADBDB9201DFEBF0600ED6528 /* Products */ = { isa = PBXGroup; children = ( ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, + 2EAFEE9C1FDDD3E9000A9A11 /* libRCTBlob-tvOS.a */, ); name = Products; sourceTree = ""; @@ -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; diff --git a/ios/devhub/Base.lproj/LaunchScreen.xib b/ios/devhub/Base.lproj/LaunchScreen.xib index 129e5a84..0c768622 100644 --- a/ios/devhub/Base.lproj/LaunchScreen.xib +++ b/ios/devhub/Base.lproj/LaunchScreen.xib @@ -1,9 +1,12 @@ - - + + + + + - - + + @@ -11,29 +14,7 @@ - - - - - - - - - - - - - + diff --git a/ios/devhub/Info.plist b/ios/devhub/Info.plist index f93d1bc9..0e9efe61 100644 --- a/ios/devhub/Info.plist +++ b/ios/devhub/Info.plist @@ -24,24 +24,7 @@ 1 LSRequiresIPhoneOS - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - NSLocationWhenInUseUsageDescription - NSAppTransportSecurity - NSExceptionDomains @@ -52,5 +35,28 @@ + NSLocationWhenInUseUsageDescription + + UIAppFonts + + MaterialIcons.ttf + Octicons.ttf + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarStyle + UIStatusBarStyleLightContent + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + diff --git a/package.json b/package.json index 49b25fd9..d27d7410 100644 --- a/package.json +++ b/package.json @@ -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?)$": "/node_modules/babel-jest", "^.+\\.(tsx?)$": "/node_modules/ts-jest/preprocessor.js" }, "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "testPathIgnorePatterns": ["/node_modules/", "/.history/"], + "testPathIgnorePatterns": [ + "/node_modules/", + "/.history/" + ], "cacheDirectory": ".jest/cache" } } diff --git a/src/components/cards/NotificationCard.tsx b/src/components/cards/NotificationCard.tsx new file mode 100644 index 00000000..742ca894 --- /dev/null +++ b/src/components/cards/NotificationCard.tsx @@ -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) => + +export default NotificationCard diff --git a/src/components/cards/NotificationCards.tsx b/src/components/cards/NotificationCards.tsx new file mode 100644 index 00000000..73b8993b --- /dev/null +++ b/src/components/cards/NotificationCards.tsx @@ -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 { + keyExtractor(notification: INotification) { + return notification.id + } + + renderItem({ item: { actor: { username } } }: { item: INotification }) { + return + } + + render() { + const { notifications } = this.props + return ( + + ) + } +} + +export default NotificationCards diff --git a/src/components/cards/partials/Card.tsx b/src/components/cards/partials/Card.tsx new file mode 100644 index 00000000..b8e36ace --- /dev/null +++ b/src/components/cards/partials/Card.tsx @@ -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) => ( + + + + +) + +export default Card diff --git a/src/components/cards/partials/CardHeader.tsx b/src/components/cards/partials/CardHeader.tsx new file mode 100644 index 00000000..8f5062f0 --- /dev/null +++ b/src/components/cards/partials/CardHeader.tsx @@ -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) => ( + + + + + + + + + + {username} +  • 2h (13:59) + + + starred a repository + + + + + + +) + +export default CardHeader diff --git a/src/components/cards/partials/CardIcon.tsx b/src/components/cards/partials/CardIcon.tsx new file mode 100644 index 00000000..950a40b0 --- /dev/null +++ b/src/components/cards/partials/CardIcon.tsx @@ -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 +} + +export default CardIcon diff --git a/src/components/cards/partials/CardItemSeparator.tsx b/src/components/cards/partials/CardItemSeparator.tsx new file mode 100644 index 00000000..a932c253 --- /dev/null +++ b/src/components/cards/partials/CardItemSeparator.tsx @@ -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 = () => + +export default CardItemSeparator diff --git a/src/components/cards/partials/SwipeableCard.tsx b/src/components/cards/partials/SwipeableCard.tsx new file mode 100644 index 00000000..9d591201 --- /dev/null +++ b/src/components/cards/partials/SwipeableCard.tsx @@ -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) => ( + {}, + }, + ]} + rightActions={[ + { + type: 'FULL', + key: 'archive', + icon: 'archive', + color: '#497AFC', + label: 'Archive', + onPress: () => {}, + }, + ]} + > + + +) + +export default SwipeableCard diff --git a/src/components/cards/partials/rows/RepositoryRow.tsx b/src/components/cards/partials/rows/RepositoryRow.tsx new file mode 100644 index 00000000..ed041c69 --- /dev/null +++ b/src/components/cards/partials/rows/RepositoryRow.tsx @@ -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) => ( + + + + + + + + {repository} +  {owner} + + + +) + +export default RepositoryRow diff --git a/src/components/cards/partials/rows/styles.ts b/src/components/cards/partials/rows/styles.ts new file mode 100644 index 00000000..64c0442d --- /dev/null +++ b/src/components/cards/partials/rows/styles.ts @@ -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, +}) diff --git a/src/components/cards/styles.ts b/src/components/cards/styles.ts new file mode 100644 index 00000000..d5e5eb51 --- /dev/null +++ b/src/components/cards/styles.ts @@ -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, +}) diff --git a/src/components/common/Avatar.tsx b/src/components/common/Avatar.tsx new file mode 100644 index 00000000..edfd007c --- /dev/null +++ b/src/components/common/Avatar.tsx @@ -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 ( + + ) +} + +export default Avatar diff --git a/src/components/common/Screen.tsx b/src/components/common/Screen.tsx new file mode 100644 index 00000000..8bb70b02 --- /dev/null +++ b/src/components/common/Screen.tsx @@ -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) => ( + +) + +export default Screen diff --git a/src/components/screens/NotificationsScreen.tsx b/src/components/screens/NotificationsScreen.tsx new file mode 100644 index 00000000..15a345f8 --- /dev/null +++ b/src/components/screens/NotificationsScreen.tsx @@ -0,0 +1,12 @@ +import React from 'react' + +import NotificationCardsContainer from '../../containers/NotificationCardsContainer' +import Screen from '../common/Screen' + +const NotificationsScreen = () => ( + + + +) + +export default NotificationsScreen diff --git a/src/containers/NotificationCardsContainer.tsx b/src/containers/NotificationCardsContainer.tsx new file mode 100644 index 00000000..329ba304 --- /dev/null +++ b/src/containers/NotificationCardsContainer.tsx @@ -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 = () => + +export default NotificationCardsContainer diff --git a/src/index.tsx b/src/index.tsx index 31cb2159..84eba37f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -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 { - render() { - return ( - - Welcome to React Native - To get started, edit index.js - Using Typescript - - ) - } -} +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 () => ( + + + + +) diff --git a/src/libs/platform/index.ts b/src/libs/platform/index.ts new file mode 100755 index 00000000..86e90b1e --- /dev/null +++ b/src/libs/platform/index.ts @@ -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 diff --git a/src/libs/platform/index.web.ts b/src/libs/platform/index.web.ts new file mode 100755 index 00000000..902a7386 --- /dev/null +++ b/src/libs/platform/index.web.ts @@ -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 diff --git a/src/libs/swipeable/AppleSwipeableRow.tsx b/src/libs/swipeable/AppleSwipeableRow.tsx new file mode 100644 index 00000000..5fcab003 --- /dev/null +++ b/src/libs/swipeable/AppleSwipeableRow.tsx @@ -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 ( + + + + {action.label} + + + + ) + } + + 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 ( + + + {action.label} + + + ) + } + + render() { + const { children, ...props } = this.props + + return ( + + {children} + + ) + } +} + +const styles = StyleSheet.create({ + actionText: { + backgroundColor: 'transparent', + fontSize: 16, + padding: 10, + }, + baseActionContainer: { + flex: 1, + justifyContent: 'center', + }, +}) diff --git a/src/libs/swipeable/BaseSwipeableRow.tsx b/src/libs/swipeable/BaseSwipeableRow.tsx new file mode 100644 index 00000000..494f7b47 --- /dev/null +++ b/src/libs/swipeable/BaseSwipeableRow.tsx @@ -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 { + _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 ( + + {buttonActions.map(action => { + x += action.width || defaultWidth + return this.renderButtonAction(action, { placement: 'LEFT', progress, x }) + })} + + ) + } + + 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 ( + + {buttonActions.map(action => { + const component = this.renderButtonAction(action, { + dragX, + placement: 'RIGHT', + progress, + x, + }) + x -= action.width || defaultWidth + return component + })} + + ) + } + + updateRef = ref => { + this._swipeableRow = ref + } + + close = () => { + this._swipeableRow.close() + } + + render() { + throw new Error('Not implemented: render') + } +} diff --git a/src/libs/swipeable/GoogleSwipeableRow.tsx b/src/libs/swipeable/GoogleSwipeableRow.tsx new file mode 100644 index 00000000..295c60cf --- /dev/null +++ b/src/libs/swipeable/GoogleSwipeableRow.tsx @@ -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 ( + + + + ) + } + + 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 ( + + + + ) + } + + render() { + const { children, ...props } = this.props + + return ( + + {children} + + ) + } +} + +const styles = StyleSheet.create({ + actionIcon: { + backgroundColor: 'transparent', + marginHorizontal: 10, + width: 30, + }, + baseActionContainer: { + flex: 1, + justifyContent: 'center', + }, +}) diff --git a/src/libs/swipeable/index.android.tsx b/src/libs/swipeable/index.android.tsx new file mode 100644 index 00000000..ea73bc8f --- /dev/null +++ b/src/libs/swipeable/index.android.tsx @@ -0,0 +1,3 @@ +import GoogleSwipeableRow from './GoogleSwipeableRow' + +export default GoogleSwipeableRow diff --git a/src/libs/swipeable/index.ios.tsx b/src/libs/swipeable/index.ios.tsx new file mode 100644 index 00000000..115aa9bb --- /dev/null +++ b/src/libs/swipeable/index.ios.tsx @@ -0,0 +1,3 @@ +import AppleSwipeableRow from './AppleSwipeableRow' + +export default AppleSwipeableRow diff --git a/src/styles/themes/base.ts b/src/styles/themes/base.ts new file mode 100755 index 00000000..40a44988 --- /dev/null +++ b/src/styles/themes/base.ts @@ -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' diff --git a/src/styles/themes/dark-blue.ts b/src/styles/themes/dark-blue.ts new file mode 100755 index 00000000..a842b8ba --- /dev/null +++ b/src/styles/themes/dark-blue.ts @@ -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', +} diff --git a/src/styles/themes/dark.ts b/src/styles/themes/dark.ts new file mode 100755 index 00000000..3572c9d0 --- /dev/null +++ b/src/styles/themes/dark.ts @@ -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', +} diff --git a/src/styles/themes/index.ts b/src/styles/themes/index.ts new file mode 100755 index 00000000..2c484232 --- /dev/null +++ b/src/styles/themes/index.ts @@ -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, +} diff --git a/src/styles/themes/light.ts b/src/styles/themes/light.ts new file mode 100755 index 00000000..bfc9a38c --- /dev/null +++ b/src/styles/themes/light.ts @@ -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', +} diff --git a/src/styles/variables.ts b/src/styles/variables.ts new file mode 100644 index 00000000..20c32d3e --- /dev/null +++ b/src/styles/variables.ts @@ -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 diff --git a/src/utils/helpers/color.ts b/src/utils/helpers/color.ts new file mode 100644 index 00000000..cf8a1779 --- /dev/null +++ b/src/utils/helpers/color.ts @@ -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})` +} diff --git a/src/utils/helpers/github.ts b/src/utils/helpers/github.ts new file mode 100644 index 00000000..a7159d0e --- /dev/null +++ b/src/utils/helpers/github.ts @@ -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('??', '?') +} diff --git a/src/utils/helpers/shared.ts b/src/utils/helpers/shared.ts new file mode 100644 index 00000000..b04541a7 --- /dev/null +++ b/src/utils/helpers/shared.ts @@ -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 +} diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 00000000..ccd6e335 --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,9 @@ +export interface IUser { + id: string + username: string +} + +export interface INotification { + id: string + actor: IUser +} diff --git a/tslint.json b/tslint.json index 3975e899..e9f120a9 100644 --- a/tslint.json +++ b/tslint.json @@ -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": [] } diff --git a/yarn.lock b/yarn.lock index 144b6baa..984a33ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"