2020-03-04 03:45:16 +00:00
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { defineMessages , injectIntl , FormattedMessage } from 'react-intl'
import { createSelector } from 'reselect'
import { List as ImmutableList } from 'immutable'
2020-04-08 02:06:59 +01:00
import debounce from 'lodash.debounce'
2019-08-13 16:54:29 +01:00
import {
expandNotifications ,
scrollTopNotifications ,
dequeueNotifications ,
2020-04-24 04:17:27 +01:00
} from '../actions/notifications'
import NotificationContainer from '../containers/notification_container'
2020-03-04 03:45:16 +00:00
// import ColumnSettingsContainer from './containers/column_settings_container'
2020-04-24 04:17:27 +01:00
import ScrollableList from '../components/scrollable_list'
import LoadMore from '../components/load_more'
import TimelineQueueButtonHeader from '../components/timeline_queue_button_header'
import Block from '../components/block'
2019-08-13 16:54:29 +01:00
2020-04-11 23:29:19 +01:00
const mapStateToProps = ( state ) => ( {
notifications : state . getIn ( [ 'notifications' , 'items' ] ) ,
2019-08-13 16:54:29 +01:00
isLoading : state . getIn ( [ 'notifications' , 'isLoading' ] , true ) ,
isUnread : state . getIn ( [ 'notifications' , 'unread' ] ) > 0 ,
hasMore : state . getIn ( [ 'notifications' , 'hasMore' ] ) ,
totalQueuedNotificationsCount : state . getIn ( [ 'notifications' , 'totalQueuedNotificationsCount' ] , 0 ) ,
2020-03-04 03:45:16 +00:00
} )
2019-08-13 16:54:29 +01:00
2020-02-25 16:04:44 +00:00
export default
@ connect ( mapStateToProps )
2019-08-13 16:54:29 +01:00
@ injectIntl
class Notifications extends ImmutablePureComponent {
static propTypes = {
notifications : ImmutablePropTypes . list . isRequired ,
dispatch : PropTypes . func . isRequired ,
intl : PropTypes . object . isRequired ,
isLoading : PropTypes . bool ,
isUnread : PropTypes . bool ,
hasMore : PropTypes . bool ,
dequeueNotifications : PropTypes . func ,
totalQueuedNotificationsCount : PropTypes . number ,
2020-03-04 03:45:16 +00:00
}
2019-08-13 16:54:29 +01:00
componentWillUnmount ( ) {
2020-03-04 03:45:16 +00:00
this . handleLoadOlder . cancel ( )
this . handleScrollToTop . cancel ( )
this . handleScroll . cancel ( )
this . props . dispatch ( scrollTopNotifications ( false ) )
2019-08-13 16:54:29 +01:00
}
componentDidMount ( ) {
2020-03-04 03:45:16 +00:00
this . handleDequeueNotifications ( )
this . props . dispatch ( scrollTopNotifications ( true ) )
2019-08-13 16:54:29 +01:00
}
handleLoadGap = ( maxId ) => {
2020-04-28 06:33:58 +01:00
// maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
2020-03-04 03:45:16 +00:00
this . props . dispatch ( expandNotifications ( { maxId } ) )
}
2019-08-13 16:54:29 +01:00
handleLoadOlder = debounce ( ( ) => {
2020-03-04 03:45:16 +00:00
const last = this . props . notifications . last ( )
this . props . dispatch ( expandNotifications ( { maxId : last && last . get ( 'id' ) } ) )
} , 300 , { leading : true } )
2019-08-13 16:54:29 +01:00
handleScrollToTop = debounce ( ( ) => {
2020-03-04 03:45:16 +00:00
this . props . dispatch ( scrollTopNotifications ( true ) )
} , 100 )
2019-08-13 16:54:29 +01:00
handleScroll = debounce ( ( ) => {
2020-03-04 03:45:16 +00:00
this . props . dispatch ( scrollTopNotifications ( false ) )
} , 100 )
2019-08-13 16:54:29 +01:00
setColumnRef = c => {
2020-03-04 03:45:16 +00:00
this . column = c
2019-08-13 16:54:29 +01:00
}
handleMoveUp = id => {
2020-03-04 03:45:16 +00:00
const elementIndex = this . props . notifications . findIndex ( item => item !== null && item . get ( 'id' ) === id ) - 1
this . _selectChild ( elementIndex , true )
2019-08-13 16:54:29 +01:00
}
handleMoveDown = id => {
2020-03-04 03:45:16 +00:00
const elementIndex = this . props . notifications . findIndex ( item => item !== null && item . get ( 'id' ) === id ) + 1
this . _selectChild ( elementIndex , false )
2019-08-13 16:54:29 +01:00
}
_selectChild ( index , align _top ) {
2020-03-04 03:45:16 +00:00
const container = this . column . node
const element = container . querySelector ( ` article:nth-of-type( ${ index + 1 } ) .focusable ` )
2019-08-13 16:54:29 +01:00
if ( element ) {
if ( align _top && container . scrollTop > element . offsetTop ) {
2020-03-04 03:45:16 +00:00
element . scrollIntoView ( true )
2019-08-13 16:54:29 +01:00
} else if ( ! align _top && container . scrollTop + container . clientHeight < element . offsetTop + element . offsetHeight ) {
2020-03-04 03:45:16 +00:00
element . scrollIntoView ( false )
2019-08-13 16:54:29 +01:00
}
2020-03-04 03:45:16 +00:00
element . focus ( )
2019-08-13 16:54:29 +01:00
}
}
handleDequeueNotifications = ( ) => {
2020-04-11 23:29:19 +01:00
window . scrollTo ( 0 , 0 )
2020-03-04 03:45:16 +00:00
this . props . dispatch ( dequeueNotifications ( ) )
}
2019-08-13 16:54:29 +01:00
render ( ) {
2020-03-04 03:45:16 +00:00
const {
intl ,
notifications ,
isLoading ,
isUnread ,
hasMore ,
totalQueuedNotificationsCount
} = this . props
let scrollableContent = null
2019-08-13 16:54:29 +01:00
2020-02-22 23:26:23 +00:00
// : todo : include follow requests
2020-05-10 04:26:58 +01:00
console . log ( '--0--notifications:' , hasMore )
2019-08-13 16:54:29 +01:00
if ( isLoading && this . scrollableContent ) {
2020-03-04 03:45:16 +00:00
scrollableContent = this . scrollableContent
2019-08-13 16:54:29 +01:00
} else if ( notifications . size > 0 || hasMore ) {
scrollableContent = notifications . map ( ( item , index ) => item === null ? (
2020-04-28 06:33:58 +01:00
< LoadMore disabled = { isLoading } onClick = { this . handleLoadGap } / >
2019-08-13 16:54:29 +01:00
) : (
< NotificationContainer
2020-03-04 03:45:16 +00:00
key = { ` notification- ${ index } ` }
2019-08-13 16:54:29 +01:00
notification = { item }
onMoveUp = { this . handleMoveUp }
onMoveDown = { this . handleMoveDown }
/ >
2020-03-04 03:45:16 +00:00
) )
2019-08-13 16:54:29 +01:00
} else {
2020-03-04 03:45:16 +00:00
scrollableContent = null
2019-08-13 16:54:29 +01:00
}
2020-03-04 03:45:16 +00:00
this . scrollableContent = scrollableContent
2019-08-13 16:54:29 +01:00
return (
2020-02-24 23:25:55 +00:00
< div ref = { this . setColumnRef } >
2020-03-02 22:26:25 +00:00
< TimelineQueueButtonHeader
onClick = { this . handleDequeueNotifications }
count = { totalQueuedNotificationsCount }
itemType = 'notification'
/ >
2020-03-04 03:45:16 +00:00
< Block >
< ScrollableList
scrollKey = 'notifications'
isLoading = { isLoading }
showLoading = { isLoading && notifications . size === 0 }
hasMore = { hasMore }
emptyMessage = { < FormattedMessage id = 'empty_column.notifications' defaultMessage = "You don't have any notifications yet. Interact with others to start the conversation." / > }
onLoadMore = { this . handleLoadOlder }
onScrollToTop = { this . handleScrollToTop }
onScroll = { this . handleScroll }
>
{ scrollableContent }
< / S c r o l l a b l e L i s t >
< / B l o c k >
2020-02-24 23:25:55 +00:00
< / d i v >
2020-03-02 22:26:25 +00:00
)
2019-08-13 16:54:29 +01:00
}
}