diff --git a/package.json b/package.json index f67485fce1908b2076e5e7db0ef43d53e02088c9..e7880bbfbfbdaf5b6247136de567079095598d8b 100644 --- a/package.json +++ b/package.json @@ -214,7 +214,7 @@ "npm": ">=5.4.2" }, "lint-staged": { - "src/**/*.+(js)": [ + "src/**/*.+(js|jsx)": [ "eslint" ], "src/**/*.+(json|css|md)": [ diff --git a/src/app/components/cards/PostSummary.jsx b/src/app/components/cards/PostSummary.jsx index 43203acbb43f5738cee3e67c2e5d8e1f957f8b07..d6cf90596c5b7ce610f5d73571a13ba05dfb6477 100644 --- a/src/app/components/cards/PostSummary.jsx +++ b/src/app/components/cards/PostSummary.jsx @@ -26,7 +26,7 @@ const CURATOR_VESTS_THRESHOLD = 1.0 * 1000.0 * 1000.0; // TODO: document why ` ` => `%20` is needed, and/or move to base fucntion const proxify = (url, size) => proxifyImageUrl(url, size).replace(/ /g, '%20'); -const vote_weights = post => { +const vote_weights = (post) => { const rshares = post.get('net_rshares'); const dn = post.getIn(['stats', 'flag_weight']); const up = Math.max(String(parseInt(rshares / 2, 10)).length - 10, 0); @@ -69,7 +69,9 @@ class PostSummary extends React.Component { } } - const { ignore, hideCategory, net_vests } = this.props; + const { + ignore, hideCategory, net_vests, sessionId, + } = this.props; const { post } = this.props; if (!post) return null; @@ -211,7 +213,7 @@ class PostSummary extends React.Component { let dots; if (net_vests >= CURATOR_VESTS_THRESHOLD) { - const _dots = cnt => { + const _dots = (cnt) => { return cnt > 0 ? '•'.repeat(cnt) : null; }; const { up, dn } = vote_weights(post); @@ -291,17 +293,8 @@ class PostSummary extends React.Component { image_link = extractImageLink(post.get('cross_post_json_metadata'), post.get('cross_post_body')); } - let listImgMedium; - let listImgLarge; if (!image_link && !isReply) { - image_link = `https://images.hive.blog/u/${author}/avatar`; - listImgMedium = `https://images.hive.blog/u/${ - author - }/avatar/medium`; - listImgLarge = `https://images.hive.blog/u/${author}/avatar/large`; - } else if (image_link) { - listImgMedium = proxify(image_link, '256x512'); - listImgLarge = proxify(image_link, '640x480'); + image_link = `https://images.hive.blog/u/${author}/avatar${sessionId ? `?ord=${sessionId}` : ''}`; } let thumb = null; @@ -364,6 +357,8 @@ class PostSummary extends React.Component { export default connect((state, props) => { const { post, hideCategory, nsfwPref } = props; const net_vests = state.user.getIn(['current', 'effective_vests'], 0.0); + const sessionId = state.user.get('sessionId'); + return { post, hideCategory, @@ -371,5 +366,6 @@ export default connect((state, props) => { blogmode: state.app.getIn(['user_preferences', 'blogmode']), nsfwPref, net_vests, + sessionId, }; })(PostSummary); diff --git a/src/app/components/cards/SubscriptionsList.jsx b/src/app/components/cards/SubscriptionsList.jsx index 6559a9ff76354e50a3153eee56bedb5819482f1d..ec27b74647e2b4832e9b7cbc33c874b7c322204a 100644 --- a/src/app/components/cards/SubscriptionsList.jsx +++ b/src/app/components/cards/SubscriptionsList.jsx @@ -5,7 +5,9 @@ import { Link } from 'react-router'; import _ from 'lodash'; import 'react-tabs/style/react-tabs.css'; import tt from 'counterpart'; -import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; +import { + Tab, Tabs, TabList, TabPanel, +} from 'react-tabs'; import LoadingIndicator from 'app/components/elements/LoadingIndicator'; import { actions as fetchDataSagaActions } from 'app/redux/FetchDataSaga'; import Callout from 'app/components/elements/Callout'; @@ -26,7 +28,9 @@ class SubscriptionsList extends React.Component { } render() { - const { subscriptions, loading, badges, username } = this.props; + const { + subscriptions, loading, badges, username, sessionId, + } = this.props; const badgesTypes = { activity: [], perso: [], @@ -60,8 +64,8 @@ class SubscriptionsList extends React.Component { if (peakdBadges) { peakdBadges.forEach((badge) => { const type = badge.get('type'); - let valid = true; - if (badgesTypes[type] === undefined || badgesTypes[type] === null) valid = false; + const valid = type in badgesTypes; + if (valid) { badgesTypes[type].push( <a @@ -72,7 +76,7 @@ class SubscriptionsList extends React.Component { rel="noopener noreferrer" > <img - src={badge.get('url')} + src={`${badge.get('url')}${sessionId ? `?ord=${sessionId}` : ''}`} alt={badge.get('title')} title={badge.get('title')} className="UserProfile__badge_image" @@ -112,11 +116,12 @@ class SubscriptionsList extends React.Component { {hasBadges && ( <div> <p> - {tt('g.badges_and_achievements_description')}{' '} + {tt('g.badges_and_achievements_description')} + {' '} <a href="https://peakd.com/" target="_blank" rel="noopener noreferrer"> Peakd - </a>{' '} - &{' '} + </a> + {' & '} <a href="https://hivebuzz.me" target="_blank" rel="noopener noreferrer"> Hivebuzz </a> @@ -171,11 +176,14 @@ export default connect( const isOwnAccount = user.getIn(['current', 'username'], '') === username; const loading = global.getIn(['subscriptions', 'loading']); const subscriptions = global.getIn(['subscriptions', username]); + const sessionId = state.user.get('sessionId'); + return { ...props, subscriptions: subscriptions ? subscriptions.toJS() : [], isOwnAccount, loading, + sessionId, }; }, (dispatch) => ({ diff --git a/src/app/components/elements/Userpic.jsx b/src/app/components/elements/Userpic.jsx index 292234447ec1108a7c7e9dfacbdbf004c1d6a19a..90bca6e46b891ecfddf3cdae34af1690bf355994 100644 --- a/src/app/components/elements/Userpic.jsx +++ b/src/app/components/elements/Userpic.jsx @@ -13,8 +13,9 @@ class Userpic extends Component { render() { if (this.props.hide) return null; - const { account, size } = this.props; - const url = imageProxy() + `u/${account}/avatar${size}`; + const { account, size, sessionId } = this.props; + + const url = `${imageProxy()}u/${account}/avatar${size}${sessionId ? `?ord=${sessionId}` : ''}`; const style = { backgroundImage: `url(${url})` }; return <div className="Userpic" style={style} />; } @@ -33,9 +34,12 @@ export default connect((state, ownProps) => { hide = !url || !/^(https?:)\/\//.test(url); } + const sessionId = state.user.get('sessionId'); + return { - account: account == 'steemitblog' ? 'steemitdev' : account, + account: account === 'steemitblog' ? 'steemitdev' : account, size: size && sizeList.indexOf(size) > -1 ? '/' + size : '', hide, + sessionId, }; })(Userpic); diff --git a/src/app/redux/UserReducer.js b/src/app/redux/UserReducer.js index 25ba0be03dc6a3d039c6af007a6a59f9c03eaef8..d39ba359947a58bfeae82642ade86e85ff610713 100644 --- a/src/app/redux/UserReducer.js +++ b/src/app/redux/UserReducer.js @@ -31,6 +31,7 @@ const SHOW_POST_ADVANCED_SETTINGS = 'user/SHOW_POST_ADVANCED_SETTINGS'; const HIDE_POST_ADVANCED_SETTINGS = 'user/HIDE_POST_ADVANCED_SETTINGS'; const HIDE_ANNOUNCEMENT = 'user/HIDE_ANNOUNCEMENT'; const SHOW_ANNOUNCEMENT = 'user/SHOW_ANNOUNCEMENT'; +const GENERATE_SESSION_ID = 'user/GENERATE_SESSION_ID'; // Saga-related export const UPLOAD_IMAGE = 'user/UPLOAD_IMAGE'; @@ -45,6 +46,7 @@ const defaultState = fromJS({ show_side_panel: false, maybeLoggedIn: false, showAnnouncement: false, + sessionId: '', }); export default function reducer(state = defaultState, action) { @@ -213,6 +215,13 @@ export default function reducer(state = defaultState, action) { typeof sessionStorage !== 'undefined' && sessionStorage.setItem('hideAnnouncement', 'true'); return state.set('showAnnouncement', false); + case GENERATE_SESSION_ID: + const gRand = () => { + return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1); + }; + + return state.set('sessionId', `${gRand() + gRand()}-${gRand()}-${gRand()}-${gRand()}-${gRand()}${gRand()}${gRand()}`); + default: return state; } @@ -362,3 +371,7 @@ export const hideAnnouncement = () => ({ export const showAnnouncement = () => ({ type: SHOW_ANNOUNCEMENT, }); + +export const generateSessionId = () => ({ + type: GENERATE_SESSION_ID, +}); diff --git a/src/app/redux/UserSaga.js b/src/app/redux/UserSaga.js index 3f3642d106365fae05cec52fe93ec01cea7ec02c..543b6a3c3ce9e7d9b1fbb2d025092de7c17d87dc 100644 --- a/src/app/redux/UserSaga.js +++ b/src/app/redux/UserSaga.js @@ -115,7 +115,9 @@ function* usernamePasswordLogin(action) { yield call(usernamePasswordLogin2, action.payload); const current = yield select((state) => state.user.get('current')); const username = current ? current.get('username') : null; + if (username) { + yield put(userActions.generateSessionId()); yield fork(loadFollows, 'getFollowingAsync', username, 'blog'); yield fork(loadFollows, 'getFollowingAsync', username, 'ignore'); }