Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

client: Restore “Mark all” button to 2.18 behaviour #1460

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 100 additions & 17 deletions client/js/templates/EntriesPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, {
useEffect,
useMemo,
useState,
useReducer,
} from 'react';
import PropTypes from 'prop-types';
import { Link, useLocation, useParams } from 'react-router-dom';
Expand All @@ -25,6 +26,39 @@ import { useShouldReload } from '../helpers/hooks';
import { forceReload, makeEntriesLinkLocation } from '../helpers/uri';
import { HttpError } from '../errors';

const LOAD_MORE = 'load-more';
const RESET_OFFSET = 'reset-offset';

function entriesReducer(
state,
action,
) {
console.log(state, action)
switch (action.type) {
case LOAD_MORE:
const { entries } = action.payload;
const lastEntry = entries[entries.length - 1];

return {
...state,
// Calculate offset.
fromDatetime: lastEntry ? lastEntry.datetime : undefined,
fromId: lastEntry ? lastEntry.id : undefined,
};

case RESET_OFFSET:
return {
...state,
// Calculate offset.
fromDatetime: undefined,
fromId: undefined,
};

default:
throw new Error('Unknown action.');
}
}

function reloadList({
fetchParams,
abortController,
Expand Down Expand Up @@ -76,13 +110,24 @@ function reloadList({
selfoss.entriesPage.setSelectedEntry(null);
}

const reloader_ = reloader;

reloader = (...args) => {
const r = reloader_(...args);
console.trace('reloader', r);
return r;
}

setLoadingState(LoadingState.LOADING);
return reloader(fetchParams, abortController).then(({ entries, hasMore }) => {
setLoadingState(LoadingState.SUCCESS);

console.trace('reloader-then', abortController.signal, abortController.signal.aborted);
if (abortController.signal.aborted) {
return;
}
console.log('after')

setLoadingState(LoadingState.SUCCESS);
selfoss.entriesPage.setHasMore(hasMore);

if (append) {
Expand Down Expand Up @@ -195,6 +240,7 @@ export function EntriesPage({
reload,
setGlobalUnreadCount,
unreadItemsCount,
setDispatchEntries,
}) {
const allowedToUpdate = useAllowedToUpdate();
const allowedToWrite = useAllowedToWrite();
Expand All @@ -212,14 +258,28 @@ export function EntriesPage({
const currentTag = params.category?.startsWith('tag-') ? params.category.replace(/^tag-/, '') : null;
const currentSource = params.category?.startsWith('source-') ? parseInt(params.category.replace(/^source-/, ''), 10) : null;

// The offsets for pagination.
// Clear them when URL changes, except for when only id changes since that happens when reading.
const [fromDatetime, setFromDatetime] = useStateWithDeps(
undefined,
[params.filter, currentTag, currentSource, searchText]
const [entriesState, dispatchEntries] = useReducer(
entriesReducer,
{
// The offsets for pagination.
// Clear them when URL changes, except for when only id changes since that happens when reading.
fromDatetime: undefined,
fromId: undefined,
}
);
const [fromId, setFromId] = useStateWithDeps(
undefined,

// Propagate the dispatcher to stateful class component.
setDispatchEntries(dispatchEntries);

const {
fromDatetime,
fromId,
} = entriesState;

useEffect(
() => dispatchEntries({
type: RESET_OFFSET,
}),
[params.filter, currentTag, currentSource, searchText]
);

Expand All @@ -236,7 +296,11 @@ export function EntriesPage({
return navSourcesExpanded;
}, [params.filter, currentTag, currentSource, searchText]);

const [moreLoadingState, setMoreLoadingState] = useState(LoadingState.INITIAL);
const [moreLoadingState, setMoreLoadingState_] = useState(LoadingState.INITIAL);
const setMoreLoadingState = (...args) => {
console.trace('moreState', ...args);
setMoreLoadingState_(...args);
};

// Perform the scheduled reload.
useEffect(() => {
Expand Down Expand Up @@ -329,13 +393,14 @@ export function EntriesPage({
const moreOnClick = useCallback(
(event) => {
event.preventDefault();
const lastEntry = entries[entries.length - 1];

// Calculate offset.
setFromDatetime(lastEntry ? lastEntry.datetime : undefined);
setFromId(lastEntry ? lastEntry.id : undefined);
dispatchEntries({
type: LOAD_MORE,
payload: {
entries,
},
});
},
[entries, setFromDatetime, setFromId]
[entries]
);

// Current time for calculating relative dates in items.
Expand Down Expand Up @@ -445,6 +510,7 @@ EntriesPage.propTypes = {
reload: PropTypes.func.isRequired,
setGlobalUnreadCount: PropTypes.func.isRequired,
unreadItemsCount: PropTypes.number.isRequired,
setDispatchEntries: PropTypes.func.isRequired,
};

const initialState = {
Expand All @@ -461,6 +527,8 @@ const initialState = {
};

export default class StateHolder extends React.Component {
dispatchEntries = () => {};

constructor(props) {
super(props);
this.state = initialState;
Expand Down Expand Up @@ -753,8 +821,8 @@ export default class StateHolder extends React.Component {
this.setExpandedEntries({});
this.props.setNavExpanded(false);

if (ids.length !== 0 && this.props.match.params.filter === FilterType.UNREAD) {
markedEntries = markedEntries.filter(({ id }) => !ids.includes(id));
if (this.props.match.params.filter === FilterType.UNREAD) {
markedEntries = markedEntries.filter(({ id }) => parseInt(this.props.match.params.id ?? null, 10) === id);
}

this.setLoadingState(LoadingState.LOADING);
Expand Down Expand Up @@ -790,6 +858,16 @@ export default class StateHolder extends React.Component {

itemsRequests.markAll(ids).then(() => {
this.setLoadingState(LoadingState.SUCCESS);

if (this.props.match.params.filter === FilterType.UNREAD) {
// We cleared out the entries page, load more.
this.dispatchEntries({
type: LOAD_MORE,
payload: {
entries: oldEntries,
},
});
}
}).catch((error) => {
selfoss.handleAjaxError(error).then(() => {
const statuses = ids.map((id) => ({
Expand Down Expand Up @@ -1076,6 +1154,10 @@ export default class StateHolder extends React.Component {
}

render() {
const setDispatchEntries = (dispatchEntries) => {
this.dispatchEntries = dispatchEntries;
};

return (
<EntriesPage
entries={this.state.entries}
Expand All @@ -1089,6 +1171,7 @@ export default class StateHolder extends React.Component {
reload={this.reload}
setGlobalUnreadCount={this.props.setGlobalUnreadCount}
unreadItemsCount={this.props.unreadItemsCount}
setDispatchEntries={setDispatchEntries}
/>
);
}
Expand Down
Loading