Skip to content

Commit 31a953c

Browse files
committed
wip: Switch to react-router 6
Currently broken because regex pattern support has been removed: remix-run/react-router#8254
1 parent d1366d8 commit 31a953c

13 files changed

+190
-328
lines changed

assets/js/selfoss-base.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ var selfoss = {
145145
if (selfoss.hasSession() || !configuration.authEnabled || configuration.publicMode) {
146146
selfoss.initUi();
147147
} else {
148-
selfoss.history.push('/sign/in');
148+
selfoss.navigate('/sign/in');
149149
}
150150
},
151151

@@ -228,7 +228,7 @@ var selfoss = {
228228
return login(credentials).then((data) => {
229229
if (data.success) {
230230
selfoss.setSession();
231-
selfoss.history.push('/');
231+
selfoss.navigate('/');
232232
// init offline if supported and not inited yet
233233
selfoss.dbOffline.init();
234234
selfoss.initUi();
@@ -247,7 +247,7 @@ var selfoss = {
247247
logout: function() {
248248
selfoss.clearSession();
249249
if (!document.body.classList.contains('publicmode')) {
250-
selfoss.history.push('/sign/in');
250+
selfoss.navigate('/sign/in');
251251
}
252252

253253
logout().catch((error) => {

assets/js/templates/App.jsx

+83-86
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import PropTypes from 'prop-types';
33
import nullable from 'prop-types-nullable';
44
import {
55
BrowserRouter as Router,
6-
Switch,
6+
Routes,
77
Route,
8-
Redirect,
9-
useHistory,
8+
Navigate,
109
useLocation,
11-
useRouteMatch,
10+
useMatch,
11+
useNavigate,
1212
} from 'react-router-dom';
1313
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
1414
import Collapse from '@kunukn/react-collapse';
@@ -140,10 +140,15 @@ function PureApp({
140140
}, []);
141141

142142
// TODO: move stuff that depends on this to the App.
143-
const history = useHistory();
143+
const navigate = useNavigate();
144144
React.useEffect(() => {
145-
selfoss.history = history;
146-
}, [history]);
145+
selfoss.navigate = navigate;
146+
}, [navigate]);
147+
148+
const entriesPageMatch = useMatch(ENTRIES_ROUTE_PATTERN);
149+
React.useEffect(() => {
150+
selfoss.entriesPageMatch = entriesPageMatch;
151+
}, [entriesPageMatch]);
147152

148153
// Prepare path of the homepage for redirecting from /
149154
let homePagePath = selfoss.config.homepage.split('/');
@@ -174,91 +179,83 @@ function PureApp({
174179
<React.Fragment>
175180
<Message message={globalMessage} />
176181

177-
<Switch>
178-
<Route path="/sign/in">
179-
{/* menu open for smartphone */}
180-
<div id="loginform" role="main">
181-
<LoginForm
182-
{...{offlineEnabled, setOfflineEnabled}}
183-
/>
184-
</div>
185-
</Route>
186-
187-
<Route path="/">
188-
<div id="nav-mobile" role="navigation">
189-
<div id="nav-mobile-logo">
190-
<div id="nav-mobile-count" className={classNames({'unread-count': true, offline: offlineState, online: !offlineState, unread: unreadItemsCount > 0})}>
191-
<span className={classNames({'offline-count': true, offline: offlineState, online: !offlineState, diff: unreadItemsCount !== unreadItemsOfflineCount && unreadItemsOfflineCount})}>{unreadItemsOfflineCount > 0 ? unreadItemsOfflineCount : ''}</span>
192-
<span className="count">{unreadItemsCount}</span>
193-
</div>
194-
</div>
195-
<button
196-
id="nav-mobile-settings"
197-
accessKey="t"
198-
aria-label={_('settingsbutton')}
199-
onClick={menuButtonOnClick}
200-
>
201-
<FontAwesomeIcon icon={icons.menu} size="2x" />
202-
</button>
203-
</div>
204-
205-
{/* navigation */}
206-
<Collapse isOpen={!smartphone || navExpanded} className="collapse-css-transition">
207-
<div id="nav" role="navigation">
208-
<Navigation
209-
entriesPage={entriesPage}
210-
setNavExpanded={setNavExpanded}
211-
navSourcesExpanded={navSourcesExpanded}
212-
setNavSourcesExpanded={setNavSourcesExpanded}
213-
offlineState={offlineState}
214-
allItemsCount={allItemsCount}
215-
allItemsOfflineCount={allItemsOfflineCount}
216-
unreadItemsCount={unreadItemsCount}
217-
unreadItemsOfflineCount={unreadItemsOfflineCount}
218-
starredItemsCount={starredItemsCount}
219-
starredItemsOfflineCount={starredItemsOfflineCount}
220-
sourcesState={sourcesState}
221-
setSourcesState={setSourcesState}
222-
sources={sources}
223-
setSources={setSources}
224-
tags={tags}
225-
reloadAll={reloadAll}
182+
<Routes>
183+
<Route
184+
path="/sign/in"
185+
element={
186+
/* menu open for smartphone */
187+
<div id="loginform" role="main">
188+
<LoginForm
189+
{...{offlineEnabled, setOfflineEnabled}}
226190
/>
227191
</div>
228-
</Collapse>
229-
230-
<ul id="search-list">
231-
<SearchList />
232-
</ul>
233-
234-
{/* content */}
235-
<div id="content" role="main">
236-
<Switch>
237-
<Route exact path="/">
238-
<Redirect to={`/${homePagePath.join('/')}`} />
239-
</Route>
240-
<Route path={ENTRIES_ROUTE_PATTERN}>
241-
{(routeProps) => (
242-
<EntriesPage
243-
{...routeProps}
244-
ref={entriesRef}
192+
}
193+
/>
194+
195+
<Route
196+
path="/"
197+
element={
198+
<React.Fragment>
199+
<div id="nav-mobile" role="navigation">
200+
<div id="nav-mobile-logo">
201+
<div id="nav-mobile-count" className={classNames({'unread-count': true, offline: offlineState, online: !offlineState, unread: unreadItemsCount > 0})}>
202+
<span className={classNames({'offline-count': true, offline: offlineState, online: !offlineState, diff: unreadItemsCount !== unreadItemsOfflineCount && unreadItemsOfflineCount})}>{unreadItemsOfflineCount > 0 ? unreadItemsOfflineCount : ''}</span>
203+
<span className="count">{unreadItemsCount}</span>
204+
</div>
205+
</div>
206+
<button
207+
id="nav-mobile-settings"
208+
accessKey="t"
209+
aria-label={_('settingsbutton')}
210+
onClick={menuButtonOnClick}
211+
>
212+
<FontAwesomeIcon icon={icons.menu} size="2x" />
213+
</button>
214+
</div>
215+
216+
{/* navigation */}
217+
<Collapse isOpen={!smartphone || navExpanded} className="collapse-css-transition">
218+
<div id="nav" role="navigation">
219+
<Navigation
220+
entriesPage={entriesPage}
245221
setNavExpanded={setNavExpanded}
246222
navSourcesExpanded={navSourcesExpanded}
247-
setTitle={setTitle}
223+
setNavSourcesExpanded={setNavSourcesExpanded}
224+
offlineState={offlineState}
225+
allItemsCount={allItemsCount}
226+
allItemsOfflineCount={allItemsOfflineCount}
248227
unreadItemsCount={unreadItemsCount}
228+
unreadItemsOfflineCount={unreadItemsOfflineCount}
229+
starredItemsCount={starredItemsCount}
230+
starredItemsOfflineCount={starredItemsOfflineCount}
231+
sourcesState={sourcesState}
232+
setSourcesState={setSourcesState}
233+
sources={sources}
234+
setSources={setSources}
235+
tags={tags}
236+
reloadAll={reloadAll}
237+
/>
238+
<Route
239+
/* TODO: regex pattern does not work https://github.com/remix-run/react-router/issues/8254 */
240+
path={ENTRIES_ROUTE_PATTERN}
241+
element={
242+
<EntriesPage
243+
ref={entriesRef}
244+
setNavExpanded={setNavExpanded}
245+
navSourcesExpanded={navSourcesExpanded}
246+
setTitle={setTitle}
247+
unreadItemsCount={unreadItemsCount}
248+
/>
249+
}
249250
/>
250-
)}
251-
</Route>
252-
<Route path="/manage/sources">
253-
<SourcesPage />
254-
</Route>
255-
<Route path="*">
256-
<NotFound />
257-
</Route>
258-
</Switch>
259-
</div>
260-
</Route>
261-
</Switch>
251+
<Route path="/manage/sources" element={<SourcesPage />} />
252+
<Route path="*" element={<NotFound />} />
253+
</Routes>
254+
</div>
255+
</React.Fragment>
256+
}
257+
/>
258+
</Routes>
262259
</React.Fragment>
263260
);
264261
}

assets/js/templates/EntriesPage.jsx

+22-21
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function reloadList({ fetchParams, abortController, append = false, waitForSync
103103
}
104104

105105
if (error instanceof HttpError && error.response.status === 403) {
106-
selfoss.history.push('/sign/in', {
106+
selfoss.navigage('/sign/in', {
107107
error: selfoss.app._('error_session_expired')
108108
});
109109
return;
@@ -613,13 +613,6 @@ export default class StateHolder extends React.Component {
613613
return params.category?.startsWith('source-') ? parseInt(params.category.replace(/^source-/, ''), 10) : null;
614614
}
615615

616-
getActiveFilter() {
617-
if (!this.props.match) {
618-
return null;
619-
}
620-
return this.props.match.params.filter;
621-
}
622-
623616
/**
624617
* Mark all visible items as read
625618
*/
@@ -661,8 +654,8 @@ export default class StateHolder extends React.Component {
661654
// close opened entry and list
662655
this.setExpandedEntries({});
663656

664-
if (ids.length !== 0 && this.props.match.filter === FilterType.UNREAD) {
665-
markedEntries = markedEntries.filter(({ id }) => ids.includes(id));
657+
if (this.entriesPageMatch.filter === FilterType.UNREAD) {
658+
markedEntries = [];
666659
}
667660

668661
this.setLoadingState(LoadingState.LOADING);
@@ -687,8 +680,10 @@ export default class StateHolder extends React.Component {
687680
selfoss.dbOffline.enqueueStatuses(statuses);
688681
}).catch((error) => {
689682
if (error instanceof HttpError && error.response.status === 403) {
690-
selfoss.history.push('/sign/in', {
691-
error: selfoss.app._('error_session_expired')
683+
selfoss.navigate('/sign/in', {
684+
state: {
685+
error: selfoss.app._('error_session_expired'),
686+
},
692687
});
693688
return;
694689
}
@@ -748,8 +743,10 @@ export default class StateHolder extends React.Component {
748743
selfoss.dbOffline.enqueueStatus(id, 'unread', !markRead);
749744
}).catch(function(error) {
750745
if (error instanceof HttpError && error.response.status === 403) {
751-
selfoss.history.push('/sign/in', {
752-
error: selfoss.app._('error_session_expired')
746+
selfoss.navigate('/sign/in', {
747+
state: {
748+
error: selfoss.app._('error_session_expired'),
749+
},
753750
});
754751
return;
755752
}
@@ -797,8 +794,10 @@ export default class StateHolder extends React.Component {
797794
selfoss.dbOffline.enqueueStatus(id, 'starred', markStarred);
798795
}).catch(function(error) {
799796
if (error instanceof HttpError && error.response.status === 403) {
800-
selfoss.history.push('/sign/in', {
801-
error: selfoss.app._('error_session_expired')
797+
selfoss.navigate('/sign/in', {
798+
state: {
799+
error: selfoss.app._('error_session_expired'),
800+
},
802801
});
803802
return;
804803
}
@@ -815,10 +814,13 @@ export default class StateHolder extends React.Component {
815814
/**
816815
* HACK: A counter that is increased every time reload action (r key) is triggered.
817816
*/
818-
selfoss.history.replace({
819-
...this.props.location,
820-
state: forceReload(this.props.location),
821-
});
817+
selfoss.navigate(
818+
{
819+
...this.props.location,
820+
state: forceReload(this.props.location),
821+
},
822+
{ replace: true }
823+
);
822824
}
823825

824826
render() {
@@ -841,7 +843,6 @@ export default class StateHolder extends React.Component {
841843
}
842844

843845
StateHolder.propTypes = {
844-
location: PropTypes.object.isRequired,
845846
match: PropTypes.object.isRequired,
846847
setNavExpanded: PropTypes.func.isRequired,
847848
navSourcesExpanded: PropTypes.bool.isRequired,

0 commit comments

Comments
 (0)