Skip to content

Commit

Permalink
wip: Switch to react-router 6
Browse files Browse the repository at this point in the history
Currently broken because regex pattern support has been removed:

remix-run/react-router#8254
  • Loading branch information
jtojnar committed Oct 14, 2022
1 parent 18e99da commit d341be2
Show file tree
Hide file tree
Showing 12 changed files with 235 additions and 338 deletions.
206 changes: 114 additions & 92 deletions assets/js/templates/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import PropTypes from 'prop-types';
import nullable from 'prop-types-nullable';
import {
BrowserRouter as Router,
Switch,
Routes,
Route,
Link,
Redirect,
useHistory,
useLocation,
useRouteMatch,
useMatch,
useNavigate,
} from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Collapse from '@kunukn/react-collapse';
Expand Down Expand Up @@ -147,10 +148,15 @@ function PureApp({
}, []);

// TODO: move stuff that depends on this to the App.
const history = useHistory();
const navigate = useNavigate();
React.useEffect(() => {
selfoss.navigate = navigate;
}, [navigate]);

const entriesPageMatch = useMatch(ENTRIES_ROUTE_PATTERN);
React.useEffect(() => {
selfoss.history = history;
}, [history]);
selfoss.entriesPageMatch = entriesPageMatch;
}, [entriesPageMatch]);

// Prepare path of the homepage for redirecting from /
let homePagePath = configuration.homepage.split('/');
Expand Down Expand Up @@ -181,97 +187,113 @@ function PureApp({
<React.StrictMode>
<Message message={globalMessage} />

<Switch>
<Route path="/sign/in">
{/* menu open for smartphone */}
<div id="loginform" role="main">
<LoginForm
{...{offlineEnabled}}
/>
</div>
</Route>

<Route path="/">
<CheckAuthorization
isAllowed={selfoss.isAllowedToRead()}
_={_}
>
<div id="nav-mobile" role="navigation">
<div id="nav-mobile-logo">
<div id="nav-mobile-count" className={classNames({'unread-count': true, offline: offlineState, online: !offlineState, unread: unreadItemsCount > 0})}>
<span className={classNames({'offline-count': true, offline: offlineState, online: !offlineState, diff: unreadItemsCount !== unreadItemsOfflineCount && unreadItemsOfflineCount})}>{unreadItemsOfflineCount > 0 ? unreadItemsOfflineCount : ''}</span>
<span className="count">{unreadItemsCount}</span>
<Routes>
<Route
path="/sign/in"
element={
/* menu open for smartphone */
<div id="loginform" role="main">
<LoginForm
{...{offlineEnabled}}
/>
</div>
}
/>

<Route
path="/"
element={
<CheckAuthorization
isAllowed={selfoss.isAllowedToRead()}
_={_}
>
<div id="nav-mobile" role="navigation">
<div id="nav-mobile-logo">
<div id="nav-mobile-count" className={classNames({'unread-count': true, offline: offlineState, online: !offlineState, unread: unreadItemsCount > 0})}>
<span className={classNames({'offline-count': true, offline: offlineState, online: !offlineState, diff: unreadItemsCount !== unreadItemsOfflineCount && unreadItemsOfflineCount})}>{unreadItemsOfflineCount > 0 ? unreadItemsOfflineCount : ''}</span>
<span className="count">{unreadItemsCount}</span>
</div>
</div>
<button
id="nav-mobile-settings"
accessKey="t"
aria-label={_('settingsbutton')}
onClick={menuButtonOnClick}
>
<FontAwesomeIcon icon={icons.menu} size="2x" />
</button>
</div>
<button
id="nav-mobile-settings"
accessKey="t"
aria-label={_('settingsbutton')}
onClick={menuButtonOnClick}
>
<FontAwesomeIcon icon={icons.menu} size="2x" />
</button>
</div>

{/* navigation */}
<Collapse isOpen={!smartphone || navExpanded} className="collapse-css-transition">
<div id="nav" role="navigation">
<Navigation
entriesPage={entriesPage}
setNavExpanded={setNavExpanded}
navSourcesExpanded={navSourcesExpanded}
setNavSourcesExpanded={setNavSourcesExpanded}
offlineState={offlineState}
allItemsCount={allItemsCount}
allItemsOfflineCount={allItemsOfflineCount}
unreadItemsCount={unreadItemsCount}
unreadItemsOfflineCount={unreadItemsOfflineCount}
starredItemsCount={starredItemsCount}
starredItemsOfflineCount={starredItemsOfflineCount}
sourcesState={sourcesState}
setSourcesState={setSourcesState}
sources={sources}
setSources={setSources}
tags={tags}
reloadAll={reloadAll}
/>
{/* navigation */}
<Collapse isOpen={!smartphone || navExpanded} className="collapse-css-transition">
<div id="nav" role="navigation">
<Navigation
entriesPage={entriesPage}
setNavExpanded={setNavExpanded}
navSourcesExpanded={navSourcesExpanded}
setNavSourcesExpanded={setNavSourcesExpanded}
offlineState={offlineState}
allItemsCount={allItemsCount}
allItemsOfflineCount={allItemsOfflineCount}
unreadItemsCount={unreadItemsCount}
unreadItemsOfflineCount={unreadItemsOfflineCount}
starredItemsCount={starredItemsCount}
starredItemsOfflineCount={starredItemsOfflineCount}
sourcesState={sourcesState}
setSourcesState={setSourcesState}
sources={sources}
setSources={setSources}
tags={tags}
reloadAll={reloadAll}
/>
</div>
</Collapse>

<ul id="search-list">
<SearchList />
</ul>

{/* content */}
<div id="content" role="main">
<Routes>
<Route
path="/"
element={
<Redirect to={`/${homePagePath.join('/')}`} />
}
/>
<Route
/* TODO: regex pattern does not work https://github.com/remix-run/react-router/issues/8254 */
path={ENTRIES_ROUTE_PATTERN}
element={
<EntriesPage
ref={entriesRef}
setNavExpanded={setNavExpanded}
configuration={configuration}
navSourcesExpanded={navSourcesExpanded}
setTitle={setTitle}
unreadItemsCount={unreadItemsCount}
/>
}
/>
<Route
path="/manage/sources"
element={
<SourcesPage />
}
/>
<Route
path="*"
element={
<NotFound />
}
/>
</Routes>
</div>
</Collapse>

<ul id="search-list">
<SearchList />
</ul>

{/* content */}
<div id="content" role="main">
<Switch>
<Route exact path="/">
<Redirect to={`/${homePagePath.join('/')}`} />
</Route>
<Route path={ENTRIES_ROUTE_PATTERN}>
{(routeProps) => (
<EntriesPage
{...routeProps}
ref={entriesRef}
setNavExpanded={setNavExpanded}
configuration={configuration}
navSourcesExpanded={navSourcesExpanded}
setTitle={setTitle}
unreadItemsCount={unreadItemsCount}
/>
)}
</Route>
<Route path="/manage/sources">
<SourcesPage />
</Route>
<Route path="*">
<NotFound />
</Route>
</Switch>
</div>
</CheckAuthorization>
</Route>
</Switch>
</CheckAuthorization>
}
/>
</Routes>
</React.StrictMode>
);
}
Expand Down
45 changes: 23 additions & 22 deletions assets/js/templates/EntriesPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function reloadList({
}

if (error instanceof HttpError && error.response.status === 403) {
selfoss.history.push('/sign/in', {
selfoss.navigage('/sign/in', {
error: selfoss.app._('error_session_expired')
});
return;
Expand Down Expand Up @@ -673,13 +673,6 @@ export default class StateHolder extends React.Component {
return params.category?.startsWith('source-') ? parseInt(params.category.replace(/^source-/, ''), 10) : null;
}

getActiveFilter() {
if (!this.props.match) {
return null;
}
return this.props.match.params.filter;
}

/**
* Mark all visible items as read
*/
Expand Down Expand Up @@ -721,8 +714,8 @@ export default class StateHolder extends React.Component {
// close opened entry and list
this.setExpandedEntries({});

if (ids.length !== 0 && this.props.match.filter === FilterType.UNREAD) {
markedEntries = markedEntries.filter(({ id }) => ids.includes(id));
if (this.entriesPageMatch.filter === FilterType.UNREAD) {
markedEntries = [];
}

this.setLoadingState(LoadingState.LOADING);
Expand All @@ -747,8 +740,10 @@ export default class StateHolder extends React.Component {
selfoss.dbOffline.enqueueStatuses(statuses);
}).catch((error) => {
if (error instanceof HttpError && error.response.status === 403) {
selfoss.history.push('/sign/in', {
error: selfoss.app._('error_session_expired')
selfoss.navigate('/sign/in', {
state: {
error: selfoss.app._('error_session_expired'),
},
});
return;
}
Expand Down Expand Up @@ -809,8 +804,10 @@ export default class StateHolder extends React.Component {
selfoss.dbOffline.enqueueStatus(id, 'unread', !markRead);
}).catch(function(error) {
if (error instanceof HttpError && error.response.status === 403) {
selfoss.history.push('/sign/in', {
error: selfoss.app._('error_session_expired')
selfoss.navigate('/sign/in', {
state: {
error: selfoss.app._('error_session_expired'),
},
});
return;
}
Expand Down Expand Up @@ -859,8 +856,10 @@ export default class StateHolder extends React.Component {
selfoss.dbOffline.enqueueStatus(id, 'starred', markStarred);
}).catch(function(error) {
if (error instanceof HttpError && error.response.status === 403) {
selfoss.history.push('/sign/in', {
error: selfoss.app._('error_session_expired')
selfoss.navigate('/sign/in', {
state: {
error: selfoss.app._('error_session_expired'),
},
});
return;
}
Expand All @@ -877,11 +876,14 @@ export default class StateHolder extends React.Component {
/**
* HACK: A counter that is increased every time reload action (r key) is triggered.
*/
selfoss.history.replace({
...this.props.location,
...makeEntriesLinkLocation(this.props.location, { id: null }),
state: forceReload(this.props.location),
});
selfoss.navigate(
{
...this.props.location,
...makeEntriesLinkLocation(this.props.location, { id: null }),
state: forceReload(this.props.location),
},
{ replace: true }
);
}

/**
Expand Down Expand Up @@ -1042,7 +1044,6 @@ export default class StateHolder extends React.Component {

StateHolder.propTypes = {
configuration: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
match: PropTypes.object.isRequired,
setNavExpanded: PropTypes.func.isRequired,
navSourcesExpanded: PropTypes.bool.isRequired,
Expand Down
Loading

0 comments on commit d341be2

Please sign in to comment.