Add "clear notifications" button, exclude posts from people who have blocked *you* from public/hashtag timelines

lolsob-rspec
Eugen Rochko 2017-02-07 00:06:40 +01:00
parent eb9934c88c
commit 94cda4cfb9
6 changed files with 54 additions and 3 deletions

View File

@ -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');
};
};

View File

@ -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;

View File

@ -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>
); );

View File

@ -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;
} }

View File

@ -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;

View File

@ -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