Progress
This commit is contained in:
parent
143725b5bd
commit
567894f614
|
@ -2,25 +2,25 @@ import api from '../api';
|
||||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||||
import { me } from '../initial_state';
|
import { me } from '../initial_state';
|
||||||
|
|
||||||
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
export const REPOST_REQUEST = 'REPOST_REQUEST';
|
||||||
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
export const REPOST_SUCCESS = 'REPOST_SUCCESS';
|
||||||
export const REBLOG_FAIL = 'REBLOG_FAIL';
|
export const REPOST_FAIL = 'REPOST_FAIL';
|
||||||
|
|
||||||
export const FAVORITE_REQUEST = 'FAVORITE_REQUEST';
|
export const FAVORITE_REQUEST = 'FAVORITE_REQUEST';
|
||||||
export const FAVORITE_SUCCESS = 'FAVORITE_SUCCESS';
|
export const FAVORITE_SUCCESS = 'FAVORITE_SUCCESS';
|
||||||
export const FAVORITE_FAIL = 'FAVORITE_FAIL';
|
export const FAVORITE_FAIL = 'FAVORITE_FAIL';
|
||||||
|
|
||||||
export const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
|
export const UNREPOST_REQUEST = 'UNREPOST_REQUEST';
|
||||||
export const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
|
export const UNREPOST_SUCCESS = 'UNREPOST_SUCCESS';
|
||||||
export const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
|
export const UNREPOST_FAIL = 'UNREPOST_FAIL';
|
||||||
|
|
||||||
export const UNFAVORITE_REQUEST = 'UNFAVORITE_REQUEST';
|
export const UNFAVORITE_REQUEST = 'UNFAVORITE_REQUEST';
|
||||||
export const UNFAVORITE_SUCCESS = 'UNFAVORITE_SUCCESS';
|
export const UNFAVORITE_SUCCESS = 'UNFAVORITE_SUCCESS';
|
||||||
export const UNFAVORITE_FAIL = 'UNFAVORITE_FAIL';
|
export const UNFAVORITE_FAIL = 'UNFAVORITE_FAIL';
|
||||||
|
|
||||||
export const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST';
|
export const REPOSTS_FETCH_REQUEST = 'REPOSTS_FETCH_REQUEST';
|
||||||
export const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS';
|
export const REPOSTS_FETCH_SUCCESS = 'REPOSTS_FETCH_SUCCESS';
|
||||||
export const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL';
|
export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL';
|
||||||
|
|
||||||
export const PIN_REQUEST = 'PIN_REQUEST';
|
export const PIN_REQUEST = 'PIN_REQUEST';
|
||||||
export const PIN_SUCCESS = 'PIN_SUCCESS';
|
export const PIN_SUCCESS = 'PIN_SUCCESS';
|
||||||
|
@ -30,119 +30,119 @@ export const UNPIN_REQUEST = 'UNPIN_REQUEST';
|
||||||
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
|
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
|
||||||
export const UNPIN_FAIL = 'UNPIN_FAIL';
|
export const UNPIN_FAIL = 'UNPIN_FAIL';
|
||||||
|
|
||||||
export function reblog(status) {
|
export function repost(status) {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
|
||||||
dispatch(reblogRequest(status));
|
dispatch(repostRequest(status));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then(function (response) {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then(function (response) {
|
||||||
// The reblog API method returns a new status wrapped around the original. In this case we are only
|
// The reblog API method returns a new status wrapped around the original. In this case we are only
|
||||||
// interested in how the original is modified, hence passing it skipping the wrapper
|
// interested in how the original is modified, hence passing it skipping the wrapper
|
||||||
dispatch(importFetchedStatus(response.data.reblog));
|
dispatch(importFetchedStatus(response.data.reblog));
|
||||||
dispatch(reblogSuccess(status));
|
dispatch(repostSuccess(status));
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
dispatch(reblogFail(status, error));
|
dispatch(repostFail(status, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unreblog(status) {
|
export function unrepost(status) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
|
||||||
dispatch(unreblogRequest(status));
|
dispatch(unrepostRequest(status));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
|
||||||
dispatch(importFetchedStatus(response.data));
|
dispatch(importFetchedStatus(response.data));
|
||||||
dispatch(unreblogSuccess(status));
|
dispatch(unrepostSuccess(status));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unreblogFail(status, error));
|
dispatch(unrepostFail(status, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reblogRequest(status) {
|
export function repostRequest(status) {
|
||||||
return {
|
return {
|
||||||
type: REBLOG_REQUEST,
|
type: REPOST_REQUEST,
|
||||||
status: status,
|
status: status,
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reblogSuccess(status) {
|
export function repostSuccess(status) {
|
||||||
return {
|
return {
|
||||||
type: REBLOG_SUCCESS,
|
type: REPOST_SUCCESS,
|
||||||
status: status,
|
status: status,
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reblogFail(status, error) {
|
export function repostFail(status, error) {
|
||||||
return {
|
return {
|
||||||
type: REBLOG_FAIL,
|
type: REPOST_FAIL,
|
||||||
status: status,
|
status: status,
|
||||||
error: error,
|
error: error,
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unreblogRequest(status) {
|
export function unrepostRequest(status) {
|
||||||
return {
|
return {
|
||||||
type: UNREBLOG_REQUEST,
|
type: UNREPOST_REQUEST,
|
||||||
status: status,
|
status: status,
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unreblogSuccess(status) {
|
export function unrepostSuccess(status) {
|
||||||
return {
|
return {
|
||||||
type: UNREBLOG_SUCCESS,
|
type: UNREPOST_SUCCESS,
|
||||||
status: status,
|
status: status,
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unreblogFail(status, error) {
|
export function unrepostFail(status, error) {
|
||||||
return {
|
return {
|
||||||
type: UNREBLOG_FAIL,
|
type: UNREPOST_FAIL,
|
||||||
status: status,
|
status: status,
|
||||||
error: error,
|
error: error,
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function favourite(status) {
|
export function favorite(status) {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
|
||||||
dispatch(favouriteRequest(status));
|
dispatch(favoriteRequest(status));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
|
||||||
dispatch(importFetchedStatus(response.data));
|
dispatch(importFetchedStatus(response.data));
|
||||||
dispatch(favouriteSuccess(status));
|
dispatch(favoriteSuccess(status));
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
dispatch(favouriteFail(status, error));
|
dispatch(favoriteFail(status, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unfavourite(status) {
|
export function unfavorite(status) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
|
||||||
dispatch(unfavouriteRequest(status));
|
dispatch(unfavoriteRequest(status));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
|
||||||
dispatch(importFetchedStatus(response.data));
|
dispatch(importFetchedStatus(response.data));
|
||||||
dispatch(unfavouriteSuccess(status));
|
dispatch(unfavoriteSuccess(status));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unfavouriteFail(status, error));
|
dispatch(unfavoriteFail(status, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function favouriteRequest(status) {
|
export function favoriteRequest(status) {
|
||||||
return {
|
return {
|
||||||
type: FAVORITE_REQUEST,
|
type: FAVORITE_REQUEST,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -150,7 +150,7 @@ export function favouriteRequest(status) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function favouriteSuccess(status) {
|
export function favoriteSuccess(status) {
|
||||||
return {
|
return {
|
||||||
type: FAVORITE_SUCCESS,
|
type: FAVORITE_SUCCESS,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -158,7 +158,7 @@ export function favouriteSuccess(status) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function favouriteFail(status, error) {
|
export function favoriteFail(status, error) {
|
||||||
return {
|
return {
|
||||||
type: FAVORITE_FAIL,
|
type: FAVORITE_FAIL,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -167,7 +167,7 @@ export function favouriteFail(status, error) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unfavouriteRequest(status) {
|
export function unfavoriteRequest(status) {
|
||||||
return {
|
return {
|
||||||
type: UNFAVORITE_REQUEST,
|
type: UNFAVORITE_REQUEST,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -175,7 +175,7 @@ export function unfavouriteRequest(status) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unfavouriteSuccess(status) {
|
export function unfavoriteSuccess(status) {
|
||||||
return {
|
return {
|
||||||
type: UNFAVORITE_SUCCESS,
|
type: UNFAVORITE_SUCCESS,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -183,7 +183,7 @@ export function unfavouriteSuccess(status) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function unfavouriteFail(status, error) {
|
export function unfavoriteFail(status, error) {
|
||||||
return {
|
return {
|
||||||
type: UNFAVORITE_FAIL,
|
type: UNFAVORITE_FAIL,
|
||||||
status: status,
|
status: status,
|
||||||
|
@ -192,39 +192,39 @@ export function unfavouriteFail(status, error) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fetchReblogs(id) {
|
export function fetchReposts(id) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
|
||||||
dispatch(fetchReblogsRequest(id));
|
dispatch(fetchRepostsRequest(id));
|
||||||
|
|
||||||
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
|
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
|
||||||
dispatch(importFetchedAccounts(response.data));
|
dispatch(importFetchedAccounts(response.data));
|
||||||
dispatch(fetchReblogsSuccess(id, response.data));
|
dispatch(fetchRepostsSuccess(id, response.data));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(fetchReblogsFail(id, error));
|
dispatch(fetchRepostsFail(id, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fetchReblogsRequest(id) {
|
export function fetchRepostsRequest(id) {
|
||||||
return {
|
return {
|
||||||
type: REBLOGS_FETCH_REQUEST,
|
type: REPOSTS_FETCH_REQUEST,
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fetchReblogsSuccess(id, accounts) {
|
export function fetchRepostsSuccess(id, accounts) {
|
||||||
return {
|
return {
|
||||||
type: REBLOGS_FETCH_SUCCESS,
|
type: REPOSTS_FETCH_SUCCESS,
|
||||||
id,
|
id,
|
||||||
accounts,
|
accounts,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fetchReblogsFail(id, error) {
|
export function fetchRepostsFail(id, error) {
|
||||||
return {
|
return {
|
||||||
type: REBLOGS_FETCH_FAIL,
|
type: REPOSTS_FETCH_FAIL,
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -157,7 +157,7 @@ export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done =
|
||||||
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
|
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
|
||||||
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
|
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
|
||||||
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
|
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
|
||||||
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
|
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 20 });
|
||||||
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
|
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
|
||||||
export const expandGroupTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done);
|
export const expandGroupTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done);
|
||||||
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
|
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import { decode } from 'blurhash'
|
||||||
|
import { autoPlayGif, displayMedia } from '../initial_state'
|
||||||
|
import Icon from './icon'
|
||||||
|
import Image from './image'
|
||||||
|
import Text from './text'
|
||||||
|
|
||||||
|
export default class MediaItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
attachment: ImmutablePropTypes.map.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
|
||||||
|
loaded: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.attachment.get('blurhash')) {
|
||||||
|
this._decode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.attachment.get('blurhash') !== this.props.attachment.get('blurhash') && this.props.attachment.get('blurhash')) {
|
||||||
|
this._decode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_decode() {
|
||||||
|
const hash = this.props.attachment.get('blurhash')
|
||||||
|
const pixels = decode(hash, 160, 160)
|
||||||
|
|
||||||
|
if (pixels && this.canvas) {
|
||||||
|
const ctx = this.canvas.getContext('2d')
|
||||||
|
const imageData = new ImageData(pixels, 160, 160)
|
||||||
|
|
||||||
|
ctx.putImageData(imageData, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setCanvasRef = c => {
|
||||||
|
this.canvas = c
|
||||||
|
}
|
||||||
|
|
||||||
|
handleImageLoad = () => {
|
||||||
|
this.setState({ loaded: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
hoverToPlay() {
|
||||||
|
return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { attachment } = this.props
|
||||||
|
const { visible, loaded } = this.state
|
||||||
|
|
||||||
|
const status = attachment.get('status')
|
||||||
|
const title = status.get('spoiler_text') || attachment.get('description')
|
||||||
|
|
||||||
|
const attachmentType = attachment.get('type')
|
||||||
|
let badge = null
|
||||||
|
|
||||||
|
if (attachmentType === 'video') {
|
||||||
|
const duration = attachment.getIn(['meta', 'duration'])
|
||||||
|
badge = (duration / 60).toFixed(2)
|
||||||
|
} else if (attachmentType === 'gifv') {
|
||||||
|
badge = 'GIF'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.width25PC, _s.paddingTop25PC].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.positionAbsolute, _s.top0, _s.height100PC, _s.width100PC, _s.paddingVertical5PX, _s.paddingHorizontal5PX].join(' ')}>
|
||||||
|
<NavLink
|
||||||
|
to={status.get('url')} /* : todo : */
|
||||||
|
title={title}
|
||||||
|
className={[_s.default, _s.width100PC, _s.height100PC, _s.border1PX, _s.borderColorSecondary, _s.overflowHidden].join(' ')}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
(!loaded || !visible) &&
|
||||||
|
<canvas
|
||||||
|
height='100%'
|
||||||
|
width='100%'
|
||||||
|
ref={this.setCanvasRef}
|
||||||
|
className={[_s.default, _s.width100PC, _s.height100PC, _s.z2].join(' ')}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
visible &&
|
||||||
|
<Image
|
||||||
|
height='100%'
|
||||||
|
src={attachment.get('preview_url')}
|
||||||
|
alt={attachment.get('description')}
|
||||||
|
title={attachment.get('description')}
|
||||||
|
onLoad={this.handleImageLoad}
|
||||||
|
className={_s.z1}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.alignItemsCenter, _s.justifyContentCenter, _s.height100PC, _s.width100PC, _s.z3, _s.positionAbsolute].join(' ')}>
|
||||||
|
{
|
||||||
|
!visible &&
|
||||||
|
<Icon
|
||||||
|
id='hidden'
|
||||||
|
width='22px'
|
||||||
|
height='22px'
|
||||||
|
className={[_s.fillColorWhite].join('')}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!!badge &&
|
||||||
|
<div className={[_s.default, _s.positionAbsolute, _s.radiusSmall, _s.backgroundColorOpaque, _s.paddingHorizontal5PX, _s.paddingVertical5PX, _s.marginRight5PX, _s.marginVertical5PX, _s.bottom0, _s.right0].join(' ')}>
|
||||||
|
<Text size='extraSmall' color='white'>
|
||||||
|
{badge}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map.isRequired,
|
status: ImmutablePropTypes.map.isRequired,
|
||||||
onReblog: PropTypes.func.isRequired,
|
onRepost: PropTypes.func.isRequired,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -33,8 +33,8 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
this.button.focus();
|
this.button.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReblog = () => {
|
handleRepost = () => {
|
||||||
this.props.onReblog(this.props.status);
|
this.props.onRepost(this.props.status);
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<Button text={intl.formatMessage(buttonText)} onClick={this.handleReblog} ref={this.setRef} />
|
<Button text={intl.formatMessage(buttonText)} onClick={this.handleRepost} ref={this.setRef} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,7 +11,7 @@ const messages = defineMessages({
|
||||||
reply: { id: 'keyboard_shortcuts.reply', defaultMessage: 'reply' },
|
reply: { id: 'keyboard_shortcuts.reply', defaultMessage: 'reply' },
|
||||||
mention: { id: 'keyboard_shortcuts.mention', defaultMessage: 'mention author' },
|
mention: { id: 'keyboard_shortcuts.mention', defaultMessage: 'mention author' },
|
||||||
profile: { id: 'keyboard_shortcuts.profile', defaultMessage: 'open author\'s profile' },
|
profile: { id: 'keyboard_shortcuts.profile', defaultMessage: 'open author\'s profile' },
|
||||||
favourite: { id: 'keyboard_shortcuts.favourite', defaultMessage: 'favorite' },
|
favorite: { id: 'keyboard_shortcuts.favorite', defaultMessage: 'favorite' },
|
||||||
boost: { id: 'keyboard_shortcuts.boost', defaultMessage: 'repost' },
|
boost: { id: 'keyboard_shortcuts.boost', defaultMessage: 'repost' },
|
||||||
enter: { id: 'keyboard_shortcuts.enter', defaultMessage: 'open status' },
|
enter: { id: 'keyboard_shortcuts.enter', defaultMessage: 'open status' },
|
||||||
toggle_hidden: { id: 'keyboard_shortcuts.toggle_hidden', defaultMessage: 'show/hide text behind CW' },
|
toggle_hidden: { id: 'keyboard_shortcuts.toggle_hidden', defaultMessage: 'show/hide text behind CW' },
|
||||||
|
@ -28,7 +28,7 @@ const messages = defineMessages({
|
||||||
notifications: { id: 'keyboard_shortcuts.notifications', defaultMessage: 'open notifications column' },
|
notifications: { id: 'keyboard_shortcuts.notifications', defaultMessage: 'open notifications column' },
|
||||||
direct: { id: 'keyboard_shortcuts.direct', defaultMessage: 'open direct messages column' },
|
direct: { id: 'keyboard_shortcuts.direct', defaultMessage: 'open direct messages column' },
|
||||||
start: { id: 'keyboard_shortcuts.start', defaultMessage: 'open "get started" column' },
|
start: { id: 'keyboard_shortcuts.start', defaultMessage: 'open "get started" column' },
|
||||||
favourites: { id: 'keyboard_shortcuts.favourites', defaultMessage: 'open favorites list' },
|
favorites: { id: 'keyboard_shortcuts.favorites', defaultMessage: 'open favorites list' },
|
||||||
pinned: { id: 'keyboard_shortcuts.pinned', defaultMessage: 'open pinned gabs list' },
|
pinned: { id: 'keyboard_shortcuts.pinned', defaultMessage: 'open pinned gabs list' },
|
||||||
my_profile: { id: 'keyboard_shortcuts.my_profile', defaultMessage: 'open your profile' },
|
my_profile: { id: 'keyboard_shortcuts.my_profile', defaultMessage: 'open your profile' },
|
||||||
blocked: { id: 'keyboard_shortcuts.blocked', defaultMessage: 'open blocked users list' },
|
blocked: { id: 'keyboard_shortcuts.blocked', defaultMessage: 'open blocked users list' },
|
||||||
|
@ -65,7 +65,7 @@ class HotkeysModal extends ImmutablePureComponent {
|
||||||
<HotKeysModalRow hotkey='r' action={intl.formatMessage(messages.reply)} />
|
<HotKeysModalRow hotkey='r' action={intl.formatMessage(messages.reply)} />
|
||||||
<HotKeysModalRow hotkey='m' action={intl.formatMessage(messages.mention)} />
|
<HotKeysModalRow hotkey='m' action={intl.formatMessage(messages.mention)} />
|
||||||
<HotKeysModalRow hotkey='p' action={intl.formatMessage(messages.profile)} />
|
<HotKeysModalRow hotkey='p' action={intl.formatMessage(messages.profile)} />
|
||||||
<HotKeysModalRow hotkey='f' action={intl.formatMessage(messages.favourite)} />
|
<HotKeysModalRow hotkey='f' action={intl.formatMessage(messages.favorite)} />
|
||||||
<HotKeysModalRow hotkey='b' action={intl.formatMessage(messages.boost)} />
|
<HotKeysModalRow hotkey='b' action={intl.formatMessage(messages.boost)} />
|
||||||
<HotKeysModalRow hotkey='enter, o' action={intl.formatMessage(messages.enter)} />
|
<HotKeysModalRow hotkey='enter, o' action={intl.formatMessage(messages.enter)} />
|
||||||
<HotKeysModalRow hotkey='x' action={intl.formatMessage(messages.toggle_hidden)} />
|
<HotKeysModalRow hotkey='x' action={intl.formatMessage(messages.toggle_hidden)} />
|
||||||
|
@ -108,7 +108,7 @@ class HotkeysModal extends ImmutablePureComponent {
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<HotKeysModalRow hotkey='g + s' action={intl.formatMessage(messages.start)} />
|
<HotKeysModalRow hotkey='g + s' action={intl.formatMessage(messages.start)} />
|
||||||
<HotKeysModalRow hotkey='g + f' action={intl.formatMessage(messages.favourites)} />
|
<HotKeysModalRow hotkey='g + f' action={intl.formatMessage(messages.favorites)} />
|
||||||
<HotKeysModalRow hotkey='g + p' action={intl.formatMessage(messages.pinned)} />
|
<HotKeysModalRow hotkey='g + p' action={intl.formatMessage(messages.pinned)} />
|
||||||
<HotKeysModalRow hotkey='g + u' action={intl.formatMessage(messages.my_profile)} />
|
<HotKeysModalRow hotkey='g + u' action={intl.formatMessage(messages.my_profile)} />
|
||||||
<HotKeysModalRow hotkey='g + b' action={intl.formatMessage(messages.blocked)} />
|
<HotKeysModalRow hotkey='g + b' action={intl.formatMessage(messages.blocked)} />
|
||||||
|
|
|
@ -51,7 +51,7 @@ class ProfileStatsPanel extends ImmutablePureComponent {
|
||||||
account.get('id') === me &&
|
account.get('id') === me &&
|
||||||
<UserStat
|
<UserStat
|
||||||
title={intl.formatMessage(messages.favorites)}
|
title={intl.formatMessage(messages.favorites)}
|
||||||
value={shortNumberFormat(account.get('favourite_count'))}
|
value={shortNumberFormat(account.get('favourite_count'))} /* : todo : */
|
||||||
to={`/${account.get('acct')}/favorites`}
|
to={`/${account.get('acct')}/favorites`}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default class StatusOptionsPopover extends PureComponent {
|
||||||
// menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
// menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
||||||
// } else {
|
// } else {
|
||||||
// if (status.get('visibility') === 'private') {
|
// if (status.get('visibility') === 'private') {
|
||||||
// menu.push({ text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleReblogClick });
|
// menu.push({ text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleRepostClick });
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -207,12 +207,14 @@ export default class ScrollableList extends PureComponent {
|
||||||
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null;
|
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null;
|
||||||
|
|
||||||
if (showLoading) {
|
if (showLoading) {
|
||||||
return ( <ColumnIndicator type='loading' /> );
|
return <ColumnIndicator type='loading' />
|
||||||
} else if (isLoading || childrenCount > 0 || hasMore || !emptyMessage) {
|
} else if (isLoading || childrenCount > 0 || hasMore || !emptyMessage) {
|
||||||
return (
|
return (
|
||||||
<div className='scrollable-list' onMouseMove={this.handleMouseMove}>
|
<div onMouseMove={this.handleMouseMove}>
|
||||||
<div role='feed'>
|
<div role='feed'>
|
||||||
{React.Children.map(this.props.children, (child, index) => (
|
{
|
||||||
|
!!this.props.children &&
|
||||||
|
React.Children.map(this.props.children, (child, index) => (
|
||||||
<IntersectionObserverArticle
|
<IntersectionObserverArticle
|
||||||
key={child.key}
|
key={child.key}
|
||||||
id={child.key}
|
id={child.key}
|
||||||
|
@ -221,14 +223,17 @@ export default class ScrollableList extends PureComponent {
|
||||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||||
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
|
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
|
||||||
>
|
>
|
||||||
{React.cloneElement(child, {
|
{
|
||||||
|
React.cloneElement(child, {
|
||||||
getScrollPosition: this.getScrollPosition,
|
getScrollPosition: this.getScrollPosition,
|
||||||
updateScrollBottom: this.updateScrollBottom,
|
updateScrollBottom: this.updateScrollBottom,
|
||||||
cachedMediaWidth: this.state.cachedMediaWidth,
|
cachedMediaWidth: this.state.cachedMediaWidth,
|
||||||
cacheMediaWidth: this.cacheMediaWidth,
|
cacheMediaWidth: this.cacheMediaWidth,
|
||||||
})}
|
})
|
||||||
|
}
|
||||||
</IntersectionObserverArticle>
|
</IntersectionObserverArticle>
|
||||||
))}
|
))
|
||||||
|
}
|
||||||
|
|
||||||
{loadMore}
|
{loadMore}
|
||||||
</div>
|
</div>
|
||||||
|
@ -236,7 +241,7 @@ export default class ScrollableList extends PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ( <ColumnIndicator type='error' message={emptyMessage} /> );
|
return <ColumnIndicator type='error' message={emptyMessage} />
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,8 @@ class Status extends ImmutablePureComponent {
|
||||||
onReply: PropTypes.func,
|
onReply: PropTypes.func,
|
||||||
onShowRevisions: PropTypes.func,
|
onShowRevisions: PropTypes.func,
|
||||||
onQuote: PropTypes.func,
|
onQuote: PropTypes.func,
|
||||||
onFavourite: PropTypes.func,
|
onFavorite: PropTypes.func,
|
||||||
onReblog: PropTypes.func,
|
onRepost: PropTypes.func,
|
||||||
onDelete: PropTypes.func,
|
onDelete: PropTypes.func,
|
||||||
onEdit: PropTypes.func,
|
onEdit: PropTypes.func,
|
||||||
onDirect: PropTypes.func,
|
onDirect: PropTypes.func,
|
||||||
|
@ -212,12 +212,12 @@ class Status extends ImmutablePureComponent {
|
||||||
this.props.onReply(this._properStatus(), this.context.router.history);
|
this.props.onReply(this._properStatus(), this.context.router.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyFavourite = () => {
|
handleHotkeyFavorite = () => {
|
||||||
this.props.onFavourite(this._properStatus());
|
this.props.onFavorite(this._properStatus());
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyBoost = e => {
|
handleHotkeyBoost = e => {
|
||||||
this.props.onReblog(this._properStatus(), e);
|
this.props.onRepost(this._properStatus(), e);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyMention = e => {
|
handleHotkeyMention = e => {
|
||||||
|
@ -424,7 +424,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
const handlers = this.props.muted ? {} : {
|
const handlers = this.props.muted ? {} : {
|
||||||
reply: this.handleHotkeyReply,
|
reply: this.handleHotkeyReply,
|
||||||
favourite: this.handleHotkeyFavourite,
|
favorite: this.handleHotkeyFavorite,
|
||||||
boost: this.handleHotkeyBoost,
|
boost: this.handleHotkeyBoost,
|
||||||
mention: this.handleHotkeyMention,
|
mention: this.handleHotkeyMention,
|
||||||
open: this.handleHotkeyOpen,
|
open: this.handleHotkeyOpen,
|
||||||
|
|
|
@ -63,8 +63,8 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
onOpenUnauthorizedModal: PropTypes.func.isRequired,
|
onOpenUnauthorizedModal: PropTypes.func.isRequired,
|
||||||
onReply: PropTypes.func,
|
onReply: PropTypes.func,
|
||||||
onQuote: PropTypes.func,
|
onQuote: PropTypes.func,
|
||||||
onFavourite: PropTypes.func,
|
onFavorite: PropTypes.func,
|
||||||
onReblog: PropTypes.func,
|
onRepost: PropTypes.func,
|
||||||
onDelete: PropTypes.func,
|
onDelete: PropTypes.func,
|
||||||
onMention: PropTypes.func,
|
onMention: PropTypes.func,
|
||||||
onMute: PropTypes.func,
|
onMute: PropTypes.func,
|
||||||
|
@ -101,17 +101,17 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFavouriteClick = () => {
|
handleFavoriteClick = () => {
|
||||||
if (me) {
|
if (me) {
|
||||||
this.props.onFavourite(this.props.status)
|
this.props.onFavorite(this.props.status)
|
||||||
} else {
|
} else {
|
||||||
this.props.onOpenUnauthorizedModal()
|
this.props.onOpenUnauthorizedModal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReblogClick = e => {
|
handleRepostClick = e => {
|
||||||
if (me) {
|
if (me) {
|
||||||
this.props.onReblog(this.props.status, e)
|
this.props.onRepost(this.props.status, e)
|
||||||
} else {
|
} else {
|
||||||
this.props.onOpenUnauthorizedModal()
|
this.props.onOpenUnauthorizedModal()
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
const reblogCount = status.get('reblogs_count')
|
const reblogCount = status.get('reblogs_count')
|
||||||
const reblogTitle = !publicStatus ? formatMessage(messages.cannot_reblog) : formatMessage(messages.reblog)
|
const reblogTitle = !publicStatus ? formatMessage(messages.cannot_reblog) : formatMessage(messages.reblog)
|
||||||
|
|
||||||
const favoriteCount = status.get('favourites_count')
|
const favoriteCount = status.get('favorites_count') // : todo :
|
||||||
|
|
||||||
const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && (
|
const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && (
|
||||||
<IconButton className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
<IconButton className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
||||||
|
@ -139,8 +139,8 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
{
|
{
|
||||||
title: formatMessage(messages.like),
|
title: formatMessage(messages.like),
|
||||||
icon: 'like',
|
icon: 'like',
|
||||||
active: !!status.get('favourited'),
|
active: !!status.get('favorited'),
|
||||||
onClick: this.handleFavouriteClick,
|
onClick: this.handleFavoriteClick,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: formatMessage(messages.comment),
|
title: formatMessage(messages.comment),
|
||||||
|
@ -153,13 +153,13 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
icon: (status.get('visibility') === 'private') ? 'lock' : 'repost',
|
icon: (status.get('visibility') === 'private') ? 'lock' : 'repost',
|
||||||
disabled: !publicStatus,
|
disabled: !publicStatus,
|
||||||
active: !!status.get('reblogged'),
|
active: !!status.get('reblogged'),
|
||||||
onClick: this.handleReblogClick,
|
onClick: this.handleRepostClick,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: formatMessage(messages.share),
|
title: formatMessage(messages.share),
|
||||||
icon: 'share',
|
icon: 'share',
|
||||||
active: false,
|
active: false,
|
||||||
onClick: this.handleFavouriteClick,
|
onClick: this.handleFavoriteClick,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ export default class StatusHeader extends ImmutablePureComponent {
|
||||||
menu.push({ text: formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
menu.push({ text: formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
||||||
} else {
|
} else {
|
||||||
if (status.get('visibility') === 'private') {
|
if (status.get('visibility') === 'private') {
|
||||||
menu.push({ text: formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleReblogClick });
|
menu.push({ text: formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleRepostClick });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick });
|
menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||||
|
|
|
@ -7,9 +7,9 @@ import {
|
||||||
} from '../actions/compose';
|
} from '../actions/compose';
|
||||||
import {
|
import {
|
||||||
reblog,
|
reblog,
|
||||||
favourite,
|
favorite,
|
||||||
unreblog,
|
unreblog,
|
||||||
unfavourite,
|
unfavorite,
|
||||||
pin,
|
pin,
|
||||||
unpin,
|
unpin,
|
||||||
} from '../actions/interactions';
|
} from '../actions/interactions';
|
||||||
|
@ -88,19 +88,19 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onModalReblog (status) {
|
onModalRepost (status) {
|
||||||
if (status.get('reblogged')) {
|
if (status.get('reblogged')) {
|
||||||
dispatch(unreblog(status));
|
dispatch(unrepost(status));
|
||||||
} else {
|
} else {
|
||||||
dispatch(reblog(status));
|
dispatch(repost(status));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onReblog (status, e) {
|
onRepost (status, e) {
|
||||||
if (e.shiftKey || !boostModal) {
|
if (e.shiftKey || !boostModal) {
|
||||||
this.onModalReblog(status);
|
this.onModalRepost(status);
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog }));
|
dispatch(openModal('BOOST', { status, onRepost: this.onModalRepost }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -108,11 +108,11 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
dispatch(openModal('STATUS_REVISION', { status }));
|
dispatch(openModal('STATUS_REVISION', { status }));
|
||||||
},
|
},
|
||||||
|
|
||||||
onFavourite (status) {
|
onFavorite (status) {
|
||||||
if (status.get('favourited')) {
|
if (status.get('favourited')) {
|
||||||
dispatch(unfavourite(status));
|
dispatch(unfavorite(status));
|
||||||
} else {
|
} else {
|
||||||
dispatch(favourite(status));
|
dispatch(favorite(status));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { expandAccountMediaTimeline } from '../actions/timelines'
|
||||||
|
import { getAccountGallery } from '../selectors'
|
||||||
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
import MediaItem from '../components/media_item'
|
||||||
|
import LoadMore from '../components/load_more'
|
||||||
|
import Block from '../components/block'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
none: { id: 'account_gallery.none', defaultMessage: 'No media to show.' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { account }) => {
|
||||||
|
const accountId = !!account ? account.get('id') : -1
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountId,
|
||||||
|
attachments: getAccountGallery(state, accountId),
|
||||||
|
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading']),
|
||||||
|
hasMore: state.getIn(['timelines', `account:${accountId}:media`, 'hasMore']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
class AccountGallery extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
account: ImmutablePropTypes.map,
|
||||||
|
accountId: PropTypes.string,
|
||||||
|
attachments: ImmutablePropTypes.list.isRequired,
|
||||||
|
isLoading: PropTypes.bool,
|
||||||
|
hasMore: PropTypes.bool,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { accountId } = this.props
|
||||||
|
|
||||||
|
if (accountId) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(accountId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleScrollToBottom = () => {
|
||||||
|
if (this.props.hasMore) {
|
||||||
|
this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleScroll = e => {
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = e.target
|
||||||
|
const offset = scrollHeight - scrollTop - clientHeight
|
||||||
|
|
||||||
|
if (150 > offset && !this.props.isLoading) {
|
||||||
|
this.handleScrollToBottom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadMore = maxId => {
|
||||||
|
if (this.props.accountId && this.props.accountId !== -1) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { maxId }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadOlder = e => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.handleScrollToBottom()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
attachments,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
intl,
|
||||||
|
account
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Block>
|
||||||
|
<div
|
||||||
|
role='feed'
|
||||||
|
onScroll={this.handleScroll}
|
||||||
|
className={[_s.default, _s.flexRow, _s.flexWrap, _s.heightMin50VH, _s.paddingVertical5PX, _s.paddingHorizontal5PX].join(' ')}
|
||||||
|
>
|
||||||
|
|
||||||
|
{
|
||||||
|
attachments.map((attachment) => (
|
||||||
|
<MediaItem key={attachment.get('id')} attachment={attachment} />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
isLoading && attachments.size === 0 &&
|
||||||
|
<ColumnIndicator type='loading' />
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /*
|
||||||
|
attachments.size == 0 &&
|
||||||
|
<ColumnIndicator type='empty' message={intl.formatMessage(messages.none)} />
|
||||||
|
*/ }
|
||||||
|
|
||||||
|
{
|
||||||
|
hasMore && !(isLoading && attachments.size === 0) &&
|
||||||
|
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,205 +0,0 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
|
|
||||||
import {
|
|
||||||
fetchAccount,
|
|
||||||
fetchAccountByUsername,
|
|
||||||
} from '../../actions/accounts';
|
|
||||||
import { openModal } from '../../actions/modal';
|
|
||||||
import { expandAccountMediaTimeline } from '../../actions/timelines';
|
|
||||||
import { me } from '../../initial_state';
|
|
||||||
import { getAccountGallery } from '../../selectors';
|
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
|
||||||
import MediaItem from './components/media_item';
|
|
||||||
import LoadMore from '../../components/load_more';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
posts: { id: 'account.posts', defaultMessage: 'Gabs' },
|
|
||||||
postsWithReplies: { id: 'account.posts_with_replies', defaultMessage: 'Gabs and replies' },
|
|
||||||
media: { id: 'account.media', defaultMessage: 'Media' },
|
|
||||||
error: { id: 'empty_column.account_unavailable', defaultMessage: 'Profile unavailable' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { mediaType, params: { username } }) => {
|
|
||||||
const accounts = state.getIn(['accounts']);
|
|
||||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase());
|
|
||||||
|
|
||||||
let accountId = -1;
|
|
||||||
let accountUsername = username;
|
|
||||||
if (accountFetchError) {
|
|
||||||
accountId = null;
|
|
||||||
} else {
|
|
||||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
|
|
||||||
accountId = account ? account.getIn(['id'], null) : -1;
|
|
||||||
accountUsername = account ? account.getIn(['acct'], '') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false);
|
|
||||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false);
|
|
||||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false);
|
|
||||||
const unavailable = (me === accountId) ? false : (isBlocked || (isLocked && !isFollowing));
|
|
||||||
|
|
||||||
return {
|
|
||||||
accountId,
|
|
||||||
unavailable,
|
|
||||||
accountUsername,
|
|
||||||
isAccount: !!state.getIn(['accounts', accountId]),
|
|
||||||
attachments: getAccountGallery(state, accountId),
|
|
||||||
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading']),
|
|
||||||
hasMore: state.getIn(['timelines', `account:${accountId}:media`, 'hasMore']),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoadMoreMedia extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
maxId: PropTypes.string,
|
|
||||||
onLoadMore: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleLoadMore = () => {
|
|
||||||
this.props.onLoadMore(this.props.maxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<LoadMore
|
|
||||||
disabled={this.props.disabled}
|
|
||||||
onClick={this.handleLoadMore}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default
|
|
||||||
@connect(mapStateToProps)
|
|
||||||
@injectIntl
|
|
||||||
class AccountGallery extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
params: PropTypes.object.isRequired,
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
attachments: ImmutablePropTypes.list.isRequired,
|
|
||||||
isLoading: PropTypes.bool,
|
|
||||||
hasMore: PropTypes.bool,
|
|
||||||
isAccount: PropTypes.bool,
|
|
||||||
unavailable: PropTypes.bool,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
state = {
|
|
||||||
width: 323,
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const { params: { username }, accountId } = this.props;
|
|
||||||
|
|
||||||
if (accountId && accountId !== -1) {
|
|
||||||
this.props.dispatch(fetchAccount(accountId));
|
|
||||||
this.props.dispatch(expandAccountMediaTimeline(accountId));
|
|
||||||
} else {
|
|
||||||
this.props.dispatch(fetchAccountByUsername(username));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId)) {
|
|
||||||
this.props.dispatch(fetchAccount(nextProps.params.accountId));
|
|
||||||
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleScrollToBottom = () => {
|
|
||||||
if (this.props.hasMore) {
|
|
||||||
this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleScroll = e => {
|
|
||||||
const { scrollTop, scrollHeight, clientHeight } = e.target;
|
|
||||||
const offset = scrollHeight - scrollTop - clientHeight;
|
|
||||||
|
|
||||||
if (150 > offset && !this.props.isLoading) {
|
|
||||||
this.handleScrollToBottom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = maxId => {
|
|
||||||
if (this.props.accountId && this.props.accountId !== -1) {
|
|
||||||
this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { maxId }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleLoadOlder = e => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.handleScrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenMedia = attachment => {
|
|
||||||
if (attachment.get('type') === 'video') {
|
|
||||||
this.props.dispatch(openModal('VIDEO', { media: attachment, status: attachment.get('status') }));
|
|
||||||
} else {
|
|
||||||
const media = attachment.getIn(['status', 'media_attachments']);
|
|
||||||
const index = media.findIndex(x => x.get('id') === attachment.get('id'));
|
|
||||||
|
|
||||||
this.props.dispatch(openModal('MEDIA', { media, index, status: attachment.get('status') }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleRef = c => {
|
|
||||||
if (c) {
|
|
||||||
this.setState({ width: c.offsetWidth });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { attachments, isLoading, hasMore, isAccount, accountId, unavailable, accountUsername, intl } = this.props;
|
|
||||||
const { width } = this.state;
|
|
||||||
|
|
||||||
if (!isAccount && accountId !== -1) {
|
|
||||||
return <ColumnIndicator type='missing' />
|
|
||||||
} else if (accountId === -1 || (!attachments && isLoading)) {
|
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (unavailable) {
|
|
||||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.error)} />
|
|
||||||
}
|
|
||||||
|
|
||||||
let loadOlder = null
|
|
||||||
|
|
||||||
if (hasMore && !(isLoading && attachments.size === 0)) {
|
|
||||||
loadOlder = <LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='scrollable-list scrollable-list--flex' onScroll={this.handleScroll}>
|
|
||||||
<div role='feed' className='account-gallery__container' ref={this.handleRef}>
|
|
||||||
{
|
|
||||||
attachments.map((attachment, index) => attachment === null ? (
|
|
||||||
<LoadMoreMedia key={'more:' + attachments.getIn(index + 1, 'id')} maxId={index > 0 ? attachments.getIn(index - 1, 'id') : null} onLoadMore={this.handleLoadMore} />
|
|
||||||
) : (
|
|
||||||
<MediaItem key={attachment.get('id')} attachment={attachment} displayWidth={width} onOpenMedia={this.handleOpenMedia} />
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
attachments.size == 0 &&
|
|
||||||
<div className='empty-column-indicator'>
|
|
||||||
<FormattedMessage id='account_gallery.none' defaultMessage='No media to show.' />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{loadOlder}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
isLoading && attachments.size === 0 &&
|
|
||||||
<div className='slist__append'>
|
|
||||||
<ColumnIndicator type='loading' />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
.account-gallery__container {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 4px 2px;
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './media_item'
|
|
|
@ -1,156 +0,0 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { decode } from 'blurhash';
|
|
||||||
import Icon from '../../../../components/icon';
|
|
||||||
import { autoPlayGif, displayMedia } from '../../../../initial_state';
|
|
||||||
import { isIOS } from '../../../../utils/is_mobile';
|
|
||||||
|
|
||||||
export default class MediaItem extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
attachment: ImmutablePropTypes.map.isRequired,
|
|
||||||
displayWidth: PropTypes.number.isRequired,
|
|
||||||
onOpenMedia: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
|
|
||||||
loaded: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
if (this.props.attachment.get('blurhash')) {
|
|
||||||
this._decode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
|
||||||
if (prevProps.attachment.get('blurhash') !== this.props.attachment.get('blurhash') && this.props.attachment.get('blurhash')) {
|
|
||||||
this._decode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_decode () {
|
|
||||||
const hash = this.props.attachment.get('blurhash');
|
|
||||||
const pixels = decode(hash, 32, 32);
|
|
||||||
|
|
||||||
if (pixels) {
|
|
||||||
const ctx = this.canvas.getContext('2d');
|
|
||||||
const imageData = new ImageData(pixels, 32, 32);
|
|
||||||
|
|
||||||
ctx.putImageData(imageData, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setCanvasRef = c => {
|
|
||||||
this.canvas = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleImageLoad = () => {
|
|
||||||
this.setState({ loaded: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMouseEnter = e => {
|
|
||||||
if (this.hoverToPlay()) {
|
|
||||||
e.target.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMouseLeave = e => {
|
|
||||||
if (this.hoverToPlay()) {
|
|
||||||
e.target.pause();
|
|
||||||
e.target.currentTime = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hoverToPlay () {
|
|
||||||
return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = e => {
|
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (this.state.visible) {
|
|
||||||
this.props.onOpenMedia(this.props.attachment);
|
|
||||||
} else {
|
|
||||||
this.setState({ visible: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { attachment, displayWidth } = this.props;
|
|
||||||
const { visible, loaded } = this.state;
|
|
||||||
|
|
||||||
const width = `${Math.floor((displayWidth - 4) / 3) - 4}px`;
|
|
||||||
const height = width;
|
|
||||||
const status = attachment.get('status');
|
|
||||||
const title = status.get('spoiler_text') || attachment.get('description');
|
|
||||||
|
|
||||||
let thumbnail = '';
|
|
||||||
let icon;
|
|
||||||
|
|
||||||
if (attachment.get('type') === 'unknown') {
|
|
||||||
// Skip
|
|
||||||
} else if (attachment.get('type') === 'image') {
|
|
||||||
const focusX = attachment.getIn(['meta', 'focus', 'x']) || 0;
|
|
||||||
const focusY = attachment.getIn(['meta', 'focus', 'y']) || 0;
|
|
||||||
const x = ((focusX / 2) + .5) * 100;
|
|
||||||
const y = ((focusY / -2) + .5) * 100;
|
|
||||||
|
|
||||||
thumbnail = (
|
|
||||||
<img
|
|
||||||
src={attachment.get('preview_url')}
|
|
||||||
alt={attachment.get('description')}
|
|
||||||
title={attachment.get('description')}
|
|
||||||
style={{ objectPosition: `${x}% ${y}%` }}
|
|
||||||
onLoad={this.handleImageLoad}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (['gifv', 'video'].indexOf(attachment.get('type')) !== -1) {
|
|
||||||
const autoPlay = !isIOS() && autoPlayGif;
|
|
||||||
|
|
||||||
thumbnail = (
|
|
||||||
<div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
|
|
||||||
<video
|
|
||||||
className='media-gallery__item-gifv-thumbnail'
|
|
||||||
aria-label={attachment.get('description')}
|
|
||||||
title={attachment.get('description')}
|
|
||||||
role='application'
|
|
||||||
src={attachment.get('url')}
|
|
||||||
onMouseEnter={this.handleMouseEnter}
|
|
||||||
onMouseLeave={this.handleMouseLeave}
|
|
||||||
autoPlay={autoPlay}
|
|
||||||
preload='auto'
|
|
||||||
loop
|
|
||||||
muted
|
|
||||||
playsInline
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span className='media-gallery__gifv__label'>GIF</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!visible) {
|
|
||||||
icon = (
|
|
||||||
<span className='account-gallery__item__icons'>
|
|
||||||
<Icon id='eye-slash' />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='account-gallery__item' style={{ width, height }}>
|
|
||||||
<a href={status.get('url')} target='_blank' onClick={this.handleClick} title={title}>
|
|
||||||
<canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': visible && loaded })} />
|
|
||||||
{visible && thumbnail}
|
|
||||||
{!visible && icon}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
.account-gallery__item {
|
|
||||||
border: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin: 2px;
|
|
||||||
|
|
||||||
&__icons {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './account_gallery'
|
|
|
@ -1,55 +1,30 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable'
|
||||||
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import { fetchAccount, fetchAccountByUsername } from '../../actions/accounts';
|
import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines'
|
||||||
import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines';
|
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'
|
||||||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
import StatusList from '../../components/status_list/status_list'
|
||||||
import { me } from '../../initial_state';
|
|
||||||
import StatusList from '../../components/status_list/status_list';
|
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
posts: { id: 'account.posts', defaultMessage: 'Gabs' },
|
empty: { id: 'empty_column.account_timeline', defaultMessage: 'No gabs here!' },
|
||||||
postsWithReplies: { id: 'account.posts_with_replies', defaultMessage: 'Gabs and replies' },
|
})
|
||||||
media: { id: 'account.media', defaultMessage: 'Media' },
|
|
||||||
error: { id: 'empty_column.account_unavailable', defaultMessage: 'Profile unavailable' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const emptyList = ImmutableList();
|
const emptyList = ImmutableList()
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username }, withReplies = false }) => {
|
const mapStateToProps = (state, { account, withReplies = false }) => {
|
||||||
const accounts = state.getIn(['accounts']);
|
const accountId = !!account ? account.getIn(['id'], null) : -1
|
||||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase());
|
|
||||||
|
|
||||||
let accountId = -1;
|
const path = withReplies ? `${accountId}:with_replies` : accountId
|
||||||
let accountUsername = username;
|
|
||||||
if (accountFetchError) {
|
|
||||||
accountId = null;
|
|
||||||
} else {
|
|
||||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
|
|
||||||
accountId = account ? account.getIn(['id'], null) : -1;
|
|
||||||
accountUsername = account ? account.getIn(['acct'], '') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const path = withReplies ? `${accountId}:with_replies` : accountId;
|
|
||||||
|
|
||||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false);
|
|
||||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false);
|
|
||||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false);
|
|
||||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accountId,
|
accountId,
|
||||||
unavailable,
|
|
||||||
accountUsername,
|
|
||||||
isAccount: !!state.getIn(['accounts', accountId]),
|
|
||||||
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
|
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
|
||||||
featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList),
|
featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList),
|
||||||
isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
|
isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
|
||||||
hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
|
hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
|
@ -64,57 +39,56 @@ class AccountTimeline extends ImmutablePureComponent {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
withReplies: PropTypes.bool,
|
withReplies: PropTypes.bool,
|
||||||
isAccount: PropTypes.bool,
|
|
||||||
unavailable: PropTypes.bool,
|
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
const { params: { username }, accountId, withReplies } = this.props;
|
|
||||||
|
|
||||||
if (accountId && accountId !== -1) {
|
|
||||||
this.props.dispatch(fetchAccount(accountId));
|
|
||||||
this.props.dispatch(fetchAccountIdentityProofs(accountId));
|
|
||||||
|
|
||||||
if (!withReplies) {
|
|
||||||
this.props.dispatch(expandAccountFeaturedTimeline(accountId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
|
componentWillMount() {
|
||||||
} else {
|
const { accountId, withReplies } = this.props
|
||||||
this.props.dispatch(fetchAccountByUsername(username));
|
|
||||||
|
if (accountId && accountId !== -1) {
|
||||||
|
this.props.dispatch(fetchAccountIdentityProofs(accountId))
|
||||||
|
|
||||||
|
if (!withReplies) {
|
||||||
|
this.props.dispatch(expandAccountFeaturedTimeline(accountId))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.dispatch(expandAccountTimeline(accountId, { withReplies }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId) || nextProps.withReplies !== this.props.withReplies) {
|
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId) || nextProps.withReplies !== this.props.withReplies) {
|
||||||
this.props.dispatch(fetchAccount(nextProps.accountId));
|
this.props.dispatch(fetchAccountIdentityProofs(nextProps.accountId))
|
||||||
this.props.dispatch(fetchAccountIdentityProofs(nextProps.accountId));
|
|
||||||
|
|
||||||
if (!nextProps.withReplies) {
|
if (!nextProps.withReplies) {
|
||||||
this.props.dispatch(expandAccountFeaturedTimeline(nextProps.accountId));
|
this.props.dispatch(expandAccountFeaturedTimeline(nextProps.accountId))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.dispatch(expandAccountTimeline(nextProps.accountId, { withReplies: nextProps.withReplies }));
|
this.props.dispatch(expandAccountTimeline(nextProps.accountId, { withReplies: nextProps.withReplies }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoadMore = maxId => {
|
handleLoadMore = maxId => {
|
||||||
if (this.props.accountId && this.props.accountId !== -1) {
|
if (this.props.accountId && this.props.accountId !== -1) {
|
||||||
this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies }));
|
this.props.dispatch(expandAccountTimeline(this.props.accountId, {
|
||||||
|
maxId,
|
||||||
|
withReplies: this.props.withReplies
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { statusIds, featuredStatusIds, isLoading, hasMore, isAccount, accountId, unavailable, accountUsername, intl } = this.props;
|
const {
|
||||||
|
account,
|
||||||
|
statusIds,
|
||||||
|
featuredStatusIds,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
intl
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
if (!isAccount && accountId !== -1) {
|
|
||||||
return <ColumnIndicator type='missing' />
|
|
||||||
} else if (accountId === -1 || (!statusIds && isLoading)) {
|
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (unavailable) {
|
|
||||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.error)} />
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<StatusList
|
<StatusList
|
||||||
scrollKey='account_timeline'
|
scrollKey='account_timeline'
|
||||||
|
@ -123,9 +97,9 @@ class AccountTimeline extends ImmutablePureComponent {
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
emptyMessage={<FormattedMessage id='empty_column.account_timeline' defaultMessage='No gabs here!' />}
|
emptyMessage={intl.formatMessage(messages.empty)}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default class Header extends ImmutablePureComponent {
|
||||||
onBlock: PropTypes.func.isRequired,
|
onBlock: PropTypes.func.isRequired,
|
||||||
onMention: PropTypes.func.isRequired,
|
onMention: PropTypes.func.isRequired,
|
||||||
onDirect: PropTypes.func.isRequired,
|
onDirect: PropTypes.func.isRequired,
|
||||||
onReblogToggle: PropTypes.func.isRequired,
|
onRepostToggle: PropTypes.func.isRequired,
|
||||||
onReport: PropTypes.func.isRequired,
|
onReport: PropTypes.func.isRequired,
|
||||||
onMute: PropTypes.func.isRequired,
|
onMute: PropTypes.func.isRequired,
|
||||||
onBlockDomain: PropTypes.func.isRequired,
|
onBlockDomain: PropTypes.func.isRequired,
|
||||||
|
@ -47,8 +47,8 @@ export default class Header extends ImmutablePureComponent {
|
||||||
this.props.onReport(this.props.account);
|
this.props.onReport(this.props.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReblogToggle = () => {
|
handleRepostToggle = () => {
|
||||||
this.props.onReblogToggle(this.props.account);
|
this.props.onRepostToggle(this.props.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMute = () => {
|
handleMute = () => {
|
||||||
|
@ -94,7 +94,7 @@ export default class Header extends ImmutablePureComponent {
|
||||||
onBlock={this.handleBlock}
|
onBlock={this.handleBlock}
|
||||||
onMention={this.handleMention}
|
onMention={this.handleMention}
|
||||||
onDirect={this.handleDirect}
|
onDirect={this.handleDirect}
|
||||||
onReblogToggle={this.handleReblogToggle}
|
onRepostToggle={this.handleRepostToggle}
|
||||||
onReport={this.handleReport}
|
onReport={this.handleReport}
|
||||||
onMute={this.handleMute}
|
onMute={this.handleMute}
|
||||||
onBlockDomain={this.handleBlockDomain}
|
onBlockDomain={this.handleBlockDomain}
|
||||||
|
|
|
@ -114,9 +114,9 @@ class Header extends ImmutablePureComponent {
|
||||||
} else {
|
} else {
|
||||||
if (account.getIn(['relationship', 'following'])) {
|
if (account.getIn(['relationship', 'following'])) {
|
||||||
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
||||||
menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });
|
menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onRepostToggle });
|
||||||
} else {
|
} else {
|
||||||
menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });
|
menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onRepostToggle });
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList });
|
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList });
|
||||||
|
@ -279,7 +279,7 @@ class Header extends ImmutablePureComponent {
|
||||||
<NavLink exact activeClassName='active' to={`/${account.get('acct')}/favorites`} title={intl.formatNumber(account.get('favourite_count'))}>
|
<NavLink exact activeClassName='active' to={`/${account.get('acct')}/favorites`} title={intl.formatNumber(account.get('favourite_count'))}>
|
||||||
{ /* : TODO : shortNumberFormat(account.get('favourite_count')) */ }
|
{ /* : TODO : shortNumberFormat(account.get('favourite_count')) */ }
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<FormattedMessage id='navigation_bar.favourites' defaultMessage='Favorites' />
|
<FormattedMessage id='navigation_bar.favorites' defaultMessage='Favorites' />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink exact activeClassName='active' to={`/${account.get('acct')}/pins`} title={intl.formatNumber(account.get('pinned_count'))}>
|
<NavLink exact activeClassName='active' to={`/${account.get('acct')}/pins`} title={intl.formatNumber(account.get('pinned_count'))}>
|
||||||
{ /* : TODO : shortNumberFormat(account.get('pinned_count')) */ }
|
{ /* : TODO : shortNumberFormat(account.get('pinned_count')) */ }
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './profile_info_panel'
|
|
|
@ -1,135 +0,0 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { List as ImmutableList } from 'immutable';
|
|
||||||
import Icon from '../../../../components/icon';
|
|
||||||
import VerifiedIcon from '../../../../components/verified_icon';
|
|
||||||
import Badge from '../../../../components/badge';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
|
|
||||||
account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' },
|
|
||||||
bot: { id: 'account.badges.bot', defaultMessage: 'Bot' },
|
|
||||||
memberSince: { id: 'account.member_since', defaultMessage:'Member since {date}'},
|
|
||||||
});
|
|
||||||
|
|
||||||
const dateFormatOptions = {
|
|
||||||
month: 'short',
|
|
||||||
day: 'numeric',
|
|
||||||
year: 'numeric',
|
|
||||||
hour12: false,
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { account }) => {
|
|
||||||
const identity_proofs = account ? state.getIn(['identity_proofs', account.get('id')], ImmutableList()) : ImmutableList();
|
|
||||||
return {
|
|
||||||
identity_proofs,
|
|
||||||
domain: state.getIn(['meta', 'domain']),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default
|
|
||||||
@connect(mapStateToProps)
|
|
||||||
@injectIntl
|
|
||||||
class ProfileInfoPanel extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
account: ImmutablePropTypes.map,
|
|
||||||
identity_proofs: ImmutablePropTypes.list,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
username: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { account, intl, identity_proofs, username } = this.props;
|
|
||||||
|
|
||||||
if (!account) {
|
|
||||||
return (
|
|
||||||
<div className='profile-info-panel'>
|
|
||||||
<div className='profile-info-panel__content'>
|
|
||||||
<div className='profile-info-panel-content__name'>
|
|
||||||
<h1>
|
|
||||||
<span/>
|
|
||||||
<small>@{username}</small>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lockedIcon = account.get('locked') ? (<Icon id='lock' title={intl.formatMessage(messages.account_locked)} />) : '';
|
|
||||||
const badge = account.get('bot') ? (<div className='account-role bot'>{intl.formatMessage(messages.bot)}</div>) : null;
|
|
||||||
const content = { __html: account.get('note_emojified') };
|
|
||||||
const fields = account.get('fields');
|
|
||||||
const acct = account.get('acct');
|
|
||||||
const displayNameHtml = { __html: account.get('display_name_html') };
|
|
||||||
const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' });
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='profile-info-panel'>
|
|
||||||
<div className='profile-info-panel__content'>
|
|
||||||
|
|
||||||
<div className='profile-info-panel-content__name'>
|
|
||||||
<h1>
|
|
||||||
<span dangerouslySetInnerHTML={displayNameHtml} />
|
|
||||||
{account.get('is_verified') && <VerifiedIcon />}
|
|
||||||
{badge}
|
|
||||||
<small>@{acct} {lockedIcon}</small>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='profile-info-panel-content__badges'>
|
|
||||||
{account.get('is_pro') && <Badge type='pro' />}
|
|
||||||
{account.get('is_donor') && <Badge type='donor' />}
|
|
||||||
{account.get('is_investor') && <Badge type='investor' />}
|
|
||||||
<div className='profile-info-panel-content__badges__join-date'>
|
|
||||||
<Icon id="calendar"/>
|
|
||||||
{intl.formatMessage(messages.memberSince, {
|
|
||||||
date: memberSinceDate
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
(account.get('note').length > 0 && account.get('note') !== '<p></p>') &&
|
|
||||||
<div className='profile-info-panel-content__bio' dangerouslySetInnerHTML={content} />
|
|
||||||
}
|
|
||||||
|
|
||||||
{(fields.size > 0 || identity_proofs.size > 0) && (
|
|
||||||
<div className='profile-info-panel-content__fields'>
|
|
||||||
{identity_proofs.map((proof, i) => (
|
|
||||||
<dl className='test' key={i}>
|
|
||||||
<dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} />
|
|
||||||
|
|
||||||
<dd className='verified'>
|
|
||||||
<a href={proof.get('proof_url')} target='_blank' rel='noopener'>
|
|
||||||
<span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
|
|
||||||
<Icon id='check' className='verified__mark' />
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a href={proof.get('profile_url')} target='_blank' rel='noopener'>
|
|
||||||
<span dangerouslySetInnerHTML={{ __html: ' ' + proof.get('provider_username') }} />
|
|
||||||
</a>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{fields.map((pair, i) => (
|
|
||||||
<dl className='profile-info-panel-content__fields__item' key={i}>
|
|
||||||
<dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} />
|
|
||||||
|
|
||||||
<dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}>
|
|
||||||
{pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
.profile-info-panel {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex: 1 1;
|
|
||||||
|
|
||||||
@media (min-width:895px) {
|
|
||||||
padding-top: 60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-info-panel-content {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
&__badges {
|
|
||||||
display: flex;
|
|
||||||
margin: 5px 0;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
&__join-date {
|
|
||||||
display: block;
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $primary-text-color;
|
|
||||||
|
|
||||||
@include text-sizing(15px, 400, 1.25);
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
color: $gab-default-text-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__name {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.account-role {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emojione {
|
|
||||||
@include size(22px);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
span:first-of-type {
|
|
||||||
color: #ffffff;
|
|
||||||
|
|
||||||
@include text-overflow(nowrap);
|
|
||||||
@include text-sizing(20px, 600, 1.25);
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
color: $gab-default-text-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
display: block;
|
|
||||||
color: $secondary-text-color;
|
|
||||||
|
|
||||||
@include text-sizing(16px, 400, 1.5);
|
|
||||||
@include text-overflow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__bio {
|
|
||||||
display: block;
|
|
||||||
flex: 1 1;
|
|
||||||
color: $primary-text-color;
|
|
||||||
margin: 15px 0;
|
|
||||||
|
|
||||||
@include text-sizing(15px, 400, 1.25);
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: lighten($ui-highlight-color, 8%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__fields {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
|
||||||
padding: 10px 0;
|
|
||||||
margin: 5px 0;
|
|
||||||
|
|
||||||
@media screen and (max-width:895px) {
|
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 12%);
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: lighten($ui-highlight-color, 8%);
|
|
||||||
}
|
|
||||||
|
|
||||||
dl:first-child .verified {
|
|
||||||
border-radius: 0 4px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verified a {
|
|
||||||
color: $valid-value-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__item {
|
|
||||||
display: flex;
|
|
||||||
padding: 2px 0;
|
|
||||||
margin: 2px 0;
|
|
||||||
flex: 1 1;
|
|
||||||
|
|
||||||
* {
|
|
||||||
@include text-sizing(15px, 400, 24px);
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
min-width: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -83,7 +83,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
dispatch(directCompose(account, router));
|
dispatch(directCompose(account, router));
|
||||||
},
|
},
|
||||||
|
|
||||||
onReblogToggle (account) {
|
onRepostToggle (account) {
|
||||||
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
||||||
dispatch(followAccount(account.get('id'), false));
|
dispatch(followAccount(account.get('id'), false));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash'
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
import AccountContainer from '../../containers/account_container';
|
import AccountContainer from '../containers/account_container'
|
||||||
import { fetchBlocks, expandBlocks } from '../../actions/blocks';
|
import { fetchBlocks, expandBlocks } from '../actions/blocks'
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
|
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './blocks'
|
|
|
@ -2,10 +2,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
|
import { fetchDomainBlocks, expandDomainBlocks } from '../actions/domain_blocks';
|
||||||
import DomainContainer from '../../containers/domain_container';
|
import DomainContainer from '../containers/domain_container';
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../components/scrollable_list';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.domain_blocks', defaultMessage: 'Hidden domains' },
|
heading: { id: 'column.domain_blocks', defaultMessage: 'Hidden domains' },
|
|
@ -1 +1 @@
|
||||||
export { default } from './domain_blocks'
|
export { default } from '../domain_blocks'
|
|
@ -1,7 +1,7 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { fetchReblogs } from '../../actions/interactions';
|
import { fetchReposts } from '../../actions/interactions';
|
||||||
import { fetchStatus } from '../../actions/statuses';
|
import { fetchStatus } from '../../actions/statuses';
|
||||||
import { makeGetStatus } from '../../selectors';
|
import { makeGetStatus } from '../../selectors';
|
||||||
import AccountContainer from '../../containers/account_container';
|
import AccountContainer from '../../containers/account_container';
|
||||||
|
@ -33,13 +33,13 @@ class Favorites extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.dispatch(fetchReblogs(this.props.params.statusId));
|
this.props.dispatch(fetchReposts(this.props.params.statusId));
|
||||||
this.props.dispatch(fetchStatus(this.props.params.statusId));
|
this.props.dispatch(fetchStatus(this.props.params.statusId));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||||
this.props.dispatch(fetchReblogs(nextProps.params.statusId));
|
this.props.dispatch(fetchReposts(nextProps.params.statusId));
|
||||||
this.props.dispatch(fetchStatus(nextProps.params.statusId));
|
this.props.dispatch(fetchStatus(nextProps.params.statusId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import { debounce } from 'lodash'
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import {
|
||||||
|
fetchFollowers,
|
||||||
|
expandFollowers,
|
||||||
|
} from '../actions/accounts'
|
||||||
|
import AccountContainer from '../containers/account_container'
|
||||||
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
import Block from '../components/block'
|
||||||
|
import Heading from '../components/heading'
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { account }) => {
|
||||||
|
const accountId = !!account ? account.get('id') : -1
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountId,
|
||||||
|
accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']),
|
||||||
|
hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||||
|
empty: { id: 'account.followers.empty', defaultMessage: 'No one follows this user yet.' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
class Followers extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
account: ImmutablePropTypes.map,
|
||||||
|
accountId: PropTypes.string,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
params: PropTypes.object.isRequired,
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
accountIds: ImmutablePropTypes.list,
|
||||||
|
hasMore: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
const { accountId } = this.props
|
||||||
|
|
||||||
|
if (accountId && accountId !== -1) {
|
||||||
|
this.props.dispatch(fetchFollowers(accountId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (!!nextProps.accountId && nextProps.accountId !== -1 && nextProps.accountId !== this.props.accountId) {
|
||||||
|
this.props.dispatch(fetchFollowers(nextProps.accountId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadMore = debounce(() => {
|
||||||
|
const { accountId } = this.props
|
||||||
|
if (!!accountId && accountId !== -1) {
|
||||||
|
this.props.dispatch(expandFollowers(accountId))
|
||||||
|
}
|
||||||
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
accountIds,
|
||||||
|
hasMore,
|
||||||
|
intl
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Block>
|
||||||
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.justifyContentCenter, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
||||||
|
<Heading size='h3'>
|
||||||
|
{intl.formatMessage(messages.followers)}
|
||||||
|
</Heading>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||||
|
<ScrollableList
|
||||||
|
scrollKey='followers'
|
||||||
|
hasMore={hasMore}
|
||||||
|
onLoadMore={this.handleLoadMore}
|
||||||
|
emptyMessage={intl.formatMessage(messages.empty)}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
!!accountIds && accountIds.map((id) => (
|
||||||
|
<AccountContainer key={`follower-${id}`} id={id} withNote={false} compact />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,132 +0,0 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
||||||
import { debounce } from 'lodash'
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
|
||||||
import ColumnIndicator from '../../components/column_indicator'
|
|
||||||
import {
|
|
||||||
fetchAccount,
|
|
||||||
fetchFollowers,
|
|
||||||
expandFollowers,
|
|
||||||
fetchAccountByUsername,
|
|
||||||
} from '../../actions/accounts'
|
|
||||||
import { me } from '../../initial_state'
|
|
||||||
import AccountContainer from '../../containers/account_container'
|
|
||||||
import ScrollableList from '../../components/scrollable_list'
|
|
||||||
import Block from '../../components/block'
|
|
||||||
import Heading from '../../components/heading'
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username } }) => {
|
|
||||||
const accounts = state.getIn(['accounts'])
|
|
||||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase())
|
|
||||||
|
|
||||||
let accountId = -1
|
|
||||||
if (accountFetchError) {
|
|
||||||
accountId = null
|
|
||||||
} else {
|
|
||||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
|
||||||
accountId = account ? account.getIn(['id'], null) : -1
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
|
||||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
|
|
||||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
|
|
||||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing))
|
|
||||||
|
|
||||||
return {
|
|
||||||
accountId,
|
|
||||||
unavailable,
|
|
||||||
isAccount: !!state.getIn(['accounts', accountId]),
|
|
||||||
accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']),
|
|
||||||
hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
|
||||||
empty: { id: 'account.followers.empty', defaultMessage: 'No one follows this user yet.' },
|
|
||||||
unavailable: { id: 'empty_column.account_unavailable', defaultMessage: 'Profile unavailable' },
|
|
||||||
})
|
|
||||||
|
|
||||||
export default
|
|
||||||
@connect(mapStateToProps)
|
|
||||||
@injectIntl
|
|
||||||
class Followers extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
params: PropTypes.object.isRequired,
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
accountIds: ImmutablePropTypes.list,
|
|
||||||
hasMore: PropTypes.bool,
|
|
||||||
isAccount: PropTypes.bool,
|
|
||||||
unavailable: PropTypes.bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
const { params: { username }, accountId } = this.props
|
|
||||||
|
|
||||||
if (accountId && accountId !== -1) {
|
|
||||||
this.props.dispatch(fetchAccount(accountId))
|
|
||||||
this.props.dispatch(fetchFollowers(accountId))
|
|
||||||
} else {
|
|
||||||
this.props.dispatch(fetchAccountByUsername(username))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId)) {
|
|
||||||
this.props.dispatch(fetchAccount(nextProps.accountId))
|
|
||||||
this.props.dispatch(fetchFollowers(nextProps.accountId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = debounce(() => {
|
|
||||||
if (this.props.accountId && this.props.accountId !== -1) {
|
|
||||||
this.props.dispatch(expandFollowers(this.props.accountId))
|
|
||||||
}
|
|
||||||
}, 300, { leading: true })
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
accountIds,
|
|
||||||
hasMore,
|
|
||||||
isAccount,
|
|
||||||
accountId,
|
|
||||||
unavailable,
|
|
||||||
intl
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
if (!isAccount && accountId !== -1) {
|
|
||||||
return <ColumnIndicator type='missing' />
|
|
||||||
} else if (accountId === -1 || (!accountIds)) {
|
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (unavailable) {
|
|
||||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.unavailable)} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Block>
|
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.justifyContentCenter, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
|
||||||
<Heading size='h3'>
|
|
||||||
{intl.formatMessage(messages.followers)}
|
|
||||||
</Heading>
|
|
||||||
</div>
|
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
|
||||||
<ScrollableList
|
|
||||||
scrollKey='followers'
|
|
||||||
hasMore={hasMore}
|
|
||||||
onLoadMore={this.handleLoadMore}
|
|
||||||
emptyMessage={intl.formatMessage(messages.empty)}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
accountIds.map((id, i) => (
|
|
||||||
<AccountContainer key={id} id={id} withNote={false} compact />
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</ScrollableList>
|
|
||||||
</div>
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './followers'
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import { debounce } from 'lodash'
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import {
|
||||||
|
fetchFollowing,
|
||||||
|
expandFollowing,
|
||||||
|
} from '../actions/accounts'
|
||||||
|
import AccountContainer from '../containers/account_container'
|
||||||
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
import Block from '../components/block'
|
||||||
|
import Heading from '../components/heading'
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { account }) => {
|
||||||
|
const accountId = !!account ? account.get('id') : -1
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountId,
|
||||||
|
accountIds: state.getIn(['user_lists', 'following', accountId, 'items']),
|
||||||
|
hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||||
|
empty: { id: 'account.follows.empty', defaultMessage: 'This user doesn\'t follow anyone yet.' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
class Following extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
params: PropTypes.object.isRequired,
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
accountIds: ImmutablePropTypes.list,
|
||||||
|
account: ImmutablePropTypes.map,
|
||||||
|
accountId: PropTypes.string,
|
||||||
|
hasMore: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
const { accountId } = this.props
|
||||||
|
|
||||||
|
if (!!accountId && accountId !== -1) {
|
||||||
|
this.props.dispatch(fetchFollowing(accountId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (!!nextProps.accountId && nextProps.accountId !== -1 && nextProps.accountId !== this.props.accountId) {
|
||||||
|
this.props.dispatch(fetchFollowing(nextProps.accountId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadMore = debounce(() => {
|
||||||
|
const { accountId } = this.props
|
||||||
|
if (!!accountId && accountId !== -1) {
|
||||||
|
this.props.dispatch(expandFollowing(accountId))
|
||||||
|
}
|
||||||
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
accountIds,
|
||||||
|
hasMore,
|
||||||
|
intl
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Block>
|
||||||
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.justifyContentCenter, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
||||||
|
<Heading size='h3'>
|
||||||
|
{intl.formatMessage(messages.follows)}
|
||||||
|
</Heading>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||||
|
<ScrollableList
|
||||||
|
scrollKey='following'
|
||||||
|
hasMore={hasMore}
|
||||||
|
onLoadMore={this.handleLoadMore}
|
||||||
|
emptyMessage={intl.formatMessage(messages.empty)}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
!!accountIds && accountIds.map((id) => (
|
||||||
|
<AccountContainer key={`following-${id}`} id={id} withNote={false} compact />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,134 +0,0 @@
|
||||||
import { Fragment } from 'react'
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
||||||
import { debounce } from 'lodash'
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
|
||||||
import {
|
|
||||||
fetchAccount,
|
|
||||||
fetchFollowing,
|
|
||||||
expandFollowing,
|
|
||||||
fetchAccountByUsername,
|
|
||||||
} from '../../actions/accounts'
|
|
||||||
import { me } from '../../initial_state'
|
|
||||||
import AccountContainer from '../../containers/account_container'
|
|
||||||
import ColumnIndicator from '../../components/column_indicator'
|
|
||||||
import ScrollableList from '../../components/scrollable_list'
|
|
||||||
import Block from '../../components/block'
|
|
||||||
import Divider from '../../components/divider'
|
|
||||||
import Heading from '../../components/heading'
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username } }) => {
|
|
||||||
const accounts = state.getIn(['accounts'])
|
|
||||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase())
|
|
||||||
|
|
||||||
let accountId = -1
|
|
||||||
if (accountFetchError) {
|
|
||||||
accountId = null
|
|
||||||
} else {
|
|
||||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
|
||||||
accountId = account ? account.getIn(['id'], null) : -1
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
|
||||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
|
|
||||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
|
|
||||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing))
|
|
||||||
|
|
||||||
return {
|
|
||||||
accountId,
|
|
||||||
unavailable,
|
|
||||||
isAccount: !!state.getIn(['accounts', accountId]),
|
|
||||||
accountIds: state.getIn(['user_lists', 'following', accountId, 'items']),
|
|
||||||
hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
|
||||||
empty: { id: 'account.follows.empty', defaultMessage: 'This user doesn\'t follow anyone yet.' },
|
|
||||||
unavailable: { id: 'empty_column.account_unavailable', defaultMessage: 'Profile unavailable' },
|
|
||||||
})
|
|
||||||
|
|
||||||
export default
|
|
||||||
@connect(mapStateToProps)
|
|
||||||
@injectIntl
|
|
||||||
class Following extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
params: PropTypes.object.isRequired,
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
accountIds: ImmutablePropTypes.list,
|
|
||||||
hasMore: PropTypes.bool,
|
|
||||||
isAccount: PropTypes.bool,
|
|
||||||
unavailable: PropTypes.bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
const { params: { username }, accountId } = this.props
|
|
||||||
|
|
||||||
if (accountId && accountId !== -1) {
|
|
||||||
this.props.dispatch(fetchAccount(accountId))
|
|
||||||
this.props.dispatch(fetchFollowing(accountId))
|
|
||||||
} else {
|
|
||||||
this.props.dispatch(fetchAccountByUsername(username))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId)) {
|
|
||||||
this.props.dispatch(fetchAccount(nextProps.accountId))
|
|
||||||
this.props.dispatch(fetchFollowing(nextProps.accountId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = debounce(() => {
|
|
||||||
if (this.props.accountId && this.props.accountId !== -1) {
|
|
||||||
this.props.dispatch(expandFollowing(this.props.accountId))
|
|
||||||
}
|
|
||||||
}, 300, { leading: true })
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
accountIds,
|
|
||||||
hasMore,
|
|
||||||
isAccount,
|
|
||||||
accountId,
|
|
||||||
unavailable,
|
|
||||||
intl
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
if (!isAccount && accountId !== -1) {
|
|
||||||
return <ColumnIndicator type='missing' />
|
|
||||||
} else if (accountId === -1 || (!accountIds)) {
|
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (unavailable) {
|
|
||||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.unavailable)} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Block>
|
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.justifyContentCenter, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
|
||||||
<Heading size='h3'>
|
|
||||||
{intl.formatMessage(messages.follows)}
|
|
||||||
</Heading>
|
|
||||||
</div>
|
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
|
||||||
<ScrollableList
|
|
||||||
scrollKey='following'
|
|
||||||
hasMore={hasMore}
|
|
||||||
onLoadMore={this.handleLoadMore}
|
|
||||||
emptyMessage={intl.formatMessage(messages.empty)}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
accountIds.map((id) => (
|
|
||||||
<AccountContainer key={id} id={id} withNote={false} compact />
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</ScrollableList>
|
|
||||||
</div>
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1 +1 @@
|
||||||
export { default } from './following'
|
export { default } from '../following'
|
|
@ -1,4 +1,4 @@
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator';
|
||||||
|
|
||||||
export default class GenericNotFound extends PureComponent {
|
export default class GenericNotFound extends PureComponent {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export { default } from './generic_not_found'
|
export { default } from '../generic_not_found'
|
|
@ -3,11 +3,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { injectIntl, defineMessages } from 'react-intl'
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { connectGroupStream } from '../../actions/streaming'
|
import { connectGroupStream } from '../actions/streaming'
|
||||||
import { expandGroupTimeline } from '../../actions/timelines'
|
import { expandGroupTimeline } from '../actions/timelines'
|
||||||
import StatusListContainer from '../../containers/status_list_container'
|
import StatusListContainer from '../containers/status_list_container'
|
||||||
// import ColumnSettingsContainer from './containers/column_settings_container'
|
// import ColumnSettingsContainer from './containers/column_settings_container'
|
||||||
import ColumnIndicator from '../../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
tabLatest: { id: 'group.timeline.tab_latest', defaultMessage: 'Latest' },
|
tabLatest: { id: 'group.timeline.tab_latest', defaultMessage: 'Latest' },
|
|
@ -1 +1 @@
|
||||||
export { default } from './group_timeline'
|
export { default } from '../group_timeline'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { fetchGroups } from '../../actions/groups'
|
import { fetchGroups } from '../actions/groups'
|
||||||
import Block from '../../components/block'
|
import Block from '../components/block'
|
||||||
import GroupCollectionItem from '../../components/group_collection_item'
|
import GroupCollectionItem from '../components/group_collection_item'
|
||||||
|
|
||||||
const mapStateToProps = (state, { activeTab }) => ({
|
const mapStateToProps = (state, { activeTab }) => ({
|
||||||
groupIds: state.getIn(['group_lists', activeTab]),
|
groupIds: state.getIn(['group_lists', activeTab]),
|
|
@ -1 +1 @@
|
||||||
export { default } from './groups_collection'
|
export { default } from '../groups_collection'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage } from 'react-intl'
|
||||||
import { isEqual } from 'lodash'
|
import { isEqual } from 'lodash'
|
||||||
import { expandHashtagTimeline, clearTimeline } from '../../actions/timelines'
|
import { expandHashtagTimeline, clearTimeline } from '../actions/timelines'
|
||||||
import { connectHashtagStream } from '../../actions/streaming'
|
import { connectHashtagStream } from '../actions/streaming'
|
||||||
import StatusListContainer from '../../containers/status_list_container'
|
import StatusListContainer from '../containers/status_list_container'
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, props) => ({
|
||||||
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0,
|
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0,
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './hashtag_timeline'
|
|
|
@ -115,10 +115,10 @@ class FrameInteractions extends Component {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3>
|
<h3>
|
||||||
<FormattedMessage id='introduction.interactions.favourite.headline' defaultMessage='Favorite' />
|
<FormattedMessage id='introduction.interactions.favorite.headline' defaultMessage='Favorite' />
|
||||||
</h3>
|
</h3>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage id='introduction.interactions.favourite.text' defaultMessage='You can save a gab for later, and let the author know that you liked it, by favouriting it.' />
|
<FormattedMessage id='introduction.interactions.favorite.text' defaultMessage='You can save a gab for later, and let the author know that you liked it, by favoriting it.' />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||||
import { connectListStream } from '../../actions/streaming';
|
import { connectListStream } from '../actions/streaming';
|
||||||
import { expandListTimeline } from '../../actions/timelines';
|
import { expandListTimeline } from '../actions/timelines';
|
||||||
import { fetchList, deleteList } from '../../actions/lists';
|
import { fetchList, deleteList } from '../actions/lists';
|
||||||
import { openModal } from '../../actions/modal';
|
import { openModal } from '../actions/modal';
|
||||||
import StatusListContainer from '../../containers/status_list_container';
|
import StatusListContainer from '../containers/status_list_container';
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator';
|
||||||
import Button from '../../components/button';
|
import Button from '../components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './list_timeline'
|
|
|
@ -2,10 +2,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { fetchMutes, expandMutes } from '../../actions/mutes';
|
import { fetchMutes, expandMutes } from '../actions/mutes';
|
||||||
import AccountContainer from '../../containers/account_container';
|
import AccountContainer from '../containers/account_container';
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../components/scrollable_list';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
|
heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
|
|
@ -1 +1 @@
|
||||||
export { default } from './mutes'
|
export { default } from '../mutes'
|
|
@ -51,12 +51,12 @@ export default class ColumnSettings extends ImmutablePureComponent {
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} />
|
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-favourite'>
|
<div role='group' aria-labelledby='notifications-favorite'>
|
||||||
<FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Favorites:' />
|
<FormattedMessage id='notifications.column_settings.favorite' defaultMessage='Favorites:' />
|
||||||
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favourite']} onChange={onChange} label={alertStr} />
|
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favorite']} onChange={onChange} label={alertStr} />
|
||||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'favourite']} onChange={this.onPushChange} label={pushStr} />}
|
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'favorite']} onChange={this.onPushChange} label={pushStr} />}
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'favourite']} onChange={onChange} label={showStr} />
|
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'favorite']} onChange={onChange} label={showStr} />
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'favourite']} onChange={onChange} label={soundStr} />
|
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'favorite']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-mention'>
|
<div role='group' aria-labelledby='notifications-mention'>
|
||||||
|
|
|
@ -29,8 +29,8 @@ class Notification extends ImmutablePureComponent {
|
||||||
onMoveUp: PropTypes.func.isRequired,
|
onMoveUp: PropTypes.func.isRequired,
|
||||||
onMoveDown: PropTypes.func.isRequired,
|
onMoveDown: PropTypes.func.isRequired,
|
||||||
onMention: PropTypes.func.isRequired,
|
onMention: PropTypes.func.isRequired,
|
||||||
onFavourite: PropTypes.func.isRequired,
|
onFavorite: PropTypes.func.isRequired,
|
||||||
onReblog: PropTypes.func.isRequired,
|
onRepost: PropTypes.func.isRequired,
|
||||||
onToggleHidden: PropTypes.func.isRequired,
|
onToggleHidden: PropTypes.func.isRequired,
|
||||||
status: ImmutablePropTypes.map,
|
status: ImmutablePropTypes.map,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
@ -72,14 +72,14 @@ class Notification extends ImmutablePureComponent {
|
||||||
onMention(notification.get('account'), this.context.router.history);
|
onMention(notification.get('account'), this.context.router.history);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyFavourite = () => {
|
handleHotkeyFavorite = () => {
|
||||||
const { status } = this.props;
|
const { status } = this.props;
|
||||||
if (status) this.props.onFavourite(status);
|
if (status) this.props.onFavorite(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyBoost = e => {
|
handleHotkeyBoost = e => {
|
||||||
const { status } = this.props;
|
const { status } = this.props;
|
||||||
if (status) this.props.onReblog(status, e);
|
if (status) this.props.onRepost(status, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyToggleHidden = () => {
|
handleHotkeyToggleHidden = () => {
|
||||||
|
@ -90,7 +90,7 @@ class Notification extends ImmutablePureComponent {
|
||||||
getHandlers() {
|
getHandlers() {
|
||||||
return {
|
return {
|
||||||
reply: this.handleMention,
|
reply: this.handleMention,
|
||||||
favourite: this.handleHotkeyFavourite,
|
favorite: this.handleHotkeyFavorite,
|
||||||
boost: this.handleHotkeyBoost,
|
boost: this.handleHotkeyBoost,
|
||||||
mention: this.handleMention,
|
mention: this.handleMention,
|
||||||
open: this.handleOpen,
|
open: this.handleOpen,
|
||||||
|
@ -108,7 +108,7 @@ class Notification extends ImmutablePureComponent {
|
||||||
<HotKeys handlers={this.getHandlers()}>
|
<HotKeys handlers={this.getHandlers()}>
|
||||||
<div className='notification notification--follow focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.follow', defaultMessage: '{name} followed you' }, { name: account.get('acct') }), notification.get('created_at'))}>
|
<div className='notification notification--follow focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.follow', defaultMessage: '{name} followed you' }, { name: account.get('acct') }), notification.get('created_at'))}>
|
||||||
<div className='notification__message'>
|
<div className='notification__message'>
|
||||||
<div className='notification__favourite-icon-wrapper'>
|
<div className='notification__favorite-icon-wrapper'>
|
||||||
<Icon id='user-plus' fixedWidth />
|
<Icon id='user-plus' fixedWidth />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -140,19 +140,19 @@ class Notification extends ImmutablePureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFavourite(notification, link) {
|
renderFavorite(notification, link) {
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={this.getHandlers()}>
|
<HotKeys handlers={this.getHandlers()}>
|
||||||
<div className='notification notification--favourite focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.favourite', defaultMessage: '{name} favorited your status' }, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
<div className='notification notification--favorite focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.favorite', defaultMessage: '{name} favorited your status' }, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
||||||
<div className='notification__message'>
|
<div className='notification__message'>
|
||||||
<div className='notification__favourite-icon-wrapper'>
|
<div className='notification__favorite-icon-wrapper'>
|
||||||
<Icon id='star' className='star-icon' fixedWidth />
|
<Icon id='star' className='star-icon' fixedWidth />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span title={notification.get('created_at')}>
|
<span title={notification.get('created_at')}>
|
||||||
<FormattedMessage id='notification.favourite' defaultMessage='{name} favorited your status' values={{ name: link }} />
|
<FormattedMessage id='notification.favorite' defaultMessage='{name} favorited your status' values={{ name: link }} />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -173,14 +173,14 @@ class Notification extends ImmutablePureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderReblog(notification, link) {
|
renderRepost(notification, link) {
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={this.getHandlers()}>
|
<HotKeys handlers={this.getHandlers()}>
|
||||||
<div className='notification notification--reblog focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.reblog', defaultMessage: '{name} reposted your status' }, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
<div className='notification notification--reblog focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.reblog', defaultMessage: '{name} reposted your status' }, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
||||||
<div className='notification__message'>
|
<div className='notification__message'>
|
||||||
<div className='notification__favourite-icon-wrapper'>
|
<div className='notification__favorite-icon-wrapper'>
|
||||||
<Icon id='retweet' fixedWidth />
|
<Icon id='retweet' fixedWidth />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ class Notification extends ImmutablePureComponent {
|
||||||
<HotKeys handlers={this.getHandlers()}>
|
<HotKeys handlers={this.getHandlers()}>
|
||||||
<div className='notification notification--poll focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }), notification.get('created_at'))}>
|
<div className='notification notification--poll focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }), notification.get('created_at'))}>
|
||||||
<div className='notification__message'>
|
<div className='notification__message'>
|
||||||
<div className='notification__favourite-icon-wrapper'>
|
<div className='notification__favorite-icon-wrapper'>
|
||||||
<Icon id='tasks' fixedWidth />
|
<Icon id='tasks' fixedWidth />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -261,9 +261,9 @@ class Notification extends ImmutablePureComponent {
|
||||||
// case 'mention':
|
// case 'mention':
|
||||||
// return this.renderMention(notification);
|
// return this.renderMention(notification);
|
||||||
case 'favourite':
|
case 'favourite':
|
||||||
return this.renderFavourite(notification, link);
|
return this.renderFavorite(notification, link);
|
||||||
// case 'reblog':
|
// case 'reblog':
|
||||||
// return this.renderReblog(notification, link);
|
// return this.renderRepost(notification, link);
|
||||||
// case 'poll':
|
// case 'poll':
|
||||||
// return this.renderPoll(notification);
|
// return this.renderPoll(notification);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
.notification {
|
|
||||||
|
|
||||||
|
|
||||||
&--favourite {
|
|
||||||
.status.status-direct {
|
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
.icon-button.disabled {
|
|
||||||
color: lighten($action-button-color, 13%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--follow {}
|
|
||||||
|
|
||||||
&--reblog {}
|
|
||||||
|
|
||||||
&--poll {}
|
|
||||||
|
|
||||||
&__message {
|
|
||||||
margin: 0 10px 0 68px;
|
|
||||||
padding: 8px 0 0;
|
|
||||||
cursor: default;
|
|
||||||
color: $gab-secondary-text;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
@include text-sizing(15px, 400, 22px);
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
color: $highlight-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
>span {
|
|
||||||
display: inline;
|
|
||||||
|
|
||||||
@include text-overflow(nowrap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__display-name {
|
|
||||||
color: inherit;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $primary-text-color;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__favourite-icon-wrapper {
|
|
||||||
left: -26px;
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
.star-icon {
|
|
||||||
color: $gold-star;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' },
|
mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' },
|
||||||
favourites: { id: 'notifications.filter.favourites', defaultMessage: 'Favorites' },
|
favorites: { id: 'notifications.filter.favorites', defaultMessage: 'Favorites' },
|
||||||
boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Reposts' },
|
boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Reposts' },
|
||||||
polls: { id: 'notifications.filter.polls', defaultMessage: 'Poll results' },
|
polls: { id: 'notifications.filter.polls', defaultMessage: 'Poll results' },
|
||||||
follows: { id: 'notifications.filter.follows', defaultMessage: 'Follows' },
|
follows: { id: 'notifications.filter.follows', defaultMessage: 'Follows' },
|
||||||
|
@ -65,9 +65,9 @@ class NotificationFilterBar extends PureComponent {
|
||||||
icon: 'at',
|
icon: 'at',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
className: selectedFilter === 'favourite' ? 'active' : '',
|
className: selectedFilter === 'favorite' ? 'active' : '',
|
||||||
onClick: this.onClick('favourite'),
|
onClick: this.onClick('favorite'),
|
||||||
title: intl.formatMessage(messages.favourites),
|
title: intl.formatMessage(messages.favorites),
|
||||||
icon: 'star',
|
icon: 'star',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { openModal } from '../../../actions/modal'
|
||||||
import { mentionCompose } from '../../../actions/compose'
|
import { mentionCompose } from '../../../actions/compose'
|
||||||
import {
|
import {
|
||||||
reblog,
|
reblog,
|
||||||
favourite,
|
favorite,
|
||||||
unreblog,
|
unreblog,
|
||||||
unfavourite,
|
unfavorite,
|
||||||
} from '../../../actions/interactions'
|
} from '../../../actions/interactions'
|
||||||
import {
|
import {
|
||||||
hideStatus,
|
hideStatus,
|
||||||
|
@ -38,27 +38,27 @@ const mapDispatchToProps = dispatch => ({
|
||||||
dispatch(mentionCompose(account, router))
|
dispatch(mentionCompose(account, router))
|
||||||
},
|
},
|
||||||
|
|
||||||
onModalReblog (status) {
|
onModalRepost (status) {
|
||||||
dispatch(reblog(status))
|
dispatch(repost(status))
|
||||||
},
|
},
|
||||||
|
|
||||||
onReblog (status, e) {
|
onRepost (status, e) {
|
||||||
if (status.get('reblogged')) {
|
if (status.get('reblogged')) {
|
||||||
dispatch(unreblog(status))
|
dispatch(unrepost(status))
|
||||||
} else {
|
} else {
|
||||||
if (e.shiftKey || !boostModal) {
|
if (e.shiftKey || !boostModal) {
|
||||||
this.onModalReblog(status)
|
this.onModalRepost(status)
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog }))
|
dispatch(openModal('BOOST', { status, onRepost: this.onModalRepost }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onFavourite (status) {
|
onFavorite (status) {
|
||||||
if (status.get('favourited')) {
|
if (status.get('favorited')) {
|
||||||
dispatch(unfavourite(status))
|
dispatch(unfavorite(status))
|
||||||
} else {
|
} else {
|
||||||
dispatch(favourite(status))
|
dispatch(favorite(status))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export { default } from './reblogs'
|
export { default } from '../reblogs'
|
|
@ -1,12 +1,12 @@
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { fetchReblogs } from '../../actions/interactions';
|
import { fetchReposts } from '../actions/interactions';
|
||||||
import { fetchStatus } from '../../actions/statuses';
|
import { fetchStatus } from '../actions/statuses';
|
||||||
import { makeGetStatus } from '../../selectors';
|
import { makeGetStatus } from '../selectors';
|
||||||
import AccountContainer from '../../containers/account_container';
|
import AccountContainer from '../containers/account_container';
|
||||||
import ColumnIndicator from '../../components/column_indicator';
|
import ColumnIndicator from '../components/column_indicator';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../components/scrollable_list';
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const getStatus = makeGetStatus();
|
const getStatus = makeGetStatus();
|
||||||
|
@ -23,7 +23,7 @@ const mapStateToProps = (state, props) => {
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
class Reblogs extends ImmutablePureComponent {
|
class Reposts extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
params: PropTypes.object.isRequired,
|
params: PropTypes.object.isRequired,
|
||||||
|
@ -33,13 +33,13 @@ class Reblogs extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
this.props.dispatch(fetchReblogs(this.props.params.statusId));
|
this.props.dispatch(fetchReposts(this.props.params.statusId));
|
||||||
this.props.dispatch(fetchStatus(this.props.params.statusId));
|
this.props.dispatch(fetchStatus(this.props.params.statusId));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||||
this.props.dispatch(fetchReblogs(nextProps.params.statusId));
|
this.props.dispatch(fetchReposts(nextProps.params.statusId));
|
||||||
this.props.dispatch(fetchStatus(nextProps.params.statusId));
|
this.props.dispatch(fetchStatus(nextProps.params.statusId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,19 +48,21 @@ class Reblogs extends ImmutablePureComponent {
|
||||||
const { accountIds, status } = this.props;
|
const { accountIds, status } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (<ColumnIndicator type='loading' />);
|
return <ColumnIndicator type='loading' />
|
||||||
} else if (!status) {
|
} else if (!status) {
|
||||||
return (<ColumnIndicator type='missing' />);
|
return <ColumnIndicator type='missing' />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reblogs'
|
scrollKey='reposts'
|
||||||
emptyMessage={<FormattedMessage id='status.reblogs.empty' defaultMessage='No one has reposted this gab yet. When someone does, they will show up here.' />}
|
emptyMessage={<FormattedMessage id='status.reblogs.empty' defaultMessage='No one has reposted this gab yet. When someone does, they will show up here.' />}
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{
|
||||||
|
accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withNote={false} />
|
<AccountContainer key={id} id={id} withNote={false} />
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// import SearchContainer from '../compose/containers/search_container';
|
// import SearchContainer from '../compose/containers/search_container';
|
||||||
import SearchResultsContainer from '../compose/containers/search_results_container';
|
import SearchResultsContainer from './compose/containers/search_results_container';
|
||||||
|
|
||||||
export default class Search extends PureComponent {
|
export default class Search extends PureComponent {
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
|
||||||
value: state.getIn(['search', 'value']),
|
|
||||||
submitted: state.getIn(['search', 'submitted']),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default
|
|
||||||
@connect(mapStateToProps)
|
|
||||||
class Header extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
value: PropTypes.string,
|
|
||||||
submitted: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
submittedValue: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
|
||||||
if (nextProps.submitted) {
|
|
||||||
const submittedValue = nextProps.value;
|
|
||||||
this.setState({submittedValue})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { submittedValue } = this.state;
|
|
||||||
|
|
||||||
if (!submittedValue) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='search-header'>
|
|
||||||
<div className='search-header__text-container'>
|
|
||||||
<h1 className='search-header__title-text'>
|
|
||||||
{submittedValue}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div className='search-header__type-filters'>
|
|
||||||
<div className='search-header__type-filters-tabs'>
|
|
||||||
{ /* <SectionHeadlineBar
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
to: '/search',
|
|
||||||
title: <FormattedMessage id='search_results.top' defaultMessage='Top' />
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
/> */ }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
.search-header {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&__text-container {
|
|
||||||
display: none;
|
|
||||||
padding: 25px 0;
|
|
||||||
background-color: lighten($ui-base-color, 6%);
|
|
||||||
|
|
||||||
@media (min-width:895px) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title-text {
|
|
||||||
color: $primary-text-color;
|
|
||||||
padding-left: 20px;
|
|
||||||
max-width: 1200px;
|
|
||||||
|
|
||||||
@include text-sizing(27px, bold, 32px);
|
|
||||||
@include text-overflow(nowrap);
|
|
||||||
@include margin-center;
|
|
||||||
|
|
||||||
@media (min-width:895px) and (max-width:1190px) {
|
|
||||||
max-width: 900px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__type-filters-tabs {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 1200px;
|
|
||||||
|
|
||||||
@include margin-center;
|
|
||||||
|
|
||||||
@media screen and (max-width:895px) {
|
|
||||||
max-width: 580px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width:895px) and (max-width:1190px) {
|
|
||||||
max-width: 900px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './header'
|
|
|
@ -1 +1 @@
|
||||||
export { default } from './search'
|
export { default } from '../search'
|
|
@ -6,9 +6,9 @@ import {
|
||||||
} from '../../../actions/compose';
|
} from '../../../actions/compose';
|
||||||
import {
|
import {
|
||||||
reblog,
|
reblog,
|
||||||
favourite,
|
favorite,
|
||||||
unreblog,
|
unreblog,
|
||||||
unfavourite,
|
unfavorite,
|
||||||
pin,
|
pin,
|
||||||
unpin,
|
unpin,
|
||||||
} from '../../../actions/interactions';
|
} from '../../../actions/interactions';
|
||||||
|
@ -65,27 +65,27 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onModalReblog (status) {
|
onModalRepost (status) {
|
||||||
dispatch(reblog(status));
|
dispatch(repost(status));
|
||||||
},
|
},
|
||||||
|
|
||||||
onReblog (status, e) {
|
onRepost (status, e) {
|
||||||
if (status.get('reblogged')) {
|
if (status.get('reblogged')) {
|
||||||
dispatch(unreblog(status));
|
dispatch(unrepost(status));
|
||||||
} else {
|
} else {
|
||||||
if (e.shiftKey || !boostModal) {
|
if (e.shiftKey || !boostModal) {
|
||||||
this.onModalReblog(status);
|
this.onModalRepost(status);
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog }));
|
dispatch(openModal('BOOST', { status, onRepost: this.onModalRepost }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onFavourite (status) {
|
onFavorite (status) {
|
||||||
if (status.get('favourited')) {
|
if (status.get('favorited')) {
|
||||||
dispatch(unfavourite(status));
|
dispatch(unfavorite(status));
|
||||||
} else {
|
} else {
|
||||||
dispatch(favourite(status));
|
dispatch(favorite(status));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
import { fetchStatus } from '../../actions/statuses';
|
import { fetchStatus } from '../../actions/statuses';
|
||||||
import {
|
import {
|
||||||
favourite,
|
favorite,
|
||||||
unfavourite,
|
unfavorite,
|
||||||
reblog,
|
reblog,
|
||||||
unreblog,
|
unreblog,
|
||||||
pin,
|
pin,
|
||||||
|
@ -155,11 +155,11 @@ class Status extends ImmutablePureComponent {
|
||||||
this.setState({ showMedia: !this.state.showMedia });
|
this.setState({ showMedia: !this.state.showMedia });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFavouriteClick = (status) => {
|
handleFavoriteClick = (status) => {
|
||||||
if (status.get('favourited')) {
|
if (status.get('favourited')) {
|
||||||
this.props.dispatch(unfavourite(status));
|
this.props.dispatch(unfavorite(status));
|
||||||
} else {
|
} else {
|
||||||
this.props.dispatch(favourite(status));
|
this.props.dispatch(favorite(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,18 +184,18 @@ class Status extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleModalReblog = (status) => {
|
handleModalRepost = (status) => {
|
||||||
this.props.dispatch(reblog(status));
|
this.props.dispatch(repost(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReblogClick = (status, e) => {
|
handleRepostClick = (status, e) => {
|
||||||
if (status.get('reblogged')) {
|
if (status.get('reblogged')) {
|
||||||
this.props.dispatch(unreblog(status));
|
this.props.dispatch(unrepost(status));
|
||||||
} else {
|
} else {
|
||||||
if ((e && e.shiftKey) || !boostModal) {
|
if ((e && e.shiftKey) || !boostModal) {
|
||||||
this.handleModalReblog(status);
|
this.handleModalRepost(status);
|
||||||
} else {
|
} else {
|
||||||
this.props.dispatch(openModal('BOOST', { status, onReblog: this.handleModalReblog }));
|
this.props.dispatch(openModal('BOOST', { status, onRepost: this.handleModalRepost }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,12 +298,12 @@ class Status extends ImmutablePureComponent {
|
||||||
this.handleReplyClick(this.props.status);
|
this.handleReplyClick(this.props.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyFavourite = () => {
|
handleHotkeyFavorite = () => {
|
||||||
this.handleFavouriteClick(this.props.status);
|
this.handleFavoriteClick(this.props.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyBoost = () => {
|
handleHotkeyBoost = () => {
|
||||||
this.handleReblogClick(this.props.status);
|
this.handleRepostClick(this.props.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyMention = e => {
|
handleHotkeyMention = e => {
|
||||||
|
@ -432,7 +432,7 @@ class Status extends ImmutablePureComponent {
|
||||||
moveUp: this.handleHotkeyMoveUp,
|
moveUp: this.handleHotkeyMoveUp,
|
||||||
moveDown: this.handleHotkeyMoveDown,
|
moveDown: this.handleHotkeyMoveDown,
|
||||||
reply: this.handleHotkeyReply,
|
reply: this.handleHotkeyReply,
|
||||||
favourite: this.handleHotkeyFavourite,
|
favorite: this.handleHotkeyFavorite,
|
||||||
boost: this.handleHotkeyBoost,
|
boost: this.handleHotkeyBoost,
|
||||||
mention: this.handleHotkeyMention,
|
mention: this.handleHotkeyMention,
|
||||||
openProfile: this.handleHotkeyOpenProfile,
|
openProfile: this.handleHotkeyOpenProfile,
|
||||||
|
@ -481,11 +481,11 @@ class Status extends ImmutablePureComponent {
|
||||||
showThread
|
showThread
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionBar
|
{/*<ActionBar
|
||||||
status={status}
|
status={status}
|
||||||
onReply={this.handleReplyClick}
|
onReply={this.handleReplyClick}
|
||||||
onFavourite={this.handleFavouriteClick}
|
onFavorite={this.handleFavoriteClick}
|
||||||
onReblog={this.handleReblogClick}
|
onRepost={this.handleRepostClick}
|
||||||
onDelete={this.handleDeleteClick}
|
onDelete={this.handleDeleteClick}
|
||||||
onDirect={this.handleDirectClick}
|
onDirect={this.handleDirectClick}
|
||||||
onMention={this.handleMentionClick}
|
onMention={this.handleMentionClick}
|
||||||
|
@ -495,7 +495,7 @@ class Status extends ImmutablePureComponent {
|
||||||
onReport={this.handleReport}
|
onReport={this.handleReport}
|
||||||
onPin={this.handlePin}
|
onPin={this.handlePin}
|
||||||
onEmbed={this.handleEmbed}
|
onEmbed={this.handleEmbed}
|
||||||
/>
|
/>*/}
|
||||||
</div>
|
</div>
|
||||||
</HotKeys>
|
</HotKeys>
|
||||||
|
|
||||||
|
|
|
@ -182,8 +182,10 @@ class SwitchingArea extends PureComponent {
|
||||||
<Redirect from='/@:username' to='/:username' exact />
|
<Redirect from='/@:username' to='/:username' exact />
|
||||||
<WrappedRoute path='/:username' publicRoute exact page={ProfilePage} component={AccountTimeline} content={children} />
|
<WrappedRoute path='/:username' publicRoute exact page={ProfilePage} component={AccountTimeline} content={children} />
|
||||||
|
|
||||||
|
{ /*
|
||||||
<Redirect from='/@:username/comments' to='/:username/comments' />
|
<Redirect from='/@:username/comments' to='/:username/comments' />
|
||||||
<WrappedRoute path='/:username/comments' page={ProfilePage} component={AccountTimeline} content={children} componentParams={{ commentsOnly: true }} />
|
<WrappedRoute path='/:username/comments' page={ProfilePage} component={AccountTimeline} content={children} componentParams={{ commentsOnly: true }} />
|
||||||
|
*/ }
|
||||||
|
|
||||||
<Redirect from='/@:username/followers' to='/:username/followers' />
|
<Redirect from='/@:username/followers' to='/:username/followers' />
|
||||||
<WrappedRoute path='/:username/followers' page={ProfilePage} component={Followers} content={children} />
|
<WrappedRoute path='/:username/followers' page={ProfilePage} component={Followers} content={children} />
|
||||||
|
@ -191,11 +193,8 @@ class SwitchingArea extends PureComponent {
|
||||||
<Redirect from='/@:username/following' to='/:username/following' />
|
<Redirect from='/@:username/following' to='/:username/following' />
|
||||||
<WrappedRoute path='/:username/following' page={ProfilePage} component={Following} content={children} />
|
<WrappedRoute path='/:username/following' page={ProfilePage} component={Following} content={children} />
|
||||||
|
|
||||||
<Redirect from='/@:username/photos' to='/:username/photos' />
|
<Redirect from='/@:username/media' to='/:username/media' />
|
||||||
<WrappedRoute path='/:username/photos' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ mediaType: 'photo' }} />
|
<WrappedRoute path='/:username/media' page={ProfilePage} component={AccountGallery} content={children} />
|
||||||
|
|
||||||
<Redirect from='/@:username/videos' to='/:username/videos' />
|
|
||||||
<WrappedRoute path='/:username/videos' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ mediaType: 'video' }} />
|
|
||||||
|
|
||||||
<Redirect from='/@:username/favorites' to='/:username/favorites' />
|
<Redirect from='/@:username/favorites' to='/:username/favorites' />
|
||||||
<WrappedRoute path='/:username/favorites' page={ProfilePage} component={FavoritedStatuses} content={children} />
|
<WrappedRoute path='/:username/favorites' page={ProfilePage} component={FavoritedStatuses} content={children} />
|
||||||
|
@ -203,8 +202,8 @@ class SwitchingArea extends PureComponent {
|
||||||
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
||||||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} />
|
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} />
|
||||||
|
|
||||||
<Redirect from='/@:username/posts/:statusId/reblogs' to='/:username/posts/:statusId/reblogs' />
|
<Redirect from='/@:username/posts/:statusId/reposts' to='/:username/posts/:statusId/reposts' />
|
||||||
<WrappedRoute path='/:username/posts/:statusId/reblogs' page={BasicPage} component={Reblogs} content={children} componentParams={{ title: 'Reblogs' }} />
|
<WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={Reposts} content={children} componentParams={{ title: 'Reposts' }} />
|
||||||
|
|
||||||
<Redirect from='/@:username/posts/:statusId/favorites' to='/:username/posts/:statusId/favorites' />
|
<Redirect from='/@:username/posts/:statusId/favorites' to='/:username/posts/:statusId/favorites' />
|
||||||
<WrappedRoute path='/:username/posts/:statusId/favorites' page={BasicPage} component={Favorites} content={children} componentParams={{ title: 'Favorites' }} />
|
<WrappedRoute path='/:username/posts/:statusId/favorites' page={BasicPage} component={Favorites} content={children} componentParams={{ title: 'Favorites' }} />
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
.ui {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 0 100px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 630px) and (max-height: 400px) {
|
|
||||||
.is-composing {
|
|
||||||
|
|
||||||
.tabs-bar,
|
|
||||||
.search {
|
|
||||||
margin-top: -50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-bar {
|
|
||||||
padding-bottom: 0;
|
|
||||||
|
|
||||||
&>a:first-child {
|
|
||||||
margin: -100px 10px 0 -50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__profile {
|
|
||||||
padding-top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__profile-edit {
|
|
||||||
position: absolute;
|
|
||||||
margin-top: -60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__actions {
|
|
||||||
.icon-button.close {
|
|
||||||
pointer-events: auto;
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1.0, 1.0) translate(0, 0);
|
|
||||||
bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.compose__action-bar .icon-button {
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.0, 1.0) translate(100%, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -114,8 +114,8 @@ export function Notifications() {
|
||||||
return import(/* webpackChunkName: "features/notifications" */'../../notifications')
|
return import(/* webpackChunkName: "features/notifications" */'../../notifications')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Reblogs() {
|
export function Reposts() {
|
||||||
return import(/* webpackChunkName: "features/reblogs" */'../../reblogs')
|
return import(/* webpackChunkName: "features/reblogs" */'../../reposts')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ReportModal() {
|
export function ReportModal() {
|
||||||
|
|
|
@ -29,12 +29,8 @@ export default class ProfileLayout extends ImmutablePureComponent {
|
||||||
title: 'Comments',
|
title: 'Comments',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: `/${account.get('acct')}/photos`,
|
to: `/${account.get('acct')}/media`,
|
||||||
title: 'Photos',
|
title: 'Media',
|
||||||
},
|
|
||||||
{
|
|
||||||
to: `/${account.get('acct')}/videos`,
|
|
||||||
title: 'Videos',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '',
|
to: '',
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Gorffen tiwtorial!",
|
"introduction.interactions.action": "Gorffen tiwtorial!",
|
||||||
"introduction.interactions.favourite.headline": "Ffefryn",
|
"introduction.interactions.favourite.headline": "Ffefryn",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Hwb",
|
"introduction.interactions.reblog.headline": "Hwb",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Ateb",
|
"introduction.interactions.reply.headline": "Ateb",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Slut tutorial!",
|
"introduction.interactions.action": "Slut tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favorisere",
|
"introduction.interactions.favourite.headline": "Favorisere",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Svar",
|
"introduction.interactions.reply.headline": "Svar",
|
||||||
|
|
|
@ -1507,7 +1507,7 @@
|
||||||
"id": "introduction.interactions.favourite.headline"
|
"id": "introduction.interactions.favourite.headline"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"defaultMessage": "You can save a gab for later, and let the author know that you liked it, by favouriting it.",
|
"defaultMessage": "You can save a gab for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"id": "introduction.interactions.favourite.text"
|
"id": "introduction.interactions.favourite.text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,7 +170,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favorite",
|
"introduction.interactions.favourite.headline": "Favorite",
|
||||||
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Boost",
|
"introduction.interactions.reblog.headline": "Boost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish toot-orial!",
|
"introduction.interactions.action": "Finish toot-orial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a gab for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's gabs with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
|
||||||
"introduction.interactions.action": "Finish tutorial!",
|
"introduction.interactions.action": "Finish tutorial!",
|
||||||
"introduction.interactions.favourite.headline": "Favourite",
|
"introduction.interactions.favourite.headline": "Favourite",
|
||||||
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
|
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favoriting it.",
|
||||||
"introduction.interactions.reblog.headline": "Repost",
|
"introduction.interactions.reblog.headline": "Repost",
|
||||||
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by reposting them.",
|
||||||
"introduction.interactions.reply.headline": "Reply",
|
"introduction.interactions.reply.headline": "Reply",
|
||||||
|
|
|
@ -3,25 +3,30 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { fetchAccountByUsername } from '../actions/accounts'
|
import { fetchAccountByUsername } from '../actions/accounts'
|
||||||
import { makeGetAccount } from '../selectors'
|
import { makeGetAccount } from '../selectors'
|
||||||
|
import { me } from '../initial_state'
|
||||||
import LinkFooter from '../components/link_footer'
|
import LinkFooter from '../components/link_footer'
|
||||||
import ProfileStatsPanel from '../components/panel/profile_stats_panel'
|
import ProfileStatsPanel from '../components/panel/profile_stats_panel'
|
||||||
import ProfileInfoPanel from '../components/panel/profile_info_panel'
|
import ProfileInfoPanel from '../components/panel/profile_info_panel'
|
||||||
import MediaGalleryPanel from '../components/panel/media_gallery_panel'
|
import MediaGalleryPanel from '../components/panel/media_gallery_panel'
|
||||||
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
import ProfileLayout from '../layouts/profile_layout'
|
import ProfileLayout from '../layouts/profile_layout'
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username }, withReplies = false }) => {
|
const mapStateToProps = (state, { params: { username } }) => {
|
||||||
const accounts = state.getIn(['accounts'])
|
const accounts = state.getIn(['accounts'])
|
||||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase())
|
const account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
||||||
|
|
||||||
let account = null
|
const accountId = !!account ? account.get('id') : -1
|
||||||
if (!accountFetchError) {
|
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
||||||
account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
|
||||||
}
|
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
|
||||||
|
|
||||||
|
const unavailable = (me === accountId) ? false : (isBlocked || (isLocked && !isFollowing))
|
||||||
|
|
||||||
const getAccount = makeGetAccount()
|
const getAccount = makeGetAccount()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account: account ? getAccount(state, account.get('id')) : null,
|
unavailable,
|
||||||
|
account: accountId !== -1 ? getAccount(state, accountId) : null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,10 +34,11 @@ export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
class ProfilePage extends ImmutablePureComponent {
|
class ProfilePage extends ImmutablePureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
params: PropTypes.object.isRequired,
|
params: PropTypes.object.isRequired,
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
children: PropTypes.node,
|
unavailable: PropTypes.bool.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
@ -41,7 +47,11 @@ class ProfilePage extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account } = this.props
|
const {
|
||||||
|
account,
|
||||||
|
children,
|
||||||
|
unavailable
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProfileLayout
|
<ProfileLayout
|
||||||
|
@ -55,7 +65,15 @@ class ProfilePage extends ImmutablePureComponent {
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{ this.props.children }
|
{
|
||||||
|
!account && <ColumnIndicator type='loading' />
|
||||||
|
}
|
||||||
|
{
|
||||||
|
!!account && !unavailable &&
|
||||||
|
React.cloneElement(children, {
|
||||||
|
account,
|
||||||
|
})
|
||||||
|
}
|
||||||
</ProfileLayout>
|
</ProfileLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
FOLLOW_REQUEST_REJECT_SUCCESS,
|
FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||||
} from '../actions/accounts';
|
} from '../actions/accounts';
|
||||||
import {
|
import {
|
||||||
REBLOGS_FETCH_SUCCESS,
|
REPOSTS_FETCH_SUCCESS,
|
||||||
} from '../actions/interactions';
|
} from '../actions/interactions';
|
||||||
import {
|
import {
|
||||||
BLOCKS_FETCH_SUCCESS,
|
BLOCKS_FETCH_SUCCESS,
|
||||||
|
@ -63,7 +63,7 @@ export default function userLists(state = initialState, action) {
|
||||||
return normalizeList(state, 'following', action.id, action.accounts, action.next);
|
return normalizeList(state, 'following', action.id, action.accounts, action.next);
|
||||||
case FOLLOWING_EXPAND_SUCCESS:
|
case FOLLOWING_EXPAND_SUCCESS:
|
||||||
return appendToList(state, 'following', action.id, action.accounts, action.next);
|
return appendToList(state, 'following', action.id, action.accounts, action.next);
|
||||||
case REBLOGS_FETCH_SUCCESS:
|
case REPOSTS_FETCH_SUCCESS:
|
||||||
return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
||||||
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
||||||
return state.setIn(['follow_requests', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next);
|
return state.setIn(['follow_requests', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next);
|
||||||
|
|
|
@ -103,7 +103,7 @@ const handlePush = (event) => {
|
||||||
options.image = undefined;
|
options.image = undefined;
|
||||||
options.actions = [actionExpand(preferred_locale)];
|
options.actions = [actionExpand(preferred_locale)];
|
||||||
} else if (notification.type === 'mention') {
|
} else if (notification.type === 'mention') {
|
||||||
options.actions = [actionReblog(preferred_locale), actionFavourite(preferred_locale)];
|
options.actions = [actionRepost(preferred_locale), actionFavorite(preferred_locale)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return notify(options);
|
return notify(options);
|
||||||
|
@ -127,13 +127,13 @@ const actionExpand = preferred_locale => ({
|
||||||
title: formatMessage('status.show_more', preferred_locale),
|
title: formatMessage('status.show_more', preferred_locale),
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionReblog = preferred_locale => ({
|
const actionRepost = preferred_locale => ({
|
||||||
action: 'reblog',
|
action: 'reblog',
|
||||||
icon: '/web-push-icon_reblog.png',
|
icon: '/web-push-icon_reblog.png',
|
||||||
title: formatMessage('status.reblog', preferred_locale),
|
title: formatMessage('status.reblog', preferred_locale),
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionFavourite = preferred_locale => ({
|
const actionFavorite = preferred_locale => ({
|
||||||
action: 'favourite',
|
action: 'favourite',
|
||||||
icon: '/web-push-icon_favourite.png',
|
icon: '/web-push-icon_favourite.png',
|
||||||
title: formatMessage('status.favourite', preferred_locale),
|
title: formatMessage('status.favourite', preferred_locale),
|
||||||
|
@ -151,7 +151,7 @@ const expandNotification = notification => {
|
||||||
|
|
||||||
newNotification.body = newNotification.data.hiddenBody;
|
newNotification.body = newNotification.data.hiddenBody;
|
||||||
newNotification.image = newNotification.data.hiddenImage;
|
newNotification.image = newNotification.data.hiddenImage;
|
||||||
newNotification.actions = [actionReblog(notification.data.preferred_locale), actionFavourite(notification.data.preferred_locale)];
|
newNotification.actions = [actionRepost(notification.data.preferred_locale), actionFavorite(notification.data.preferred_locale)];
|
||||||
|
|
||||||
return self.registration.showNotification(newNotification.title, newNotification);
|
return self.registration.showNotification(newNotification.title, newNotification);
|
||||||
};
|
};
|
||||||
|
|
|
@ -409,6 +409,10 @@ body {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heightMin50VH {
|
||||||
|
min-height: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
.height100VH {
|
.height100VH {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
@ -437,6 +441,10 @@ body {
|
||||||
height: 122px;
|
height: 122px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.height158PX {
|
||||||
|
height: 158px;
|
||||||
|
}
|
||||||
|
|
||||||
.height220PX {
|
.height220PX {
|
||||||
height: 220px;
|
height: 220px;
|
||||||
}
|
}
|
||||||
|
@ -469,18 +477,22 @@ body {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.width100PC {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.width72PX {
|
.width72PX {
|
||||||
width: 72px;
|
width: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.width100PC {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.width50PC {
|
.width50PC {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.width25PC {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
.maxWidth100PC {
|
.maxWidth100PC {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -743,6 +755,10 @@ body {
|
||||||
padding-top: 56.25%;
|
padding-top: 56.25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paddingTop25PC {
|
||||||
|
padding-top: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
.paddingTop10PX {
|
.paddingTop10PX {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue