diff --git a/RootNavigationContainer.js b/RootNavigationContainer.js
index 5b155d86..2030f387 100644
--- a/RootNavigationContainer.js
+++ b/RootNavigationContainer.js
@@ -1,10 +1,10 @@
import React from 'react';
-import { View, Dimensions, Easing, Animated } from 'react-native';
+import { View, Platform } from 'react-native';
import { Root } from 'native-base';
import { createSwitchNavigator, createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
+import NavigationAnimation from "./src/helpers/NavigationAnimation";
import { createBottomTabNavigator } from 'react-navigation-tabs';
-import deepGet from 'lodash/get';
import NavigationService from './src/services/NavigationService';
import AuthLoading from './src/components/AuthLoading';
@@ -39,6 +39,7 @@ import { NotificationToastComponent } from './src/theme/components/NotificationT
import SocketManager from './src/services/SocketManager';
import SearchScreen from './src/components/Search';
import FanVideoDetails from './src/components/FanVideoDetails';
+import FanVideoReplyDetails from './src/components/FanVideoReplyDetails';
import WalletSettingScreen from './src/components/WalletSetting';
import StoreProductsScreen from './src/components/StoreProducts';
import PaymentWorker from './src/components/PaymentWorker';
@@ -56,14 +57,24 @@ import CouchMarks from './src/components/CouchMarks';
import RedemptiomScreen from './src/components/Redemption';
import VideoTags from './src/components/VideoTags';
import FullScreenVideoCollection from './src/components/FullScreenVideoCollection';
+import VideoReplies from './src/components/VideoReplies';
+import FullScreenReplyCollection from './src/components/FullScreenReplyCollection';
+import VideoReplyPlayer from './src/components/CommonComponents/VideoReplyPlayer';
const customTabHiddenRoutes = [
'CaptureVideo',
'FanVideoDetails',
+ 'FanVideoReplyDetails',
'InviteCodeScreen',
'AddEmailScreen',
'InAppBrowserComponent',
- 'CouchMarks'
+ 'CouchMarks',
+ 'VideoReplies',
+ 'FullScreenReplyCollection',
+ 'FullScreenVideoCollection',
+ 'UserVideoHistory',
+ 'VideoPlayer',
+ 'VideoReplyPlayer'
];
const modalStackConfig = {
@@ -80,38 +91,44 @@ const modalStackConfig = {
const txModalConfig = {
transparentCard: true,
- cardStyle: { backgroundColor: 'rgba(0,0,0,0.5)' },
+ cardStyle: { backgroundColor: 'rgba(0,0,0,0)' },
gesturesEnabled: false,
- transitionConfig: () => ({
- transitionSpec: {
- duration: 300,
- easing: Easing.out(Easing.poly(4)),
- timing: Animated.timing
- },
- screenInterpolator: (sceneProps) => {
- const { layout, position, scene } = sceneProps;
- const { index } = scene;
+ transitionConfig: (transitionProps, prevTransitionProps) => {
+ return NavigationAnimation.defaultTransition();
+ }
+};
- const height = layout.initHeight;
- const translateY = position.interpolate({
- inputRange: [index - 1, index, index + 1],
- outputRange: [height, 0, 0]
- });
+const cardStackConfig = {
+ transparentCard: true,
+ cardStyle: { backgroundColor: 'rgba(0,0,0,0)' },
+ transitionConfig: ( transitionProps, prevTransitionProps ) => {
+ const scenes = transitionProps["scenes"];
+ const prevScene = scenes[scenes.length - 2];
+ const nextScene = scenes[scenes.length - 1];
- const opacity = position.interpolate({
- inputRange: [index - 1, index - 0.99, index],
- outputRange: [0, 1, 1]
- });
+ if (nextScene.route.routeName === 'VideoReplies') {
+ return NavigationAnimation.fromBottom();
+ }
- return { opacity, transform: [{ translateY }] };
+ if(Platform.OS == "ios"){
+ if (prevScene
+ && prevScene.route.routeName === 'VideoReplies'
+ && nextScene.route.routeName === 'FullScreenReplyCollection') {
+ return NavigationAnimation.fromBottom();
+ }
}
- })
-};
+
+ }
+}
+
const CaptureVideoStack = createStackNavigator(
{
CaptureVideo: CaptureVideo,
- FanVideoDetails: FanVideoDetails
+ FanVideoDetails: FanVideoDetails,
+ FanVideoReplyDetails: FanVideoReplyDetails,
+ WalletSettingScreen: WalletSettingScreen,
+ WalletDetails: WalletDetails
},
{
headerLayoutPreset: 'center'
@@ -134,11 +151,19 @@ const HomePushStack = createStackNavigator(
UserVideoHistory: UserVideoHistory,
SupportingListScreen: SupportingListScreen,
SupportersListScreen: SupportersListScreen,
+ VideoPlayer: VideoPlayer,
+ VideoReplyPlayer: VideoReplyPlayer,
VideoTags: VideoTags,
- FullScreenVideoCollection: FullScreenVideoCollection
+ WalletSettingScreen: WalletSettingScreen,
+ WalletDetails: WalletDetails,
+ FullScreenVideoCollection: FullScreenVideoCollection,
+ VideoReplies:VideoReplies ,
+ FullScreenReplyCollection: FullScreenReplyCollection
},
{
- headerLayoutPreset: 'center'
+ initialRouteName: 'HomeScreen',
+ headerLayoutPreset: 'center' ,
+ ...cardStackConfig
}
);
@@ -166,13 +191,19 @@ const NotificationPushStack = createStackNavigator(
UsersProfileScreen: UsersProfileScreen,
UserVideoHistory: UserVideoHistory,
VideoPlayer: VideoPlayer,
+ VideoReplyPlayer: VideoReplyPlayer,
SupportingListScreen: SupportingListScreen,
SupportersListScreen: SupportersListScreen,
VideoTags: VideoTags,
- FullScreenVideoCollection: FullScreenVideoCollection
+ WalletSettingScreen: WalletSettingScreen,
+ WalletDetails: WalletDetails,
+ FullScreenVideoCollection: FullScreenVideoCollection,
+ VideoReplies:VideoReplies ,
+ FullScreenReplyCollection: FullScreenReplyCollection
},
{
- headerLayoutPreset: 'center'
+ headerLayoutPreset: 'center',
+ ...cardStackConfig
}
);
@@ -199,14 +230,19 @@ const ProfilePushStack = createStackNavigator(
BioScreen: BioScreen,
EmailScreen: EmailScreen,
ReferAndEarn: ReferAndEarn,
+ VideoPlayer: VideoPlayer,
+ VideoReplyPlayer: VideoReplyPlayer,
Invites: Invites,
WalletSettingScreen: WalletSettingScreen,
WalletDetails: WalletDetails,
VideoTags: VideoTags,
- FullScreenVideoCollection: FullScreenVideoCollection
+ FullScreenVideoCollection: FullScreenVideoCollection,
+ VideoReplies:VideoReplies ,
+ FullScreenReplyCollection: FullScreenReplyCollection
},
{
- headerLayoutPreset: 'center'
+ headerLayoutPreset: 'center',
+ ...cardStackConfig
}
);
@@ -222,17 +258,7 @@ const ProfileStack = createStackNavigator(
StoreProductsScreen: StoreProductsScreen,
RedemptiomScreen: RedemptiomScreen
},
- {
- headerLayoutPreset: 'center',
- headerMode: 'none',
- mode: 'modal',
- navigationOptions: ({ navigation }) => {
- return {
- tabBarVisible: deepGet(navigation, 'state.index') === 0
- };
- },
- ...txModalConfig
- }
+ { ...modalStackConfig, ...txModalConfig }
);
const SearchPushStack = createStackNavigator(
@@ -242,11 +268,18 @@ const SearchPushStack = createStackNavigator(
SupportingListScreen: SupportingListScreen,
SupportersListScreen: SupportersListScreen,
UserVideoHistory: UserVideoHistory,
+ VideoPlayer: VideoPlayer,
+ VideoReplyPlayer: VideoReplyPlayer,
VideoTags: VideoTags,
- FullScreenVideoCollection: FullScreenVideoCollection
+ WalletSettingScreen: WalletSettingScreen,
+ WalletDetails: WalletDetails,
+ FullScreenVideoCollection: FullScreenVideoCollection,
+ VideoReplies:VideoReplies ,
+ FullScreenReplyCollection: FullScreenReplyCollection,
},
{
- headerLayoutPreset: 'center'
+ headerLayoutPreset: 'center',
+ ...cardStackConfig
}
);
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9a553b9c..1e055172 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -126,8 +126,8 @@ android {
applicationId "com.pepo.staging"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 19
- versionName "0.9.6"
+ versionCode 20
+ versionName "1.0.0"
missingDimensionStrategy 'react-native-camera', 'general'
}
splits {
diff --git a/index.js b/index.js
index 83b27449..226255de 100644
--- a/index.js
+++ b/index.js
@@ -1,7 +1,6 @@
/**
* @format
*/
-import * as foo from "./src/helpers/Logger";
import { AppRegistry } from 'react-native';
import AppContainer from './AppContainer';
import { name as appName } from './app.json';
diff --git a/ios/Cartfile b/ios/Cartfile
index 6ad59fcb..50d55200 100644
--- a/ios/Cartfile
+++ b/ios/Cartfile
@@ -1 +1 @@
-github "ostdotcom/ost-wallet-sdk-ios" == 2.3.4
+github "ostdotcom/ost-wallet-sdk-ios" == 2.3.5
diff --git a/ios/Pepo2.xcodeproj/project.pbxproj b/ios/Pepo2.xcodeproj/project.pbxproj
index 53da8e0c..3c15fe5c 100644
--- a/ios/Pepo2.xcodeproj/project.pbxproj
+++ b/ios/Pepo2.xcodeproj/project.pbxproj
@@ -5,7 +5,6 @@
};
objectVersion = 46;
objects = {
-
/* Begin PBXBuildFile section */
00029B4323329B55009E6919 /* TrustKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B76D86A2318FAAC007316D4 /* TrustKit.framework */; };
00029B4423329B63009E6919 /* OstWalletSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0050FDA022A8226800C2634F /* OstWalletSdk.framework */; };
@@ -2314,7 +2313,7 @@
"$(inherited)",
"\"$(SRCROOT)/Pepo2\"",
);
- MARKETING_VERSION = 0.9.7;
+ MARKETING_VERSION = 1.0.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -2377,7 +2376,7 @@
"$(inherited)",
"\"$(SRCROOT)/Pepo2\"",
);
- MARKETING_VERSION = 0.9.7;
+ MARKETING_VERSION = 1.0.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
diff --git a/ios/Pepo2/AppDelegate.m b/ios/Pepo2/AppDelegate.m
index 0920b269..4bd3bbec 100644
--- a/ios/Pepo2/AppDelegate.m
+++ b/ios/Pepo2/AppDelegate.m
@@ -146,6 +146,7 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N
restorationHandler:restorationHandler];
return handled;
+
}
diff --git a/ios/Pepo2/InfoPlist/com.pepo.staging-Info.plist b/ios/Pepo2/InfoPlist/com.pepo.staging-Info.plist
index e0f6f95d..37629cd6 100644
--- a/ios/Pepo2/InfoPlist/com.pepo.staging-Info.plist
+++ b/ios/Pepo2/InfoPlist/com.pepo.staging-Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.9.7
+ 1.0.0
CFBundleSignature
????
CFBundleURLTypes
diff --git a/ios/Pepo2/InfoPlist/com.pepo.v2.production-Info.plist b/ios/Pepo2/InfoPlist/com.pepo.v2.production-Info.plist
index 1b3349e1..7c27f3fa 100644
--- a/ios/Pepo2/InfoPlist/com.pepo.v2.production-Info.plist
+++ b/ios/Pepo2/InfoPlist/com.pepo.v2.production-Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.9.7
+ 1.0.0
CFBundleSignature
????
CFBundleURLTypes
diff --git a/ios/Pepo2/InfoPlist/com.pepo.v2.sandbox-Info.plist b/ios/Pepo2/InfoPlist/com.pepo.v2.sandbox-Info.plist
index daf3861c..7d1e6a53 100644
--- a/ios/Pepo2/InfoPlist/com.pepo.v2.sandbox-Info.plist
+++ b/ios/Pepo2/InfoPlist/com.pepo.v2.sandbox-Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.9.7
+ 1.0.0
CFBundleSignature
????
CFBundleURLTypes
diff --git a/package-lock.json b/package-lock.json
index 842076a8..93f5ac3e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -35,11 +35,11 @@
}
},
"@babel/generator": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz",
- "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz",
+ "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==",
"requires": {
- "@babel/types": "^7.7.2",
+ "@babel/types": "^7.7.4",
"jsesc": "^2.5.1",
"lodash": "^4.17.13",
"source-map": "^0.5.0"
@@ -53,70 +53,70 @@
}
},
"@babel/helper-annotate-as-pure": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz",
- "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz",
+ "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz",
- "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz",
+ "integrity": "sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ==",
"requires": {
- "@babel/helper-explode-assignable-expression": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/helper-explode-assignable-expression": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-builder-react-jsx": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.0.tgz",
- "integrity": "sha512-LSln3cexwInTMYYoFeVLKnYPPMfWNJ8PubTBs3hkh7wCu9iBaqq1OOyW+xGmEdLxT1nhsl+9SJ+h2oUDYz0l2A==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz",
+ "integrity": "sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA==",
"requires": {
- "@babel/types": "^7.7.0",
+ "@babel/types": "^7.7.4",
"esutils": "^2.0.0"
}
},
"@babel/helper-call-delegate": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz",
- "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz",
+ "integrity": "sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA==",
"requires": {
- "@babel/helper-hoist-variables": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/helper-hoist-variables": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.0.tgz",
- "integrity": "sha512-MZiB5qvTWoyiFOgootmRSDV1udjIqJW/8lmxgzKq6oDqxdmHUjeP2ZUOmgHdYjmUVNABqRrHjYAYRvj8Eox/UA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz",
+ "integrity": "sha512-l+OnKACG4uiDHQ/aJT8dwpR+LhCJALxL0mJ6nzjB25e5IPwqV1VOsY7ah6UB1DG+VOXAIMtuC54rFJGiHkxjgA==",
"requires": {
- "@babel/helper-function-name": "^7.7.0",
- "@babel/helper-member-expression-to-functions": "^7.7.0",
- "@babel/helper-optimise-call-expression": "^7.7.0",
+ "@babel/helper-function-name": "^7.7.4",
+ "@babel/helper-member-expression-to-functions": "^7.7.4",
+ "@babel/helper-optimise-call-expression": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-replace-supers": "^7.7.0",
- "@babel/helper-split-export-declaration": "^7.7.0"
+ "@babel/helper-replace-supers": "^7.7.4",
+ "@babel/helper-split-export-declaration": "^7.7.4"
}
},
"@babel/helper-create-regexp-features-plugin": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz",
- "integrity": "sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz",
+ "integrity": "sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A==",
"requires": {
"@babel/helper-regex": "^7.4.4",
"regexpu-core": "^4.6.0"
}
},
"@babel/helper-define-map": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz",
- "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz",
+ "integrity": "sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg==",
"requires": {
- "@babel/helper-function-name": "^7.7.0",
- "@babel/types": "^7.7.0",
+ "@babel/helper-function-name": "^7.7.4",
+ "@babel/types": "^7.7.4",
"lodash": "^4.17.13"
},
"dependencies": {
@@ -128,66 +128,66 @@
}
},
"@babel/helper-explode-assignable-expression": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz",
- "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz",
+ "integrity": "sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg==",
"requires": {
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-function-name": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz",
- "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
+ "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
"requires": {
- "@babel/helper-get-function-arity": "^7.7.0",
- "@babel/template": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/helper-get-function-arity": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-get-function-arity": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz",
- "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
+ "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-hoist-variables": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz",
- "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz",
+ "integrity": "sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz",
- "integrity": "sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz",
+ "integrity": "sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-module-imports": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz",
- "integrity": "sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz",
+ "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-module-transforms": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz",
- "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==",
- "requires": {
- "@babel/helper-module-imports": "^7.7.0",
- "@babel/helper-simple-access": "^7.7.0",
- "@babel/helper-split-export-declaration": "^7.7.0",
- "@babel/template": "^7.7.0",
- "@babel/types": "^7.7.0",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.4.tgz",
+ "integrity": "sha512-ehGBu4mXrhs0FxAqN8tWkzF8GSIGAiEumu4ONZ/hD9M88uHcD+Yu2ttKfOCgwzoesJOJrtQh7trI5YPbRtMmnA==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.7.4",
+ "@babel/helper-simple-access": "^7.7.4",
+ "@babel/helper-split-export-declaration": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/types": "^7.7.4",
"lodash": "^4.17.13"
},
"dependencies": {
@@ -199,11 +199,11 @@
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz",
- "integrity": "sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz",
+ "integrity": "sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-plugin-utils": {
@@ -227,64 +227,64 @@
}
},
"@babel/helper-remap-async-to-generator": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz",
- "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz",
+ "integrity": "sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.7.0",
- "@babel/helper-wrap-function": "^7.7.0",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/helper-annotate-as-pure": "^7.7.4",
+ "@babel/helper-wrap-function": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-replace-supers": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz",
- "integrity": "sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz",
+ "integrity": "sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==",
"requires": {
- "@babel/helper-member-expression-to-functions": "^7.7.0",
- "@babel/helper-optimise-call-expression": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/helper-member-expression-to-functions": "^7.7.4",
+ "@babel/helper-optimise-call-expression": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-simple-access": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz",
- "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz",
+ "integrity": "sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A==",
"requires": {
- "@babel/template": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/template": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-split-export-declaration": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz",
- "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
+ "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
"requires": {
- "@babel/types": "^7.7.0"
+ "@babel/types": "^7.7.4"
}
},
"@babel/helper-wrap-function": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz",
- "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz",
+ "integrity": "sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==",
"requires": {
- "@babel/helper-function-name": "^7.7.0",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/helper-function-name": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/helpers": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz",
- "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz",
+ "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==",
"requires": {
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/highlight": {
@@ -298,182 +298,182 @@
}
},
"@babel/parser": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.3.tgz",
- "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A=="
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz",
+ "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g=="
},
"@babel/plugin-external-helpers": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.2.0.tgz",
- "integrity": "sha512-QFmtcCShFkyAsNtdCM3lJPmRe1iB+vPZymlB4LnDIKEBj2yKQLQKtoxXxJ8ePT5fwMl4QGg303p4mB0UsSI2/g==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.7.4.tgz",
+ "integrity": "sha512-RVGNajLaFlknbZLutaP/uv7Q+xmVs2LMlEWFXbcjLnwtBdPqAVpV3nzYIAJqri/VjJCUrhG5nALijtg0aND+XA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-proposal-class-properties": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.0.tgz",
- "integrity": "sha512-tufDcFA1Vj+eWvwHN+jvMN6QsV5o+vUlytNKrbMiCeDL0F2j92RURzUsUMWE5EJkLyWxjdUslCsMQa9FWth16A==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.4.tgz",
+ "integrity": "sha512-EcuXeV4Hv1X3+Q1TsuOmyyxeTRiSqurGJ26+I/FW1WbymmRRapVORm6x1Zl3iDIHyRxEs+VXWp6qnlcfcJSbbw==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.7.0",
+ "@babel/helper-create-class-features-plugin": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-proposal-export-default-from": {
- "version": "7.5.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.5.2.tgz",
- "integrity": "sha512-wr9Itk05L1/wyyZKVEmXWCdcsp/e185WUNl6AfYZeEKYaUPPvHXRDqO5K1VH7/UamYqGJowFRuCv30aDYZawsg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.7.4.tgz",
+ "integrity": "sha512-1t6dh7BHYUz4zD1m4pozYYEZy/3m8dgOr9owx3r0mPPI3iGKRUKUbIxfYmcJ4hwljs/dhd0qOTr1ZDUp43ix+w==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-export-default-from": "^7.2.0"
+ "@babel/plugin-syntax-export-default-from": "^7.7.4"
}
},
"@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz",
- "integrity": "sha512-Amph7Epui1Dh/xxUxS2+K22/MUi6+6JVTvy3P58tja3B6yKTSjwwx0/d83rF7551D6PVSSoplQb8GCwqec7HRw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.7.4.tgz",
+ "integrity": "sha512-TbYHmr1Gl1UC7Vo2HVuj/Naci5BEGNZ0AJhzqD2Vpr6QPFWpUmBRLrIDjedzx7/CShq0bRDS2gI4FIs77VHLVQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.2.0"
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.7.4"
}
},
"@babel/plugin-proposal-object-rest-spread": {
- "version": "7.6.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz",
- "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz",
+ "integrity": "sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+ "@babel/plugin-syntax-object-rest-spread": "^7.7.4"
}
},
"@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
- "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz",
+ "integrity": "sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
+ "@babel/plugin-syntax-optional-catch-binding": "^7.7.4"
}
},
"@babel/plugin-proposal-optional-chaining": {
- "version": "7.6.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.6.0.tgz",
- "integrity": "sha512-kj4gkZ6qUggkprRq3Uh5KP8XnE1MdIO0J7MhdDX8+rAbB6dJ2UrensGIS+0NPZAaaJ1Vr0PN6oLUgXMU1uMcSg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.7.4.tgz",
+ "integrity": "sha512-JmgaS+ygAWDR/STPe3/7y0lNlHgS+19qZ9aC06nYLwQ/XB7c0q5Xs+ksFU3EDnp9EiEsO0dnRAOKeyLHTZuW3A==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-optional-chaining": "^7.2.0"
+ "@babel/plugin-syntax-optional-chaining": "^7.7.4"
}
},
"@babel/plugin-syntax-class-properties": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.2.0.tgz",
- "integrity": "sha512-UxYaGXYQ7rrKJS/PxIKRkv3exi05oH7rokBAsmCSsCxz1sVPZ7Fu6FzKoGgUvmY+0YgSkYHgUoCh5R5bCNBQlw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.7.4.tgz",
+ "integrity": "sha512-JH3v5ZOeKT0qqdJ9BeBcZTFQiJOMax8RopSr1bH6ASkZKo2qWsvBML7W1mp89sszBRDBBRO8snqcByGdrMTdMg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-dynamic-import": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz",
- "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz",
+ "integrity": "sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-export-default-from": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.2.0.tgz",
- "integrity": "sha512-c7nqUnNST97BWPtoe+Ssi+fJukc9P9/JMZ71IOMNQWza2E+Psrd46N6AEvtw6pqK+gt7ChjXyrw4SPDO79f3Lw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.7.4.tgz",
+ "integrity": "sha512-j888jpjATLEzOWhKawq46UrpXnCRDbdhBd5io4jgwjJ3+CHHGCRb6PNAVEgs+BXIb+dNRAmnkv36zfB992PRVw==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-flow": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.0.tgz",
- "integrity": "sha512-vQMV07p+L+jZeUnvX3pEJ9EiXGCjB5CTTvsirFD9rpEuATnoAvLBLoYbw1v5tyn3d2XxSuvEKi8cV3KqYUa0vQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz",
+ "integrity": "sha512-2AMAWl5PsmM5KPkB22cvOkUyWk6MjUaqhHNU5nSPUl/ns3j5qLfw2SuYP5RbVZ0tfLvePr4zUScbICtDP2CUNw==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-jsx": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz",
- "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz",
+ "integrity": "sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.2.0.tgz",
- "integrity": "sha512-lRCEaKE+LTxDQtgbYajI04ddt6WW0WJq57xqkAZ+s11h4YgfRHhVA/Y2VhfPzzFD4qeLHWg32DMp9HooY4Kqlg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.7.4.tgz",
+ "integrity": "sha512-XKh/yIRPiQTOeBg0QJjEus5qiSKucKAiApNtO1psqG7D17xmE+X2i5ZqBEuSvo0HRuyPaKaSN/Gy+Ha9KFQolw==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-object-rest-spread": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
- "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz",
+ "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
- "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz",
+ "integrity": "sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-optional-chaining": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.2.0.tgz",
- "integrity": "sha512-HtGCtvp5Uq/jH/WNUPkK6b7rufnCPLLlDAFN7cmACoIjaOOiXxUt3SswU5loHqrhtqTsa/WoLQ1OQ1AGuZqaWA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.7.4.tgz",
+ "integrity": "sha512-2MqYD5WjZSbJdUagnJvIdSfkb/ucOC9/1fRJxm7GAxY6YQLWlUvkfxoNbUPcPLHJyetKUDQ4+yyuUyAoc0HriA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-typescript": {
- "version": "7.3.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz",
- "integrity": "sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz",
+ "integrity": "sha512-77blgY18Hud4NM1ggTA8xVT/dBENQf17OpiToSa2jSmEY3fWXD2jwrdVlO4kq5yzUTeF15WSQ6b4fByNvJcjpQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-arrow-functions": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
- "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz",
+ "integrity": "sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-async-to-generator": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz",
- "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz",
+ "integrity": "sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg==",
"requires": {
- "@babel/helper-module-imports": "^7.7.0",
+ "@babel/helper-module-imports": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-remap-async-to-generator": "^7.7.0"
+ "@babel/helper-remap-async-to-generator": "^7.7.4"
}
},
"@babel/plugin-transform-block-scoped-functions": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
- "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz",
+ "integrity": "sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz",
- "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz",
+ "integrity": "sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"lodash": "^4.17.13"
@@ -487,236 +487,236 @@
}
},
"@babel/plugin-transform-classes": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz",
- "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.7.0",
- "@babel/helper-define-map": "^7.7.0",
- "@babel/helper-function-name": "^7.7.0",
- "@babel/helper-optimise-call-expression": "^7.7.0",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz",
+ "integrity": "sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.7.4",
+ "@babel/helper-define-map": "^7.7.4",
+ "@babel/helper-function-name": "^7.7.4",
+ "@babel/helper-optimise-call-expression": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-replace-supers": "^7.7.0",
- "@babel/helper-split-export-declaration": "^7.7.0",
+ "@babel/helper-replace-supers": "^7.7.4",
+ "@babel/helper-split-export-declaration": "^7.7.4",
"globals": "^11.1.0"
}
},
"@babel/plugin-transform-computed-properties": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
- "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz",
+ "integrity": "sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.6.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz",
- "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz",
+ "integrity": "sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-exponentiation-operator": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
- "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz",
+ "integrity": "sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ==",
"requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-flow-strip-types": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.6.3.tgz",
- "integrity": "sha512-l0ETkyEofkqFJ9LS6HChNIKtVJw2ylKbhYMlJ5C6df+ldxxaLIyXY4yOdDQQspfFpV8/vDiaWoJlvflstlYNxg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz",
+ "integrity": "sha512-w9dRNlHY5ElNimyMYy0oQowvQpwt/PRHI0QS98ZJCTZU2bvSnKXo5zEiD5u76FBPigTm8TkqzmnUTg16T7qbkA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-flow": "^7.2.0"
+ "@babel/plugin-syntax-flow": "^7.7.4"
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz",
- "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz",
+ "integrity": "sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz",
- "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz",
+ "integrity": "sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g==",
"requires": {
- "@babel/helper-function-name": "^7.7.0",
+ "@babel/helper-function-name": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-literals": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
- "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz",
+ "integrity": "sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-member-expression-literals": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz",
- "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz",
+ "integrity": "sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-modules-commonjs": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz",
- "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.4.tgz",
+ "integrity": "sha512-k8iVS7Jhc367IcNF53KCwIXtKAH7czev866ThsTgy8CwlXjnKZna2VHwChglzLleYrcHz1eQEIJlGRQxB53nqA==",
"requires": {
- "@babel/helper-module-transforms": "^7.7.0",
+ "@babel/helper-module-transforms": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-simple-access": "^7.7.0",
+ "@babel/helper-simple-access": "^7.7.4",
"babel-plugin-dynamic-import-node": "^2.3.0"
}
},
"@babel/plugin-transform-object-assign": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.2.0.tgz",
- "integrity": "sha512-nmE55cZBPFgUktbF2OuoZgPRadfxosLOpSgzEPYotKSls9J4pEPcembi8r78RU37Rph6UApCpNmsQA4QMWK9Ng==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.7.4.tgz",
+ "integrity": "sha512-0TpeUlnhQDwKxPLTIckdaWt46L2s61c/5w5snw1OUod5ehOJywZD98Ha3dFHVjeqkfOFtOTH7cqxddjxUuvcmg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-object-super": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz",
- "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz",
+ "integrity": "sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-replace-supers": "^7.5.5"
+ "@babel/helper-replace-supers": "^7.7.4"
}
},
"@babel/plugin-transform-parameters": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz",
- "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz",
+ "integrity": "sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw==",
"requires": {
- "@babel/helper-call-delegate": "^7.4.4",
- "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/helper-call-delegate": "^7.7.4",
+ "@babel/helper-get-function-arity": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-property-literals": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz",
- "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz",
+ "integrity": "sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-react-display-name": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz",
- "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.7.4.tgz",
+ "integrity": "sha512-sBbIvqYkthai0X0vkD2xsAwluBp+LtNHH+/V4a5ydifmTtb8KOVOlrMIk/MYmIc4uTYDnjZUHQildYNo36SRJw==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-react-jsx": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.0.tgz",
- "integrity": "sha512-mXhBtyVB1Ujfy+0L6934jeJcSXj/VCg6whZzEcgiiZHNS0PGC7vUCsZDQCxxztkpIdF+dY1fUMcjAgEOC3ZOMQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.4.tgz",
+ "integrity": "sha512-LixU4BS95ZTEAZdPaIuyg/k8FiiqN9laQ0dMHB4MlpydHY53uQdWCUrwjLr5o6ilS6fAgZey4Q14XBjl5tL6xw==",
"requires": {
- "@babel/helper-builder-react-jsx": "^7.7.0",
+ "@babel/helper-builder-react-jsx": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-jsx": "^7.2.0"
+ "@babel/plugin-syntax-jsx": "^7.7.4"
}
},
"@babel/plugin-transform-react-jsx-source": {
- "version": "7.5.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz",
- "integrity": "sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.7.4.tgz",
+ "integrity": "sha512-5ZU9FnPhqtHsOXxutRtXZAzoEJwDaP32QcobbMP1/qt7NYcsCNK8XgzJcJfoEr/ZnzVvUNInNjIW22Z6I8p9mg==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-jsx": "^7.2.0"
+ "@babel/plugin-syntax-jsx": "^7.7.4"
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz",
- "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.4.tgz",
+ "integrity": "sha512-e7MWl5UJvmPEwFJTwkBlPmqixCtr9yAASBqff4ggXTNicZiwbF8Eefzm6NVgfiBp7JdAGItecnctKTgH44q2Jw==",
"requires": {
"regenerator-transform": "^0.14.0"
}
},
"@babel/plugin-transform-runtime": {
- "version": "7.6.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz",
- "integrity": "sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.4.tgz",
+ "integrity": "sha512-O8kSkS5fP74Ad/8pfsCMGa8sBRdLxYoSReaARRNSz3FbFQj3z/QUvoUmJ28gn9BO93YfnXc3j+Xyaqe8cKDNBQ==",
"requires": {
- "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-module-imports": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
"resolve": "^1.8.1",
"semver": "^5.5.1"
}
},
"@babel/plugin-transform-shorthand-properties": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
- "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz",
+ "integrity": "sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-spread": {
- "version": "7.6.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz",
- "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz",
+ "integrity": "sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-sticky-regex": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
- "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz",
+ "integrity": "sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A==",
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/helper-regex": "^7.0.0"
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz",
- "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz",
+ "integrity": "sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-annotate-as-pure": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-typescript": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.2.tgz",
- "integrity": "sha512-UWhDaJRqdPUtdK1s0sKYdoRuqK0NepjZto2UZltvuCgMoMZmdjhgz5hcRokie/3aYEaSz3xvusyoayVaq4PjRg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz",
+ "integrity": "sha512-X8e3tcPEKnwwPVG+vP/vSqEShkwODOEeyQGod82qrIuidwIrfnsGn11qPM1jBLF4MqguTXXYzm58d0dY+/wdpg==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.7.0",
+ "@babel/helper-create-class-features-plugin": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-typescript": "^7.2.0"
+ "@babel/plugin-syntax-typescript": "^7.7.4"
}
},
"@babel/plugin-transform-unicode-regex": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz",
- "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz",
+ "integrity": "sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw==",
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.7.0",
+ "@babel/helper-create-regexp-features-plugin": "^7.7.4",
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/register": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.7.0.tgz",
- "integrity": "sha512-HV3GJzTvSoyOMWGYn2TAh6uL6g+gqKTgEZ99Q3+X9UURT1VPT/WcU46R61XftIc5rXytcOHZ4Z0doDlsjPomIg==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.7.4.tgz",
+ "integrity": "sha512-/fmONZqL6ZMl9KJUYajetCrID6m0xmL4odX7v+Xvoxcv0DdbP/oO0TWIeLUCHqczQ6L6njDMqmqHFy2cp3FFsA==",
"requires": {
"find-cache-dir": "^2.0.0",
"lodash": "^4.17.13",
@@ -750,26 +750,26 @@
}
},
"@babel/template": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz",
- "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
+ "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
"requires": {
"@babel/code-frame": "^7.0.0",
- "@babel/parser": "^7.7.0",
- "@babel/types": "^7.7.0"
+ "@babel/parser": "^7.7.4",
+ "@babel/types": "^7.7.4"
}
},
"@babel/traverse": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz",
- "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
+ "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
"requires": {
"@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.2",
- "@babel/helper-function-name": "^7.7.0",
- "@babel/helper-split-export-declaration": "^7.7.0",
- "@babel/parser": "^7.7.2",
- "@babel/types": "^7.7.2",
+ "@babel/generator": "^7.7.4",
+ "@babel/helper-function-name": "^7.7.4",
+ "@babel/helper-split-export-declaration": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/types": "^7.7.4",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.13"
@@ -783,9 +783,9 @@
}
},
"@babel/types": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz",
- "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
+ "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
"requires": {
"esutils": "^2.0.2",
"lodash": "^4.17.13",
@@ -878,9 +878,9 @@
}
},
"@google-cloud/paginator": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.1.tgz",
- "integrity": "sha512-HZ6UTGY/gHGNriD7OCikYWL/Eu0sTEur2qqse2w6OVsz+57se3nTkqH14JIPxtf0vlEJ8IJN5w3BdZ22pjCB8g==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.2.tgz",
+ "integrity": "sha512-PCddVtZWvw0iZ3BLIsCXMBQvxUcS9O5CgfHBu8Zd8T3DCiML+oQED1odsbl3CQ9d3RrvBaj+eIh7Dv12D15PbA==",
"dev": true,
"optional": true,
"requires": {
@@ -889,16 +889,16 @@
}
},
"@google-cloud/projectify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.1.tgz",
- "integrity": "sha512-xknDOmsMgOYHksKc1GPbwDLsdej8aRNIA17SlSZgQdyrcC0lx0OGo4VZgYfwoEU1YS8oUxF9Y+6EzDOb0eB7Xg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.2.tgz",
+ "integrity": "sha512-WnkGxvk4U1kAJpoS/Ehk+3MZXVW+XHHhwc/QyD6G8Za4xml3Fv+NRn/bYffl1TxSg+gE0N0mj9Shgc7e8+fl8A==",
"dev": true,
"optional": true
},
"@google-cloud/promisify": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.2.tgz",
- "integrity": "sha512-7WfV4R/3YV5T30WRZW0lqmvZy9hE2/p9MvpI34WuKa2Wz62mLu5XplGTFEMK6uTbJCLWUxTcZ4J4IyClKucE5g==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.3.tgz",
+ "integrity": "sha512-Rufgfl3TnkIil3CjsH33Q6093zeoVqyqCdvtvgHuCqRJxCZYfaVPIyr8JViMeLTD4Ja630pRKKZVSjKggoVbNg==",
"dev": true,
"optional": true
},
@@ -2946,9 +2946,9 @@
}
},
"@ostdotcom/ost-wallet-sdk-react-native": {
- "version": "2.3.7-alpha.3",
- "resolved": "https://registry.npmjs.org/@ostdotcom/ost-wallet-sdk-react-native/-/ost-wallet-sdk-react-native-2.3.7-alpha.3.tgz",
- "integrity": "sha512-GAshH+6nO/gC7ToKNCscuamos3Vbhhpo8UtjjIz5seKYNWVRMJnHuD4VEvisgJXJ0ARZnm8v2vFWCGW7467f8w=="
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/@ostdotcom/ost-wallet-sdk-react-native/-/ost-wallet-sdk-react-native-2.3.10.tgz",
+ "integrity": "sha512-SthTSY/CiJoA6/wSsGdzcP/9quk+XYxJ39DOvkIWQvaVx7jkNF+lL26GzVXNT1sbrkBuNCWTal+pwXnHYIF8Fg=="
},
"@protobufjs/aspromise": {
"version": "1.1.2",
@@ -3035,9 +3035,9 @@
"integrity": "sha512-cvJewReV2l65exdsccveqnqXHGFuTgwdbjr+0MASxq6zQ+eeHLx9g/wYk8YrXHWXJqf5B/jZnNDpcg/y23atmw=="
},
"@react-native-community/cli": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.11.2.tgz",
- "integrity": "sha512-5NuYd30f5PCTrGUbZLnusZKv5nfTWvTDTRa/3Q4vwdMnUQrhm9sZXWGQ5CnFoQ7cE58EAqhj6/ShXeJF3DZ9uQ==",
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.12.0.tgz",
+ "integrity": "sha512-GAs4JgVP8QkEYeZks/T7cCrBuwFJKxd9ksBLRdQ058uvLGkOEeS4g3y4GsVM/9C1zat5h6Z6QwU0h/hj7G3tzg==",
"requires": {
"chalk": "^1.1.1",
"commander": "^2.19.0",
@@ -3168,9 +3168,9 @@
},
"dependencies": {
"hoist-non-react-statics": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
- "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw==",
"requires": {
"react-is": "^16.7.0"
}
@@ -3188,9 +3188,9 @@
},
"dependencies": {
"hoist-non-react-statics": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
- "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw==",
"requires": {
"react-is": "^16.7.0"
}
@@ -3230,9 +3230,9 @@
}
},
"@types/babel__traverse": {
- "version": "7.0.7",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz",
- "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==",
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz",
+ "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==",
"dev": true,
"requires": {
"@babel/types": "^7.3.0"
@@ -3298,9 +3298,9 @@
"dev": true
},
"abab": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz",
- "integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
+ "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
"dev": true
},
"abort-controller": {
@@ -3353,9 +3353,9 @@
},
"dependencies": {
"acorn": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
- "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz",
+ "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==",
"dev": true
}
}
@@ -3877,9 +3877,9 @@
"dev": true
},
"aws4": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
- "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz",
+ "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==",
"dev": true
},
"babel-jest": {
@@ -4131,9 +4131,9 @@
}
},
"big-integer": {
- "version": "1.6.47",
- "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.47.tgz",
- "integrity": "sha512-9t9f7X3as2XGX8b52GqG6ox0GvIdM86LyIXASJnDCFhYNgt+A+MByQZ3W2PyMRZjEvG5f8TEbSPfEotVuMJnQg=="
+ "version": "1.6.48",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
+ "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
},
"bignumber.js": {
"version": "8.1.1",
@@ -4824,9 +4824,9 @@
"integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ="
},
"deep-equal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz",
- "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
+ "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
"dev": true,
"optional": true,
"requires": {
@@ -5134,18 +5134,18 @@
}
},
"es-abstract": {
- "version": "1.16.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz",
- "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==",
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.2.tgz",
+ "integrity": "sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA==",
"dev": true,
"requires": {
- "es-to-primitive": "^1.2.0",
+ "es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
- "has-symbols": "^1.0.0",
+ "has-symbols": "^1.0.1",
"is-callable": "^1.1.4",
"is-regex": "^1.0.4",
- "object-inspect": "^1.6.0",
+ "object-inspect": "^1.7.0",
"object-keys": "^1.1.1",
"string.prototype.trimleft": "^2.1.0",
"string.prototype.trimright": "^2.1.0"
@@ -5446,17 +5446,17 @@
},
"dependencies": {
"@babel/core": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
- "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
+ "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
"requires": {
"@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.2",
- "@babel/helpers": "^7.7.0",
- "@babel/parser": "^7.7.2",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.2",
- "@babel/types": "^7.7.2",
+ "@babel/generator": "^7.7.4",
+ "@babel/helpers": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
@@ -6146,9 +6146,9 @@
}
},
"gcp-metadata": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.2.1.tgz",
- "integrity": "sha512-JjDedBWnbXVXWwTpjBdpb9RpVLiowXG4/50rra4hPH8REXAi2si6Xbb48B2SwkQBLz9Wu6+o32GDTvVy2kkLoQ==",
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.2.2.tgz",
+ "integrity": "sha512-vR7kcJMCYJG/mYWp/a1OszdOqnLB/XW1GorWW1hc1lWVNL26L497zypWb9cG0CYDQ4Bl1Wk0+fSZFFjwJlTQgQ==",
"dev": true,
"optional": true,
"requires": {
@@ -6157,9 +6157,9 @@
}
},
"gcs-resumable-upload": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.0.tgz",
- "integrity": "sha512-PclXJiEngrVx0c4K0LfE1XOxhmOkBEy39Rrhspdn6jAbbwe4OQMZfjo7Z1LHBrh57+bNZeIN4M+BooYppCoHSg==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.1.tgz",
+ "integrity": "sha512-zEO7L+jz99VznQsbsF7vFTnIFbSu+CjdJqt5htnjIrfsp5j+QCVBvbbKdqpaTfCPzpUPYj1Q9O9DhIh/8newfA==",
"dev": true,
"optional": true,
"requires": {
@@ -6276,14 +6276,15 @@
}
},
"google-gax": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.8.0.tgz",
- "integrity": "sha512-gDlL1mcyMSde7guPVzwpWi9V8XP+4F8UwFKoUiINEGRDNDbEj18OorL016XU0Kyt8Aizcf5dgb3q8UKegYAOmQ==",
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.11.1.tgz",
+ "integrity": "sha512-v/APF2G5h2nS5R/1DW2vsgloaMu2/B3xjHdAptR1yUwZpEd9rxPTlhqosrjl/VRu+gWGr9JZN19ZgJTXQ/Db6Q==",
"dev": true,
"optional": true,
"requires": {
"@grpc/grpc-js": "0.6.9",
"@grpc/proto-loader": "^0.5.1",
+ "@types/long": "^4.0.0",
"abort-controller": "^3.0.0",
"duplexify": "^3.6.0",
"google-auth-library": "^5.0.0",
@@ -6307,9 +6308,9 @@
}
},
"google-p12-pem": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.2.tgz",
- "integrity": "sha512-UfnEARfJKI6pbmC1hfFFm+UAcZxeIwTiEcHfqKe/drMsXD/ilnVjF7zgOGpHXyhuvX6jNJK3S8A0hOQjwtFxEw==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.3.tgz",
+ "integrity": "sha512-Tq2kBCANxYYPxaBpTgCpRfdoPs9+/lNzc/Iaee4kuMVW5ascD+HwhpBsTLwH85C9Ev4qfB8KKHmpPQYyD2vg2w==",
"dev": true,
"optional": true,
"requires": {
@@ -6336,9 +6337,9 @@
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE="
},
"gtoken": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.1.tgz",
- "integrity": "sha512-2FEmEDGi4NdM6u+mtaLjSDDtHiw5wT+nBsI+yrSeFO6fVqPEytYVF6uiIpRaOaZhRP+ozjYWuwwtMlrjAyTcYA==",
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.3.tgz",
+ "integrity": "sha512-ofW+FiXjswyKdkjMcDbe6E4K7cDDdE82dGDhZIc++kUECqaE7MSErf6arJPAjcnYn1qxE1/Ti06qQuqgVusovQ==",
"dev": true,
"optional": true,
"requires": {
@@ -6358,9 +6359,9 @@
}
},
"handlebars": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz",
- "integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==",
+ "version": "4.5.3",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+ "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
"dev": true,
"requires": {
"neo-async": "^2.6.0",
@@ -6376,9 +6377,9 @@
"dev": true
},
"uglify-js": {
- "version": "3.6.8",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.8.tgz",
- "integrity": "sha512-XhHJ3S3ZyMwP8kY1Gkugqx3CJh2C3O0y8NPiSxtm1tyD/pktLAkFZsFGpuNfTZddKDQ/bbDBLAd2YyA1pbi8HQ==",
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.0.tgz",
+ "integrity": "sha512-PC/ee458NEMITe1OufAjal65i6lB58R1HWMRcxwvdz1UopW0DYqlRL3xdu3IcTvTXsB02CRHykidkTRL+A3hQA==",
"dev": true,
"optional": true,
"requires": {
@@ -6447,9 +6448,9 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"has-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
- "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
},
"has-unicode": {
"version": "2.0.1",
@@ -6914,12 +6915,12 @@
"optional": true
},
"is-symbol": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
- "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"dev": true,
"requires": {
- "has-symbols": "^1.0.0"
+ "has-symbols": "^1.0.1"
}
},
"is-typedarray": {
@@ -9946,17 +9947,17 @@
},
"dependencies": {
"@babel/core": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
- "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
+ "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
"requires": {
"@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.2",
- "@babel/helpers": "^7.7.0",
- "@babel/parser": "^7.7.2",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.2",
- "@babel/types": "^7.7.2",
+ "@babel/generator": "^7.7.4",
+ "@babel/helpers": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
@@ -10116,17 +10117,17 @@
},
"dependencies": {
"@babel/core": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
- "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
+ "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
"requires": {
"@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.2",
- "@babel/helpers": "^7.7.0",
- "@babel/parser": "^7.7.2",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.2",
- "@babel/types": "^7.7.2",
+ "@babel/generator": "^7.7.4",
+ "@babel/helpers": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
@@ -10152,17 +10153,17 @@
},
"dependencies": {
"@babel/core": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
- "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
+ "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
"requires": {
"@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.2",
- "@babel/helpers": "^7.7.0",
- "@babel/parser": "^7.7.2",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.2",
- "@babel/types": "^7.7.2",
+ "@babel/generator": "^7.7.4",
+ "@babel/helpers": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
@@ -10296,17 +10297,17 @@
},
"dependencies": {
"@babel/core": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
- "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
+ "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
"requires": {
"@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.2",
- "@babel/helpers": "^7.7.0",
- "@babel/parser": "^7.7.2",
- "@babel/template": "^7.7.0",
- "@babel/traverse": "^7.7.2",
- "@babel/types": "^7.7.2",
+ "@babel/generator": "^7.7.4",
+ "@babel/helpers": "^7.7.4",
+ "@babel/parser": "^7.7.4",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@babel/types": "^7.7.4",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
@@ -10423,16 +10424,16 @@
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
- "version": "1.40.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
- "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ "version": "1.42.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
+ "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
},
"mime-types": {
- "version": "2.1.24",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
- "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "version": "2.1.25",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
+ "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
"requires": {
- "mime-db": "1.40.0"
+ "mime-db": "1.42.0"
}
},
"mimic-fn": {
@@ -10500,6 +10501,14 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
+ "moment-timezone": {
+ "version": "0.5.27",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz",
+ "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==",
+ "requires": {
+ "moment": ">= 2.9.0"
+ }
+ },
"morgan": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
@@ -10761,9 +10770,9 @@
}
},
"object-inspect": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
- "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
"dev": true
},
"object-is": {
@@ -11334,9 +11343,9 @@
},
"dependencies": {
"@types/node": {
- "version": "10.17.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz",
- "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==",
+ "version": "10.17.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz",
+ "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==",
"dev": true,
"optional": true
}
@@ -11413,9 +11422,9 @@
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
"query-string": {
- "version": "6.8.3",
- "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.8.3.tgz",
- "integrity": "sha512-llcxWccnyaWlODe7A9hRjkvdCKamEKTh+wH8ITdTc3OhchaqUZteiSCX/2ablWHVrkVIe04dntnaZJ7BdyW0lQ==",
+ "version": "6.9.0",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.9.0.tgz",
+ "integrity": "sha512-KG4bhCFYapExLsUHrFt+kQVEegF2agm4cpF/VNc6pZVthIfCc/GK8t8VyNIE3nyXG9DK3Tf2EGkxjR6/uRdYsA==",
"requires": {
"decode-uri-component": "^0.2.0",
"split-on-first": "^1.0.0",
@@ -11505,9 +11514,9 @@
}
},
"react-is": {
- "version": "16.11.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
- "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw=="
+ "version": "16.12.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
+ "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
},
"react-native": {
"version": "0.59.9",
@@ -11567,9 +11576,9 @@
},
"dependencies": {
"@babel/runtime": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz",
- "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.4.tgz",
+ "integrity": "sha512-r24eVUUr0QqNZa+qrImUk8fn5SPhHq+IfYvIoIMg0do3GdK9sMdiLKP3GYVVaxpPKORgm8KRKaNTEhAjgIpLMw==",
"requires": {
"regenerator-runtime": "^0.13.2"
},
@@ -11917,17 +11926,17 @@
},
"dependencies": {
"@babel/runtime": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz",
- "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.4.tgz",
+ "integrity": "sha512-r24eVUUr0QqNZa+qrImUk8fn5SPhHq+IfYvIoIMg0do3GdK9sMdiLKP3GYVVaxpPKORgm8KRKaNTEhAjgIpLMw==",
"requires": {
"regenerator-runtime": "^0.13.2"
}
},
"hoist-non-react-statics": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
- "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw==",
"requires": {
"react-is": "^16.7.0"
}
@@ -12241,9 +12250,9 @@
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
},
"resolve": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
- "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
+ "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==",
"requires": {
"path-parse": "^1.0.6"
}
@@ -12312,6 +12321,15 @@
"glob": "^7.1.3"
}
},
+ "rn-sliding-up-panel": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/rn-sliding-up-panel/-/rn-sliding-up-panel-2.3.3.tgz",
+ "integrity": "sha512-LcIaU/qbriu5i0aLtwBDJRl2b26idj9XJQZYEdvSCxtNEhm5R3+OEHFwq0YF14a4tnfGmnlHIALi9sKBIj6mcw==",
+ "requires": {
+ "clamp": "^1.0.1",
+ "prop-types": "^15.7.2"
+ }
+ },
"rsvp": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz",
diff --git a/package.json b/package.json
index 38e46d64..5daab109 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"test": "jest"
},
"dependencies": {
- "@ostdotcom/ost-wallet-sdk-react-native": "2.3.9",
+ "@ostdotcom/ost-wallet-sdk-react-native": "2.3.10",
"@react-native-community/async-storage": "1.6.1",
"@react-native-community/cameraroll": "1.1.1",
"@react-native-community/netinfo": "3.2.1",
@@ -16,6 +16,7 @@
"lodash": "4.17.11",
"metro-react-native-babel-preset": "0.54.1",
"moment": "2.24.0",
+ "moment-timezone": "0.5.27",
"native-base": "2.12.1",
"numeral": "2.0.6",
"qs": "6.7.0",
@@ -52,6 +53,7 @@
"redux": "4.0.1",
"redux-actions": "2.6.5",
"redux-logger": "3.0.6",
+ "rn-sliding-up-panel": "2.3.3",
"socket.io-client": "2.2.0",
"react-native-keep-awake": "4.0.0"
},
diff --git a/src/actions/constants.js b/src/actions/constants.js
index 3e2d58de..3eec4023 100644
--- a/src/actions/constants.js
+++ b/src/actions/constants.js
@@ -4,6 +4,7 @@ const SHOW_MODAL_COVER = 'SHOW_MODAL_COVER';
const HIDE_MODAL_COVER = 'HIDE_MODAL_COVER';
const SHOW_LOGIN_POPOVER = 'SHOW_LOGIN_POPOVER';
const HIDE_LOGIN_POPOVER = 'HIDE_LOGIN_POPOVER';
+const SHOW_CONNECTING_LOGIN_POPOVER = 'SHOW_CONNECTING_LOGIN_POPOVER';
const UPSERT_USER_ENTITIES = 'UPSERT_USER_ENTITIES';
const LOGOUT_USER = 'LOGOUT_USER';
const UPSERT_ACTIVITIES_ENTITIES = 'UPSERT_ACTIVITIES_ENTITIES';
@@ -16,12 +17,16 @@ const UPSERT_USER_STAT_ENTITIES = 'UPSERT_USER_STAT_ENTITIES';
const UPSERT_LINK_ENTITIES = 'UPSERT_LINK_ENTITIES';
const UPSERT_VIDEO_ENTITIES = 'UPSERT_VIDEO_ENTITIES';
const UPSERT_VIDEO_STAT_ENTITIES = 'UPSERT_VIDEO_STAT_ENTITIES';
+const UPSERT_REPLY_DETAIL_ENTITIES = 'UPSERT_REPLY_DETAIL_ENTITIES';
+const UPSERT_CURRENT_USER_VIDEO_RELATION_ENTITIES = 'UPSERT_CURRENT_USER_VIDEO_RELATION_ENTITIES';
+const UPSERT_CURRENT_USER_REPLY_DETAIL_RELATION_ENTITIES = 'UPSERT_CURRENT_USER_REPLY_DETAIL_RELATION_ENTITIES';
const UPSERT_HOME_FEED_ENTITIES = 'UPSERT_HOME_FEED_ENTITIES';
const UPSERT_IMAGE_ENTITIES = 'UPSERT_IMAGE_ENTITIES';
const UPDATE_BALANCE = 'UPDATE_BALANCE';
const UPDATE_IS_PURCHASE = 'UPDATE_IS_PURCHASE';
const UPDATE_EXECUTE_TRANSACTION_STATUS = 'UPDATE_EXECUTE_TRANSACTION_STATUS';
const UPSERT_VIDEO_CONTRIBUTION_ENTITIES = 'UPSERT_VIDEO_CONTRIBUTION_ENTITIES';
+const UPSERT_REPLY_CONTRIBUTION_ENTITIES = 'UPSERT_REPLY_CONTRIBUTION_ENTITIES';
const UPSERT_USER_CONTRIBUTION_ENTITIES = 'UPSERT_USER_CONTRIBUTION_ENTITIES';
const UPSERT_USER_VIDEO_ENTITIES = 'UPSERT_USER_VIDEO_ENTITIES';
const UPDATE_PRICE_POINTS = 'UPDATE_PRICE_POINTS';
@@ -50,6 +55,7 @@ export {
SHOW_MODAL_COVER,
HIDE_MODAL_COVER,
SHOW_LOGIN_POPOVER,
+ SHOW_CONNECTING_LOGIN_POPOVER,
HIDE_LOGIN_POPOVER,
UPSERT_USER_ENTITIES,
UPSERT_ACTIVITIES_ENTITIES,
@@ -59,6 +65,9 @@ export {
UPSERT_TAG_ENTITIES,
UPSERT_USER_PROFILE_ENTITIES,
UPSERT_USER_STAT_ENTITIES,
+ UPSERT_REPLY_DETAIL_ENTITIES,
+ UPSERT_CURRENT_USER_VIDEO_RELATION_ENTITIES,
+ UPSERT_CURRENT_USER_REPLY_DETAIL_RELATION_ENTITIES,
UPSERT_LINK_ENTITIES,
UPSERT_VIDEO_ENTITIES,
UPSERT_VIDEO_STAT_ENTITIES,
@@ -68,6 +77,7 @@ export {
UPDATE_IS_PURCHASE,
UPDATE_EXECUTE_TRANSACTION_STATUS,
UPSERT_VIDEO_CONTRIBUTION_ENTITIES,
+ UPSERT_REPLY_CONTRIBUTION_ENTITIES,
UPSERT_USER_CONTRIBUTION_ENTITIES,
UPSERT_USER_VIDEO_ENTITIES,
UPDATE_PRICE_POINTS,
diff --git a/src/actions/index.js b/src/actions/index.js
index f056d3dd..26a1571b 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -27,19 +27,35 @@ export const showLoginPopover = () => ({
type: types.SHOW_LOGIN_POPOVER,
payload: {
login_popover: {
- show: true
+ show: true,
+ isTwitterConnecting: false
}
}
});
-export const hideLoginPopover = () => ({
- type: types.HIDE_LOGIN_POPOVER,
- payload: {
- login_popover: {
- show: false
+export const hideLoginPopover = () => {
+ return {
+ type: types.HIDE_LOGIN_POPOVER,
+ payload: {
+ login_popover: {
+ show: false,
+ isTwitterConnecting: false
+ }
}
- }
-});
+ };
+};
+
+export const showConnectingLoginPopover = () => {
+ return {
+ type: types.SHOW_CONNECTING_LOGIN_POPOVER,
+ payload: {
+ login_popover: {
+ show: true,
+ isTwitterConnecting: true
+ }
+ }
+ };
+};
export const updateCurrentUser = (current_user) => ({
type: types.UPDATE_CURRENT_USER,
@@ -107,6 +123,21 @@ export const upsertVideoStatEntities = (data) => ({
payload: { video_stat_entities: data }
});
+export const upsertReplyDetailEntities = (data) => ({
+ type: types.UPSERT_REPLY_DETAIL_ENTITIES,
+ payload: { reply_detail_entities: data }
+});
+
+export const upsertCurrentUserVideoRelationEntities = (data) => ({
+ type: types.UPSERT_CURRENT_USER_VIDEO_RELATION_ENTITIES,
+ payload: { current_user_video_relation_entities: data }
+});
+
+export const upsertCurrentUserReplyDetailRelationEntities = (data) => ({
+ type: types.UPSERT_CURRENT_USER_REPLY_DETAIL_RELATION_ENTITIES,
+ payload: { current_user_reply_detail_relation_entities: data }
+});
+
export const upsertHomeFeedEntities = (data) => ({
type: types.UPSERT_HOME_FEED_ENTITIES,
payload: { home_feed_entities: data }
@@ -129,6 +160,13 @@ export const upsertVideoContributionEntities = (data) => ({
payload: { video_contribution_entities: data }
});
+
+export const upsertReplyContributionEntities = (data) => ({
+ type: types.UPSERT_REPLY_CONTRIBUTION_ENTITIES,
+ payload: { reply_contribution_entities: data }
+});
+
+
export const upsertUserContributionEntities = (data) => ({
type: types.UPSERT_USER_CONTRIBUTION_ENTITIES,
payload: { user_contribution_entities: data }
diff --git a/src/assets/UnicornSmall.png b/src/assets/UnicornSmall.png
index bf146545..831194a5 100644
Binary files a/src/assets/UnicornSmall.png and b/src/assets/UnicornSmall.png differ
diff --git a/src/assets/cameraIconWhite.png b/src/assets/cameraIconWhite.png
new file mode 100644
index 00000000..2d94f7b6
Binary files /dev/null and b/src/assets/cameraIconWhite.png differ
diff --git a/src/assets/cross-icon-white.png b/src/assets/cross-icon-white.png
new file mode 100644
index 00000000..97a9f86b
Binary files /dev/null and b/src/assets/cross-icon-white.png differ
diff --git a/src/assets/reply-video-white.png b/src/assets/reply-video-white.png
new file mode 100644
index 00000000..2d94f7b6
Binary files /dev/null and b/src/assets/reply-video-white.png differ
diff --git a/src/assets/reply-with-pepo.png b/src/assets/reply-with-pepo.png
new file mode 100644
index 00000000..b65c104c
Binary files /dev/null and b/src/assets/reply-with-pepo.png differ
diff --git a/src/assets/reply_video.png b/src/assets/reply_video.png
new file mode 100644
index 00000000..a792e83c
Binary files /dev/null and b/src/assets/reply_video.png differ
diff --git a/src/assets/reply_video_icon.png b/src/assets/reply_video_icon.png
new file mode 100644
index 00000000..695dd2c5
Binary files /dev/null and b/src/assets/reply_video_icon.png differ
diff --git a/src/assets/top-up-icon.png b/src/assets/top-up-icon.png
index f157d055..f6f593fd 100644
Binary files a/src/assets/top-up-icon.png and b/src/assets/top-up-icon.png differ
diff --git a/src/assets/video-reply.png b/src/assets/video-reply.png
new file mode 100644
index 00000000..d78e5a67
Binary files /dev/null and b/src/assets/video-reply.png differ
diff --git a/src/components/AddEmail/index.js b/src/components/AddEmail/index.js
index 16f5cf85..5e60e9f7 100644
--- a/src/components/AddEmail/index.js
+++ b/src/components/AddEmail/index.js
@@ -14,6 +14,7 @@ import { ostErrors } from '../../services/OstErrors';
import Colors from '../../theme/styles/Colors';
import CurrentUser from '../../models/CurrentUser';
import { navigateTo } from '../../helpers/navigateTo';
+import CommonStyle from '../../theme/styles/Common';
const bottomSpace = getBottomSpace([true]),
extraPadding = 10,
@@ -113,7 +114,7 @@ class AddEmailScreen extends React.Component {
};
onSuccess(res) {
- //TODO show success screen
+
this.setState({
emailSent: true
});
@@ -214,7 +215,7 @@ class AddEmailScreen extends React.Component {
render() {
return (
-
+
{!this.state.emailSent ? this.emailSignUp() : this.confirmEmail()}
diff --git a/src/components/AuthLoading/index.js b/src/components/AuthLoading/index.js
index 6ff180bf..1278f4ff 100644
--- a/src/components/AuthLoading/index.js
+++ b/src/components/AuthLoading/index.js
@@ -1,5 +1,5 @@
import React, { Component } from 'react';
-import { View, StatusBar, Alert, Platform, Linking } from 'react-native';
+import { View, StatusBar, Alert } from 'react-native';
import Toast from '../../theme/components/NotificationToast';
import styles from './styles';
diff --git a/src/components/Bio/index.js b/src/components/Bio/index.js
index c268dfaa..f2662634 100644
--- a/src/components/Bio/index.js
+++ b/src/components/Bio/index.js
@@ -1,10 +1,11 @@
import React, { PureComponent } from 'react';
-import { View, Text, ScrollView } from 'react-native';
+import {View, Text} from 'react-native';
import { withNavigation } from 'react-navigation';
import BackArrow from '../CommonComponents/BackArrow';
import TagsInput from '../CommonComponents/TagsInput';
import Colors from '../../theme/styles/Colors';
+import CommonStyle from '../../theme/styles/Common';
import inlineStyles from './style';
class BioScreen extends PureComponent {
@@ -51,29 +52,24 @@ class BioScreen extends PureComponent {
render() {
return (
-
-
+
+
+
{this.state.count} /300
-
-
+
+
);
}
}
-const SearchResultRowComponent = (props) => (
-
- {`#${props.val}`}
-
-);
-
export default withNavigation(BioScreen);
diff --git a/src/components/Bio/style.js b/src/components/Bio/style.js
index 792eb83a..682e2989 100644
--- a/src/components/Bio/style.js
+++ b/src/components/Bio/style.js
@@ -5,18 +5,27 @@ let stylesMap = {
multilineTextInput:{
height : 100 ,
textAlignVertical:'top',
- paddingTop:20
+ padding: 15,
+ paddingTop: 15,
+ marginTop: 0
},
- suggestionText:{
- fontWeight:"normal",
- color:Colors.midNightblue,
- fontSize:18
- },
- suggestionTextWrapper : {
- marginTop:20
+ dropDownStyle: {
+ position: 'absolute',
+ top: 99,
+ width: '100%',
+ zIndex: 1,
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 1
+ },
+ shadowOpacity: 0.2,
+ shadowRadius: 1.5,
+ elevation: 1
},
countStyle:{
fontSize:10,
+ marginTop: 5,
textAlign:'right'
}
};
diff --git a/src/components/BottomStatus/Base.js b/src/components/BottomStatus/Base.js
new file mode 100644
index 00000000..9d8d788d
--- /dev/null
+++ b/src/components/BottomStatus/Base.js
@@ -0,0 +1,183 @@
+import React, { PureComponent } from 'react';
+import { View, Text } from 'react-native';
+
+import inlineStyles from './styles';
+import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
+import reduxGetter from '../../services/ReduxGetters';
+
+import multipleClickHandler from '../../services/MultipleClickHandler';
+import InAppBrowser from '../../services/InAppBrowser';
+import Utilities from '../../services/Utilities';
+import CurrentUser from '../../models/CurrentUser';
+
+class BottomStatus extends PureComponent {
+ constructor(props) {
+ super(props);
+ }
+
+ onLinkClick = () => {
+ InAppBrowser.openBrowser(this.props.link);
+ };
+
+ navigateToUserProfile = () => {
+ if(!this.props.isUserNavigate) return;
+ if (Utilities.checkActiveUser()) {
+ if (this.props.userId == CurrentUser.getUserId()) {
+ this.props.navigation.navigate('ProfileScreen');
+ } else {
+ this.props.navigation.push('UsersProfileScreen', { userId: this.props.userId });
+ }
+ }
+ };
+
+ isValidTag(descriptionId, tappedText) {
+ if(tappedText.indexOf('#') != 0 ) return false;
+ return this.isValidIncludes( descriptionId, tappedText );
+ }
+
+ isValidMention(descriptionId, tappedText) {
+ if(tappedText.indexOf('@') != 0 ) return false;
+ return this.isValidIncludes( descriptionId, tappedText );
+ }
+
+ isValidIncludes(descriptionId, tappedText){
+ return !!reduxGetter.getTappedIncludesEntity(descriptionId, tappedText);
+ }
+
+ getHashTagMarkup( item , prevText ){
+ const tagText = item.replace("#", "");
+ return (
+
+ {prevText}
+ {
+ this.onIncludesPressed(item)
+ }}>
+ #
+ {tagText}
+
+
+ );
+ }
+
+ getMentionMarkup( item , prevText ){
+ const mentionText = item.replace("@", "");
+ return (
+
+ {prevText}
+ {
+ this.onIncludesPressed(item)
+ }}>
+ @
+ {mentionText}
+
+
+ );
+ }
+
+ onIncludesPressed = (tag) => {
+ if(!Utilities.checkActiveUser()) return;
+
+ let tapEntity = reduxGetter.getTappedIncludesEntity(this.props.entityDescriptionId, tag);
+ if (!tapEntity) {
+ return;
+ }
+
+ if( tapEntity.kind === 'tags'){
+ this.props.navigation.push('VideoTags', { "tagId": tapEntity.id });
+ return;
+ }
+
+ if( tapEntity.kind === 'users'){
+ if (tapEntity.id == CurrentUser.getUserId()) {
+ this.props.navigation.navigate('ProfileScreen');
+ }else{
+ this.props.navigation.push('UsersProfileScreen', { userId: tapEntity.id });
+ }
+ return;
+ }
+ };
+
+ getTextMarkup( item , prevText){
+ return (
+
+ {prevText + item}
+
+ )
+ }
+
+ render() {
+
+ let processingString = this.props.description;
+ let includesArray = processingString.match(/(#|@)\w+/g) || [];
+
+ return (
+
+
+
+ this.navigateToUserProfile())} pointerEvents={'auto'}>
+ {!!this.props.userName &&
+
+ {`@${this.props.userName}`}
+ }
+
+ {this.props.description ? (
+
+
+ {(includesArray.map((item) => {
+ let tagLocation = processingString.search(item);
+ let prevText = processingString.slice(0, tagLocation);
+ processingString = processingString.slice(tagLocation + item.length);
+ if (this.isValidTag(this.props.entityDescriptionId, item)) {
+ return this.getHashTagMarkup(item, prevText);
+ } if( this.isValidMention(this.props.entityDescriptionId , item) ){
+ return this.getMentionMarkup(item, prevText);
+ }else {
+ return this.getTextMarkup(item, prevText);
+ }
+ }))}
+
+ {processingString}
+
+
+ ) : (
+
+ )
+ }
+
+
+ {this.props.link ? (
+ {
+ this.onLinkClick();
+ })}
+ pointerEvents={'auto'}
+ >
+
+ {this.props.link.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')}
+
+
+ ) : (
+
+ )}
+
+ );
+ };
+}
+
+BottomStatus.defaultProps = {
+ isUserNavigate : true
+}
+
+export default BottomStatus;
diff --git a/src/components/BottomStatus/ReplyVideoBottomStatus.js b/src/components/BottomStatus/ReplyVideoBottomStatus.js
new file mode 100644
index 00000000..a352a1d6
--- /dev/null
+++ b/src/components/BottomStatus/ReplyVideoBottomStatus.js
@@ -0,0 +1,20 @@
+import reduxGetter from "../../services/ReduxGetters";
+import { connect } from 'react-redux';
+import Base from "./Base"
+import { withNavigation } from "react-navigation";
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ userName: reduxGetter.getUserName(ownProps.userId, state),
+ name: reduxGetter.getName(ownProps.userId, state),
+ entityDescriptionId : reduxGetter.getReplyDescriptionId(ownProps.entityId),
+ description: reduxGetter.getVideoDescription(reduxGetter.getReplyDescriptionId(ownProps.entityId, state), state),
+ link: reduxGetter.getVideoLink(reduxGetter.getReplyLinkId(ownProps.entityId, state), state),
+ supporters: reduxGetter.getReplySupporters(ownProps.entityId),
+ totalBt: reduxGetter.getReplyBt(ownProps.entityId, state)
+ };
+ };
+
+const ReplyVideoBottomStatus = connect(mapStateToProps)( withNavigation( Base ));
+
+export default ReplyVideoBottomStatus;
diff --git a/src/components/BottomStatus/VideoBottomStatus.js b/src/components/BottomStatus/VideoBottomStatus.js
new file mode 100644
index 00000000..f3741ffa
--- /dev/null
+++ b/src/components/BottomStatus/VideoBottomStatus.js
@@ -0,0 +1,20 @@
+import reduxGetter from "../../services/ReduxGetters";
+import { connect } from 'react-redux';
+import Base from "./Base"
+import { withNavigation } from "react-navigation";
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ userName: reduxGetter.getUserName(ownProps.userId, state),
+ name: reduxGetter.getName(ownProps.userId, state),
+ entityDescriptionId : reduxGetter.getVideoDescriptionId(ownProps.entityId),
+ description: reduxGetter.getVideoDescription(reduxGetter.getVideoDescriptionId(ownProps.entityId, state), state),
+ link: reduxGetter.getVideoLink(reduxGetter.getVideoLinkId(ownProps.entityId, state), state),
+ supporters: reduxGetter.getVideoSupporters(ownProps.entityId),
+ totalBt: reduxGetter.getVideoBt(ownProps.entityId, state)
+ };
+ };
+
+const VideoBottomStatus = connect(mapStateToProps)( withNavigation( Base ));
+
+export default VideoBottomStatus ;
diff --git a/src/components/BottomStatus/styles.js b/src/components/BottomStatus/styles.js
new file mode 100644
index 00000000..f06df144
--- /dev/null
+++ b/src/components/BottomStatus/styles.js
@@ -0,0 +1,30 @@
+import { Dimensions} from 'react-native';
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../theme/styles/Colors';
+
+const { height} = Dimensions.get('window');
+
+let stylesMap = {
+
+ bottomBg: {
+ backgroundColor: 'rgba(0, 0, 0, 0.6)',
+ borderTopLeftRadius: 20,
+ minHeight: height * 0.05,
+ paddingHorizontal: 12
+ },
+
+ bottomBgTxt: {
+ color: Colors.white
+ },
+ handle: {
+ fontSize: 15,
+ paddingBottom: 3,
+ color: Colors.white,
+ fontFamily: 'AvenirNext-DemiBold',
+ fontWeight: '700'
+ }
+}
+
+;
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CaptureVideo/index.js b/src/components/CaptureVideo/index.js
index ba824740..23208b81 100644
--- a/src/components/CaptureVideo/index.js
+++ b/src/components/CaptureVideo/index.js
@@ -2,9 +2,15 @@ import React, { Component } from 'react';
import VideoRecorder from '../VideoRecorder';
import { View } from 'react-native';
import PreviewRecordedVideo from '../PreviewRecordedVideo';
+import Store from "../../store";
+import {upsertRecordedVideo} from "../../actions";
+import utilities from '../../services/Utilities';
+import CurrentUser from '../../models/CurrentUser';
+import AppConfig from '../../constants/AppConfig';
+import deepGet from 'lodash/get';
import FanVideoDetails from '../FanVideoDetails';
import KeepAwake from 'react-native-keep-awake';
-
+import reduxGetters from "../../services/ReduxGetters";
class CaptureVideo extends Component {
@@ -13,34 +19,124 @@ class CaptureVideo extends Component {
};
constructor(props) {
super(props);
+ let isChargeble = props.navigation.getParam("isChargeble");
this.state = {
recordingScreen: true,
videoUri: '',
actionSheetOnRecordVideo: true,
modalVisible: true,
- acceptedCameraTnC: null
+ acceptedCameraTnC: null,
+ showLightBoxOnReply: isChargeble
};
+ this.replyReceiverUserId = null;
+ this.replyReceiverVideoId = null;
+ this.amountToSendWithReply = null;
+ this.videoType = null;
+ this.proceedWithExisting = null;
+ this.setReplyVideoParams();
+ this.showCoachForVideoRecord();
+
+ }
+
+ componentDidMount () {}
+
+
+ showCoachForVideoRecord() {
+ const oThis = this;
+ if (this.isVideoTypePost()) {
+ utilities.getItem(`${CurrentUser.getUserId()}-accepted-camera-t-n-c`).then((terms) => {
+ oThis.setState({ acceptedCameraTnC: terms });
+ });
+ }
+ }
+
+ setReplyVideoParams(){
+ this.videoType = this.props.navigation.getParam("videoType");
+ if (this.isVideoTypeReply()){
+ this.replyReceiverUserId = this.props.navigation.getParam("userId");
+ this.replyReceiverVideoId = this.props.navigation.getParam("videoId");
+ this.amountToSendWithReply = this.props.navigation.getParam("amount");
+ this.isChargeble = this.props.navigation.getParam("isChargeble");
+ this.toTokenHolderAddress = this.props.navigation.getParam("toTokenHolderAddress");
+
+ } else {
+ // Do nothing.
+ }
}
+ isVideoTypePost(){
+ return this.videoType === AppConfig.videoTypes.post;
+ }
+
+ isVideoTypeReply = () => {
+ return this.videoType === AppConfig.videoTypes.reply;
+ };
+
goToRecordScreen() {
this.setState({
recordingScreen: true,
actionSheetOnRecordVideo: false,
- acceptedCameraTnC: 'true'
+ acceptedCameraTnC: 'true',
+ showLightBoxOnReply: false
});
}
- goToPreviewScreen(videoUri) {
- this.setState({
+
+ proceedWithExistingVideo = (recordedVideoObj) => {
+ this.proceedWithExisting = true;
+ this.videoType = recordedVideoObj.video_type || AppConfig.videoTypes.post ;
+ this.setState ({
recordingScreen: false,
- videoUri
+ videoUri: recordedVideoObj.raw_video
});
+ };
+
+
+ saveVideoPrimaryInfo = () => {
+ this.proceedWithExisting = false;
+
+ Store.dispatch(upsertRecordedVideo(this.getPrimaryVideoInfo()));
+ };
+
+
+ getPrimaryVideoInfo = () => {
+ if (this.proceedWithExisting) return {};
+
+ if (this.isVideoTypeReply()){
+ return { video_type: AppConfig.videoTypes.reply , reply_obj: this.getReplyOptions()};
+ } else if (this.isVideoTypePost()) {
+ return { video_type: AppConfig.videoTypes.post };
+ }
+
+ };
+
+
+ goToDetailsScreen () {
+ if (this.videoType === AppConfig.videoTypes.post ){
+ this.props.navigation.push('FanVideoDetails', this.getPrimaryVideoInfo());
+ } else if (this.videoType === AppConfig.videoTypes.reply ){
+ this.props.navigation.push('FanVideoReplyDetails', this.getPrimaryVideoInfo());
+ }
+ }
+
+ getReplyOptions(){
+ // Reply options are received to View when user click on Record video (Plus icon).
+ let replyOptions = {};
+ if ( this.isVideoTypeReply()) {
+ replyOptions['replyReceiverUserId'] = this.replyReceiverUserId;
+ replyOptions['replyReceiverVideoId'] = this.replyReceiverVideoId;
+ replyOptions['amountToSendWithReply'] = this.amountToSendWithReply;
+ replyOptions['isChargeble'] = this.isChargeble;
+ replyOptions['toTokenHolderAddress'] = this.toTokenHolderAddress;
+ }
+ return replyOptions;
}
- goToDetailsScreen() {
- this.props.navigation.push('FanVideoDetails');
+ getName(){
+ return reduxGetters.getUserName(deepGet (reduxGetters.getRecordedVideo(),'reply_obj.replyReceiverUserId'));
}
+
modalRequestClose = () => {
if (this.state.recordingScreen) {
this.props.navigation.goBack();
@@ -49,6 +145,22 @@ class CaptureVideo extends Component {
}
};
+ getActionSheetText = (videoObject) => {
+ if (videoObject.video_type ===AppConfig.videoTypes.reply ){
+ return 'You have a pre-recorded reply';
+ } else if (videoObject.video_type === AppConfig.videoTypes.post ) {
+ return 'You have already recorded video';
+ }
+ };
+
+ goToPreviewScreen = (videoUri) => {
+ this.setState({
+ recordingScreen: false,
+ videoUri
+ });
+ };
+
+
getCurrentView() {
if (this.state.recordingScreen) {
return (
@@ -57,11 +169,16 @@ class CaptureVideo extends Component {
this.videoRecorder = recorder;
}}
acceptedCameraTnC={this.state.acceptedCameraTnC}
- goToPreviewScreen={(videoUri) => {
- this.goToPreviewScreen(videoUri);
- }}
+ proceedWithExistingVideo={this.proceedWithExistingVideo}
+ saveVideoPrimaryInfo={this.saveVideoPrimaryInfo}
+ goToPreviewScreen={this.goToPreviewScreen}
actionSheetOnRecordVideo={this.state.actionSheetOnRecordVideo}
+ getActionSheetText={this.getActionSheetText}
navigation={this.props.navigation}
+ isVideoTypeReply={this.isVideoTypeReply()}
+ showLightBoxOnReply={this.state.showLightBoxOnReply}
+ videoId={this.replyReceiverVideoId}
+
/>
);
} else {
@@ -76,6 +193,7 @@ class CaptureVideo extends Component {
goToDetailsScreen={() => {
this.goToDetailsScreen();
}}
+ saveVideoPrimaryInfo={this.saveVideoPrimaryInfo}
cachedvideoUrl={this.state.videoUri}
navigation={this.props.navigation}
/>
diff --git a/src/components/CommonComponents/BottomReplyBar/index.js b/src/components/CommonComponents/BottomReplyBar/index.js
new file mode 100644
index 00000000..402a2340
--- /dev/null
+++ b/src/components/CommonComponents/BottomReplyBar/index.js
@@ -0,0 +1,40 @@
+import React, { PureComponent } from 'react';
+import { View , Text , Image } from 'react-native';
+import { withNavigation } from 'react-navigation';
+import inlineStyles from './styles';
+import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
+import cameraIconWhite from '../../../assets/reply-video-white.png';
+
+import {navigateToCamera, replyPreValidationAndMessage} from "../../../helpers/cameraHelper";
+import multipleClickHandler from '../../../services/MultipleClickHandler';
+
+class BottomReplyBar extends PureComponent {
+
+ constructor(props){
+ super(props);
+ }
+
+ replyVideo =( ) => {
+ if(!this.props.videoId || !this.props.userId) return;
+ if( replyPreValidationAndMessage( this.props.videoId , this.props.userId) ) {
+ navigateToCamera( this.props.videoId , this.props.userId , this.props.navigation ) ;
+ }
+ }
+
+ render(){
+ return(
+
+ this.replyVideo())} >
+
+
+ Add a reply...
+
+
+
+ );
+
+ }
+
+}
+
+export default withNavigation( BottomReplyBar )
diff --git a/src/components/CommonComponents/BottomReplyBar/styles.js b/src/components/CommonComponents/BottomReplyBar/styles.js
new file mode 100644
index 00000000..97d9048f
--- /dev/null
+++ b/src/components/CommonComponents/BottomReplyBar/styles.js
@@ -0,0 +1,26 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../../theme/styles/Colors';
+import { CUSTOM_TAB_Height } from "../../../theme/constants";
+
+let stylesMap = {
+ wrapper : {
+ flex: 1,
+ height: CUSTOM_TAB_Height,
+ backgroundColor: Colors.darkShadeOfGray,
+ paddingHorizontal: 10,
+ justifyContent: 'center',
+ borderTopWidth: 0.5,
+ borderColor: 'rgba(151, 151, 151, 0.6)'
+ },
+ text: {
+ color: Colors.white,
+ marginLeft: 10,
+ fontFamily: 'AvenirNext-Medium'
+ },
+ replyIconSkipFont : {
+ height:10,
+ width:15
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/BubbleList/index.js b/src/components/CommonComponents/BubbleList/index.js
new file mode 100644
index 00000000..db9a2764
--- /dev/null
+++ b/src/components/CommonComponents/BubbleList/index.js
@@ -0,0 +1,136 @@
+import React, { PureComponent } from 'react';
+import inlineStyles from './styles';
+import { Text, View, TouchableOpacity} from 'react-native';
+import { withNavigation } from 'react-navigation';
+
+import DataContract from '../../../constants/DataContract';
+import deepGet from "lodash/get";
+import reduxGetter from "../../../services/ReduxGetters";
+import multipleClickHandler from '../../../services/MultipleClickHandler';
+import {FetchServices} from "../../../services/FetchServices";
+import SingleBubble from '../SingleBubble';
+import {connect} from "react-redux";
+import Utilities from '../../../services/Utilities';
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ replyCount : reduxGetter.getVideoReplyCount(ownProps.videoId)
+ };
+};
+
+
+//
+const NO_OF_ITEMS_TO_SHOW = 3;
+
+class BubbleList extends PureComponent {
+
+ static navigationOptions = {
+ header: null
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ list: []
+ };
+ this.fetchServices = new FetchServices(this.getFetchUrl());
+ this.getDataWhileLoading();
+ this.onClickHandler = this.props.onClickHandler || this.defaultClickHandler;
+ }
+
+ componentDidUpdate(prevProps, prevState ) {
+ if( this.props.doRender && this.props.doRender !== prevProps.doRender ){
+ this.getListData();
+ }
+ if (this.props.replyCount != prevProps.replyCount){
+ this.getListData();
+ }
+ }
+
+
+ getFetchUrl = () => {
+ return `/videos/${this.props.videoId}/replies`;
+ };
+
+
+
+ getDataWhileLoading(){
+ if (this.props.doRender){
+ this.getListData();
+ }
+ };
+
+ getListData = () => {
+ if ( this.props.replyCount == 0 ) {
+ return;
+ }
+
+ this.getFetchService()
+ .refresh()
+ .then((res) => {
+ this.onRefresh(res);
+ })
+ .catch((error) => {
+ //this.onRefreshError(error);
+ console.log(error);
+ });
+ };
+
+
+ onRefresh = (res) => {
+ let listToBeShownOnUI = this.fetchServices.getAllResults().slice(0,NO_OF_ITEMS_TO_SHOW);
+ this.replyCount = reduxGetter.getVideoReplyCount(this.props.videoId);
+ this.setState({ list : listToBeShownOnUI } );
+
+ };
+
+ getBubbleListJSX = () => {
+ let listToRender = this.state.list;
+ return listToRender.length? listToRender.map((item) => {
+ let userId = deepGet(item,'payload.user_id'),
+ replyDetailId=deepGet(item,'payload.reply_detail_id');
+ return
+ }): <>> ;
+ };
+
+ moreReplyText = () => {
+
+ let list = this.state.list;
+ if (! this.replyCount || ! list.length){
+ return ''
+ }
+ if (this.replyCount > list.length){
+ return ` + ${this.replyCount - list.length} Replies`;
+ }
+ };
+
+ getFetchService = () => {
+ return this.fetchServices;
+ }
+
+ defaultClickHandler= ()=> {
+ const baseUrl = DataContract.replies.getReplyListApi(this.props.videoId);
+Â Â Â Â this.props.navigation.push('FullScreenReplyCollection',{
+Â Â Â Â Â Â "baseUrl":Â baseUrl,
+ "fetchServices":this.getFetchService()
+Â Â Â Â Â Â Â Â });
+ }
+
+ onIconClick = () => {
+ if(!Utilities.checkActiveUser()) return;
+ this.onClickHandler();
+ }
+
+ render() {
+ return
+ {this.onIconClick()})}
+ style={{flexDirection: 'row-reverse', marginRight: 5}}>{this.getBubbleListJSX()}
+
+ {/*{this.moreReplyText()}*/}
+
+ }
+}
+
+
+//make this component available to the app
+export default connect(mapStateToProps)(withNavigation(BubbleList)) ;
diff --git a/src/components/CommonComponents/BubbleList/styles.js b/src/components/CommonComponents/BubbleList/styles.js
new file mode 100644
index 00000000..a5421c81
--- /dev/null
+++ b/src/components/CommonComponents/BubbleList/styles.js
@@ -0,0 +1,39 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../../theme/styles/Colors';
+
+let stylesMap = {
+
+ bubbleShadow: {
+ shadowColor: Colors.wildWatermelon2,
+ shadowOffset: { width: 0, height: 0 },
+ shadowOpacity: 0.8,
+ shadowRadius: 5,
+ elevation: 3,
+ borderColor: Colors.wildWatermelon2,
+ borderWidth: .5,
+ borderRadius: 20
+ },
+
+ bubbleSize: {
+ height: 38,
+ width: 38,
+ borderColor: 'white',
+ borderWidth: 1,
+ borderRadius: 20
+ },
+
+ bubbleContainer: {
+ flexDirection:'row',
+ marginLeft: 30,
+ alignItems: 'center'
+ },
+
+ repliesTxt: {
+ color: 'white',
+ fontSize: 16,
+ fontFamily: 'AvenirNext-DemiBold'
+ }
+
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/DeleteVideo/index.js b/src/components/CommonComponents/DeleteVideo/index.js
index 4051062f..ddb61f13 100644
--- a/src/components/CommonComponents/DeleteVideo/index.js
+++ b/src/components/CommonComponents/DeleteVideo/index.js
@@ -19,14 +19,13 @@ export default class DeleteVideo extends Component {
super(props);
}
- deleteUser = () => {
- if(!this.props.videoId) return;
- new PepoApi(`/videos/${this.props.videoId}/delete`)
+ deleteEntity = () => {
+ if(!this.props.fetchUrl) return;
+ new PepoApi(this.props.fetchUrl)
.post()
.then((response) => {
-
if (response && response.success){
- this.props.removeVideo && this.props.removeVideo(this.props.videoId);
+ this.props.removeVideo && this.props.removeVideo();
Toast.show({text:'Video deleted successfully!', icon: 'success'});
} else {
Toast.show({text:ostErrors.getUIErrorMessage('delete_video_error'), icon: 'error'});
@@ -43,7 +42,7 @@ export default class DeleteVideo extends Component {
'',
'Are you sure to delete video?',
[
- {text: 'Delete', onPress: () => this.deleteUser() },
+ {text: 'Delete', onPress: () => this.deleteEntity() },
{
text: 'Cancel',
style: 'cancel'
diff --git a/src/components/CommonComponents/DeletedVideoInfo/index.js b/src/components/CommonComponents/DeletedVideoInfo/index.js
new file mode 100644
index 00000000..3253725b
--- /dev/null
+++ b/src/components/CommonComponents/DeletedVideoInfo/index.js
@@ -0,0 +1,25 @@
+import React, {PureComponent} from 'react';
+import {TouchableOpacity, View, Image, Text} from 'react-native';
+import {withNavigation} from 'react-navigation';
+
+import video_not_available from '../../../assets/video-not-available.png';
+import historyBack from "../../../assets/user-video-history-back-icon.png";
+import inlineStyles from './styles';
+
+class DeletedVideoInfo extends PureComponent{
+ constructor(props){
+ super(props);
+ }
+
+ render(){
+ return (
+ this.props.navigation.goBack()} style={inlineStyles.historyBackSkipFont}>
+
+
+
+ Looks like the Video you were looking for isn’t available and might have been deleted by the creator!
+ );
+ }
+}
+
+export default withNavigation(DeletedVideoInfo);
\ No newline at end of file
diff --git a/src/components/CommonComponents/DeletedVideoInfo/styles.js b/src/components/CommonComponents/DeletedVideoInfo/styles.js
new file mode 100644
index 00000000..00b62fe2
--- /dev/null
+++ b/src/components/CommonComponents/DeletedVideoInfo/styles.js
@@ -0,0 +1,43 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import {ifIphoneX} from "react-native-iphone-x-helper";
+import Colors from '../../../theme/styles/Colors';
+
+let stylesMap = {
+
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.snow
+ },
+
+ imgSizeSkipFont: {
+ width: 68.5,
+ height: 68.5
+ },
+
+ desc:{
+ fontSize: 22,
+ marginTop: 10,
+ textAlign: 'center',
+ paddingHorizontal: 25,
+ color: Colors.valhalla,
+ fontFamily: 'AvenirNext-Regular'
+ },
+
+ historyBackSkipFont:{
+ ...ifIphoneX({
+ top: 55,
+ }, {
+ top: 25,
+ }),
+ width: 29,
+ height: 34,
+ position: 'absolute',
+ left: 10,
+ alignItems: 'center',
+ justifyContent: 'center'
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/FlotingBackArrow/index.js b/src/components/CommonComponents/FlotingBackArrow/index.js
new file mode 100644
index 00000000..3fd1489d
--- /dev/null
+++ b/src/components/CommonComponents/FlotingBackArrow/index.js
@@ -0,0 +1,24 @@
+import React, { PureComponent } from 'react';
+import {Image,TouchableOpacity} from 'react-native';
+
+import historyBack from "../../../assets/user-video-history-back-icon.png";
+import inlineStyles from './styles'
+import { withNavigation } from 'react-navigation';
+
+class FloatingBackArrow extends PureComponent {
+
+ constructor(props){
+ super(props);
+ }
+
+ render(){
+ return (
+ this.props.navigation.goBack(null)} style={inlineStyles.historyBackSkipFont}>
+
+
+ )
+ }
+
+}
+
+export default withNavigation( FloatingBackArrow );
\ No newline at end of file
diff --git a/src/components/CommonComponents/FlotingBackArrow/styles.js b/src/components/CommonComponents/FlotingBackArrow/styles.js
new file mode 100644
index 00000000..9a135846
--- /dev/null
+++ b/src/components/CommonComponents/FlotingBackArrow/styles.js
@@ -0,0 +1,20 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import {ifIphoneX} from "react-native-iphone-x-helper";
+
+let stylesMap = {
+ historyBackSkipFont:{
+ ...ifIphoneX({
+ top: 55,
+ }, {
+ top: 25,
+ }),
+ width: 29,
+ height: 34,
+ position: 'absolute',
+ left: 10,
+ alignItems: 'center',
+ justifyContent: 'center'
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/InAppBrowser/index.js b/src/components/CommonComponents/InAppBrowser/index.js
index 20cca936..21057808 100644
--- a/src/components/CommonComponents/InAppBrowser/index.js
+++ b/src/components/CommonComponents/InAppBrowser/index.js
@@ -12,6 +12,7 @@ import ForwardActive from '../../../assets/ForwardActive.png';
import BrowserMenu from './BrowserMenu';
import { getHostName } from '../../../helpers/helpers';
import Colors from '../../../theme/styles/Colors';
+import CommonStyle from '../../../theme/styles/Common';
export default class InAppBrowserComponent extends Component {
static navigationOptions = (props) => {
@@ -92,7 +93,7 @@ export default class InAppBrowserComponent extends Component {
render() {
return (
-
+
{this.state.loadingProgress != 1 && (
{
+ return {
+ seen: reduxGetters.isReplySeen( deepGet(ownProps.payload,'reply_detail_id'))
+ };
+};
+
+class ReplyThumbnailItem extends Component {
+
+ constructor(props) {
+ super(props);
+ this.videoId = this.props.payload.video_id;
+ this.replyDetailId = this.props.payload.reply_detail_id;
+ this.userId = reduxGetters.getReplyEntity(this.replyDetailId).creator_user_id;
+ }
+
+ render() {
+ return
+ { this.props.onClickHandler();})}
+ style={[inlineStyle.wrapperStyle, !this.props.seen && inlineStyle.unseen, this.props.isActive && inlineStyle.active]}>
+
+
+
+ }
+
+ isActiveOrUnseen = () => {
+ return !this.props.seen || this.props.isActive;
+ }
+
+}
+
+const outerRingDiameter = AppConfig.thumbnailListConstants.outerRingDiameter;
+const outerBorderWidth = AppConfig.thumbnailListConstants.outerBorderWidth;
+const transparentGap = AppConfig.thumbnailListConstants.transparentGap;
+const iconImageDiameter = AppConfig.thumbnailListConstants.iconImageDiameter();
+
+const inlineStyle= {
+ iconStyle: { height: iconImageDiameter,
+ width: iconImageDiameter,
+ borderRadius: iconImageDiameter/ 2,
+ marginLeft: transparentGap,
+ marginTop: transparentGap
+ },
+ wrapperStyle: {
+ width: outerRingDiameter,
+ height: outerRingDiameter,
+ borderRadius: outerRingDiameter/ 2,
+ borderWidth: outerBorderWidth,
+ borderColor: 'transparent',
+ },
+ active: {
+ borderColor: '#fff',
+ },
+ unseen: {
+ borderColor: '#FD8691'
+ }
+};
+
+//make this component available to the app
+export default connect(mapStateToProps)(ReplyThumbnailItem);
diff --git a/src/components/CommonComponents/InvertedReplyThumbnailList/index.js b/src/components/CommonComponents/InvertedReplyThumbnailList/index.js
new file mode 100644
index 00000000..0abbfeee
--- /dev/null
+++ b/src/components/CommonComponents/InvertedReplyThumbnailList/index.js
@@ -0,0 +1,335 @@
+import React, { PureComponent } from 'react';
+import { View } from 'react-native';
+import { withNavigation } from 'react-navigation';
+import deepGet from "lodash/get";
+
+import Pagination from "../../../services/Pagination";
+import ReplyThumbnailItem from './ReplyThumbnailItem'
+import {FlatList} from 'react-native-gesture-handler';
+import ReplyHelper from '../../../helpers/ReplyHelper';
+import AppConfig from "../../../constants/AppConfig";
+import DataContract from '../../../constants/DataContract';
+import ReduxGetters from '../../../services/ReduxGetters';
+import Utilities from '../../../services/Utilities';
+
+
+const ITEM_HEIGHT = AppConfig.thumbnailListConstants.cellHeight();
+const ITEM_SEPERATOR_HEIGHT = AppConfig.thumbnailListConstants.separatorHeight;
+
+class InvertedReplyList extends PureComponent {
+
+ static navigationOptions = {
+ header: null
+ };
+
+ constructor(props) {
+ super(props);
+ this.paginationService = null;
+ this.hasInitialData = true;
+ this.setPagination();
+
+ this.state = {
+ list: this.getInitialList(),
+ refreshing : false,
+ loadingNext: false
+ };
+
+ this.listRef = null;
+ this.onItemClick = null;
+ }
+
+ getInitialList = () => {
+ if (this.props.paginationService){
+ return this.paginationService.getResults();
+ }
+ return [];
+ };
+
+ setClickHandlers = ()=> {
+ this.onItemClick = this.props.onChildClickDelegate || this.defaultChildClickHandler;
+ };
+
+ getPagination = () => {
+ return this.paginationService;
+ };
+
+ componentDidMount () {
+ this.bindPaginationEvents();
+ this.setClickHandlers();
+ }
+
+ bubbleClickHandler = ()=> {
+ this.props.navigation.goBack(null);
+ }
+
+ getParentClickHandler =( videoId )=>{
+ return () => {
+ let parentUserId = ReduxGetters.getVideoCreatorUserId(videoId);
+ this.props.navigation.push('VideoPlayer', {
+ userId: parentUserId,
+ videoId: videoId,
+ bubbleClickHandler: this.bubbleClickHandler
+ });
+ }
+ }
+
+ defaultChildClickHandler = ( index, item )=>Â {
+ const videoId = ReduxGetters.getReplyParentVideoId(deepGet(item , "payload.reply_detail_id")),
+ baseUrl = DataContract.replies.getReplyListApi(videoId),
+ clonedInstance = this.getPagination().fetchServices.cloneInstance();
+ ReplyHelper.updateEntitySeen( item );
+Â Â Â Â this.props.navigation.push('FullScreenReplyCollection',{
+Â Â Â Â Â Â "fetchServices": clonedInstance,
+Â Â Â Â Â Â "currentIndex":index,
+Â Â Â Â Â Â "baseUrl":Â baseUrl,
+ "parentClickHandler": this.getParentClickHandler( videoId )
+Â Â Â Â });
+Â Â };
+
+ setPagination() {
+ let fetchUrl = this.getFetchUrl();
+ this.paginationService = this.props.paginationService;
+ if( !this.paginationService || !( this.paginationService instanceof Pagination)){
+ this.paginationService = new Pagination(fetchUrl);
+ if( this.props.doRender ){
+ this.initPagination();
+ }else {
+ //Load data later
+ this.hasInitialData = false;
+ }
+ }
+ }
+
+ componentWillUnmount() {
+ this.removePaginationListeners();
+ this.onItemClick = ()=> {};
+ }
+
+ componentDidUpdate(prevProps, prevState ) {
+ if( this.props.doRender && this.props.doRender !== prevProps.doRender && !this.hasInitialData ){
+ this.initPagination();
+ }
+ if(this.props.currentIndex != prevProps.currentIndex){
+ this.listRef && this.listRef.scrollToIndex({index : this.props.currentIndex, viewOffset: 100, viewPosition: 0.5});
+ }
+ }
+
+ onScrollToIndexFailed =( info) => {
+ console.log("======onScrollToIndexFailed=====" , info );
+ }
+
+ // region - Pagination and Event Handlers
+
+ initPagination(){
+ this.getPagination().initPagination();
+ }
+
+ bindPaginationEvents(){
+ let pagination = this.getPagination();
+ if ( !pagination ) {
+ return;
+ }
+ let paginationEvent = pagination.event;
+ if ( null === paginationEvent ) {
+ return;
+ }
+
+ paginationEvent.on("onBeforeRefresh" , this.beforeRefresh.bind(this) );
+ paginationEvent.on("onRefresh" , this.onRefresh.bind(this) );
+ paginationEvent.on("onRefreshError" , this.onRefreshError.bind(this));
+ paginationEvent.on("onBeforeNext" , this.beforeNext.bind(this));
+ paginationEvent.on("onNext" , this.onNext.bind(this) );
+ paginationEvent.on("onNextError" , this.onNextError.bind(this));
+ }
+
+ removePaginationListeners(){
+ let pagination = this.getPagination();
+ if ( !pagination ) {
+ return;
+ }
+ let paginationEvent = pagination.event;
+ if ( null === paginationEvent ) {
+ return;
+ }
+ paginationEvent.removeListener('onBeforeRefresh');
+ paginationEvent.removeListener('onRefresh');
+ paginationEvent.removeListener('onRefreshError');
+ paginationEvent.removeListener('onBeforeNext');
+ paginationEvent.removeListener('onNext');
+ paginationEvent.removeListener('onNextError');
+ }
+
+ getFetchUrl = () => {
+ return DataContract.replies.getReplyListApi(this.props.videoId);
+ };
+
+ scrollToTop(){
+ this.listRef.scrollToOffset({offset: 0});
+ }
+
+ beforeRefresh = ( ) => {
+ console.log('beforeRefresh')
+ this.props.beforeRefresh && this.props.beforeRefresh();
+ let stateObject = {refreshing : true};
+ if (this.state.loadingNext) {
+ stateObject['loadingNext'] = false;
+ }
+ this.setState(stateObject);
+ };
+
+ onRefresh = ( res ) => {
+ let results = this.getPagination().getResults() ;
+ this.props.onRefresh && this.props.onRefresh( results , res );
+ this.setState({ refreshing : false , list : results });
+ // this.setState({ refreshing : false , list : [results[0], results[1]] });
+ }
+
+ onRefreshError = ( error ) => {
+ this.setState({ refreshing : false });
+ }
+
+ beforeNext =() => {
+ if (this.state.refreshing) return;
+ this.setState({ loadingNext : true });
+ }
+
+ onNext = ( res ) => {
+ this.setState({ loadingNext : false , list : this.getPagination().getResults() });
+ }
+
+ onNextError = ( error ) => {
+ this.setState({ loadingNext : false });
+ }
+
+ getNext = () => {
+ this.getPagination().getNext();
+ }
+
+ refresh = () => {
+ this.getPagination().refresh();
+ };
+
+ _keyExtractor = (item, index) => {
+ return `id_${item.id}`;
+ };
+
+ _renderItem = ({item, index}) => {
+ return
+ {this.onItemClick(index, item)}}
+ isActive={this.isActiveEntity( index , item)}
+ cellIndex={index}
+ totalCells={this.state.list.length}
+ />
+ ;
+ };
+
+ isActiveEntity = ( index , item )=>{
+ if(typeof this.props.isActiveEntity == "function" ){
+ return this.props.isActiveEntity(this.props.fullVideoReplyId , item , index) ;
+ }
+ return this.props.currentIndex == index;
+ }
+
+ setListRef = (ref) => {
+ this.listRef = ref;
+ };
+
+ getItemSeperatorComponent = ({leadingItem}) => {
+ let styles = {
+ backgroundColor: AppConfig.thumbnailListConstants.separatorColor,
+ height: AppConfig.thumbnailListConstants.separatorHeight,
+ width: AppConfig.thumbnailListConstants.separatorWidth,
+ alignSelf:'center'
+ };
+
+ const separatorMargin = AppConfig.thumbnailListConstants.separatorMargin();
+
+ // Leading Item
+ let leadingItemIndex = this.state.list.indexOf(leadingItem);
+ let isLeadingSelected = this.isActiveEntity( leadingItemIndex , leadingItem);
+ let isLeadingSeen = ReduxGetters.isReplySeen( deepGet(leadingItem.payload,'reply_detail_id'));
+
+ //Top margin is needed if and only if the leading cell is seen and is not selected.
+ if ( isLeadingSeen && !isLeadingSelected ) {
+ //Leading does not have border.
+ styles.marginTop = -1 * separatorMargin;
+ styles.height = styles.height + separatorMargin;
+ }
+
+ let trailingItemIndex = leadingItemIndex + 1;
+ let trailingItem = this.state.list[trailingItemIndex];
+ let isTrailingSelected = this.isActiveEntity( trailingItemIndex , trailingItem);
+ let isTrailingSeen = ReduxGetters.isReplySeen( deepGet(trailingItem.payload,'reply_detail_id'));
+
+ //Bottom margin is needed if and only if the trailing cell is seen and is not selected.
+ if ( isTrailingSeen && !isTrailingSelected ) {
+ //Trailing cell does not have border.
+ styles.marginBottom = -1 * separatorMargin;
+ styles.height = styles.height + separatorMargin;
+ }
+
+ return
+ };
+
+ getAvailableHeight = () => {
+ let availableHeight = Utilities.getPendantAvailableHeight();
+ return availableHeight - this.props.bottomRounding;
+ }
+
+ getListHeight = () => {
+ let availableHeight = this.getAvailableHeight();
+ let noOfItems = this.state.list.length;
+ if (noOfItems > 0){
+ let heightOfElements = noOfItems * ITEM_HEIGHT,
+ heightOfSeparator = (noOfItems - 1 ) * AppConfig.thumbnailListConstants.separatorHeight,
+ heightOfFlatList = heightOfElements + heightOfSeparator ,
+ finalHeight = availableHeight > heightOfFlatList ? heightOfFlatList : availableHeight;
+ return finalHeight;
+ }
+ return 0;
+ };
+
+ getItemLayout= (data, index) => {
+ let itemLength = ITEM_SEPERATOR_HEIGHT + ITEM_HEIGHT;
+ let itemOffset = index * (itemLength);
+ return {
+ length: itemLength,
+ offset: itemOffset,
+ index: index
+ };
+ }
+
+ render() {
+ console.log("InvertedReplyList :: this.props.listKey", this.props.listKey);
+ return
+ }
+}
+
+InvertedReplyList.defaultProps = {
+ paginationService : null,
+ doRender: true,
+ currentIndex: 0,
+ bottomRounding: 10
+};
+
+//make this component available to the app
+export default withNavigation(InvertedReplyList);
diff --git a/src/components/CommonComponents/InvertedReplyThumbnailList/styles.js b/src/components/CommonComponents/InvertedReplyThumbnailList/styles.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/components/CommonComponents/NumberInput/index.js b/src/components/CommonComponents/NumberInput/index.js
new file mode 100644
index 00000000..201c2b95
--- /dev/null
+++ b/src/components/CommonComponents/NumberInput/index.js
@@ -0,0 +1,67 @@
+import React,{PureComponent} from 'react';
+import {View,Text,TextInput} from 'react-native';
+
+import NumberFormatter from '../../../helpers/NumberFormatter';
+import { ostErrors } from '../../../services/OstErrors';
+import Theme from '../../../theme/styles';
+
+export default class NumberInput extends PureComponent{
+ constructor( props ){
+ super( props );
+ this.state={
+ value : props.value,
+ errorMsg : null
+ };
+ this.numberFormatter = new NumberFormatter();
+ }
+
+ validateAndSet(val){
+ let errMsg = null;
+ if (!this.numberFormatter.isValidInputProvided(val)) {
+ errMsg = this.getErrorMessage( val );
+ }
+ this.setState({
+ value: val,
+ valueError: errMsg
+ });
+ }
+
+ getErrorMessage( val ){
+ if (val && String(val).indexOf(',') > -1) {
+ return ostErrors.getUIErrorMessage('bt_amount_decimal_error');
+ }
+ else if (val && String(val).split('.')[1] && String(val).split('.')[1].length > 2) {
+ return ostErrors.getUIErrorMessage('bt_amount_decimal_allowed_error');
+ } else {
+ return "invalid input";
+ }
+ }
+
+ onChangeText(value) {
+ let formattedVal = this.numberFormatter.convertToValidFormat(value)
+ , val = this.numberFormatter.getFullStopValue(formattedVal)
+ ;
+ this.validateAndSet(value);
+ this.props.onChangeText && this.props.onChangeText(val);
+ }
+
+ render(){
+ return(
+
+
+ {this.onChangeText(value)}}
+ value = {String(this.props.value)}
+ keyboardType = 'decimal-pad'
+ style={{paddingVertical: 0}}
+ />
+
+ { this.props.errorMsg || this.state.valueError }
+
+
+
+ )
+ }
+}
+
+
diff --git a/src/components/CommonComponents/ReplyIcon/index.js b/src/components/CommonComponents/ReplyIcon/index.js
new file mode 100644
index 00000000..693865bd
--- /dev/null
+++ b/src/components/CommonComponents/ReplyIcon/index.js
@@ -0,0 +1,58 @@
+import React, { PureComponent } from 'react';
+import {TouchableOpacity , Image, View, Text} from "react-native";
+import { connect } from 'react-redux';
+import {withNavigation} from "react-navigation";
+import reduxGetter from '../../../services/ReduxGetters';
+import inlineStyles from './styles';
+import multipleClickHandler from "../../../services/MultipleClickHandler";
+import reply_video from '../../../assets/video-reply.png';
+import Utilities from '../../../services/Utilities';
+import NavigationService from "../../../services/NavigationService";
+import utilities from "../../../services/Utilities";
+import {getVideoReplyObject, replyPreValidationAndMessage} from "../../../helpers/cameraHelper";
+import Pricer from "../../../services/Pricer";
+
+const mapStateToProps = (state , ownProps) => {
+ return {
+ videoReplyCount : reduxGetter.getVideoReplyCount(ownProps.videoId, state)
+ }
+};
+
+class ReplyIcon extends PureComponent {
+
+ constructor(props){
+ super(props);
+ };
+
+ replyVideo = ()=> {
+
+ if(!Utilities.checkActiveUser()) return;
+
+ if ( this.props.videoReplyCount > 0 ) {
+ this.props.navigation.push('VideoReplies',
+ {'videoId': this.props.videoId ,
+ 'userId': this.props.userId
+ });
+ } else if( replyPreValidationAndMessage(this.props.videoId , this.props.userId ) ){
+ let activeTab = NavigationService.getActiveTab();
+ let params = getVideoReplyObject(this.props.videoId, this.props.userId);
+ utilities.handleVideoUploadModal(activeTab, this.props.navigation, params);
+ }
+
+ };
+
+ render(){
+ return (
+
+ {Pricer.toDisplayAmount(this.props.videoReplyCount)}
+ this.replyVideo())} >
+
+
+ );
+ }
+
+};
+
+export default connect(mapStateToProps)(withNavigation(ReplyIcon));
diff --git a/src/components/CommonComponents/ReplyIcon/styles.js b/src/components/CommonComponents/ReplyIcon/styles.js
new file mode 100644
index 00000000..70893536
--- /dev/null
+++ b/src/components/CommonComponents/ReplyIcon/styles.js
@@ -0,0 +1,24 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../../theme/styles/Colors';
+
+let stylesMap = {
+
+ replyIconWrapper : {
+ marginBottom: 5,
+ height: 40,
+ width: 40,
+ alignItems: 'center',
+ justifyContent: 'center'
+ },
+ videoReplyCount : {
+ fontSize: 18,
+ color: Colors.white,
+ alignSelf: 'center',
+ textShadowColor: 'rgba(0, 0, 0, 0.65)',
+ textShadowOffset: {width: 1, height: 1},
+ textShadowRadius: 1,
+ fontFamily: 'AvenirNext-DemiBold'
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/ReportVideo/index.js b/src/components/CommonComponents/ReportVideo/index.js
index 7560c9f8..fe653f19 100644
--- a/src/components/CommonComponents/ReportVideo/index.js
+++ b/src/components/CommonComponents/ReportVideo/index.js
@@ -32,7 +32,7 @@ class ReportVideo extends PureComponent {
reportVideo = () => {
new PepoApi('/report')
- .post({report_entity_kind: 'video', report_entity_id: this.props.videoId })
+ .post({report_entity_kind: this.props.reportKind, report_entity_id: this.props.reportEntityId })
.then((response) => {
if (response && response.success){
Toast.show({text:'Video reported successfully!', icon: 'success' });
@@ -87,7 +87,7 @@ class ReportVideo extends PureComponent {
render(){
return this.isVisible() && ( this.showActionSheet())} >
)
diff --git a/src/components/CommonComponents/ShareIcon/index.js b/src/components/CommonComponents/ShareIcon/Base.js
similarity index 58%
rename from src/components/CommonComponents/ShareIcon/index.js
rename to src/components/CommonComponents/ShareIcon/Base.js
index fea0a3d1..510569c0 100644
--- a/src/components/CommonComponents/ShareIcon/index.js
+++ b/src/components/CommonComponents/ShareIcon/Base.js
@@ -1,44 +1,33 @@
import React, { PureComponent } from 'react';
import {TouchableOpacity , Image} from "react-native";
-import { connect } from 'react-redux';
-import reduxGetter from '../../../services/ReduxGetters';
-import inlineStyles from './styles';
import multipleClickHandler from "../../../services/MultipleClickHandler";
import ShareVideo from "../../../services/shareVideo";
import share_icon from '../../../assets/social-share-icon.png';
import share_icon_disabled from '../../../assets/social-disabled-share-icon.png';
-const mapStateToProps = (state , ownProps) => {
- return {
- isCreatorApproved : reduxGetter.isCreatorApproved(ownProps.userId)
- }
-};
-class ShareIcon extends PureComponent {
+class Base extends PureComponent {
constructor(props){
super(props);
};
shareVideo = () => {
- let shareVideo = new ShareVideo(this.props.videoId);
+ let shareVideo = new ShareVideo(this.props.url);
shareVideo.perform();
};
- isDisabled = () => {
- return this.props.isCreatorApproved != 1;
- };
-
render(){
return ( this.shareVideo())} >
-
+
);
}
};
-export default connect(mapStateToProps)(ShareIcon);
+
+export default Base;
diff --git a/src/components/CommonComponents/ShareIcon/ReplyShare.js b/src/components/CommonComponents/ShareIcon/ReplyShare.js
new file mode 100644
index 00000000..463750ca
--- /dev/null
+++ b/src/components/CommonComponents/ShareIcon/ReplyShare.js
@@ -0,0 +1,12 @@
+import reduxGetter from '../../../services/ReduxGetters';
+import { connect } from 'react-redux';
+import Base from "./Base"
+
+const mapStateToProps = (state , ownProps) => {
+ return {
+ canReply : reduxGetter.isReplyShareable(ownProps.entityId , state)
+ }
+};
+
+const ReplyShareIcon = connect(mapStateToProps)(Base);
+export default ReplyShareIcon;
\ No newline at end of file
diff --git a/src/components/CommonComponents/ShareIcon/VideoShare.js b/src/components/CommonComponents/ShareIcon/VideoShare.js
new file mode 100644
index 00000000..aaf37675
--- /dev/null
+++ b/src/components/CommonComponents/ShareIcon/VideoShare.js
@@ -0,0 +1,13 @@
+import reduxGetter from '../../../services/ReduxGetters';
+import { connect } from 'react-redux';
+import Base from "./Base"
+
+
+const mapStateToProps = (state , ownProps) => {
+ return {
+ canReply : reduxGetter.isVideoShareable(ownProps.entityId , state)
+ }
+};
+
+const VideoShareIcon = connect(mapStateToProps)(Base);
+export default VideoShareIcon;
\ No newline at end of file
diff --git a/src/components/CommonComponents/SingleBubble/index.js b/src/components/CommonComponents/SingleBubble/index.js
new file mode 100644
index 00000000..47af57b9
--- /dev/null
+++ b/src/components/CommonComponents/SingleBubble/index.js
@@ -0,0 +1,34 @@
+import React, { Component } from 'react';
+import {View} from 'react-native';
+import { connect } from 'react-redux';
+import ProfilePicture from "../../ProfilePicture";
+import reduxGetters from '../../../services/ReduxGetters';
+import inlineStyles from './styles';
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ seen: reduxGetters.isReplySeen(ownProps.replyDetailId)
+ };
+};
+
+class SingleBubble extends Component {
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return
+
+
+ }
+ isActiveOrUnseen = () => {
+ return ! this.props.seen || this.props.isActive();
+ }
+
+}
+
+//make this component available to the app
+export default connect(mapStateToProps)(SingleBubble);
diff --git a/src/components/CommonComponents/SingleBubble/styles.js b/src/components/CommonComponents/SingleBubble/styles.js
new file mode 100644
index 00000000..0b89cc98
--- /dev/null
+++ b/src/components/CommonComponents/SingleBubble/styles.js
@@ -0,0 +1,39 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../../theme/styles/Colors';
+
+let stylesMap = {
+
+ bubbleShadow: {
+ shadowColor: Colors.wildWatermelon2,
+ shadowOffset: { width: 0, height: 0 },
+ shadowOpacity: 0.8,
+ shadowRadius: 5,
+ elevation: 3,
+ borderColor: Colors.wildWatermelon2,
+ borderWidth: .5,
+ borderRadius: 20
+ },
+
+ bubbleSizeSkipFont: {
+ height: 38,
+ width: 38,
+ borderColor: 'white',
+ borderWidth: 1,
+ borderRadius: 20
+ },
+
+ bubbleContainer: {
+ flexDirection:'row',
+ marginLeft: 30,
+ alignItems: 'center'
+ },
+
+ repliesTxt: {
+ color: 'white',
+ fontSize: 16,
+ fontFamily: 'AvenirNext-DemiBold'
+ }
+
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/SlidingUpPanel/index.js b/src/components/CommonComponents/SlidingUpPanel/index.js
new file mode 100644
index 00000000..5dbf5bde
--- /dev/null
+++ b/src/components/CommonComponents/SlidingUpPanel/index.js
@@ -0,0 +1,15 @@
+import SlidingUpPanel from "rn-sliding-up-panel";
+
+class Panel extends SlidingUpPanel{
+
+ constructor(props) {
+ super(props);
+ }
+
+ _onBackButtonPress() {
+ return false;
+ }
+
+}
+
+export default Panel ;
diff --git a/src/components/CommonComponents/SlidingUpPanel/styles.js b/src/components/CommonComponents/SlidingUpPanel/styles.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/components/CommonComponents/TagsInput/CustomTextInput.js b/src/components/CommonComponents/TagsInput/CustomTextInput.js
index 1234830e..bcfdc9f7 100644
--- a/src/components/CommonComponents/TagsInput/CustomTextInput.js
+++ b/src/components/CommonComponents/TagsInput/CustomTextInput.js
@@ -1,14 +1,17 @@
import React, { PureComponent } from 'react';
-import { View, Text, TextInput } from 'react-native';
+import { View, Text, TextInput, Platform } from 'react-native';
import Theme from '../../../theme/styles';
const MAX_LENGTH = 500;
+const IS_ANDROID = Platform.OS === 'android';
class CustomTextInput extends PureComponent {
constructor(props) {
super(props);
this.textInputRef = null;
+ this.textVal = "";
+ this.needsOnChangeText = false;
}
setTextInputRef = (textInputRef) => {
@@ -23,19 +26,40 @@ class CustomTextInput extends PureComponent {
this.textInputRef.setNativeProps({
"text": text
});
+ this.textVal = text;
}
};
+ onChangeText = (text) => {
+ this.textVal = text;
+ if ( IS_ANDROID ) {
+ this.needsOnChangeText = true;
+ } else {
+ // Only for iOS
+ this.triggerOnTextChange(text);
+ }
+ }
+
+ onSelectionChange = (...args) => {
+ this.props.locationGetter(...args);
+ if ( this.needsOnChangeText ) {
+ this.triggerOnTextChange(this.textVal);
+ }
+ }
+
+ triggerOnTextChange = (text) => {
+ this.props.onChangeText(text);
+ this.needsOnChangeText = false;
+ }
+
render() {
return (
{
- this.props.onChangeText(value);
- }}
+ onSelectionChange={this.onSelectionChange}
+ onChangeText={this.onChangeText}
multiline={true}
autoFocus={this.props.autoFocus}
placeholder={this.props.placeholderText}
diff --git a/src/components/CommonComponents/TagsInput/index.js b/src/components/CommonComponents/TagsInput/index.js
index b300f45c..6e2e07a2 100644
--- a/src/components/CommonComponents/TagsInput/index.js
+++ b/src/components/CommonComponents/TagsInput/index.js
@@ -1,14 +1,21 @@
import React, { PureComponent } from 'react';
-import { TouchableOpacity, FlatList } from 'react-native';
+import { View, Dimensions, Text, Animated} from 'react-native';
+import { FlatList, TouchableOpacity, TouchableWithoutFeedback } from 'react-native-gesture-handler';
import PepoApi from '../../../services/PepoApi';
import CustomTextInput from './CustomTextInput';
+import deepGet from 'lodash/get';
+import unescape from 'lodash/unescape';
+import DataContract from "../../../constants/DataContract";
+import inlineStyles from "./styles";
+import ProfilePicture from "../../ProfilePicture";
class TagsInput extends PureComponent {
constructor(props) {
super(props);
this.state = {
- data: [],
+ hashTagsData: [],
+ mentionsData: [],
keyword: ''
};
this.value = this.props.initialValue;
@@ -24,10 +31,24 @@ class TagsInput extends PureComponent {
const reqParam = keyword.substr(1);
this.reqTimer = setTimeout(() => {
if (!reqParam) return;
- new PepoApi('/tags')
+ new PepoApi(DataContract.tags.userTags)
.get('q=' + reqParam)
.then((res) => {
- this.openSuggestionsPanel(res);
+ this.openTagsPanel(res);
+ })
+ .catch((error) => {});
+ }, 300);
+ };
+
+ fetchMentions = (keyword) => {
+ clearTimeout(this.reqTimer);
+ const reqParam = keyword.substr(1);
+ this.reqTimer = setTimeout(() => {
+ if (!reqParam) return;
+ new PepoApi(DataContract.mentions.userMentions)
+ .get('q=' + reqParam)
+ .then((res) => {
+ this.openMentionsPanel(res);
})
.catch((error) => {});
}, 300);
@@ -55,18 +76,21 @@ class TagsInput extends PureComponent {
currentIndexChar = val.charAt(location),
isValidChar = this.isValidChar(currentIndexChar),
wordAtIndex = this.getWordAtIndex(val, location),
- isHashTag = this.isHashTag(wordAtIndex);
- if (isValidChar && isHashTag) {
+ isHashTag = this.isHashTag(wordAtIndex),
+ isMention = this.isMention(wordAtIndex);
+ if (isValidChar && isHashTag || isMention) {
this.wordIndex = location;
this.indexWord = wordAtIndex;
this.startTracking();
- this.fetchHashTags(wordAtIndex);
+ isHashTag && this.fetchHashTags(wordAtIndex);
+ isMention && this.fetchMentions(wordAtIndex);
} else {
this.closeSuggestionsPanel();
}
this.changeValue(val);
};
+
setCustomInputRef = ( ref )=> {
this.customTextInputRef = ref;
}
@@ -80,10 +104,22 @@ class TagsInput extends PureComponent {
};
isHashTag(val) {
- const hastagRegex = /(?:\s|^)#[A-Za-z0-9\-\.\_]+(?:\s|$)/g;
- return hastagRegex.test(val);
+ const hastagRegex = /(?:\s|^)#[A-Za-z0-9\-\.\_]+(?:\s|$)/g;
+ return hastagRegex.test(val);
+ };
+
+ inIncludeMentions(){
+ return this.props.mentions && this.props.mentions.includes("@");
}
+ isMention(val){
+ if(this.inIncludeMentions()) {
+ const mentionRegex = /(?:\s|^)@[A-Za-z0-9\-\.\_]+(?:\s|$)/g;
+ return mentionRegex.test(val);
+ }
+ return false;
+ };
+
isValidChar(val) {
const spaceRegex = /\s/g;
return val && !spaceRegex.test(val);
@@ -93,18 +129,56 @@ class TagsInput extends PureComponent {
this.location = event && event.nativeEvent && event.nativeEvent.selection && event.nativeEvent.selection.start;
};
- openSuggestionsPanel(res) {
+ openTagsPanel(res) {
if (!this.isTrackingStarted) return;
- if (res && res.success && res.data ) {
- let resultType = res.data.result_type;
- resultType && this.setState({ data: res.data[resultType]});
+ if ( deepGet(res , "data.meta.search_kind") === "tags" ) {
+ let resultTypeTags = res.data.result_type;
+ if ( !resultTypeTags ) {
+ return;
+ }
+ let results = res.data[resultTypeTags];
+ this.setState({ mentionsData:[], hashTagsData: results});
+ if ( results && results.length ) {
+ this.triggerOnSuggestionsPanelOpen();
+ } else {
+ this.triggerOnSuggestionsPanelClose();
+ }
+ }
+ }
+
+ openMentionsPanel(res) {
+ if (!this.isTrackingStarted) return;
+ if ( deepGet(res , "data.meta.search_kind") == "users") {
+ let resultTypeMentions = res.data.result_type;
+ if ( !resultTypeMentions ) {
+ return;
+ }
+ let results = res.data[resultTypeMentions];
+ this.setState({hashTagsData:[], mentionsData: results});
+ this.triggerOnSuggestionsPanelOpen();
+ if ( results && results.length ) {
+ this.triggerOnSuggestionsPanelOpen();
+ } else {
+ this.triggerOnSuggestionsPanelClose();
+ }
}
}
closeSuggestionsPanel() {
this.stopStracking();
- if (this.state.data.length > 0) {
- this.setState({ data: [] });
+ this.setState({ hashTagsData: [], mentionsData: [] });
+ this.triggerOnSuggestionsPanelClose();
+ }
+
+ triggerOnSuggestionsPanelOpen() {
+ if( this.props.onSuggestionsPanelOpen ) {
+ this.props.onSuggestionsPanelOpen();
+ }
+ }
+
+ triggerOnSuggestionsPanelClose() {
+ if ( this.props.onSuggestionsPanelClose ) {
+ this.props.onSuggestionsPanelClose();
}
}
@@ -118,16 +192,26 @@ class TagsInput extends PureComponent {
_keyExtractor = (item, index) => `id_${item.id}`;
- _renderItem = ({ item }) => {
- const SearchResultRowComponent = this.props.searchResultRowComponent;
+ _renderHashTagItem = ({ item }) => {
+ const HashRow = this.props.hashResultRowComponent || HashResultRowComponent ;
return (
- this.onSuggestionTap(item)}>
-
+ this.onHashSuggestionTap(item)} style={{paddingLeft: 8}}>
+ {/* Hashtags do not include special character like '&' today, but unescaped if they start supporting*/}
+
);
};
- onSuggestionTap(item) {
+ _renderMentionsItem = ({ item }) => {
+ const MentionRow = this.props.mentionResultRowComponent || MentionResultRowComponent ;
+ return (
+ this.onMentionSuggestionTap(item)} style={{paddingLeft: 8}}>
+
+
+ );
+ };
+
+ onHashSuggestionTap(item ) {
this.closeSuggestionsPanel();
const wordToReplace = this.getWordAtIndex(this.value, this.wordIndex),
isHashTag = this.isHashTag(wordToReplace);
@@ -140,6 +224,19 @@ class TagsInput extends PureComponent {
}
}
+ onMentionSuggestionTap(item ) {
+ this.closeSuggestionsPanel();
+ const wordToReplace = this.getWordAtIndex(this.value, this.wordIndex),
+ isMention = this.isMention(wordToReplace);
+ if (isMention) {
+ const startIndex = this.getStartIndex(this.value, this.wordIndex),
+ endIndex = this.getEndIndex(this.value, this.wordIndex),
+ replaceString = ` @${item.user_name} `,
+ newString = this.replaceBetween(startIndex, endIndex, replaceString);
+ this.changeValue(newString);
+ }
+ }
+
replaceBetween(start, end, replaceString) {
return this.value.substring(0, start) + replaceString + this.value.substring(end);
}
@@ -170,38 +267,81 @@ class TagsInput extends PureComponent {
return endIndex;
}
+ isHastagData(){
+ return this.state.hashTagsData && this.state.hashTagsData.length > 0 ;
+ }
+
+ isMentionsData(){
+ return this.state.mentionsData && this.state.mentionsData.length > 0 ;
+ }
+
render() {
return (
-
- {
- this.props.submitEvent(this.value);
- }}
- locationGetter={this.locationGetter}
- onChangeText={this.onChangeText}
- placeholderText={this.props.placeholderText}
- autoFocus={this.props.autoFocus}
- maxLength={this.props.maxLength}
- />
- {this.props.children}
-
-
- }
- stickyHeaderIndices={[0]}
- />
+
+ {
+ this.props.submitEvent(this.value);
+ }}
+ locationGetter={this.locationGetter}
+ onChangeText={this.onChangeText}
+ placeholderText={this.props.placeholderText}
+ autoFocus={this.props.autoFocus}
+ maxLength={this.props.maxLength}
+ />
+
+ {this.isHastagData() ?
+ : this.isMentionsData() && (
+
+ )
+ }
+
+
);
}
}
+
+const HashResultRowComponent = (props) => (
+
+ {`#${props.val}`}
+
+);
+
+const MentionResultRowComponent = (props) => (
+
+
+
+ {`${props.name}`}
+ {`@${props.userName}`}
+
+
+);
+
export default TagsInput;
diff --git a/src/components/CommonComponents/TagsInput/styles.js b/src/components/CommonComponents/TagsInput/styles.js
index d329a9ed..5c79c242 100644
--- a/src/components/CommonComponents/TagsInput/styles.js
+++ b/src/components/CommonComponents/TagsInput/styles.js
@@ -1,6 +1,24 @@
import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
import Colors from '../../../theme/styles/Colors';
-let stylesMap = {};
+let stylesMap = {
+ suggestionTextWrapper: {
+ marginVertical: 9
+ },
+ suggestionText:{
+ fontFamily: 'AvenirNext-Regular',
+ color:Colors.midNightblue,
+ fontSize:16
+ },
+ mentionsTitle:{
+ fontSize: 15,
+ color:Colors.midNightblue,
+ fontFamily: 'AvenirNext-Medium',
+ },
+ mentionSubTitle: {
+ fontSize: 14,
+ color: Colors.light
+ }
+};
export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/UserInfo/index.js b/src/components/CommonComponents/UserInfo/index.js
index 1dd789c4..dd552a7e 100644
--- a/src/components/CommonComponents/UserInfo/index.js
+++ b/src/components/CommonComponents/UserInfo/index.js
@@ -16,7 +16,6 @@ import InAppBrowser from '../../../services/InAppBrowser';
import profileLink from '../../../assets/profile_link.png';
import twitterLink from '../../../assets/twitter_link.png';
import Utilities from '../../../services/Utilities';
-import inlineStyles from '../../Home/styles';
const mapStateToProps = (state, ownProps) => {
return {
@@ -52,15 +51,12 @@ class UserInfo extends React.PureComponent {
}
onDidFocus = (payload) => {
- let pixelParams = {
+ PixelCall({
e_entity: 'page',
e_action: 'view',
- e_data_json: {
- profile_user_id: this.props.userId
- },
- p_type: 'user_profile'
- };
- PixelCall(pixelParams);
+ p_type: 'user_profile',
+ p_name: this.props.userId
+ });
};
goToSupporting = () => {
@@ -165,7 +161,7 @@ class UserInfo extends React.PureComponent {
if (this.isValidBioTag(this.props.userId, hashTag)) {
let tagText = hashTag.replace("#", "");
return (
-
+
{prevText}
+
{prevText + hashTag}
)
diff --git a/src/components/CommonComponents/UserProfileFlatList/index.js b/src/components/CommonComponents/UserProfileFlatList/index.js
index 0923ed5d..16077e1a 100644
--- a/src/components/CommonComponents/UserProfileFlatList/index.js
+++ b/src/components/CommonComponents/UserProfileFlatList/index.js
@@ -24,7 +24,9 @@ import LinearGradient from "react-native-linear-gradient";
import CurrentUser from "../../../models/CurrentUser";
import DeleteVideo from "../DeleteVideo";
import Colors from '../../../theme/styles/Colors';
-import VideoThumbnailItem from '../VideoThumbnailItem';
+import CommonStyle from "../../../theme/styles/Common"
+import VideoThumbnail from '../../CommonComponents/VideoThumbnail/VideoThumbnail';
+import DataContract from '../../../constants/DataContract';
class UserProfileFlatList extends PureComponent {
@@ -130,7 +132,7 @@ class UserProfileFlatList extends PureComponent {
let array = [...this.state.list]; // make a separate copy of the array
array.splice(index, 1);
this.setState({list: array});
- this.props.onDelete(array);
+ this.props.onDelete && this.props.onDelete(array);
}
}
@@ -147,10 +149,11 @@ class UserProfileFlatList extends PureComponent {
style={{width: (Dimensions.get('window').width - 6) / 2, margin: 1, position: 'absolute', top: 0, left: 0, zIndex: 1, alignItems: 'flex-end'}}
>
- {this.removeVideo(videoId , index )}} />
+ {this.removeVideo(videoId , index )}} />
}
- {this.onVideoClick(item, index)}}/>
);
};
@@ -180,7 +183,7 @@ class UserProfileFlatList extends PureComponent {
render(){
return(
-
+
{this.listRef = ref } }
ListHeaderComponent={this.listHeaderComponent()}
diff --git a/src/components/CommonComponents/VideoAmoutStat.js b/src/components/CommonComponents/VideoAmoutStat.js
deleted file mode 100644
index 69fc0f1b..00000000
--- a/src/components/CommonComponents/VideoAmoutStat.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import React, { PureComponent } from 'react';
-import { View, Text } from 'react-native';
-import { connect } from 'react-redux';
-
-import reduxGetter from '../../services/ReduxGetters';
-
-import pricer from '../../services/Pricer';
-
-import inlineStyles from '../Home/styles';
-import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
-import multipleClickHandler from '../../services/MultipleClickHandler';
-import Utilities from "../../services/Utilities";
-
-
-const mapStateToProps = (state, ownProps) => {
- return {
- supporters: reduxGetter.getUserSupporters(ownProps.userId, state),
- totalBt: reduxGetter.getVideoBt(ownProps.videoId, state)
- };
-};
-
-class VideoAmountStat extends PureComponent {
- constructor(props) {
- super(props);
- }
-
- btToFiat(btAmount) {
- const priceOracle = pricer.getPriceOracle();
- btAmount = priceOracle.fromDecimal(btAmount);
- return (priceOracle && priceOracle.btToFiat(btAmount, 2)) || 0;
- }
-
- onWrapperClick = (e) => {
- this.props.onWrapperClick && this.props.onWrapperClick();
- };
-
- render() {
- return (
- this.onWrapperClick())} pointerEvents={'auto'}>
-
- {/*{*/}
- {/**/}
- {/*${`${ pricer.toDisplayAmount(this.btToFiat(this.props.totalBt))}`}{' '}RAISED*/}
- {/**/}
- {/*}*/}
- {
-
-
- {this.props.supporters || 0}
- {Utilities.getSingularPluralText(this.props.supporters , "Supporter")}
-
-
-
- }
-
-
- );
- }
-}
-
-export default connect(mapStateToProps)(VideoAmountStat);
diff --git a/src/components/CommonComponents/VideoPlayer/index.js b/src/components/CommonComponents/VideoPlayer/index.js
index b67ab15f..56daa7c1 100644
--- a/src/components/CommonComponents/VideoPlayer/index.js
+++ b/src/components/CommonComponents/VideoPlayer/index.js
@@ -1,16 +1,16 @@
import React, { Component } from 'react';
-import {View,Image,TouchableOpacity, Text} from 'react-native';
-import VideoRowComponent from "../../UserVideoHistory/UserVideoHistoryRow";
+import UserVideoHistoryRow from "../../UserVideoHistory/UserVideoHistoryRow";
import TopStatus from "../../Home/TopStatus";
import deepGet from "lodash/get";
import PepoApi from "../../../services/PepoApi";
-import inlineStyles from './styles'
-import historyBack from "../../../assets/user-video-history-back-icon.png";
-import video_not_available from '../../../assets/video-not-available.png';
import Utilities from '../../../services/Utilities';
-import CurrentUser from '../../../models/CurrentUser';
import reduxGetter from '../../../services/ReduxGetters';
-import Colors from "../../../theme/styles/Colors";
+import DeletedVideoInfo from '../DeletedVideoInfo';
+import CommonStyles from "../../../theme/styles/Common";
+import FlotingBackArrow from "../../CommonComponents/FlotingBackArrow";
+import { SafeAreaView } from "react-navigation";
+import { fetchVideo } from '../../../helpers/helpers';
+import DataContract from '../../../constants/DataContract';
class VideoPlayer extends Component {
@@ -24,9 +24,10 @@ class VideoPlayer extends Component {
constructor(props){
super(props);
this.videoId = this.props.navigation.getParam('videoId');
+ this.bubbleClickHandler = this.props.navigation.getParam('bubbleClickHandler');
this.state = {
- userId : this.props.navigation.getParam('userId') || null,
- isDeleted : reduxGetter.isVideoDeleted(this.videoId)
+ userId : reduxGetter.getVideoCreatorUserId(this.videoId) || null,
+ isDeleted : false
};
this.refetchVideo();
this.isActiveScreen = true;
@@ -54,10 +55,7 @@ class VideoPlayer extends Component {
refetchVideo = () => {
if (this.state.isDeleted) return;
- new PepoApi(`/videos/${this.videoId}`)
- .get()
- .then((res) => { this.onRefetchVideo(res) })
- .catch((error) => {});
+ fetchVideo( this.videoId , this.onRefetchVideo );
};
onRefetchVideo = ( res ) => {
@@ -65,45 +63,34 @@ class VideoPlayer extends Component {
this.setState({isDeleted: true});
return;
}
- const users = deepGet(res , "data.users") || {} ,
- userKeys = Object.keys(users) || [] ,
- userId = userKeys[0] || null;
- if(userId){
- this.setState({ userId : userId});
+ const video_details = deepGet(res, `data.${DataContract.videos.videoDetailsKey}`),
+ item = video_details[this.videoId];
+ if( item ){
+ this.setState({
+ userId: item[DataContract.videos.creatorUserIdKey]
+ })
}
};
- navigateToUserProfile = (e) => {
- if (Utilities.checkActiveUser()) {
- if (this.state.userId == CurrentUser.getUserId()) {
- this.props.navigation.navigate('ProfileScreen');
- } else {
- this.isActiveScreen = false;
- this.props.navigation.push('UsersProfileScreen', { userId: this.state.userId });
- }
- }
- };
+ getPixelDropData = () => {
+ return pixelParams = {
+ p_type: 'single_video',
+ p_name: this.videoId
+ };
+ }
render() {
if(this.state.isDeleted){
- return
- this.props.navigation.goBack()} style={inlineStyles.historyBackSkipFont}>
-
-
-
- Looks like the Video you were looking for isn’t available and might have been deleted by the creator!
-
+ return
}else{
return (
-
+
-
- this.props.navigation.goBack()} style={inlineStyles.historyBackSkipFont}>
-
-
-
+
+
+
)
}
}
diff --git a/src/components/CommonComponents/VideoReplyPlayer/index.js b/src/components/CommonComponents/VideoReplyPlayer/index.js
new file mode 100644
index 00000000..3baf1618
--- /dev/null
+++ b/src/components/CommonComponents/VideoReplyPlayer/index.js
@@ -0,0 +1,120 @@
+import React, { PureComponent } from 'react';
+import TopStatus from "../../Home/TopStatus";
+import deepGet from "lodash/get";
+import PepoApi from "../../../services/PepoApi";
+import Utilities from '../../../services/Utilities';
+import reduxGetter from '../../../services/ReduxGetters';
+import DataContract from '../../../constants/DataContract';
+import DeletedVideoInfo from '../DeletedVideoInfo';
+import VideoReplyRow from '../../FullScreenReplyCollection/VideoReplyRow';
+import FlotingBackArrow from "../../CommonComponents/FlotingBackArrow";
+import CommonStyles from "../../../theme/styles/Common";
+import { SafeAreaView } from "react-navigation";
+
+class VideoReplyPlayer extends PureComponent {
+
+ static navigationOptions = ({navigation, navigationOptions}) => {
+ return {
+ headerBackTitle: null,
+ header: null
+ };
+ };
+
+ constructor(props){
+ super(props);
+ this.replyDetailId = this.props.navigation.getParam('replyDetailId');
+ this.state = {
+ userId : reduxGetter.getReplyUserId( this.replyDetailId ) || null,
+ isLoading: true,
+ isDeleted : false
+ };
+ this.fetchReply();
+ this.isActiveScreen = true;
+ }
+
+ componentDidMount(){
+ this.willFocusSubscription = this.props.navigation.addListener('willFocus', (payload) => {
+ this.isActiveScreen = true ;
+ });
+
+ this.willBlurSubscription = this.props.navigation.addListener('willBlur', (payload) => {
+ this.isActiveScreen = false ;
+ });
+ }
+
+ componentWillUnmount(){
+ this.onReplyFetch = () => {};
+ this.willFocusSubscription && this.willFocusSubscription.remove();
+ this.willBlurSubscription && this.willBlurSubscription.remove();
+ }
+
+ shouldPlay = () => {
+ return this.isActiveScreen;
+ };
+
+ fetchReply = () => {
+ if (this.state.isDeleted) return;
+ new PepoApi(DataContract.replies.getSingleVideoReplyApi(this.replyDetailId))
+ .get()
+ .then((res) => { this.onReplyFetch(res) })
+ .catch((error) => {});
+ };
+
+ onReplyFetch = ( res ) => {
+ if(Utilities.isEntityDeleted(res)){
+ this.setState({isDeleted: true});
+ return;
+ }
+ const replyDetails = deepGet(res , `data.${DataContract.replies.replyDetailsKey}`) ,
+ item = replyDetails[this.replyDetailId]
+ if(item){
+ this.setState({ userId : item[DataContract.replies.creatorUserIdKey], isLoading : false});
+ }
+ };
+
+ getPixelDropData = () => {
+ return pixelParams = {
+ e_entity: 'reply',
+ p_type: 'single_reply',
+ p_name: this.replyDetailId,
+ };
+ }
+
+ parentClickHandler =()=>{
+ const parentVideoId = reduxGetter.getReplyParentVideoId(this.replyDetailId);
+ this.props.navigation.push('VideoPlayer', {
+ userId: this.state.userId,
+ videoId: parentVideoId
+ });
+ }
+
+ isActiveEntity = (fullVideoReplyId , item , index)=> {
+ let replyId = deepGet(item, `payload.${DataContract.replies.replyDetailIdKey}`)
+ return fullVideoReplyId == replyId;
+ }
+
+ render() {
+ if(this.state.isDeleted){
+ return
+ }else{
+ return (
+
+
+ {!this.state.isLoading && ( )}
+
+
+ )
+ }
+ }
+}
+
+export default VideoReplyPlayer ;
diff --git a/src/components/CommonComponents/VideoReplyPlayer/styles.js b/src/components/CommonComponents/VideoReplyPlayer/styles.js
new file mode 100644
index 00000000..00b62fe2
--- /dev/null
+++ b/src/components/CommonComponents/VideoReplyPlayer/styles.js
@@ -0,0 +1,43 @@
+import DefaultStyleGenerator from '../../../theme/styles/DefaultStyleGenerator';
+import {ifIphoneX} from "react-native-iphone-x-helper";
+import Colors from '../../../theme/styles/Colors';
+
+let stylesMap = {
+
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.snow
+ },
+
+ imgSizeSkipFont: {
+ width: 68.5,
+ height: 68.5
+ },
+
+ desc:{
+ fontSize: 22,
+ marginTop: 10,
+ textAlign: 'center',
+ paddingHorizontal: 25,
+ color: Colors.valhalla,
+ fontFamily: 'AvenirNext-Regular'
+ },
+
+ historyBackSkipFont:{
+ ...ifIphoneX({
+ top: 55,
+ }, {
+ top: 25,
+ }),
+ width: 29,
+ height: 34,
+ position: 'absolute',
+ left: 10,
+ alignItems: 'center',
+ justifyContent: 'center'
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/CommonComponents/VideoSupporterStat/Base.js b/src/components/CommonComponents/VideoSupporterStat/Base.js
new file mode 100644
index 00000000..c4a566d5
--- /dev/null
+++ b/src/components/CommonComponents/VideoSupporterStat/Base.js
@@ -0,0 +1,51 @@
+import React, { PureComponent } from 'react';
+import { View, Text } from 'react-native';
+
+import pricer from '../../../services/Pricer';
+import inlineStyles from '../../Home/styles';
+import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
+import multipleClickHandler from '../../../services/MultipleClickHandler';
+import Utilities from "../../../services/Utilities";
+import CurrentUser from '../../../models/CurrentUser';
+
+class Base extends PureComponent {
+ constructor(props) {
+ super(props);
+ }
+
+ btToFiat(btAmount) {
+ const priceOracle = pricer.getPriceOracle();
+ btAmount = priceOracle.fromDecimal(btAmount);
+ return (priceOracle && priceOracle.btToFiat(btAmount, 2)) || 0;
+ }
+
+ navigateToUserProfile = () => {
+ if (Utilities.checkActiveUser()) {
+ if (this.props.userId == CurrentUser.getUserId()) {
+ this.props.navigation.navigate('ProfileScreen');
+ } else {
+ this.props.navigation.push('UsersProfileScreen', { userId: this.props.userId });
+ }
+ }
+ };
+
+ render() {
+ return (
+ this.navigateToUserProfile())} pointerEvents={'auto'}>
+
+ {
+
+
+ {this.props.supporters || 0}
+ {Utilities.getSingularPluralText(this.props.supporters , "Supporter")}
+
+
+
+ }
+
+
+ );
+ }
+}
+
+export default Base;
diff --git a/src/components/CommonComponents/VideoSupporterStat/VideoReplySupporterStat.js b/src/components/CommonComponents/VideoSupporterStat/VideoReplySupporterStat.js
new file mode 100644
index 00000000..4a4c6f50
--- /dev/null
+++ b/src/components/CommonComponents/VideoSupporterStat/VideoReplySupporterStat.js
@@ -0,0 +1,16 @@
+import { connect } from 'react-redux';
+
+import reduxGetter from '../../../services/ReduxGetters';
+import Base from './Base';
+import { withNavigation } from 'react-navigation';
+
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ supporters: reduxGetter.getUserSupporters(ownProps.userId, state),
+ totalBt: reduxGetter.getReplyBt(ownProps.entityId, state)
+ };
+};
+
+
+export default connect(mapStateToProps)( withNavigation( Base ));
diff --git a/src/components/CommonComponents/VideoSupporterStat/VideoSupporterStat.js b/src/components/CommonComponents/VideoSupporterStat/VideoSupporterStat.js
new file mode 100644
index 00000000..33817844
--- /dev/null
+++ b/src/components/CommonComponents/VideoSupporterStat/VideoSupporterStat.js
@@ -0,0 +1,16 @@
+import { connect } from 'react-redux';
+
+import reduxGetter from '../../../services/ReduxGetters';
+import Base from './Base';
+import { withNavigation } from 'react-navigation';
+
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ supporters: reduxGetter.getUserSupporters(ownProps.userId, state),
+ totalBt: reduxGetter.getVideoBt(ownProps.entityId, state)
+ };
+};
+
+
+export default connect(mapStateToProps)( withNavigation ( Base) );
diff --git a/src/components/CommonComponents/VideoThumbnailItem/index.js b/src/components/CommonComponents/VideoThumbnail/Base.js
similarity index 57%
rename from src/components/CommonComponents/VideoThumbnailItem/index.js
rename to src/components/CommonComponents/VideoThumbnail/Base.js
index c9b39320..0395d6ec 100644
--- a/src/components/CommonComponents/VideoThumbnailItem/index.js
+++ b/src/components/CommonComponents/VideoThumbnail/Base.js
@@ -1,40 +1,32 @@
import {Dimensions, Image, Text, TouchableWithoutFeedback, View} from "react-native";
-import React from 'react';
+import React, { PureComponent } from 'react';
import FastImage from 'react-native-fast-image';
import Colors from "../../../theme/styles/Colors";
import LinearGradient from "react-native-linear-gradient";
import pepoWhiteIcon from "../../../assets/pepo-white-icon.png";
import inlineStyles from "./style";
-import reduxGetters from "../../../services/ReduxGetters";
-import AppConfig from "../../../constants/AppConfig";
import multipleClickHandler from '../../../services/MultipleClickHandler'
-import Pricer from "../../../services/Pricer";
-import deepGet from 'lodash/get';
import ProfilePicture from "../../ProfilePicture";
-let getVideoBtAmount = (videoId) => {
- return Pricer.displayAmountWithKFomatter( Pricer.getFromDecimal( reduxGetters.getVideoBt(videoId) ) ) ;
-}
-export default (props) => {
- const videoId = deepGet(props, 'payload.video_id'),
- userId = deepGet(props, 'payload.user_id')
- userName = reduxGetters.getUserName(userId),
- imageUrl = reduxGetters.getVideoImgUrl(videoId,null, AppConfig.userVideos.userScreenCoverImageWidth),
- videoDesc =reduxGetters.getVideoDescription(reduxGetters.getVideoDescriptionId(videoId));
+class Base extends PureComponent {
+ constructor(props){
+ super(props);
+ }
- return { props.onVideoClick && props.onVideoClick(videoId, props.index );} )}
+ render(){
+ return { this.props.onVideoClick && this.props.onVideoClick()} )}
>
{
style={{width: (Dimensions.get('window').width - 6) / 2, margin: 1, position: 'absolute', bottom: 0, left: 0}}
>
- {videoDesc}
+ {this.props.videoDesc}
-
- @{userName}
+
+ @{this.props.userName}
- {getVideoBtAmount(videoId)}
+ {this.props.btAmount || 0}
@@ -61,4 +53,8 @@ export default (props) => {
-}
\ No newline at end of file
+ }
+
+}
+
+export default Base;
\ No newline at end of file
diff --git a/src/components/CommonComponents/VideoThumbnail/ReplyThumbnail.js b/src/components/CommonComponents/VideoThumbnail/ReplyThumbnail.js
new file mode 100644
index 00000000..a0b85fa5
--- /dev/null
+++ b/src/components/CommonComponents/VideoThumbnail/ReplyThumbnail.js
@@ -0,0 +1,30 @@
+import Base from "./Base";
+import React, { PureComponent } from 'react';
+import reduxGetters from '../../../services/ReduxGetters';
+import AppConfig from '../../../constants/AppConfig';
+import deepGet from "lodash/get";
+import Pricer from "../../../services/Pricer";
+
+class ReplyThumbnail extends PureComponent {
+ constructor(props){
+ super(props);
+ }
+
+ getReplyStats(replyId) {
+ let replyBt = reduxGetters.getReplyBt(replyId);
+ return Pricer.getFromDecimal(replyBt) || 0;
+ }
+
+ render(){
+ const replyId = deepGet(this.props , "payload.reply_detail_id"),
+ userId = deepGet(this.props , "payload.user_id") ,
+ videoId = reduxGetters.getReplyEntityId( replyId ),
+ userName = reduxGetters.getUserName(userId),
+ imageUrl = reduxGetters.getVideoImgUrl(videoId, null, AppConfig.userVideos.userScreenCoverImageWidth) ,
+ videoDesc = reduxGetters.getVideoDescription(reduxGetters.getReplyDescriptionId(replyId)) ,
+ replyBtAmount = this.getReplyStats(replyId)
+ ;
+ return ;
+ }
+}
+export default ReplyThumbnail;
diff --git a/src/components/CommonComponents/VideoThumbnail/VideoThumbnail.js b/src/components/CommonComponents/VideoThumbnail/VideoThumbnail.js
new file mode 100644
index 00000000..63d82e00
--- /dev/null
+++ b/src/components/CommonComponents/VideoThumbnail/VideoThumbnail.js
@@ -0,0 +1,29 @@
+import Base from "./Base";
+import React, { PureComponent } from 'react';
+import reduxGetters from '../../../services/ReduxGetters';
+import AppConfig from '../../../constants/AppConfig';
+import deepGet from "lodash/get";
+import Pricer from "../../../services/Pricer";
+
+class VideoThumbnail extends PureComponent {
+ constructor(props){
+ super(props);
+ }
+
+ getVideoStats(videoId) {
+ let videoBt = reduxGetters.getVideoBt(videoId);
+ return Pricer.getFromDecimal(videoBt) || 0;
+ }
+
+ render(){
+ const videoId = deepGet(this.props , "payload.video_id"),
+ userId = deepGet(this.props , "payload.user_id") ,
+ userName = reduxGetters.getUserName(userId),
+ imageUrl = reduxGetters.getVideoImgUrl(videoId, null, AppConfig.userVideos.userScreenCoverImageWidth) ,
+ videoDesc = reduxGetters.getVideoDescription(reduxGetters.getVideoDescriptionId(videoId)) ,
+ videoBtAmount = this.getVideoStats(videoId)
+ ;
+ return ;
+ }
+}
+export default VideoThumbnail;
diff --git a/src/components/CommonComponents/VideoThumbnailItem/style.js b/src/components/CommonComponents/VideoThumbnail/style.js
similarity index 100%
rename from src/components/CommonComponents/VideoThumbnailItem/style.js
rename to src/components/CommonComponents/VideoThumbnail/style.js
diff --git a/src/components/CustomDrawerContent/index.js b/src/components/CustomDrawerContent/index.js
index cb4b872d..52e41f9a 100644
--- a/src/components/CustomDrawerContent/index.js
+++ b/src/components/CustomDrawerContent/index.js
@@ -147,7 +147,6 @@ class CustomDrawerContent extends Component {
};
initWallet = () => {
- //TODO: Navigation should push instead of navigate
this.props.navigation.navigate('WalletSettingScreen');
};
diff --git a/src/components/CustomTab/index.js b/src/components/CustomTab/index.js
index af1acfa1..4d7cb08d 100644
--- a/src/components/CustomTab/index.js
+++ b/src/components/CustomTab/index.js
@@ -42,7 +42,7 @@ let refreshTimeOut = 0;
function loginInFlow(navigation, tab) {
let currentTabIndex = tab.navigationIndex;
if (tab.rootStack === 'CaptureVideo') {
- utilities.handleVideoUploadModal(previousTabIndex, navigation);
+ utilities.handleVideoUploadModal(previousTabIndex, navigation, {videoType: appConfig.videoTypes.post });
return;
}
if (currentTabIndex == undefined || currentTabIndex == null) return;
@@ -52,8 +52,8 @@ function loginInFlow(navigation, tab) {
} else if (utilities.getLastChildRoutename(navigation.state) !== tab.childStack) {
try {
navigation.dispatch(StackActions.popToTop());
- } catch {
- console.log('Catch error');
+ } catch(e) {
+ console.log('Catch error', e);
}
} else {
clearTimeout(refreshTimeOut);
diff --git a/src/components/CustomTab/styles.js b/src/components/CustomTab/styles.js
index e818becb..80f9bbbc 100644
--- a/src/components/CustomTab/styles.js
+++ b/src/components/CustomTab/styles.js
@@ -16,10 +16,6 @@ let stylesMap = {
shadowRadius: 1,
elevation: 5,
alignItems: 'center'
- // borderColor: 'rgba(0, 0, 0, 0.25)',
- // borderWidth: 1,
- // borderBottomWidth: 0,
- // elevation: 8
},
tapArea:{
minHeight: 55,
@@ -28,17 +24,9 @@ let stylesMap = {
tabElementSkipFont: {
alignSelf: 'center',
marginHorizontal: 20,
- // marginVertical: 10,
height: 35,
width: 35
}
- // tabElementFriendsSkipFont: {
- // alignSelf: 'center',
- // marginHorizontal: 20,
- // marginVertical: 10,
- // height: 22,
- // width: 35
- // }
};
export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/Email/styles.js b/src/components/Email/styles.js
index 83ca4db7..1e899a1f 100644
--- a/src/components/Email/styles.js
+++ b/src/components/Email/styles.js
@@ -4,8 +4,9 @@ import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
let stylesMap = {
container: {
flex: 1,
- marginVertical: 20,
- marginHorizontal: 10
+ backgroundColor: Colors.white,
+ paddingVertical: 20,
+ paddingHorizontal: 10
},
resend: {
color: Colors.valhalla,
diff --git a/src/components/FanVideoDetails/VideoDescription.js b/src/components/FanVideoDetails/VideoDescription.js
index 8e6f1930..f6403627 100644
--- a/src/components/FanVideoDetails/VideoDescription.js
+++ b/src/components/FanVideoDetails/VideoDescription.js
@@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
-import { View, Text } from 'react-native';
+import {View, Text} from 'react-native';
import inlineStyles from './styles';
import TagsInput from '../CommonComponents/TagsInput';
@@ -20,25 +20,22 @@ class VideoDescription extends PureComponent {
return (
);
}
}
-const SearchResultRowComponent = (props) => (
-
- {`#${props.val}`}
-
-);
-
export default VideoDescription;
diff --git a/src/components/FanVideoDetails/VideoLink.js b/src/components/FanVideoDetails/VideoLink.js
index 3dcd20f5..81429203 100644
--- a/src/components/FanVideoDetails/VideoLink.js
+++ b/src/components/FanVideoDetails/VideoLink.js
@@ -1,7 +1,8 @@
import React, { Component } from 'react';
-import { TextInput } from 'react-native';
+import { TextInput, TouchableOpacity, Image } from 'react-native';
import styles from './styles';
+import CloseIcon from '../../assets/modal-cross-icon.png';
class VideoLink extends Component {
constructor(props) {
@@ -22,6 +23,10 @@ class VideoLink extends Component {
);
};
+ onLinkCrossIconClick = () =>{
+ this.onChangeValue("");
+ }
+
render() {
return (
@@ -31,11 +36,14 @@ class VideoLink extends Component {
ellipsizeMode={'tail'}
returnKeyType="done"
returnKeyLabel="Done"
- placeholder="Add a link (optional)"
+ placeholder="Add a link to your video"
onChangeText={this.onChangeValue}
value={this.state.value}
autoCapitalize={'none'}
/>
+ {this.state.value ?
+
+ : }
);
}
diff --git a/src/components/FanVideoDetails/index.js b/src/components/FanVideoDetails/index.js
index 6a2de143..7fd63a39 100644
--- a/src/components/FanVideoDetails/index.js
+++ b/src/components/FanVideoDetails/index.js
@@ -27,17 +27,29 @@ import { upsertRecordedVideo } from '../../actions';
import multipleClickHandler from '../../services/MultipleClickHandler';
import { getBottomSpace } from 'react-native-iphone-x-helper';
import { StackActions } from 'react-navigation';
+import PepoApi from "../../services/PepoApi";
+import DataContract from "../../constants/DataContract";
+import NumberInput from "../CommonComponents/NumberInput";
+import NumberFormatter from "../../helpers/NumberFormatter";
+import pricer from '../../services/Pricer';
+import PepoPinkIcon from '../../assets/pepo-tx-icon.png';
+import AppConfig from '../../constants/AppConfig'
+
+//TODO setParams dont use
const mapStateToProps = (state, ownProps) => {
return {
+ balance : state.balance,
recordedVideo: reduxGetter.getRecordedVideo()
};
};
+const DEFAUT_BT_VALUE = AppConfig.default_bt_amt;
+
class FanVideoDetails extends Component {
static navigationOptions = ({ navigation }) => {
return {
- title: 'Post',
+ title: 'Details',
headerStyle: {
backgroundColor: Colors.white,
borderBottomWidth: 0,
@@ -67,20 +79,39 @@ class FanVideoDetails extends Component {
static saveToRedux = (navigation) => {
let desc = navigation.state.params.videoDesc,
- link = navigation.state.params.videoLink;
- Store.dispatch(upsertRecordedVideo({ video_desc: desc, video_link: link }));
+ link = navigation.state.params.videoLink,
+ amount = navigation.state.params.replyAmount;
+ Store.dispatch(upsertRecordedVideo({ video_desc: desc, video_link: link, reply_amount:amount }));
};
constructor(props) {
super(props);
this.videoDesc = this.props.recordedVideo.video_desc;
this.videoLink = this.props.recordedVideo.video_link;
+ this.replyAmount = this.props.recordedVideo.reply_amount ? this.props.recordedVideo.reply_amount : pricer.getToDecimal(DEFAUT_BT_VALUE);
+
+ this.priceOracle = pricer.getPriceOracle();
+ this.numberFormatter = new NumberFormatter();
+ this.max = props.balance;
+ this.min = 0;
this.state = {
viewStyle: {
paddingBottom: 10
},
- error: null
+ error: null,
+ amountError: null,
+ linkError: null,
+ descError : null,
+ usdVal : this.weiToUSD(this.replyAmount),
+ replyAmt : null,
+ buttonText: 'Post',
+ isSuggestOpen: false
};
+
+ if (! props.recordedVideo.video_type ) {
+ let videoType = this.props.navigation.getParam('video_type');
+ Store.dispatch(upsertRecordedVideo({ video_type: videoType }));
+ }
}
_keyboardShown = (e) => {
let keyboardHeight = deepGet(e, 'endCoordinates.height') || 350;
@@ -110,10 +141,13 @@ class FanVideoDetails extends Component {
componentDidMount() {
this.props.navigation.setParams({
videoDesc: this.props.recordedVideo.video_desc,
- videoLink: this.props.recordedVideo.video_link
+ videoLink: this.props.recordedVideo.video_link,
+ replyAmount: this.props.recordedVideo.reply_amount
});
+
}
+
componentWillUnmount() {
this.keyboardWillShowListener.remove();
this.keyboardWillHideListener.remove();
@@ -122,16 +156,75 @@ class FanVideoDetails extends Component {
}
enableStartUploadFlag = () => {
- // if (!this.validLink()) return;
- utilities.saveItem(`${CurrentUser.getUserId()}-accepted-camera-t-n-c`, true);
- Store.dispatch(
- upsertRecordedVideo({ video_desc: this.videoDesc, video_link: this.videoLink, do_upload: true })
- );
- this.props.navigation.dispatch(StackActions.popToTop());
- this.props.navigation.dispatch(StackActions.popToTop());
- this.props.navigation.navigate('HomeScreen');
+
+ this.clearErrors();
+ this.setState({buttonText: 'Posting...'});
+ this.validateData().then((res) => {
+ utilities.saveItem(`${CurrentUser.getUserId()}-accepted-camera-t-n-c`, true);
+ Store.dispatch(
+ upsertRecordedVideo({ video_desc: this.videoDesc,
+ video_link: this.videoLink,
+ reply_amount: this.replyAmount,
+ do_upload: true })
+ );
+ this.props.navigation.dispatch(StackActions.popToTop());
+ this.props.navigation.dispatch(StackActions.popToTop());
+ this.setState({buttonText: 'Post'});
+ this.props.navigation.navigate('HomeScreen');
+ }).catch((err)=>{
+ // show error on UI.
+ this.setState({buttonText: 'Post'});
+ this.showError(err);
+ });
};
+ clearErrors = () => {
+ this.setState({
+ linkError: null,
+ descError: null,
+ amountError: null,
+ error: null
+ });
+ };
+
+ showError = (err) => {
+ if(!err.error_data) return;
+ for (let error of err.error_data){
+ switch (error.parameter) {
+ case "link":
+ this.setState({linkError: error.msg});
+ break;
+ case "video_description":
+ this.setState({descError: error.msg});
+ break;
+ case "per_reply_amount_in_wei":
+ this.setState({amountError: error.msg});
+ break;
+ }
+ }
+ };
+
+ validateData = () => {
+ let params = {};
+ params['video_description'] = this.videoDesc;
+ params['link'] = this.videoLink;
+ params['per_reply_amount_in_wei'] = this.replyAmount;
+ return new Promise((resolve, reject) => {
+ new PepoApi(DataContract.replies.validatePost)
+ .post(params)
+ .then((res)=>{
+ if (res && res.success){
+ return resolve(res);
+ } else {
+ return reject(res.err);
+ }
+ }).catch((err)=>{
+ return reject(err);
+ })
+ });
+ };
+
+
onChangeDesc = (desc) => {
this.videoDesc = desc;
//Done for the value to be accessible in static navigationOptions
@@ -175,14 +268,63 @@ class FanVideoDetails extends Component {
return true;
};
+
+ onErrorCallBack = ( errMsg ) =>{
+ this.setState({
+ amountError : errMsg
+ })
+ }
+
+ replyAmountChange = ( value )=>{
+ this.replyAmount = pricer.getToDecimal(value);
+ if (isNaN(this.replyAmount)) this.replyAmount = "";
+
+ let formattedUsdVal = this.weiToUSD( pricer.getToDecimal(value) );
+ //Done for the value to be accessible in static navigationOptions
+ this.props.navigation.setParams({
+ replyAmount: this.replyAmount
+ });
+ this.setState({
+ usdVal : formattedUsdVal,
+ replyAmt : value
+ });
+ };
+ weiToUSD = (value ) =>{
+ let weiToBt = pricer.getFromDecimal(value, 2),
+ usdVal = this.priceOracle.btToFiat(weiToBt),
+ formattedUsdVal = this.numberFormatter.getFormattedValue( usdVal );
+ return formattedUsdVal;
+ }
+
+ pointerEventForInPageElement() {
+ if ( this.state.isSuggestOpen ) {
+ return "none";
+ }
+ return "auto";
+ }
+
+ onSuggestionsPanelClose = () => {
+ this.setState({
+ isSuggestOpen: false
+ });
+ }
+
+ onSuggestionsPanelOpen = () => {
+ this.setState({
+ isSuggestOpen: true
+ });
+ }
+
render() {
- let imageUrl = this.props.recordedVideo.cover_image;
+ let imageUrl = this.props.recordedVideo.cover_image,
+ value = pricer.getFromDecimal(this.replyAmount, 2) ;
return (
@@ -197,13 +339,38 @@ class FanVideoDetails extends Component {
-
+
-
+ {this.state.descError }
+
+ Link
+ {this.state.linkError }
+
+ Set Price for replies
+
+
+
+
+ ${this.state.usdVal}
+
+
+
+ {this.state.amountError }
-
+
{this.state.error}
{
this.enableStartUploadFlag();
})}
diff --git a/src/components/FanVideoDetails/styles.js b/src/components/FanVideoDetails/styles.js
index d7a9a900..58e17fb2 100644
--- a/src/components/FanVideoDetails/styles.js
+++ b/src/components/FanVideoDetails/styles.js
@@ -31,6 +31,26 @@ let stylesMap = {
paddingHorizontal: 15,
paddingVertical: 20
},
+ videoLinkItem: {
+ flexDirection: 'row',
+ borderBottomWidth: 1,
+ borderColor: '#ccd3cd',
+ paddingBottom: 16,
+ alignItems: 'center',
+ paddingHorizontal: 12,
+ zIndex: -1
+ },
+ videoAmountItem: {
+ flexDirection: 'row',
+ borderBottomWidth: 1,
+ borderColor: '#ccd3cd',
+
+ alignItems: 'center',
+ paddingBottom: 16,
+ paddingHorizontal: 12,
+ zIndex: -1
+
+ },
videoDescription: {
color: 'rgba(42, 41, 59, 0.8)',
// flex: 1,
@@ -43,18 +63,31 @@ let stylesMap = {
marginLeft: 10,
marginTop: 0,
padding: 0,
+ paddingTop: 0,
+ position: 'relative',
paddingLeft: 0,
height: 100
},
- suggestionText: {
- fontWeight: 'bold',
- color: Colors.midNightblue,
- fontSize: 18
+ dropDownStyle: {
+ marginLeft: -90,
+ width: Dimensions.get('window').width,
+ shadowColor: '#000',
+ shadowOffset: { width: -1, height: 1 },
+ shadowOpacity: 0.2,
+ elevation: 1
},
- suggestionTextWrapper: {
- marginTop: 20
+ linkText: { color: Colors.softBlue, flex: 3, paddingVertical: 0},
+ replyAmtWrapper : {
+ flex:1,
+ flexDirection:"row",
+ justifyContent:'space-between',
+ alignItems:'center'
},
- linkText: { color: Colors.softBlue, flex: 1 }
+ errorStyle: {
+ width: 0,
+ flex: 0,
+ height: 0
+ }
};
export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/FanVideoReplyDetails/TouchableButton.js b/src/components/FanVideoReplyDetails/TouchableButton.js
new file mode 100644
index 00000000..2460e629
--- /dev/null
+++ b/src/components/FanVideoReplyDetails/TouchableButton.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { Image, Text, TouchableOpacity } from 'react-native';
+import Theme from '../../theme/styles';
+import source from '../../assets/reply-with-pepo.png'
+
+const TouchableButton = ({ TouchableStyles, TextStyles, textBeforeImage, textAfterImage, onPress, imgDimension, buttonText, disabled = false }) => (
+
+ {buttonText ?
+ {buttonText}:
+
+ {textBeforeImage}
+
+ {textAfterImage}
+
+ }
+
+);
+
+export default TouchableButton;
diff --git a/src/components/FanVideoReplyDetails/index.js b/src/components/FanVideoReplyDetails/index.js
new file mode 100644
index 00000000..9fa80f81
--- /dev/null
+++ b/src/components/FanVideoReplyDetails/index.js
@@ -0,0 +1,400 @@
+import React, { Component } from 'react';
+import {
+ Image,
+ ImageBackground,
+ TouchableOpacity,
+ View,
+ Text,
+ Keyboard,
+ ScrollView
+} from 'react-native';
+import deepGet from 'lodash/get';
+import CurrentUser from '../../models/CurrentUser';
+import styles from './styles';
+import VideoDescription from '../FanVideoDetails/VideoDescription';
+import BackArrow from '../CommonComponents/BackArrow';
+import Colors from '../../theme/styles/Colors';
+import playIcon from '../../assets/play_icon.png';
+import TouchableButton from './TouchableButton';
+import Theme from '../../theme/styles';
+import LinearGradient from 'react-native-linear-gradient';
+import VideoLink from '../FanVideoDetails/VideoLink';
+import reduxGetter from '../../services/ReduxGetters';
+import { connect } from 'react-redux';
+import Store from '../../store';
+import { upsertRecordedVideo } from '../../actions';
+import multipleClickHandler from '../../services/MultipleClickHandler';
+import { getBottomSpace } from 'react-native-iphone-x-helper';
+import { StackActions } from 'react-navigation';
+import PepoApi from "../../services/PepoApi";
+import DataContract from "../../constants/DataContract";
+import pricer from "../../services/Pricer";
+import {ensureDeivceAndSession, ON_USER_CANCLLED_ERROR_MSG} from "../../helpers/TransactionHelper";
+import Toast from "../../theme/components/NotificationToast";
+import { WORKFLOW_CANCELLED_MSG } from '../../services/OstSdkErrors';
+import AppConfig from '../../constants/AppConfig';
+
+//TODO setParams dont use
+
+const PROCESSING_TEXT = 'Processing...';
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ recordedVideo: reduxGetter.getRecordedVideo()
+ };
+};
+
+class FanVideoReplyDetails extends Component {
+ static navigationOptions = ({ navigation }) => {
+ return {
+ title: 'Post',
+ headerBackTitle: null,
+ headerStyle: {
+ backgroundColor: Colors.white,
+ borderBottomWidth: 0,
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 1
+ },
+ shadowOpacity: 0.1,
+ shadowRadius: 3
+ },
+ headerTitleStyle: {
+ fontFamily: 'AvenirNext-Medium'
+ },
+ headerLeft: (
+ {
+ FanVideoReplyDetails.saveToRedux(navigation);
+ navigation.goBack();
+ })}
+ >
+
+
+ )
+ };
+ };
+
+ static saveToRedux = (navigation) => {
+ let desc = navigation.state.params.videoDesc,
+ link = navigation.state.params.videoLink;
+ Store.dispatch(upsertRecordedVideo({ video_desc: desc, video_link: link }));
+ };
+
+ constructor(props) {
+ super(props);
+ this.videoDesc = props.recordedVideo.video_desc || '';
+ this.videoLink = props.recordedVideo.video_link || '';
+ if (! props.recordedVideo.video_type ){
+ // It means
+ this.replyObject = this.props.navigation.getParam('reply_obj');
+ let videoType = this.props.navigation.getParam('video_type');
+ Store.dispatch(upsertRecordedVideo({ reply_obj: this.replyObject, video_type: videoType }));
+ } else {
+ this.replyObject = props.recordedVideo.reply_obj;
+ }
+
+ this.state = {
+ viewStyle: {
+ paddingBottom: 10
+ },
+ error: null,
+ linkError: null,
+ descError : null,
+ buttonText: null,
+ isSuggestOpen: false
+ };
+ }
+ _keyboardShown = (e) => {
+ let keyboardHeight = deepGet(e, 'endCoordinates.height') || 350;
+ this.setState({
+ viewStyle: {
+ paddingBottom: keyboardHeight - (15 + getBottomSpace([true]))
+ }
+ });
+ };
+
+ _keyboardHidden = () => {
+ this.setState({
+ viewStyle: {
+ paddingBottom: 10
+ }
+ });
+ };
+
+ componentWillMount() {
+ this.keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', this._keyboardShown.bind(this));
+ this.keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', this._keyboardHidden.bind(this));
+
+ this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardShown.bind(this));
+ this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardHidden.bind(this));
+ }
+
+ componentDidMount() {
+ this.props.navigation.setParams({
+ videoDesc: this.props.recordedVideo.video_desc,
+ videoLink: this.props.recordedVideo.video_link
+ });
+ this.setState({buttonText: this.setButtonText()});
+ }
+
+ setButtonText = () => {
+ if (! this.checkIfReplyChargeable()){
+ return 'Reply';
+ }
+ return null;
+ };
+
+
+ componentWillUnmount() {
+ this.keyboardWillShowListener.remove();
+ this.keyboardWillHideListener.remove();
+ this.keyboardDidShowListener.remove();
+ this.keyboardDidHideListener.remove();
+ }
+
+ checkIfReplyChargeable = () => {
+ let btAmount = this.getAmountToSend();
+ return this.replyObject.isChargeble && btAmount != '0';
+ };
+
+
+ ensureSession = () => {
+ return new Promise((resolve, reject)=> {
+ let btAmount = this.getAmountToSend();
+ const btInDecimal = pricer.getToDecimal(btAmount);
+ if (! this.checkIfReplyChargeable()) {
+ return resolve();
+ }
+ ensureDeivceAndSession(CurrentUser.getOstUserId(), btInDecimal, (device) => {
+ this._deviceUnauthorizedCallback(device);
+ reject();
+ }, (errorMessage, success) => {
+ if ( success ) {
+ return resolve();
+ } else {
+ if (ON_USER_CANCLLED_ERROR_MSG !== errorMessage && WORKFLOW_CANCELLED_MSG !== errorMessage) {
+ Toast.show({
+ text: errorMessage,
+ icon: 'error'
+ });
+ }
+ return reject()
+ }
+ });
+ });
+
+ // check If session active
+ };
+
+
+ _deviceUnauthorizedCallback = (device) => {
+ this.props.navigation.push('AuthDeviceDrawer', { device });
+ };
+
+
+ giveUploadConsent = () => {
+ Store.dispatch(
+ upsertRecordedVideo({ video_desc: this.videoDesc, video_link: this.videoLink, do_upload: true })
+ );
+ const popAction = StackActions.pop(1);
+ this.props.navigation.dispatch(popAction);
+ this.props.navigation.dispatch(popAction);
+ };
+
+
+
+
+ enableStartUploadFlag = () => {
+ this.clearErrors();
+ //todo @mayur button text change to validating or similar
+ let buttonText = this.state.buttonText;
+ this.setState({buttonText: PROCESSING_TEXT});
+ this.validateData().then((res) => {
+ let videoOwnerId = this.replyObject.replyReceiverUserId;
+ if (videoOwnerId === CurrentUser.getUserId()){
+ this.giveUploadConsent();
+ return;
+ }
+ this.ensureSession().then(() => {
+ this.giveUploadConsent();
+ }).catch(()=> {
+ });
+ this.setState({buttonText: buttonText});
+ }).catch((err)=>{
+ // show error on UI.
+ this.setState({buttonText: buttonText});
+ this.showError(err);
+ }) ;
+ };
+
+
+ showError = (err) => {
+ if(!err.error_data) return;
+ for (let error of err.error_data){
+ switch (error.parameter) {
+ case "link":
+ this.setState({linkError: error.msg});
+ break;
+ case "video_description":
+ this.setState({descError: error.msg});
+ break;
+ }
+ }
+ const status = deepGet(err , "code") || "";
+ if(status.toLowerCase() == AppConfig.beKnownErrorCodeMaps.validateUploadError){
+ this.setState({error: err.msg});
+ }
+ };
+
+
+ clearErrors = () => {
+ this.setState({
+ linkError: null,
+ descError: null,
+ error: null
+ });
+ };
+
+
+ validateData = () => {
+ let params = {};
+ //todo : @mayur put strings in data contract file
+ params['video_description'] = this.videoDesc;
+ params['link'] = this.videoLink;
+
+ params['parent_kind'] = 'video';
+ params['parent_id'] = this.replyObject.replyReceiverVideoId;
+
+ return new Promise((resolve, reject) => {
+ new PepoApi(DataContract.replies.validateReply)
+ .post(params)
+ .then((res)=>{
+ if (res && res.success){
+ return resolve(res);
+ } else {
+ return reject(res.err);
+ }
+ })
+ .catch((err)=>{
+ return reject(err);
+ })
+ });
+ };
+
+ onChangeDesc = (desc) => {
+ this.videoDesc = desc;
+ //Done for the value to be accessible in static navigationOptions
+ this.props.navigation.setParams({
+ videoDesc: desc
+ });
+ };
+
+ onChangeLink = (link) => {
+ this.videoLink = link;
+ //Done for the value to be accessible in static navigationOptions
+ this.props.navigation.setParams({
+ videoLink: link
+ });
+ };
+
+ setError = (error) => {
+ this.setState({
+ error
+ });
+ };
+
+
+ getAmountToSend = () => {
+ let amount = this.replyObject.amountToSendWithReply ;
+ return pricer.getToBT(pricer.getFromDecimal(amount), 2);
+ };
+
+
+ pointerEventForInPageElement() {
+ if ( this.state.isSuggestOpen ) {
+ return "none";
+ }
+ return "auto";
+ };
+
+ onSuggestionsPanelClose = () => {
+ this.setState({
+ isSuggestOpen: false
+ });
+ };
+
+ onSuggestionsPanelOpen = () => {
+ this.setState({
+ isSuggestOpen: true
+ });
+ };
+
+ render() {
+ let imageUrl = this.props.recordedVideo.cover_image;
+ return (
+
+
+
+ {
+ FanVideoReplyDetails.saveToRedux(this.props.navigation);
+ this.props.navigation.goBack();
+ })}
+ style={{ height: 100 }}
+ >
+
+
+
+
+
+
+
+ {this.state.descError }
+
+ Link
+
+
+ {this.state.linkError }
+
+
+ {this.state.error}
+
+ {
+ this.enableStartUploadFlag();
+ })}
+ />
+
+
+
+ );
+ }
+}
+
+export default connect(mapStateToProps)(FanVideoReplyDetails);
diff --git a/src/components/FanVideoReplyDetails/styles.js b/src/components/FanVideoReplyDetails/styles.js
new file mode 100644
index 00000000..e792ac12
--- /dev/null
+++ b/src/components/FanVideoReplyDetails/styles.js
@@ -0,0 +1,79 @@
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../theme/styles/Colors';
+import { Dimensions } from 'react-native';
+import { Header } from 'react-navigation-stack';
+
+import { getStatusBarHeight, getBottomSpace, isIphoneX } from 'react-native-iphone-x-helper';
+
+const safeAreaHeight = getStatusBarHeight() + getBottomSpace([true]);
+
+let stylesMap = {
+ container: {
+ backgroundColor: '#fff',
+ flex: 1,
+ justifyContent: 'space-between',
+ height: Dimensions.get('window').height - safeAreaHeight - Header.HEIGHT - 55
+ },
+ posterImageSkipFont: {
+ aspectRatio: 3 / 4,
+ height: 100,
+ justifyContent: 'center'
+ },
+ playIconSkipFont: {
+ height: 14,
+ width: 14,
+ alignSelf: 'center'
+ },
+ videoDescriptionItem: {
+ flexDirection: 'row',
+ borderBottomWidth: 1,
+ borderColor: '#ccd3cd',
+ paddingHorizontal: 15,
+ paddingVertical: 20
+ },
+ videoDescription: {
+ color: 'rgba(42, 41, 59, 0.8)',
+ // flex: 1,
+ flexWrap: 'wrap',
+ fontFamily: 'AvenirNext-Regular',
+ borderColor: 'transparent',
+ borderWidth: 0,
+ borderRadius: 0,
+ fontWeight: '300',
+ marginLeft: 10,
+ marginTop: 0,
+ padding: 0,
+ paddingTop: 0,
+ position: 'relative',
+ paddingLeft: 0,
+ height: 100
+ },
+ videoLinkItem: {
+ flexDirection: 'row',
+ borderBottomWidth: 1,
+ borderColor: '#ccd3cd',
+ paddingBottom: 16,
+ alignItems: 'center',
+ paddingHorizontal: 12,
+ zIndex: -1
+ },
+ dropDownStyle: {
+ marginLeft: -90,
+ width: Dimensions.get('window').width,
+ shadowColor: '#000',
+ shadowOffset: { width: -1, height: 1 },
+ shadowOpacity: 0.2,
+ elevation: 1
+ },
+ suggestionText: {
+ color: Colors.midNightblue,
+ fontSize: 16,
+ fontFamily: 'AvenirNext-Regular'
+ },
+ suggestionTextWrapper: {
+ marginVertical: 9
+ },
+ linkText: { color: Colors.softBlue, flex: 3, paddingVertical: 0}
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/FullScreenReplyCollection/BaseVideoReplyRow.js b/src/components/FullScreenReplyCollection/BaseVideoReplyRow.js
new file mode 100644
index 00000000..13f31018
--- /dev/null
+++ b/src/components/FullScreenReplyCollection/BaseVideoReplyRow.js
@@ -0,0 +1,191 @@
+import React, { PureComponent } from 'react';
+import { View, TouchableOpacity} from 'react-native';
+import FanVideo from "../VideoWrapper/FanVideo";
+import ReportVideo from "../CommonComponents/ReportVideo";
+import BottomReplyBar from "../CommonComponents/BottomReplyBar";
+import PepoApi from '../../services/PepoApi';
+import deepGet from 'lodash/get';
+
+import inlineStyles from './styles';
+
+import ReplyPepoTxBtn from '../PepoTransactionButton/ReplyPepoTxBtn';
+import VideoReplySupporterStat from '../CommonComponents/VideoSupporterStat/VideoReplySupporterStat';
+
+import ReplyVideoBottomStatus from '../BottomStatus/ReplyVideoBottomStatus';
+import DataContract from '../../constants/DataContract';
+import ReduxGetters from '../../services/ReduxGetters';
+import CommonStyle from "../../theme/styles/Common";
+import assignIn from 'lodash/assignIn';
+import InvertedReplyList from "../CommonComponents/InvertedReplyThumbnailList";
+
+import AppConfig from "../../constants/AppConfig";
+import ProfilePicture from "../ProfilePicture";
+import multipleClickHandler from '../../services/MultipleClickHandler';
+import { fetchVideo } from '../../helpers/helpers';
+import ReplyShareIcon from '../CommonComponents/ShareIcon/ReplyShare';
+
+class BaseVideoReplyRow extends PureComponent {
+ constructor(props) {
+ super(props);
+ this.state = {
+ parentVideoId : ReduxGetters.getReplyParentVideoId( props.replyDetailId ),
+ parentUserId : ReduxGetters.getReplyParentUserId( props.replyDetailId )
+ }
+ this.onParentClickDelegate = this.props.parentClickHandler || this.defaultParentClickHandler;
+ }
+
+ componentDidMount(){
+ if(this.props.doRender && this.state.parentVideoId && !this.state.parentUserId ){
+ this.fetchParentVideo = fetchVideo(this.state.parentVideoId, this.onParentVideoFetch , null , this.onParentVideoFetchComplete);
+ }
+ }
+
+ componentDidUpdate(prevProps){
+ if(!this.fetchParentVideo && this.props.doRender && this.props.doRender !== prevProps.doRender && !this.state.parentUserId ){
+ fetchVideo(this.state.parentVideoId, this.onParentVideoFetch , null , this.onParentVideoFetchComplete);
+ }
+ }
+
+ componentWillUnmount(){
+ this.onParentVideoFetch = () => {};
+ this.onParentVideoFetchComplete = () => {};
+ }
+
+ onParentProfileIconClick() {
+ if(this.state.parentVideoId){
+ this.onParentClickDelegate();
+ }
+ }
+
+ onParentVideoFetchComplete() {
+ this.fetchParentVideo = null;
+ }
+
+ onParentVideoFetch = (res) => {
+ const video_details = deepGet(res, `data.${DataContract.videos.videoDetailsKey}`),
+ item = video_details[this.state.parentVideoId];
+ if( item ){
+ this.setState({
+ parentUserId: item[DataContract.videos.creatorUserIdKey]
+ })
+ }
+ }
+
+ refetchVideoReply = () => {
+ new PepoApi(`/replies/${this.props.replyDetailId}`)
+ .get()
+ .then((res) => {})
+ .catch((error) => {});
+ };
+
+ getPixelDropData = () => {
+ const parentData = this.props.getPixelDropData();
+ const pixelParams = {
+ e_entity: 'reply',
+ parent_video_id : this.state.parentVideoId,
+ p_name: this.state.parentVideoId,
+ reply_detail_id :this.props.replyDetailId
+ };
+ return assignIn({}, pixelParams, parentData);
+ }
+
+ defaultParentClickHandler(){
+ this.props.navigation.goBack(null);
+ }
+
+ _renderInvertedFlatList = () => {
+ if( this.state.parentVideoId && this.props.isActive ){
+ return (
+
+
+
+ )
+ }
+ return null;
+ }
+
+ render() {
+ const videoId = ReduxGetters.getReplyEntityId(this.props.replyDetailId);
+ return (
+
+
+
+
+
+
+ {!!videoId && !!this.props.userId && (
+
+
+
+
+ {this._renderInvertedFlatList()}
+
+
+
+
+ {this.onParentProfileIconClick()})}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+
+ );
+ }
+}
+
+BaseVideoReplyRow.defaultProps = {
+ getPixelDropData: function(){
+ console.warn("getPixelDropData props is mandatory for Video component");
+ return {};
+ },
+ paginationService : null,
+ currentIndex: 0
+ };
+
+export default BaseVideoReplyRow
diff --git a/src/components/FullScreenReplyCollection/NoPendantsVideoReplyRow.js b/src/components/FullScreenReplyCollection/NoPendantsVideoReplyRow.js
new file mode 100644
index 00000000..a2325106
--- /dev/null
+++ b/src/components/FullScreenReplyCollection/NoPendantsVideoReplyRow.js
@@ -0,0 +1,16 @@
+import BaseVideoReplyRow from "./BaseVideoReplyRow";
+import { withNavigation } from "react-navigation";
+
+class NoPendantsVideoReplyRow extends BaseVideoReplyRow {
+ constructor(props){
+ super(props);
+ }
+
+ _renderInvertedFlatList =() => {
+ return null;
+ }
+}
+
+NoPendantsVideoReplyRow.defaultProps = BaseVideoReplyRow.defaultProps;
+
+export default withNavigation( NoPendantsVideoReplyRow );
diff --git a/src/components/FullScreenReplyCollection/VideoReplyRow.js b/src/components/FullScreenReplyCollection/VideoReplyRow.js
new file mode 100644
index 00000000..5a606b04
--- /dev/null
+++ b/src/components/FullScreenReplyCollection/VideoReplyRow.js
@@ -0,0 +1,14 @@
+
+
+import BaseVideoReplyRow from "./BaseVideoReplyRow";
+import { withNavigation } from "react-navigation";
+
+class VideoReplyRow extends BaseVideoReplyRow {
+ constructor(props) {
+ super(props);
+ }
+}
+
+VideoReplyRow.defaultProps = BaseVideoReplyRow.defaultProps;
+
+export default withNavigation( VideoReplyRow )
diff --git a/src/components/FullScreenReplyCollection/index.js b/src/components/FullScreenReplyCollection/index.js
new file mode 100644
index 00000000..98563d5e
--- /dev/null
+++ b/src/components/FullScreenReplyCollection/index.js
@@ -0,0 +1,281 @@
+import React , {PureComponent} from "react";
+import {FlatList ,View } from "react-native";
+import FloatingBackArrow from "../CommonComponents/FlotingBackArrow";
+import deepGet from "lodash/get";
+
+import Pagination from "../../services/Pagination";
+import VideoReplyRow from "./VideoReplyRow";
+import entityHelper from "../../helpers/EntityHelper";
+import DataContract from "../../constants/DataContract";
+import CommonStyle from "../../theme/styles/Common";
+import { SafeAreaView } from "react-navigation";
+import ReplyHelper from "../../helpers/ReplyHelper";
+import TopStatus from "../Home/TopStatus";
+import InvertedReplyList from "../CommonComponents/InvertedReplyThumbnailList";
+import NoPendantsVideoReplyRow from "./NoPendantsVideoReplyRow";
+import Utilities from "../../services/Utilities";
+
+const maxVideosThreshold = 3;
+
+class FullScreenReplyCollection extends PureComponent{
+
+ static navigationOptions = (props) => {
+ return {
+ headerBackTitle: null,
+ header: null
+ };
+ };
+
+ constructor(props){
+ super(props);
+ this.setVideoPagination();
+ this.paginationEvent = this.getVideoPagination().event;
+ this.currentIndex = this.props.navigation.getParam("currentIndex") || 0;
+ this.parentClickHandler = this.props.navigation.getParam("parentClickHandler");
+ this.isScrolled = false ;
+ this.willFocusSubscription = null ;
+ this.flatlistRef = null;
+
+ this.state = {
+ list : this.getVideoPagination().getResults(),
+ activeIndex: this.currentIndex,
+ refreshing : false,
+ loadingNext: false
+ };
+ this.isActiveScreen = true;
+ }
+
+ getBaseUrl(){
+ return this.props.navigation.getParam("baseUrl");
+ }
+
+ getPassedFetchServices(){
+ return this.props.navigation.getParam("fetchServices")
+ }
+
+ setVideoPagination(){
+ let fetchService = this.getPassedFetchServices();
+ fetchService = fetchService.cloneWithData();
+ this.fullPagePagination = new Pagination( this.getBaseUrl(), null , fetchService);
+ }
+
+ getVideoPagination(){
+ return this.fullPagePagination;
+ }
+
+ componentDidMount(){
+ this.paginationEvent.on("onBeforeRefresh" , this.beforeRefresh.bind(this) );
+ this.paginationEvent.on("onRefresh" , this.onRefresh.bind(this) );
+ this.paginationEvent.on("onRefreshError" , this.onRefreshError.bind(this) );
+ this.paginationEvent.on("onBeforeNext" , this.beforeNext.bind(this) );
+ this.paginationEvent.on("onNext" , this.onNext.bind(this) );
+ this.paginationEvent.on("onNextError" , this.onNextError.bind(this) );
+
+ //This is an hack for reset scroll for flatlist. Need to debug a bit more.
+ this.willFocusSubscription = this.props.navigation.addListener('willFocus', (payload) => {
+ const offset = this.state.activeIndex > 0 ? CommonStyle.fullScreen.height * this.state.activeIndex : 0 ;
+ this.flatlistRef && this.flatlistRef.scrollToOffset({offset: offset , animated: false});
+ this.isActiveScreen = true ;
+ });
+
+ this.willBlurSubscription = this.props.navigation.addListener('willBlur', (payload) => {
+ this.isActiveScreen = false ;
+ });
+
+ //If there is no getPassedFetchServices passed that means its a fresh view.
+ //So load data
+ if(!this.getPassedFetchServices()){
+ this.refresh();
+ }
+ }
+
+ componentWillUnmount(){
+ this.paginationEvent.removeListener('onBeforeRefresh');
+ this.paginationEvent.removeListener('onRefresh');
+ this.paginationEvent.removeListener('onRefreshError');
+ this.paginationEvent.removeListener('onBeforeNext');
+ this.paginationEvent.removeListener('onNext');
+ this.paginationEvent.removeListener('onNextError');
+ this.willFocusSubscription && this.willFocusSubscription.remove();
+ this.willBlurSubscription && this.willBlurSubscription.remove();
+ }
+
+ shouldPlay = () => {
+ return this.isActiveScreen;
+ };
+
+ beforeRefresh = ( ) => {
+ this.setState({ refreshing : true });
+ }
+
+ onRefresh = ( res ) => {
+ let paginationService = this.getVideoPagination();
+ let resultList = paginationService.getResults();
+ this.setState({ refreshing : false , list : resultList });
+ }
+
+ onRefreshError = ( error ) => {
+ this.setState({ refreshing : false });
+ }
+
+ beforeNext =() => {
+ this.isScrolled = false;
+ this.setState({ loadingNext : true });
+ }
+
+ onNext = ( res ) => {
+ let paginationService = this.getVideoPagination();
+ let resultList = paginationService.getResults();
+ this.setState({ loadingNext : false , list : resultList });
+ }
+
+ onNextError = ( error ) => {
+ this.setState({ loadingNext : false });
+ }
+
+ getNext = () => {
+ // if(!this.isScrolled) return;
+ this.getVideoPagination().getNext();
+ }
+
+ refresh = () => {
+ this.getVideoPagination().refresh();
+ }
+
+ _keyExtractor = (item, index) => {
+ return `id_${item.id}`;
+ }
+
+ _renderItem = ({ item, index }) => {
+ if(entityHelper.isVideoReplyEntity( item )){
+ if(entityHelper.isReplyVideoTypeEntity(item)){
+ return this._renderVideoReplyRow( item, index );
+ }
+ }
+ };
+
+ getPixelDropData = ( replyDetailId ) => {
+ return () => {
+ return {
+ e_entity: 'reply',
+ p_type: 'video_reply'
+ };
+ }
+ }
+
+ _renderVideoReplyRow(item, index){
+ let userId = deepGet(item,'payload.user_id'),
+ replyDetailId = deepGet(item,`payload.${DataContract.replies.replyDetailIdKey}`);
+ return ;
+ }
+
+ childClickHandler = ( index, item )=> {
+ ReplyHelper.updateEntitySeen( item );
+ this.scrollToIndex( index );
+ }
+
+ scrollToIndex = ( index )=>{
+ this.setActiveIndex( index, () => {
+ this.flatlistRef.scrollToIndex({index: index});
+ });
+ }
+
+ onViewableItemsChanged = (data) => {
+ let item = deepGet(data, 'viewableItems[0].item');
+ item && ReplyHelper.updateEntitySeen( item );
+ let currentIndex = deepGet(data, 'viewableItems[0].index');
+ if ( "number" === typeof currentIndex ) {
+ this.currentIndex = currentIndex;
+ }
+ }
+
+ setActiveIndex( index, callback ) {
+ if( typeof index === "number"){
+ this.currentIndex = index;
+ }
+ this.setState({ activeIndex: this.currentIndex }, callback);
+ }
+
+ onMomentumScrollEndCallback = () => {
+ this.setActiveIndex();
+ };
+
+ onMomentumScrollBeginCallback = () => {
+ this.isScrolled = true;
+ }
+
+ onScrollToIndexFailed =( info) => {
+ console.log("======onScrollToIndexFailed=====" , info );
+ }
+
+ getItemLayout= (data, index) => {
+ return {length: CommonStyle.fullScreen.height, offset: CommonStyle.fullScreen.height * index, index} ;
+ }
+
+ closeVideo = () => {
+ this.navigateBack();
+ };
+
+ navigateBack() {
+ this.props.navigation.goBack();
+ }
+
+ onScrollToTop = () => {
+ this.setActiveIndex();
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+
+ {this.flatlistRef = ref }}
+ onEndReachedThreshold={7}
+ onViewableItemsChanged={this.onViewableItemsChanged}
+ onMomentumScrollEnd={this.onMomentumScrollEndCallback}
+ onMomentumScrollBegin={this.onMomentumScrollBeginCallback}
+ renderItem={this._renderItem}
+ style={[CommonStyle.fullScreen , {backgroundColor: "#000"}]}
+ showsVerticalScrollIndicator={false}
+ onScrollToTop={this.onScrollToTop}
+ initialScrollIndex={this.state.activeIndex}
+ getItemLayout={this.getItemLayout}
+ onScrollToIndexFailed={this.onScrollToIndexFailed}
+ />
+
+
+ );
+ }
+
+}
+
+export default FullScreenReplyCollection ;
diff --git a/src/components/FullScreenReplyCollection/styles.js b/src/components/FullScreenReplyCollection/styles.js
new file mode 100644
index 00000000..555f80e3
--- /dev/null
+++ b/src/components/FullScreenReplyCollection/styles.js
@@ -0,0 +1,132 @@
+import { Dimensions, StatusBar, NativeModules } from 'react-native';
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../theme/styles/Colors';
+import { ifIphoneX, getBottomSpace , getStatusBarHeight} from 'react-native-iphone-x-helper';
+
+import NotchHelper from "../../helpers/NotchHelper";
+import { HEADER_HEIGHT } from '../../theme/constants';
+const {width, height} = Dimensions.get('window');
+const statusBarHeight = StatusBar.currentHeight || 20;
+
+
+let RNDeviceInfo = NativeModules.RNDeviceInfo;
+let modalDeviceName = RNDeviceInfo.model === "Redmi Note 7 Pro" && RNDeviceInfo.brand === "xiaomi";
+let btmSpace = modalDeviceName ? 5 : 0;
+
+let stylesMap = {
+ fullScreen: {
+ width: width,
+ ...ifIphoneX(
+ {
+ height: height - HEADER_HEIGHT - getStatusBarHeight(true)
+ },
+ {
+ height:
+ NotchHelper.hasNotch()
+ ? height + statusBarHeight - btmSpace - HEADER_HEIGHT
+ : height - statusBarHeight - HEADER_HEIGHT
+ }
+ )
+ },
+ touchablesBtns: {
+ alignItems: 'flex-end',
+ marginBottom: -10,
+ zIndex: 1,
+ flexDirection: 'row'
+ },
+ invertedList: {
+ marginRight: 'auto',
+ minWidth: '20%',
+ marginBottom: 40
+ },
+ pepoTxCount: {
+ fontSize: 18,
+ color: Colors.white,
+ alignSelf: 'center',
+ marginTop: 3,
+ marginBottom: 5
+ },
+ txElem: {
+ marginBottom: 20
+ },
+ bottomContainer: {
+ width: width,
+ position: 'absolute',
+ bottom: 0
+ },
+ bottomBg: {
+ backgroundColor: 'rgba(0, 0, 0, 0.6)',
+ borderTopLeftRadius: 20,
+ minHeight: height * 0.05,
+ paddingHorizontal: 12
+ },
+ handle: {
+ fontSize: 15,
+ paddingBottom: 3,
+ color: Colors.white,
+ fontFamily: 'AvenirNext-DemiBold',
+ fontWeight: '700'
+ },
+ bottomBgTxt: {
+ color: Colors.white
+ },
+ raisedSupported: {
+ backgroundColor: Colors.wildWatermelon2,
+ borderTopLeftRadius: 25,
+ borderBottomRightRadius: 25,
+ paddingHorizontal: 8,
+ minWidth: 120,
+ height: 40,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginRight: 10
+ },
+ raisedSupportedTxt: {
+ color: Colors.white,
+ fontSize: 14,
+ fontFamily: 'AvenirNext-DemiBold'
+ },
+ btnText: {
+ color: Colors.white
+ },
+ iconWrapper: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: 60,
+ width: 60
+ },
+ iconSkipFont: {
+ height: 20,
+ width: 20
+ },
+ headerStyles: {
+ backgroundColor: Colors.white,
+ borderBottomWidth: 0,
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 1
+ },
+ shadowOpacity: 0.1,
+ shadowRadius: 3,
+ height: HEADER_HEIGHT
+ },
+ headerText:{
+ fontWeight: '600'
+ },
+ headerSubText:{
+ fontSize: 12
+ },
+ listContainer: {
+ // width: width,
+ position: 'absolute',
+ bottom: height * 0.05 + 50,
+ left: 10,
+ zIndex: 9,
+ alignSelf: 'flex-start',
+ height: height - 200
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/FullScreenVideoCollection/FullScreeVideoRow.js b/src/components/FullScreenVideoCollection/FullScreeVideoRow.js
deleted file mode 100644
index 0dbf318a..00000000
--- a/src/components/FullScreenVideoCollection/FullScreeVideoRow.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import React, { PureComponent } from 'react';
-import { View, TouchableOpacity, Image } from 'react-native';
-import { withNavigation } from 'react-navigation';
-import VideoWrapper from '../Home/VideoWrapper';
-import ShareIcon from "../CommonComponents/ShareIcon";
-import ReportVideo from "../CommonComponents/ReportVideo";
-import PepoApi from '../../services/PepoApi';
-import TransactionPepoButton from '../Home/TransactionPepoButton';
-import deepGet from 'lodash/get';
-import CurrentUser from '../../models/CurrentUser';
-
-import BottomStatus from '../Home/BottomStatus';
-import VideoAmountStat from '../CommonComponents/VideoAmoutStat';
-import ShareVideo from '../../services/shareVideo';
-import inlineStyles from './styles';
-
-import utilities from '../../services/Utilities';
-import OptionsIcon from '../../assets/options_self_video.png';
-
-
-class FullScreeVideoRow extends PureComponent {
- constructor(props) {
- super(props);
- console.log("this.props", this.props);
- this.userId = deepGet(this.props.payload, 'user_id');
- this.videoId = deepGet(this.props.payload, 'video_id');
-
-
-
- }
-
- refetchVideo = () => {
- new PepoApi(`/videos/${this.videoId}`)
- .get()
- .then((res) => {})
- .catch((error) => {});
- };
-
-
-
- shareVideo = () => {
- let shareVideo = new ShareVideo(this.videoId);
- shareVideo.perform();
- };
-
- navigateToUserProfile = (e) => {
- if (utilities.checkActiveUser()) {
- if (this.userId == CurrentUser.getUserId()) {
- this.props.navigation.navigate('ProfileScreen');
- } else {
- this.props.navigation.push('UsersProfileScreen', { userId: this.userId });
- }
- }
- };
-
- onDescriptionClick = ( tapEntity , tapText ) => {
- if (!tapEntity) {
- return;
- }
-
- if( tapEntity.kind === 'tags'){
- this.props.navigation.push('VideoTags', {
- "tagId": tapEntity.id
- });
- }
-
- }
-
- render() {
- return (
-
-
-
- {!!this.videoId && !!this.userId && (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- );
- }
-}
-
-export default withNavigation(FullScreeVideoRow);
diff --git a/src/components/FullScreenVideoCollection/FullScreenVideoRow.js b/src/components/FullScreenVideoCollection/FullScreenVideoRow.js
new file mode 100644
index 00000000..bbd181b1
--- /dev/null
+++ b/src/components/FullScreenVideoCollection/FullScreenVideoRow.js
@@ -0,0 +1,110 @@
+import React, { PureComponent } from 'react';
+import { View , Dimensions} from 'react-native';
+import { withNavigation } from 'react-navigation';
+import FanVideo from '../VideoWrapper/FanVideo';
+import ReportVideo from "../CommonComponents/ReportVideo";
+import PepoApi from '../../services/PepoApi';
+import deepGet from 'lodash/get';
+
+import VideoBottomStatus from '../BottomStatus/VideoBottomStatus';
+import inlineStyles from './styles';
+
+import ReplyIcon from '../CommonComponents/ReplyIcon';
+import PepoTxBtn from '../PepoTransactionButton/PepoTxBtn';
+import VideoSupporterStat from '../CommonComponents/VideoSupporterStat/VideoSupporterStat';
+import DataContract from '../../constants/DataContract';
+import BottomReplyBar from '../CommonComponents/BottomReplyBar';
+import assignIn from 'lodash/assignIn';
+
+
+import AppConfig from "../../constants/AppConfig";
+import CommonStyle from "../../theme/styles/Common";
+import BubbleList from "../CommonComponents/BubbleList";
+import VideoShareIcon from '../CommonComponents/ShareIcon/VideoShare';
+
+
+const AREA = AppConfig.MaxDescriptionArea;
+const height = AREA / Dimensions.get('window').width + 20;
+
+class FullScreeVideoRow extends PureComponent {
+ constructor(props) {
+ super(props);
+ this.userId = deepGet(this.props.payload, 'user_id');
+ this.videoId = deepGet(this.props.payload, 'video_id');
+ }
+
+ refetchVideo = () => {
+ new PepoApi(`/videos/${this.videoId}`)
+ .get()
+ .then((res) => {})
+ .catch((error) => {});
+ };
+
+ getPixelDropData = () => {
+ const parentData = this.props.getPixelDropData();
+ const pixelParams = { e_entity: 'video' , video_id : this.videoId};
+ return assignIn({}, pixelParams, parentData);
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ {!!this.videoId && !!this.userId && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {p_type: 'feed'}}
+ />
+
+ )}
+
+
+
+ );
+ }
+}
+
+FullScreeVideoRow.defaultProps = {
+ getPixelDropData: function(){
+ console.warn("getPixelDropData props is mandatory for Video component");
+ return {};
+ }
+ };
+
+
+export default withNavigation(FullScreeVideoRow);
diff --git a/src/components/FullScreenVideoCollection/index.js b/src/components/FullScreenVideoCollection/index.js
index 4028438f..e8297b13 100644
--- a/src/components/FullScreenVideoCollection/index.js
+++ b/src/components/FullScreenVideoCollection/index.js
@@ -1,12 +1,17 @@
import React , {PureComponent} from "react";
-import {FlatList , View , TouchableOpacity, Image} from "react-native";
+import {FlatList} from "react-native";
import deepGet from "lodash/get";
+
import reduxGetters from "../../services/ReduxGetters";
import Pagination from "../../services/Pagination";
-import FullScreeVideoRow from "./FullScreeVideoRow";
-import inlineStyles from "./styles";
-import historyBack from '../../assets/user-video-history-back-icon.png';
+import FullScreenVideoRow from "./FullScreenVideoRow";
+import FloatingBackArrow from "../CommonComponents/FlotingBackArrow";
import TopStatus from "../Home/TopStatus";
+import CommonStyle from "../../theme/styles/Common";
+import entityHelper from '../../helpers/EntityHelper';
+import DataContract from "../../constants/DataContract";
+import VideoReplyRow from "../FullScreenReplyCollection/VideoReplyRow";
+import { SafeAreaView } from "react-navigation";
const maxVideosThreshold = 3;
@@ -24,12 +29,13 @@ class FullScreenVideoCollection extends PureComponent{
this.setVideoPagination();
this.paginationEvent = this.getVideoPagination().event;
this.currentIndex = this.props.navigation.getParam("currentIndex");
+ this.tagId = this.props.navigation.getParam("tagId");
this.isScrolled = false ;
this.willFocusSubscription = null ;
this.flatlistRef = null;
this.state = {
- list : this.getVideoPagination().getList(),
+ list : this.getVideoPagination().getResults(),
activeIndex: this.currentIndex,
refreshing : false,
loadingNext: false
@@ -63,7 +69,7 @@ class FullScreenVideoCollection extends PureComponent{
//This is an hack for reset scroll for flatlist. Need to debug a bit more.
this.willFocusSubscription = this.props.navigation.addListener('willFocus', (payload) => {
- const offset = this.state.activeIndex > 0 ? inlineStyles.fullScreen.height * this.state.activeIndex : 0 ;
+ const offset = this.state.activeIndex > 0 ? CommonStyle.fullScreen.height * this.state.activeIndex : 0 ;
this.flatlistRef && this.flatlistRef.scrollToOffset({offset: offset , animated: false});
this.isActiveScreen = true ;
});
@@ -93,7 +99,7 @@ class FullScreenVideoCollection extends PureComponent{
}
onRefresh = ( res ) => {
- this.setState({ refreshing : false , list : this.getVideoPagination().getList() });
+ this.setState({ refreshing : false , list : this.getVideoPagination().getResults() });
}
onRefreshError = ( error ) => {
@@ -106,7 +112,7 @@ class FullScreenVideoCollection extends PureComponent{
}
onNext = ( res ) => {
- this.setState({ loadingNext : false , list : this.getVideoPagination().getList() });
+ this.setState({ loadingNext : false , list : this.getVideoPagination().getResults() });
}
onNextError = ( error ) => {
@@ -124,21 +130,86 @@ class FullScreenVideoCollection extends PureComponent{
}
_keyExtractor = (item, index) => {
- return `id_${item}`;
+ let keyStr = `id_${item.id}`;
+ return keyStr;
};
_renderItem = ({ item, index }) => {
const payload = reduxGetters.getTagsVideoPayload(item);
console.log("payload", payload);
- return ;
+ if(entityHelper.isVideoReplyEntity( item )){
+ if(entityHelper.isReplyVideoTypeEntity(item)){
+ return this._renderVideoReplyRow( item, index );
+ }
+ } else if( entityHelper.isVideoEntity( item )) {
+ return this._renderVideoRow( item, index);
+ }
+
};
+ getPixelDropData = () => {
+ return {
+ e_entity: 'video',
+ p_type: 'tag',
+ p_name: this.tagId,
+ };
+ }
+
+ getReplyPixelDrop = () => {
+ return {
+ e_entity: 'reply',
+ p_type: 'tag',
+ p_name: this.tagId,
+ };
+ }
+
+ parentClickHandler =(replyDetailId)=>{
+ const parentVideoId = reduxGetters.getReplyParentVideoId(replyDetailId),
+ parentUserId = reduxGetters.getReplyParentUserId(replyDetailId );
+ this.props.navigation.push('VideoPlayer', {
+ userId: parentUserId,
+ videoId: parentVideoId
+ });
+ }
+
+ isActiveEntity = (fullVideoReplyId , item , index)=> {
+ let replyId = deepGet(item, `payload.${DataContract.replies.replyDetailIdKey}`)
+ return fullVideoReplyId == replyId;
+ }
+
+ _renderVideoReplyRow(item, index){
+ let userId = deepGet(item,'payload.user_id'),
+ replyDetailId = deepGet(item,`payload.${DataContract.replies.replyDetailIdKey}`),
+ rowKey = this._keyExtractor(item, index)
+ ;
+ return {this.parentClickHandler(replyDetailId)}}
+ isActiveEntity={this.isActiveEntity}
+ /> ;
+ }
+
+ _renderVideoRow( item, index ){
+ let rowKey = this._keyExtractor(item, index);
+ return ;
+ }
+
onViewableItemsChanged = (data) => {
- this.currentIndex = deepGet(data, 'viewableItems[0].index') || 0;
+ const currentIndex = deepGet(data, 'viewableItems[0].index');
+ if("number" === typeof currentIndex ){
+ this.currentIndex = currentIndex;
+ }
}
setActiveIndex() {
@@ -158,7 +229,7 @@ class FullScreenVideoCollection extends PureComponent{
}
getItemLayout= (data, index) => {
- return {length: inlineStyles.fullScreen.height, offset: inlineStyles.fullScreen.height * index, index} ;
+ return {length: CommonStyle.fullScreen.height, offset: CommonStyle.fullScreen.height * index, index} ;
}
closeVideo = () => {
@@ -176,9 +247,10 @@ class FullScreenVideoCollection extends PureComponent{
render() {
return (
-
- {this.props.navigation.getParam("showBalanceFlier") && }
+
+ {this.props.navigation.getParam("showBalanceFlyer") && }
-
-
-
-
+
+
);
}
diff --git a/src/components/FullScreenVideoCollection/styles.js b/src/components/FullScreenVideoCollection/styles.js
index b59db44e..23f8a34f 100644
--- a/src/components/FullScreenVideoCollection/styles.js
+++ b/src/components/FullScreenVideoCollection/styles.js
@@ -33,25 +33,26 @@ let stylesMap = {
height: "100%"
},
touchablesBtns: {
- alignSelf: 'flex-end',
- marginBottom: -15,
- zIndex: 1
+ alignItems: 'flex-end',
+ marginBottom: -10,
+ zIndex: 1,
+ flexDirection: 'row'
+ },
+ invertedList: {
+ marginRight: 'auto',
+ minWidth: '20%',
+ marginBottom: 40
},
pepoTxCount: {
fontSize: 18,
color: Colors.white,
alignSelf: 'center',
marginTop: 3,
- marginBottom: 15
+ marginBottom: 5
},
txElem: {
marginBottom: 20
},
- bottomContainer: {
- width: width,
- position: 'absolute',
- bottom: 0
- },
bottomBg: {
backgroundColor: 'rgba(0, 0, 0, 0.6)',
borderTopLeftRadius: 20,
@@ -118,7 +119,21 @@ let stylesMap = {
height :10,
width:23,
zIndex: 1,
- }
+ },
+ bottomContainer: {
+ width: width,
+ position: 'absolute',
+ bottom: 0
+ },
+ listContainer: {
+ // width: width,
+ position: 'absolute',
+ bottom: height * 0.05 + 50,
+ left: 10,
+ zIndex: 9,
+ alignSelf: 'flex-start',
+ height: height - 200
+ }
};
export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/Home/AuthDeviceDrawer.js b/src/components/Home/AuthDeviceDrawer.js
index cee77513..b0122d27 100644
--- a/src/components/Home/AuthDeviceDrawer.js
+++ b/src/components/Home/AuthDeviceDrawer.js
@@ -10,6 +10,7 @@ import infoIcon from '../../assets/toast_error.png';
import Theme from "../../theme/styles";
import modalCross from '../../assets/modal-cross-icon.png';
import LinearGradient from 'react-native-linear-gradient';
+import CommonStyle from '../../theme/styles/Common';
@@ -128,7 +129,7 @@ export default class AuthDeviceDrawer extends PureComponent {
let config = this._getViewConfig();
return(
-
+
diff --git a/src/components/Home/BottomStatus.js b/src/components/Home/BottomStatus.js
deleted file mode 100644
index 307a4928..00000000
--- a/src/components/Home/BottomStatus.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import React, { PureComponent } from 'react';
-import { View, Text } from 'react-native';
-import { connect } from 'react-redux';
-import { withNavigation } from 'react-navigation';
-
-import inlineStyles from './styles';
-import { TouchableWithoutFeedback, TouchableOpacity } from 'react-native-gesture-handler';
-import reduxGetter from '../../services/ReduxGetters';
-
-import multipleClickHandler from '../../services/MultipleClickHandler';
-import InAppBrowser from '../../services/InAppBrowser';
-
-const mapStateToProps = (state, ownProps) => {
- return {
- userName: reduxGetter.getUserName(ownProps.userId, state),
- name: reduxGetter.getName(ownProps.userId, state),
- description: reduxGetter.getVideoDescription(reduxGetter.getVideoDescriptionId(ownProps.videoId, state), state),
- link: reduxGetter.getVideoLink(reduxGetter.getVideoLinkId(ownProps.videoId, state), state),
- supporters: reduxGetter.getVideoSupporters(ownProps.videoId),
- totalBt: reduxGetter.getVideoBt(ownProps.videoId, state)
- };
-};
-
-class BottomStatus extends PureComponent {
- constructor(props) {
- super(props);
- this.videoDescriptionId = reduxGetter.getVideoDescriptionId(this.props.videoId);
- }
-
- onWrapperClick = (e) => {
- this.props.onWrapperClick && this.props.onWrapperClick();
- };
-
- onLinkClick = () => {
- InAppBrowser.openBrowser(this.props.link);
- };
-
- onTagPressed = (tag) => {
- let entity = reduxGetter.getTappedIncludesEntity(this.videoDescriptionId, tag);
- this.props.onDescriptionClick && this.props.onDescriptionClick(entity, tag);
- };
-
- isValidTag(videoId, tappedText) {
- let entity = reduxGetter.getTappedIncludesEntity(videoId, tappedText);
- return !!entity
- }
-
- render() {
-
- let processingString = this.props.description;
- let hasTagArray = processingString.match(/#\w+/g) || [];
-
- return (
-
-
-
- this.onWrapperClick())} pointerEvents={'auto'}>
-
- {`@${this.props.userName}`}
-
-
- {this.props.description ? (
-
-
- {(hasTagArray.map((hashTag) => {
-
- let tagLocation = processingString.search(hashTag);
- let prevText = processingString.slice(0, tagLocation);
-
- processingString = processingString.slice(tagLocation + hashTag.length);
-
- if (this.isValidTag(this.videoDescriptionId, hashTag)) {
- let tagText = hashTag.replace("#", "");
- return (
-
- {prevText}
- {
- this.onTagPressed(hashTag)
- }}>
- #
- {tagText}
-
-
-
- );
- } else {
- return (
-
- {prevText + hashTag}
-
- )
- }
- }))
- }
- {processingString}
-
-
- ) : (
-
- )
- }
-
-
- {this.props.link ? (
- {
- this.onLinkClick();
- })}
- pointerEvents={'auto'}
- >
-
- {this.props.link.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')}
-
-
- ) : (
-
- )}
-
- );
- };
-}
-
-export default connect(mapStateToProps)(withNavigation(BottomStatus));
diff --git a/src/components/Home/HomeFeedRow.js b/src/components/Home/HomeFeedRow.js
index 7814e81a..07e1f7c6 100644
--- a/src/components/Home/HomeFeedRow.js
+++ b/src/components/Home/HomeFeedRow.js
@@ -1,20 +1,21 @@
import React, { PureComponent } from 'react';
-import { View, TouchableOpacity, Image, TouchableWithoutFeedback } from 'react-native';
+import {View, Dimensions} from 'react-native';
import { withNavigation } from 'react-navigation';
-import VideoWrapper from './VideoWrapper';
-import ShareIcon from "../CommonComponents/ShareIcon";
+import FanVideo from '../VideoWrapper/FanVideo';
import PepoApi from '../../services/PepoApi';
import reduxGetter from '../../services/ReduxGetters';
-import TransactionPepoButton from './TransactionPepoButton';
-import CurrentUser from '../../models/CurrentUser';
+import assignIn from 'lodash/assignIn';
-import BottomStatus from './BottomStatus';
-import VideoAmountStat from '../CommonComponents/VideoAmoutStat';
+import VideoBottomStatus from '../BottomStatus/VideoBottomStatus';
import inlineStyles from './styles';
-import utilities from '../../services/Utilities';
import ReportVideo from "../CommonComponents/ReportVideo";
+import ReplyIcon from '../CommonComponents/ReplyIcon';
+import PepoTxBtn from '../PepoTransactionButton/PepoTxBtn';
+import VideoSupporterStat from '../CommonComponents/VideoSupporterStat/VideoSupporterStat';
+import DataContract from '../../constants/DataContract';
+import VideoShareIcon from '../CommonComponents/ShareIcon/VideoShare';
class HomeFeedRow extends PureComponent {
constructor(props) {
@@ -36,80 +37,61 @@ class HomeFeedRow extends PureComponent {
.catch((error) => {});
};
- navigateToTransactionScreen = (e) => {
- if (utilities.checkActiveUser() && CurrentUser.isUserActivated(true)) {
- this.props.navigation.push('TransactionScreen', {
- toUserId: this.userId,
- videoId: reduxGetter.getHomeFeedVideoId(this.props.feedId),
- requestAcknowledgeDelegate: this.refetchFeed
- });
- }
- };
-
- navigateToUserProfile = (e) => {
- if (utilities.checkActiveUser()) {
- if (this.userId == CurrentUser.getUserId()) {
- this.props.navigation.navigate('ProfileScreen');
- } else {
- this.props.navigation.push('UsersProfileScreen', { userId: this.userId });
- }
- }
- };
-
- onDescriptionClick = ( tapEntity , tapText ) => {
- if (utilities.checkActiveUser()) {
- if (!tapEntity) {
- return;
- }
-
- if( tapEntity.kind === 'tags'){
- this.props.navigation.push('VideoTags', {
- "tagId": tapEntity.id
- });
- }
-
- }
- };
+ getPixelDropData = () => {
+ const parentData = this.props.getPixelDropData && this.props.getPixelDropData() || {};
+ const pixelParams = {
+ e_entity: 'video',
+ p_type: 'feed',
+ video_id: this.videoId,
+ };
+ return assignIn({}, pixelParams, parentData);
+ }
render() {
return (
-
-
+
+
-
-
-
-
+
+
+
+
-
-
+
+
+
-
+
+
+
-
+
);
}
}
+
export default withNavigation(HomeFeedRow);
diff --git a/src/components/Home/HomeScreen.js b/src/components/Home/HomeScreen.js
index fde383cd..cb02c59c 100644
--- a/src/components/Home/HomeScreen.js
+++ b/src/components/Home/HomeScreen.js
@@ -16,6 +16,7 @@ import {navigateTo} from "../../helpers/navigateTo";
import { LoadingModal } from '../../theme/components/LoadingModalCover';
import Colors from "../../theme/styles/Colors";
import utilities from "../../services/Utilities";
+import reduxGetter from '../../services/ReduxGetters';
const mapStateToProps = (state) => {
return {
@@ -165,6 +166,16 @@ class HomeScreen extends Component {
updateFlatList && updateFlatList([]);
}
+
+ getUploadingText = () => {
+ let videoType = reduxGetter.getRecordedVideoType();
+ if (videoType === 'post'){
+ return "Uploading Video";
+ } else if (videoType === 'reply'){
+ return "Posting reply";
+ }
+ };
+
beforeRefresh = () => {
Pricer.getBalance();
};
@@ -190,7 +201,7 @@ class HomeScreen extends Component {
),
left: 10
}}
- displayText="Uploading Video"
+ displayText={this.getUploadingText()}
extendDirection="right"
extend={true}
id={2}
diff --git a/src/components/Home/VideoList.js b/src/components/Home/VideoList.js
index b57e6fa3..e8d044bb 100644
--- a/src/components/Home/VideoList.js
+++ b/src/components/Home/VideoList.js
@@ -84,6 +84,7 @@ class VideoList extends PureComponent {
onScrollToTop={this.onScrollToTop}
onScrollToIndexFailed={this.onScrollToIndexFailed}
ref={(ref) => (this.flatlistRef = ref)}
+
/>
);
}
diff --git a/src/components/Home/styles.js b/src/components/Home/styles.js
index d46318af..bdabc21f 100644
--- a/src/components/Home/styles.js
+++ b/src/components/Home/styles.js
@@ -33,15 +33,21 @@ let stylesMap = {
height: "100%"
},
touchablesBtns: {
- alignSelf: 'flex-end',
- marginBottom: -15,
- zIndex: 1
+ alignItems: 'flex-end',
+ marginBottom: -10,
+ zIndex: 1,
+ flexDirection: 'row'
+ },
+ invertedList: {
+ marginRight: 'auto',
+ minWidth: '20%',
+ marginBottom: 40
},
pepoTxCount: {
fontSize: 18,
color: Colors.white,
alignSelf: 'center',
- marginBottom: 8,
+ marginBottom: 5,
textShadowColor: 'rgba(0, 0, 0, 0.65)',
textShadowOffset: {width: 1, height: 1},
textShadowRadius: 1,
@@ -55,6 +61,15 @@ let stylesMap = {
position: 'absolute',
bottom: 0
},
+ listContainer: {
+ // width: width,
+ position: 'absolute',
+ bottom: height * 0.05 + 50,
+ left: 10,
+ zIndex: 9,
+ // alignSelf: 'flex-start',
+ //height: height - 200
+ },
bottomBg: {
backgroundColor: 'rgba(0, 0, 0, 0.6)',
borderTopLeftRadius: 20,
diff --git a/src/components/InviteCode/index.js b/src/components/InviteCode/index.js
index 05cc1c56..4758879e 100644
--- a/src/components/InviteCode/index.js
+++ b/src/components/InviteCode/index.js
@@ -18,6 +18,7 @@ import Utilities from '../../services/Utilities';
import AppConfig from '../../constants/AppConfig';
import { upsertInviteCode } from '../../actions';
import Store from '../../store';
+import CommonStyle from '../../theme/styles/Common';
const mapStateToProps = ({ invite_code }) => ({ invite_code });
@@ -183,7 +184,7 @@ class InviteCodeScreen extends React.Component {
render() {
return (
-
+
diff --git a/src/components/Invites/index.js b/src/components/Invites/index.js
index 29759ae8..b2867f0c 100644
--- a/src/components/Invites/index.js
+++ b/src/components/Invites/index.js
@@ -1,11 +1,10 @@
import React, { Component } from 'react';
import { Text, SafeAreaView } from 'react-native';
-import styles from './styles';
import Colors from '../../theme/styles/Colors';
import BackArrow from '../CommonComponents/BackArrow';
import InvitesList from './InvitesList';
-import CurrentUser from '../../models/CurrentUser';
+import CommonStyle from "../../theme/styles/Common";
class Invites extends Component {
static navigationOptions = (options) => {
@@ -46,7 +45,7 @@ class Invites extends Component {
render() {
return (
-
+
{
TwitterAuthService = imports.default;
});
-const mapStateToProps = ({ login_popover }) => ({
- show: login_popover.show
-});
+const mapStateToProps = ({ login_popover }) => {
+ return {
+ show: login_popover.show,
+ isTwitterConnecting: login_popover.isTwitterConnecting
+ }
+};
const btnPreText = 'Connect with Twitter';
const btnPostText = 'Connecting...';
@@ -32,39 +36,43 @@ class loginPopover extends React.Component {
constructor(props) {
super(props);
this.state = {
- disableLoginBtn: false,
- btnText: btnPreText
+ disableLoginBtn: false
};
- this.isTwitterConnecting = false;
}
componentWillUnmount() {
this.state.disableLoginBtn = false;
- this.state.btnText = btnPreText;
- this.isTwitterConnecting = false;
+
}
componentDidUpdate(prevProps) {
- if (this.props.show && this.props.show !== prevProps.show) {
- this.setState({ disableLoginBtn: false, btnText: btnPreText });
- this.isTwitterConnecting = false;
+ if ( this.props.isTwitterConnecting && this.props.isTwitterConnecting !== prevProps.isTwitterConnecting ) {
+ this.setState({ disableLoginBtn: true });
+ } else if (this.props.show && this.props.show !== prevProps.show) {
+ this.setState({ disableLoginBtn: false });
}
}
onSignUp = () => {
- this.setState({ disableLoginBtn: true, btnText: btnPostText });
- this.isTwitterConnecting = true;
+ this.setState({ disableLoginBtn: true });
TwitterAuthService.signUp();
};
//Use this function if needed to handle hardware back handling for android.
closeModal = () => {
- if (!this.isTwitterConnecting) {
+ if (!this.props.isTwitterConnecting) {
Store.dispatch(hideLoginPopover());
}
return true;
};
+ getConnectBtnText = () => {
+ if ( this.props.isTwitterConnecting || this.state.disableLoginBtn) {
+ return btnPostText;
+ }
+ return btnPreText;
+ }
+
render() {
return (
@@ -75,7 +83,6 @@ class loginPopover extends React.Component {
visible={this.props.show}
coverScreen={false}
hasBackdrop={true}
- onRequestClose={() => console.log('onRequestClose')}
>
@@ -132,7 +139,7 @@ class loginPopover extends React.Component {
this.state.disableLoginBtn ? Theme.Button.disabled : null
]}
TextStyles={[Theme.Button.btnPinkText, { fontSize: 18 }]}
- text={this.state.btnText}
+ text={this.getConnectBtnText()}
onPress={this.onSignUp}
source={twitterBird}
imgDimension={{ width: 28, height: 22.5, marginRight: 8 }}
@@ -140,15 +147,14 @@ class loginPopover extends React.Component {
/>
- By signing up, you confirm that you agree to
- our
+ By signing up you confirm that you agree to our
{
this.closeModal();
InAppBrowser.openBrowser(
`${WEB_ROOT}/terms`
);
})}>Terms of use
- and have read and agree to our
+ and
{
this.closeModal();
InAppBrowser.openBrowser(
@@ -170,11 +176,21 @@ class loginPopover extends React.Component {
export const LoginPopover = connect(mapStateToProps)(loginPopover);
export const LoginPopoverActions = {
+ _track: () => {
+ let analyticsAction = AppConfig.routesAnalyticsMap.TwitterLogin;
+ firebase.analytics().setCurrentScreen(analyticsAction, analyticsAction);
+ },
show: () => {
Store.dispatch(showLoginPopover());
- let analyticsAction = AppConfig.routesAnalyticsMap.TwitterLogin;
- console.log('firebase.analytics().setCurrentScreen() ::', analyticsAction);
- firebase.analytics().setCurrentScreen(analyticsAction, analyticsAction);
+ LoginPopoverActions._track();
+ },
+ showConnecting: () => {
+ let loginPopoverProps = ReduxGetter.getLoginPopOverProps();
+ if ( !loginPopoverProps || !loginPopoverProps.show ) {
+ //Track.
+ LoginPopoverActions._track();
+ }
+ Store.dispatch(showConnectingLoginPopover());
},
hide: () => {
Store.dispatch(hideLoginPopover());
diff --git a/src/components/Notification/NotificationItem.js b/src/components/Notification/NotificationItem.js
index 8a1bef4e..abeba325 100644
--- a/src/components/Notification/NotificationItem.js
+++ b/src/components/Notification/NotificationItem.js
@@ -125,7 +125,7 @@ class NotificationItem extends Component {
};
notificationInfo = () => {
- if (this.props.kind == AppConfig.notificationConstants.videoAddKind) {
+ if (this.shouldShowVideo()) {
return this.showVideoComponent();
}
};
@@ -183,8 +183,10 @@ class NotificationItem extends Component {
let includesObj = this.props.heading && this.props.heading["includes"] || {} ,
userObj ;
for(let key in includesObj ){
- userObj = includesObj[key] || null;
- break ;
+ if ( includesObj[key] && includesObj[key].kind === 'users'){
+ userObj = includesObj[key] || null;
+ break;
+ }
}
if(userObj){
return this.includesTextNavigate(userObj))}>
@@ -195,7 +197,7 @@ class NotificationItem extends Component {
}else {
return(
- ;
+
)
@@ -204,10 +206,23 @@ class NotificationItem extends Component {
}
}
+ shouldShowVideo = () => {
+ let videoKinds = [
+ AppConfig.notificationConstants.videoAddKind,
+ AppConfig.notificationConstants.userMention,
+ AppConfig.notificationConstants.replyUserMention,
+ AppConfig.notificationConstants.replySenderWithAmount,
+ AppConfig.notificationConstants.replySenderWithoutAmount,
+ AppConfig.notificationConstants.replyReceiverWithAmount,
+ AppConfig.notificationConstants.replyReceiverWithoutAmount
+ ]
+ return videoKinds.includes(this.props.kind);
+ }
+
render() {
let headerWidth = '92%',
notificationInfoWidth = '0%';
- if (this.props.kind === AppConfig.notificationConstants.videoAddKind) {
+ if (this.shouldShowVideo()) {
headerWidth = '72%';
notificationInfoWidth = '20%';
}
@@ -220,7 +235,7 @@ class NotificationItem extends Component {
{this.getActivityIcon()}
-
+
{this.getHeading()}
@@ -233,7 +248,7 @@ class NotificationItem extends Component {
{this.showIfFailed()}
- {this.props.kind === AppConfig.notificationConstants.videoAddKind ?
+ { this.shouldShowVideo() ?
{this.notificationInfo()}
diff --git a/src/components/Notification/index.js b/src/components/Notification/index.js
index e6d8a27c..0d9f7c47 100644
--- a/src/components/Notification/index.js
+++ b/src/components/Notification/index.js
@@ -18,6 +18,9 @@ import {PushNotificationMethods} from '../../services/PushNotificationManager'
import AndroidOpenSettings from "react-native-android-open-settings";
import LinearGradient from "react-native-linear-gradient";
import Theme from "../../theme/styles";
+
+import CommonStyle from "../../theme/styles/Common";
+
const mapStateToProps = (state) => {
return {
userId: CurrentUser.getUserId(),
@@ -197,7 +200,7 @@ class NotificationScreen extends Component {
render() {
return (
this.props.userId && (
-
+
{
this.listRef = ref;
diff --git a/src/components/Home/TransactionPepoButton.js b/src/components/PepoTransactionButton/Base.js
similarity index 76%
rename from src/components/Home/TransactionPepoButton.js
rename to src/components/PepoTransactionButton/Base.js
index c7107575..8df4cff6 100644
--- a/src/components/Home/TransactionPepoButton.js
+++ b/src/components/PepoTransactionButton/Base.js
@@ -3,9 +3,7 @@ import { TouchableWithoutFeedback, View } from 'react-native';
import { OstWalletSdk } from '@ostdotcom/ost-wallet-sdk-react-native';
import Toast from '../../theme/components/NotificationToast';
import deepGet from 'lodash/get';
-import clone from 'lodash/clone';
-import { connect } from 'react-redux';
-import { withNavigation } from 'react-navigation';
+import assignIn from "lodash/assignIn";
import CurrentUser from '../../models/CurrentUser';
import PepoButton from './PepoButton';
@@ -13,7 +11,7 @@ import appConfig from '../../constants/AppConfig';
import PepoApi from '../../services/PepoApi';
import pricer from '../../services/Pricer';
import Store from '../../store';
-import { updateExecuteTransactionStatus, updateBalance, upsertVideoStatEntities } from '../../actions';
+import { updateExecuteTransactionStatus, updateBalance } from '../../actions';
import ExecuteTransactionWorkflow from '../../services/OstWalletCallbacks/ExecuteTransactionWorkFlow';
import reduxGetter from '../../services/ReduxGetters';
import { ostErrors } from '../../services/OstErrors';
@@ -24,17 +22,8 @@ import PixelCall from '../../services/PixelCall';
import {ON_USER_CANCLLED_ERROR_MSG, ensureDeivceAndSession} from '../../helpers/TransactionHelper';
import {VideoPlayPauseEmitter} from "../../helpers/Emitters";
-const mapStateToProps = (state, ownProps) => ({
- balance: state.balance,
- disabled: state.executeTransactionDisabledStatus,
- isVideoUserActivated: utilities.isUserActivated(reduxGetter.getUserActivationStatus(ownProps.userId)),
- supporters: reduxGetter.getVideoSupporters(ownProps.videoId),
- isSupporting: reduxGetter.isVideoSupported(ownProps.videoId),
- totalBt: reduxGetter.getVideoBt(ownProps.videoId, state),
- isCurrentUserActivated: CurrentUser.isUserActivated()
-});
-
-class TransactionPepoButton extends PureComponent {
+
+class Base extends PureComponent {
constructor(props) {
super(props);
this.localSupported = this.props.isSupporting;
@@ -42,7 +31,7 @@ class TransactionPepoButton extends PureComponent {
isDisabled = () => {
return (
- this.props.userId == CurrentUser.getUserId() || !this.isBalance() || !this.props.isCurrentUserActivated || this.props.disabled || !this.props.isVideoUserActivated
+ this.props.userId == CurrentUser.getUserId() || !this.isBalance() || !this.props.isCurrentUserActivated || this.props.disabled || !this.props.isEntityUserActivated
);
};
@@ -119,12 +108,7 @@ class TransactionPepoButton extends PureComponent {
}
getSdkMetaProperties() {
- const metaProperties = clone(appConfig.metaProperties);
- if (this.props.videoId) {
- metaProperties['name'] = 'video';
- metaProperties['details'] = `vi_${this.props.videoId}`;
- }
- return metaProperties;
+ throw "Overwrite";
}
onRequestAcknowledge(ostWorkflowContext, ostWorkflowEntity) {
@@ -132,18 +116,14 @@ class TransactionPepoButton extends PureComponent {
this.dropPixel();
}
+ getDropPixel(){
+ console.log("getDropPixel is mandatory to be implemented in Transaction button");
+ return {};
+ }
+
dropPixel() {
- let pixelParams = {
- e_entity: 'video',
- e_action: 'contribution',
- e_data_json: {
- video_id: this.props.videoId,
- profile_user_id: this.props.userId,
- amount: this.btAmount
- },
- p_type: 'feed'
- };
- PixelCall(pixelParams);
+
+ PixelCall(this.getDropPixel());
}
onFlowInterrupt(ostWorkflowContext, error) {
@@ -178,10 +158,7 @@ class TransactionPepoButton extends PureComponent {
getSendTransactionPlatformData(ostWorkflowEntity) {
return {
ost_transaction: deepGet(ostWorkflowEntity, 'entity'),
- ost_transaction_uuid: deepGet(ostWorkflowEntity, 'entity.id'),
- meta: {
- vi: this.props.videoId
- }
+ ost_transaction_uuid: deepGet(ostWorkflowEntity, 'entity.id')
};
}
@@ -199,21 +176,11 @@ class TransactionPepoButton extends PureComponent {
Store.dispatch(updateBalance(balance));
}
- let videoStats = reduxGetter.getVideoStats(this.props.videoId),
- updateVideoStats = false;
- if (totalBt && totalBt > 0) {
- videoStats['total_amount_raised_in_wei'] = Pricer.getToDecimal(totalBt);
- updateVideoStats = true;
- }
-
- if (supporters && !this.props.isSupporting) {
- videoStats['total_contributed_by'] = supporters;
- updateVideoStats = true;
- }
+ this.reduxEntityUpdate( totalBt, supporters );
+ }
- if (updateVideoStats) {
- Store.dispatch(upsertVideoStatEntities(utilities._getEntityFromObj(videoStats)));
- }
+ reduxEntityUpdate( totalBt, supporters ){
+ throw "OverWrite";
}
onPressOut = (btAmount, totalBt) => {
@@ -265,7 +232,7 @@ class TransactionPepoButton extends PureComponent {
- {/*+ {this.props.count}*/}
);
@@ -73,7 +69,6 @@ export default class ClapBubble extends React.Component {
const styles = StyleSheet.create({
clapbubble: {
elevation: 4,
- // backgroundColor:Colors.primary ,
height: 40,
width: 40,
borderRadius: 20,
diff --git a/src/components/Home/PepoButton/ClapButton.js b/src/components/PepoTransactionButton/PepoButton/ClapButton.js
similarity index 98%
rename from src/components/Home/PepoButton/ClapButton.js
rename to src/components/PepoTransactionButton/PepoButton/ClapButton.js
index 2c0b7710..b90c263c 100644
--- a/src/components/Home/PepoButton/ClapButton.js
+++ b/src/components/PepoTransactionButton/PepoButton/ClapButton.js
@@ -1,5 +1,5 @@
import * as React from 'react';
-import { Animated, Easing, View, Vibration } from 'react-native';
+import { Animated, Easing, View } from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import pepo_tx_img from '../../../assets/pepo_anim_btn.png';
diff --git a/src/components/Home/PepoButton/index.js b/src/components/PepoTransactionButton/PepoButton/index.js
similarity index 98%
rename from src/components/Home/PepoButton/index.js
rename to src/components/PepoTransactionButton/PepoButton/index.js
index 5c76758a..a16ce52d 100644
--- a/src/components/Home/PepoButton/index.js
+++ b/src/components/PepoTransactionButton/PepoButton/index.js
@@ -6,7 +6,7 @@ import {
TouchableWithoutFeedback
} from "react-native";
import ClapBubble from "./ClapBubble";
-import inlineStyles from '../styles'
+import inlineStyles from '../styles';
import ClapButton from "./ClapButton";
import appConfig from "../../../constants/AppConfig";
import Pricer from "../../../services/Pricer";
diff --git a/src/components/PepoTransactionButton/PepoTxBtn.js b/src/components/PepoTransactionButton/PepoTxBtn.js
new file mode 100644
index 00000000..47cf7bcf
--- /dev/null
+++ b/src/components/PepoTransactionButton/PepoTxBtn.js
@@ -0,0 +1,70 @@
+import { connect } from 'react-redux';
+import clone from 'lodash/clone';
+import assignIn from 'lodash/assignIn';
+
+import CurrentUser from '../../models/CurrentUser';
+import appConfig from '../../constants/AppConfig';
+import Store from '../../store';
+import { upsertVideoStatEntities } from '../../actions';
+import reduxGetter from '../../services/ReduxGetters';
+import Pricer from '../../services/Pricer';
+import utilities from '../../services/Utilities';
+import { withNavigation } from 'react-navigation';
+
+import Base from "./Base";
+
+const mapStateToProps = (state, ownProps) => ({
+ balance: state.balance,
+ disabled: state.executeTransactionDisabledStatus,
+ isEntityUserActivated: utilities.isUserActivated(reduxGetter.getUserActivationStatus(ownProps.userId)),
+ supporters: reduxGetter.getVideoSupporters(ownProps.entityId),
+ isSupporting: reduxGetter.isVideoSupported(ownProps.entityId),
+ totalBt: reduxGetter.getVideoBt(ownProps.entityId, state),
+ isCurrentUserActivated: CurrentUser.isUserActivated()
+ });
+
+class PepoTxBtn extends Base {
+
+ constructor(props){
+ super(props);
+ }
+
+ getSdkMetaProperties() {
+ const metaProperties = clone(appConfig.metaProperties);
+ metaProperties['name'] = 'video';
+ metaProperties['details'] = `vi_${this.props.entityId}`;
+ return metaProperties;
+ }
+
+ getDropPixel(){
+ let specificData = this.props.getPixelDropData(),
+ defaultData = {
+ e_entity: 'video',
+ e_action: 'contribution',
+ video_id: this.props.entityId,
+ amount: this.btAmount
+ };
+ return assignIn({}, specificData, defaultData);
+ }
+
+ reduxEntityUpdate( totalBt, supporters ){
+ let videoStats = reduxGetter.getVideoStats(this.props.entityId),
+ updateVideoStats = false;
+ if (totalBt && totalBt > 0) {
+ videoStats['total_amount_raised_in_wei'] = Pricer.getToDecimal(totalBt);
+ updateVideoStats = true;
+ }
+
+ if (supporters && !this.props.isSupporting) {
+ videoStats['total_contributed_by'] = supporters;
+ updateVideoStats = true;
+ }
+
+ if (updateVideoStats) {
+ Store.dispatch(upsertVideoStatEntities(utilities._getEntityFromObj(videoStats)));
+ }
+ }
+
+}
+
+export default connect(mapStateToProps)(withNavigation(PepoTxBtn));
diff --git a/src/components/PepoTransactionButton/ReplyPepoTxBtn.js b/src/components/PepoTransactionButton/ReplyPepoTxBtn.js
new file mode 100644
index 00000000..ba5087c3
--- /dev/null
+++ b/src/components/PepoTransactionButton/ReplyPepoTxBtn.js
@@ -0,0 +1,70 @@
+import { connect } from 'react-redux';
+import clone from 'lodash/clone';
+import CurrentUser from '../../models/CurrentUser';
+import appConfig from '../../constants/AppConfig';
+import Store from '../../store';
+import { upsertReplyDetailEntities } from '../../actions';
+import reduxGetter from '../../services/ReduxGetters';
+import Pricer from '../../services/Pricer';
+import utilities from '../../services/Utilities';
+import { withNavigation } from 'react-navigation';
+
+import Base from "./Base";
+import assignIn from "lodash/assignIn";
+
+const mapStateToProps = (state, ownProps) => ({
+ balance: state.balance,
+ disabled: state.executeTransactionDisabledStatus,
+ isEntityUserActivated: utilities.isUserActivated(reduxGetter.getUserActivationStatus(ownProps.userId)),
+ isCurrentUserActivated: CurrentUser.isUserActivated() ,
+ supporters: reduxGetter.getReplySupporters(ownProps.entityId),
+ isSupporting: reduxGetter.isReplySupported(ownProps.entityId) ,
+ totalBt: reduxGetter.getReplyBt(ownProps.entityId),
+ });
+
+class ReplyPepoTxBtn extends Base {
+
+ constructor(props){
+ super(props);
+ }
+
+ getSdkMetaProperties() {
+ const metaProperties = clone(appConfig.metaProperties);
+ metaProperties['name'] = 'pepo_on_reply';
+ metaProperties['details'] = `rdi_${this.props.entityId}`;
+ return metaProperties;
+ }
+
+ getDropPixel(){
+ let specificData = this.props.getPixelDropData(),
+ defaultData = {
+ e_entity: 'reply',
+ e_action: 'contribution',
+ reply_detail_id: this.props.entityId,
+ amount: this.btAmount
+ };
+ return assignIn({}, specificData, defaultData);
+ }
+
+ reduxEntityUpdate( totalBt, supporters ){
+ let replyDetails = reduxGetter.getReplyEntity(this.props.entityId),
+ updateEntity = false
+ ;
+ if (totalBt && totalBt > 0) {
+ replyDetails['total_amount_raised_in_wei'] = Pricer.getToDecimal(totalBt);
+ updateEntity = true;
+ }
+
+ if (supporters && !this.props.isSupporting) {
+ replyDetails['total_contributed_by'] = supporters;
+ updateEntity = true;
+ }
+
+ if (updateEntity) {
+ Store.dispatch(upsertReplyDetailEntities(utilities._getEntityFromObj(replyDetails)));
+ }
+ }
+
+}
+
+export default connect(mapStateToProps)( withNavigation( ReplyPepoTxBtn ));
diff --git a/src/components/PepoTransactionButton/styles.js b/src/components/PepoTransactionButton/styles.js
new file mode 100644
index 00000000..b9f7185b
--- /dev/null
+++ b/src/components/PepoTransactionButton/styles.js
@@ -0,0 +1,19 @@
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../theme/styles/Colors';
+
+let stylesMap = {
+ pepoTxCount: {
+ fontSize: 18,
+ color: Colors.white,
+ alignSelf: 'center',
+ marginBottom: 5,
+ textShadowColor: 'rgba(0, 0, 0, 0.65)',
+ textShadowOffset: {width: 1, height: 1},
+ textShadowRadius: 1,
+ fontFamily: 'AvenirNext-DemiBold'
+ }
+}
+
+;
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/PreviewRecordedVideo/index.js b/src/components/PreviewRecordedVideo/index.js
index cfed2368..3fedfaac 100644
--- a/src/components/PreviewRecordedVideo/index.js
+++ b/src/components/PreviewRecordedVideo/index.js
@@ -99,10 +99,10 @@ class PreviewRecordedVideo extends Component {
do_discard: true
})
);
+ this.props.saveVideoPrimaryInfo();
this.props.goToRecordScreen();
} else if (buttonIndex == ACTION_SHEET_DESCTRUCTIVE_INDEX) {
this.props.navigation.goBack(null);
- // videoUploaderComponent.emit('hide');
Store.dispatch(
upsertRecordedVideo({
do_discard: true
diff --git a/src/components/Profile/ProfileEditScreen.js b/src/components/Profile/ProfileEditScreen.js
index 410e6979..e5e9fe5d 100644
--- a/src/components/Profile/ProfileEditScreen.js
+++ b/src/components/Profile/ProfileEditScreen.js
@@ -353,204 +353,208 @@ class ProfileEdit extends React.PureComponent {
render() {
return (
-
-
- {this.getImageSrc()}
-
-
-
-
-
-
-
- Name
- this.setState({ name, error: null, name_error: null })}
- fieldName="name"
- textContentType="none"
- style={[Theme.TextInput.textInputStyle]}
- placeholder="Name"
- returnKeyType="next"
- returnKeyLabel="Next"
- placeholderTextColor="#ababab"
- blurOnSubmit={false}
- isFocus={this.state.current_formField == this.tabIndex.name}
- onFocus={() => {
- this.setState({
- current_formField: this.tabIndex.name
- });
+
+ {
- this.onSubmitEditing(this.tabIndex.name);
- }}
- value={this.state.name}
- errorMsg={this.state.name_error}
- serverErrors={this.state.server_errors}
- />
-
- Username
- this.setState({ user_name, error: null, user_name_error: null })}
- fieldName="user_name"
- textContentType="none"
- style={[Theme.TextInput.textInputStyle]}
- placeholder="User Name"
- returnKeyType="next"
- returnKeyLabel="Next"
- placeholderTextColor="#ababab"
- blurOnSubmit={false}
- onSubmitEditing={() => {
- Keyboard.dismiss();
- this.onSubmitEditing(this.tabIndex.username);
- }}
- isFocus={this.state.current_formField == this.tabIndex.username}
- onFocus={() => {
- this.setState({
- current_formField: this.tabIndex.username
- });
- }}
- value={this.state.user_name}
- errorMsg={this.state.user_name_error}
- serverErrors={this.state.server_errors}
- />
-
- Email Address
-
- this.onEmailFocus())}
- style={[inlineStyles.clickWrapper,{height : EMAIL_HEIGHT}]}
- >
-
-
+ showsVerticalScrollIndicator={false}
+ >
+
+ {this.getImageSrc()}
+
+
+
+
+
+
+
+ Name
this.setState({ name, error: null, name_error: null })}
+ fieldName="name"
textContentType="none"
- style={[
- Theme.TextInput.textInputStyle,
- !this.state.isVerifiedEmail
- ? { borderColor: Colors.wildWatermelon2 }
- : { backgroundColor: Colors.whiteSmoke }
- ]}
- placeholder="Email"
+ style={[Theme.TextInput.textInputStyle]}
+ placeholder="Name"
returnKeyType="next"
returnKeyLabel="Next"
placeholderTextColor="#ababab"
blurOnSubmit={false}
- value={this.state.emailAddress}
- serverErrors={this.state.server_errors}
- autoCapitalize={'none'}
- isFocus={false}
- />
- {
+ this.setState({
+ current_formField: this.tabIndex.name
+ });
}}
+ onSubmitEditing={() => {
+ this.onSubmitEditing(this.tabIndex.name);
+ }}
+ value={this.state.name}
+ errorMsg={this.state.name_error}
+ serverErrors={this.state.server_errors}
/>
-
- Bio
-
- this.onBioFocus())}>
-
+ Username
this.setState({ user_name, error: null, user_name_error: null })}
+ fieldName="user_name"
textContentType="none"
- style={[Theme.TextInput.textInputStyle, { height: BIO_HEIGHT, paddingVertical: 15 }]}
- placeholder="Bio"
+ style={[Theme.TextInput.textInputStyle]}
+ placeholder="User Name"
returnKeyType="next"
returnKeyLabel="Next"
placeholderTextColor="#ababab"
blurOnSubmit={false}
- maxLength={100}
- value={this.state.bio}
+ onSubmitEditing={() => {
+ Keyboard.dismiss();
+ this.onSubmitEditing(this.tabIndex.username);
+ }}
+ isFocus={this.state.current_formField == this.tabIndex.username}
+ onFocus={() => {
+ this.setState({
+ current_formField: this.tabIndex.username
+ });
+ }}
+ value={this.state.user_name}
+ errorMsg={this.state.user_name_error}
serverErrors={this.state.server_errors}
- isFocus={false}
- //onFocus={multipleClickHandler(() => this.onBioFocus())}
/>
-
-
-
- Link
- this.setState({ link, error: null, link_error: null })}
- fieldName="link"
- textContentType="none"
- style={[Theme.TextInput.textInputStyle]}
- placeholder="Link"
- returnKeyType="done"
- returnKeyLabel="Done"
- placeholderTextColor="#ababab"
- blurOnSubmit={false}
- onSubmitEditing={() => {
- Keyboard.dismiss();
- }}
- value={this.state.link}
- serverErrors={this.state.server_errors}
- />
-
-
- {this.state.btnText}
-
-
-
- {this.state.general_error}
- {
- this.setState({
- showGalleryAccessModal: false
- });
- }}
- modalVisibility={this.state.showGalleryAccessModal}
- headerText="Library"
- accessText="Enable Library Access"
- accessTextDesc="Please allow access to photo library to select your profile picture"
- imageSrc={GalleryIcon}
- imageSrcStyle={{ height: 40, width: 40 }}
- />
- {
- this.setState({
- showCameraAccessModal: false
- });
- }}
- modalVisibility={this.state.showCameraAccessModal}
- headerText="Camera"
- accessText="Enable Camera Access"
- accessTextDesc="Allow access to your camera and microphone to take video "
- imageSrc={CameraIcon}
- />
-
+ Email Address
+
+ this.onEmailFocus())}
+ style={[inlineStyles.clickWrapper,{height : EMAIL_HEIGHT}]}
+ >
+
+
+
+
+
+
+ Bio
+
+ this.onBioFocus())}>
+
+ this.onBioFocus())}
+ />
+
+
+
+ Link
+ this.setState({ link, error: null, link_error: null })}
+ fieldName="link"
+ textContentType="none"
+ style={[Theme.TextInput.textInputStyle]}
+ placeholder="Link"
+ returnKeyType="done"
+ returnKeyLabel="Done"
+ placeholderTextColor="#ababab"
+ blurOnSubmit={false}
+ onSubmitEditing={() => {
+ Keyboard.dismiss();
+ }}
+ value={this.state.link}
+ serverErrors={this.state.server_errors}
+ />
+
+
+
+ {this.state.btnText}
+
+
+
+ {this.state.general_error}
+ {
+ this.setState({
+ showGalleryAccessModal: false
+ });
+ }}
+ modalVisibility={this.state.showGalleryAccessModal}
+ headerText="Library"
+ accessText="Enable Library Access"
+ accessTextDesc="Please allow access to photo library to select your profile picture"
+ imageSrc={GalleryIcon}
+ imageSrcStyle={{ height: 40, width: 40 }}
+ />
+ {
+ this.setState({
+ showCameraAccessModal: false
+ });
+ }}
+ modalVisibility={this.state.showCameraAccessModal}
+ headerText="Camera"
+ accessText="Enable Camera Access"
+ accessTextDesc="Allow access to your camera and microphone to take video "
+ imageSrc={CameraIcon}
+ />
+
+
);
}
}
diff --git a/src/components/Redemption/index.js b/src/components/Redemption/index.js
index 1bc9e6f4..8c9bb259 100644
--- a/src/components/Redemption/index.js
+++ b/src/components/Redemption/index.js
@@ -50,6 +50,7 @@ import clone from 'lodash/clone';
import { ostSdkErrors, WORKFLOW_CANCELLED_MSG } from '../../services/OstSdkErrors';
import Colors from '../../theme/styles/Colors';
import InAppBrowser from '../../services/InAppBrowser';
+import CommonStyle from '../../theme/styles/Common';
const bottomSpace = getBottomSpace([true]),
extraPadding = 10,
@@ -658,7 +659,7 @@ class Redemption extends PureComponent{
render(){
return (
-
+
diff --git a/src/components/ReferAndEarn/index.js b/src/components/ReferAndEarn/index.js
index f4e4a10e..182b57de 100644
--- a/src/components/ReferAndEarn/index.js
+++ b/src/components/ReferAndEarn/index.js
@@ -14,6 +14,7 @@ import BackArrow from '../CommonComponents/BackArrow';
import { ScrollView } from 'react-native-gesture-handler';
import PepoApi from '../../services/PepoApi';
import { WEB_ROOT } from '../../constants/index';
+import CommonStyle from "../../theme/styles/Common";
class ReferAndEarn extends Component {
static navigationOptions = (options) => {
@@ -116,7 +117,7 @@ class ReferAndEarn extends Component {
render() {
return (
-
+
{this.state.pendingInvites != 0 ? (
@@ -126,7 +127,7 @@ class ReferAndEarn extends Component {
style={[styles.heading, { textAlign: 'center' }]}
>{`You have ${this.state.inviteText} invites remaining`}
- Pepo is currently invite only. Invite your friends and you will get 5% commission on their earnings.
+ Invite your friends and you will get 5% commission on their earnings.
diff --git a/src/components/ReplyCollection/index.js b/src/components/ReplyCollection/index.js
new file mode 100644
index 00000000..59ed5e00
--- /dev/null
+++ b/src/components/ReplyCollection/index.js
@@ -0,0 +1,262 @@
+import React, { PureComponent } from 'react';
+import {
+ FlatList,
+ ActivityIndicator,
+ Dimensions,
+ View
+} from "react-native";
+import { withNavigation} from "react-navigation";
+import deepGet from "lodash/get";
+import LinearGradient from "react-native-linear-gradient";
+
+import Pagination from "../../services/Pagination";
+import DeleteVideo from "../CommonComponents/DeleteVideo";
+import inlineStyles from './styles';
+import CurrentUser from '../../models/CurrentUser';
+import DataContract from '../../constants/DataContract';
+import { VideoReplyEmitter } from '../../helpers/Emitters';
+import PepoApi from '../../services/PepoApi';
+import ReplyThumbnail from '../CommonComponents/VideoThumbnail/ReplyThumbnail';
+import ReduxGetters from '../../services/ReduxGetters';
+import entityHelper from '../../helpers/EntityHelper';
+import { fetchVideo } from '../../helpers/helpers';
+
+
+class ReplyCollection extends PureComponent {
+
+ constructor(props){
+ super(props);
+ this.state = {
+ list : [],
+ refreshing : true,
+ loadingNext: false
+ };
+ this.listRef = null;
+ this.numColumns = 2;
+ }
+
+ componentDidMount(){
+ this.initPagination();
+ this.refresh();
+ this.bindEvents();
+ }
+
+ bindEvents(){
+ VideoReplyEmitter.on('videoUploaded', ( payload )=>{
+ this.fetchVideoReply( payload.videoId );
+ })
+ }
+
+ fetchVideoReply = (id)=> {
+ new PepoApi(DataContract.replies.getSingleVideoReplyApi(id))
+ .get()
+ .then((res)=> {
+ let newVideoReply = res.data['result_type'];
+ this.addVideo( newVideoReply );
+ })
+ }
+
+ addVideo = ( item ) => {
+ this.videoPagination.addItems( item );
+ let array = [...this.state.list]; // make a separate copy of the array
+ array.unshift( item );
+ this.setState({list: array});
+ }
+
+ componentWillUnmount() {
+ this.removePaginationListeners();
+ }
+
+ getPagination = () => {
+ return this.videoPagination;
+ };
+
+
+ initPagination() {
+ // First, take care of existing Pagination if exists.
+ this.removePaginationListeners();
+
+ // Now, create a new one.
+ let fetchUrl = this.props.fetchUrl;
+ this.videoPagination = new Pagination(fetchUrl);
+ this.bindPaginationEvents();
+ }
+
+ bindPaginationEvents(){
+ let pagination = this.videoPagination;
+ if ( !pagination ) {
+ return;
+ }
+ let paginationEvent = pagination.event;
+ if ( null === paginationEvent ) {
+ return;
+ }
+
+ paginationEvent.on("onBeforeRefresh" , this.beforeRefresh.bind(this) );
+ paginationEvent.on("onRefresh" , this.onRefresh.bind(this) );
+ paginationEvent.on("onRefreshError" , this.onRefreshError.bind(this));
+ paginationEvent.on("onBeforeNext" , this.beforeNext.bind(this));
+ paginationEvent.on("onNext" , this.onNext.bind(this) );
+ paginationEvent.on("onNextError" , this.onNextError.bind(this));
+ }
+
+ removePaginationListeners(){
+ let pagination = this.videoPagination;
+ if ( !pagination ) {
+ return;
+ }
+ let paginationEvent = pagination.event;
+ if ( null === paginationEvent ) {
+ return;
+ }
+ paginationEvent.removeListener('onBeforeRefresh');
+ paginationEvent.removeListener('onRefresh');
+ paginationEvent.removeListener('onRefreshError');
+ paginationEvent.removeListener('onBeforeNext');
+ paginationEvent.removeListener('onNext');
+ paginationEvent.removeListener('onNextError');
+ }
+
+ beforeRefresh = ( ) => {
+ this.setState({ refreshing : true });
+ };
+
+ onRefresh = ( res ) => {
+ const list = this.getResultList();
+ this.props.onRefresh && this.props.onRefresh( list , res );
+ this.setState({
+ refreshing : false,
+ list : list
+ });
+ };
+
+ onRefreshError = ( error ) => {
+ this.setState({ refreshing : false });
+ };
+
+ beforeNext =() => {
+ this.setState({ loadingNext : true });
+ };
+
+ onNext = ( res ) => {
+ this.setState({
+ loadingNext : false,
+ list : this.getResultList()
+ });
+ }
+
+ onNextError = ( error ) => {
+ this.setState({ loadingNext : false });
+ };
+
+ getNext = () => {
+ this.videoPagination.getNext();
+ };
+
+ refresh = () => {
+ this.videoPagination.refresh();
+ };
+
+ _keyExtractor = (item, index) => {
+ return `id_${item.id}`;
+ }
+
+ _renderItem = ({ item, index }) => {
+ // Render Video cell
+ return this._renderVideoCell({item,index});
+ };
+
+ _renderVideoCell = ({ item, index }) => {
+ return this.renderThumbnailItem(item , index)
+ };
+
+ renderThumbnailItem ( item , index ){
+ if(entityHelper.isVideoReplyEntity( item )){
+ if(entityHelper.isReplyVideoTypeEntity(item)){
+ return this._renderVideoReplyThumbnail( item, index );
+ }
+ }
+ }
+
+ _renderVideoReplyThumbnail( item, index ) {
+ const reply_detail_id = deepGet(item,`payload.${DataContract.replies.replyDetailIdKey}`);
+ return (
+ {ReduxGetters.getCanDeleteReply( reply_detail_id ) &&
+
+ {this.removeVideo(reply_detail_id , index )}} />
+
+ }
+ {this.onVideoClick(index , item)}}/>
+ );
+ }
+
+ isCurrentUser = ( userId ) => {
+ return userId === CurrentUser.getUserId();
+ }
+
+ removeVideo = (id, index) => {
+ const videoId = ReduxGetters.getReplyEntityId(id);
+ videoId && fetchVideo(videoId);
+ if (index > -1) {
+ this.videoPagination.deleteItem(id , "payload.reply_detail_id");
+ let array = [...this.state.list]; // make a separate copy of the array
+ array.splice(index, 1);
+ this.setState({list: array});
+ }
+ }
+
+ onVideoClick = ( index , item) => {
+ const clonedInstance = this.videoPagination.fetchServices.cloneInstance();
+ this.props.navigation.push("FullScreenReplyCollection", {
+ "fetchServices" : clonedInstance,
+ "currentIndex": index,
+ "baseUrl": this.props.fetchUrl
+ });
+ }
+
+ renderFooter = () => {
+ if (!this.state.loadingNext) return null;
+ return ;
+ };
+
+ getResultList(){
+ return this.videoPagination.getResults();
+ }
+
+ scrollToTop(){
+ this.listRef.scrollToOffset({offset: 0});
+ }
+
+ setListRef = (listRef) => {
+ this.listRef = listRef;
+ };
+
+ render(){
+ return (
+
+ );
+ }
+
+}
+
+export default withNavigation( ReplyCollection );
diff --git a/src/components/ReplyCollection/styles.js b/src/components/ReplyCollection/styles.js
new file mode 100644
index 00000000..9c094b87
--- /dev/null
+++ b/src/components/ReplyCollection/styles.js
@@ -0,0 +1,12 @@
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+
+let stylesMap = {
+ deleteButton: {
+ height: 24,
+ width: 40,
+ justifyContent: 'center',
+ alignItems: 'center'
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/SayThanks/index.js b/src/components/SayThanks/index.js
index fa63803a..4bcf31ec 100644
--- a/src/components/SayThanks/index.js
+++ b/src/components/SayThanks/index.js
@@ -5,8 +5,7 @@ import {
Keyboard,
BackHandler,
ActivityIndicator,
- TouchableWithoutFeedback,
- Switch
+ TouchableWithoutFeedback
} from 'react-native';
import { connect } from 'react-redux';
import { getBottomSpace, isIphoneX } from 'react-native-iphone-x-helper';
@@ -20,6 +19,7 @@ import Theme from '../../theme/styles';
import Colors from '../../theme/styles/Colors';
import TwitterAuth from '../../services/ExternalLogin/TwitterAuth';
import Toast from '../../theme/components/NotificationToast';
+import CommonStyle from '../../theme/styles/Common';
const bottomSpace = getBottomSpace([true]),
extraPadding = 10,
@@ -156,7 +156,6 @@ class SayThanks extends Component {
thanksMessage: this.tweeterHandle ? `@${this.tweeterHandle} ${this.state.thanksMessage}`: this.state.thanksMessage
});
} else {
- //TODO: show error
if (resp.err.msg) {
Toast.show({ text: resp.err.msg, icon: 'error' });
}
@@ -197,7 +196,7 @@ class SayThanks extends Component {
}
}}
>
-
+
{this.state.gettingTweetInfo && (
diff --git a/src/components/Search/index.js b/src/components/Search/index.js
index 525b7a7a..cd4c25a9 100644
--- a/src/components/Search/index.js
+++ b/src/components/Search/index.js
@@ -49,7 +49,7 @@ const TabMap = {
}
},
extraParams: {
- showBalanceFlier: true
+ showBalanceFlyer: true
},
supported: true
},
@@ -97,7 +97,7 @@ const TabMap = {
"isEmpty": true
},
extraParams: {
- showBalanceFlier: true
+ showBalanceFlyer: true
},
renderNoResults : (noResultsData) => {
const oThis = TabMap.videos;
@@ -136,10 +136,9 @@ class SearchScreen extends PureComponent {
return prevProps.userId !== this.props.userId;
}
-
componentDidUpdate(prevProps){
if(this.isUserUpdated(prevProps)) {
- this.initReferences();
+ //this.initReferences();
}
}
@@ -164,8 +163,9 @@ class SearchScreen extends PureComponent {
let tabData = TabsArray[ tabIndx];
let newTabUrl = this.getUrlForTab( tabData );
let tabFlatList = this.getTabFlatList( tabIndx );
+ if(!tabFlatList) return;
tabFlatList.forcedRefresh(newTabUrl);
- tabFlatList.scrollToTop();
+ tabFlatList && tabFlatList.scrollToTop();
};
initReferences = () =>{
@@ -201,6 +201,7 @@ class SearchScreen extends PureComponent {
if ( !currentTabUrl || currentTabUrl !== newTabUrl ) {
// Force refresh
let tabFlatList = this.getTabFlatList( tabIndx );
+ if(!tabFlatList) return;
tabFlatList.scrollToTop();
tabFlatList.forcedRefresh(newTabUrl);
} else {
@@ -319,12 +320,13 @@ class SearchScreen extends PureComponent {
if (this.isUserLoggedIn()){
return this.renderLoggedInView();
} else {
+ this.initReferences();
return this.renderLoggedOutView()
}
}
renderLoggedOutView = () => {
- return
+ return
};
renderTabBar = () => {
diff --git a/src/components/Search/styles.js b/src/components/Search/styles.js
index 8b3670ee..27f3c949 100644
--- a/src/components/Search/styles.js
+++ b/src/components/Search/styles.js
@@ -5,6 +5,7 @@ import { Platform } from 'react-native';
let stylesMap = {
container: {
paddingBottom: 0,
+ backgroundColor: Colors.white,
paddingTop: Platform.OS === 'ios' ? 30 : 20,
flex: 1
},
diff --git a/src/components/StoreProducts/index.js b/src/components/StoreProducts/index.js
index 536a60e4..e1e3bdb1 100644
--- a/src/components/StoreProducts/index.js
+++ b/src/components/StoreProducts/index.js
@@ -26,6 +26,7 @@ import toastError from '../../assets/toast_error.png';
import pepoIcon from '../../assets/self-amount-pepo-icon.png';
import mailIcon from '../../assets/mail-filled.png';
import { ostErrors } from '../../services/OstErrors';
+import CommonStyle from '../../theme/styles/Common';
class StoreProductsScreen extends PureComponent{
@@ -279,7 +280,7 @@ class StoreProductsScreen extends PureComponent{
render(){
return (
-
+
{/**/}
diff --git a/src/components/SupportersList/SupportersListComponent.js b/src/components/SupportersList/SupportersListComponent.js
index d083fa5f..9dd6d46c 100644
--- a/src/components/SupportersList/SupportersListComponent.js
+++ b/src/components/SupportersList/SupportersListComponent.js
@@ -5,6 +5,7 @@ import User from '../Users/User';
import Pricer from '../../services/Pricer';
import reduxGetters from '../../services/ReduxGetters';
import EmptyList from '../EmptyFriendsList/EmptyList';
+import CommonStyle from "../../theme/styles/Common";
class SupportersList extends PureComponent {
constructor(props) {
@@ -27,7 +28,7 @@ class SupportersList extends PureComponent {
render() {
return (
-
+
+
-
+
diff --git a/src/components/UserVideoHistory/UserVideoHistoryRow.js b/src/components/UserVideoHistory/UserVideoHistoryRow.js
index 9a3b88a1..153a41ec 100644
--- a/src/components/UserVideoHistory/UserVideoHistoryRow.js
+++ b/src/components/UserVideoHistory/UserVideoHistoryRow.js
@@ -1,111 +1,124 @@
import React, { PureComponent } from 'react';
-import { View, TouchableOpacity, Image } from 'react-native';
+import { View, Dimensions } from 'react-native';
import { withNavigation } from 'react-navigation';
-import VideoWrapper from '../Home/VideoWrapper';
-import ShareIcon from "../CommonComponents/ShareIcon";
+import FanVideo from '../VideoWrapper/FanVideo';
import ReportVideo from "../CommonComponents/ReportVideo";
import PepoApi from '../../services/PepoApi';
-import TransactionPepoButton from '../Home/TransactionPepoButton';
-import CurrentUser from '../../models/CurrentUser';
-
-import BottomStatus from '../Home/BottomStatus';
-import VideoAmountStat from '../CommonComponents/VideoAmoutStat';
-import ShareVideo from '../../services/shareVideo';
+import VideoBottomStatus from '../BottomStatus/VideoBottomStatus';
import inlineStyles from './styles';
-import utilities from '../../services/Utilities';
-import OptionsIcon from '../../assets/options_self_video.png';
+import Utilities from '../../services/Utilities';
+import ReplyIcon from '../CommonComponents/ReplyIcon';
+import PepoTxBtn from '../PepoTransactionButton/PepoTxBtn';
+import VideoSupporterStat from '../CommonComponents/VideoSupporterStat/VideoSupporterStat';
+import DataContract from '../../constants/DataContract';
+import BottomReplyBar from '../CommonComponents/BottomReplyBar';
+import CommonStyle from "../../theme/styles/Common";
+import assignIn from 'lodash/assignIn';
+import InvertedReplyList from "../CommonComponents/InvertedReplyThumbnailList";
+import AppConfig from "../../constants/AppConfig";
+import BubbleList from '../CommonComponents/BubbleList';
+import VideoShareIcon from '../CommonComponents/ShareIcon/VideoShare';
+
+const AREA = AppConfig.MaxDescriptionArea;
+const height = AREA / Dimensions.get('window').width + 20;
class UserVideoHistoryRow extends PureComponent {
constructor(props) {
super(props);
+ this.isUserNavigate = false;
+ this.pageType = "user_profile";
+ this.pageInit();
}
- refetchVideo = () => {
- new PepoApi(`/videos/${this.props.videoId}`)
- .get()
- .then((res) => {})
- .catch((error) => {});
- };
-
- navigateToTransactionScreen = (e) => {
- if (this.isCurrentUser()) return;
- if (utilities.checkActiveUser() && CurrentUser.isUserActivated(true)) {
- this.props.navigation.push('TransactionScreen', {
- toUserId: this.props.userId,
- videoId: this.props.videoId,
- requestAcknowledgeDelegate: this.refetchVideo
- });
+ pageInit = () => {
+ if( Utilities.getLastChildRoutename(this.props.navigation.state) === 'VideoPlayer'){
+ this.isUserNavigate = true;
+ return this.pageType = 'video_player';
}
- };
-
- isCurrentUser() {
- return this.props.userId == CurrentUser.getUserId();
}
- shareVideo = () => {
- let shareVideo = new ShareVideo(this.props.videoId);
- shareVideo.perform();
- };
-
- onDescriptionClick = ( tapEntity , tapText ) => {
+ getPixelDropData = () => {
+ const parentData = this.props.getPixelDropData() ;
+ const pixelParams = {
+ e_entity: 'video',
+ video_id: this.props.videoId,
+ };
+ return assignIn({}, pixelParams, parentData);
+ }
- if (!tapEntity) {
- return;
- }
- if(tapEntity.kind === 'tags'){
- this.props.navigation.push('VideoTags', {
- "tagId": tapEntity.id
- });
- }
+ refetchVideo = () => {
+ new PepoApi(`/videos/${this.props.videoId}`)
+ .get()
+ .then((res) => {})
+ .catch((error) => {});
};
render() {
return (
-
-
-
- {!!this.props.videoId && !!this.props.userId && (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
+
+
+
+
+
+
+ {!!this.props.videoId && !!this.props.userId && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
);
}
}
+UserVideoHistoryRow.defaultProps = {
+ getPixelDropData: function(){
+ console.warn("getPixelDropData props is mandatory for UserVideoHistoryRow component");
+ return {};
+ }
+};
+
export default withNavigation(UserVideoHistoryRow);
diff --git a/src/components/UserVideoHistory/index.js b/src/components/UserVideoHistory/index.js
index 85808e50..8446e1b2 100644
--- a/src/components/UserVideoHistory/index.js
+++ b/src/components/UserVideoHistory/index.js
@@ -1,16 +1,16 @@
import React , {PureComponent} from "react";
-import {FlatList , View , TouchableOpacity, Image} from "react-native";
+import {FlatList} from "react-native";
import deepGet from "lodash/get";
import reduxGetters from "../../services/ReduxGetters";
import Pagination from "../../services/Pagination";
import UserVideoHistoryRow from "./UserVideoHistoryRow";
import TopStatus from "../../components/Home/TopStatus";
-
-import inlineStyles from "./styles";
import CurrentUser from "../../models/CurrentUser";
+import CommonStyle from "../../theme/styles/Common";
-import historyBack from '../../assets/user-video-history-back-icon.png';
+import FlotingBackArrow from "../CommonComponents/FlotingBackArrow";
+import { SafeAreaView } from "react-navigation";
const maxVideosThreshold = 3;
@@ -56,7 +56,7 @@ class UserVideoHistoryScreen extends PureComponent{
//This is an hack for reset scroll for flatlist. Need to debug a bit more.
this.willFocusSubscription = this.props.navigation.addListener('willFocus', (payload) => {
- const offset = this.state.activeIndex > 0 ? inlineStyles.fullScreen.height * this.state.activeIndex : 0 ;
+ const offset = this.state.activeIndex > 0 ? CommonStyle.fullScreen.height * this.state.activeIndex : 0 ;
this.flatlistRef && this.flatlistRef.scrollToOffset({offset: offset , animated: false});
this.isActiveScreen = true ;
});
@@ -119,9 +119,17 @@ class UserVideoHistoryScreen extends PureComponent{
return `id_${item}`;
};
+ getPixelDropData = () => {
+ return pixelParams = {
+ p_type: 'user_profile',
+ p_name: this.userId
+ };
+ }
+
_renderItem = ({ item, index }) => {
const videoId = reduxGetters.getUserVideoId(item) ;
return ;
@@ -148,7 +156,7 @@ class UserVideoHistoryScreen extends PureComponent{
}
getItemLayout= (data, index) => {
- return {length: inlineStyles.fullScreen.height, offset: inlineStyles.fullScreen.height * index, index} ;
+ return {length: CommonStyle.fullScreen.height, offset: CommonStyle.fullScreen.height * index, index} ;
}
isCurrentUser(){
@@ -170,7 +178,7 @@ class UserVideoHistoryScreen extends PureComponent{
render() {
return(
-
+
{!this.isCurrentUser() && }
-
-
-
-
+
+
);
}
diff --git a/src/components/UserVideoHistory/styles.js b/src/components/UserVideoHistory/styles.js
index c4eb3865..8ceb8980 100644
--- a/src/components/UserVideoHistory/styles.js
+++ b/src/components/UserVideoHistory/styles.js
@@ -33,16 +33,22 @@ let stylesMap = {
height: "100%"
},
touchablesBtns: {
- alignSelf: 'flex-end',
- marginBottom: -15,
- zIndex: 1
+ alignItems: 'flex-end',
+ marginBottom: -10,
+ zIndex: 1,
+ flexDirection: 'row'
+ },
+ invertedList: {
+ marginRight: 'auto',
+ minWidth: '20%',
+ marginBottom: 40
},
pepoTxCount: {
fontSize: 18,
color: Colors.white,
alignSelf: 'center',
marginTop: 3,
- marginBottom: 15
+ marginBottom: 5
},
txElem: {
marginBottom: 20
@@ -118,7 +124,16 @@ let stylesMap = {
height :10,
width:23,
zIndex: 1,
- }
+ },
+listContainer: {
+ // width: width,
+ position: 'absolute',
+ bottom: height * 0.05 + 50,
+ left: 10,
+ zIndex: 9,
+ alignSelf: 'flex-start',
+ height: height - 200
+}
};
export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/UsersProfile/index.js b/src/components/UsersProfile/index.js
index e094eb56..3bb9acb2 100644
--- a/src/components/UsersProfile/index.js
+++ b/src/components/UsersProfile/index.js
@@ -16,14 +16,18 @@ import { fetchUser } from '../../helpers/helpers';
import utilities from '../../services/Utilities';
import inlineStyles from './styles';
import UserProfileActionSheet from './userProfileActionSheet';
+import CommonStyle from "../../theme/styles/Common";
+import deepGet from "lodash/get";
+import unescape from'lodash/unescape';
import EventEmitter from "eventemitter3";
const userActionEvents = new EventEmitter();
export default class UsersProfile extends Component {
static navigationOptions = ({ navigation }) => {
+ const name = navigation.getParam('headerTitle') || reduxGetter.getName(navigation.getParam('userId'));
return {
- title: reduxGetter.getName(navigation.getParam('userId')),
+ title: name,
headerBackTitle: null,
headerStyle: {
backgroundColor: '#ffffff',
@@ -80,7 +84,10 @@ export default class UsersProfile extends Component {
onUserResponse = ( res ) => {
if(utilities.isEntityDeleted(res)){
this.setState({isDeleted: true});
+ return
}
+ let userName = deepGet(res, `data.users.${this.userId}.name` , "");
+ this.props.navigation.setParams({ headerTitle: unescape(userName)});
}
_headerComponent() {
@@ -97,7 +104,7 @@ export default class UsersProfile extends Component {
)
}else{
return (
-
+
-
+
);
}
}
diff --git a/src/components/UsersProfile/userProfileActionSheet.js b/src/components/UsersProfile/userProfileActionSheet.js
index fee0026b..9dc9c371 100644
--- a/src/components/UsersProfile/userProfileActionSheet.js
+++ b/src/components/UsersProfile/userProfileActionSheet.js
@@ -18,7 +18,7 @@ const ACTION_SHEET_BLOCK_UNBLOCK_INDEX = 1;
const mapStateToProps = (state, ownProps) => {
return {
- canBlockUser: ReduxGetters.canBlockUser(ownProps.userId , state)
+ canBlockUser: ReduxGetters.canBlockUser(ownProps.userId , state)
};
};
@@ -34,15 +34,17 @@ class UserProfileActionSheet extends PureComponent {
.then((response) => {
if (response && response.success){
Toast.show({text:'User reported successfully!', icon: 'success' });
+ } else {
+ Toast.show({text: `Unable to report user right now.`, icon: 'error' });
}
})
.catch((err) => {
- console.log('Report user failed', err);
+ Toast.show({text: `Unable to report user right now.`, icon: 'error' });
});
}
blockUser = () => {
- const oThis =this;
+ const oThis = this;
new PepoApi(`/users/${this.props.userId}/block`)
.post()
.then((response) => {
@@ -50,11 +52,11 @@ class UserProfileActionSheet extends PureComponent {
oThis.onBlockUnblockSuccessToast(true);
oThis.onBlockUnBlockSuccess(true);
}else{
- oThis.onBlockUnblockErrorToast(true);
+ oThis.onBlockUnblockErrorToast(true);
}
})
.catch((err) => {
- oThis.onBlockUnblockErrorToast(true);
+ oThis.onBlockUnblockErrorToast(true);
});
}
@@ -67,11 +69,11 @@ class UserProfileActionSheet extends PureComponent {
oThis.onBlockUnblockSuccessToast();
oThis.onBlockUnBlockSuccess();
}else{
- oThis.onBlockUnblockErrorToast();
+ oThis.onBlockUnblockErrorToast();
}
})
.catch((err) => {
- oThis.onBlockUnblockErrorToast();
+ oThis.onBlockUnblockErrorToast();
});
}
@@ -116,7 +118,7 @@ class UserProfileActionSheet extends PureComponent {
}
],
{cancelable: true},
- );
+ );
}
showActionSheet = () => {
@@ -124,13 +126,14 @@ class UserProfileActionSheet extends PureComponent {
blockAction = this.showBlockAlert;
if(!this.props.canBlockUser){
actionOptions = ['Report', 'Unblock' ,'Cancel'] ; //Mutate via code later.
- blockAction = this.unBlockUser;
+ blockAction = this.unBlockUser;
}
ActionSheet.show(
{
options: actionOptions,
cancelButtonIndex: ACTION_SHEET_CANCEL_INDEX,
- destructiveButtonIndex: ACTION_SHEET_DESCTRUCTIVE_INDEX
+ destructiveButtonIndex: ACTION_SHEET_DESCTRUCTIVE_INDEX,
+ title: "Select user action"
},
(buttonIndex) => {
if (buttonIndex == ACTION_SHEET_REPORT_INDEX) {
@@ -153,4 +156,4 @@ class UserProfileActionSheet extends PureComponent {
}
-export default connect(mapStateToProps)(UserProfileActionSheet);
\ No newline at end of file
+export default connect(mapStateToProps)(UserProfileActionSheet);
diff --git a/src/components/VideoCollections/index.js b/src/components/VideoCollections/index.js
index 319099c9..2781811f 100644
--- a/src/components/VideoCollections/index.js
+++ b/src/components/VideoCollections/index.js
@@ -2,7 +2,11 @@ import React, { PureComponent } from 'react';
import { ActivityIndicator , FlatList} from "react-native";
import {SafeAreaView} from "react-navigation";
import Pagination from "../../services/Pagination";
-import VideoThumbnailItem from '../../components/CommonComponents/VideoThumbnailItem';
+
+import CommonStyle from "../../theme/styles/Common";
+import VideoThumbnail from '../CommonComponents/VideoThumbnail/VideoThumbnail';
+import ReplyThumbnail from '../CommonComponents/VideoThumbnail/ReplyThumbnail';
+import entityHelper from '../../helpers/EntityHelper';
class VideoCollections extends PureComponent {
constructor(props){
@@ -92,8 +96,7 @@ class VideoCollections extends PureComponent {
}
beforeRefresh = ( ) => {
- //this.props.beforeRefresh && this.props.beforeRefresh();
- //this.onPullToRefresh();
+ this.props.beforeRefresh && this.props.beforeRefresh();
this.setState({ refreshing : true });
};
@@ -149,25 +152,41 @@ class VideoCollections extends PureComponent {
};
_renderVideoCell = ({ item, index }) => {
- return ( {this.onVideoClick(item.payload, index)}}
- isEmpty={item.isEmpty}
- emptyRenderFunction={this.props.getNoResultsCell}/>);
+ if(entityHelper.isVideoReplyEntity( item )){
+ if(entityHelper.isReplyVideoTypeEntity(item)){
+ return this._renderVideoReplyThumbnail( item, index );
+ }
+ } else if( entityHelper.isVideoEntity( item )) {
+ return this._renderVideoThumbnail( item, index);
+ }
};
+ _renderVideoReplyThumbnail( item, index ) {
+ return ( {this.onVideoClick(item.payload,index)}}/>);
+ }
+
+ _renderVideoThumbnail( item, index){
+ return ( {this.onVideoClick(item.payload, index)}}
+ isEmpty={item.isEmpty}
+ emptyRenderFunction={this.props.getNoResultsCell}/>);
+ }
+
onVideoClick = (payload, index) => {
const clonedInstance = this.videoPagination.fetchServices.cloneInstance();
this.props.navigation.push("FullScreenVideoCollection", {
fetchServices : clonedInstance,
+ tagId: this.props.tagId,
currentIndex: index,
payload,
baseUrl: this.props.getFetchUrl(),
- showBalanceFlier: this.props.extraParams && this.props.extraParams.showBalanceFlier
+ showBalanceFlyer: this.props.extraParams && this.props.extraParams.showBalanceFlyer
});
}
+
renderFooter = () => {
if (!this.state.loadingNext) return null;
return ;
@@ -199,15 +218,13 @@ class VideoCollections extends PureComponent {
this.listRef.scrollToOffset({offset: 0});
}
-
-
setListRef = (listRef) => {
this.listRef = listRef;
};
render(){
return (
-
+
{
nextAppState === 'background' && this.cancleVideoHandling();
};
- async componentDidMount() {
- if (this.props.acceptedCameraTnC === null) {
- utilities.getItem(`${CurrentUser.getUserId()}-accepted-camera-t-n-c`).then((terms) => {
- this.setState({ acceptedCameraTnC: terms });
- });
+ componentWillReceiveProps( nextProps ){
+ if( nextProps.acceptedCameraTnC != this.state.acceptedCameraTnC ){
+ this.setState({acceptedCameraTnC: nextProps.acceptedCameraTnC })
+ }
+
+ if ( nextProps.showLightBoxOnReply != this.state.showLightBoxOnReply ) {
+ this.setState({showLightBoxOnReply: nextProps.showLightBoxOnReply })
}
+ }
+
+
+
+ isStaleReduxObjectPresent(){
+ let acceptableKeys = ['reply_obj', 'video_type'];
+ for (let key in this.recordedVideoObj) {
+ if (! acceptableKeys.includes(key)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ async componentDidMount() {
+
BackHandler.addEventListener('hardwareBackPress', this._handleBackPress);
AppState.addEventListener('change', this._handleAppStateChange);
if (this.props.actionSheetOnRecordVideo) {
- let recordedVideoObj = reduxGetters.getRecordedVideo();
- this.recordedVideo = recordedVideoObj.raw_video;
- let isFileExists = false;
+ let isFileExists = await this.ifLocalVideoPresent();
const oThis = this;
-
- // this.showActionSheet();
- if (this.recordedVideo) {
- isFileExists = await RNFS.exists(this.recordedVideo);
- }
if (isFileExists) {
+ this.setState({ isLocalVideoPresent: true });
setTimeout(function() {
oThis.showActionSheet();
}, 100);
- } else if (Object.keys(recordedVideoObj).length > 0) {
+ } else if (this.isStaleReduxObjectPresent()) {
Store.dispatch(
upsertRecordedVideo({
do_discard: true
})
);
+ } else {
+ this.props.saveVideoPrimaryInfo();
}
}
}
@@ -85,7 +104,7 @@ class VideoRecorder extends Component {
ActionSheet.show(
{
options: ACTION_SHEET_BUTTONS,
- title: 'You have already recorded video'
+ title: this.props.getActionSheetText(this.recordedVideoObj)
},
(buttonIndex) => {
if (buttonIndex == ACTION_SHEET_RESHOOT_INDEX) {
@@ -96,9 +115,10 @@ class VideoRecorder extends Component {
do_discard: true
})
);
+ this.props.saveVideoPrimaryInfo();
} else if (buttonIndex == ACTION_SHEET_CONTINUE_INDEX) {
//navigate to previous page
- this.props.goToPreviewScreen(this.recordedVideo);
+ this.props.proceedWithExistingVideo(this.recordedVideoObj);
}
}
);
@@ -125,10 +145,132 @@ class VideoRecorder extends Component {
});
};
+ replyToVideo = () => {
+ this.setState({
+ showLightBoxOnReply: false
+ });
+ };
+
flipCamera = () => {
this.setState({ cameraFrontMode: !this.state.cameraFrontMode });
};
+
+ ifLocalVideoPresent = async () => {
+ let recordedVideo = this.recordedVideoObj.raw_video;
+ let isFileExists = false;
+ if (recordedVideo) {
+ isFileExists = await RNFS.exists(recordedVideo);
+ }
+ return isFileExists;
+ };
+
+ getPepoAmount = () => {
+ let amount = reduxGetters.getBtAmountForReply(this.props.videoId);
+ return Pricer.getToBT(Pricer.getFromDecimal(amount), 2);
+ };
+
+ getUserFullName = () => {
+ let userId = reduxGetters.getVideoCreatorUserId(this.props.videoId);
+ return reduxGetters.getName(userId)
+ };
+
+
+ showCoachForPosting = () => {
+ // If already recorded video present in local, do not show coach.
+ if (this.state.isLocalVideoPresent) return;
+
+ if (this.props.isVideoTypeReply) {
+ // TODO: return coach for posting
+ if (this.state.showLightBoxOnReply){
+ // Show video
+ return
+
+
+
+
+
+
+ Post a reply
+
+
+
+
+ Reply to {this.getUserFullName()}'s video for {this.getPepoAmount()} Pepo Coins
+
+
+
+ {
+ this.replyToVideo();
+ })}
+ />
+
+
+
+
+ }
+ // if (no video reply present) { return Coach }
+ } else {
+ if (this.state.acceptedCameraTnC !== 'true'){
+ console.log('=========----============-----------');
+
+ return
+
+ Submit your first video
+
+
+ Create a 30 second video update. Share what you're working on, what excites you, or anything on your
+ mind.
+
+
+
+
+ Approval process
+
+
+ The Pepo team will review your first video before it is shared publicly. We'll get in touch with you
+ ASAP!
+
+
+
+
+
+ Get Started
+
+
+
+
+
+
+
+ }
+ }
+ };
+
cameraView() {
return (
@@ -154,56 +296,33 @@ class VideoRecorder extends Component {
defaultVideoQuality={RNCamera.Constants.VideoQuality[AppConfig.cameraConstants.VIDEO_QUALITY]}
defaultMuted={false}
>
- {this.state.acceptedCameraTnC != 'true' && (
-
-
- Submit your first video
-
-
- Create a 30 second video update. Share what you're working on, what excites you, or anything on your
- mind.
-
-
-
-
- Approval process
-
-
- The Pepo team will review your first video before it is shared publicly. We'll get in touch with you
- ASAP!
-
-
-
-
-
- Get Started
-
-
-
-
-
-
- )}
+ {this.showCoachForPosting()}
{this.showCameraActions()}
);
}
+
+ shouldShowActionButtons = () => {
+
+ if (this.state.isLocalVideoPresent){
+ // If local video present, coach screen will not be seen. So we need to show action buttons.
+ return true;
+ }
+
+ if (this.props.isVideoTypeReply){
+ // If video type is reply and has video replies then we will not show coach and we need to show action buttons
+ return ! this.state.showLightBoxOnReply;
+ } else {
+ // If video type is post and terms and conditions are accepted then we will not show coach and we need to show action buttons
+ return this.state.acceptedCameraTnC === 'true';
+ }
+
+ };
+
showCameraActions = () => {
- if (this.state.acceptedCameraTnC == 'true') {
+ if (this.shouldShowActionButtons()) {
return (
height;
+const topPadding = getInset('top', landScape);
+const bottomPadding = getInset('bottom', landScape);
+const bottomReplyViewHeight = isIphoneX() ? 89 : 54;
+const listBottomPadding = height - (height/1.5)+bottomReplyViewHeight ;
+
+const bottomSpace = getBottomSpace([true]);
+
+class VideoRepliesScreen extends PureComponent {
+
+ static navigationOptions = ({ navigation, navigationOptions }) => {
+ return {
+ header: null,
+ headerBackTitle: null,
+ gesturesEnabled: false
+ };
+ };
+
+ constructor(props){
+ super(props);
+ this.userId = props.navigation.getParam('userId');
+ this.videoId = props.navigation.getParam('videoId');
+ this.fetchUrl = DataContract.replies.getReplyListApi(this.videoId);
+ this.initialHeight = height/1.5;
+ this.animatedValue = new Animated.Value(this.initialHeight) ;
+ this.listener = null;
+ this.panelAnimateTimeOut = 0 ;
+
+
+ this.state = {
+ showBackdrop : false,
+ addRepliesVisible : true,
+ videoUploaderVisible: false,
+ currentHeight : this.initialHeight,
+ videoReplyCount : ReduxGetters.getVideoReplyCount(this.videoId)
+ }
+ }
+
+ componentDidMount(){
+ this.listener = this.animatedValue.addListener(this.onAnimatedValueChange);
+ setTimeout(()=> {
+ this.setState({
+ showBackdrop: true,
+ videoUploaderVisible: ReduxGetters.getVideoProcessingStatus()
+ });
+
+ }, 300)
+ videoUploaderComponent.on('show', this.showVideoUploader);
+ videoUploaderComponent.on('hide', this.hideVideoUploader);
+ }
+
+ componentWillUnmount() {
+ this.onAnimatedValueChange= () => {};
+ this.animatedValue.removeListener(this.listener);
+ videoUploaderComponent.removeListener('show' , this.showVideoUploader , this);
+ videoUploaderComponent.removeListener('hide' , this.hideVideoUploader , this);
+ }
+
+ showVideoUploader = () => {
+ this.setState({
+ videoUploaderVisible: true
+ });
+ };
+
+ hideVideoUploader = ( otherStates, callback ) => {
+ otherStates = otherStates || {};
+ this.setState({
+ ...otherStates,
+ videoUploaderVisible: false
+ }, callback);
+ };
+
+ onAnimatedValueChange = ({ value }) => {
+ clearTimeout(this.panelAnimateTimeOut);
+ this.panelAnimateTimeOut = setTimeout(()=> {
+ if( value < 10){
+ this.hideVideoUploader({
+ addRepliesVisible: false
+ },() => {
+ this.props.navigation.goBack();
+ });
+ }
+ } , 10)
+ };
+
+ onCrossIconClick = () => {
+ this._panel.hide();
+ };
+
+ getUploadingText = () => {
+ let videoType = ReduxGetters.getRecordedVideoType();
+ if (videoType === 'post'){
+ return "Uploading Video";
+ } else if (videoType === 'reply'){
+ return "Posting reply";
+ }
+ }
+ ;
+
+ openCamera = () => {
+ if( replyPreValidationAndMessage( this.videoId , this.userId ) ){
+ let activeTab = NavigationService.getActiveTab();
+ let params = getVideoReplyObject ( this.videoId , this.userId) ;
+ utilities.handleVideoUploadModal(activeTab, this.props.navigation, params);
+ }
+ }
+
+ onData = ( data ) => {
+ this.dataLoaded = true;
+ }
+
+ getWrapViewStyles = () => {
+ let wrapStyles = {};
+ if ( !this.state.addRepliesVisible ) {
+ wrapStyles.display = "none";
+ }
+ return wrapStyles;
+ };
+
+ onRefresh = ()=> {
+ this.setState({
+ videoReplyCount : ReduxGetters.getVideoReplyCount(this.videoId)
+ })
+ };
+
+ render(){
+ return (
+
+ {this.userId && this.state.videoUploaderVisible && (
+
+ )}
+ (this._panel = c)}
+ containerStyle={{zIndex: 99}}
+ animatedValue={this.animatedValue}
+ onMomentumDragEnd={(value) => {
+ this.setState({
+ currentHeight : value
+ })
+
+ }}
+ ref={c => (this._panel = c)}
+ draggableRange={{
+ top: height - topPadding,
+ bottom: 0
+ }}
+ showBackdrop={this.state.showBackdrop}
+ snappingPoints={[0, this.initialHeight, height]}>
+ {dragHandler => (
+
+
+
+
+
+
+
+
+
+ {this.state.videoReplyCount} Repl{this.state.videoReplyCount > 1 ? 'ies' : 'y'}
+
+ {/*Send a reply with{' '}*/}
+ {/**/}
+ {/*{ Pricer.getToBT(Pricer.getFromDecimal(ReduxGetters.getBtAmountForReply(this.videoId )), 2)}*/}
+
+
+ this.initialHeight? topPadding+bottomPadding+bottomReplyViewHeight : listBottomPadding}
+ onRefresh={this.onRefresh}
+ />
+
+
+
+ )}
+
+ {this.state.addRepliesVisible && (
+
+
+
+
+
+ Add a reply...
+
+
+
+
+ )}
+
+ );
+ }
+
+}
+
+
+export default VideoRepliesScreen;
+
+
diff --git a/src/components/VideoReplies/styles.js b/src/components/VideoReplies/styles.js
new file mode 100644
index 00000000..1fd35680
--- /dev/null
+++ b/src/components/VideoReplies/styles.js
@@ -0,0 +1,99 @@
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+import Colors from '../../theme/styles/Colors';
+import {ifIphoneX} from "react-native-iphone-x-helper";
+
+let stylesMap = {
+ container: {
+ flex: 1,
+ zIndex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.white,
+ borderTopLeftRadius: 30,
+ borderTopRightRadius: 30,
+ overflow: 'hidden'
+ },
+ dragHandler: {
+ height: 65,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.white,
+ flexDirection: 'row',
+ zIndex: 9,
+ width: '100%',
+ borderBottomWidth: 0.4,
+ borderColor: 'rgba(0, 0, 0, 0.3)'
+ },
+ iconWrapper: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: 50,
+ width: 50
+ },
+ iconSkipFont: {
+ height: 16,
+ width: 16
+ },
+ repliesTxt: {
+ flex: 4,
+ alignItems: 'center',
+ marginRight:50 //equal to crossIcon width in order to maintain text in center
+ },
+ headerStyles: {
+ backgroundColor: Colors.white,
+ borderBottomWidth: 0,
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 1
+ },
+ shadowOpacity: 0.1,
+ shadowRadius: 3
+ },
+ headerText:{
+ fontFamily: 'AvenirNext-Medium',
+ color: Colors.valhalla,
+ fontSize: 18
+ },
+ headerSubText:{
+ fontSize: 12,
+ color: 'rgba(42, 41, 59, 0.7)'
+ },
+ addReplyView : {
+ width:'100%',
+ ...ifIphoneX(
+ {
+ height: 89
+ },
+ {
+ height: 54
+ }),
+ shadowColor:'#000',
+ elevation: 8,
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.8,shadowRadius: 1,
+ position:'absolute',
+ bottom:0,
+ zIndex:9999,
+ backgroundColor:Colors.white
+ },
+ addReplyInnerView:{
+ height: 54,
+ width: '100%',
+ flexDirection:'row',
+ alignItems: 'center',
+ paddingHorizontal:12,
+ backgroundColor:Colors.white,
+ },
+ addReplyText : {
+ color:Colors.black,
+ marginLeft:10
+ },
+ addReplyImageDimensionSkipFont : {
+ height:10,
+ width:15
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/VideoTags/index.js b/src/components/VideoTags/index.js
index d61b9514..a30d7010 100644
--- a/src/components/VideoTags/index.js
+++ b/src/components/VideoTags/index.js
@@ -1,5 +1,7 @@
import React, { PureComponent } from 'react';
import { View } from 'react-native';
+import qs from 'qs';
+
import reduxGetter from '../../services/ReduxGetters';
import VideoCollections from '../VideoCollections';
import Colors from '../../theme/styles/Colors';
@@ -79,16 +81,17 @@ class VideoTags extends PureComponent {
this.didFocus && this.didFocus.remove && this.didFocus.remove();
}
-
-
_headerComponent() {
// do nothing
}
- getFetchUrl = () => {
- return `/tags/${this.getTagId()}/videos`
-
- }
+ getFetchUrl = () => {
+ let baseUrl = `/tags/${this.getTagId()}/allvideos`;
+ let params = {
+ supported_entities: ['videos', 'replies']
+ };
+ return baseUrl + "?" + qs.stringify(params);
+ };
getTagId = () => {
return this.props.navigation.getParam("tagId")
@@ -101,7 +104,7 @@ class VideoTags extends PureComponent {
getExtraParams = () => {
return {
- showBalanceFlier: true
+ showBalanceFlyer: true
};
};
@@ -115,6 +118,7 @@ class VideoTags extends PureComponent {
navigation={this.props.navigation}
noResultsData={this.noResultsData}
getNoResultsCell={this.renderNoResults}
+ tagId={this.getTagId()}
extraParams={this.getExtraParams()}
/>
} else {
diff --git a/src/components/Home/VideoWrapper.js b/src/components/VideoWrapper/Base.js
similarity index 85%
rename from src/components/Home/VideoWrapper.js
rename to src/components/VideoWrapper/Base.js
index 76b27141..ad79a296 100644
--- a/src/components/Home/VideoWrapper.js
+++ b/src/components/VideoWrapper/Base.js
@@ -1,29 +1,21 @@
import React, { PureComponent } from 'react';
import { TouchableWithoutFeedback, AppState, View, Image, ActivityIndicator } from 'react-native';
-import { connect } from 'react-redux';
import { withNavigation } from 'react-navigation';
import Video from 'react-native-video';
import inlineStyles from './styles';
-import reduxGetter from '../../services/ReduxGetters';
import playIcon from '../../assets/play_icon.png';
import PixelCall from '../../services/PixelCall';
import {VideoPlayPauseEmitter} from '../../helpers/Emitters';
import AppConfig from '../../constants/AppConfig';
import socketPixelCall from './../../services/SocketPixelCall'
import CurrentUser from "../../models/CurrentUser";
+import assignIn from 'lodash/assignIn';
-const mapStateToProps = (state, ownProps) => {
- return {
- videoImgUrl: reduxGetter.getVideoImgUrl(ownProps.videoId, state),
- videoUrl: reduxGetter.getVideoUrl(ownProps.videoId, state),
- loginPopover: ownProps.isActive && state.login_popover.show
- };
-};
const VIDEO_PLAY_START_EVENT_NAME = "video_play_start";
const VIDEO_PLAY_END_EVENT_NAME = "video_play_end";
-class VideoWrapper extends PureComponent {
+class Base extends PureComponent {
constructor(props) {
super(props);
this.state = {
@@ -115,7 +107,7 @@ class VideoWrapper extends PureComponent {
if (this.props.isActive && this.state.paused) {
this.setState({ paused: false });
return;
- }
+ }
if ( this.isPaused() != this.currentPauseStatus ) {
//Force render.
this.forceUpdate();
@@ -167,19 +159,11 @@ class VideoWrapper extends PureComponent {
fireEvent(params) {
if (this.videoContext.isEventCalledOnView(CurrentUser.getUserId(), this.props.video_id)) return;
if (params.currentTime >= this.minTimeConsideredForView) {
- let pixelParams = {
- e_entity: 'video',
- e_action: 'view',
- e_data_json: {
- video_id: this.props.videoId,
- profile_user_id: this.props.userId
- },
- p_type: this.props.navigation.state.routeName === 'HomeScreen' ? 'feed' : 'user_profile'
- };
+ const parentData = this.props.getPixelDropData() ;
+ let pixelParams = { e_action: 'view' };
+ pixelParams = assignIn({}, pixelParams, parentData);
PixelCall(pixelParams);
-
this.sendFeedVideoEvent(VIDEO_PLAY_START_EVENT_NAME);
-
this.videoContext.eventFired(CurrentUser.getUserId(), this.props.video_id);
}
}
@@ -199,17 +183,13 @@ class VideoWrapper extends PureComponent {
onEnd = (params) => {
if (this.isPixelCalledOnEnd) return;
- let pixelParams = {
- e_entity: 'video',
- e_action: 'full_viewed',
- e_data_json: {
- video_id: this.props.videoId,
- profile_user_id: this.props.userId
- },
- p_type: this.props.navigation.state.routeName === 'HomeScreen' ? 'feed' : 'user_profile'
- };
+ const parentData = this.props.getPixelDropData() ;
+ let pixelParams = { e_action: 'full_viewed', };
+ pixelParams = assignIn({}, pixelParams, parentData);
PixelCall(pixelParams);
this.isPixelCalledOnEnd = true;
+
+ this.sendFeedVideoEvent(VIDEO_PLAY_END_EVENT_NAME);
};
getIsVideoPausedStatus = () => {
@@ -248,12 +228,16 @@ class VideoWrapper extends PureComponent {
}
}
-VideoWrapper.defaultProps = {
+Base.defaultProps = {
shouldPlay: function(){
return true;
},
+ getPixelDropData: function(){
+ console.warn("getPixelDropData props is mandatory for Video component");
+ return {};
+ },
doRender: true ,
isActive: true
};
-export default connect(mapStateToProps)(withNavigation(VideoWrapper));
+export default withNavigation(Base);
diff --git a/src/components/VideoWrapper/FanVideo.js b/src/components/VideoWrapper/FanVideo.js
new file mode 100644
index 00000000..9b53894e
--- /dev/null
+++ b/src/components/VideoWrapper/FanVideo.js
@@ -0,0 +1,15 @@
+
+import reduxGetter from "../../services/ReduxGetters";
+import { connect } from 'react-redux';
+import Base from "./Base";
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ videoImgUrl: reduxGetter.getVideoImgUrl(ownProps.videoId, state),
+ videoUrl: reduxGetter.getVideoUrl(ownProps.videoId, state),
+ loginPopover: ownProps.isActive && state.login_popover.show
+ };
+};
+
+const FanVideo = connect(mapStateToProps)(Base);
+export default FanVideo;
\ No newline at end of file
diff --git a/src/components/VideoWrapper/styles.js b/src/components/VideoWrapper/styles.js
new file mode 100644
index 00000000..2af13b42
--- /dev/null
+++ b/src/components/VideoWrapper/styles.js
@@ -0,0 +1,21 @@
+import { Dimensions} from 'react-native';
+import DefaultStyleGenerator from '../../theme/styles/DefaultStyleGenerator';
+
+const {width, height} = Dimensions.get('window');
+
+let stylesMap = {
+
+ fullHeightWidthSkipFont: {
+ width: "100%",
+ height: "100%"
+ },
+ playIconSkipFont: {
+ position: 'absolute',
+ height: 25,
+ width: 25,
+ top: height * 0.5 - 12,
+ left: width * 0.5 - 12
+ }
+};
+
+export default styles = DefaultStyleGenerator.generate(stylesMap);
diff --git a/src/components/WalletSetting/WalletSettingController.js b/src/components/WalletSetting/WalletSettingController.js
index 4dffe4b9..781d50cc 100644
--- a/src/components/WalletSetting/WalletSettingController.js
+++ b/src/components/WalletSetting/WalletSettingController.js
@@ -44,15 +44,15 @@ class WalletSettingController {
}
_initializeOptions() {
- this._createOptionsData(optionIds.addSession, "Add Session", "Add Session to do transaction");
- this._createOptionsData(optionIds.walletDetails, "Wallet Details", "View your wallet details");
- this._createOptionsData(optionIds.recoverDevice, "Recover Device", "Recover your device");
- this._createOptionsData(optionIds.abortRecovery, "Abort Device Recovery", "Abort Device Recovery");
- this._createOptionsData(optionIds.resetPin, "Reset Pin", "Reset your wallet pin");
+ this._createOptionsData(optionIds.addSession, "Add Session", "Add Session to do transaction.");
+ this._createOptionsData(optionIds.walletDetails, "Wallet Details", "View your wallet details.");
+ this._createOptionsData(optionIds.recoverDevice, "Recover Device", "Recover your device.");
+ this._createOptionsData(optionIds.abortRecovery, "Abort Device Recovery", "Abort Device Recovery.");
+ this._createOptionsData(optionIds.resetPin, "Reset Pin", "Reset your wallet pin.");
this._createOptionsData(optionIds.viewMnemonics, "Show Mnemonics", "While not required, writing down your 12 word mnemonic phrase provides an additional backup in case you forget your PIN.");
- this._createOptionsData(optionIds.authorizeWithMnemonics, "Authorize Device with Mnemonics", "Authorize current device by using mnemonics");
+ this._createOptionsData(optionIds.authorizeWithMnemonics, "Authorize Device with Mnemonics", "Authorize current device by using mnemonics.");
this._createOptionsData(optionIds.authorizeWithQR, "Add Another Device", "Scan QR Code to add another device.");
- this._createOptionsData(optionIds.showQR, "Show Device QR Code", "Scan QR Code from the device authorized device to authorize this device");
+ this._createOptionsData(optionIds.showQR, "Show Device QR Code", "Scan QR Code from the device authorized device to authorize this device.");
this._createOptionsData(optionIds.updateBiometricPreference, "Enable Biometric", "Use biometrics to authorize new Sessions and to confirm high value transactions.");
}
diff --git a/src/components/WalletSetting/styles.js b/src/components/WalletSetting/styles.js
index 5e03fa29..d57ac17c 100644
--- a/src/components/WalletSetting/styles.js
+++ b/src/components/WalletSetting/styles.js
@@ -5,7 +5,8 @@ let stylesMap = {
list: {
flex: 1,
- marginTop: 15
+ backgroundColor: Colors.white,
+ paddingTop: 15
},
title: {
color: Colors.valhalla,
diff --git a/src/components/WalletSetting/walletDetailsStyles.js b/src/components/WalletSetting/walletDetailsStyles.js
index 1ca75d48..61227ec5 100644
--- a/src/components/WalletSetting/walletDetailsStyles.js
+++ b/src/components/WalletSetting/walletDetailsStyles.js
@@ -5,6 +5,7 @@ let stylesMap = {
list: {
flex: 1,
+ backgroundColor: Colors.white
},
title: {
color: Colors.grey,
diff --git a/src/constants/AppConfig.js b/src/constants/AppConfig.js
index 430e6147..e633a791 100644
--- a/src/constants/AppConfig.js
+++ b/src/constants/AppConfig.js
@@ -3,12 +3,28 @@ import balance_header_pepo_icon from '../assets/balance_header_pepo_icon.png';
import twitterDisconnectIcon from '../assets/drawer-twitter-icon.png';
import defaultLinkIcon from '../assets/default_link_icon.png';
import feedLinkIcon from '../assets/Link.png';
+import {getBottomSpace, ifIphoneX} from "react-native-iphone-x-helper";
+import {CUSTOM_TAB_Height} from "../theme/constants";
+import NotchHelper from "../helpers/NotchHelper";
+import {Dimensions, NativeModules, StatusBar} from "react-native";
+
+const statusBarHeight = StatusBar.currentHeight;
+const {height} = Dimensions.get('window');
+let RNDeviceInfo = NativeModules.RNDeviceInfo;
+let modalDeviceName = RNDeviceInfo.model === "Redmi Note 7 Pro" && RNDeviceInfo.brand === "xiaomi";
+let btmSpace = modalDeviceName ? 5 : 0;
const PROFILE_TX_SEND_SUCCESS = 'PROFILE_TX_SEND_SUCCESS',
PROFILE_TX_RECEIVE_SUCCESS = 'PROFILE_TX_RECEIVE_SUCCESS',
VIDEO_TX_SEND_SUCCESS = 'VIDEO_TX_SEND_SUCCESS',
VIDEO_TX_RECEIVE_SUCCESS = 'VIDEO_TX_RECEIVE_SUCCESS',
VIDEO_ADD = 'VIDEO_ADD',
+ USER_MENTION = 'USER_MENTION',
+ REPLY_USER_MENTION = 'REPLY_USER_MENTION',
+ REPLY_SENDER_WITH_AMOUNT = 'REPLY_SENDER_WITH_AMOUNT',
+ REPLY_SENDER_WITHOUT_AMOUNT = 'REPLY_SENDER_WITHOUT_AMOUNT',
+ REPLY_RECEIVER_WITH_AMOUNT = 'REPLY_RECEIVER_WITH_AMOUNT',
+ REPLY_RECEIVER_WITHOUT_AMOUNT = 'REPLY_RECEIVER_WITHOUT_AMOUNT',
CONTRIBUTION_THANKS = 'CONTRIBUTION_THANKS',
SYSTEM_NOTIFICATION = 'SYSTEM_NOTIFICATION',
PROFILE_TX_SEND_FAILURE = 'PROFILE_TX_SEND_FAILURE',
@@ -22,7 +38,8 @@ export default {
logoutTimeOut : 2000,
beKnownErrorCodeMaps : {
- entityDeleted: "not_found"
+ entityDeleted: "not_found",
+ validateUploadError: "precondition_failed"
},
userStatusMap: {
@@ -35,6 +52,10 @@ export default {
deleted: 'deleted'
},
+ replyStatusMap:{
+ deleted: 'deleted'
+ },
+
deviceStatusMap: {
registered: 'registered',
authorizing: 'authorizing',
@@ -54,6 +75,11 @@ export default {
name: 'profile'
},
+ replyMetaProperties: {
+ type: 'user_to_user',
+ name: 'reply_on_video'
+ },
+
redemptionMetaProperties : {
type: 'user_to_company',
name: 'redemption'
@@ -141,6 +167,12 @@ export default {
videoTxSendKind: VIDEO_TX_SEND_SUCCESS,
videoTxReceiveKind: VIDEO_TX_RECEIVE_SUCCESS,
videoAddKind: VIDEO_ADD,
+ userMention: USER_MENTION,
+ replyUserMention: REPLY_USER_MENTION,
+ replySenderWithAmount: REPLY_SENDER_WITH_AMOUNT,
+ replySenderWithoutAmount: REPLY_SENDER_WITHOUT_AMOUNT,
+ replyReceiverWithAmount: REPLY_RECEIVER_WITH_AMOUNT,
+ replyReceiverWithoutAmount: REPLY_RECEIVER_WITHOUT_AMOUNT,
AppreciationKind: CONTRIBUTION_THANKS,
systemNotification: SYSTEM_NOTIFICATION,
airDropNotification: AIRDROP_DONE,
@@ -154,8 +186,9 @@ export default {
PROFILE_TX_SEND_FAILURE,
VIDEO_TX_SEND_FAILURE,
AIRDROP_DONE,
- TOPUP_DONE
-
+ TOPUP_DONE,
+ REPLY_SENDER_WITH_AMOUNT,
+ REPLY_RECEIVER_WITH_AMOUNT
],
whitelistedNotificationKinds: [
PROFILE_TX_SEND_SUCCESS,
@@ -291,7 +324,71 @@ export default {
RedemptionSuccess: 'Redemption/Success',
CouchMarks: 'CouchMarks',
AuthDeviceDrawer: 'DeviceUnauthorized',
- TwitterLogin: 'TwitterLogin'
+ TwitterLogin: 'TwitterLogin',
+ FullScreenReplyCollection: 'FullScreenReplyCollection',
+ VideoReplyPlayer: 'VideoReplyPlayer',
+ VideoReplies: 'VideoReplies'
+ },
+ default_bt_amt : 10,
+
+ videoTypes: {
+ post : 'post',
+ reply: 'reply'
+ },
+
+ MaxDescriptionArea: 35250,
+ thumbnailListConstants: {
+
+
+ // NOTE: Outer Circle Configs.
+ // -----------------------------------------------------------------------
+ // 1. outerRingDiameter - Replaces old iconHeight/iconWidth.
+ //
+ // 2. borderWidth - The border width is applied outside the
+ // this iconHeight (Diameter).
+ //
+ // 3. transparentGap - Gap between the inner edge of Outer-Circle
+ // and icon itself.
+ //
+ // 4. iconImageDiameter - Diameter of icon Image is computed
+ // using outerRingDiameter, outerBorderWidth
+ // and transparentGap.
+ // -----------------------------------------------------------------------
+ outerRingDiameter: 48,
+ outerBorderWidth: 2,
+ transparentGap: 2,
+ iconImageDiameter: function () {
+ return this.outerRingDiameter - (2 * (this.outerBorderWidth + this.transparentGap ));
+ },
+
+ // cellHeight - Gives actual height of cell.
+ cellHeight: function() {
+ return this.outerRingDiameter + (2 * this.outerBorderWidth);
+ },
+
+ separatorHeight: 25,
+ separatorWidth: 1,
+ separatorColor: 'white',
+ //separatorMargin - Margin to draw over the transparent outer ring (to be applied in negative);
+ separatorMargin: function () {
+ return this.outerBorderWidth + this.transparentGap;
+ },
+
+ parentIconHeight: 46,
+ parentIconWidth: 46
+ },
+ VideoScreenObject : {
+ ...ifIphoneX(
+ {
+ height: height - CUSTOM_TAB_Height - getBottomSpace([true])
+ },
+ {
+ height:
+ NotchHelper.hasNotch()
+ ? height + statusBarHeight - CUSTOM_TAB_Height - btmSpace
+ : height - CUSTOM_TAB_Height
+ }
+ )
}
};
diff --git a/src/constants/DataContract.js b/src/constants/DataContract.js
index a0e5f2c0..ca562d9a 100644
--- a/src/constants/DataContract.js
+++ b/src/constants/DataContract.js
@@ -37,8 +37,59 @@ export default {
infoApi: "/support/info"
},
+ replies: {
+ validateReply: "/replies/validate-upload",
+ getReplyListApi : (id) => {
+ return `/videos/${id}/replies`
+ },
+ getDeleteVideoReplyApi : (id) => {
+ return `/replies/${id}/delete`;
+ },
+ validatePost: "/videos/validate-upload",
+ getSingleVideoReplyApi : (id) => {
+ return `/replies/${id}`;
+ },
+ videoReplyKind: {
+ video: "VIDEO"
+ },
+ replyDetailIdKey: 'reply_detail_id',
+ parentVideoIdKey: 'parent_id',
+ creatorUserIdKey: 'creator_user_id',
+ replyDetailsKey: 'reply_details'
+ },
+
common: {
resultType : "data.result_type"
+ },
+
+ mentions: {
+ userMentions: "/search/users-mention"
+ },
+
+ tags: {
+ userTags: "/tags"
+ },
+
+ videos: {
+ getDeleteVideoApi : (id) => {
+ return `/videos/${id}/delete`;
+ },
+ videoKind: {
+ reply : "VIDEO_REPLY",
+ video:"FAN_UPDATE"
+ },
+ kindKey: "kind",
+ creatorUserIdKey: 'creator_user_id',
+ videoDetailsKey: 'video_details'
+ },
+
+ share: {
+ getVideoShareApi: ( id ) => {
+ return `/videos/${id}/share`;
+ },
+ getVideoReplyShareApi: ( id ) => {
+ return `/replies/${id}/share`;
+ }
}
}
diff --git a/src/helpers/Emitters.js b/src/helpers/Emitters.js
index c63dce6a..13a77023 100644
--- a/src/helpers/Emitters.js
+++ b/src/helpers/Emitters.js
@@ -1,5 +1,6 @@
import EventEmitter from 'eventemitter3';
let VideoPlayPauseEmitter = new EventEmitter();
let DrawerEmitter = new EventEmitter();
+let VideoReplyEmitter = new EventEmitter();
-export { VideoPlayPauseEmitter, DrawerEmitter };
+export { VideoPlayPauseEmitter, DrawerEmitter, VideoReplyEmitter };
diff --git a/src/helpers/EntityHelper.js b/src/helpers/EntityHelper.js
new file mode 100644
index 00000000..b8ff4ca8
--- /dev/null
+++ b/src/helpers/EntityHelper.js
@@ -0,0 +1,35 @@
+import deepGet from 'lodash/get';
+import DataContract from '../constants/DataContract';
+import ReduxGetters from '../services/ReduxGetters';
+
+class EntityHelper {
+
+ getEntityType( entity ){
+ const type = deepGet(entity,`${DataContract.videos.kindKey}`);
+ return type;
+ }
+
+ getReplyKind( entity ){
+ const replyDetailId = deepGet(entity,`payload.${DataContract.replies.replyDetailIdKey}`);
+ const replyKind = ReduxGetters.getReplyKind(replyDetailId);
+ return replyKind;
+ }
+
+ isVideoEntity( entity ){
+ const type = this.getEntityType(entity);
+ return type == DataContract.videos.videoKind.video;
+ }
+
+ isVideoReplyEntity( entity ){
+ const type = this.getEntityType(entity);
+ return type == DataContract.videos.videoKind.reply;
+ }
+
+ isReplyVideoTypeEntity( entity ){
+ const replyKind = this.getReplyKind( entity );
+ return replyKind == DataContract.replies.videoReplyKind.video;
+ }
+
+}
+
+export default new EntityHelper();
\ No newline at end of file
diff --git a/src/helpers/NavigationAnimation.js b/src/helpers/NavigationAnimation.js
new file mode 100644
index 00000000..0e9b2e13
--- /dev/null
+++ b/src/helpers/NavigationAnimation.js
@@ -0,0 +1,102 @@
+
+import { Easing, Animated,Platform } from 'react-native';
+
+
+export default {
+ zoomIn: ( duration=300 ) =>{
+ return {
+ transitionSpec: {
+ duration,
+ easing: Easing.out(Easing.poly(4)),
+ timing: Animated.timing,
+ useNativeDriver: true,
+ },
+ screenInterpolator: ({ position, scene }) => {
+ const { index } = scene;
+ let start = 0;
+ if (Platform.OS !== 'ios') {
+ start = 0.005
+ }
+
+ const scale = position.interpolate({
+ inputRange: [index - 1, index , index + 1],
+ outputRange: [start, 1 , 1],
+ });
+
+ return { transform: [{ scale }] };
+ },
+ }
+ },
+ zoomOut : ( duration=300 ) => {
+ return {
+ transitionSpec: {
+ duration,
+ easing: Easing.out(Easing.poly(4)),
+ timing: Animated.timing,
+ useNativeDriver: true,
+ },
+ screenInterpolator: ({ position, scene }) => {
+ const { index } = scene;
+
+ const scale = position.interpolate({
+ inputRange: [index - 1, index],
+ outputRange: [10, 1],
+ });
+
+ return { transform: [{ scale }] };
+ },
+ }
+ },
+ fromBottom : (duration = 300) => {
+ return {
+ transitionSpec: {
+ duration,
+ easing: Easing.out(Easing.poly(4)),
+ timing: Animated.timing,
+ useNativeDriver: true,
+ },
+ screenInterpolator: ({ layout, position, scene }) => {
+ const { index } = scene;
+ const { initHeight } = layout;
+
+ const translateY = position.interpolate({
+ inputRange: [index - 1, index, index + 1],
+ outputRange: [initHeight, 0, 0],
+ });
+
+ const opacity = position.interpolate({
+ inputRange: [index - 1, index - 0.99, index],
+ outputRange: [0, 1, 1],
+ });
+
+ return { opacity, transform: [{ translateY }] };
+ },
+ };
+ },
+ defaultTransition: ( duration=300 ) => {
+ return {
+ transitionSpec: {
+ duration: 300,
+ easing: Easing.out(Easing.poly(4)),
+ timing: Animated.timing
+ },
+ screenInterpolator: (sceneProps) => {
+ const { layout, position, scene } = sceneProps;
+ const { index } = scene;
+
+ const height = layout.initHeight;
+ const translateY = position.interpolate({
+ inputRange: [index - 1, index, index + 1],
+ outputRange: [height, 0, 0]
+ });
+
+ const opacity = position.interpolate({
+ inputRange: [index - 1, index - 0.99, index],
+ outputRange: [0, 1, 1]
+ });
+
+ return { opacity, transform: [{ translateY }] };
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/helpers/NotchHelper.js b/src/helpers/NotchHelper.js
index 09340d93..005da3bd 100644
--- a/src/helpers/NotchHelper.js
+++ b/src/helpers/NotchHelper.js
@@ -1,6 +1,4 @@
-import {NativeModules} from "react-native";
-const RNDeviceInfo = NativeModules.RNDeviceInfo;
-import PepoApi from "../services/PepoApi";
+import DeviceInfo from 'react-native-device-info';
let devicesWithNotch = [
{
@@ -123,6 +121,10 @@ let devicesWithNotch = [
"brand": "HONOR",
"model": "COR-AL00"
},
+ {
+ "brand": "HONOR",
+ "model": "JSN-L42"
+ },
{
"brand": "OnePlus",
"model": "ONEPLUS A6010"
@@ -132,21 +134,36 @@ let devicesWithNotch = [
class NotchHelper {
syncList(){
- let listUrl = "https://d3attjoi5jlede.cloudfront.net/pepo-app/devices-list/notch-devices.json";
- new PepoApi(listUrl).get().then((res)=> {
- const devices = res && res.devices;
- if( devices && devices instanceof Array && devices.length < 1 ) {
- devicesWithNotch = devices;
+ fetch(`https://d3attjoi5jlede.cloudfront.net/pepo-app/devices-list/notch-devices.json?${Date.now()}`)
+ .then((response) => response.json())
+ .then((responseJson) => {
+ const devices = responseJson && responseJson.devices;
+ if( devices && devices instanceof Array && devices.length > 0 ) {
+ devicesWithNotch = devices;
+ }
+ })
+ .catch((error) => {
+ console.log("Notch helper fetch error ignored");
+ });
+ }
+
+ hasNotchRemote(){
+ if(devicesWithNotch.length > 0){
+ return (
+ devicesWithNotch.findIndex(
+ item =>
+ item.brand.toLowerCase() === DeviceInfo.getBrand().toLowerCase() &&
+ (item.model.toLowerCase() === DeviceInfo.getDeviceName().toLowerCase() || item.model.toLowerCase() === DeviceInfo.getModel().toLowerCase())
+ ) !== -1
+ );
}
- }).catch((error)=> {
- console.log("ignore")
- })
+ return false;
}
hasNotch() {
- return devicesWithNotch.findIndex(item => item.brand === RNDeviceInfo.brand && ( item.model === RNDeviceInfo.deviceName || item.model === RNDeviceInfo.model )) !== -1;
+ return DeviceInfo.hasNotch() || this.hasNotchRemote();
}
}
-export default new NotchHelper()
\ No newline at end of file
+export default new NotchHelper()
diff --git a/src/helpers/ReplyHelper.js b/src/helpers/ReplyHelper.js
new file mode 100644
index 00000000..8c3d9015
--- /dev/null
+++ b/src/helpers/ReplyHelper.js
@@ -0,0 +1,19 @@
+import deepGet from 'lodash/get';
+
+import store from '../store';
+import ReduxGetters from "../services/ReduxGetters";
+import { upsertCurrentUserReplyDetailRelationEntities } from '../reducers';
+import Utilities from '../services/Utilities';
+import DataContract from '../constants/DataContract';
+
+
+function updateEntitySeen (item) {
+ const replyDetailId = deepGet(item,`payload.${DataContract.replies.replyDetailIdKey}`);
+ let currentUserReplyDetailRelationEntity = ReduxGetters.getReplyDetailRelationEntity( replyDetailId );
+ if(currentUserReplyDetailRelationEntity){
+ currentUserReplyDetailRelationEntity['has_seen'] = true;
+ store.dispatch(upsertCurrentUserReplyDetailRelationEntities(Utilities._getEntityFromObj(currentUserReplyDetailRelationEntity)));
+ }
+ }
+
+export default { updateEntitySeen }
\ No newline at end of file
diff --git a/src/helpers/TransactionHelper.js b/src/helpers/TransactionHelper.js
index 5fa262b3..473d872d 100644
--- a/src/helpers/TransactionHelper.js
+++ b/src/helpers/TransactionHelper.js
@@ -1,12 +1,10 @@
import BigNumber from 'bignumber.js';
-import {OstWalletSdk, OstWalletSdkUI, OstJsonApi} from '@ostdotcom/ost-wallet-sdk-react-native';
+import {OstWalletSdk, OstWalletSdkUI} from '@ostdotcom/ost-wallet-sdk-react-native';
import {
IS_PRODUCTION, DEFAULT_SESSION_KEY_EXPIRY_TIME, DEFAULT_SPENDING_LIMIT, MAX_SPENDING_LIMIT,
HIGH_SPEND_SESSION_KEY_EXPIRY_TIME, MEDIUM_SPEND_SESSION_KEY_EXPIRY_TIME
} from '../constants';
import CurrentUser from "../models/CurrentUser";
-import pricer from '../services/Pricer';
-import Toast from '../theme/components/NotificationToast';
import {LoadingModal} from '../theme/components/LoadingModalCover';
import {ostSdkErrors, WORKFLOW_CANCELLED_MSG} from '../services/OstSdkErrors';
import {ostErrors} from "../services/OstErrors";
@@ -14,7 +12,7 @@ import {VideoPlayPauseEmitter} from './Emitters'
const ON_USER_CANCLLED_ERROR_MSG = WORKFLOW_CANCELLED_MSG;
-const DEVICE_UNAUTHORIZED_ERROR_MSG = "Your device is not authorized to perform transactions";;
+const DEVICE_UNAUTHORIZED_ERROR_MSG = "Your device is not authorized to perform transactions";
const bnDefaultSpendingLimit = new BigNumber(DEFAULT_SPENDING_LIMIT);
const bnMaxSpendingLimit = new BigNumber(MAX_SPENDING_LIMIT);
const bnOne = new BigNumber(1);
diff --git a/src/helpers/cameraHelper.js b/src/helpers/cameraHelper.js
new file mode 100644
index 00000000..8399de6e
--- /dev/null
+++ b/src/helpers/cameraHelper.js
@@ -0,0 +1,68 @@
+import AppConfig from '../constants/AppConfig'
+import NavigationService from "../services/NavigationService";
+import Utilities from "../services/Utilities";
+import CurrentUser from "../models/CurrentUser";
+import { ostErrors } from "../services/OstErrors";
+import Pricer from "../services/Pricer";
+import ReduxGetters from "../services/ReduxGetters";
+import Toast from '../theme/components/NotificationToast';
+
+
+// creatorUserId is mandatory as without it token holder address can not be accessed.
+const getVideoReplyObject = (videoId, creatorUserId) => {
+ return {
+ videoType : AppConfig.videoTypes.reply,
+ videoId: videoId,
+ userId: creatorUserId,
+ amount: ReduxGetters.getBtAmountForReply(videoId),
+ videoReplyCount: ReduxGetters.getVideoReplyCount(videoId),
+ isChargeble: ReduxGetters.isVideoIsChargeable(videoId),
+ toTokenHolderAddress: ReduxGetters.getUser( creatorUserId ).ost_token_holder_address
+ };
+};
+
+
+const navigateToCamera = (videoId , userId , navigation) => {
+ let activeTab = NavigationService.getActiveTab();
+ let params = getVideoReplyObject ( videoId , userId);
+ Utilities.handleVideoUploadModal(activeTab, navigation, params);
+};
+
+const replyPreValidationAndMessage = (videoId , userId) => {
+
+ if(!videoId || !userId){
+ console.warn("replyPreValidationAndMessage missing videoId - " + videoId + "or userId - " + userId );
+ return false;
+ }
+
+ if(!CurrentUser.isUserActivated( true )){
+ return false;
+ }
+
+ const isReplyAllowed = ReduxGetters.isReplyAllowed(videoId) ,
+ isVideoUserActivated = Utilities.isUserActivated(ReduxGetters.getUserActivationStatus(userId))
+ ;
+
+ if( !isReplyAllowed || !isVideoUserActivated ){
+ Toast.show({
+ text: ostErrors.getUIErrorMessage("video_reply_not_allowed"),
+ icon: 'error'
+ });
+ return false;
+ }
+
+ const requiredPepo = ReduxGetters.getBtAmountForReply(videoId);
+
+ if(Pricer.getWeiToNumber(ReduxGetters.getBalance()) < Pricer.getWeiToNumber(requiredPepo)){
+ Toast.show({
+ text: ostErrors.getUIErrorMessage("video_reply_not_allowed_low_bal"),
+ icon: 'error'
+ });
+ return false ;
+ }
+
+ return true;
+
+}
+
+export { getVideoReplyObject , navigateToCamera , replyPreValidationAndMessage}
diff --git a/src/helpers/helpers.js b/src/helpers/helpers.js
index e0e6d203..91b51a60 100644
--- a/src/helpers/helpers.js
+++ b/src/helpers/helpers.js
@@ -33,6 +33,20 @@ function fetchUser(userId, onResponse, errorCallback, finallyCallback) {
});
}
+function fetchVideo( videoId , onResponse, onError, onComplete ){
+ return new PepoApi(`/videos/${videoId}`)
+ .get()
+ .then((res) => {
+ onResponse && onResponse(res);
+ })
+ .catch((error) => {
+ onError && onError(error);
+ })
+ .finally(() => {
+ onComplete && onComplete();
+ });
+}
+
function getSocialIcon(url, screen) {
let hostName = url && url.match(/^(?:https?:\/\/)?(?:[^@\/\n]+@)?([^:\/?\n]+)/im);
if ( !hostName || hostName.length < 2) {
@@ -53,4 +67,4 @@ function getHostName( url ){
return url.match(/^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/?\n]+)/im)[1];
}
-export { fetchUser, getHostName };
+export { fetchUser, getHostName , fetchVideo};
diff --git a/src/helpers/navigateTo.js b/src/helpers/navigateTo.js
index 3d6c0206..c2f54e01 100644
--- a/src/helpers/navigateTo.js
+++ b/src/helpers/navigateTo.js
@@ -41,6 +41,8 @@ class NavigateTo {
this.goToSupporters(goToObject.v.puid, payload);
} else if (goToObject && goToObject.pn === 'v') {
this.goToVideo(goToObject.v.vid, payload);
+ }else if (goToObject && goToObject.pn === 'rd') {
+ this.goToVideoReply(goToObject.v.rdi, payload);
} else if (goToObject && goToObject.pn === 'f') {
this.__navigate('Home', payload);
} else if (goToObject && goToObject.pn === 'nc') {
@@ -122,6 +124,21 @@ class NavigateTo {
}, timeOut)
};
+ goToVideoReply = (rdId, payload) => {
+ let timeOut = 0 ;
+ payload = payload || {};
+ payload['replyDetailId'] = rdId;
+ if(NavigationService.getActiveTab() != "Notification"){
+ timeOut = 100;
+ this.__navigate('NotificationScreen', payload);
+ }
+ //Once migrated to react-navigation version 4 remove the settimeout code
+ //as version 3 dosent provides navigation chaining.
+ setTimeout(()=> {
+ this.__push('VideoReplyPlayer', payload);
+ }, timeOut)
+ };
+
goToSupportings = (profileId, payload) => {
payload = payload || {};
payload['userId'] = profileId;
diff --git a/src/reducers/index.js b/src/reducers/index.js
index fc0be1b0..4743b9e0 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -10,6 +10,7 @@ export const {
hideModalCover,
showLoginPopover,
hideLoginPopover,
+ showConnectingLoginPopover,
showToast,
hideToast,
upsertUserEntities,
@@ -25,6 +26,9 @@ export const {
upsertUserStatEntities,
upsertVideoEntities,
upsertVideoStatEntities,
+ upsertReplyDetailEntities,
+ upsertCurrentUserVideoRelationEntities,
+ upsertCurrentUserReplyDetailRelationEntities,
upsertImageEntities,
upsertHomeFeedEntities,
updateBalance,
@@ -34,6 +38,7 @@ export const {
updatePepocorn,
updateExecuteTransactionStatus,
upsertVideoContributionEntities,
+ upsertReplyContributionEntities,
upsertUserContributionEntities,
upsertRecordedVideo,
clearRecordedVideo,
@@ -68,6 +73,9 @@ const defaultState = {
link_entities: {},
video_entities: {},
video_stat_entities: {},
+ reply_detail_entities: {},
+ current_user_video_relation_entities: {},
+ current_user_reply_detail_relation_entities: {},
video_description_entities: {},
image_entities: {},
home_feed_entities: {},
@@ -99,6 +107,9 @@ const logoutDefault = {
link_entities: {},
video_entities: {},
video_stat_entities: {},
+ reply_detail_entities: {},
+ current_user_video_relation_entities: {},
+ current_user_reply_detail_relation_entities: {},
video_description_entities: {},
image_entities: {},
home_feed_entities: {},
@@ -119,10 +130,14 @@ export const reducer = handleActions(
{
[showModal]: (state, action) => ({ ...state, modal: action.payload.modal }),
[showModalCover]: (state, action) => ({ ...state, modal_cover: action.payload.modal_cover }),
+
[showLoginPopover]: (state, action) => ({ ...state, login_popover: action.payload.login_popover }),
+ [showConnectingLoginPopover]: (state, action) => ({ ...state, login_popover: action.payload.login_popover }),
+ [hideLoginPopover]: (state, action) => ({ ...state, login_popover: action.payload.login_popover }),
+
[hideModal]: (state, action) => ({ ...state, modal: action.payload.modal }),
[hideModalCover]: (state, action) => ({ ...state, modal_cover: action.payload.modal_cover }),
- [hideLoginPopover]: (state, action) => ({ ...state, login_popover: action.payload.login_popover }),
+
[showToast]: (state, action) => ({ ...state, toast: action.payload.toast }),
[hideToast]: (state, action) => ({ ...state, toast: action.payload.toast }),
[upsertUserEntities]: (state, action) => ({
@@ -173,6 +188,18 @@ export const reducer = handleActions(
...state,
video_stat_entities: assignIn({}, state.video_stat_entities, action.payload.video_stat_entities)
}),
+ [upsertReplyDetailEntities]: (state, action) => ({
+ ...state,
+ reply_detail_entities: assignIn({}, state.reply_detail_entities, action.payload.reply_detail_entities)
+ }),
+ [upsertCurrentUserVideoRelationEntities]: (state, action) => ({
+ ...state,
+ current_user_video_relation_entities: assignIn({}, state.current_user_video_relation_entities, action.payload.current_user_video_relation_entities)
+ }),
+ [upsertCurrentUserReplyDetailRelationEntities]: (state, action) => ({
+ ...state,
+ current_user_reply_detail_relation_entities: assignIn({}, state.current_user_reply_detail_relation_entities, action.payload.current_user_reply_detail_relation_entities)
+ }),
[upsertVideoDescriptionEntities]: (state, action) => ({
...state,
video_description_entities: assignIn(
@@ -205,6 +232,14 @@ export const reducer = handleActions(
action.payload.video_contribution_entities
)
}),
+ [upsertReplyContributionEntities]: (state, action) => ({
+ ...state,
+ reply_contribution_entities: assignIn(
+ {},
+ state.reply_contribution_entities,
+ action.payload.reply_contribution_entities
+ )
+ }),
[upsertUserContributionEntities]: (state, action) => ({
...state,
user_contribution_entities: assignIn(
@@ -221,10 +256,22 @@ export const reducer = handleActions(
...state,
balance: action.payload.isPurchase
}),
- [updatePricePoints]: (state, action) => ({
- ...state,
- price_points: action.payload.price_points
- }),
+ [updatePricePoints]: (state, action) => {
+ //Make sure price_points is not null;
+ if (!action.payload.price_points) {
+ return {...state};
+ }
+
+ // Make sure response has keys;
+ if ( !Object.keys(action.payload.price_points).length ) {
+ return {...state};
+ }
+
+ return {
+ ...state,
+ price_points: action.payload.price_points
+ };
+ },
[updateToken]: (state, action) => ({
...state,
token: action.payload.token
diff --git a/src/services/CameraWorker.js b/src/services/CameraWorker.js
index a262e788..af2e645c 100644
--- a/src/services/CameraWorker.js
+++ b/src/services/CameraWorker.js
@@ -2,6 +2,9 @@ import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import RNFS from 'react-native-fs';
import Store from '../store';
+import deepGet from 'lodash/get';
+import clone from 'lodash/clone';
+
import {
upsertRecordedVideo,
@@ -20,7 +23,11 @@ import videoUploaderComponent from './CameraWorkerEventEmitter';
import createObjectForRedux from '../helpers/createObjectForRedux';
import Toast from '../theme/components/NotificationToast';
import CurrentUser from '../models/CurrentUser';
-
+import DataContract from "../constants/DataContract";
+import {TransactionExecutor} from './TransactionExecutor';
+import { ostSdkErrors } from '../services/OstSdkErrors';
+import AppConfig from '../constants/AppConfig';
+import { fetchVideo } from '../helpers/helpers';
const recordedVideoStates = [
'raw_video',
'compressed_video',
@@ -28,7 +35,10 @@ const recordedVideoStates = [
'cover_image',
's3_cover_image',
'video_desc',
- 'video_link'
+ 'video_link',
+ 'reply_amount',
+ 'video_type',
+ 'reply_obj'
];
const processingStatuses = [
@@ -87,6 +97,20 @@ class CameraWorker extends PureComponent {
}
}
+ VideoUploadStatusToProcessing = () => {
+ if (this.isCleanUpCalled || this.props.recorded_video.do_discard || ! this.props.recorded_video.do_upload) {
+ console.log('VideoUploadStatusToProcessing:: return condition');
+ return;
+ }
+ Store.dispatch(videoInProcessing(true));
+ videoUploaderComponent.emit('show');
+ };
+
+ VideoUploadStatusToNotProcessing = () => {
+ Store.dispatch(videoInProcessing(false));
+ videoUploaderComponent.emit('hide');
+ };
+
async processVideo() {
// Early exit
if ( ! this.props.currentUserId || Object.keys(this.props.recorded_video).length === 0) {
@@ -113,28 +137,320 @@ class CameraWorker extends PureComponent {
}
if (this.props.recorded_video.do_upload) {
- !ReduxGetters.getVideoProcessingStatus() && Store.dispatch(videoInProcessing(true));
+ if (!ReduxGetters.getVideoProcessingStatus()) {
+ console.log('processVideo :: VideoUploadStatusToProcessing');
+ this.VideoUploadStatusToProcessing();
+ }
console.log(
'processVideo :: Got upload consent. Uploading video and cover image to s3 and attempting post Video with Cover Image...'
);
- this.updateProfileViewRawVideo();
- await this.uploadVideo();
- await this.uploadCoverImage();
- await this.postVideoWithCoverImage();
+ await this.processVideoBasedOnType ();
+
}
}
- updateProfileViewRawVideo() {
- if (this.props.recorded_video.cover_image && !this.props.recorded_video.video_s3_upload_processing) {
- // this.updateProfileViewVideo(this.props.recorded_video.cover_image, this.props.recorded_video.raw_video);
+
+ processVideoBasedOnType = async () => {
+ let videoType = this.props.recorded_video.video_type;
+ if (! videoType){
+ return;
+ }
+ if (videoType === 'post'){
+ await this.processPostVideo();
+ } else if (videoType === 'reply'){
+ await this.processReplyVideo();
}
+ };
+
+
+ processPostVideo = async () => {
+ await this.uploadVideo();
+ await this.uploadCoverImage();
+ await this.postVideoToPepoApi();
+ };
+
+
+ processReplyVideo = async () => {
+ console.log(
+ '-----processReplyVideo--------'
+ );
+
+ // let sessionCreated = await this.ensureSession();
+ //
+ // if (! sessionCreated) {
+ // return ;
+ // }
+ await this.uploadReplyVideo();
+ await this.executeTransaction()
+
+
+ };
+
+ videoUploadedSuccessCallback = ( ostWorkflowContext, ostWorkflowEntity ) => {
+ console.log('CameraWorker.videoUploadedSuccessCallback');
+ Toast.show({
+ text: 'Your video uploaded successfully.',
+ icon: 'success',
+ imageUri: this.props.recorded_video.cover_image
+ });
+ this.executeTx = false;
+ Store.dispatch(
+ upsertRecordedVideo({
+ do_discard: true,
+ pepo_api_posting: false,
+ })
+ );
+ this.fetchParentVideo();
+ };
+
+ fetchParentVideo = () => {
+ const videoId = deepGet(this.props.recorded_video , 'reply_obj.replyReceiverVideoId');
+ fetchVideo( videoId );
+ };
+
+ onFlowInterrupt = (ostWorkflowContext, error) => {
+ console.log('CameraWorker.onFlowInterrupt', ostWorkflowContext, error);
+ console.log('onFlowInterrupt::VideoUploadStatusToNotProcessing');
+ this.executionFailed();
+ Toast.show({
+ text: ostSdkErrors.getErrorMessage(ostWorkflowContext, error),
+ icon: 'error'
+ });
+ };
+
+
+ executionFailed = () => {
+ Store.dispatch(
+ upsertRecordedVideo({
+ do_upload: false,
+ go_for_tx: false
+ })
+ );
+ this.executeTx = false;
+ this.VideoUploadStatusToNotProcessing();
+ this.executingTx = false;
}
+
+ getSdkMetaProperties = () => {
+ const metaProperties = clone(AppConfig.replyMetaProperties);
+ let parentVideoId = deepGet(this.props.recorded_video , 'reply_obj.replyReceiverVideoId'),
+ replyDetailId = deepGet(this.props.recorded_video , 'reply_obj.replyDetailId')
+ ;
+
+ if (! parentVideoId || ! replyDetailId ){
+ return ;
+ }
+
+ let details = `vi_${parentVideoId} `;
+ details += `rdi_${replyDetailId}`;
+ metaProperties['details'] = details;
+ return metaProperties;
+ };
+
+ isReplyChargeable = () => {
+ let isChargeable = deepGet (this.props.recorded_video, 'reply_obj.isChargeble'),
+ amountToSendWithReply = deepGet(this.props.recorded_video, 'reply_obj.amountToSendWithReply');
+ return isChargeable && amountToSendWithReply != '0';
+ };
+
+ onPlatfromAcknowledgeComplete = (videoId) => {
+ new PepoApi(`/videos/${videoId}`)
+ .get()
+ .then((res) => {})
+ .catch((error) => {});
+ };
+
+
+
+
+ executeTransaction = () => {
+
+ if (this.checkIfDiscardedAndClean()){
+ return;
+ }
+
+ let goForTx = this.props.recorded_video.go_for_tx,
+ doDiscard = this.props.recorded_video.do_discard,
+ receiverUserId = deepGet (this.props.recorded_video, 'reply_obj.replyReceiverUserId'),
+ amountToSendWithReply = deepGet(this.props.recorded_video, 'reply_obj.amountToSendWithReply'),
+ toTokenHolderAddress = deepGet(this.props.recorded_video,'reply_obj.toTokenHolderAddress' ),
+ parentVideoId = deepGet(this.props.recorded_video , 'reply_obj.replyReceiverVideoId');
+ if (! goForTx || ! receiverUserId || doDiscard || this.executeTx ){
+ return;
+ }
+ this.executeTx = true;
+ console.log('executeTransaction::VideoUploadStatusToProcessing');
+ this.VideoUploadStatusToProcessing();
+ console.log('CameraWorker.executeTransaction');
+
+ if (! this.isReplyChargeable()) {
+ this.videoUploadedSuccessCallback();
+ return;
+ }
+
+ upsertRecordedVideo({
+ executing_tx: true
+ });
+
+
+ let callbacks = {
+ onRequestAcknowledge: this.videoUploadedSuccessCallback,
+ onFlowInterrupt: this.onFlowInterrupt,
+ onPlatfromAcknowledgeComplete: () => {this.onPlatfromAcknowledgeComplete(parentVideoId)}
+ };
+ let config = {metaProperties: this.getSdkMetaProperties()};
+ let txExecutor = new TransactionExecutor(config, callbacks);
+ txExecutor.sendTransactionToSdk( amountToSendWithReply, toTokenHolderAddress, false);
+ // todo : Execute transaction code. call clean up after that.
+
+ };
+
+ checkIfDiscardedAndClean = () => {
+ if (this.props.recorded_video.do_discard) {
+ console.log(
+ 'processVideo :: Discarding video... Cleaning up Async, Stop Compression, remove files from cache, cleanup Redux'
+ );
+ this.cleanUp();
+ return true;
+ }
+ };
+
+
+ uploadReplyVideo = async () => {
+ console.log('CameraWorker.uploadReplyVideo');
+ await this.uploadVideo();
+ await this.uploadCoverImage();
+ await this.postReplyVideoToPepoApi() ;
+ };
+
+
+ postReplyVideoToPepoApi = async () => {
+
+ if (this.checkIfDiscardedAndClean()){
+ return;
+ }
+
+ let readyForTx = deepGet(this.props.recorded_video , 'go_for_tx' ),
+ parentVideoId = deepGet(this.props.recorded_video , 'reply_obj.replyReceiverVideoId');
+
+ if ( readyForTx || !parentVideoId ) {
+ // we have reply OR we dont have video Id
+ return true
+ }
+
+ if (
+ this.props.recorded_video.s3_video &&
+ !this.props.recorded_video.pepo_api_posting &&
+ !this.postToPepoApi
+ ) {
+ this.postToPepoApi = true;
+ let videoInfo = await RNFS.stat(this.props.recorded_video.compressed_video);
+ let videoSize = videoInfo.size;
+ let imageInfo, imageSize;
+ if(this.props.recorded_video.cover_image !== INVALID){
+ imageInfo = await RNFS.stat(this.props.recorded_video.cover_image);
+ imageSize = imageInfo.size;
+ }
+ console.log('CameraWorker.postReplyVideoToPepoApi');
+ Store.dispatch(
+ upsertRecordedVideo({
+ pepo_api_posting: true
+ })
+ );
+
+ let payloadWithoutImage = {
+ video_url: this.props.recorded_video.s3_video,
+ video_description: this.props.recorded_video.video_desc,
+ link: this.props.recorded_video.video_link,
+ video_width: appConfig.cameraConstants.VIDEO_WIDTH,
+ video_height: appConfig.cameraConstants.VIDEO_HEIGHT,
+ image_width: appConfig.cameraConstants.VIDEO_WIDTH,
+ image_height: appConfig.cameraConstants.VIDEO_HEIGHT,
+ video_size: videoSize,
+ parent_kind: 'video',
+ parent_id: parentVideoId
+ };
+
+ let payload = payloadWithoutImage;
+
+ if(this.props.recorded_video.cover_image !== INVALID){
+ payload = {
+ ...payload,
+ poster_image_url: this.props.recorded_video.s3_cover_image,
+ image_size: imageSize
+ };
+ }
+
+ let replyDetailId = deepGet(this.props.recorded_video , 'reply_obj.replyDetailId' );
+ if (replyDetailId) {
+ payload['reply_detail_id'] = replyDetailId;
+ }
+
+ new PepoApi(`/replies`)
+ .post(payload)
+ .then((responseData) => {
+ Store.dispatch(
+ upsertRecordedVideo({
+ pepo_api_posting: false
+ })
+ );
+
+ if (responseData.success && responseData.data) {
+ console.log('reply sent Successfully to Pepo Api');
+ let resultType = deepGet(responseData, DataContract.common.resultType),
+ reply = deepGet(responseData, `data.${resultType}` );
+
+ if (reply && reply.length > 0 ){
+ let replyObj = deepGet(this.props.recorded_video , 'reply_obj' );
+ replyObj['replyDetailId'] = reply[0].payload.reply_detail_id;
+ Store.dispatch(
+ upsertRecordedVideo({
+ reply_obj: replyObj,
+ go_for_tx: true
+ })
+ );
+ }
+ } else {
+ Toast.show({
+ text: responseData.err.msg,
+ icon: 'error'
+ });
+ console.log('/replies:::VideoUploadStatusToNotProcessing');
+ this.VideoUploadStatusToNotProcessing();
+ Store.dispatch(
+ upsertRecordedVideo({
+ do_upload: false
+ })
+ );
+ this.executeTx = false;
+ }
+ this.postToPepoApi = false;
+ })
+ .catch(() => {
+ this.postToPepoApi = false;
+ Store.dispatch(
+ upsertRecordedVideo({
+ pepo_api_posting: false
+ })
+ );
+ Toast.show({
+ text: 'Video upload failed - Try Again',
+ icon: 'error'
+ });
+ });
+ }
+ };
+
async cleanUp() {
// stop ffmpge processing
- videoUploaderComponent.emit('hide');
- Store.dispatch(videoInProcessing(false));
+ if (this.isCleanUpCalled){
+ return;
+ }
+ this.isCleanUpCalled = true;
+ console.log('cleanUp:::VideoUploadStatusToNotProcessing');
+ this.VideoUploadStatusToNotProcessing();
FfmpegProcesser.cancel();
// remove files from cache,
await this.removeFile(this.props.recorded_video.raw_video);
@@ -144,6 +460,7 @@ class CameraWorker extends PureComponent {
utilities.removeItem(this.getCurrentUserRecordedVideoKey());
// cleanup Redux
Store.dispatch(clearRecordedVideo());
+ this.isCleanUpCalled = false;
}
async removeFile(file) {
@@ -209,7 +526,8 @@ class CameraWorker extends PureComponent {
compression_processing: true
})
);
- videoUploaderComponent.emit('show');
+ console.log('compressVideo:::VideoUploadStatusToProcessing');
+ this.VideoUploadStatusToProcessing();
FfmpegProcesser.init(this.props.recorded_video.raw_video);
FfmpegProcesser.compress()
@@ -261,6 +579,10 @@ class CameraWorker extends PureComponent {
}
async uploadVideo() {
+ if (this.checkIfDiscardedAndClean()){
+ return;
+ }
+
!this.props.recorded_video.compressed_video && (await this.compressVideo());
if (
@@ -273,8 +595,9 @@ class CameraWorker extends PureComponent {
video_s3_upload_processing: true
})
);
- videoUploaderComponent.emit('show');
- this.uploadToS3(this.props.recorded_video.compressed_video, 'video')
+ console.log('uploadVideo:::VideoUploadStatusToProcessing');
+ this.VideoUploadStatusToProcessing();
+ return this.uploadToS3(this.props.recorded_video.compressed_video, 'video')
.then((s3Video) => {
console.log('uploadVideo success :: s3Video', s3Video);
Store.dispatch(
@@ -296,6 +619,11 @@ class CameraWorker extends PureComponent {
}
async uploadCoverImage() {
+
+ if (this.checkIfDiscardedAndClean()){
+ return;
+ }
+
!this.props.recorded_video.cover_image && (await this.createThumbnail());
if (
this.props.recorded_video.cover_image &&
@@ -309,7 +637,7 @@ class CameraWorker extends PureComponent {
})
);
- this.uploadToS3(this.props.recorded_video.cover_image, 'image')
+ return this.uploadToS3(this.props.recorded_video.cover_image, 'image')
.then((s3CoverImage) => {
console.log('uploadCoverImage success :: s3CoverImage', s3CoverImage);
Store.dispatch(
@@ -335,7 +663,12 @@ class CameraWorker extends PureComponent {
return uploadToS3.perform();
}
- async postVideoWithCoverImage() {
+ async postVideoToPepoApi() {
+
+ if (this.checkIfDiscardedAndClean()){
+ return;
+ }
+
if (
this.props.recorded_video.s3_video &&
!this.props.recorded_video.pepo_api_posting &&
@@ -364,7 +697,8 @@ class CameraWorker extends PureComponent {
video_height: appConfig.cameraConstants.VIDEO_HEIGHT,
image_width: appConfig.cameraConstants.VIDEO_WIDTH,
image_height: appConfig.cameraConstants.VIDEO_HEIGHT,
- video_size: videoSize
+ video_size: videoSize,
+ per_reply_amount_in_wei: this.props.recorded_video.reply_amount
};
let payload = payloadWithoutImage;
@@ -377,7 +711,7 @@ class CameraWorker extends PureComponent {
};
}
- new PepoApi(`/users/${this.props.currentUserId}/fan-video`)
+ return new PepoApi(`/users/${this.props.currentUserId}/fan-video`)
.post(payload)
.then((responseData) => {
if (responseData.success && responseData.data) {
@@ -393,6 +727,9 @@ class CameraWorker extends PureComponent {
pepo_api_posting: false
})
);
+ } else {
+ console.log('/fanvideo:::VideoUploadStatusToNotProcessing');
+ this.VideoUploadStatusToNotProcessing();
}
this.postToPepoApi = false;
})
@@ -436,6 +773,6 @@ class CameraWorker extends PureComponent {
}
}
-const mapStateToProps = ({ recorded_video }) => ({ recorded_video, currentUserId: CurrentUser.getUserId() });
+const mapStateToProps = ({ recorded_video }) => ({ recorded_video, currentUserId: CurrentUser.getUserId(), currentOstUserId: CurrentUser.getOstUserId() });
export default connect(mapStateToProps)(CameraWorker);
diff --git a/src/services/FetchServices.js b/src/services/FetchServices.js
index e5f8c32a..ab4ecbfd 100644
--- a/src/services/FetchServices.js
+++ b/src/services/FetchServices.js
@@ -23,7 +23,7 @@ class FetchServices {
}
initVals() {
-
+ //NOTE: If adding removing vals from here, update cloneWithData method.
this.isFetching = false;
this.hasNextPage = true;
this.nextPagePayload = null;
@@ -160,6 +160,20 @@ class FetchServices {
return new Constructor(this.url, this.extraParams, this.id, this.options);
}
+ cloneWithData() {
+ let Constructor = this.constructor;
+ let newInstance = new Constructor(this.url, this.extraParams, this.id);
+ const seedData = this.result;
+
+ newInstance.processResults( this.results || []);
+ newInstance.isFetching = false;
+ newInstance.hasNextPage = this.hasNextPage;
+ newInstance.nextPagePayload = this.nextPagePayload;
+ newInstance.meta = Object.assign({}, this.meta);
+ console.log("newInstance.results.length", newInstance.results.length);
+ return newInstance;
+ }
+
cloneInstance(){
return Object.assign( Object.create( Object.getPrototypeOf(this)), this);
}
diff --git a/src/services/NavigationService.js b/src/services/NavigationService.js
index 354dcc9c..fc166760 100644
--- a/src/services/NavigationService.js
+++ b/src/services/NavigationService.js
@@ -43,6 +43,26 @@ const findCurrentRoute = (navState) => {
}
}
+const getStackNumber = (routes , index , num , whiteListedStacks) => {
+ if (typeof index !== "number" || !whiteListedStacks.length) {
+ return num;
+ } else {
+ const currentRoute = routes[index] || {};
+ const innerRoutes = currentRoute["routes"] || []
+ for(let cnt = 0 ; cnt < innerRoutes.length ; cnt++){
+ const route = innerRoutes[cnt];
+ const routeName = route["routeName"];
+ const indexOfItem = whiteListedStacks.indexOf(routeName);
+ if(indexOfItem > -1){
+ num ++;
+ whiteListedStacks.splice(indexOfItem, 1);
+ }
+ num = getStackNumber( route["routes"], route["index"], num , whiteListedStacks);
+ }
+ return num;
+ }
+}
+
function reset(navigation) {
if(!navigation) return;
navigation.dispatch(StackActions.popToTop("Notification"));
@@ -56,5 +76,6 @@ export default {
getTopLevelNavigator,
findCurrentRoute,
getActiveTab,
+ getStackNumber,
reset
};
diff --git a/src/services/NavigationStateHandler.js b/src/services/NavigationStateHandler.js
index beaf2809..359c6e9f 100644
--- a/src/services/NavigationStateHandler.js
+++ b/src/services/NavigationStateHandler.js
@@ -5,7 +5,7 @@ import Colors from "../theme/styles/Colors";
import NavigationService from './NavigationService';
import AppConfig from '../constants/AppConfig';
-const routesWithoutStatusBar = ['Home', 'HomeScreen', 'VideoPlayer', 'CaptureVideo', 'CaptureImageScreen', 'ImageGalleryScreen', 'UserVideoHistory', 'FullScreenVideoCollection'];
+const routesWithoutStatusBar = ['Home', 'HomeScreen', 'VideoPlayer', 'CaptureVideo', 'CaptureImageScreen', 'ImageGalleryScreen', 'UserVideoHistory', 'VideoReplies', 'FullScreenVideoCollection', 'FullScreenReplyCollection', 'VideoReplyPlayer'];
const typesToIgnore = ['Navigation/COMPLETE_TRANSITION', 'Navigation/MARK_DRAWER_SETTLING', 'Navigation/MARK_DRAWER_IDLE', 'Navigation/DRAWER_CLOSED'];
const routesAnalyticsMap = AppConfig.routesAnalyticsMap;
@@ -16,7 +16,7 @@ const StatusBarShow = () => {
StatusBar.setTranslucent(false);
}
- if(Platform.OS == "ios"){
+ if(Platform.OS === "ios"){
StatusBar.setBarStyle("dark-content")
}
diff --git a/src/services/OstErrors.js b/src/services/OstErrors.js
index 7d837bea..f7093352 100644
--- a/src/services/OstErrors.js
+++ b/src/services/OstErrors.js
@@ -5,7 +5,8 @@ const sdkErrors = {
USER_NOT_ACTIVATED: 'User is not activated.',
SESSION_NOT_FOUND: 'Please check your spending limit.',
DEVICE_UNAUTHORIZED: 'Device is unauthorized.',
- GENERAL_ERROR: 'Something went wrong please try again later.'
+ GENERAL_ERROR: 'Something went wrong please try again later.',
+ WORKFLOW_CANCELLED: 'Workflow Cancelled'
};
const UIErros = {
@@ -35,12 +36,14 @@ const UIErros = {
email_error: 'Enter a valid email.',
device_unathorized: "Your device is not authorized. Please authorized the device.",
top_not_available: "Topup not available at this time, we are looking into it. Please check back later.",
- delete_video_error:"Unable to delete Video at this moment.",
+ delete_video_error:"Unable to delete Video at this moment.",
redemption_error : "Failed to redeem, please try again later",
max_pepocorns: `Sorry, you don't have enough Pepo Coins to buy this many ${Utilities.getPepoCornsName()}`,
price_point_validation_failed: `Sorry, you don't have enough Pepo Coins to buy this many ${Utilities.getPepoCornsName()}`,
min_pepocorns: `Minimum amount allowed is 1 ${Utilities.getPepoCornsName()}.`,
- bt_exceeds_bal_amount_error : `Sorry, you don't have enough Pepo Coins for this transactions.`
+ bt_exceeds_bal_amount_error : `Sorry, you don't have enough Pepo Coins for this transactions.`,
+ video_reply_not_allowed: 'Reply is not allowed for this video.',
+ video_reply_not_allowed_low_bal: "Insufficient balance for reply"
};
const UIWhitelistedErrorCode = {
diff --git a/src/services/Pagination.js b/src/services/Pagination.js
index 9329cb97..89510490 100644
--- a/src/services/Pagination.js
+++ b/src/services/Pagination.js
@@ -111,6 +111,10 @@ class Pagination {
console.log("this.fetchServices.results" ,this.fetchServices.results );
}
+ addItems( items ) {
+ this.getResults().unshift( items );
+ }
+
};
diff --git a/src/services/PepoApi.js b/src/services/PepoApi.js
index 68a0a7eb..3f7b57dc 100644
--- a/src/services/PepoApi.js
+++ b/src/services/PepoApi.js
@@ -25,6 +25,7 @@ export default class PepoApi {
'User-Agent': DeviceInfo.getUserAgent(),
'X-PEPO-DEVICE-OS': Platform.OS,
'X-PEPO-DEVICE-OS-VERSION': DeviceInfo.getSystemVersion(),
+ 'X-PEPO-DEVICE-ID': DeviceInfo.getUniqueID(),
'X-PEPO-BUILD-NUMBER': DeviceInfo.getBuildNumber(),
'X-PEPO-APP-VERSION': DeviceInfo.getVersion()
}
diff --git a/src/services/PepoSocket.js b/src/services/PepoSocket.js
index 2f811571..1efc22a5 100644
--- a/src/services/PepoSocket.js
+++ b/src/services/PepoSocket.js
@@ -1,7 +1,9 @@
import io from 'socket.io-client';
-import PepoApi from '../services/PepoApi';
+import { YellowBox } from 'react-native';
import deepGet from 'lodash/get';
+import PepoApi from '../services/PepoApi';
+
import { upsertNotificationUnread } from '../actions';
import Store from '../store';
@@ -23,6 +25,11 @@ export default class PepoSocket {
this.socket = null;
this.isConnecting = false;
this.attempt = 0;
+ // Supress un-actionable warnings
+ YellowBox.ignoreWarnings(['Setting a timer']);
+ YellowBox.ignoreWarnings([
+ 'Unrecognized WebSocket connection option(s) `agent`, `perMessageDeflate`, `pfx`, `key`, `passphrase`, `cert`, `ca`, `ciphers`, `rejectUnauthorized`. Did you mean to put these under `headers`?'
+ ])
}
setConnectionParams(response) {
diff --git a/src/services/PixelCall.js b/src/services/PixelCall.js
index 60bfedf9..3ab02af7 100644
--- a/src/services/PixelCall.js
+++ b/src/services/PixelCall.js
@@ -2,8 +2,10 @@ import {Platform, Dimensions} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import qs from 'qs';
import assignIn from 'lodash/assignIn';
-import Store from '../store';
+import momentTimezone from 'moment-timezone';
+
import { TRACKER_ENDPOINT } from '../constants/index';
+import CurrentUser from "../models/CurrentUser";
const keyAliasMap = {
t_version: 'v',
@@ -12,7 +14,6 @@ const keyAliasMap = {
u_service_id: 'serid',
u_session_id: 'sesid',
u_timezone: 'tz',
- e_timestamp: 'ts',
e_entity: 'ee',
e_action: 'ea',
p_type: 'pt',
@@ -32,12 +33,11 @@ const keyAliasMap = {
};
const staticData = {
- t_version: 1.0,
- t_gid: 'placeholder_t_gid',
+ t_version: 2,
+ t_gid: DeviceInfo.getUniqueID(),
u_service_id: 1,
u_session_id: 'placeholder_u_session_id',
- u_timezone: DeviceInfo.getTimezone(),
- e_timestamp: Math.round((new Date).getTime()/1000),
+ u_timezone: momentTimezone.tz(DeviceInfo.getTimezone()).utcOffset(),
device_id: DeviceInfo.getUniqueID(),
device_model: DeviceInfo.getModel(),
device_platform: DeviceInfo.getSystemVersion(),
@@ -45,19 +45,19 @@ const staticData = {
device_language: DeviceInfo.getDeviceLocale(),
device_width: Dimensions.get('window').width,
device_height: Dimensions.get('window').height,
- user_agent: DeviceInfo.getUserAgent()
+ device_type: 'mobile_app',
+ user_agent: DeviceInfo.getUserAgent(),
+ mobile_app_version: DeviceInfo.getVersion()
};
-if(Store.getState().current_user.id){
- staticData.u_id = Store.getState().current_user.id;
- staticData.e_data_json.user_id = Store.getState().current_user.id;
-}
+const mandatoryKeys = ['e_entity', 'e_action', 'p_type'];
const makeCompactData = params => {
let compactData = {};
for(var key in params){
if (params.hasOwnProperty(key)) {
- compactData[keyAliasMap[key]] = typeof params[key] === 'object' ? JSON.stringify(params[key]) : params[key];
+ let keyName = keyAliasMap[key] ? keyAliasMap[key] : key;
+ compactData[keyName] = typeof params[key] === 'object' ? JSON.stringify(params[key]) : params[key];
}
}
return compactData;
@@ -68,15 +68,33 @@ export default (data) => {
// Extend outer data with staticData
let pixelData = assignIn({}, staticData, data);
+ // Add user context (if any) else bail out
+ let currentUserId = CurrentUser.getUserId();
+ if(!currentUserId) return;
+ pixelData.u_id = currentUserId;
+
+ // Validate and bail out on fail
+ for(var mi = 0; mi < mandatoryKeys.length; mi++){
+ if(!pixelData[mandatoryKeys[mi]]){
+ console.log(`PixelCall validation failed. Mandatory key ${mandatoryKeys[mi]} missing.`);
+ return;
+ }
+ }
+ for(var key in pixelData){
+ if (pixelData.hasOwnProperty(key) && !pixelData[key]) {
+ console.log(`PixelCall validation failed. Invalid value of ${mandatoryKeys[mi]}.`);
+ return;
+ }
+ }
+
// Compact data
let compactData = makeCompactData(pixelData);
- // Log
- let ts = (new Date).getTime();
- console.log(`PixelCall (${ts}) URL: ${TRACKER_ENDPOINT}, data: `, compactData);
-
// Fire the fetch call
- fetch(`${TRACKER_ENDPOINT}?${qs.stringify(compactData)}`)
- .then((response) => console.log(`PixelCall (${ts}) fetch request complete!`))
- .catch((error) => console.log(`PixelCall (${ts}) fetch error: `, error));
+ fetch(`${TRACKER_ENDPOINT}?${qs.stringify(compactData)}`, {
+ headers: {
+ 'User-Agent': DeviceInfo.getUserAgent()
+ }
+ }).then((response) => console.log(`PixelCall to URL: ${TRACKER_ENDPOINT} completed with data: `, compactData))
+ .catch((error) => console.log(`PixelCall fetch error: `, error));
}
diff --git a/src/services/PriceOracle.js b/src/services/PriceOracle.js
index d2e4e25e..42a8f210 100644
--- a/src/services/PriceOracle.js
+++ b/src/services/PriceOracle.js
@@ -5,11 +5,21 @@ const btPrecession = 2;
export default class PriceOracle {
constructor(token, pricePoints) {
- if (!token || !token.conversion_factor || !pricePoints) {
- return null;
+ if ( !token ) {
+ //Assign token to an empty object so that fallback values apply.
+ token = {};
}
- this.conversionFactor = token.conversion_factor;
+ if ( !pricePoints ) {
+ //Assign pricePoints to an empty object so that fallback values apply.
+ pricePoints = {};
+ }
+
+ ///NOTE: If you are wondering why fall back is 1, Ask Ashutosh.
+ this.conversionFactor = token.conversion_factor || 1;
+
+ ///NOTE: If you are wondering why fall back is 18, Ask Ashutosh.
this.decimals = token.decimal || 18;
+
this.usdPricePoint = pricePoints['USD'];
}
diff --git a/src/services/Pricer.js b/src/services/Pricer.js
index dfbcfd0d..0c653d47 100644
--- a/src/services/Pricer.js
+++ b/src/services/Pricer.js
@@ -6,14 +6,16 @@ import PriceOracle from './PriceOracle';
import ReduxGetter from "./ReduxGetters";
import numeral from "numeral";
import OstWalletSdkHelper from '../helpers/OstWalletSdkHelper';
-import PepoApi from './PepoApi';
import DataContract from '../constants/DataContract';
import BigNumber from 'bignumber.js';
-let CurrentUser;
+let CurrentUser, PepoApi;
import('../models/CurrentUser').then((imports) => {
CurrentUser = imports.default;
});
+import('./PepoApi').then((imports) => {
+ PepoApi = imports.default;
+});
let ostErrors;
import('./OstErrors').then((imports) => {
@@ -94,6 +96,10 @@ class Pricer {
toDisplayAmount(amount) {
if(isNaN(amount)) return amount;
+ if(amount <= 0.0000001 ){
+ amount = parseInt(amount);
+ amount = amount.toFixed(2);
+ }
return numeral(amount).format('0[.]00a') || 0;
}
@@ -106,10 +112,14 @@ class Pricer {
}
}
+ getWeiToNumber = ( val ) => {
+ return val && Math.floor(Number(this.getFromDecimal(val))) || 0;
+ } ;
+
getBtFromPepoCornsInWei( pepoCorns , step , pepoInWeiPerStep){
if(!pepoCorns || !step || !pepoInWeiPerStep ) return "0";
let pepoInEthPerStep = this.getFromDecimal(pepoInWeiPerStep); //Normalize to ETH
- let pepoInEthPerStepBN = BigNumber( pepoInEthPerStep ); //Convert to BN
+ let pepoInEthPerStepBN = BigNumber( pepoInEthPerStep ); //Convert to BN
let amountBn = BigNumber(pepoCorns).dividedBy(step) ; //Get amount in BN
amountBn = pepoInEthPerStepBN.multipliedBy(amountBn).toString(10); //Get pepo in ETH
amountBn = this.getToDecimal( amountBn ); // Convert to WEI
diff --git a/src/services/ReduxGetters.js b/src/services/ReduxGetters.js
index 26581708..82d97f9b 100644
--- a/src/services/ReduxGetters.js
+++ b/src/services/ReduxGetters.js
@@ -42,6 +42,10 @@ class ReduxGetters {
state = state || Store.getState();
size = size || appConfig.videoConstant.videoImageWidth;
let posterImageId = deepGet(state, `video_entities.id_${id}.poster_image_id`);
+ return this.getImageUrl(posterImageId, state, size);
+ }
+
+ getImageUrl( posterImageId, state, size) {
return (
deepGet(state, `image_entities.id_${posterImageId}.resolutions.${size}.url`) ||
deepGet(state, `image_entities.id_${posterImageId}.resolutions.original.url`)
@@ -50,13 +54,14 @@ class ReduxGetters {
getUserName(id, state) {
state = state || Store.getState();
- return deepGet(state, `user_entities.id_${id}.user_name`);
+ return deepGet(state, `user_entities.id_${id}.user_name`, "");
}
getUserTwitterHandle(id, state) {
state = state || Store.getState();
return deepGet(state, `twitter_entities.id_${id}.handle`);
}
+
getUserTwitterHandleLink(id, state) {
state = state || Store.getState();
return deepGet(state, `twitter_entities.id_${id}.link`);
@@ -123,10 +128,30 @@ class ReduxGetters {
return deepGet(state, `video_stat_entities.id_${id}.description_id`);
}
+ getVideoReplyCount(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `video_stat_entities.id_${id}.total_video_replies`, 0);
+ }
+
+ getBtAmountForReply(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `video_stat_entities.id_${id}.per_reply_amount_in_wei`, 0);
+ }
+
+ isReplyAllowed(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `video_stat_entities.id_${id}.is_reply_allowed`, true);
+ }
+
+ getVideoCreatorUserId(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `video_stat_entities.id_${id}.creator_user_id`, true);
+ }
+
getTappedIncludesEntity(videoId, tappedText) {
let lowercasedText = tappedText.toLowerCase();
let state = Store.getState();
- return deepGet(state, `video_description_entities.id_${videoId}.includes.${lowercasedText}`);
+ return deepGet(state, `video_description_entities.id_${videoId}.includes.${lowercasedText}`) || deepGet(state, `video_description_entities.id_${videoId}.includes.${tappedText}`);
}
getVideoLink(id, state) {
@@ -170,6 +195,12 @@ class ReduxGetters {
return deepGet(Store.getState(), `recorded_video`);
}
+ getRecordedVideoType() {
+ return deepGet(Store.getState(), `recorded_video.video_type`);
+ }
+
+
+
getRecordedVideoCurrentProcess() {
let processing = [];
if (deepGet(Store.getState(), `recorded_video.cover_capture_processing`)) {
@@ -187,6 +218,7 @@ class ReduxGetters {
return processing.join(', ');
}
+
getUserCoverVideoId(id, state) {
state = state || Store.getState();
if (deepGet(state, `user_profile_entities.id_${id}.cover_video_id`)) {
@@ -402,11 +434,6 @@ class ReduxGetters {
return deepGet(state, `user_entities.id_${id}.status`, '').toLowerCase() == appConfig.userStatusMap.inActive;
}
- isVideoDeleted(id, state) {
- state = state || Store.getState();
- return deepGet(state, `video_entities.id_${id}.status`, '').toLowerCase() == appConfig.videoStatusMap.deleted;
- }
-
getUSDPrice(state){
state = state || Store.getState();
return deepGet(state, "price_points.OST.USD");
@@ -422,6 +449,110 @@ class ReduxGetters {
return deepGet(state, `tag_entities.id_${id}`);
}
+ getReplyEntity(id, state) {
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}`);
+ }
+
+ getReplyBt(id, state) {
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.total_amount_raised_in_wei`);
+ }
+
+ getReplyKind(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.entity_kind`);
+ }
+
+ getReplyEntityId(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.entity_id`);
+ }
+
+ getVideoRelationEntity(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `current_user_video_relation_entities.id_${id}`);
+ }
+
+ getReplyDetailRelationEntity(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `current_user_reply_detail_relation_entities.id_${id}`);
+ }
+
+ isReplySeen(id, state){
+ state = state || Store.getState();
+ return deepGet(state, `current_user_reply_detail_relation_entities.id_${id}.has_seen`);
+ }
+
+ getCanDeleteReply(id, state){
+ state = state || Store.getState();
+ return !!Number( deepGet(state, `current_user_reply_detail_relation_entities.id_${id}.can_delete` , 0) );
+ }
+
+ isVideoIsChargeable(id, state){
+ state = state || Store.getState();
+ return !!Number( deepGet(state, `current_user_video_relation_entities.id_${id}.is_reply_chargeable` , 0) );
+
+ }
+
+ isReplyShareable(id , state){
+ state = state || Store.getState();
+ return !!Number( deepGet(state, `current_user_reply_detail_relation_entities.id_${id}.is_shareable` , 0));
+ }
+
+ isVideoShareable(id ,state){
+ state = state || Store.getState();
+ return !!Number( deepGet(state, `current_user_video_relation_entities.id_${id}.is_shareable` , 0) );
+ }
+
+ getReplyDescriptionId(id, state) {
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.description_id`);
+ }
+
+ getReplyBt(id, state) {
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.total_amount_raised_in_wei`);
+ }
+
+ getReplySupporters(id , state){
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.total_contributed_by`);
+ }
+
+ getReplyLinkId(id, state) {
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.link_ids[0]`);
+ }
+
+ isReplySupported(id, state) {
+ state = state || Store.getState();
+ let val = deepGet(state, `reply_contribution_entities.id_${id}`);
+ val = val && Number(val);
+ return !!val;
+ }
+
+ getReplyParentVideoId(id , state){
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.parent_id`);
+ }
+
+ getReplyUserId(id , state){
+ state = state || Store.getState();
+ return deepGet(state, `reply_detail_entities.id_${id}.creator_user_id`);
+ }
+
+ getReplyParentUserId(id , state){
+ state = state || Store.getState();
+ let parentId = deepGet(state, `reply_detail_entities.id_${id}.parent_id`);
+ return deepGet(state, `video_stat_entities.id_${parentId}.creator_user_id`);
+ }
+
+ getLoginPopOverProps(state) {
+ state = state || Store.getState();
+ return deepGet(state, `login_popover`);
+ }
+
}
export default new ReduxGetters();
diff --git a/src/services/ReduxSetters.js b/src/services/ReduxSetters.js
index 56005376..b13c16cb 100644
--- a/src/services/ReduxSetters.js
+++ b/src/services/ReduxSetters.js
@@ -6,14 +6,20 @@ const knownEntitiesDispatcherMap = {
gifs: 'upsertGiffyEntities',
tags: 'upsertTagEntities',
tag_search_results:'upsertTagEntities',
+ user_search_results:'upsertUserEntities',
user_profiles: 'upsertUserProfileEntities',
user_stats: 'upsertUserStatEntities',
links: 'upsertLinkEntities',
video_descriptions: 'upsertVideoDescriptionEntities',
videos: 'upsertVideoEntities',
video_details: 'upsertVideoStatEntities',
+ video_replies: 'upsertVideoReplyEntities',
+ reply_details: 'upsertReplyDetailEntities',
+ current_user_video_relations: 'upsertCurrentUserVideoRelationEntities',
+ current_user_reply_detail_relations: 'upsertCurrentUserReplyDetailRelationEntities',
images: 'upsertImageEntities',
current_user_video_contributions: 'upsertVideoContributionEntities',
+ current_user_reply_detail_contributions: 'upsertReplyContributionEntities',
current_user_user_contributions: 'upsertUserContributionEntities',
price_points: 'updatePricePoints',
token: 'updateToken',
diff --git a/src/services/TransactionExecutor.js b/src/services/TransactionExecutor.js
new file mode 100644
index 00000000..c33d5328
--- /dev/null
+++ b/src/services/TransactionExecutor.js
@@ -0,0 +1,121 @@
+import { OstWalletSdk } from '@ostdotcom/ost-wallet-sdk-react-native';
+import {ensureDeivceAndSession} from '../helpers/TransactionHelper';
+import ExecuteTransactionWorkflow from '../services/OstWalletCallbacks/ExecuteTransactionWorkFlow';
+import Pricer from "../services/Pricer";
+import deepGet from 'lodash/get';
+import PepoApi from '../services/PepoApi';
+import CurrentUser from "../models/CurrentUser";
+import AppConfig from '../constants/AppConfig';
+import ReduxGetters from './ReduxGetters';
+
+
+/***
+ * Mandatory config
+ * - apiEndpoint
+ * - metaProperties
+ *
+ * Optional config
+ * - ruleName
+ *
+ * CallBack
+ * onDeviceUnauthorized
+ * onEnsureDeivceAndSessionSuccess
+ * onEnsureDeivceAndSessionError
+ * onRequestAcknowledge
+ * onFlowInterrupt
+ * onPlatfromAcknowledgeSuccess
+ * onPlatfromAcknowledgeError
+ * onPlatfromAcknowledgeComplete
+ */
+
+class TransactionExecutor {
+
+ constructor( config , callbacks ){
+ this.config = config || {};
+ this.callbacks = callbacks || {};
+ }
+
+ sendTransactionToSdk(btInDecimal, toTokenHolderAddress , validateSession=true ) {
+ if(!btInDecimal) return ;
+ this.toTokenHolderAddress = toTokenHolderAddress;
+
+ if( !validateSession ){
+ return this._executeTransaction(btInDecimal);
+ }
+
+ ensureDeivceAndSession(CurrentUser.getOstUserId(), btInDecimal, (device) => {
+ this._deviceUnauthorizedCallback(device);
+ }, (errorMessage, success) => {
+ this._ensureDeivceAndSessionCallback(btInDecimal,errorMessage, success);
+ });
+ }
+
+ _deviceUnauthorizedCallback(device){
+ this.callbacks.onDeviceUnauthorized && this.callbacks.onDeviceUnauthorized( device );
+ }
+
+ _ensureDeivceAndSessionCallback(btInDecimal,errorMessage, success){
+ if( success ){
+ this.callbacks.onEnsureDeivceAndSessionSuccess && this.callbacks.onEnsureDeivceAndSessionSuccess( btInDecimal,errorMessage, success );
+ return this._executeTransaction(btInDecimal);
+ }
+
+ if( errorMessage ){
+ this.callbacks.onEnsureDeivceAndSessionError && this.callbacks.onEnsureDeivceAndSessionError( btInDecimal,errorMessage, success );
+ }
+ }
+
+ _executeTransaction(btInDecimal) {
+ this.workflow = new ExecuteTransactionWorkflow(this);
+ OstWalletSdk.executeTransaction(
+ CurrentUser.getOstUserId(),
+ [this.toTokenHolderAddress],
+ [btInDecimal],
+ this.config.ruleName || AppConfig.ruleTypeMap.directTransfer,
+ this.getSdkMetaProperties(),
+ this.workflow
+ );
+ }
+
+ getSdkMetaProperties() {
+ return this.config.metaProperties || {};
+ }
+
+ onRequestAcknowledge(ostWorkflowContext, ostWorkflowEntity) {
+ Pricer.getBalance();
+ this.sendTransactionToPlatform(ostWorkflowEntity);
+ this.callbacks.onRequestAcknowledge && this.callbacks.onRequestAcknowledge( ostWorkflowContext, ostWorkflowEntity );
+ }
+
+ onFlowInterrupt(ostWorkflowContext, error) {
+ this.callbacks.onFlowInterrupt && this.callbacks.onFlowInterrupt( ostWorkflowContext, error );
+ }
+
+ sendTransactionToPlatform(ostWorkflowEntity) {
+ const params = this.getSendTransactionPlatformData(ostWorkflowEntity);
+ const apiEndpoint = this.config.apiEndpoint || '/ost-transactions';
+ new PepoApi(apiEndpoint)
+ .post(params)
+ .then((res) => {
+ this.callbacks.onPlatfromAcknowledgeSuccess && this.callbacks.onPlatfromAcknowledgeSuccess(res);
+ })
+ .catch((error) => {
+ this.callbacks.onPlatfromAcknowledgeError && this.callbacks.onPlatfromAcknowledgeError(error);
+ })
+ .finally(() => {
+ this.callbacks.onPlatfromAcknowledgeComplete && this.callbacks.onPlatfromAcknowledgeComplete();
+ });
+ }
+
+ getSendTransactionPlatformData(ostWorkflowEntity) {
+ const params = {
+ ost_transaction: deepGet(ostWorkflowEntity, 'entity'),
+ ost_transaction_uuid: deepGet(ostWorkflowEntity, 'entity.id')
+ };
+ return params;
+ }
+
+
+}
+
+export { TransactionExecutor };
diff --git a/src/services/TwitterAuthService.js b/src/services/TwitterAuthService.js
index dde3dd2f..1cb1a96f 100644
--- a/src/services/TwitterAuthService.js
+++ b/src/services/TwitterAuthService.js
@@ -1,5 +1,5 @@
import deepGet from 'lodash/get';
-
+import ReduxGetter from "./ReduxGetters";
import Toast from '../theme/components/NotificationToast';
import { upsertInviteCode } from '../actions';
import Store from '../store';
@@ -29,6 +29,9 @@ class TwitterAuthService {
signUp() {
TwitterAuth.signIn()
.then(async (params) => {
+ // Disable the Pop-Up.
+ LoginPopoverActions.showConnecting();
+
if (params) {
let inviteCode = await Utilities.getItem(AppConfig.appInstallInviteCodeASKey);
if (inviteCode) {
@@ -50,7 +53,6 @@ class TwitterAuthService {
});
} else {
LoginPopoverActions.hide();
- console.log('No user data!');
}
})
.catch((error) => {
diff --git a/src/services/Utilities.js b/src/services/Utilities.js
index 9d81505b..3d9bc648 100644
--- a/src/services/Utilities.js
+++ b/src/services/Utilities.js
@@ -1,37 +1,39 @@
import AsyncStorage from '@react-native-community/async-storage';
-import { Alert, Platform, Linking } from 'react-native';
+import { Alert, Platform, Linking , Dimensions } from 'react-native';
import deepGet from 'lodash/get';
import pricer from './Pricer';
import reduxGetters from './ReduxGetters';
-import appConfig from '../constants/AppConfig';
import { FlyerEventEmitter } from '../components/CommonComponents/FlyerHOC';
import { LoginPopoverActions } from '../components/LoginPopover';
import Toast from '../theme/components/NotificationToast';
import CameraPermissionsApi from '../services/CameraPermissionsApi';
import { allowAcessModalEventEmitter } from '../components/AllowAccessModalScreen';
-import AppConfig from '../constants/AppConfig';
-import PepoApi from './PepoApi';
+import AppConfig from '../constants/AppConfig';;
import DataContract from '../constants/DataContract';
+import { isIphoneX } from 'react-native-iphone-x-helper';
-let CurrentUser;
+let CurrentUser, PepoApi;
import('../models/CurrentUser').then((imports) => {
CurrentUser = imports.default;
});
+import('./PepoApi').then((imports) => {
+ PepoApi = imports.default;
+});
let os = Platform.OS || "";
os = os.toLowerCase();
let recursiveMaxCount = 0;
-let checkVideoPermission = function(navigation) {
+let checkVideoPermission = function(navigation, params ) {
CameraPermissionsApi.requestPermission('camera').then((cameraResult) => {
CameraPermissionsApi.requestPermission('microphone').then((microphoneResult) => {
if (cameraResult == 'authorized' && microphoneResult == 'authorized') {
console.log('checkVideoPermission:cameraResult', cameraResult);
console.log('checkVideoPermission:microphoneResult', microphoneResult);
- navigation.navigate('CaptureVideo');
+ navigation.navigate('CaptureVideo', params);
} else if (
(Platform.OS == 'ios' && (cameraResult == 'denied' || microphoneResult == 'denied')) ||
cameraResult == 'restricted' ||
@@ -84,7 +86,7 @@ export default {
getTokenSymbolImageConfig() {
let symbol = pricer.getTokenSymbol();
- return appConfig['tokenSymbols'][symbol];
+ return AppConfig['tokenSymbols'][symbol];
},
_getIDList(resultData, key = 'id') {
@@ -120,7 +122,7 @@ export default {
isUserActivated(status) {
status = status || '';
- return status.toLowerCase() == appConfig.userStatusMap.activated;
+ return status.toLowerCase() == AppConfig.userStatusMap.activated;
},
getLastChildRoutename(state) {
@@ -135,15 +137,23 @@ export default {
return this.getLastChildRoutename(routes[index]);
},
- handleVideoUploadModal(previousTabIndex, navigation) {
- if (reduxGetters.getVideoProcessingStatus() == true && previousTabIndex == 0) {
+ getActiveTab( navigation ){
+ if( !navigation ) return ;
+ let activeIndex = deepGet(navigation , 'state.index'),
+ route = deepGet(navigation , `state.routes[${activeIndex}]`);
+ return route && route["routeName"];
+ },
+
+ handleVideoUploadModal(previousTabIndex, navigation, params = {}) {
+ //todo: @mayur toast and flyer logic change.
+ if (reduxGetters.getVideoProcessingStatus() && previousTabIndex == 0) {
FlyerEventEmitter.emit('onShowProfileFlyer', { id: 2 });
- } else if (reduxGetters.getVideoProcessingStatus() == true) {
+ } else if (reduxGetters.getVideoProcessingStatus()) {
Toast.show({
text: 'Video uploading in progress.'
});
} else {
- checkVideoPermission(navigation);
+ checkVideoPermission(navigation, params);
}
},
@@ -206,6 +216,21 @@ export default {
return pepocornsName.substring(0, length - 1);
}
return pepocornsName;
+ },
+
+ getPendantAvailableHeight(){
+ const area = AppConfig.MaxDescriptionArea;
+ let height = ( area / Dimensions.get('window').width ) + 20;
+ //70 is height of top section
+ return AppConfig.VideoScreenObject.height - height - (isIphoneX ? 78 : Platform.OS === 'ios' ? 28 : 80) ;
+ } ,
+
+ getPendantTop(){
+ if( isIphoneX ){
+ return 60 + 45;
+ }else{
+ return 30+45;
+ }
}
};
diff --git a/src/services/shareVideo.js b/src/services/shareVideo.js
index 8c3dc8c3..226a6cbd 100644
--- a/src/services/shareVideo.js
+++ b/src/services/shareVideo.js
@@ -1,16 +1,15 @@
import PepoApi from './PepoApi';
-
-import { Share, Platform } from 'react-native';
+import { Share } from 'react-native';
class ShareVideo {
- constructor(videoId) {
- this.videoId = videoId;
+ constructor(url , entityId) {
+ this.url = url;
+ this.entityId = entityId;
}
perform() {
return new Promise((resolve, reject) => {
- new PepoApi(`/videos/${this.videoId}/share`).get().then((res) => {
- console.log(res, 'videos/:video_id/share in then');
+ new PepoApi(this.url).get().then((res) => {
this.shareTray(res);
});
});
diff --git a/src/store/index.js b/src/store/index.js
index 14a81640..b386dca5 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -3,6 +3,6 @@ import logger from 'redux-logger';
import { reducer } from '../reducers';
// export const store = __DEV__ === true ? createStore(reducer, applyMiddleware(logger)) : createStore(reducer);
-export const store = createStore(reducer);
+ export const store = createStore(reducer);
export default store;
diff --git a/src/theme/constants/index.js b/src/theme/constants/index.js
index dc0daa99..5ac76747 100644
--- a/src/theme/constants/index.js
+++ b/src/theme/constants/index.js
@@ -1 +1,2 @@
-export const CUSTOM_TAB_Height = 55;
\ No newline at end of file
+export const CUSTOM_TAB_Height = 55;
+export const HEADER_HEIGHT = 56;
\ No newline at end of file
diff --git a/src/theme/ostsdk/ost-sdk-content-config.js b/src/theme/ostsdk/ost-sdk-content-config.js
index 4d2d0d70..ec563d36 100644
--- a/src/theme/ostsdk/ost-sdk-content-config.js
+++ b/src/theme/ostsdk/ost-sdk-content-config.js
@@ -56,7 +56,7 @@ export default {
"text": "Authorize New Session"
},
"lead_label": {
- "text": "Add a 6-digit PIN to secure your wallet"
+ "text": "Enter your 6-digit PIN to authorize yourself"
},
"info_label":{
"text": ""
diff --git a/src/theme/ostsdk/ost-sdk-theme-config.js b/src/theme/ostsdk/ost-sdk-theme-config.js
index 9c660b55..5e1934ef 100644
--- a/src/theme/ostsdk/ost-sdk-theme-config.js
+++ b/src/theme/ostsdk/ost-sdk-theme-config.js
@@ -91,7 +91,7 @@ export default {
"tint_color": colors.paynesGrey
},
"back":{
- "tint_color": "#438bad"
+ "tint_color": colors.paynesGrey
}
},
diff --git a/src/theme/styles/Colors.js b/src/theme/styles/Colors.js
index 8a036a1d..ffc788ce 100644
--- a/src/theme/styles/Colors.js
+++ b/src/theme/styles/Colors.js
@@ -25,5 +25,8 @@ export default {
whisper: '#ECECEC',
rhino: "#34445b",
snow: '#FBFBFB',
- green: '#0F9D58'
+ green: '#0F9D58',
+ nobel: '#979797',
+ gray:"#333333",
+ darkShadeOfGray: '#111111'
};
diff --git a/src/theme/styles/Common.js b/src/theme/styles/Common.js
new file mode 100644
index 00000000..7e0ab5db
--- /dev/null
+++ b/src/theme/styles/Common.js
@@ -0,0 +1,62 @@
+import { ifIphoneX , getBottomSpace} from 'react-native-iphone-x-helper';
+import { Dimensions, StatusBar , NativeModules } from 'react-native';
+import NotchHelper from "../../helpers/NotchHelper";
+import DefaultStyleGenerator from './DefaultStyleGenerator';
+import Colors from './Colors';
+
+
+let RNDeviceInfo = NativeModules.RNDeviceInfo;
+let modalDeviceName = RNDeviceInfo.model === "Redmi Note 7 Pro" && RNDeviceInfo.brand === "xiaomi";
+let btmSpace = modalDeviceName ? 5 : 0;
+import { CUSTOM_TAB_Height } from '../../theme/constants';
+const statusBarHeight = StatusBar.currentHeight;
+const {width, height} = Dimensions.get('window');
+
+const styles = {
+ viewContainer: {
+ flex:1, backgroundColor: Colors.white
+ },
+ modalViewContainer: {
+ flex:1,
+ backgroundColor: 'rgba(0,0,0,0.5)'
+ },
+ fullScreenVideoSafeAreaContainer: {
+ flex:1, backgroundColor: Colors.darkShadeOfGray,
+ },
+ fullScreen: {
+ width: width,
+ ...ifIphoneX(
+ {
+ height: height - getBottomSpace([true])
+ },
+ {
+ height:
+ NotchHelper.hasNotch()
+ ? height + statusBarHeight - btmSpace
+ : height
+ }
+ )
+ },
+
+ videoWrapperfullScreen: {
+ width: width,
+ ...ifIphoneX(
+ {
+ height: height - CUSTOM_TAB_Height - getBottomSpace([true])
+ },
+ {
+ height:
+ NotchHelper.hasNotch()
+ ? height + statusBarHeight - CUSTOM_TAB_Height - btmSpace
+ : height - CUSTOM_TAB_Height
+ }
+ )
+ },
+
+ fullHeightWidth: {
+ width: "100%",
+ height: "100%"
+ },
+};
+
+export default CommonStyle = DefaultStyleGenerator.generate(styles);
diff --git a/src/theme/styles/index.js b/src/theme/styles/index.js
index 5e272451..6cc375bb 100644
--- a/src/theme/styles/index.js
+++ b/src/theme/styles/index.js
@@ -2,10 +2,12 @@ import Button from './Button';
import TextInput from './TextInput';
import Errors from './Errors';
import Colors from './Colors';
+import CommonStyle from './Common';
export default {
Button,
TextInput,
Errors,
- Colors
+ Colors,
+ CommonStyle
};