From 65a2a40cb220fb80ed43c8ade916aac3fb1ed56d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 4 Nov 2021 14:07:20 -0500 Subject: [PATCH] Pull to Refresh: Notifications, Chats, Bookmarks --- app/soapbox/actions/bookmarks.js | 10 ++++++---- app/soapbox/features/bookmarks/index.js | 18 ++++++++++++++---- app/soapbox/features/chats/index.js | 13 +++++++++---- app/soapbox/features/notifications/index.js | 11 +++++++---- app/styles/components/columns.scss | 16 ++++++++++++---- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/app/soapbox/actions/bookmarks.js b/app/soapbox/actions/bookmarks.js index 3c8eec546..cf1ca8113 100644 --- a/app/soapbox/actions/bookmarks.js +++ b/app/soapbox/actions/bookmarks.js @@ -9,15 +9,17 @@ export const BOOKMARKED_STATUSES_EXPAND_REQUEST = 'BOOKMARKED_STATUSES_EXPAND_RE export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = 'BOOKMARKED_STATUSES_EXPAND_SUCCESS'; export const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL'; +const noOp = () => new Promise(f => f()); + export function fetchBookmarkedStatuses() { return (dispatch, getState) => { if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) { - return; + return dispatch(noOp); } dispatch(fetchBookmarkedStatusesRequest()); - api(getState).get('/api/v1/bookmarks').then(response => { + return api(getState).get('/api/v1/bookmarks').then(response => { const next = getLinks(response).refs.find(link => link.rel === 'next'); dispatch(importFetchedStatuses(response.data)); dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); @@ -53,12 +55,12 @@ export function expandBookmarkedStatuses() { const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null); if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) { - return; + return dispatch(noOp); } dispatch(expandBookmarkedStatusesRequest()); - api(getState).get(url).then(response => { + return api(getState).get(url).then(response => { const next = getLinks(response).refs.find(link => link.rel === 'next'); dispatch(importFetchedStatuses(response.data)); dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); diff --git a/app/soapbox/features/bookmarks/index.js b/app/soapbox/features/bookmarks/index.js index 0099871f5..ec4185f96 100644 --- a/app/soapbox/features/bookmarks/index.js +++ b/app/soapbox/features/bookmarks/index.js @@ -2,7 +2,8 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; +import Column from 'soapbox/components/column'; +import SubNavigation from 'soapbox/components/sub_navigation'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import StatusList from '../../components/status_list'; @@ -38,15 +39,22 @@ class Bookmarks extends ImmutablePureComponent { isLoading: PropTypes.bool, }; - componentDidMount() { + fetchData = () => { const { dispatch } = this.props; - dispatch(fetchBookmarkedStatuses()); + return dispatch(fetchBookmarkedStatuses()); + } + + componentDidMount() { + this.fetchData(); } handleLoadMore = debounce(() => { this.props.dispatch(expandBookmarkedStatuses()); }, 300, { leading: true }) + handleRefresh = () => { + return this.fetchData(); + } render() { const { intl, shouldUpdateScroll, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; @@ -55,7 +63,8 @@ class Bookmarks extends ImmutablePureComponent { const emptyMessage = ; return ( - + + { + const { dispatch } = this.props; + return dispatch(fetchChats()); + } + render() { const { intl } = this.props; @@ -55,12 +60,12 @@ class ChatIndex extends React.PureComponent { onSelected={this.handleSuggestion} /> - + } /> - + ); } diff --git a/app/soapbox/features/notifications/index.js b/app/soapbox/features/notifications/index.js index 61367bad4..58f567f7d 100644 --- a/app/soapbox/features/notifications/index.js +++ b/app/soapbox/features/notifications/index.js @@ -21,7 +21,6 @@ import TimelineQueueButtonHeader from '../../components/timeline_queue_button_h import { getSettings } from 'soapbox/actions/settings'; import PlaceholderNotification from 'soapbox/features/placeholder/components/placeholder_notification'; import SubNavigation from 'soapbox/components/sub_navigation'; -import Pullable from 'soapbox/components/pullable'; const messages = defineMessages({ title: { id: 'column.notifications', defaultMessage: 'Notifications' }, @@ -129,6 +128,11 @@ class Notifications extends React.PureComponent { this.props.dispatch(dequeueNotifications()); }; + handleRefresh = () => { + const { dispatch } = this.props; + return dispatch(expandNotifications()); + } + render() { const { intl, notifications, isLoading, hasMore, showFilterBar, totalQueuedNotificationsCount } = this.props; const emptyMessage = ; @@ -173,6 +177,7 @@ class Notifications extends React.PureComponent { placeholderComponent={PlaceholderNotification} placeholderCount={20} onLoadMore={this.handleLoadOlder} + onRefresh={this.handleRefresh} onScrollToTop={this.handleScrollToTop} onScroll={this.handleScroll} > @@ -189,9 +194,7 @@ class Notifications extends React.PureComponent { count={totalQueuedNotificationsCount} message={messages.queue} /> - - {scrollContainer} - + {scrollContainer} ); } diff --git a/app/styles/components/columns.scss b/app/styles/components/columns.scss index 1b82cdcfd..854d5c1af 100644 --- a/app/styles/components/columns.scss +++ b/app/styles/components/columns.scss @@ -934,10 +934,18 @@ } // Make MaterialStatus flush against SubNavigation -.sub-navigation ~ .slist .item-list > article:first-child .material-status__status, -.sub-navigation ~ .material-status:not(.material-status + .material-status) .material-status__status { - border-top-left-radius: 0; - border-top-right-radius: 0; +.sub-navigation ~, +.sub-navigation ~ .ptr > .ptr__children > { + // ScrollableList + .slist .item-list > article:first-child, + // Thread + .material-status:not(.material-status + .material-status) { + // MaterialStatus + .material-status__status { + border-top-left-radius: 0; + border-top-right-radius: 0; + } + } } // Display background for loading indicator