Update for post display screen

This commit is contained in:
Mustafa Buyukcelebi 2019-11-05 11:43:42 +03:00
commit bdd1caa576
56 changed files with 964 additions and 591 deletions

9
ios/File.swift Normal file
View File

@ -0,0 +1,9 @@
//
// File.swift
// eSteem
//
// Created by Ugur Erdal on 14.10.2019.
// Copyright © 2019 Facebook. All rights reserved.
//
import Foundation

View File

@ -14,15 +14,15 @@ PODS:
- AppCenter/Push
- AppCenterReactNativeShared
- React
- AppCenter/Analytics (2.4.0):
- AppCenter/Analytics (2.5.0):
- AppCenter/Core
- AppCenter/Core (2.4.0)
- AppCenter/Crashes (2.4.0):
- AppCenter/Core (2.5.0)
- AppCenter/Crashes (2.5.0):
- AppCenter/Core
- AppCenter/Push (2.4.0):
- AppCenter/Push (2.5.0):
- AppCenter/Core
- AppCenterReactNativeShared (2.4.0):
- AppCenter/Core (= 2.4.0)
- AppCenterReactNativeShared (2.5.0):
- AppCenter/Core (= 2.5.0)
- boost-for-react-native (1.63.0)
- BugsnagReactNative (2.23.2):
- BugsnagReactNative/Core (= 2.23.2)
@ -65,6 +65,10 @@ PODS:
- DoubleConversion
- glog
- glog (0.3.5)
- lottie-ios (3.1.3)
- lottie-react-native (3.2.1):
- lottie-ios (~> 3.1.3)
- React
- QBImagePickerController (3.4.0)
- RCTRequired (0.61.2)
- RCTTypeSafety (0.61.2):
@ -277,6 +281,8 @@ PODS:
- React-cxxreact (= 0.61.2)
- React-jsi (= 0.61.2)
- ReactCommon/jscallinvoker (= 0.61.2)
- ReactNativeDarkMode (0.1.2):
- React
- RNGestureHandler (1.4.1):
- React
- RNIap (3.4.15):
@ -314,6 +320,8 @@ DEPENDENCIES:
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- lottie-ios (from `../node_modules/lottie-ios`)
- lottie-react-native (from `../node_modules/lottie-react-native`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
@ -341,6 +349,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- ReactNativeDarkMode (from `../node_modules/react-native-dark-mode`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNIap (from `../node_modules/react-native-iap`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
@ -385,6 +394,10 @@ EXTERNAL SOURCES:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
lottie-ios:
:path: "../node_modules/lottie-ios"
lottie-react-native:
:path: "../node_modules/lottie-react-native"
RCTRequired:
:path: "../node_modules/react-native/Libraries/RCTRequired"
RCTTypeSafety:
@ -433,6 +446,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/Vibration"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
ReactNativeDarkMode:
:path: "../node_modules/react-native-dark-mode"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNIap:
@ -451,12 +466,12 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
AppCenter: 49a9ffe114c00e2bf5374aeda816d47eabf1978a
AppCenter: 637f180deefc61e8ab3f94223869ee50f61dabea
appcenter: 4072e79b8d037d99056e6fc6556224b4525b5829
appcenter-analytics: 94be52eca805d586207d710aac95e0ddca8b3ddb
appcenter-crashes: 30caece47856aee7c4c7449d4f4dae2d69795bd6
appcenter-push: f6c62e8e55cf09f53076674c185df72f68ea9dd7
AppCenterReactNativeShared: 57a66e6539e9abe6079ba8f93a002bc3f95788cc
AppCenterReactNativeShared: 99e7f662ec66b1cb41306ecf357aabac35931c08
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BugsnagReactNative: 0a24a1dd2cac88862d67b938f809bec8274130a9
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
@ -467,6 +482,8 @@ SPEC CHECKSUMS:
FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
lottie-ios: 496ac5cea1bbf1a7bd1f1f472f3232eb1b8d744b
lottie-react-native: b123a79529cc732201091f585c62c89bb4747252
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
RCTRequired: c639d59ed389cfb1f1203f65c2ea946d8ec586e2
RCTTypeSafety: dc23fb655d6c77667c78e327bf661bc11e3b8aec
@ -492,6 +509,7 @@ SPEC CHECKSUMS:
React-RCTText: e3ef6191cdb627855ff7fe8fa0c1e14094967fb8
React-RCTVibration: fb54c732fd20405a76598e431aa2f8c2bf527de9
ReactCommon: 5848032ed2f274fcb40f6b9ec24067787c42d479
ReactNativeDarkMode: 315535c6f7a066bc4e8ba60591a63aafa16d5dca
RNGestureHandler: 4cb47a93019c1a201df2644413a0a1569a51c8aa
RNIap: b4c77c8bc4501203f4b743126a05da23f10f40b4
RNImageCropPicker: bfb3ea9c8622f290532e2fe63f369e0d5a52f597

View File

@ -0,0 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

View File

@ -39,6 +39,7 @@
8A865CFDCD1C4F4885488F9D /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 22F5F05A06E142C2B41A4D38 /* MaterialCommunityIcons.ttf */; };
8FA95502318C441BB5187988 /* Fontisto.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 98D3D7C3AF354BF0987A2BFA /* Fontisto.ttf */; };
94139B1E6AEB4494837396E2 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34E88D888DD444F8B285363C /* SimpleLineIcons.ttf */; };
9487A245235508C60080E6CD /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9487A244235508C60080E6CD /* File.swift */; };
B5B60E44B0FA4A72BB3B3BF2 /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 112758B0BBF9458381CE41FD /* FontAwesome.ttf */; };
BD7763EC3A6A4DDCB59E8CEE /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A239FC84622A4A9CA7950ED9 /* EvilIcons.ttf */; };
D71EB20EDB9B987C0574BAFE /* libPods-eSteemTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C97456BE898C00B5EDA21C2E /* libPods-eSteemTests.a */; };
@ -130,6 +131,8 @@
926635867AC7C716988E74B7 /* libPods-eSteem-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-eSteem-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
93B182C6FFA44610AB188D7C /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
9464AFB033664B4F8E9F0BED /* AntDesign.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = AntDesign.ttf; path = "../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf"; sourceTree = "<group>"; };
9487A243235508C50080E6CD /* eSteem-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "eSteem-Bridging-Header.h"; sourceTree = "<group>"; };
9487A244235508C60080E6CD /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
95E8535BAE22D33276B4ED85 /* Pods-eSteem-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-eSteem-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-eSteem-tvOSTests/Pods-eSteem-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
980BC9BC0D3B4AC69645C842 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
98D3D7C3AF354BF0987A2BFA /* Fontisto.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Fontisto.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf"; sourceTree = "<group>"; };
@ -215,6 +218,8 @@
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
9487A244235508C60080E6CD /* File.swift */,
9487A243235508C50080E6CD /* eSteem-Bridging-Header.h */,
);
name = eSteem;
sourceTree = "<group>";
@ -439,6 +444,7 @@
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = 75B6RXTKGT;
LastSwiftMigration = 1110;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.InAppPurchase = {
@ -796,6 +802,7 @@
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
9487A245235508C60080E6CD /* File.swift in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -849,6 +856,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = DEAC5F1FB6C25D794F6F4108 /* Pods-eSteemTests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@ -872,6 +880,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 122D7FCBA41B06097098B6E8 /* Pods-eSteemTests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
COPY_PHASE_STRIP = NO;
INFOPLIST_FILE = eSteemTests/Info.plist;
@ -893,6 +902,7 @@
baseConfigurationReference = F78BB3E26D5377FC091969E5 /* Pods-eSteem.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = eSteem/eSteem.entitlements;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 7;
@ -962,6 +972,7 @@
baseConfigurationReference = FFDF532341ADF17A45F71E22 /* Pods-eSteem.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = eSteem/eSteem.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
@ -1187,6 +1198,7 @@
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@ -1232,6 +1244,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = Release;

View File

@ -92,7 +92,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"

View File

@ -41,6 +41,8 @@
"intl": "^1.2.5",
"jsc-android": "^236355.1.1",
"lodash": "^4.17.13",
"lottie-ios": "3.1.3",
"lottie-react-native": "^3.2.1",
"moment": "^2.22.2",
"react": "16.9.0",
"react-intl": "^3.3.1",
@ -50,6 +52,7 @@
"react-native-autoheight-webview": "^1.2.2",
"react-native-code-push": "esteemapp/react-native-code-push",
"react-native-config": "luggit/react-native-config#master",
"react-native-dark-mode": "^0.1.2",
"react-native-datepicker": "^1.7.2",
"react-native-extended-stylesheet": "^0.10.0",
"react-native-fast-image": "^4.0.14",

View File

@ -1,44 +1,53 @@
/* eslint-disable radix */
import React from 'react';
import { connect } from 'react-redux';
import { Dimensions, View } from 'react-native';
import times from 'lodash/times';
import Placeholder from 'rn-placeholder';
import { ThemeContainer } from '../../../../containers';
import styles from './boostPlaceHolderStyles';
const HEIGHT = Dimensions.get('window').height;
const BoostPlaceHolder = ({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
const BoostPlaceHolder = () => {
const ratio = (HEIGHT - 300) / 50 / 1.3;
const listElements = [];
times(parseInt(ratio), i => {
listElements.push(
<View style={styles.container} key={i}>
<View style={styles.line}>
<Placeholder.Box color={color} width={90} height={40} animate="fade" />
<View style={styles.paragraphWrapper}>
<Placeholder.Box color={color} width={140} radius={25} height={50} animate="fade" />
</View>
<Placeholder.Box
style={styles.rightBox}
color={color}
width={20}
height={10}
animate="fade"
/>
</View>
</View>,
<ThemeContainer>
{({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
return (
<View style={styles.container} key={i}>
<View style={styles.line}>
<Placeholder.Box color={color} width={90} height={40} animate="fade" />
<View style={styles.paragraphWrapper}>
<Placeholder.Box
color={color}
width={140}
radius={25}
height={50}
animate="fade"
/>
</View>
<Placeholder.Box
style={styles.rightBox}
color={color}
width={20}
height={10}
animate="fade"
/>
</View>
</View>
);
}}
</ThemeContainer>,
);
});
return <View style={styles.container}>{listElements}</View>;
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(BoostPlaceHolder);
export default BoostPlaceHolder;

View File

@ -1,34 +1,36 @@
import React from 'react';
import { connect } from 'react-redux';
import { View } from 'react-native';
import Placeholder from 'rn-placeholder';
import { ThemeContainer } from '../../../../containers';
import styles from './listItemPlaceHolderStyles';
const ListItemPlaceHolderView = ({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
const ListItemPlaceHolderView = () => {
return (
<View style={styles.container}>
<Placeholder.Media size={30} hasRadius animate="fade" color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={2}
textSize={12}
lineSpacing={8}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
<ThemeContainer>
{({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
return (
<View style={styles.container}>
<Placeholder.Media size={30} hasRadius animate="fade" color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={2}
textSize={12}
lineSpacing={8}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
);
}}
</ThemeContainer>
);
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(ListItemPlaceHolderView);
export default ListItemPlaceHolderView;

View File

@ -1,6 +1,5 @@
/* eslint-disable radix */
import React, { Fragment } from 'react';
import { connect } from 'react-redux';
import { Dimensions } from 'react-native';
import times from 'lodash/times';
@ -18,9 +17,4 @@ const ListPlaceHolderView = () => {
return <Fragment>{listElements}</Fragment>;
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(ListPlaceHolderView);
export default ListPlaceHolderView;

View File

@ -1,38 +1,39 @@
import React from 'react';
import { connect } from 'react-redux';
import { View } from 'react-native';
import Placeholder from 'rn-placeholder';
import { ThemeContainer } from '../../../../containers';
import styles from './postCardPlaceHolderStyles';
// TODO: make container for place holder wrapper after alpha
const PostCardPlaceHolder = ({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
const PostCardPlaceHolder = () => {
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Placeholder.Media size={35} hasRadius animate="fade" color={color} />
<Placeholder.Line width="30%" lastLineWidth="30%" animate="fade" color={color} />
</View>
<Placeholder.Box animate="fade" height={200} width="100%" radius={5} color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
lineNumber={3}
color={color}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
<ThemeContainer>
{({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Placeholder.Media size={35} hasRadius animate="fade" color={color} />
<Placeholder.Line width="30%" lastLineWidth="30%" animate="fade" color={color} />
</View>
<Placeholder.Box animate="fade" height={200} width="100%" radius={5} color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
lineNumber={3}
color={color}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
);
}}
</ThemeContainer>
);
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(PostCardPlaceHolder);
export default PostCardPlaceHolder;

View File

@ -1,47 +1,50 @@
import React from 'react';
import { connect } from 'react-redux';
import { View } from 'react-native';
import Placeholder from 'rn-placeholder';
import styles from './postCardPlaceHolderStyles';
// TODO: make container for place holder wrapper after alpha
const PostPlaceHolder = ({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
import { ThemeContainer } from '../../../../containers';
import styles from './postCardPlaceHolderStyles';
const PostPlaceHolder = () => {
return (
<View>
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={2}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
<View style={styles.paragraphWrapper} />
<Placeholder.Box animate="fade" height={200} width="100%" radius={5} color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={18}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
<ThemeContainer>
{({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
return (
<View>
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={2}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
<View style={styles.paragraphWrapper} />
<Placeholder.Box animate="fade" height={200} width="100%" radius={5} color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={18}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
);
}}
</ThemeContainer>
);
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(PostPlaceHolder);
export default PostPlaceHolder;

View File

@ -1,37 +1,40 @@
import React from 'react';
import { connect } from 'react-redux';
import { View } from 'react-native';
import Placeholder from 'rn-placeholder';
import { ThemeContainer } from '../../../../containers';
import styles from './profileSummaryPlaceHolderStyles';
// TODO: make container for place holder wrapper after alpha
const ProfileSummaryPlaceHolder = ({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
const ProfileSummaryPlaceHolder = () => {
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Placeholder.Paragraph lineNumber={1} color={color} />
</View>
<Placeholder.Box animate="fade" height={75} width="100%" radius={5} color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={3}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
<ThemeContainer>
{({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Placeholder.Paragraph lineNumber={1} color={color} />
</View>
<Placeholder.Box animate="fade" height={75} width="100%" radius={5} color={color} />
<View style={styles.paragraphWrapper}>
<Placeholder.Paragraph
color={color}
lineNumber={3}
textSize={16}
lineSpacing={5}
width="100%"
lastLineWidth="70%"
firstLineWidth="50%"
animate="fade"
/>
</View>
</View>
);
}}
</ThemeContainer>
);
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(ProfileSummaryPlaceHolder);
export default ProfileSummaryPlaceHolder;

View File

@ -1,10 +1,11 @@
/* eslint-disable radix */
import React, { Fragment } from 'react';
import { connect } from 'react-redux';
import { View, Dimensions } from 'react-native';
import Placeholder from 'rn-placeholder';
import times from 'lodash/times';
import { ThemeContainer } from '../../../../containers';
import styles from './walletDetailsPlaceHolderStyles';
const HEIGHT = Dimensions.get('window').height;
@ -24,21 +25,21 @@ const listPlaceHolderView = color => {
return <Fragment>{listElements}</Fragment>;
};
const WalletDetailsPlaceHolder = ({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
const WalletDetailsPlaceHolder = () => (
<ThemeContainer>
{({ isDarkTheme }) => {
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Placeholder.Paragraph lineNumber={1} color={color} />
</View>
{listPlaceHolderView(color)}
</View>
);
};
return (
<View style={styles.container}>
<View style={styles.textWrapper}>
<Placeholder.Paragraph lineNumber={1} color={color} />
</View>
{listPlaceHolderView(color)}
</View>
);
}}
</ThemeContainer>
);
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(WalletDetailsPlaceHolder);
export default WalletDetailsPlaceHolder;

View File

@ -9,6 +9,9 @@ import { updateActiveBottomTab } from '../../../redux/actions/uiAction';
// Constants
import ROUTES from '../../../constants/routeNames';
// Container
import { ThemeContainer } from '../../../containers';
// Components
import TabBar from './tabbar';
@ -38,36 +41,40 @@ const BottomTabBarView = ({
useEffect(() => {
dispatch(updateActiveBottomTab(routes[index].routeName));
}, [dispatch, routes, index]);
}, [dispatch, index, routes]);
return (
<SafeAreaView style={styles.wrapper}>
<TabBar
selectedIndex={index}
circleBackgroundColor="#357ce6"
backgroundColor="#f6f6f6"
onChange={i => _jumpTo(routes[i], index, routes, jumpTo)}
activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor}
>
{routes.map(route => (
<TabBar.Item
icon={renderIcon({
route,
focused: false,
tintColor: inactiveTintColor,
})}
selectedIcon={renderIcon({
route,
focused: true,
tintColor: activeTintColor,
})}
key={route}
disabled={route.routeName === ROUTES.TABBAR.POST_BUTTON}
/>
))}
</TabBar>
</SafeAreaView>
<ThemeContainer>
{({ isDarkTheme }) => (
<SafeAreaView style={styles.wrapper}>
<TabBar
selectedIndex={index}
circleBackgroundColor="#357ce6"
backgroundColor={isDarkTheme ? '#2e3d51' : '#f6f6f6'}
onChange={i => _jumpTo(routes[i], index, routes, jumpTo)}
activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor}
>
{routes.map(route => (
<TabBar.Item
icon={renderIcon({
route,
focused: false,
tintColor: inactiveTintColor,
})}
selectedIcon={renderIcon({
route,
focused: true,
tintColor: activeTintColor,
})}
key={route}
disabled={route.routeName === ROUTES.TABBAR.POST_BUTTON}
/>
))}
</TabBar>
</SafeAreaView>
)}
</ThemeContainer>
);
};

View File

@ -36,7 +36,6 @@ export default class TabBar extends Component {
circleRadius: new Animated.Value(91 + selectedIndex * value),
pathD: new Animated.Value(selectedIndex * value),
pathX: selectedIndex * value,
showIcon: true,
animateConstant: value,
};
@ -72,15 +71,16 @@ export default class TabBar extends Component {
_move = index => {
const { animateConstant, pathD, circleRadius } = this.state;
this.setState({
selectedIndex: index,
showIcon: false,
});
this.setState({ selectedIndex: '' });
Animated.timing(pathD, {
toValue: 0 + index * animateConstant,
duration: 450,
}).start(() => this.setState({ showIcon: true }));
}).start(() => {
setTimeout(() => {
this.setState({ selectedIndex: index });
}, 350);
});
Animated.timing(circleRadius, {
toValue: 91 + index * animateConstant,
}).start();
@ -88,20 +88,19 @@ export default class TabBar extends Component {
render() {
const { children, backgroundColor, circleBackgroundColor, style } = this.props;
const { selectedIndex, showIcon, pathX, circleRadius } = this.state;
const { selectedIndex, pathX, circleRadius } = this.state;
return (
<View style={style}>
<View style={styles.subContent}>
{children.map((route, i) => {
const element = React.cloneElement(route, {
return React.cloneElement(route, {
selected: selectedIndex === i,
onPress: this._onPress,
key: i,
index: i,
showIcon,
showIcon: true,
});
return element;
})}
</View>
@ -148,8 +147,10 @@ const TabBarItem = ({ icon, selectedIcon, index, selected, onPress, showIcon, di
</TouchableHighlight>
);
}
return <View style={styles.navItem} />;
}
return (
<TouchableHighlight
underlayColor={'transparent'}

View File

@ -6,7 +6,7 @@ export default EStyleSheet.create({
borderTopRightRadius: 8,
marginTop: 16,
flexDirection: 'row',
backgroundColor: '$primaryGray',
backgroundColor: '$primaryLightBackground',
height: 60,
borderBottomWidth: 2,
},

View File

@ -5,6 +5,7 @@ import FastImage from 'react-native-fast-image';
// Components
import { TextInput } from '../../textInput';
import { Icon } from '../../icon';
import { ThemeContainer } from '../../../containers';
// Utils
import { getResizedAvatar } from '../../../utils/image';
@ -68,6 +69,7 @@ class FormInputView extends Component {
height,
inputStyle,
} = this.props;
return (
<View
style={[
@ -95,19 +97,24 @@ class FormInputView extends Component {
)
)}
<View style={styles.textInput}>
<TextInput
style={inputStyle}
onFocus={() => this.setState({ inputBorderColor: '#357ce6' })}
onBlur={() => this.setState({ inputBorderColor: '#e7e7e7' })}
autoCapitalize="none"
secureTextEntry={secureTextEntry}
height={height}
placeholder={placeholder}
editable={isEditable || true}
textContentType={type}
onChangeText={this._handleOnChange}
value={value}
/>
<ThemeContainer>
{({ isDarkTheme }) => (
<TextInput
style={inputStyle}
onFocus={() => this.setState({ inputBorderColor: '#357ce6' })}
onBlur={() => this.setState({ inputBorderColor: '#e7e7e7' })}
autoCapitalize="none"
secureTextEntry={secureTextEntry}
height={height}
placeholder={placeholder}
editable={isEditable || true}
textContentType={type}
onChangeText={this._handleOnChange}
value={value}
placeholderTextColor={isDarkTheme ? '#526d91' : '#788187'}
/>
)}
</ThemeContainer>
</View>
{value && value.length > 0 ? (

View File

@ -34,7 +34,6 @@ class HeaderView extends Component {
render() {
const {
avatarUrl,
displayName,
handleOnPressBackButton,
handleOpenDrawer,

View File

@ -13,6 +13,8 @@ import { PostBody } from '../../postElements';
import { StickyBar } from '../../basicUIElements';
import { TextInput } from '../../textInput';
import { ThemeContainer } from '../../../containers';
// Styles
import styles from './markdownEditorStyles';
@ -201,22 +203,26 @@ export default class MarkdownEditorView extends Component {
behavior={Platform.OS === 'ios' ? 'padding' : null}
>
{!isPreviewActive ? (
<TextInput
multiline
onChangeText={this._changeText}
onSelectionChange={this._handleOnSelectionChange}
placeholder={intl.formatMessage({
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
})}
placeholderTextColor="#c1c5c7"
selection={selection}
selectionColor="#357ce6"
style={styles.textWrapper}
underlineColorAndroid="transparent"
value={text}
innerRef={this.inputRef}
editable={!isLoading}
/>
<ThemeContainer>
{({ isDarkTheme }) => (
<TextInput
multiline
onChangeText={this._changeText}
onSelectionChange={this._handleOnSelectionChange}
placeholder={intl.formatMessage({
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
})}
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
selection={selection}
selectionColor="#357ce6"
style={styles.textWrapper}
underlineColorAndroid="transparent"
value={text}
innerRef={this.inputRef}
editable={!isLoading}
/>
)}
</ThemeContainer>
) : (
this._renderPreview()
)}

View File

@ -10,6 +10,7 @@ import { ContainerHeader } from '../../containerHeader';
import { FilterBar } from '../../filterBar';
import { NotificationLine } from '../..';
import { ListPlaceHolder } from '../../basicUIElements';
import { ThemeContainer } from '../../../containers';
// Utils
import { isToday, isYesterday, isThisWeek, isThisMonth } from '../../../utils/time';
@ -149,12 +150,7 @@ class NotificationView extends PureComponent {
);
render() {
const {
readAllNotification,
getActivities,
isNotificationRefreshing,
isDarkTheme,
} = this.props;
const { readAllNotification, getActivities, isNotificationRefreshing } = this.props;
const { filters, selectedFilter } = this.state;
const _notifications = this._getNotificationsArrays();
@ -178,13 +174,17 @@ class NotificationView extends PureComponent {
ListFooterComponent={this._renderFooterLoading}
ListEmptyComponent={<ListPlaceHolder />}
refreshControl={
<RefreshControl
refreshing={isNotificationRefreshing}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
<ThemeContainer>
{({ isDarkTheme }) => (
<RefreshControl
refreshing={isNotificationRefreshing}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
)}
</ThemeContainer>
}
renderItem={({ item, index }) => (
<Fragment>

View File

@ -24,7 +24,7 @@ export default EStyleSheet.create({
},
buttonWithoutBorder: {
borderWidth: 0,
backgroundColor: '$primaryWhiteLightBackground',
backgroundColor: 'transparent',
width: '$deviceWidth / 7',
height: '$deviceWidth / 7',
alignItems: 'center',

View File

@ -1,10 +1,10 @@
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import { Animated, Easing, View } from 'react-native';
// Styles
import styles from './pinAnimatedInputStyles';
class PinAnimatedInput extends PureComponent {
class PinAnimatedInput extends Component {
/* Props
*
* @prop { string } pin - Description.

View File

@ -119,7 +119,7 @@ export default EStyleSheet.create({
},
scrollContainer: {
flex: 1,
backgroundColor: '$pureWhite',
backgroundColor: '$primaryBackgroundColor',
},
popoverDetails: {
flexDirection: 'row',

View File

@ -13,6 +13,7 @@ import { Icon } from '../../icon';
import { MainButton } from '../../mainButton';
import { DropdownButton } from '../../dropdownButton';
import { CollapsibleCard } from '../../collapsibleCard';
import { ThemeContainer } from '../../../containers';
// Utils
import { getTimeFromNow } from '../../../utils/time';
@ -40,17 +41,21 @@ class PointsView extends Component {
// Component Functions
refreshControl = () => {
const { fetchUserActivity, refreshing, isDarkTheme } = this.props;
const { fetchUserActivity, refreshing } = this.props;
return (
<RefreshControl
refreshing={refreshing}
onRefresh={fetchUserActivity}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
<ThemeContainer>
{isDarkTheme => (
<RefreshControl
refreshing={refreshing}
onRefresh={fetchUserActivity}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
)}
</ThemeContainer>
);
};

View File

@ -2,7 +2,7 @@ import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
text: {
fontSize: 14,
fontSize: 16,
color: '$primaryBlack',
fontFamily: '$primaryFont',
},

View File

@ -1,49 +1,52 @@
import React, { PureComponent, Fragment } from 'react';
import React, { Fragment } from 'react';
import { Dimensions, Linking, Alert, TouchableOpacity, Text } from 'react-native';
import { withNavigation } from 'react-navigation';
import { injectIntl } from 'react-intl';
import AutoHeightWebView from 'react-native-autoheight-webview';
import { useIntl, injectIntl } from 'react-intl';
import HTML from 'react-native-render-html';
import { getParentsTagsRecursively } from 'react-native-render-html/src/HTMLUtils';
import AutoHeightWebView from 'react-native-autoheight-webview';
import EStyleSheet from 'react-native-extended-stylesheet';
// Constants
import { default as ROUTES } from '../../../../constants/routeNames';
// Styles
import styles from './postBodyStyles';
// Constants
import { default as ROUTES } from '../../../../constants/routeNames';
// Components
const WIDTH = Dimensions.get('window').width;
class PostBody extends PureComponent {
// Component Life Cycles
const PostBody = ({
navigation,
body,
isComment,
textSelectable = true,
handleOnUserPress,
handleOnPostPress,
}) => {
const intl = useIntl();
// Component Functions
_handleOnLinkPress = (href, hrefatr) => {
const { handleOnUserPress, handleOnPostPress } = this.props;
if (hrefatr.class === 'markdown-author-link') {
const _handleOnLinkPress = (href, hrefAtr) => {
if (hrefAtr.class === 'markdown-author-link') {
if (!handleOnUserPress) {
this._handleOnUserPress(hrefatr['data-author']);
_handleOnUserPress(hrefAtr['data-author']);
} else {
handleOnUserPress(hrefatr['data-author']);
handleOnUserPress(hrefAtr['data-author']);
}
} else if (hrefatr.class === 'markdown-post-link') {
} else if (hrefAtr.class === 'markdown-post-link') {
if (!handleOnPostPress) {
this._handleOnPostPress(hrefatr['data-permlink'], hrefatr['data-author']);
_handleOnPostPress(hrefAtr['data-permlink'], hrefAtr['data-author']);
} else {
handleOnPostPress(hrefatr['data-permlink']);
handleOnPostPress(hrefAtr['data-permlink']);
}
} else {
this._handleBrowserLink(href);
_handleBrowserLink(href);
}
};
_handleBrowserLink = async url => {
if (!url) return;
const { intl } = this.props;
const _handleBrowserLink = async url => {
if (!url) {
return;
}
Linking.canOpenURL(url).then(supported => {
if (supported) {
@ -54,9 +57,7 @@ class PostBody extends PureComponent {
});
};
_handleOnPostPress = (permlink, author) => {
const { navigation } = this.props;
const _handleOnPostPress = (permlink, author) => {
if (permlink) {
navigation.navigate({
routeName: ROUTES.SCREENS.POST,
@ -69,9 +70,7 @@ class PostBody extends PureComponent {
}
};
_handleOnUserPress = username => {
const { navigation } = this.props;
const _handleOnUserPress = username => {
if (username) {
navigation.navigate({
routeName: ROUTES.SCREENS.PROFILE,
@ -81,33 +80,35 @@ class PostBody extends PureComponent {
key: username,
});
} else {
Alert.alert('Opps!', 'Wrong link :(');
Alert.alert('Opss!', 'Wrong link.');
}
};
_hasParentTag = (node, name) => {
if (!node.parent) return false;
if (node.name === name) return true;
return this._hasParentTag(node.parent, name);
const _hasParentTag = (node, name) => {
if (!node.parent) {
return false;
}
if (node.name === name) {
return true;
}
return _hasParentTag(node.parent, name);
};
_alterNode = (node, isComment) => {
const _alterNode = (node, isComment) => {
if (isComment) {
if (node.name === 'img') {
node.attribs.style = `max-width: ${WIDTH - 50}px; height: 100px; width: ${WIDTH -
50}px; text-align: center;`;
}
// else if (node.name === 'iframe') {
// node.attribs.style = `max-width: ${WIDTH}px; left: -30px`;
// node.attribs.height = 216;
// }
} else if (node.name === 'a') {
node.attribs.style = 'text-decoration: underline';
}
if (node.name === 'img') {
node.attribs.style = 'text-align: center;';
if (this._hasParentTag(node, 'td')) {
if (_hasParentTag(node, 'td')) {
node.attribs.style = `max-width: ${WIDTH / 2 - 20}px; `;
}
}
@ -133,7 +134,7 @@ class PostBody extends PureComponent {
}
};
_alterData = node => {
const _alterData = node => {
if (
node.type === 'text' &&
node.data.includes('markdown-author-link') &&
@ -143,82 +144,184 @@ class PostBody extends PureComponent {
return node.data.replace(/<[^>]*>/g, '');
}
};
handleWebViewNavigationStateChange = newNavState => {
const handleWebViewNavigationStateChange = newNavState => {
console.log('newNavState :', newNavState);
if (newNavState.navigationType === 'click') {
return false;
}
return newNavState;
};
render() {
const { body, isComment, textSelectable = true } = this.props;
const _initialDimensions = isComment
? { width: WIDTH - 50, height: 80 }
: { width: WIDTH, height: 216 };
const jsCode = `
document.querySelector('a').addEventListener("click", function() {
alert('Hello Web')
});
true;
`;
const _initialDimensions = isComment
? { width: WIDTH - 50, height: 80 }
: { width: WIDTH, height: 216 };
const _customRenderer = {
a: (htmlAttribs, children, convertedCSSStyles, passProps) => {
if (passProps.parentWrapper === 'Text') {
return (
<Text
key={passProps.key}
{...htmlAttribs}
onPress={() => this._handleOnLinkPress(htmlAttribs['data-href'], htmlAttribs)}
>
{children}
</Text>
);
}
const _customRenderer = {
a: (htmlAttribs, children, convertedCSSStyles, passProps) => {
if (passProps.parentWrapper === 'Text') {
return (
<TouchableOpacity
<Text
key={passProps.key}
{...htmlAttribs}
onPress={() => this._handleOnLinkPress(htmlAttribs['data-href'], htmlAttribs)}
onPress={() => _handleOnLinkPress(htmlAttribs['data-href'], htmlAttribs)}
>
{children}
</TouchableOpacity>
</Text>
);
},
br: (htmlAttribs, children, passProps) => {
return <Text {...passProps}>{'\n'}</Text>;
},
};
}
return (
<TouchableOpacity
key={passProps.key}
{...htmlAttribs}
onPress={() => _handleOnLinkPress(htmlAttribs['data-href'], htmlAttribs)}
>
{children}
</TouchableOpacity>
);
},
br: (htmlAttribs, children, passProps) => {
return <Text {...passProps}>{'\n'}</Text>;
},
};
const test = body.replace(/<a/g, '<a target="_blank"');
// console.log('test :', test);
const runFirst = `
document.addEventListener('click', function(event) {
let el = event.target;
// A element can be wrapped with inline element. Look parent elements.
// alert(el.tagName.toString())
while (el.tagName !== 'A') {
if (!el.parentNode) {
break;
}
el = el.parentNode;
}
window.ReactNativeWebView.postMessage('"Hello!"')
window.ReactNativeWebView.postMessage('1')
if (!el || el.tagName !== 'A') {
const test = body.replace(/<a/g, '<a href');
console.log('test :', test);
return (
<Fragment>
<AutoHeightWebView
style={{ width: Dimensions.get('window').width - 15, marginTop: 35 }}
source={{
html: test,
}}
onShouldStartLoadWithRequest={this.handleWebViewNavigationStateChange}
injectedJavaScript={jsCode}
/>
<HTML
html={body}
onLinkPress={(evt, href, hrefatr) => this._handleOnLinkPress(evt, href, hrefatr)}
containerStyle={isComment ? styles.commentContainer : styles.container}
textSelectable={textSelectable}
tagsStyles={isComment ? { img: { height: 120 } } : styles}
ignoredTags={['script']}
debug={false}
staticContentMaxWidth={WIDTH - 33}
imagesInitialDimensions={_initialDimensions}
baseFontStyle={styles.text}
imagesMaxWidth={isComment ? WIDTH - 50 : WIDTH}
alterNode={e => this._alterNode(e, isComment)}
alterData={e => this._alterData(e)}
renderers={_customRenderer}
/>
</Fragment>
);
// window.ReactNativeWebView.postMessage(!el)
// window.ReactNativeWebView.postMessage(el.tagName)
return;
}
window.ReactNativeWebView.postMessage('2')
if (el.getAttribute('target') === '_external') {
const href = el.getAttribute('href');
shell.openExternal(href);
event.preventDefault();
return true;
}
window.ReactNativeWebView.postMessage('3')
if (el.classList.contains('markdown-external-link')) {
const href = el.getAttribute('data-href');
shell.openExternal(href);
event.preventDefault();
return true;
}
window.ReactNativeWebView.postMessage('4')
const author = el.getAttribute('data-author').toString();
window.ReactNativeWebView.postMessage(JSON.stringify(author))
})
true; // note: this is required, or you'll sometimes get silent failures
`;
// console.log('body :', body);
// EStyleSheet.value('$contentWidth')
const customStyle = `
* {
color: ${EStyleSheet.value('$primaryBlack')};
font-family: Roboto, sans-serif;
}
}
body {
color: ${EStyleSheet.value('$primaryBlack')};
}
a {
color: ${EStyleSheet.value('$primaryBlue')};
cursor: pointer;
}
img {
max-width: 100%;
margin-bottom: 30px;
align-self: 'center';
}
center {
text-align: 'center';
align-items: 'center';
justify-content: 'center';
}
th {
flex: 1;
justify-content: 'center';
font-weight: 'bold';
color: ${EStyleSheet.value('$primaryBlack')};
font-size: 14;
padding: 5;
}
tr {
background-color: ${EStyleSheet.value('$darkIconColor')};
flex-direction: 'row';
}
td: {
border-width: 0.5;
border-color: ${EStyleSheet.value('$tableBorderColor')};
flex: 1;
padding: 10;
background-color: ${EStyleSheet.value('$tableTrColor')};
}
blockquote: {
border-left-width: 5;
border-color: ${EStyleSheet.value('$darkIconColor')};
padding-left: 5;
}
code: {
background-color: ${EStyleSheet.value('$darkIconColor')};
font-family: ${EStyleSheet.value('$editorFont')};
}
center: {
text-align: 'center';
align-items: 'center';
justify-content: 'center';
}`;
console.log('EStyleSheet.value', EStyleSheet.value('$primaryBlack'));
console.log('customStyle :', customStyle);
return (
<Fragment>
<AutoHeightWebView
style={{ maxWidth: Dimensions.get('window').width - 15, marginTop: 35 }}
source={{
html: test,
}}
// javaScriptEnabled={false}
customStyle={customStyle}
onMessage={m => console.log('message :', m.nativeEvent.data)}
// onShouldStartLoadWithRequest={handleWebViewNavigationStateChange}
customScript={runFirst}
/>
<HTML
html={body}
onLinkPress={(evt, href, hrefAtr) => _handleOnLinkPress(evt, href, hrefAtr)}
containerStyle={isComment ? styles.commentContainer : styles.container}
textSelectable={textSelectable}
tagsStyles={isComment ? { img: { height: 120 } } : styles}
ignoredTags={['script']}
debug={false}
staticContentMaxWidth={WIDTH - 33}
imagesInitialDimensions={_initialDimensions}
baseFontStyle={styles.text}
imagesMaxWidth={isComment ? WIDTH - 50 : WIDTH}
alterNode={e => _alterNode(e, isComment)}
alterData={e => _alterData(e)}
renderers={_customRenderer}
/>
</Fragment>
);
};
export default injectIntl(withNavigation(PostBody));
const areEqual = (prevProps, nextProps) => {
// console.log('prevProps, nextProps :', prevProps, nextProps);
if (prevProps.body !== nextProps.body) {
return true;
}
return false;
};
export default React.memo(injectIntl(withNavigation(PostBody)), areEqual);

View File

@ -55,7 +55,6 @@ class PostsContainer extends PureComponent {
tag,
isLoginDone,
isLoggedIn,
isDarkTheme,
nsfw,
} = this.props;
const { promotedPosts } = this.state;
@ -80,7 +79,6 @@ class PostsContainer extends PureComponent {
tag={tag}
isLoginDone={isLoginDone}
isLoggedIn={isLoggedIn}
isDarkTheme={isDarkTheme}
nsfw={nsfw}
/>
);
@ -89,7 +87,6 @@ class PostsContainer extends PureComponent {
const mapStateToProps = state => ({
currentAccount: state.account.currentAccount,
isDarkTheme: state.application.isDarkTheme,
isLoggedIn: state.application.isLoggedIn,
isLoginDone: state.application.isLoginDone,
nsfw: state.application.nsfw,

View File

@ -14,6 +14,7 @@ import { PostCard } from '../../postCard';
import { FilterBar } from '../../filterBar';
import { PostCardPlaceHolder, NoPost } from '../../basicUIElements';
import { POPULAR_FILTERS, PROFILE_FILTERS } from '../../../constants/options/filters';
import { ThemeContainer } from '../../../containers';
// Styles
import styles from './postsStyles';
@ -141,7 +142,6 @@ class PostsView extends Component {
? POPULAR_FILTERS[selectedFilterIndex].toLowerCase()
: PROFILE_FILTERS[selectedFilterIndex].toLowerCase();
let options;
const newPosts = [];
const limit = 3;
if (!isConnected) {
@ -362,7 +362,6 @@ class PostsView extends Component {
const {
filterOptions,
selectedOptionIndex,
isDarkTheme,
isHideImage,
handleImagesHide,
} = this.props;
@ -401,14 +400,18 @@ class PostsView extends Component {
onScrollEndDrag={this._handleOnScroll}
ListEmptyComponent={this._renderEmptyContent}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={this._handleOnRefreshPosts}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
<ThemeContainer>
{({ isDarkTheme }) => (
<RefreshControl
refreshing={refreshing}
onRefresh={this._handleOnRefreshPosts}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
)}
</ThemeContainer>
}
ref={ref => {
this.flatList = ref;

View File

@ -5,13 +5,14 @@ import get from 'lodash/get';
// Services and Actions
import { search } from '../../../providers/esteem/esteem';
import { lookupAccounts, getTrendingTags } from '../../../providers/steem/dsteem';
import { lookupAccounts, getTrendingTags, getPurePost } from '../../../providers/steem/dsteem';
// Constants
import { default as ROUTES } from '../../../constants/routeNames';
import ROUTES from '../../../constants/routeNames';
// Utilities
import { getResizedAvatar } from '../../../utils/image';
import postUrlParser from '../../../utils/postUrlParser';
// Component
import SearchModalView from '../view/searchModalView';
@ -41,31 +42,67 @@ class SearchModalContainer extends PureComponent {
_handleOnChangeSearchInput = text => {
const { isConnected } = this.props;
if (text && text.length < 2) return;
if (this.timer) {
clearTimeout(this.timer);
}
if (!isConnected) return;
this.timer = setTimeout(() => {
if (text && text !== '@' && text !== '#') {
if (text[0] === '@') {
lookupAccounts(text.substr(1)).then(res => {
const users = res.map(item => ({
image: getResizedAvatar(item),
text: item,
...item,
}));
this.setState({ searchResults: { type: 'user', data: users } });
});
} else if (text[0] === '#') {
getTrendingTags(text.substr(1)).then(res => {
const tags = res.map(item => ({
text: `#${get(item, 'name', '')}`,
...item,
}));
if (text && text !== '@' && text !== '#') {
if (text[0] === '@') {
lookupAccounts(text.substr(1)).then(res => {
const users = res.map(item => ({
image: getResizedAvatar(item),
text: item,
...item,
}));
this.setState({ searchResults: { type: 'user', data: users } });
});
} else if (text[0] === '#') {
getTrendingTags(text.substr(1)).then(res => {
const tags = res.map(item => ({
text: `#${get(item, 'name', '')}`,
...item,
}));
this.setState({ searchResults: { type: 'tag', data: tags } });
});
this.setState({ searchResults: { type: 'tag', data: tags } });
});
} else if (text.includes('https')) {
const postUrl = postUrlParser(text.replace(/\s/g, ''));
if (postUrl) {
const { author, permlink } = postUrl;
if (author) {
if (permlink) {
getPurePost(author, permlink).then(post => {
if (post.id !== 0) {
const result = {};
const metadata = JSON.parse(get(post, 'json_metadata', ''));
if (get(metadata, 'image', false) && metadata.image.length > 0) {
result.image = metadata.image[0];
} else {
result.image = getResizedAvatar(author);
}
result.author = author;
result.text = post.title;
result.permlink = permlink;
this.setState({ searchResults: { type: 'content', data: [result] } });
} else {
this.setState({ searchResults: { type: 'content', data: [] } });
}
});
} else {
lookupAccounts(author).then(res => {
const users = res.map(item => ({
image: getResizedAvatar(item),
text: item,
...item,
}));
this.setState({ searchResults: { type: 'user', data: users } });
});
}
}
} else {
search({ q: text }).then(res => {
res.results = res.results
@ -79,7 +116,7 @@ class SearchModalContainer extends PureComponent {
});
}
}
}, 500);
}
};
_handleOnPressListItem = (type, item) => {

View File

@ -1,21 +1,22 @@
import React from 'react';
import { TextInput } from 'react-native';
import { connect } from 'react-redux';
import { ThemeContainer } from '../../../containers';
// Styles
import styles from './textInputStyles';
const TextInputView = ({ isDarkTheme, innerRef, height, style, ...props }) => (
<TextInput
ref={innerRef}
keyboardAppearance={isDarkTheme ? 'dark' : 'light'}
{...props}
style={[styles.input, { minHeight: height }, style]}
/>
const TextInputView = ({ innerRef, height, style, ...props }) => (
<ThemeContainer>
{({ isDarkTheme }) => (
<TextInput
ref={innerRef}
keyboardAppearance={isDarkTheme ? 'dark' : 'light'}
{...props}
style={[styles.input, { minHeight: height }, style]}
/>
)}
</ThemeContainer>
);
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(TextInputView);
export default TextInputView;

View File

@ -1,36 +0,0 @@
import React, { Component } from 'react';
import { withNavigation } from 'react-navigation';
// Constants
import ROUTES from '../../../constants/routeNames';
// Component
import VotersDisplayView from '../view/votersDisplayView';
/*
* Props Name Description Value
*@props --> props name here description here Value Type Here
*
*/
class VotersDisplayContainer extends Component {
_handleOnUserPress = username => {
const { navigation } = this.props;
navigation.navigate({
routeName: ROUTES.SCREENS.PROFILE,
params: {
username,
},
key: username,
});
};
render() {
const { votes } = this.props;
return <VotersDisplayView handleOnUserPress={this._handleOnUserPress} votes={votes} />;
}
}
export default withNavigation(VotersDisplayContainer);

View File

@ -1,5 +1,4 @@
import VotersDisplayView from './view/votersDisplayView';
import VotersDisplay from './container/votersDisplayContainer';
import VotersDisplay from './view/votersDisplayView';
export { VotersDisplay, VotersDisplayView };
export { VotersDisplay };
export default VotersDisplay;

View File

@ -2,6 +2,7 @@ import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
flex: 1,
padding: 8,
flexDirection: 'row',
height: '$deviceHeight - 150',

View File

@ -1,24 +1,34 @@
import React, { Component } from 'react';
import { View, FlatList, Text } from 'react-native';
import { injectIntl } from 'react-intl';
import React from 'react';
import { SafeAreaView, FlatList, Text } from 'react-native';
import { withNavigation } from 'react-navigation';
import { useIntl } from 'react-intl';
// Utils
import { getTimeFromNow } from '../../../utils/time';
// Components
import { UserListItem } from '../../basicUIElements';
// Constants
import ROUTES from '../../../constants/routeNames';
// Styles
import styles from './votersDisplayStyles';
class VotersDisplayView extends Component {
/* Props
* ------------------------------------------------
* @prop { type } name - Description....
*/
const VotersDisplayView = ({ votes, navigation }) => {
const intl = useIntl();
// Component Functions
_renderItem = (item, index) => {
const { handleOnUserPress } = this.props;
const _handleOnUserPress = username => {
navigation.navigate({
routeName: ROUTES.SCREENS.PROFILE,
params: {
username,
},
key: username,
});
};
const _renderItem = (item, index) => {
const value = `$ ${item.value}`;
const percent = `${item.percent}%`;
@ -30,35 +40,31 @@ class VotersDisplayView extends Component {
isHasRightItem
isRightColor={item.is_down_vote}
rightText={value}
handleOnPress={() => handleOnUserPress(item.voter)}
handleOnPress={() => _handleOnUserPress(item.voter)}
isClickable
subRightText={percent}
/>
);
};
render() {
const { votes, intl } = this.props;
return (
<SafeAreaView style={styles.container}>
{votes && votes.length > 0 ? (
<FlatList
data={votes}
keyExtractor={item => item.voter}
removeClippedSubviews={false}
renderItem={({ item, index }) => _renderItem(item, index)}
/>
) : (
<Text style={styles.text}>
{intl.formatMessage({
id: 'voters.no_user',
})}
</Text>
)}
</SafeAreaView>
);
};
return (
<View style={styles.container}>
{votes.length > 0 ? (
<FlatList
data={votes}
keyExtractor={item => item.voter}
removeClippedSubviews={false}
renderItem={({ item, index }) => this._renderItem(item, index)}
/>
) : (
<Text style={styles.text}>
{intl.formatMessage({
id: 'voters.no_user',
})}
</Text>
)}
</View>
);
}
}
export default injectIntl(VotersDisplayView);
export default withNavigation(VotersDisplayView);

View File

@ -137,7 +137,7 @@ class WalletContainer extends Component {
};
render() {
const { currentAccount, selectedUser, isDarkTheme, handleOnScroll } = this.props;
const { currentAccount, selectedUser, handleOnScroll } = this.props;
const { walletData, isClaiming, isRefreshing } = this.state;
return (
@ -149,7 +149,6 @@ class WalletContainer extends Component {
isClaiming={isClaiming}
handleOnWalletRefresh={this._handleOnWalletRefresh}
isRefreshing={isRefreshing}
isDarkTheme={isDarkTheme}
handleOnScroll={handleOnScroll}
/>
);
@ -159,7 +158,6 @@ class WalletContainer extends Component {
const mapStateToProps = state => ({
currentAccount: state.account.currentAccount,
pinCode: state.application.pin,
isDarkTheme: state.application.isDarkTheme,
globalProps: state.account.globalProps,
});

View File

@ -10,6 +10,7 @@ import { CollapsibleCard } from '../../collapsibleCard';
import { WalletDetails } from '../../walletDetails';
import { Transaction } from '../../transaction';
import { WalletDetailsPlaceHolder } from '../../basicUIElements';
import { ThemeContainer } from '../../../containers';
// Styles
import styles from './walletStyles';
@ -53,7 +54,6 @@ class WalletView extends PureComponent {
isRefreshing,
selectedUsername,
walletData,
isDarkTheme,
handleOnScroll,
} = this.props;
@ -62,14 +62,18 @@ class WalletView extends PureComponent {
onScroll={handleOnScroll && handleOnScroll}
style={styles.scrollView}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={handleOnWalletRefresh}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
<ThemeContainer>
{isDarkTheme => (
<RefreshControl
refreshing={isRefreshing}
onRefresh={handleOnWalletRefresh}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
)}
</ThemeContainer>
}
>
{!walletData ? (

View File

@ -5,6 +5,7 @@ import ProfileEditContainer from './profileEditContainer';
import RedeemContainer from './redeemContainer';
import SpinGameContainer from './spinGameContainer';
import TransferContainer from './transferContainer';
import ThemeContainer from './themeContainer';
export {
InAppPurchaseContainer,
@ -14,4 +15,5 @@ export {
RedeemContainer,
SpinGameContainer,
TransferContainer,
ThemeContainer,
};

View File

@ -231,7 +231,6 @@ class PointsContainer extends Component {
const {
balance,
isClaiming,
isDarkTheme,
isLoading,
navigationParams,
refreshing,
@ -257,7 +256,6 @@ class PointsContainer extends Component {
handleOnDropdownSelected: this._handleOnDropdownSelected,
handleOnPressTransfer: this._handleOnPressTransfer,
isClaiming,
isDarkTheme,
isLoading,
navigationParams,
refreshing,
@ -271,7 +269,6 @@ class PointsContainer extends Component {
const mapStateToProps = state => ({
username: state.account.currentAccount.name,
isDarkTheme: state.application.isDarkTheme,
activeBottomTab: state.ui.activeBottomTab,
isConnected: state.application.isConnected,
accounts: state.account.otherAccounts,

View File

@ -140,7 +140,6 @@ class RedeemContainer extends Component {
const mapStateToProps = state => ({
username: state.account.currentAccount.name,
isDarkTheme: state.application.isDarkTheme,
activeBottomTab: state.ui.activeBottomTab,
isConnected: state.application.isConnected,
accounts: state.account.otherAccounts,

View File

@ -0,0 +1,18 @@
/* eslint-disable no-unused-vars */
import React from 'react';
import { connect } from 'react-redux';
const ThemeContainer = ({ children, isDarkTheme }) => {
return (
children &&
children({
isDarkTheme,
})
);
};
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
});
export default connect(mapStateToProps)(ThemeContainer);

View File

@ -1,3 +1,4 @@
/* eslint-disable curly */
import { Component } from 'react';
import { Platform, BackHandler, Alert, Linking, AppState } from 'react-native';
import NetInfo from '@react-native-community/netinfo';
@ -12,6 +13,10 @@ import { NavigationActions } from 'react-navigation';
import { bindActionCreators } from 'redux';
import EStyleSheet from 'react-native-extended-stylesheet';
import { forEach, isEmpty, some } from 'lodash';
import {
initialMode as nativeThemeInitialMode,
eventEmitter as nativeThemeEventEmitter,
} from 'react-native-dark-mode';
// Constants
import AUTH_TYPE from '../../../constants/authType';
@ -96,7 +101,6 @@ class ApplicationContainer extends Component {
componentDidMount = () => {
const { isIos } = this.state;
this._setNetworkListener();
if (!isIos) BackHandler.addEventListener('hardwareBackPress', this._onBackPress);
@ -111,6 +115,14 @@ class ApplicationContainer extends Component {
setPreviousAppState();
this._createPushListener();
if (nativeThemeEventEmitter) {
nativeThemeEventEmitter.on('currentModeChanged', newMode => {
const { dispatch } = this.props;
dispatch(isDarkTheme(newMode === 'dark'));
});
}
};
UNSAFE_componentWillReceiveProps(nextProps) {
@ -527,7 +539,7 @@ class ApplicationContainer extends Component {
const settings = await getSettings();
if (settings) {
if (settings.isDarkTheme !== '') dispatch(isDarkTheme(settings.isDarkTheme));
dispatch(isDarkTheme(nativeThemeInitialMode === 'dark' || settings.isDarkTheme));
if (settings.isPinCodeOpen !== '') dispatch(isPinCodeOpen(settings.isPinCodeOpen));
if (settings.language !== '') dispatch(setLanguage(settings.language));
if (settings.server !== '') dispatch(setApi(settings.server));

View File

@ -1,4 +1,4 @@
import React, { Fragment } from 'react';
import React, { Fragment, useEffect, useState } from 'react';
import ApplicationScreen from './screen/applicationScreen';
import ApplicationContainer from './container/applicationContainer';
@ -7,43 +7,54 @@ import Launch from '../launch';
import { Modal } from '../../components';
import { PinCode } from '../pinCode';
const Application = () => (
<ApplicationContainer>
{({
isConnected,
locale,
toastNotification,
isReady,
isDarkTheme,
isRenderRequire,
isThemeReady,
isPinCodeRequire,
}) => {
if (!isReady || !isRenderRequire || !isThemeReady) {
return <Launch />;
}
return (
<Fragment>
<Modal
isOpen={isPinCodeRequire}
isFullScreen
swipeToClose={false}
backButtonClose={false}
>
<PinCode />
</Modal>
<ApplicationScreen
isConnected={isConnected}
locale={locale}
toastNotification={toastNotification}
isReady={isReady}
isDarkTheme={isDarkTheme}
/>
</Fragment>
);
}}
</ApplicationContainer>
);
const Application = () => {
const [showAnimation, setShowAnimation] = useState(true);
useEffect(() => {
setTimeout(() => {
setShowAnimation(false);
}, 500);
}, []);
return (
<ApplicationContainer>
{({
isConnected,
locale,
toastNotification,
isReady,
isDarkTheme,
isRenderRequire,
isThemeReady,
isPinCodeRequire,
}) => {
if (showAnimation || !isReady || !isRenderRequire || !isThemeReady) {
return <Launch />;
}
return (
<Fragment>
<Modal
isOpen={isPinCodeRequire}
isFullScreen
swipeToClose={false}
backButtonClose={false}
>
<PinCode />
</Modal>
<ApplicationScreen
isConnected={isConnected}
locale={locale}
toastNotification={toastNotification}
isReady={isReady}
isDarkTheme={isDarkTheme}
/>
</Fragment>
);
}}
</ApplicationContainer>
);
};
export default Application;

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,12 @@
import React from 'react';
import { View, Image } from 'react-native';
import { View } from 'react-native';
import LottieView from 'lottie-react-native';
import LOGO from '../../../assets/launch_screen.png';
import styles from './launchStyles';
const LaunchScreen = () => (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Image
source={LOGO}
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
resizeMode="contain"
/>
<View style={styles.container}>
<LottieView source={require('./animation.json')} autoPlay loop={false} />
</View>
);

View File

@ -0,0 +1,9 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});

View File

@ -119,6 +119,7 @@ class LoginScreen extends PureComponent {
type="username"
isFirstImage
value={username}
inputStyle={styles.input}
/>
<FormInput
rightIconName="lock"
@ -131,6 +132,7 @@ class LoginScreen extends PureComponent {
isEditable
secureTextEntry
type="password"
inputStyle={styles.input}
/>
<InformationArea
description={intl.formatMessage({

View File

@ -39,4 +39,7 @@ export default EStyleSheet.create({
marginHorizontal: 30,
marginVertical: 10,
},
input: {
color: '$primaryDarkText',
},
});

View File

@ -151,13 +151,12 @@ class NotificationContainer extends Component {
render() {
const { isLoggedIn } = this.props;
const { notifications, isNotificationRefreshing, isDarkTheme } = this.state;
const { notifications, isNotificationRefreshing } = this.state;
return (
<NotificationScreen
getActivities={this._getAvtivities}
notifications={notifications}
isDarkTheme={isDarkTheme}
navigateToNotificationRoute={this._navigateToNotificationRoute}
readAllNotification={this._readAllNotification}
handleLoginPress={this._handleOnPressLogin}
@ -171,7 +170,6 @@ class NotificationContainer extends Component {
const mapStateToProps = state => ({
isLoggedIn: state.application.isLoggedIn,
isDarkTheme: state.application.isDarkTheme,
isConnected: state.application.isConnected,
username: state.account.currentAccount.name,

View File

@ -25,7 +25,6 @@ const PointsScreen = ({ isLoggedIn, handleLoginPress }) => {
claimPoints,
fetchUserActivity,
isClaiming,
isDarkTheme,
isLoading,
refreshing,
userActivities,
@ -35,7 +34,6 @@ const PointsScreen = ({ isLoggedIn, handleLoginPress }) => {
claimPoints={claimPoints}
fetchUserActivity={fetchUserActivity}
isClaiming={isClaiming}
isDarkTheme={isDarkTheme}
isLoading={isLoading}
refreshing={refreshing}
userActivities={userActivities}

View File

@ -1,12 +1,12 @@
import React from 'react';
import { View, FlatList } from 'react-native';
import { View, FlatList, SafeAreaView } from 'react-native';
import { useIntl } from 'react-intl';
// Constants
import get from 'lodash/get';
// Components
import { BasicHeader, UserListItem } from '../../../components';
// Container
import AccountListContainer from '../../../containers/accountListContainer';
// Utils
@ -31,13 +31,12 @@ const ReblogScreen = ({ navigation }) => {
id: 'reblog.title',
});
const activeVotes =
navigation.state && navigation.state.params && navigation.state.params.reblogs;
const activeVotes = get(navigation, 'state.params.reblogs');
return (
<AccountListContainer data={activeVotes} navigation={navigation}>
{({ data, filterResult, handleSearch, handleOnUserPress }) => (
<View style={globalStyles.container}>
<SafeAreaView style={globalStyles.container}>
<BasicHeader
title={`${headerTitle} (${data && data.length})`}
isHasSearch
@ -49,7 +48,7 @@ const ReblogScreen = ({ navigation }) => {
removeClippedSubviews={false}
renderItem={({ item, index }) => renderUserListItem(item, index, handleOnUserPress)}
/>
</View>
</SafeAreaView>
)}
</AccountListContainer>
);

View File

@ -1,8 +1,7 @@
import React from 'react';
import { View } from 'react-native';
import { SafeAreaView } from 'react-native';
import { useIntl } from 'react-intl';
// Constants
import get from 'lodash/get';
// Components
import { BasicHeader, FilterBar, VotersDisplay } from '../../../components';
@ -20,13 +19,12 @@ const VotersScreen = ({ navigation }) => {
id: 'voters.voters_info',
});
const activeVotes =
navigation.state && navigation.state.params && navigation.state.params.activeVotes;
const activeVotes = get(navigation, 'state.params.activeVotes');
return (
<AccountListContainer data={activeVotes}>
{({ data, filterResult, handleOnVotersDropdownSelect, handleSearch }) => (
<View style={globalStyles.container}>
<SafeAreaView style={globalStyles.container}>
<BasicHeader
title={`${headerTitle} (${data && data.length})`}
isHasSearch
@ -43,7 +41,7 @@ const VotersScreen = ({ navigation }) => {
onDropdownSelect={handleOnVotersDropdownSelect}
/>
<VotersDisplay votes={filterResult || data} />
</View>
</SafeAreaView>
)}
</AccountListContainer>
);

View File

@ -25,13 +25,14 @@ export const parsePost = async (post, currentUserName, isPromoted) => {
if (!post) {
return null;
}
const activeVotes = await getActiveVotes(get(post, 'author'), get(post, 'permlink'));
if (currentUserName === post.author) {
post.markdownBody = post.body;
}
post.is_promoted = isPromoted;
post.json_metadata = JSON.parse(post.json_metadata);
post.image = postImage(post.json_metadata, post.body);
post.active_votes = activeVotes;
post.vote_count = post.active_votes.length;
post.author_reputation = getReputation(post.author_reputation);
post.avatar = getResizedAvatar(get(post, 'author'));

View File

@ -0,0 +1,75 @@
export default url => {
const parseCatAuthorPermlink = u => {
const postRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
const postMatch = u.match(postRegex);
if (postMatch && postMatch.length === 5) {
return {
author: postMatch[3].replace('@', ''),
permlink: postMatch[4],
};
}
const authorRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)/i;
const authorMatch = u.match(authorRegex);
if (authorMatch && authorMatch.length === 4) {
return {
author: authorMatch[3].replace('@', ''),
permlink: null,
};
}
return null;
};
const parseAuthorPermlink = u => {
const r = /^https?:\/\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
const match = u.match(r);
if (match && match.length === 4) {
return {
author: match[2].replace('@', ''),
permlink: match[3],
};
}
const authorRegex = /^https?:\/\/(.*)\/(@[\w.\d-]+)/i;
const authorMatch = u.match(authorRegex);
if (authorMatch && authorMatch.length === 3) {
return {
author: authorMatch[2].replace('@', ''),
permlink: null,
};
}
return null;
};
if (
['https://esteem.app', 'https://steemit.com', 'https://steempeak.com'].some(x =>
url.startsWith(x),
)
) {
return parseCatAuthorPermlink(url);
}
if (['https://busy.org', 'https://steemhunt.com'].some(x => url.startsWith(x))) {
return parseAuthorPermlink(url);
}
// For non urls like @good-karma/esteem-london-presentation-e3105ba6637ed
let match = url.match(/^[/]?(@[\w.\d-]+)\/(.*)/);
if (match && match.length === 3) {
return {
author: match[1].replace('@', ''),
permlink: match[2],
};
}
// For non urls with category like esteem/@good-karma/esteem-london-presentation-e3105ba6637ed
match = url.match(/^[/]?([\w.\d-]+)\/(@[\w.\d-]+)\/(.*)/);
if (match && match.length === 4) {
return {
category: match[1],
author: match[2].replace('@', ''),
permlink: match[3],
};
}
return null;
};

View File

@ -1476,6 +1476,11 @@
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
"@types/events@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
@ -1519,6 +1524,14 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/react-native@*":
version "0.60.21"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.60.21.tgz#81a41cae7b232f52ab3983d854f4a0b0df79531e"
integrity sha512-E7F+P/UG4Utu+kh8Hy544i0m4CzpHw1awNX6hVfkhlu4mXSlAn6KLZzKEkPBbHm7g1kspmZTiuP23HAKZpASPw==
dependencies:
"@types/prop-types" "*"
"@types/react" "*"
"@types/react@*":
version "16.9.5"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.5.tgz#079dabd918b19b32118c25fd00a786bb6d0d5e51"
@ -3093,6 +3106,11 @@ decompress@^4.2.0:
pify "^2.3.0"
strip-dirs "^2.0.0"
dedent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb"
integrity sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s=
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@ -3854,6 +3872,11 @@ events@^1.1.0:
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
events@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==
evp_bytestokey@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
@ -6108,6 +6131,21 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lottie-ios@3.1.3, lottie-ios@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/lottie-ios/-/lottie-ios-3.1.3.tgz#dfa18a3a7e66e5d4a6665bf0a2392d143d15661a"
integrity sha512-FKSx9l5Ekwm1Wt/ncoCwvsq8NAb1nylzMFlxrHixLYNBtO2eCQet+vwQag+74Nc/E9Lp3DKkBUCyBfz+zjtmAw==
lottie-react-native@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/lottie-react-native/-/lottie-react-native-3.2.1.tgz#0b2b13b03a2cda9ece8474b9cf633d0fbe78d82b"
integrity sha512-dmOySV+qgFrQszCY+7uOZR0XkgbP2FXgCWJZ2h39GqlxJZRHD2uCmXoT+WxaBGw83Gk/2KfIQ1MQMFL8UqC2bw==
dependencies:
invariant "^2.2.2"
lottie-ios "^3.1.3"
prop-types "^15.5.10"
react-native-safe-modules "^1.0.0"
lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
@ -7676,6 +7714,17 @@ react-native-config@luggit/react-native-config#master:
version "0.11.7"
resolved "https://codeload.github.com/luggit/react-native-config/tar.gz/89a602bf8be3808838403a97afaf915caeec76c2"
react-native-dark-mode@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/react-native-dark-mode/-/react-native-dark-mode-0.1.2.tgz#4afd760073d5eb02bb83fc09004733d036e9f2d8"
integrity sha512-oCanZ5LBJvhmgNCG2uPtvKRfBZ85nBCz/2UHkizXDt3t7ep1Vp994REye/RkIW86bbpPH/Dt8QUHExw5R0ftpg==
dependencies:
"@types/events" "*"
"@types/react" "*"
"@types/react-native" "*"
events "^3.0.0"
toolkit.ts "^0.0.2"
react-native-datepicker@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/react-native-datepicker/-/react-native-datepicker-1.7.2.tgz#58d0822591a0ac9b32aba082650222a0ee29669d"
@ -7782,6 +7831,13 @@ react-native-safe-area-view@^0.14.1, react-native-safe-area-view@^0.14.6:
dependencies:
hoist-non-react-statics "^2.3.1"
react-native-safe-modules@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/react-native-safe-modules/-/react-native-safe-modules-1.0.0.tgz#10a918adf97da920adb1e33e0c852b1e80123b65"
integrity sha512-ShT8duWBT30W4OFcltZl+UvpPDikZFURvLDQqAsrvbyy6HzWPGJDCpdqM+6GqzPPs4DPEW31YfMNmdJcZ6zI2w==
dependencies:
dedent "^0.6.0"
"react-native-screens@^1.0.0 || ^1.0.0-alpha", react-native-screens@^1.0.0-alpha.23:
version "1.0.0-alpha.23"
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-1.0.0-alpha.23.tgz#25d7ea4d11bda4fcde2d1da7ae50271c6aa636e0"
@ -9332,6 +9388,11 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
toolkit.ts@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/toolkit.ts/-/toolkit.ts-0.0.2.tgz#91bde730e5e6ad1a22146cdaf83f4a52721cf3b2"
integrity sha512-yJJTVbCwiD6AfFgReewJCGJuODmyZUeL1sDjnxp33t0UBxnezgQrLbz/F9++RC28CTlk5u5pVji4TbeondYEkw==
tough-cookie@^2.3.3, tough-cookie@^2.3.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"