diff --git a/android/app/build.gradle b/android/app/build.gradle index 8f9068114..d9b59c7dd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -140,6 +140,7 @@ android { } dependencies { + compile project(':react-native-version-number') compile project(':react-native-code-push') compile project(':realm') compile project(':react-native-fast-image') diff --git a/android/app/src/main/java/app/esteem/mobile/MainApplication.java b/android/app/src/main/java/app/esteem/mobile/MainApplication.java index 27a8664f6..6339c80b2 100644 --- a/android/app/src/main/java/app/esteem/mobile/MainApplication.java +++ b/android/app/src/main/java/app/esteem/mobile/MainApplication.java @@ -3,6 +3,7 @@ package app.esteem.mobile; import android.app.Application; import com.facebook.react.ReactApplication; +import com.apsl.versionnumber.RNVersionNumberPackage; import com.microsoft.codepush.react.CodePush; import io.realm.react.RealmReactPackage; import com.dylanvann.fastimage.FastImageViewPackage; @@ -43,6 +44,7 @@ public class MainApplication extends Application implements ReactApplication { protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new RNVersionNumberPackage(), new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG), new RealmReactPackage(), new FastImageViewPackage(), diff --git a/android/settings.gradle b/android/settings.gradle index 7ef80f5b5..d3b4d8727 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'eSteem' +include ':react-native-version-number' +project(':react-native-version-number').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-version-number/android') include ':react-native-code-push' project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app') include ':realm' diff --git a/ios/Podfile b/ios/Podfile index 2220767c1..85cca3ab8 100755 --- a/ios/Podfile +++ b/ios/Podfile @@ -36,6 +36,8 @@ target 'eSteem' do pod 'CodePush', :path => '../node_modules/react-native-code-push' + pod 'react-native-version-number', :path => '../node_modules/react-native-version-number' + target 'eSteemTests' do inherit! :search_paths # Pods for testing diff --git a/ios/Pods/Pods.xcodeproj/xcuserdata/mistik.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/Pods/Pods.xcodeproj/xcuserdata/mistik.xcuserdatad/xcschemes/xcschememanagement.plist index 07c0bc2aa..921c959b3 100644 --- a/ios/Pods/Pods.xcodeproj/xcuserdata/mistik.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ios/Pods/Pods.xcodeproj/xcuserdata/mistik.xcuserdatad/xcschemes/xcschememanagement.plist @@ -14,7 +14,7 @@ FLAnimatedImage.xcscheme_^#shared#^_ orderHint - 14 + 67 Folly.xcscheme @@ -82,7 +82,7 @@ SDWebImage.xcscheme_^#shared#^_ orderHint - 16 + 69 glog.xcscheme @@ -94,7 +94,7 @@ react-native-fast-image.xcscheme_^#shared#^_ orderHint - 15 + 68 SuppressBuildableAutocreation diff --git a/ios/eSteem.xcodeproj/project.pbxproj b/ios/eSteem.xcodeproj/project.pbxproj index 503e04b6f..2f22d6e21 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 */; }; diff --git a/ios/eSteem.xcworkspace/xcuserdata/m.xcuserdatad/UserInterfaceState.xcuserstate b/ios/eSteem.xcworkspace/xcuserdata/m.xcuserdatad/UserInterfaceState.xcuserstate index 799698a08..134dc58b4 100644 Binary files a/ios/eSteem.xcworkspace/xcuserdata/m.xcuserdatad/UserInterfaceState.xcuserstate and b/ios/eSteem.xcworkspace/xcuserdata/m.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate b/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate index a0a55fc80..4aa21bb6e 100644 Binary files a/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate and b/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/eSteem/Info.plist b/ios/eSteem/Info.plist index 7fd0735fd..12b08d6e1 100755 --- a/ios/eSteem/Info.plist +++ b/ios/eSteem/Info.plist @@ -47,7 +47,7 @@ NSCameraUsageDescription To access your photos, eSteem needs your permission to help you share your photos. NSLocationWhenInUseUsageDescription - + NSMainNibFile LaunchScreen NSMicrophoneUsageDescription diff --git a/package.json b/package.json index 64f2dbdb1..f4767ccd2 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "react-native-restart": "0.0.6", "react-native-slider": "^0.11.0", "react-native-vector-icons": "^6.0.2", + "react-native-version-number": "^0.3.5", "react-native-view-overflow": "0.0.3", "react-navigation": "^2.18.3", "react-navigation-redux-helpers": "^2.0.8", diff --git a/src/components/basicUIElements/view/textWithIcon/textWithIconView.js b/src/components/basicUIElements/view/textWithIcon/textWithIconView.js index 9fb846dd4..c6fe97bc9 100644 --- a/src/components/basicUIElements/view/textWithIcon/textWithIconView.js +++ b/src/components/basicUIElements/view/textWithIcon/textWithIconView.js @@ -4,12 +4,20 @@ import { Icon } from '../../../icon'; import styles from './textWithIconStyles'; const TextWithIcon = ({ - iconName, text, isClickable, onPress, iconStyle, iconType, iconSize, + iconName, + text, + isClickable, + onPress, + iconStyle, + iconType, + iconSize, + wrapperStyle, + textStyle, }) => ( {isClickable || onPress ? ( onPress && onPress()} > @@ -19,7 +27,7 @@ const TextWithIcon = ({ name={iconName} iconType={iconType} /> - {text} + {text} ) : ( diff --git a/src/components/comment/index.js b/src/components/comment/index.js new file mode 100644 index 000000000..715ca649a --- /dev/null +++ b/src/components/comment/index.js @@ -0,0 +1,4 @@ +import Comment from './view/commentView'; + +export { Comment }; +export default Comment; diff --git a/src/components/comment/view/commentStyles.js b/src/components/comment/view/commentStyles.js new file mode 100644 index 000000000..cde0f67a9 --- /dev/null +++ b/src/components/comment/view/commentStyles.js @@ -0,0 +1,39 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + leftIcon: { + color: '$iconColor', + }, + leftButton: { + marginLeft: 10, + }, + rightButton: { + backgroundColor: '$iconColor', + height: 18, + flexDirection: 'row-reverse', + borderRadius: 20, + }, + moreText: { + color: '$white', + fontSize: 10, + marginLeft: 12, + marginRight: 2, + }, + bodyWrapper: { + marginTop: -10, + }, + iconStyle: { + color: '$white', + marginRight: 12, + marginTop: 1, + }, + footerWrapper: { + flex: 1, + flexDirection: 'row', + }, + rightButtonWrapper: { + alignSelf: 'flex-end', + position: 'absolute', + right: 0, + }, +}); diff --git a/src/components/comment/view/commentView.js b/src/components/comment/view/commentView.js new file mode 100644 index 000000000..06a8ba178 --- /dev/null +++ b/src/components/comment/view/commentView.js @@ -0,0 +1,127 @@ +import React, { PureComponent, Fragment } from 'react'; +import { View } from 'react-native'; + +import { getTimeFromNow } from '../../../utils/time'; +// Constants + +// Components +import { PostBody, PostHeaderDescription } from '../../postElements'; +import { Upvote } from '../../upvote'; +import { IconButton } from '../../iconButton'; +import { Comments } from '../../comments'; +import { TextWithIcon } from '../../basicUIElements'; + +// Styles +import styles from './commentStyles'; + +class CommentView extends PureComponent { + /* Props + * ------------------------------------------------ + * @prop { type } name - Description.... + */ + + constructor(props) { + super(props); + this.state = { + isShowSubComments: props.isShowSubComments || false, + }; + } + + // Component Life Cycles + // Component Functions + + _showSubCommentsToggle = () => { + const { isShowSubComments } = this.state; + + this.setState({ isShowSubComments: !isShowSubComments }); + }; + + render() { + const { + avatarSize, + currentAccountUsername, + handleOnEditPress, + handleOnReplyPress, + handleOnUserPress, + isLoggedIn, + marginLeft, + isShowMoreButton, + comment, + commentNumber, + fetchPost, + isShowComments, + } = this.props; + const { isShowSubComments } = this.state; + + return ( + + + + + + {isLoggedIn && ( + + + handleOnReplyPress && handleOnReplyPress(comment)} + iconType="MaterialIcons" + /> + {currentAccountUsername === comment.author && ( + handleOnEditPress && handleOnEditPress(comment)} + iconType="MaterialIcons" + /> + )} + + )} + {isShowMoreButton && ( + + this._showSubCommentsToggle()} + text={`${comment.children} more replies`} + /> + + )} + + {isShowSubComments && commentNumber > 0 && ( + + )} + + + ); + } +} + +export default CommentView; diff --git a/src/components/comments/container/commentsContainer.js b/src/components/comments/container/commentsContainer.js index bbd0ca8a7..507b34654 100644 --- a/src/components/comments/container/commentsContainer.js +++ b/src/components/comments/container/commentsContainer.js @@ -82,29 +82,36 @@ class CommentsContainer extends Component { }; render() { - const { comments: _comments } = this.state; + const { comments: _comments, selectedPermlink } = this.state; const { isLoggedIn, commentCount, author, permlink, currentAccount, - isProfilePreview, + commentNumber, comments, + fetchPost, + isShowMoreButton, + selectedPermlink: _selectedPermlink, } = this.props; return ( ); } diff --git a/src/components/comments/view/commentsView.js b/src/components/comments/view/commentsView.js index 83f32b8dd..246902515 100644 --- a/src/components/comments/view/commentsView.js +++ b/src/components/comments/view/commentsView.js @@ -1,14 +1,8 @@ -import React, { PureComponent, Fragment } from 'react'; +import React, { PureComponent } from 'react'; import { View, FlatList } from 'react-native'; -import { getTimeFromNow } from '../../../utils/time'; -// Constants - // Components -import Comments from '../container/commentsContainer'; -import { PostBody, PostHeaderDescription } from '../../postElements'; -import { Upvote } from '../../upvote'; -import { IconButton } from '../../iconButton'; +import { Comment } from '../../comment'; // Styles // import styles from './commentStyles'; @@ -41,81 +35,37 @@ class CommentsView extends PureComponent { handleOnReplyPress, handleOnUserPress, isLoggedIn, - isProfilePreview, marginLeft, + isShowSubComments, fetchPost, + commentCount, } = this.props; return ( - - {!!comments && ( - ( - - - - - - {isLoggedIn && ( - - - handleOnReplyPress && handleOnReplyPress(item)} - iconType="MaterialIcons" - /> - {currentAccountUsername === item.author && ( - handleOnEditPress && handleOnEditPress(item)} - iconType="MaterialIcons" - /> - )} - - )} - - - {!isProfilePreview && ( - - {commentNumber !== 8 && ( - - )} - - )} - - )} - /> + ( + + 0} + comment={item} + marginLeft={marginLeft} + commentNumber={commentNumber} + fetchPost={fetchPost} + commentCount={commentCount || item.children} + isShowSubComments={isShowSubComments} + avatarSize={avatarSize} + currentAccountUsername={currentAccountUsername} + handleOnReplyPress={handleOnReplyPress} + handleOnEditPress={handleOnEditPress} + handleOnUserPress={handleOnUserPress} + isLoggedIn={isLoggedIn} + showComentsToggle={this._showComentsToggle} + /> + )} - + /> ); } } diff --git a/src/components/postDropdown/container/postDropdownContainer.js b/src/components/postDropdown/container/postDropdownContainer.js index c2f7a07dc..8b1840561 100644 --- a/src/components/postDropdown/container/postDropdownContainer.js +++ b/src/components/postDropdown/container/postDropdownContainer.js @@ -1,7 +1,7 @@ import React, { PureComponent, Fragment } from 'react'; import { connect } from 'react-redux'; import { withNavigation } from 'react-navigation'; -import { Alert } from 'react-native'; +import { Alert, Share } from 'react-native'; import ActionSheet from 'react-native-actionsheet'; import { injectIntl } from 'react-intl'; @@ -16,6 +16,7 @@ import { default as ROUTES } from '../../../constants/routeNames'; // Utilities import { writeToClipboard } from '../../../utils/clipboard'; +import { getPostUrl } from '../../../utils/post'; // Component import PostDropdownView from '../view/postDropdownView'; @@ -40,7 +41,7 @@ class PostDropdownContainer extends PureComponent { switch (index) { case '0': - writeToClipboard(`https://steemit.com${content.url}`); + writeToClipboard(getPostUrl(content.url)); break; case '1': @@ -52,12 +53,26 @@ class PostDropdownContainer extends PureComponent { case '2': this._replyNavigation(); break; + case '3': + setTimeout(() => { + this._share(); + }, 500); + break; default: break; } }; + _share = () => { + const { content } = this.props; + + Share.share({ + message: content.title, + url: getPostUrl(content.url), + }); + }; + _reblog = () => { const { currentAccount, content, isLoggedIn, pinCode, intl, @@ -115,7 +130,7 @@ class PostDropdownContainer extends PureComponent { return ( intl.formatMessage({ id: `post_dropdown.${item}` }).toUpperCase())} handleOnDropdownSelect={this._handleOnDropdownSelect} {...this.props} /> diff --git a/src/components/sideMenu/view/sideMenuStyles.js b/src/components/sideMenu/view/sideMenuStyles.js index 3dddead85..566c60f81 100644 --- a/src/components/sideMenu/view/sideMenuStyles.js +++ b/src/components/sideMenu/view/sideMenuStyles.js @@ -83,4 +83,8 @@ export default EStyleSheet.create({ flexDirection: 'row', marginLeft: 55, }, + versionText: { + textAlign: 'center', + color: '$iconColor', + }, }); diff --git a/src/components/sideMenu/view/sideMenuView.js b/src/components/sideMenu/view/sideMenuView.js index f1efd3229..ae01c8c9a 100644 --- a/src/components/sideMenu/view/sideMenuView.js +++ b/src/components/sideMenu/view/sideMenuView.js @@ -5,6 +5,7 @@ import { import { injectIntl } from 'react-intl'; import LinearGradient from 'react-native-linear-gradient'; import ActionSheet from 'react-native-actionsheet'; +import VersionNumber from 'react-native-version-number'; // Components import { IconButton } from '../../buttons'; @@ -13,6 +14,7 @@ import { UserAvatar } from '../../userAvatar'; // Constants import { default as MENU } from '../../../constants/sideMenuItems'; +import PackageJson from '../../../../package.json'; // Styles import styles from './sideMenuStyles'; @@ -85,6 +87,8 @@ class SideMenuView extends Component { currentAccount, isLoggedIn, intl, handleLogout, } = this.props; const { menuItems, isAddAccountIconActive } = this.state; + const { version } = PackageJson; + const { buildVersion } = VersionNumber; return ( @@ -163,6 +167,7 @@ class SideMenuView extends Component { )} /> + {`v${version}, ${buildVersion}`} (this.ActionSheet = o)} options={[intl.formatMessage({ id: 'side_menu.logout' }), intl.formatMessage({ id: 'side_menu.cancel' })]} diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index 8cca9a566..116c7e990 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -35,7 +35,7 @@ "profile": { "following": "Following", "follower": "Follower", - "post": "Post", + "post": "Posts", "details": "Profile Details", "comments": "Comments", "replies": "Replies", @@ -62,7 +62,7 @@ "server": "Server", "dark_theme": "Dark Theme", "push_notification": "Push Notification", - "pincode": "Pincode", + "pincode": "PIN code", "reset": "Reset" }, "voters": { @@ -116,8 +116,8 @@ "reply": "Reply" }, "pincode": { - "enter_text": "Enter pin to unlock", - "set_new": "Set new pin", + "enter_text": "Enter PIN to unlock", + "set_new": "Set new PIN", "write_again": "Write again", "forgot_text": "Oh, I forgot it..." }, @@ -132,8 +132,8 @@ "success_rebloged": "Reblogged!", "already_rebloged": "You have already reblogged!", "warning": "Warning", - "invalid_pincode": "Invalid pin code, please check and try again.", - "remove_alert": "Are you sure want to remove?", + "invalid_pincode": "Invalid PIN code, please check and try again.", + "remove_alert": "Are you sure you want to remove?", "cancel": "Cancel", "delete": "Delete" }, @@ -167,7 +167,7 @@ "search": "Search in favorites" }, "auth": { - "invalid_pin": "Invalid pin code, please check and try again", + "invalid_pin": "Invalid PIN code, please check and try again", "invalid_username": "Invalid username, please check and try again", "already_logged": "You are already logged in, please try to add another account", "invalid_credentials": "Invalid credentials, please check and try again", @@ -179,5 +179,11 @@ "author_payout": "Author Payout", "curation_payout": "Curation Payout", "payout_date": "Payout" + }, + "post_dropdown": { + "copy": "copy link", + "reblog": "reblog", + "reply": "reply", + "share": "share" } } diff --git a/src/config/locales/ru-RU.json b/src/config/locales/ru-RU.json index 46f02eab0..418cc64c1 100644 --- a/src/config/locales/ru-RU.json +++ b/src/config/locales/ru-RU.json @@ -179,5 +179,11 @@ "author_payout": "Автору", "curation_payout": "Кураторам", "payout_date": "Выплата" + }, + "post_dropdown": { + "copy": "copy link", + "reblog": "reblog", + "reply": "reply", + "share": "share" } } diff --git a/src/config/locales/tr-TR.json b/src/config/locales/tr-TR.json index bbb793466..947fb0dd3 100644 --- a/src/config/locales/tr-TR.json +++ b/src/config/locales/tr-TR.json @@ -179,5 +179,11 @@ "author_payout": "Yazar Ödemeleri", "curation_payout": "Küratör Ödemeleri", "payout_date": "Ödeme" + }, + "post_dropdown": { + "copy": "kopyala", + "reblog": "reblog", + "reply": "cevapla", + "share": "paylaş" } } diff --git a/src/constants/options/post.js b/src/constants/options/post.js index ab6e42ef7..8831e207f 100644 --- a/src/constants/options/post.js +++ b/src/constants/options/post.js @@ -1,3 +1 @@ -export default ['COPY LINK', 'REBLOG', 'REPLY']; - -export const VALUE = ['copy', 'reblog', 'reply']; +export default ['copy', 'reblog', 'reply', 'share']; diff --git a/src/utils/post.js b/src/utils/post.js index e317f4c9b..968a68dd1 100644 --- a/src/utils/post.js +++ b/src/utils/post.js @@ -12,3 +12,9 @@ export const postSumTotal = (content) => { ? parseToken(content.total_payout_value) + parseToken(content.curator_payout_value) : 0; }; + +export const getPostUrl = (url) => { + const BASE_URL = 'https://steemit.com'; + + return BASE_URL + url; +}; diff --git a/yarn.lock b/yarn.lock index a52fbea0f..c16e9bd79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7088,6 +7088,11 @@ react-native-vector-icons@^6.0.2: prop-types "^15.6.2" yargs "^8.0.2" +react-native-version-number@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/react-native-version-number/-/react-native-version-number-0.3.5.tgz#90f1b49bcb5e72f801bdc22ed6bad6c7cbbc2222" + integrity sha512-iANHQrYyDSe5Yts2qVjAjFXpK5EHkJGSFAqnVa3Bu/UKBRUjhnMqvskc3EH+IIvvJH9N2Qpidm1KCq42BWa6jQ== + react-native-view-overflow@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/react-native-view-overflow/-/react-native-view-overflow-0.0.3.tgz#d7b08e8c1e5047a2cf07f3ece82025899f930674"