Add "clear notifications" button, exclude posts from people who have blocked *you* from public/hashtag timelines
parent
eb9934c88c
commit
94cda4cfb9
|
@ -14,6 +14,8 @@ export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
|
||||||
export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
|
export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
|
||||||
export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
|
export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
|
||||||
|
|
||||||
|
export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
|
||||||
|
|
||||||
const fetchRelatedRelationships = (dispatch, notifications) => {
|
const fetchRelatedRelationships = (dispatch, notifications) => {
|
||||||
const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
|
const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
|
||||||
|
|
||||||
|
@ -139,3 +141,13 @@ export function expandNotificationsFail(error) {
|
||||||
error
|
error
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function clearNotifications() {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({
|
||||||
|
type: NOTIFICATIONS_CLEAR
|
||||||
|
});
|
||||||
|
|
||||||
|
api(getState).post('/api/v1/notifications/clear');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
const iconStyle = {
|
||||||
|
fontSize: '16px',
|
||||||
|
padding: '15px',
|
||||||
|
position: 'absolute',
|
||||||
|
right: '48px',
|
||||||
|
top: '0',
|
||||||
|
cursor: 'pointer',
|
||||||
|
background: '#2f3441'
|
||||||
|
};
|
||||||
|
|
||||||
|
const ClearColumnButton = ({ onClick }) => (
|
||||||
|
<div className='column-icon' style={iconStyle} onClick={onClick}>
|
||||||
|
<i className='fa fa-trash' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
ClearColumnButton.propTypes = {
|
||||||
|
onClick: React.PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClearColumnButton;
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Column from '../ui/components/column';
|
import Column from '../ui/components/column';
|
||||||
import { expandNotifications } from '../../actions/notifications';
|
import { expandNotifications, clearNotifications } from '../../actions/notifications';
|
||||||
import NotificationContainer from './containers/notification_container';
|
import NotificationContainer from './containers/notification_container';
|
||||||
import { ScrollContainer } from 'react-router-scroll';
|
import { ScrollContainer } from 'react-router-scroll';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
@ -10,6 +10,7 @@ import ColumnSettingsContainer from './containers/column_settings_container';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
import LoadMore from '../../components/load_more';
|
import LoadMore from '../../components/load_more';
|
||||||
|
import ClearColumnButton from './components/clear_column_button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.notifications', defaultMessage: 'Notifications' }
|
title: { id: 'column.notifications', defaultMessage: 'Notifications' }
|
||||||
|
@ -64,6 +65,10 @@ const Notifications = React.createClass({
|
||||||
this.props.dispatch(expandNotifications());
|
this.props.dispatch(expandNotifications());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleClear () {
|
||||||
|
this.props.dispatch(clearNotifications());
|
||||||
|
},
|
||||||
|
|
||||||
setRef (c) {
|
setRef (c) {
|
||||||
this.node = c;
|
this.node = c;
|
||||||
},
|
},
|
||||||
|
@ -90,6 +95,7 @@ const Notifications = React.createClass({
|
||||||
return (
|
return (
|
||||||
<Column icon='bell' heading={intl.formatMessage(messages.title)}>
|
<Column icon='bell' heading={intl.formatMessage(messages.title)}>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
|
<ClearColumnButton onClick={this.handleClear} />
|
||||||
<ScrollContainer scrollKey='notifications'>
|
<ScrollContainer scrollKey='notifications'>
|
||||||
{scrollableArea}
|
{scrollableArea}
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
|
@ -99,6 +105,7 @@ const Notifications = React.createClass({
|
||||||
return (
|
return (
|
||||||
<Column icon='bell' heading={intl.formatMessage(messages.title)}>
|
<Column icon='bell' heading={intl.formatMessage(messages.title)}>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
|
<ClearColumnButton onClick={this.handleClear} />
|
||||||
{scrollableArea}
|
{scrollableArea}
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {
|
||||||
NOTIFICATIONS_REFRESH_REQUEST,
|
NOTIFICATIONS_REFRESH_REQUEST,
|
||||||
NOTIFICATIONS_EXPAND_REQUEST,
|
NOTIFICATIONS_EXPAND_REQUEST,
|
||||||
NOTIFICATIONS_REFRESH_FAIL,
|
NOTIFICATIONS_REFRESH_FAIL,
|
||||||
NOTIFICATIONS_EXPAND_FAIL
|
NOTIFICATIONS_EXPAND_FAIL,
|
||||||
|
NOTIFICATIONS_CLEAR
|
||||||
} from '../actions/notifications';
|
} from '../actions/notifications';
|
||||||
import { ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts';
|
import { ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
|
@ -75,6 +76,8 @@ export default function notifications(state = initialState, action) {
|
||||||
return appendNormalizedNotifications(state, action.notifications, action.next);
|
return appendNormalizedNotifications(state, action.notifications, action.next);
|
||||||
case ACCOUNT_BLOCK_SUCCESS:
|
case ACCOUNT_BLOCK_SUCCESS:
|
||||||
return filterNotifications(state, action.relationship);
|
return filterNotifications(state, action.relationship);
|
||||||
|
case NOTIFICATIONS_CLEAR:
|
||||||
|
return state.set('items', Immutable.List()).set('next', null);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.column-icon {
|
||||||
|
color: $color3;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: lighten($color3, 7%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
color: lighten($color1, 26%);
|
color: lighten($color1, 26%);
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
@ -161,7 +161,7 @@ class Status < ApplicationRecord
|
||||||
private
|
private
|
||||||
|
|
||||||
def filter_timeline(query, account)
|
def filter_timeline(query, account)
|
||||||
blocked = Block.where(account: account).pluck(:target_account_id)
|
blocked = Block.where(account: account).pluck(:target_account_id) + Block.where(target_account: account).pluck(:account_id)
|
||||||
query = query.where('statuses.account_id NOT IN (?)', blocked) unless blocked.empty?
|
query = query.where('statuses.account_id NOT IN (?)', blocked) unless blocked.empty?
|
||||||
query = query.where('accounts.silenced = TRUE') if account.silenced?
|
query = query.where('accounts.silenced = TRUE') if account.silenced?
|
||||||
query
|
query
|
||||||
|
|
Loading…
Reference in New Issue