diff --git a/.env.development b/.env.development index 59709599..2c136720 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -REACT_APP_VERSION=3.21.1-dev +REACT_APP_VERSION=3.21.2-dev REACT_APP_SEARCH_API=https://endpoint.d.buzz/api/v1 REACT_APP_SCRAPE_API=https://endpoint.d.buzz/api/v1/meta REACT_APP_IMAGE_API=https://endpoint.d.buzz/api/v1/imageservice diff --git a/src/components/layout/SideBarLeft/index.js b/src/components/layout/SideBarLeft/index.js index 3f0373de..9ef7181c 100644 --- a/src/components/layout/SideBarLeft/index.js +++ b/src/components/layout/SideBarLeft/index.js @@ -318,11 +318,11 @@ const SideBarLeft = (props) => { setOpenLoginModal(false) } - const refreshLatestRouteData = () => { - if(pathname.match(/^\/latest/)){ - setRefreshRouteStatus("latest",timestamp) - } - } + // const refreshLatestRouteData = () => { + // if(pathname.match(/^\/latest/)){ + // setRefreshRouteStatus("latest",timestamp) + // } + // } const refreshTrendingRouteData = () => { if(pathname.match(/^\/trending/)){ @@ -356,7 +356,8 @@ const SideBarLeft = (props) => { path: "/latest", icon: , preventDefault: false, - onClick: refreshLatestRouteData, + // onClick: refreshLatestRouteData, + onClick: () => window.location.reload(true), }, { name: 'Notifications', diff --git a/src/components/modals/LoginModal/index.js b/src/components/modals/LoginModal/index.js index 34492b6d..e1acb516 100644 --- a/src/components/modals/LoginModal/index.js +++ b/src/components/modals/LoginModal/index.js @@ -10,7 +10,7 @@ import { authenticateUserRequest } from 'store/auth/actions' import { Spinner } from 'components/elements' import { connect } from 'react-redux' import { bindActionCreators } from 'redux' -import { pending } from 'redux-saga-thunk' +// import { pending } from 'redux-saga-thunk' import classNames from 'classnames' import { hasCompatibleKeychain } from 'services/helper' import { FaChrome, FaFirefoxBrowser } from 'react-icons/fa' @@ -100,7 +100,7 @@ const LoginModal = (props) => { show, onHide, authenticateUserRequest, - loading, + // loading, fromIntentBuzz, buzzIntentCallback = () => { }, accounts, @@ -114,15 +114,16 @@ const LoginModal = (props) => { const [useKeychain, setUseKeychain] = useState(false) const [hasInstalledKeychain, setHasInstalledKeychain] = useState(false) const [hasAuthenticationError, setHasAuthenticationError] = useState(false) + const [loading, setLoading] = useState(false) const onChange = (e) => { const { target } = e const { name, value } = target if (name === 'username') { - setUsername(value.replace("@", "")) + setUsername(value.replace(/[@!#$%^&*()+=/\\~`,;:"'_\s]/gi, '')) } else if (name === 'password') { - setPassword(value) + setPassword(value.replace(/[\s]/gi, '')) } setHasAuthenticationError(false) } @@ -142,17 +143,24 @@ const LoginModal = (props) => { } const handleClickLogin = () => { + setLoading(true) authenticateUserRequest(username, password, useKeychain) .then(({ is_authenticated }) => { if (!is_authenticated) { setHasAuthenticationError(true) + setLoading(false) } else { if (fromIntentBuzz && buzzIntentCallback) { buzzIntentCallback() + setLoading(false) } onHide() } }) + setTimeout(() => { + setHasAuthenticationError(true) + setLoading(false) + }, 10000) } const isDisabled = () => { @@ -322,7 +330,7 @@ const LoginModal = (props) => { } const mapStateToProps = (state) => ({ - loading: pending(state, 'AUTHENTICATE_USER_REQUEST'), + // loading: pending(state, 'AUTHENTICATE_USER_REQUEST'), accounts: state.auth.get('accounts'), user: state.auth.get('user'), }) diff --git a/src/components/modals/UpdateFormModal/index.js b/src/components/modals/UpdateFormModal/index.js index 39930d01..d281a123 100644 --- a/src/components/modals/UpdateFormModal/index.js +++ b/src/components/modals/UpdateFormModal/index.js @@ -89,7 +89,6 @@ const useStyles = createUseStyles(theme => ({ }, circle: { strokeLinecap: 'round', - color: '#e53935', }, previewContainer: { width: '100%', @@ -142,6 +141,26 @@ const useStyles = createUseStyles(theme => ({ actionWrapper: { width: '100%', }, + characterCounter: { + position: 'relative', + width: '30px', + height: '30px', + float: 'right', + marginTop: 15, + marginRight: 10, + }, + counter: { + position: 'absolute', + fontWeight: 'bold', + fontSize: '0.8em', + marginRight: 12, + color: '#e61c34', + width: 'fit-content', + left: '50%', + top: '50%', + transform: 'translate(-52%,-52%)', + animation: 'counterAnimation 350ms', + }, })) const UpdateFormModal = (props) => { @@ -160,8 +179,6 @@ const UpdateFormModal = (props) => { uploadFileRequest, } = props - const CircularProgressStyle = { float: 'right', marginRight: 5, marginTop: 15 } - const { username } = user const inputRef = useRef(null) const [content, setContent] = useState('') @@ -176,6 +193,20 @@ const UpdateFormModal = (props) => { const inputFile = { display: 'none' } const replyButtonStyle = { width: 85 } + const [counterColor, setCounterColor] = useState('#e53935') + const CircularProgressStyle = { float: 'right', color: counterColor, transform: content.length >= 260 && 'scale(1.3)' } + + + useEffect(() => { + if(content.length === 280) { + setCounterColor('#E0245E') + } else if(content.length >= 260) { + setCounterColor('#FFAD1F') + } else { + setCounterColor('#e53935') + } + }, [content]) + useEffect(() => { if(body && body !== '') { setContent(body) @@ -229,11 +260,11 @@ const UpdateFormModal = (props) => { publishUpdateRequest(permlink, content) .then((success) => { if(success) { - broadcastNotification('success', `Post successfully edited`) + broadcastNotification('success', `Buzz successfully edited`) onSuccess(content) onClose() } else { - broadcastNotification('error', `Post failed to edited`) + broadcastNotification('error', `Buzz failed to edited`) } }) } @@ -364,15 +395,19 @@ const UpdateFormModal = (props) => { onClick={handleClickSubmitUpdate} disabled={loading || `${content}`.trim() === ''} /> - +
+ + {content.length >= 260 &&

{280 - content.length}

} +
diff --git a/src/components/pages/Content/index.js b/src/components/pages/Content/index.js index 21b63709..bb3f0de5 100644 --- a/src/components/pages/Content/index.js +++ b/src/components/pages/Content/index.js @@ -21,7 +21,7 @@ import { } from 'components' import { bindActionCreators } from 'redux' import { pending } from 'redux-saga-thunk' -import { anchorTop, calculatePayout, invokeTwitterIntent, sendToBerries } from 'services/helper' +import { anchorTop, calculateOverhead, calculatePayout, invokeTwitterIntent, sendToBerries } from 'services/helper' import Row from 'react-bootstrap/Row' import Col from 'react-bootstrap/Col' import Tooltip from '@material-ui/core/Tooltip' @@ -41,6 +41,7 @@ import { import Chip from '@material-ui/core/Chip' import { useHistory } from 'react-router-dom' import { truncateBody, censorLinks } from 'services/helper' +import ReportProblemRoundedIcon from '@material-ui/icons/ReportProblemRounded' const useStyles = createUseStyles(theme => ({ wrapper: { @@ -130,6 +131,29 @@ const useStyles = createUseStyles(theme => ({ marginTop: 5, marginBottom: 5, }, + invalidBuzz: { + width: '100%', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + color: '#E61C34', + fontWeight: 600, + fontSize: '1.2em', + gap: 20, + + '@media (max-width: 480px)': { + textAlign: 'center', + + '& .errorIcon': { + fontSize: '8em !important', + }, + }, + + '& .errorIcon': { + fontSize: '6em !important', + }, + }, })) const Content = (props) => { @@ -161,6 +185,8 @@ const Content = (props) => { const [openVoteList, setOpenVoteList] = useState(false) const popoverAnchor = useRef(null) const history = useHistory() + const [overhead, setOverhead] = useState(0) + const [invalidBuzz, setInvalidBuzz] = useState(false) const { @@ -193,6 +219,19 @@ const Content = (props) => { let hasUpvoted = false let payout_at = cashout_time + useEffect(() => { + const overhead = calculateOverhead(content.body) + setOverhead(overhead) + + // check for invalid buzz + if(!content.body && !loadingContent && !loadingReplies){ + setInvalidBuzz(true) + } else { + setInvalidBuzz(false) + } + // eslint-disable-next-line + }, [content.body]) + useEffect(() => { checkHasUpdateAuthorityRequest(username) .then((result) => { @@ -406,7 +445,7 @@ const Content = (props) => {

- {depth !== 0 && parent_author !== null && !(body.length > 280) && ( + {depth !== 0 && parent_author !== null && !(content.body.length - overhead > 280) && (
@@ -454,7 +493,7 @@ const Content = (props) => {
- {(`${stripHtml(body)}`.length > 280) && ( + {(`${stripHtml(content.body)}`.length - overhead > 280) && (
@@ -565,6 +604,12 @@ const Content = (props) => { onClose={handleClickOnCloseVoteList} upvoteList={active_votes || []} /> + + {invalidBuzz && !loadingContent && !loadingReplies && +
+ + Hmm...this page doesn’t exist. Try searching for something else. +
} ) } diff --git a/src/components/sections/CreateBuzzForm/index.js b/src/components/sections/CreateBuzzForm/index.js index 7654b4dc..b879df47 100644 --- a/src/components/sections/CreateBuzzForm/index.js +++ b/src/components/sections/CreateBuzzForm/index.js @@ -414,7 +414,8 @@ const CreateBuzzForm = (props) => { // getting the draft post value from browser storage savePostAsDraft(localStorage.getItem('draft_post')) - setTags(extractAllHashtags(draftPost || content)) + buzzThreads && setTags(extractAllHashtags(buzzThreads[1].content)) + // eslint-disable-next-line }, [content, draftPost, images, savePostAsDraft]) useEffect(() => { diff --git a/src/components/sections/PostList/index.js b/src/components/sections/PostList/index.js index 3897db84..39d6dc05 100644 --- a/src/components/sections/PostList/index.js +++ b/src/components/sections/PostList/index.js @@ -202,7 +202,7 @@ const PostList = React.memo((props) => { title = null, disableProfileLink = false, disableUserMenu = false, - disableUpvote = false, + // disableUpvote = false, openUserDialog, saveScrollIndex, scrollIndex, @@ -274,7 +274,6 @@ const PostList = React.memo((props) => { } }, [censorList, author, permlink]) - useEffect(() => { if(!isMobile) { if(width >= 676) { @@ -431,7 +430,7 @@ const PostList = React.memo((props) => { - {!muted && !hidden && !opacityActivated && disableOpacity && !isMutedUser() && !isAHiddenBuzz() && ( + {!isAuthor() && !muted && !hidden && !opacityActivated && disableOpacity && !isMutedUser() && !isAHiddenBuzz() && ( @@ -451,7 +450,7 @@ const PostList = React.memo((props) => {
{ />
)} - - Tip - {!isAuthor() && (Mute User)} - {!isAuthor() && (Hide Buzz)} - {!isAuthor() && user.username === 'dbuzz' && !user.useKeychain && !isCensored && (Censor Buzz)} - + {!isAuthor && + + {!isAuthor() && (Tip)} + {!isAuthor() && (Mute User)} + {!isAuthor() && (Hide Buzz)} + {!isAuthor() && user.username === 'dbuzz' && !user.useKeychain && !isCensored && (Censor Buzz)} + }
diff --git a/src/components/sections/ReplyList/index.js b/src/components/sections/ReplyList/index.js index 83208717..7266c3ea 100644 --- a/src/components/sections/ReplyList/index.js +++ b/src/components/sections/ReplyList/index.js @@ -20,7 +20,7 @@ import IconButton from '@material-ui/core/IconButton' import MuteIcon from '@material-ui/icons/VolumeOff' import Chip from '@material-ui/core/Chip' import { Link, useHistory } from 'react-router-dom' -import { truncateBody } from 'services/helper' +import { calculateOverhead, truncateBody } from 'services/helper' import stripHtml from 'string-strip-html' import { censorLinks } from 'services/helper' @@ -171,6 +171,28 @@ const useStyles = createUseStyles(theme => ({ muteButton: { float: 'right', }, + seeMoreRepliesButton: { + display: 'flex', + justifyContent: 'center', + padding: '15px 0', + width: '100%', + fontFamily: 'Segoe-Bold', + cursor: 'pointer', + + '&:hover': { + background: theme.seeMoreReplies.background, + }, + + '& span': { + display: 'flex', + alignItems: 'center', + width: 'fit-content', + padding: '8px 25px', + borderRadius: 8, + userSelect: 'none', + ...theme.seeMoreReplies, + }, + }, })) const countReplies = async (replies = []) => { @@ -200,6 +222,7 @@ const ReplyList = (props) => { const [replyCounter, setReplyCounter] = useState(0) const [repliesState, setRepliesState] = useState(replies) const history = useHistory() + const [overhead, setOverhead] = useState(0) useEffect(() => { countReplies(replies) @@ -361,6 +384,11 @@ const ReplyList = (props) => { openCensorshipDialog(author, permlink, censorCallBack) } + useEffect(() => { + const overhead = calculateOverhead(reply.body) + setOverhead(overhead) + }, [reply.body]) + useEffect(() => { if(censorList.length !== 0 && author && permlink) { const result = censorList.filter((item) => `${item.author}/${item.permlink}` === `${author}/${permlink}`) @@ -382,9 +410,9 @@ const ReplyList = (props) => {
- {replies.length !== 0 && ( + {/* {replies.length !== 0 && (
- )} + )} */}
@@ -412,7 +440,7 @@ const ReplyList = (props) => { )}
- {`${stripHtml(content)}`.length > 280 && ( + {`${stripHtml(reply.body)}`.length - overhead > 280 && (
Reply is truncated because it is over 280 characters
@@ -443,11 +471,14 @@ const ReplyList = (props) => {
{replies.length !== 0 && ( - - {replies.map((reply, index) => ( - - ))} - + // + // {replies.map((reply, index) => ( + // + // ))} + // +
+ view more replies on this... +
)} ) @@ -462,7 +493,7 @@ const ReplyList = (props) => {

)} - {repliesState.map((reply, index) => ( + {repliesState.slice(0).reverse().map((reply, index) => (
diff --git a/src/services/helper.js b/src/services/helper.js index de0d435c..898664c0 100644 --- a/src/services/helper.js +++ b/src/services/helper.js @@ -11,7 +11,7 @@ const dmp = new diff_match_patch() export const getUrls = (text) => { const regexUrls = /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[/w@?^=%&/~+#-(a-z)(A-Z)(0-9)])?/gm - return text.match(regexUrls) !== null ? text.match(regexUrls) : [] + return text?.match(regexUrls) !== null ? text?.match(regexUrls) : [] } export const anchorTop = () => { @@ -254,8 +254,27 @@ export const sendToBerries = (author, theme) => { window.open(`https://buymeberri.es/!dbuzz${color}/@${author}`, '_blank') } +export const calculateOverhead = (content) => { + let urls = getUrls(content) + + let overhead = 0 + + if(urls?.length > 3) { + urls = urls?.slice(0, 2) + } + + if(urls){ + urls.forEach((item) => { + overhead += item.length + }) + } + + return overhead +} + export const truncateBody = (body) => { - const bodyLength = `${stripHtml(body)}`.length + const overhead = calculateOverhead(body) + const bodyLength = `${stripHtml(body)}`.length - overhead if(bodyLength > 280) { body = stripHtml(body) @@ -367,19 +386,3 @@ export const redirectToUserProfile = () => { window.location = (`/#/@${account[1].replace("#/", "")}`) } } - -export const calculateOverhead = (content) => { - let urls = getUrls(content) - - let overhead = 0 - - if(urls.length > 3) { - urls = urls.slice(0, 2) - } - - urls.forEach((item) => { - overhead += item.length - }) - - return overhead -} diff --git a/src/services/theme.js b/src/services/theme.js index 5f48c378..884a40f1 100644 --- a/src/services/theme.js +++ b/src/services/theme.js @@ -168,6 +168,10 @@ const night = { color: '#172e3f', highlight: 'rgb(56 68 77 / 31%)', }, + seeMoreReplies: { + background: '#192734', + color: '#ffffff', + }, } const light = { @@ -329,6 +333,10 @@ const light = { }, }, skeleton: { }, + seeMoreReplies: { + background: '#F5F8FA', + color: '#778694', + }, } const gray = { @@ -500,6 +508,10 @@ const gray = { color: '#2f3136', highlight: '#36393fed', }, + seeMoreReplies: { + background: '#282A2D', + color: '#ffffff', + }, } export const getTheme = (mode) => {