diff --git a/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate b/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate
index 9f7267666..3ff52e2d0 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/package.json b/package.json
index 0519de56f..929766680 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
"react-native": "0.61.2",
"react-native-actionsheet": "^2.4.2",
"react-native-autocomplete-input": "^4.1.0",
+ "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",
diff --git a/src/components/basicUIElements/index.js b/src/components/basicUIElements/index.js
index f4ff21f63..e4cf494d2 100644
--- a/src/components/basicUIElements/index.js
+++ b/src/components/basicUIElements/index.js
@@ -19,10 +19,12 @@ import WalletDetailsPlaceHolder from './view/placeHolder/walletDetailsPlaceHolde
import WalletUnclaimedPlaceHolder from './view/placeHolder/walletUnclaimedPlaceHolder';
import ListPlaceHolder from './view/placeHolder/listPlaceHolderView';
import BoostPlaceHolder from './view/placeHolder/boostPlaceHolderView';
+import CommentPlaceHolder from './view/placeHolder/commentPlaceHolderView';
export {
Card,
Chip,
+ CommentPlaceHolder,
GrayWrapper,
LineBreak,
ListItemPlaceHolder,
diff --git a/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js b/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js
new file mode 100644
index 000000000..7f7c51f4f
--- /dev/null
+++ b/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import { View } from 'react-native';
+import Placeholder from 'rn-placeholder';
+
+import { ThemeContainer } from '../../../../containers';
+
+import styles from './listItemPlaceHolderStyles';
+
+const CommentPlaceHolderView = () => {
+ return (
+
+ {({ isDarkTheme }) => {
+ const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
+ return (
+
+
+
+
+
+ );
+ }}
+
+ );
+};
+
+export default CommentPlaceHolderView;
diff --git a/src/components/basicUIElements/view/placeHolder/listItemPlaceHolderStyles.js b/src/components/basicUIElements/view/placeHolder/listItemPlaceHolderStyles.js
index c006f721b..c489b1019 100644
--- a/src/components/basicUIElements/view/placeHolder/listItemPlaceHolderStyles.js
+++ b/src/components/basicUIElements/view/placeHolder/listItemPlaceHolderStyles.js
@@ -16,4 +16,7 @@ export default EStyleSheet.create({
marginTop: 3,
flex: 1,
},
+ paragraphWithoutMargin: {
+ flex: 1,
+ },
});
diff --git a/src/components/postElements/body/view/config.js b/src/components/postElements/body/view/config.js
new file mode 100644
index 000000000..30c8fc2f4
--- /dev/null
+++ b/src/components/postElements/body/view/config.js
@@ -0,0 +1,106 @@
+export default `document.addEventListener('click', function(event) {
+ let el = event.target;
+ // A element can be wrapped with inline element. Look parent elements.
+ while (el.tagName !== 'A') {
+ if (!el.parentNode) {
+ break;
+ }
+ el = el.parentNode;
+ }
+ if (!el || el.tagName !== 'A') {
+ window.ReactNativeWebView.postMessage('4');
+ if (el.tagName) window.ReactNativeWebView.postMessage(el.tagName);
+ return;
+ }
+ if (el.getAttribute('target') === '_external') {
+ const href = el.getAttribute('href');
+ const result = {
+ type: '_external',
+ href
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+
+ return true;
+ }
+ if (el.classList.contains('markdown-external-link')) {
+ const href = el.getAttribute('data-href');
+ const result = {
+ type: 'markdown-external-link',
+ href
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+
+ return true;
+ }
+ if (el.classList.contains('markdown-author-link')) {
+ const author = el.getAttribute('data-author');
+ const result = {
+ type: 'markdown-author-link',
+ author,
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+ return false;
+ }
+
+ if (el.classList.contains('markdown-post-link')) {
+ let category = el.getAttribute('data-tag');
+ let author = el.getAttribute('data-author');
+ let permlink = el.getAttribute('data-permlink');
+ const result = {
+ type: 'markdown-post-link',
+ category,
+ author,
+ permlink,
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+ return false;
+ }
+ if (el.classList.contains('markdown-tag-link')) {
+ let tag = el.getAttribute('data-tag');
+ const result = {
+ type: 'markdown-tag-link',
+ tag
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+ return false;
+ }
+ if (el.classList.contains('markdown-witnesses-link')) {
+
+ const result = {
+ type: 'markdown-witnesses-link'
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+ return false;
+ }
+ if (el.classList.contains('markdown-proposal-link')) {
+
+ let proposal = el.getAttribute('data-proposal');
+ const result = {
+ type: 'markdown-proposal-link',
+ proposal
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+ return false;
+ }
+ if (el.classList.contains('markdown-video-link')) {
+ const embedSrc = '';
+ if (embedSrc) {
+ el.innerHTML = embedSrc;
+ return;
+ }
+ const videoHref = el.getAttribute('data-video-href');
+ if (videoHref) {
+ const result = {
+ type: 'markdown-video-link',
+ videoHref
+ }
+ window.ReactNativeWebView.postMessage(JSON.stringify(result));
+
+ return false;
+ }
+ }
+ window.ReactNativeWebView.postMessage('4');
+ const author = el.getAttribute('data-author').toString();
+ window.ReactNativeWebView.postMessage(JSON.stringify(author));
+})
+true;`;
diff --git a/src/components/postElements/body/view/postBodyView.js b/src/components/postElements/body/view/postBodyView.js
index 2b0fcac67..3a3aef673 100644
--- a/src/components/postElements/body/view/postBodyView.js
+++ b/src/components/postElements/body/view/postBodyView.js
@@ -1,16 +1,17 @@
-import React from 'react';
-import { Dimensions, Linking, Alert, TouchableOpacity, Text } from 'react-native';
+import React, { Fragment } from 'react';
+import { Dimensions, Linking, Alert } from 'react-native';
import { withNavigation } from 'react-navigation';
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';
+import get from 'lodash/get';
+
+import script from './config.js';
+import { PostPlaceHolder, CommentPlaceHolder } from '../../../basicUIElements';
// Constants
import { default as ROUTES } from '../../../../constants/routeNames';
-// Styles
-import styles from './postBodyStyles';
-
const WIDTH = Dimensions.get('window').width;
const PostBody = ({
@@ -23,36 +24,72 @@ const PostBody = ({
}) => {
const intl = useIntl();
- const _handleOnLinkPress = (href, hrefAtr) => {
- if (hrefAtr.class === 'markdown-author-link') {
- if (!handleOnUserPress) {
- _handleOnUserPress(hrefAtr['data-author']);
- } else {
- handleOnUserPress(hrefAtr['data-author']);
+ const _handleOnLinkPress = event => {
+ if ((!event && !get(event, 'nativeEvent.data'), false)) {
+ return;
+ }
+
+ try {
+ const data = JSON.parse(get(event, 'nativeEvent.data'));
+
+ const { type, href, author, category, permlink, tag, proposal, videoHref } = data;
+
+ switch (type) {
+ case '_external':
+ case 'markdown-external-link':
+ _handleBrowserLink(href);
+ break;
+ case 'markdown-author-link':
+ if (!handleOnUserPress) {
+ _handleOnUserPress(author);
+ } else {
+ handleOnUserPress(author);
+ }
+ break;
+ case 'markdown-post-link':
+ if (!handleOnPostPress) {
+ _handleOnPostPress(permlink, author);
+ } else {
+ handleOnPostPress(permlink, author);
+ }
+ break;
+ case 'markdown-tag-link':
+ _handleTagPress(tag);
+ break;
+ case 'markdown-witnesses-link':
+ break;
+ case 'markdown-proposal-link':
+ break;
+ case 'markdown-video-link':
+ break;
+
+ default:
+ break;
}
- } else if (hrefAtr.class === 'markdown-post-link') {
- if (!handleOnPostPress) {
- _handleOnPostPress(hrefAtr['data-permlink'], hrefAtr['data-author']);
- } else {
- handleOnPostPress(hrefAtr['data-permlink']);
- }
- } else {
- _handleBrowserLink(href);
+ } catch (error) {}
+ };
+
+ const _handleTagPress = tag => {
+ if (tag) {
+ navigation.navigate({
+ routeName: ROUTES.SCREENS.SEARCH_RESULT,
+ params: {
+ tag,
+ },
+ });
}
};
const _handleBrowserLink = async url => {
- if (!url) {
- return;
+ if (url) {
+ Linking.canOpenURL(url).then(supported => {
+ if (supported) {
+ Linking.openURL(url);
+ } else {
+ Alert.alert(intl.formatMessage({ id: 'alert.failed_to_open' }));
+ }
+ });
}
-
- Linking.canOpenURL(url).then(supported => {
- if (supported) {
- Linking.openURL(url);
- } else {
- Alert.alert(intl.formatMessage({ id: 'alert.failed_to_open' }));
- }
- });
};
const _handleOnPostPress = (permlink, author) => {
@@ -82,117 +119,116 @@ const PostBody = ({
}
};
- const _hasParentTag = (node, name) => {
- if (!node.parent) {
- return false;
- }
-
- if (node.name === name) {
- return true;
- }
-
- return _hasParentTag(node.parent, name);
- };
-
- 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 === 'a') {
- node.attribs.style = 'text-decoration: underline';
- }
-
- if (node.name === 'img') {
- node.attribs.style = 'text-align: center;';
- if (_hasParentTag(node, 'td')) {
- node.attribs.style = `max-width: ${WIDTH / 2 - 20}px; `;
- }
- }
-
- if (node.name === 'div' && node.attribs && node.attribs.class) {
- const _className = node.attribs.class;
-
- if (_className === 'pull-right') {
- node.attribs.style = 'text-align: right; align-self: flex-end;';
- }
-
- if (_className === 'pull-left') {
- node.attribs.style = 'text-align: left; align-self: flex-start;';
- }
-
- if (_className === 'text-justify') {
- node.attribs.style = 'text-align: justify; text-justify: inter-word; letter-spacing: 0px;';
- }
-
- if (_className === 'phishy') {
- node.attribs.style = 'color: red';
- }
- }
- };
-
- const _alterData = node => {
- if (
- node.type === 'text' &&
- node.data.includes('markdown-author-link') &&
- node.parent &&
- getParentsTagsRecursively(node.parent).includes('code')
- ) {
- return node.data.replace(/<[^>]*>/g, '');
- }
- };
-
- const _initialDimensions = isComment
- ? { width: WIDTH - 50, height: 80 }
- : { width: WIDTH, height: 216 };
-
- const _customRenderer = {
- a: (htmlAttribs, children, convertedCSSStyles, passProps) => {
- if (passProps.parentWrapper === 'Text') {
- return (
- _handleOnLinkPress(htmlAttribs['data-href'], htmlAttribs)}
- >
- {children}
-
- );
- }
- return (
- _handleOnLinkPress(htmlAttribs['data-href'], htmlAttribs)}
- >
- {children}
-
- );
- },
- br: (htmlAttribs, children, passProps) => {
- return {'\n'};
- },
- };
+ const test = body.replace(/ _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}
- />
+
+ (isComment ? : )}
+ startInLoadingState={true}
+ onShouldStartLoadWithRequest={false}
+ scrollEnabled={false}
+ />
+
);
};
-export default injectIntl(withNavigation(PostBody));
+const areEqual = (prevProps, nextProps) => {
+ if (prevProps.body !== nextProps.body) {
+ return true;
+ }
+ return false;
+};
+
+export default React.memo(injectIntl(withNavigation(PostBody)), areEqual);
diff --git a/src/components/postView/view/postDisplayView.js b/src/components/postView/view/postDisplayView.js
index 52c43b16b..6e3d1aa00 100644
--- a/src/components/postView/view/postDisplayView.js
+++ b/src/components/postView/view/postDisplayView.js
@@ -162,7 +162,9 @@ class PostDisplayView extends PureComponent {
const isGetComment = scrollHeight + 300 > postHeight;
const formatedTime = post && getTimeFromNow(post.created);
- if (isGetComment && !isLoadedComments) this.setState({ isLoadedComments: true });
+ if (isGetComment && !isLoadedComments) {
+ this.setState({ isLoadedComments: true });
+ }
if (isPostUnavailable) {
return (
diff --git a/yarn.lock b/yarn.lock
index d3fdc471e..c39b7898c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7458,6 +7458,13 @@ react-native-autocomplete-input@^4.1.0:
resolved "https://registry.yarnpkg.com/react-native-autocomplete-input/-/react-native-autocomplete-input-4.1.0.tgz#979ece28d891b245ecb967b6d31f1f924445b8ab"
integrity sha512-Yn4GulZ9F6tde74UUGZHdVFeYWVuL7+EbUZy6kt+QHrzMc5B4OuRop1FT4RyWLpvbySW/vvqYgj9LAmlzkuEqA==
+react-native-autoheight-webview@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/react-native-autoheight-webview/-/react-native-autoheight-webview-1.2.2.tgz#5b65fdad47f552cd154fc9dd916aebc69492cc24"
+ integrity sha512-Did1IBXxY3fmGyGn7ioT3Osu9Uk7H+4M/rc6bal83cwEjxsX0lUDhzXOMNJh4D6Wh5eRne2r7zPz52tKjeLv8g==
+ dependencies:
+ prop-types "^15.7.2"
+
react-native-code-push@esteemapp/react-native-code-push:
version "1000.0.0-beta"
resolved "https://codeload.github.com/esteemapp/react-native-code-push/tar.gz/c07b7023c1212dc5d9231a0526a869d2501cb221"