forked from cybrespace/mastodon
		
	Add "clear notifications" button, exclude posts from people who have blocked *you* from public/hashtag timelines
This commit is contained in:
		
							parent
							
								
									c8252759df
								
							
						
					
					
						commit
						ac035108aa
					
				
					 6 changed files with 54 additions and 3 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		
		Reference in a new issue