Split boosts/repeats off to their own tab and add to the API.
parent
ed9c8f67c4
commit
1ab60fea48
|
@ -59,14 +59,20 @@ class AccountsController < ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def show_pinned_statuses?
|
def show_pinned_statuses?
|
||||||
[replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
|
[reblogs_requested?, replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_statuses
|
def filtered_statuses
|
||||||
default_statuses.tap do |statuses|
|
if reblogs_requested?
|
||||||
statuses.merge!(hashtag_scope) if tag_requested?
|
default_statuses.reblogs
|
||||||
statuses.merge!(only_media_scope) if media_requested?
|
elsif replies_requested?
|
||||||
statuses.merge!(no_replies_scope) unless @account.replies && replies_requested?
|
@account.replies ? default_statuses : default_statuses.without_replies
|
||||||
|
elsif media_requested?
|
||||||
|
default_statuses.where(id: account_media_status_ids)
|
||||||
|
elsif tag_requested?
|
||||||
|
default_statuses.hashtag_scope
|
||||||
|
else
|
||||||
|
default_statuses.without_replies.without_reblogs
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -74,18 +80,6 @@ class AccountsController < ApplicationController
|
||||||
@account.statuses.not_local_only.where(visibility: [:public, :unlisted])
|
@account.statuses.not_local_only.where(visibility: [:public, :unlisted])
|
||||||
end
|
end
|
||||||
|
|
||||||
def only_media_scope
|
|
||||||
Status.where(id: account_media_status_ids)
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_media_status_ids
|
|
||||||
@account.media_attachments.attached.reorder(nil).select(:status_id).distinct
|
|
||||||
end
|
|
||||||
|
|
||||||
def no_replies_scope
|
|
||||||
Status.without_replies
|
|
||||||
end
|
|
||||||
|
|
||||||
def hashtag_scope
|
def hashtag_scope
|
||||||
tag = Tag.find_normalized(params[:tag])
|
tag = Tag.find_normalized(params[:tag])
|
||||||
|
|
||||||
|
@ -115,6 +109,8 @@ class AccountsController < ApplicationController
|
||||||
short_account_media_url(@account, max_id: max_id, min_id: min_id)
|
short_account_media_url(@account, max_id: max_id, min_id: min_id)
|
||||||
elsif replies_requested?
|
elsif replies_requested?
|
||||||
short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
|
short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
|
||||||
|
elsif reblogs_requested?
|
||||||
|
short_account_reblogs_url(@account, max_id: max_id, min_id: min_id)
|
||||||
else
|
else
|
||||||
short_account_url(@account, max_id: max_id, min_id: min_id)
|
short_account_url(@account, max_id: max_id, min_id: min_id)
|
||||||
end
|
end
|
||||||
|
@ -128,6 +124,10 @@ class AccountsController < ApplicationController
|
||||||
request.path.ends_with?('/with_replies')
|
request.path.ends_with?('/with_replies')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reblogs_requested?
|
||||||
|
request.path.ends_with?('/reblogs')
|
||||||
|
end
|
||||||
|
|
||||||
def tag_requested?
|
def tag_requested?
|
||||||
request.path.ends_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
|
request.path.ends_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,14 +28,14 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
||||||
|
|
||||||
def account_statuses
|
def account_statuses
|
||||||
statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses
|
statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses
|
||||||
statuses = statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
|
|
||||||
|
|
||||||
statuses.merge!(only_media_scope) if truthy_param?(:only_media)
|
statuses = statuses.without_replies if !@account.replies || truthy_param?(:exclude_replies)
|
||||||
statuses.merge!(no_replies_scope) if truthy_param?(:exclude_replies)
|
statuses = statuses.without_reblogs if truthy_param?(:exclude_reblogs)
|
||||||
statuses.merge!(no_reblogs_scope) if truthy_param?(:exclude_reblogs)
|
statuses = statuses.reblogs if truthy_param?(:reblogs) && !truthy_param?(:exclude_reblogs)
|
||||||
statuses.merge!(hashtag_scope) if params[:tagged].present?
|
statuses = statuses.where(id: account_media_status_ids) if truthy_param?(:only_media)
|
||||||
|
statuses = statuses.hashtag_scope if params[:tagged].present?
|
||||||
|
|
||||||
statuses
|
statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||||
end
|
end
|
||||||
|
|
||||||
def permitted_account_statuses
|
def permitted_account_statuses
|
||||||
|
|
|
@ -95,7 +95,7 @@ export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => ex
|
||||||
export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done);
|
export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { 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 expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
|
||||||
export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
|
export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, 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, reblogs } = {}) => expandTimeline(`account:${accountId}${reblogs ? ':reblogs' : withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, reblogs: reblogs, 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: 40 });
|
||||||
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);
|
||||||
|
|
|
@ -120,6 +120,7 @@ export default class Header extends ImmutablePureComponent {
|
||||||
<div className='account__section-headline'>
|
<div className='account__section-headline'>
|
||||||
<NavLink exact to={`/accounts/${account.get('id')}`}><FormattedMessage id='account.posts' defaultMessage='Toots' /></NavLink>
|
<NavLink exact to={`/accounts/${account.get('id')}`}><FormattedMessage id='account.posts' defaultMessage='Toots' /></NavLink>
|
||||||
<NavLink exact to={`/accounts/${account.get('id')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Toots with replies' /></NavLink>
|
<NavLink exact to={`/accounts/${account.get('id')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Toots with replies' /></NavLink>
|
||||||
|
<NavLink exact to={`/accounts/${account.get('id')}/reblogs`}><FormattedMessage id='account.reblogs' defaultMessage='Boosts' /></NavLink>
|
||||||
<NavLink exact to={`/accounts/${account.get('id')}/media`}><FormattedMessage id='account.media' defaultMessage='Media' /></NavLink>
|
<NavLink exact to={`/accounts/${account.get('id')}/media`}><FormattedMessage id='account.media' defaultMessage='Media' /></NavLink>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -15,13 +15,13 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
||||||
import MissingIndicator from 'flavours/glitch/components/missing_indicator';
|
import MissingIndicator from 'flavours/glitch/components/missing_indicator';
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => {
|
const mapStateToProps = (state, { params: { accountId }, withReplies = false, reblogs = false }) => {
|
||||||
const path = withReplies ? `${accountId}:with_replies` : accountId;
|
const path = reblogs ? `${accountId}:reblogs` : withReplies ? `${accountId}:with_replies` : accountId;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isAccount: !!state.getIn(['accounts', accountId]),
|
isAccount: !!state.getIn(['accounts', accountId]),
|
||||||
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()),
|
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()),
|
||||||
featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], ImmutableList()),
|
featuredStatusIds: (withReplies || reblogs) ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], ImmutableList()),
|
||||||
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']),
|
||||||
};
|
};
|
||||||
|
@ -38,28 +38,29 @@ export default class AccountTimeline extends ImmutablePureComponent {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
withReplies: PropTypes.bool,
|
withReplies: PropTypes.bool,
|
||||||
|
reblogs: PropTypes.bool,
|
||||||
isAccount: PropTypes.bool,
|
isAccount: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
const { params: { accountId }, withReplies } = this.props;
|
const { params: { accountId }, withReplies, reblogs } = this.props;
|
||||||
|
|
||||||
this.props.dispatch(fetchAccount(accountId));
|
this.props.dispatch(fetchAccount(accountId));
|
||||||
this.props.dispatch(fetchAccountIdentityProofs(accountId));
|
this.props.dispatch(fetchAccountIdentityProofs(accountId));
|
||||||
if (!withReplies) {
|
if (!withReplies && !reblogs) {
|
||||||
this.props.dispatch(expandAccountFeaturedTimeline(accountId));
|
this.props.dispatch(expandAccountFeaturedTimeline(accountId));
|
||||||
}
|
}
|
||||||
this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
|
this.props.dispatch(expandAccountTimeline(accountId, { withReplies: withReplies, reblogs: reblogs }));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) {
|
if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies || nextProps.reblogs !== this.props.reblogs) {
|
||||||
this.props.dispatch(fetchAccount(nextProps.params.accountId));
|
this.props.dispatch(fetchAccount(nextProps.params.accountId));
|
||||||
this.props.dispatch(fetchAccountIdentityProofs(nextProps.params.accountId));
|
this.props.dispatch(fetchAccountIdentityProofs(nextProps.params.accountId));
|
||||||
if (!nextProps.withReplies) {
|
if (!nextProps.withReplies && !nextProps.reblogs) {
|
||||||
this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId));
|
this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId));
|
||||||
}
|
}
|
||||||
this.props.dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies }));
|
this.props.dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies, reblogs: nextProps.params.reblogs }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ export default class AccountTimeline extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoadMore = maxId => {
|
handleLoadMore = maxId => {
|
||||||
this.props.dispatch(expandAccountTimeline(this.props.params.accountId, { maxId, withReplies: this.props.withReplies }));
|
this.props.dispatch(expandAccountTimeline(this.props.params.accountId, { maxId, withReplies: this.props.withReplies, reblogs: this.props.reblogs }));
|
||||||
}
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
|
|
|
@ -500,6 +500,7 @@ export default class UI extends React.Component {
|
||||||
<WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} />
|
<WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} />
|
<WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} />
|
||||||
|
<WrappedRoute path='/accounts/:accountId/reblogs' component={AccountTimeline} content={children} componentParams={{ reblogs: true }} />
|
||||||
<WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
|
<WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
|
||||||
<WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} />
|
<WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} />
|
||||||
<WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} />
|
<WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} />
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"account.mute_notifications": "Mute notifications from @{name}",
|
"account.mute_notifications": "Mute notifications from @{name}",
|
||||||
"account.muted": "Muted",
|
"account.muted": "Muted",
|
||||||
"account.posts": "Roars",
|
"account.posts": "Roars",
|
||||||
|
"account.reblogs": "Repeats",
|
||||||
"account.posts_with_replies": "Roars & growls",
|
"account.posts_with_replies": "Roars & growls",
|
||||||
"account.report": "Report @{name}",
|
"account.report": "Report @{name}",
|
||||||
"account.requested": "Awaiting approval. Click to cancel join request",
|
"account.requested": "Awaiting approval. Click to cancel join request",
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
= active_link_to t('accounts.posts_tab_heading'), short_account_url(@account)
|
= active_link_to t('accounts.posts_tab_heading'), short_account_url(@account)
|
||||||
- if @account.replies
|
- if @account.replies
|
||||||
= active_link_to t('accounts.posts_with_replies'), short_account_with_replies_url(@account)
|
= active_link_to t('accounts.posts_with_replies'), short_account_with_replies_url(@account)
|
||||||
|
= active_link_to t('accounts.reblogs_tab_heading'), short_account_reblogs_url(@account)
|
||||||
= active_link_to t('accounts.media'), short_account_media_url(@account)
|
= active_link_to t('accounts.media'), short_account_media_url(@account)
|
||||||
|
|
||||||
- if user_signed_in? && @account.blocking?(current_account)
|
- if user_signed_in? && @account.blocking?(current_account)
|
||||||
|
|
|
@ -61,7 +61,11 @@ en:
|
||||||
posts:
|
posts:
|
||||||
one: Roar
|
one: Roar
|
||||||
other: Roars
|
other: Roars
|
||||||
|
reblogs:
|
||||||
|
one: Repeat
|
||||||
|
other: Repeats
|
||||||
posts_tab_heading: Roars
|
posts_tab_heading: Roars
|
||||||
|
reblogs_tab_heading: Repeats
|
||||||
posts_with_replies: Roars & growls
|
posts_with_replies: Roars & growls
|
||||||
reserved_username: The creaturename is reserved
|
reserved_username: The creaturename is reserved
|
||||||
roles:
|
roles:
|
||||||
|
|
|
@ -77,6 +77,7 @@ Rails.application.routes.draw do
|
||||||
get '/@:username', to: 'accounts#show', as: :short_account
|
get '/@:username', to: 'accounts#show', as: :short_account
|
||||||
get '/@:username/with_replies', to: 'accounts#show', as: :short_account_with_replies
|
get '/@:username/with_replies', to: 'accounts#show', as: :short_account_with_replies
|
||||||
get '/@:username/media', to: 'accounts#show', as: :short_account_media
|
get '/@:username/media', to: 'accounts#show', as: :short_account_media
|
||||||
|
get '/@:username/reblogs', to: 'accounts#show', as: :short_account_reblogs
|
||||||
get '/@:username/tagged/:tag', to: 'accounts#show', as: :short_account_tag
|
get '/@:username/tagged/:tag', to: 'accounts#show', as: :short_account_tag
|
||||||
get '/@:account_username/:id', to: 'statuses#show', as: :short_account_status
|
get '/@:account_username/:id', to: 'statuses#show', as: :short_account_status
|
||||||
get '/@:account_username/:id/embed', to: 'statuses#embed', as: :embed_short_account_status
|
get '/@:account_username/:id/embed', to: 'statuses#embed', as: :embed_short_account_status
|
||||||
|
|
Loading…
Reference in New Issue