about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/features/notifications/index.js
diff options
context:
space:
mode:
authorThibaut Girka <thib@sitedethib.com>2018-05-27 19:30:52 +0200
committerThibG <thib@sitedethib.com>2018-05-29 21:25:28 +0200
commit4eba8c50c31d70f466a68d48445f86d644e4a889 (patch)
treee9f7f44ef62c4f0c1f8d4de38ca43f4337e8f6ca /app/javascript/flavours/glitch/features/notifications/index.js
parent0ad3eedd4cf6d1d7f7ceacc2c4412dbd8ee79cef (diff)
[Glitch] Allow clients to fetch notifications made while they were offline
Port cbf97c03bba35a642e6f1d1a698aad7a69ad13a3 to glitch-soc
Diffstat (limited to 'app/javascript/flavours/glitch/features/notifications/index.js')
-rw-r--r--app/javascript/flavours/glitch/features/notifications/index.js48
1 files changed, 39 insertions, 9 deletions
diff --git a/app/javascript/flavours/glitch/features/notifications/index.js b/app/javascript/flavours/glitch/features/notifications/index.js
index c27d3ffc9..f1319af45 100644
--- a/app/javascript/flavours/glitch/features/notifications/index.js
+++ b/app/javascript/flavours/glitch/features/notifications/index.js
@@ -17,6 +17,7 @@ import { createSelector } from 'reselect';
 import { List as ImmutableList } from 'immutable';
 import { debounce } from 'lodash';
 import ScrollableList from 'flavours/glitch/components/scrollable_list';
+import LoadMore from 'flavours/glitch/components/load_more';
 
 const messages = defineMessages({
   title: { id: 'column.notifications', defaultMessage: 'Notifications' },
@@ -25,14 +26,32 @@ const messages = defineMessages({
 const getNotifications = createSelector([
   state => ImmutableList(state.getIn(['settings', 'notifications', 'shows']).filter(item => !item).keys()),
   state => state.getIn(['notifications', 'items']),
-], (excludedTypes, notifications) => notifications.filterNot(item => excludedTypes.includes(item.get('type'))));
+], (excludedTypes, notifications) => notifications.filterNot(item => item !== null && excludedTypes.includes(item.get('type'))));
+
+class LoadGap extends React.PureComponent {
+
+  static propTypes = {
+    disabled: PropTypes.bool,
+    maxId: PropTypes.string,
+    onClick: PropTypes.func.isRequired,
+  };
+
+  handleClick = () => {
+    this.props.onClick(this.props.maxId);
+  }
+
+  render () {
+    return <LoadMore onClick={this.handleClick} disabled={this.props.disabled} />;
+  }
+
+}
 
 const mapStateToProps = state => ({
   notifications: getNotifications(state),
   localSettings:  state.get('local_settings'),
   isLoading: state.getIn(['notifications', 'isLoading'], true),
   isUnread: state.getIn(['notifications', 'unread']) > 0,
-  hasMore: !!state.getIn(['notifications', 'next']),
+  hasMore: state.getIn(['notifications', 'hasMore']),
   notifCleaningActive: state.getIn(['notifications', 'cleaningMode']),
 });
 
@@ -67,9 +86,13 @@ export default class Notifications extends React.PureComponent {
     trackScroll: true,
   };
 
-  handleLoadMore = debounce(() => {
-    this.props.dispatch(scrollTopNotifications(false));
-    this.props.dispatch(expandNotifications());
+  handleLoadGap = (maxId) => {
+    this.props.dispatch(expandNotifications({ maxId }));
+  };
+
+  handleLoadOlder = debounce(() => {
+    const last = this.props.notifications.last();
+    this.props.dispatch(expandNotifications({ maxId: last && last.get('id') }));
   }, 300, { leading: true });
 
   handleScrollToTop = debounce(() => {
@@ -104,12 +127,12 @@ export default class Notifications extends React.PureComponent {
   }
 
   handleMoveUp = id => {
-    const elementIndex = this.props.notifications.findIndex(item => item.get('id') === id) - 1;
+    const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) - 1;
     this._selectChild(elementIndex);
   }
 
   handleMoveDown = id => {
-    const elementIndex = this.props.notifications.findIndex(item => item.get('id') === id) + 1;
+    const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) + 1;
     this._selectChild(elementIndex);
   }
 
@@ -131,7 +154,14 @@ export default class Notifications extends React.PureComponent {
     if (isLoading && this.scrollableContent) {
       scrollableContent = this.scrollableContent;
     } else if (notifications.size > 0 || hasMore) {
-      scrollableContent = notifications.map((item) => (
+      scrollableContent = notifications.map((item, index) => item === null ? (
+        <LoadGap
+          key={'gap:' + notifications.getIn([index + 1, 'id'])}
+          disabled={isLoading}
+          maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
+          onClick={this.handleLoadGap}
+        />
+      ) : (
         <NotificationContainer
           key={item.get('id')}
           notification={item}
@@ -153,7 +183,7 @@ export default class Notifications extends React.PureComponent {
         isLoading={isLoading}
         hasMore={hasMore}
         emptyMessage={emptyMessage}
-        onLoadMore={this.handleLoadMore}
+        onLoadMore={this.handleLoadOlder}
         onScrollToTop={this.handleScrollToTop}
         onScroll={this.handleScroll}
         shouldUpdateScroll={shouldUpdateScroll}