diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf index ecbc761ef..953d567b2 100644 Binary files a/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf and b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf index 36a7de36c..235101c2d 100644 Binary files a/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf and b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf index 2a0551269..7c92e986f 100644 Binary files a/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf and b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf differ diff --git a/ios/eSteem.xcodeproj/project.pbxproj b/ios/eSteem.xcodeproj/project.pbxproj index 2e88475cf..50e8fbe2b 100644 --- a/ios/eSteem.xcodeproj/project.pbxproj +++ b/ios/eSteem.xcodeproj/project.pbxproj @@ -5,7 +5,6 @@ }; objectVersion = 46; objects = { - /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; @@ -452,6 +451,27 @@ remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; + 94D7D3C421B3E7F100476275 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1E5BA5C385A94A9996A8961A /* AppCenterReactNativePush.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = BA189FAA1EEE74F100CAD13F; + remoteInfo = AppCenterReactNativePush; + }; + 94D7D3CC21B3E7F100476275 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTAnimation; + }; + 94D7D3CE21B3E7F100476275 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 2D2A28201D9B03D100D4039D; + remoteInfo = "RCTAnimation-tvOS"; + }; ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; @@ -473,6 +493,7 @@ 00E356F21AD99517003FC87E /* eSteemTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = eSteemTests.m; sourceTree = ""; }; 044930AF6BF7488DA7F02A8F /* RobotoMono-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "RobotoMono-Regular.ttf"; path = "../src/assets/Fonts/RobotoMono-Regular.ttf"; sourceTree = ""; }; 08EFE8017CAE493492474D23 /* AppCenterReactNativeAnalytics.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = AppCenterReactNativeAnalytics.xcodeproj; path = "../node_modules/appcenter-analytics/ios/AppCenterReactNativeAnalytics.xcodeproj"; sourceTree = ""; }; + 0C51B07921B45A3500E7A2D1 /* eSteem.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = eSteem.entitlements; path = eSteem/eSteem.entitlements; sourceTree = ""; }; 11DD9F9D560A49FAB7A23E9D /* BVLinearGradient.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = BVLinearGradient.xcodeproj; path = "../node_modules/react-native-linear-gradient/BVLinearGradient.xcodeproj"; sourceTree = ""; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; @@ -993,6 +1014,14 @@ name = Resources; sourceTree = ""; }; + 94D7D3B521B3E7EE00476275 /* Products */ = { + isa = PBXGroup; + children = ( + 94D7D3C521B3E7F100476275 /* libAppCenterReactNativePush.a */, + ); + name = Products; + sourceTree = ""; + }; ADBDB9201DFEBF0600ED6528 /* Products */ = { isa = PBXGroup; children = ( @@ -1598,6 +1627,27 @@ remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 94D7D3C521B3E7F100476275 /* libAppCenterReactNativePush.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libAppCenterReactNativePush.a; + remoteRef = 94D7D3C421B3E7F100476275 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 94D7D3CD21B3E7F100476275 /* libRCTAnimation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTAnimation.a; + remoteRef = 94D7D3CC21B3E7F100476275 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 94D7D3CF21B3E7F100476275 /* libRCTAnimation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTAnimation.a; + remoteRef = 94D7D3CE21B3E7F100476275 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; diff --git a/ios/eSteem/Info.plist b/ios/eSteem/Info.plist index 69dfd25f6..2de3682eb 100755 --- a/ios/eSteem/Info.plist +++ b/ios/eSteem/Info.plist @@ -40,7 +40,7 @@ NSCameraUsageDescription Camera Usage Access NSLocationWhenInUseUsageDescription - + NSMicrophoneUsageDescription Microphone Usage Access NSPhotoLibraryAddUsageDescription diff --git a/src/components/basicHeader/view/basicHeaderStyles.js b/src/components/basicHeader/view/basicHeaderStyles.js index c7ebf85fa..cbee00667 100644 --- a/src/components/basicHeader/view/basicHeaderStyles.js +++ b/src/components/basicHeader/view/basicHeaderStyles.js @@ -43,7 +43,6 @@ export default EStyleSheet.create({ color: '$iconColor', justifyContent: 'center', alignSelf: 'center', - marginRight: 10, }, iconButton: { marginRight: 24, diff --git a/src/components/basicHeader/view/basicHeaderView.js b/src/components/basicHeader/view/basicHeaderView.js index f016bd476..0ef4d2a95 100644 --- a/src/components/basicHeader/view/basicHeaderView.js +++ b/src/components/basicHeader/view/basicHeaderView.js @@ -15,10 +15,10 @@ import styles from './basicHeaderStyles'; class BasicHeaderView extends Component { /* Props - * ------------------------------------------------ - * @prop { boolean } isFormValid - Righst button propertie - * @prop { string } quickTitle - Left side behind back button text - */ + * ------------------------------------------------ + * @prop { boolean } isFormValid - Righst button propertie + * @prop { string } quickTitle - Left side behind back button text + */ constructor(props) { super(props); @@ -58,24 +58,26 @@ class BasicHeaderView extends Component { render() { const { handleOnPressBackButton, - handleOnPressPreviewButton, - isPreviewActive, - quickTitle, - isFormValid, - title, - isHasIcons, - rightIconName, - isHasDropdown, - handleRightIconPress, - isModalHeader, handleOnPressClose, + handleOnPressPreviewButton, + handleOnSaveButtonPress, + handleRightIconPress, + intl, + isDraftSaved, + isDraftSaving, + isFormValid, + isHasDropdown, + isHasIcons, isHasSearch, isLoading, - handleOnSaveButtonPress, - isDraftSaving, - isDraftSaved, isLoggedIn, - intl, + isModalHeader, + isPostSending, + isPreviewActive, + isReply, + quickTitle, + rightIconName, + title, } = this.props; const { isInputVisible } = this.state; return ( @@ -120,15 +122,14 @@ class BasicHeaderView extends Component { )} - {rightIconName - && !isHasSearch && ( - handleRightIconPress()} - iconStyle={styles.rightIcon} - name={rightIconName} - /> + {rightIconName && !isHasSearch && ( + handleRightIconPress()} + iconStyle={styles.rightIcon} + name={rightIconName} + /> )} {isInputVisible && ( @@ -178,7 +179,7 @@ class BasicHeaderView extends Component { onPress={isFormValid && this._handleOnPress} style={styles.textButtonWrapper} text={intl.formatMessage({ - id: 'basic_header.publish', + id: isReply ? 'basic_header.reply' : 'basic_header.publish', })} /> ) : ( diff --git a/src/components/comments/container/commentsContainer.js b/src/components/comments/container/commentsContainer.js index 703e24548..2074fbccd 100644 --- a/src/components/comments/container/commentsContainer.js +++ b/src/components/comments/container/commentsContainer.js @@ -1,4 +1,6 @@ import React, { Component } from 'react'; +import { withNavigation } from 'react-navigation'; + import { getComments } from '../../../providers/steem/dsteem'; // Services and Actions @@ -6,6 +8,7 @@ import { getComments } from '../../../providers/steem/dsteem'; // Middleware // Constants +import { default as ROUTES } from '../../../constants/routeNames'; // Utilities @@ -13,10 +16,10 @@ import { getComments } from '../../../providers/steem/dsteem'; import { CommentsView } from '..'; /* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ + * Props Name Description Value + *@props --> props name here description here Value Type Here + * + */ class CommentsContainer extends Component { constructor(props) { @@ -35,18 +38,23 @@ class CommentsContainer extends Component { this.setState({ comments, }); - console.log(comments); }) .catch((error) => { - alert(error); + // alert(error); }); } // Component Functions - _handleOnReplyPress = () => { - alert( - 'Reply functions not working yet. Thank you for your understanding. Your friends at eSteem :)', - ); + _handleOnReplyPress = (item) => { + const { navigation } = this.props; + + navigation.navigate({ + routeName: ROUTES.SCREENS.EDITOR, + params: { + isReply: true, + post: item, + }, + }); }; render() { @@ -62,4 +70,4 @@ class CommentsContainer extends Component { } } -export default CommentsContainer; +export default withNavigation(CommentsContainer); diff --git a/src/components/comments/view/commentsView.js b/src/components/comments/view/commentsView.js index 75125d3c0..c0c756979 100644 --- a/src/components/comments/view/commentsView.js +++ b/src/components/comments/view/commentsView.js @@ -14,9 +14,9 @@ import { IconButton } from '../../iconButton'; class CommentsView extends Component { /* Props - * ------------------------------------------------ - * @prop { type } name - Description.... - */ + * ------------------------------------------------ + * @prop { type } name - Description.... + */ constructor(props) { super(props); @@ -67,12 +67,12 @@ class CommentsView extends Component { > - + handleOnReplyPress && handleOnReplyPress()} + onPress={() => handleOnReplyPress && handleOnReplyPress(item)} iconType="FontAwesome" /> diff --git a/src/components/editorElements/index.js b/src/components/editorElements/index.js index 51b5ac968..494edc0bd 100644 --- a/src/components/editorElements/index.js +++ b/src/components/editorElements/index.js @@ -1,5 +1,8 @@ -import TitleArea from './titleArea/view/titleAreaView'; +import SummaryArea from './summaryArea/view/summaryAreaView'; import TagArea from './tagArea/view/tagAreaView'; import TextArea from './textArea/view/textAreaView'; +import TitleArea from './titleArea/view/titleAreaView'; -export { TitleArea, TagArea, TextArea }; +export { + SummaryArea, TagArea, TextArea, TitleArea, +}; diff --git a/src/components/editorElements/summaryArea/view/summaryAreaStyles.js b/src/components/editorElements/summaryArea/view/summaryAreaStyles.js new file mode 100644 index 000000000..a03395e01 --- /dev/null +++ b/src/components/editorElements/summaryArea/view/summaryAreaStyles.js @@ -0,0 +1,9 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + summaryText: { + color: '$primaryBlack', + fontWeight: 'bold', + fontSize: 10, + }, +}); diff --git a/src/components/editorElements/summaryArea/view/summaryAreaView.js b/src/components/editorElements/summaryArea/view/summaryAreaView.js new file mode 100644 index 000000000..cb10139fa --- /dev/null +++ b/src/components/editorElements/summaryArea/view/summaryAreaView.js @@ -0,0 +1,34 @@ +import React, { Component } from 'react'; +import { View, Text } from 'react-native'; +// Constants + +// Components +// Styles +import styles from './summaryAreaStyles'; +import globalStyles from '../../../../globalStyles'; + +export default class SummaryAreaView extends Component { + /* Props + * ------------------------------------------------ + * @prop { type } name - Description.... + */ + + constructor(props) { + super(props); + this.state = {}; + } + + // Component Life Cycles + + // Component Functions + + render() { + const { summary } = this.props; + + return ( + + {summary} + + ); + } +} diff --git a/src/components/editorElements/titleArea/view/titleAreaView.js b/src/components/editorElements/titleArea/view/titleAreaView.js index f379b64e8..c797356ba 100644 --- a/src/components/editorElements/titleArea/view/titleAreaView.js +++ b/src/components/editorElements/titleArea/view/titleAreaView.js @@ -11,9 +11,9 @@ import globalStyles from '../../../../globalStyles'; export default class TitleAreaView extends Component { /* Props - * ------------------------------------------------ - * @prop { type } name - Description.... - */ + * ------------------------------------------------ + * @prop { type } name - Description.... + */ constructor(props) { super(props); @@ -53,8 +53,9 @@ export default class TitleAreaView extends Component { autoFocus={autoFocus} numberOfLines={4} onChangeText={text => this._handleOnChange(text)} - value={value} - {...this.props} + // TODO: Fix it + // value={value && value} + // {...this.props} /> ); diff --git a/src/components/markdownEditor/view/markdownEditorView.js b/src/components/markdownEditor/view/markdownEditorView.js index 81f512234..9085c8e7b 100644 --- a/src/components/markdownEditor/view/markdownEditorView.js +++ b/src/components/markdownEditor/view/markdownEditorView.js @@ -3,13 +3,15 @@ import { View, KeyboardAvoidingView, ScrollView, FlatList, Text, ActionSheetIOS } from 'react-native'; import Markdown, { getUniqueID } from 'react-native-markdown-renderer'; + // Components -import Formats from './formats/formats'; -import { IconButton } from '../../iconButton'; import { DropdownButton } from '../../dropdownButton'; +import { IconButton } from '../../iconButton'; import { StickyBar } from '../../basicUIElements'; import { TextInput } from '../../textInput'; import applyImageLink from './formats/applyWebLinkFormat'; +import Formats from './formats/formats'; + // Styles import styles from './markdownEditorStyles'; import markdownStyle from './markdownPreviewStyles'; @@ -177,7 +179,7 @@ export default class MarkdownEditorView extends Component { }; render() { - const { isPreviewActive, intl } = this.props; + const { intl, isPreviewActive, isReply } = this.props; const { text, selection } = this.state; return ( @@ -188,7 +190,7 @@ export default class MarkdownEditorView extends Component { onChangeText={e => this._changeText(e)} onSelectionChange={this._handleOnSelectionChange} placeholder={intl.formatMessage({ - id: 'editor.description', + id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder', })} placeholderTextColor="#c1c5c7" selection={selection} diff --git a/src/components/postCard/view/postCardView.js b/src/components/postCard/view/postCardView.js index d324b1741..12eb82117 100644 --- a/src/components/postCard/view/postCardView.js +++ b/src/components/postCard/view/postCardView.js @@ -15,11 +15,11 @@ import styles from './postCardStyles'; class PostCard extends Component { /* Props - * ------------------------------------------------ - * @prop { string } description - Description texts. - * @prop { string } iconName - For icon render name. - * - */ + * ------------------------------------------------ + * @prop { string } description - Description texts. + * @prop { string } iconName - For icon render name. + * + */ constructor(props) { super(props); @@ -56,7 +56,7 @@ class PostCard extends Component { render() { const { - content, isLoggedIn, user, isShowImages, + content, isLoggedIn, user, isHideImage, } = this.props; // const likersText = `@${content.top_likers[0]}, @${content.top_likers[1]}, @${ // content.top_likers[2] @@ -68,14 +68,14 @@ class PostCard extends Component { this._handleOnContentPress()} > - {isShowImages && ( + {!isHideImage && ( - + this._handleOnVotersPress()} diff --git a/src/components/postElements/headerDescription/view/postHeaderDescription.js b/src/components/postElements/headerDescription/view/postHeaderDescription.js index 185395a9c..bd387427a 100644 --- a/src/components/postElements/headerDescription/view/postHeaderDescription.js +++ b/src/components/postElements/headerDescription/view/postHeaderDescription.js @@ -46,11 +46,17 @@ class PostHeaderDescription extends Component { tag, profileOnPress, tagOnPress, - isShowImages, + isHideImage, } = this.props; const _reputationText = `(${reputation})`; - const _avatar = isShowImages ? avatar && { uri: avatar } : null; + let _avatar; + + if (isHideImage) { + _avatar = null; + } else { + _avatar = avatar && { uri: avatar }; + } return ( diff --git a/src/components/postView/container/postDisplayContainer.js b/src/components/postView/container/postDisplayContainer.js index 506ee4948..c5b594221 100644 --- a/src/components/postView/container/postDisplayContainer.js +++ b/src/components/postView/container/postDisplayContainer.js @@ -15,10 +15,10 @@ import { default as ROUTES } from '../../../constants/routeNames'; import { PostDisplayView } from '..'; /* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ + * Props Name Description Value + *@props --> props name here description here Value Type Here + * + */ class PostDisplayContainer extends Component { constructor(props) { @@ -29,7 +29,7 @@ class PostDisplayContainer extends Component { // Component Life Cycle Functions // Component Functions - _handleVotersPress = (activeVotes) => { + _handleOnVotersPress = (activeVotes) => { const { navigation } = this.props; navigation.navigate({ @@ -40,12 +40,25 @@ class PostDisplayContainer extends Component { }); }; + _handleOnReplyPress = () => { + const { post, navigation } = this.props; + + navigation.navigate({ + routeName: ROUTES.SCREENS.EDITOR, + params: { + isReply: true, + post, + }, + }); + }; + render() { const { post, currentUser } = this.props; return ( diff --git a/src/components/postView/view/postDisplayView.js b/src/components/postView/view/postDisplayView.js index cbd28beeb..c68824669 100644 --- a/src/components/postView/view/postDisplayView.js +++ b/src/components/postView/view/postDisplayView.js @@ -56,19 +56,19 @@ class PostDisplayView extends Component { currentUser, handleOnReplyPress, handleOnEditPress, - handleVotersPress, + handleOnVotersPress, } = this.props; return ( - + handleVotersPress && handleVotersPress(post.active_votes)} + onPress={() => handleOnVotersPress && handleOnVotersPress(post.active_votes)} iconName="ios-people" /> { const { getFor, tag } = this.props; - const { isShowImages } = this.state; + const { isHideImage } = this.state; let options; _getFor ? (options = { limit: 3 }) : (options = { tag: _tag || tag, limit: 3 }); if (user) { - getPostsSummary(_getFor || getFor, options, user && user.name, isShowImages) + getPostsSummary(_getFor || getFor, options, user && user.name, isHideImage) .then((result) => { if (result) { this.setState({ @@ -72,7 +72,7 @@ class PostsView extends Component { _loadMore = () => { // TODO: merge above function with this func (after alpha). const { - posts, startAuthor, startPermlink, user, isShowImages, + posts, startAuthor, startPermlink, user, isHideImage, } = this.state; const { getFor, tag } = this.props; @@ -87,7 +87,7 @@ class PostsView extends Component { start_permlink: startPermlink, }, (user && user.name) || 'esteemapp', - isShowImages, + isHideImage, ).then((result) => { const _posts = result; _posts.shift(); @@ -132,14 +132,14 @@ class PostsView extends Component { }; _onRightIconPress = () => { - const { isShowImages } = this.state; + const { isHideImage } = this.state; - this.setState({ isShowImages: !isShowImages }); + this.setState({ isHideImage: !isHideImage }); }; render() { const { - refreshing, posts, user, isPostsLoading, isShowImages, + refreshing, posts, user, isPostsLoading, isHideImage, } = this.state; const { componentId, filterOptions, isLoggedIn } = this.props; @@ -166,7 +166,7 @@ class PostsView extends Component { content={item} user={user} isLoggedIn={isLoggedIn} - isShowImages={isShowImages} + isHideImage={isHideImage} /> )} keyExtractor={(post, index) => index.toString()} diff --git a/src/components/upvote/container/upvoteContainer.js b/src/components/upvote/container/upvoteContainer.js index cf6418974..512f4a1e0 100644 --- a/src/components/upvote/container/upvoteContainer.js +++ b/src/components/upvote/container/upvoteContainer.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -// import { connect } from 'react-redux'; +import { connect } from 'react-redux'; // Services and Actions @@ -13,10 +13,10 @@ import React, { Component } from 'react'; import { UpvoteView } from '..'; /* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ + * Props Name Description Value + *@props --> props name here description here Value Type Here + * + */ class UpvoteContainer extends Component { constructor(props) { @@ -33,8 +33,11 @@ class UpvoteContainer extends Component { } } -// const mapStateToProps = state => ({ -// user: state.user.user, -// }); +const mapStateToProps = state => ({ + isLoggedIn: state.application.isLoggedIn, -export default UpvoteContainer; + // TODO: Remove users as coming props. pass follow current account + currentAccount: state.account.currentAccount, +}); + +export default connect(mapStateToProps)(UpvoteContainer); diff --git a/src/components/upvote/view/upvoteView.js b/src/components/upvote/view/upvoteView.js index e4eb05945..0c9ba4bba 100644 --- a/src/components/upvote/view/upvoteView.js +++ b/src/components/upvote/view/upvoteView.js @@ -106,7 +106,7 @@ class UpvoteView extends Component { }; render() { - const { isLoggedIn, isShowpayoutValue, content } = this.props; + const { isLoggedIn, isShowPayoutValue, content } = this.props; const { isVoting, isModalVisible, amount, value, isVoted, } = this.state; @@ -136,7 +136,7 @@ class UpvoteView extends Component { iconType="AntDesign" name={isVoted ? 'upcircle' : 'upcircleo'} /> - {isShowpayoutValue && ( + {isShowPayoutValue && ( $ {' '} diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index d48316893..a7313724e 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -95,13 +95,16 @@ }, "basic_header": { "publish": "Publish", - "search": "Search" + "search": "Search", + "reply": "Reply" }, "editor": { "title": "Title", "tags": "tags", - "description": "What would you like to write about today?", - "publish": "Publish" + "default_placeholder": "What would you like to write about today?", + "reply_placeholder": "What would you like to write about above post?", + "publish": "Publish", + "reply": "Reply" }, "pincode": { "enter_text": "Enter pin to unlock", diff --git a/src/config/locales/tr-TR.json b/src/config/locales/tr-TR.json index 8dc7be5d3..9399955e6 100644 --- a/src/config/locales/tr-TR.json +++ b/src/config/locales/tr-TR.json @@ -95,13 +95,16 @@ }, "basic_header": { "publish": "Yayınla", - "search": "Ara" + "search": "Ara", + "reply": "Cevapla" }, "editor": { "title": "Başlık", "tags": "etiketler", - "description": "Bu gün ne hakkında yazmak istersin?", - "publish": "Yayınla" + "default_placeholder": "Bu gün ne hakkında yazmak istersin?", + "reply_placeholder": "Yukarıdaki yazi hakkinda nasil bir cevap yazmak istersin?", + "publish": "Yayınla", + "reply": "Cevapla" }, "pincode": { "enter_text": "Açmak için pin kodunu giriniz", diff --git a/src/providers/steem/dsteem.js b/src/providers/steem/dsteem.js index 131895b66..b6918a41c 100644 --- a/src/providers/steem/dsteem.js +++ b/src/providers/steem/dsteem.js @@ -7,6 +7,10 @@ import { Client, PrivateKey } from 'dsteem'; import { AsyncStorage } from 'react-native'; import { getUnreadActivityCount } from '../esteem/esteem'; +import sc2 from './steemConnectAPI'; + +// Utils +import { decryptKey } from '../../utils/crypto'; import { parsePosts, parsePost, parseComments, parsePostsSummary, @@ -90,10 +94,11 @@ export const getUser = async (user) => { } }; -//TODO: Move to utils folder -export const vestToSteem = async (vestingShares, totalVestingShares, totalVestingFundSteem) => { - return (parseFloat(totalVestingFundSteem) * (parseFloat(vestingShares) / parseFloat(totalVestingShares))).toFixed(0); -} +// TODO: Move to utils folder +export const vestToSteem = async (vestingShares, totalVestingShares, totalVestingFundSteem) => ( + parseFloat(totalVestingFundSteem) + * (parseFloat(vestingShares) / parseFloat(totalVestingShares)) +).toFixed(0); /** * @method getFollows get account data @@ -248,7 +253,6 @@ export const getUserComments = async (query) => { try { let comments = await client.database.getDiscussions('comments', query); comments = parseComments(comments); - console.log(comments); return comments; } catch (error) { return error; @@ -356,25 +360,6 @@ export const upvoteAmount = async (input) => { return estimated; }; -/** - * @method postComment post a comment/reply - * @param comment comment object { author, permlink, ... } - * @param PrivateKey Private posting key - */ -export const postComment = (comment, postingKey) => { - const key = PrivateKey.fromString(postingKey); - return new Promise((resolve, reject) => { - try { - client.broadcast.comment(comment, key).then((result) => { - resolve(result); - }); - } catch (error) { - console.log(error); - reject(error); - } - }); -}; - export const transferToken = (data, activeKey) => { const key = PrivateKey.fromString(activeKey); return new Promise((resolve, reject) => { @@ -624,3 +609,70 @@ export const lookupAccounts = async (username) => { throw error; } }; + +/** + * @method postComment post a comment/reply + * @param comment comment object { author, permlink, ... } + */ +export const postComment = ( + account, + digitPinCode, + parentAuthor, + parentPermlink, + permlink, + title, + body, + jsonMetadata, + options = null, + voteWeight = null, +) => { + const { name: author } = account; + + const opArray = [ + [ + 'comment', + { + parent_author: parentAuthor, + parent_permlink: parentPermlink, + author, + permlink, + title, + body, + json_metadata: JSON.stringify(jsonMetadata), + }, + ], + ]; + + if (options) { + const e = ['comment_options', options]; + opArray.push(e); + } + + if (voteWeight) { + const e = [ + 'vote', + { + voter: author, + author, + permlink, + weight: voteWeight, + }, + ]; + opArray.push(e); + } + + const key = decryptKey(account.realm_object.postingKey, digitPinCode); + const privateKey = PrivateKey.fromString(key); + + return new Promise((resolve, reject) => { + client.broadcast + .sendOperations(opArray, privateKey) + .then((result) => { + resolve(result); + }) + .catch((error) => { + console.log(error); + reject(error); + }); + }); +}; diff --git a/src/screens/editor/container/editorContainer.js b/src/screens/editor/container/editorContainer.js index e29b34906..d81413f66 100644 --- a/src/screens/editor/container/editorContainer.js +++ b/src/screens/editor/container/editorContainer.js @@ -5,7 +5,7 @@ import ImagePicker from 'react-native-image-crop-picker'; // Services and Actions // import { Buffer } from 'buffer'; import { uploadImage } from '../../../providers/esteem/esteem'; -import { postContent } from '../../../providers/steem/dsteem'; +import { postContent, postComment } from '../../../providers/steem/dsteem'; import { setDraftPost, getDraftPost } from '../../../realm/realm'; import { getDigitPinCode } from '../../../providers/steem/auth'; @@ -15,7 +15,12 @@ import { getDigitPinCode } from '../../../providers/steem/auth'; import { default as ROUTES } from '../../../constants/routeNames'; // Utilities -import { generatePermlink } from '../../../utils/editor'; +import { + generatePermlink, + generateReplyPermlink, + makeJsonMetadataReply, + makeOptions, +} from '../../../utils/editor'; import { decryptKey } from '../../../utils/crypto'; // import { generateSignature } from '../../../utils/image'; // Component @@ -31,41 +36,54 @@ class EditorContainer extends Component { constructor(props) { super(props); this.state = { - isPostSending: false, - isDraftSaving: false, - isDraftSaved: false, + autoFocusText: false, draftPost: null, isCameraOrPickerOpen: false, - autoFocusText: false, - uploadedImage: null, + isDraftSaved: false, + isDraftSaving: false, + isPostSending: false, + isReply: false, isUploading: false, + post: null, + uploadedImage: null, }; } // Component Life Cycle Functions - // Component Functions componentWillMount() { const { currentAccount, navigation } = this.props; const username = currentAccount && currentAccount.name ? currentAccount.name : ''; - const routingAction = navigation.state && navigation.state.params; + let isReply; + let post; - // Routing action state ex if coming for video or image or only text - if (routingAction && routingAction.action) { - this._handleRoutingAction(routingAction.action); + if (navigation.state && navigation.state.params) { + const navigationParams = navigation.state.params; + + if (navigationParams.isReply) { + isReply = navigationParams.isReply; + post = navigationParams.post; + this.setState({ isReply, post }); + } + + if (navigationParams.action) { + this._handleRoutingAction(navigationParams.action); + } } else { this.setState({ autoFocusText: true }); } - getDraftPost(username) - .then((result) => { - this.setState({ - draftPost: { body: result.body, title: result.title, tags: result.tags.split(',') }, + if (!isReply) { + getDraftPost(username) + .then((result) => { + this.setState({ + draftPost: { body: result.body, title: result.title, tags: result.tags.split(',') }, + }); + }) + .catch((error) => { + // alert(error); }); - }) - .catch((error) => { - // alert(error); - }); + } } _handleRoutingAction = (routingAction) => { @@ -181,15 +199,16 @@ class EditorContainer extends Component { }; _submitPost = async (fields) => { - this.setState({ isPostSending: true }); - const { navigation, currentAccount } = this.props; - const permlink = generatePermlink(fields.title); - const digitPinCode = await getDigitPinCode(); - - const postingKey = decryptKey(currentAccount.realm_object.postingKey, digitPinCode); if (currentAccount) { + this.setState({ isPostSending: true }); + + const permlink = generatePermlink(fields.title); + const digitPinCode = await getDigitPinCode(); + + const postingKey = decryptKey(currentAccount.realm_object.postingKey, digitPinCode); + const post = { ...fields, permlink, @@ -208,8 +227,53 @@ class EditorContainer extends Component { } }; + _submitReply = async (fields) => { + const { navigation, currentAccount } = this.props; + + if (currentAccount) { + this.setState({ isPostSending: true }); + + const { post } = this.state; + + const jsonMeta = makeJsonMetadataReply(post.json_metadata.tags || ['esteem']); + const permlink = generateReplyPermlink(post.author); + const digitPinCode = await getDigitPinCode(); + const author = currentAccount.name; + const options = makeOptions(author, permlink); + const parentAuthor = post.author; + const parentPermlink = post.permlink; + + await postComment( + currentAccount, + digitPinCode, + parentAuthor, + parentPermlink, + permlink, + '', + fields.body, + jsonMeta, + options, + 0, + ) + .then((result) => { + alert('Your post succesfully shared'); + navigation.goBack(); + }) + .catch((error) => { + alert(`Opps! there is a problem${error}`); + this.setState({ isPostSending: false }); + }); + } + }; + _handleSubmit = (form) => { - this._submitPost(form); + const { isReply } = this.state; + + if (isReply) { + this._submitReply(form.fields); + } else { + this._submitPost(form); + } }; _handleFormChanged = () => { @@ -223,15 +287,17 @@ class EditorContainer extends Component { render() { const { isLoggedIn, isDarkTheme } = this.props; const { + autoFocusText, draftPost, + isCameraOrPickerOpen, isDraftSaved, isDraftSaving, isOpenCamera, - isCameraOrPickerOpen, - autoFocusText, - uploadedImage, isPostSending, + isReply, isUploading, + post, + uploadedImage, } = this.state; return ( @@ -245,12 +311,14 @@ class EditorContainer extends Component { isCameraOrPickerOpen={isCameraOrPickerOpen} isDarkTheme={isDarkTheme} isDraftSaved={isDraftSaved} - isPostSending={isPostSending} isDraftSaving={isDraftSaving} isLoggedIn={isLoggedIn} isOpenCamera={isOpenCamera} - uploadedImage={uploadedImage} + isPostSending={isPostSending} + isReply={isReply} isUploading={isUploading} + post={post} + uploadedImage={uploadedImage} /> ); } diff --git a/src/screens/editor/screen/editorScreen.js b/src/screens/editor/screen/editorScreen.js index c0d614c55..f836269ba 100644 --- a/src/screens/editor/screen/editorScreen.js +++ b/src/screens/editor/screen/editorScreen.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react'; -import { View, ActivityIndicator, Text } from 'react-native'; +import React, { Component, Fragment } from 'react'; +import { View, Text } from 'react-native'; import { injectIntl } from 'react-intl'; // Utils @@ -9,8 +9,11 @@ import { getWordsCount } from '../../../utils/editor'; // Components import { BasicHeader } from '../../../components/basicHeader'; -import { TitleArea, TagArea, TextArea } from '../../../components/editorElements'; +import { + TitleArea, TagArea, TextArea, SummaryArea, +} from '../../../components/editorElements'; import { PostForm } from '../../../components/postForm'; + // Styles import globalStyles from '../../../globalStyles'; @@ -82,15 +85,21 @@ class EditorScreen extends Component { _handleIsFormValid = () => { const { fields } = this.state; + const { isReply } = this.props; + let _isFormValid; - this.setState({ - isFormValid: - fields.title + if (isReply) { + _isFormValid = fields && fields.body && fields.body.length > 0; + } else { + _isFormValid = fields + && fields.title && fields.title.length > 0 && fields.body && fields.body.length > 0 - && fields.tags.length > 0, - }); + && fields.tags.length > 0; + } + + this.setState({ isFormValid: _isFormValid }); }; _handleFormUpdate = (componentID, content) => { @@ -120,7 +129,7 @@ class EditorScreen extends Component { render() { const { - isPreviewActive, wordsCount, isFormValid, fields, + draftPost, fields, isChanged, isPreviewActive, wordsCount, isFormValid, } = this.state; const { autoFocusText, @@ -130,8 +139,10 @@ class EditorScreen extends Component { isDraftSaving, isLoggedIn, isPostSending, - uploadedImage, + isReply, isUploading, + post, + uploadedImage, } = this.props; return ( @@ -145,6 +156,7 @@ class EditorScreen extends Component { isFormValid={isFormValid} isHasIcons isLoggedIn={isLoggedIn} + isReply={isReply} isLoading={isPostSending || isUploading} isPreviewActive={isPreviewActive} quickTitle={wordsCount > 0 && `${wordsCount} words`} @@ -155,19 +167,16 @@ class EditorScreen extends Component { isFormValid={isFormValid} isPreviewActive={isPreviewActive} > - - + {isReply && } + {!isReply && } + {!isReply && ( + + )}