diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index 8cc3455f..51ea6223 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -8,7 +8,7 @@ class Api::V1::NotificationsController < Api::BaseController respond_to :json - DEFAULT_NOTIFICATIONS_LIMIT = 50 + DEFAULT_NOTIFICATIONS_LIMIT = 30 def index @notifications = load_notifications diff --git a/app/javascript/gabsocial/components/input.js b/app/javascript/gabsocial/components/input.js index 9eb1aad9..ef9f0df8 100644 --- a/app/javascript/gabsocial/components/input.js +++ b/app/javascript/gabsocial/components/input.js @@ -73,7 +73,7 @@ export default class Input extends PureComponent { }) const btnClasses = cx({ - displayNone: value.length === 0, + displayNone: !value || value.length === 0, px10: 1, mr5: 1, }) diff --git a/app/javascript/gabsocial/components/panel/notification_filter_panel.js b/app/javascript/gabsocial/components/panel/notification_filter_panel.js index e428652a..b8bdd430 100644 --- a/app/javascript/gabsocial/components/panel/notification_filter_panel.js +++ b/app/javascript/gabsocial/components/panel/notification_filter_panel.js @@ -1,16 +1,7 @@ -import { Fragment } from 'react' import { defineMessages, injectIntl } from 'react-intl' import ImmutablePureComponent from 'react-immutable-pure-component' -import ImmutablePropTypes from 'react-immutable-proptypes' -import { shortNumberFormat } from '../../utils/numbers' import PanelLayout from './panel_layout' -import Button from '../button' -import Divider from '../divider' -import Heading from '../heading' -import Icon from '../icon' -import Input from '../input' import Switch from '../switch' -import Text from '../text' const messages = defineMessages({ title: { id: 'notification_filters', defaultMessage: 'Notification Filters' }, @@ -27,25 +18,8 @@ class NotificationFilterPanel extends ImmutablePureComponent { render() { const { intl } = this.props - // date - // verfied or not - // specific user - // specific status - // only people i do/not follow - return ( - Start Date - End Date - - - - - - - - - { @@ -31,26 +39,108 @@ class Notification extends ImmutablePureComponent { } static propTypes = { - status: ImmutablePropTypes.map, intl: PropTypes.object.isRequired, - notificationType: PropTypes.string.isRequired, - accounts: ImmutablePropTypes.list, + accounts: ImmutablePropTypes.list.isRequired, + createdAt: PropTypes.string, + statusId: PropTypes.string, + type: PropTypes.string.isRequired, } - renderFavorite = () => { - const { status, notificationType, accounts } = this.props + renderMention = () => { + const { intl, accounts, createdAt, statusId } = this.props + + if (accounts.size === 0) return null + const account = accounts.get(0) + + // : todo : render statuscontainer or commentcontainer return (
- + -
+
+
+ + + +
+
+
+
+ +
+ + {' '} + {intl.formatMessage(messages.mentionedInPost)} + +
+
+ +
+ +
+
+ +
+
+
+ ) + } + + renderPoll = () => { + const { intl, statusId } = this.props + + return ( +
+
+
+ + + +
+
+ + {intl.formatMessage(messages.poll)} + +
+ +
+ +
+
+ +
+
+
+ ) + } + + renderFollow = () => { + const { intl, accounts, statusId } = this.props + + const count = accounts.size + if (count === 0) return null + + return ( +
+
+
+ + + +
{ - accounts.slice(0, 6).map((account, i) => ( + accounts.slice(0, 8).map((account, i) => ( -  and 3 others favorited your gab + {' '} + {intl.formatMessage(count > 1 ? messages.followedYouMultiple : messages.followedYouOne, { + count: count - 1, + })}
+
+
+
+
+ ) + } + + renderLike = () => { + const { intl, accounts, statusId } = this.props + + const count = accounts.size + if (count === 0 || !statusId) return null + + return ( +
+
+
+ + + +
+
+ { + accounts.slice(0, 8).map((account, i) => ( + + + + )) + } +
- - post this at 1-14-2020 12:15pm (edited) - +
+
+ { + accounts.slice(0, 1).map((account, i) => ( + + )) + } +
+ + {' '} + {intl.formatMessage(count > 1 ? messages.likedStatusMultiple : messages.likedStatusOne, { + count: count - 1, + })} + +
+
+
+ +
+
+ +
+
+
+ ) + } + + renderRepost = () => { + const { intl, accounts, statusId } = this.props + + const count = accounts.size + if (count === 0 || !statusId) return null + + return ( +
+
+
+ + + +
+
+ { + accounts.slice(0, 8).map((account, i) => ( + + + + )) + } +
+
+
+
+ { + accounts.slice(0, 1).map((account, i) => ( + + )) + } +
+ + {' '} + {intl.formatMessage(count > 1 ? messages.repostedStatusMultiple : messages.repostedStatusOne, { + count: count - 1, + })} + +
+
+
+
@@ -90,65 +293,22 @@ class Notification extends ImmutablePureComponent { } render() { - const { - status, - notificationType, - accounts, - intl - } = this.props + const { type } = this.props - // const linkTo = '/admin/posts/123/reblogs' // etc. + switch (type) { + case 'follow': + return this.renderFollow() + case 'mention': + return this.renderMention() + case 'like': + return this.renderLike() + case 'repost': + return this.renderRepost(); + case 'poll': + return this.renderPoll() + } - return ( - -
-
- - - -
-
- { - accounts.slice(0, 6).map((account, i) => ( - - - - )) - } -
-
-
-
- { - accounts.slice(0, 1).map((account, i) => ( - - )) - } -
- -  and 3 others favorited your gab - -
-
- -
- - post this at 1-14-2020 12:15pm (edited) - -
-
- -
-
-
- ) + return null } } diff --git a/app/javascript/gabsocial/features/notifications/containers/notification_container.js b/app/javascript/gabsocial/features/notifications/containers/notification_container.js index 44ead996..14ee8665 100644 --- a/app/javascript/gabsocial/features/notifications/containers/notification_container.js +++ b/app/javascript/gabsocial/features/notifications/containers/notification_container.js @@ -1,3 +1,4 @@ +import { List as ImmutableList } from 'immutable' import { openModal } from '../../../actions/modal' import { mentionCompose } from '../../../actions/compose' import { @@ -10,23 +11,68 @@ import { hideStatus, revealStatus, } from '../../../actions/statuses' -import { boostModal, me } from '../../../initial_state' -import { makeGetNotification, makeGetStatus } from '../../../selectors' +import { boostModal } from '../../../initial_state' +import { makeGetNotification } from '../../../selectors' import Notification from '../components/notification/notification-alt' +const getAccountFromState = (state, accountId) => { + return state.getIn(['accounts', accountId]) +} + const makeMapStateToProps = () => { const getNotification = makeGetNotification() - const getStatus = makeGetStatus() const mapStateToProps = (state, props) => { - const notification = getNotification(state, props.notification, props.accountId) + const isFollows = !!props.notification.get('follow') + const isLikes = !!props.notification.get('like') + const isReposts = !!props.notification.get('repost') + const isGrouped = isFollows || isLikes || isReposts - const account = state.getIn(['accounts', me]) + if (isFollows) { + const list = props.notification.get('follow') + + let accounts = ImmutableList() + list.forEach((item) => { + const account = getAccountFromState(state, item.get('account')) + accounts = accounts.set(accounts.size, account) + }) + + return { + type: 'follow', + accounts: accounts, + createdAt: undefined, + statusId: undefined, + } + } else if (isLikes || isReposts) { + const theType = isLikes ? 'like' : 'repost' + const list = props.notification.get(theType) - return { - accounts: [account, account, account], - notification: notification, - status: notification.get('status') ? getStatus(state, { id: notification.get('status') }) : null, + let accounts = ImmutableList() + const accountIdArr = list.get('accounts') + + for (let i = 0; i < accountIdArr.length; i++) { + const accountId = accountIdArr[i]; + const account = getAccountFromState(state, accountId) + accounts = accounts.set(accounts.size, account) + } + + return { + type: theType, + accounts: accounts, + createdAt: undefined, + statusId: list.get('status'), + } + } else if (!isGrouped) { + const notification = getNotification(state, props.notification, props.notification.get('account')) + const account = notification.get('account') + const statusId = notification.get('status') + + return { + accounts: !!account ? ImmutableList([account]) : ImmutableList(), + type: notification.get('type'), + createdAt: notification.get('created_at'), + statusId: statusId || undefined, + } } } diff --git a/app/javascript/gabsocial/features/notifications/notifications.js b/app/javascript/gabsocial/features/notifications/notifications.js index e134728e..c5b7df26 100644 --- a/app/javascript/gabsocial/features/notifications/notifications.js +++ b/app/javascript/gabsocial/features/notifications/notifications.js @@ -133,37 +133,7 @@ class Notifications extends ImmutablePureComponent { // : todo : include follow requests - console.log('notifications:', notifications) - - let filteredNotifications = {follows:[]} - - notifications.forEach((notification) => { - // const createdAt = notification.get('createdAt') - // const account = notification.get('account') - const type = notification.get('type') - const status = notification.get('status') - if (type === 'follow') { - filteredNotifications.follows.push(notification) - } else if (type === 'favourite') { - if (filteredNotifications[status] === undefined) { - filteredNotifications[status] = {} - } - if (filteredNotifications[status]['favorite'] === undefined) { - filteredNotifications[status].favorite = [] - } - filteredNotifications[status].favorite.push(notification) - } else if (type === 'poll') { - if (filteredNotifications[status] === undefined) { - filteredNotifications[status] = {} - } - if (filteredNotifications[status]['poll'] === undefined) { - filteredNotifications[status].poll = [] - } - filteredNotifications[status].poll.push(notification) - } - }) - - console.log('filteredNotifications:', filteredNotifications) + // console.log('notifications:', notifications) if (isLoading && this.scrollableContent) { scrollableContent = this.scrollableContent diff --git a/app/javascript/gabsocial/pages/notifications_page.js b/app/javascript/gabsocial/pages/notifications_page.js index 1c6210df..4a506eee 100644 --- a/app/javascript/gabsocial/pages/notifications_page.js +++ b/app/javascript/gabsocial/pages/notifications_page.js @@ -56,27 +56,27 @@ class NotificationsPage extends PureComponent { active: false, }, { - title: ' @ ', + title: 'Mentions', onClick: null, active: false, }, { - icon: 'like', + title: 'Likes', onClick: null, active: false, }, { - icon: 'repost', + title: 'Reposts', onClick: null, active: false, }, { - icon: 'poll', + title: 'Polls', onClick: null, active: false, }, { - icon: 'user-plus', + title: 'Follows', onClick: null, active: false, }, diff --git a/app/javascript/gabsocial/reducers/notifications.js b/app/javascript/gabsocial/reducers/notifications.js index 6001f1d6..2def0e56 100644 --- a/app/javascript/gabsocial/reducers/notifications.js +++ b/app/javascript/gabsocial/reducers/notifications.js @@ -17,7 +17,7 @@ import { ACCOUNT_MUTE_SUCCESS, } from '../actions/accounts'; import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from '../actions/timelines'; -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; import compareId from '../utils/compare_id'; import { unreadCount } from '../initial_state'; @@ -57,31 +57,95 @@ const normalizeNotification = (state, notification) => { }; const expandNormalizedNotifications = (state, notifications, next) => { - let items = ImmutableList(); + //Grouped items + let follows = ImmutableList() + let likes = {} + let reposts = {} + + let items = ImmutableList() // : todo filter notiications here: - notifications.forEach((n, i) => { - items = items.set(i, notificationToMap(n)); - }); + notifications.forEach((n) => { + const notification = notificationToMap(n) + const statusId = notification.get('status') + const type = notification.get('type') + + switch (type) { + case 'follow': { + follows = follows.set(follows.size, notification) + break + } + case 'favourite': { + if (likes[statusId] === undefined) likes[statusId] = [] + likes[statusId].push({ + account: notification.get('account'), + }) + break + } + case 'reblog': { + if (reposts[statusId] === undefined) reposts[statusId] = [] + reposts[statusId].push({ + account: notification.get('account'), + }) + break + } + default: { + items = items.set(items.size, notification) + break + } + } + }) - console.log("reducer notifications:", notifications) + if (follows.size > 0) { + items = items.set(items.size, ImmutableMap({ + follow: follows, + })) + } + if (Object.keys(likes).length > 0) { + for (const statusId in likes) { + if (likes.hasOwnProperty(statusId)) { + const likeArr = likes[statusId] + const accounts = likeArr.map((l) => l.account) + items = items.set(items.size, ImmutableMap({ + like: ImmutableMap({ + status: statusId, + accounts: accounts, + }) + })) + } + } + } + if (Object.keys(reposts).length > 0) { + for (const statusId in reposts) { + if (reposts.hasOwnProperty(statusId)) { + const repostArr = reposts[statusId] + const accounts = repostArr.map((l) => l.account) + items = items.set(items.size, ImmutableMap({ + repost: ImmutableMap({ + status: statusId, + accounts: accounts, + }) + })) + } + } + } return state.withMutations(mutable => { if (!items.isEmpty()) { mutable.update('items', list => { const lastIndex = 1 + list.findLastIndex( item => item !== null && (compareId(item.get('id'), items.last().get('id')) > 0 || item.get('id') === items.last().get('id')) - ); + ) const firstIndex = 1 + list.take(lastIndex).findLastIndex( item => item !== null && compareId(item.get('id'), items.first().get('id')) > 0 - ); + ) + + const pop = list.take(firstIndex).concat(items, list.skip(lastIndex)) - const pop = list.take(firstIndex).concat(items, list.skip(lastIndex)); - console.log("pop:", pop) return pop - }); + }) } if (!next) {