Skip to content

Commit 859c31c

Browse files
authored
Merge pull request #6632 from WoltLab/63-skip-list-view-reload
Skip unnecessary list view reloads when only the URL hash changes
2 parents da76421 + 2095dc6 commit 859c31c

4 files changed

Lines changed: 130 additions & 90 deletions

File tree

ts/WoltLabSuite/Core/Component/GridView/State.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export class State extends EventTarget {
2525
readonly #selection: Selection;
2626
readonly #sorting: Sorting;
2727
readonly #gridViewFooter: HTMLElement;
28+
#lastUrl: string;
2829
#pageNo: number;
2930

3031
constructor(
@@ -75,6 +76,7 @@ export class State extends EventTarget {
7576
});
7677
}
7778

79+
this.#updateLastUrl();
7880
this.#updatePaginationUrl();
7981
this.#updateGridViewFooter();
8082
}
@@ -104,6 +106,7 @@ export class State extends EventTarget {
104106
this.#pagination.count = count;
105107
this.#updatePaginationUrl();
106108
this.#selection.refresh();
109+
this.#updateLastUrl();
107110

108111
if (cause === StateChangeCause.Change || cause === StateChangeCause.Pagination) {
109112
this.#updateQueryString();
@@ -124,26 +127,7 @@ export class State extends EventTarget {
124127
return;
125128
}
126129

127-
const url = new URL(this.#baseUrl);
128-
129-
const parameters: [string, string][] = [];
130-
if (this.#pageNo > 1) {
131-
parameters.push(["pageNo", this.#pageNo.toString()]);
132-
}
133-
134-
for (const parameter of this.#sorting.getQueryParameters()) {
135-
parameters.push(parameter);
136-
}
137-
138-
for (const parameter of this.#filter.getQueryParameters()) {
139-
parameters.push(parameter);
140-
}
141-
142-
if (parameters.length > 0) {
143-
url.search += url.search !== "" ? "&" : "?";
144-
url.search += new URLSearchParams(parameters).toString();
145-
}
146-
130+
const url = this.#getUrl();
147131
window.history.pushState({}, document.title, url.toString());
148132
}
149133

@@ -152,9 +136,18 @@ export class State extends EventTarget {
152136
return;
153137
}
154138

139+
const url = this.#getUrl(false);
140+
this.#pagination.url = url.toString();
141+
}
142+
143+
#getUrl(withPageNo: boolean = true): URL {
155144
const url = new URL(this.#baseUrl);
156145

157146
const parameters: [string, string][] = [];
147+
if (withPageNo && this.#pageNo > 1) {
148+
parameters.push(["pageNo", this.#pageNo.toString()]);
149+
}
150+
158151
for (const parameter of this.#sorting.getQueryParameters()) {
159152
parameters.push(parameter);
160153
}
@@ -168,27 +161,45 @@ export class State extends EventTarget {
168161
url.search += new URLSearchParams(parameters).toString();
169162
}
170163

171-
this.#pagination.url = url.toString();
164+
return url;
172165
}
173166

174167
#handlePopState(): void {
168+
const url = new URL(window.location.href);
169+
170+
if (this.#isOnlyHashChange(url)) {
171+
return;
172+
}
173+
175174
let pageNo = 1;
176175

177-
const { searchParams } = new URL(window.location.href);
178-
const value = searchParams.get("pageNo");
176+
const value = url.searchParams.get("pageNo");
179177
if (value !== null) {
180178
pageNo = parseInt(value);
181179
if (Number.isNaN(pageNo) || pageNo < 1) {
182180
pageNo = 1;
183181
}
184182
}
185183

186-
this.#filter.updateFromSearchParams(searchParams);
187-
this.#sorting.updateFromSearchParams(searchParams);
184+
this.#filter.updateFromSearchParams(url.searchParams);
185+
this.#sorting.updateFromSearchParams(url.searchParams);
188186

189187
this.#switchPage(pageNo, StateChangeCause.History);
190188
}
191189

190+
#updateLastUrl(): void {
191+
if (!this.#baseUrl) {
192+
return;
193+
}
194+
195+
const url = this.#getUrl();
196+
this.#lastUrl = url.pathname + url.search;
197+
}
198+
199+
#isOnlyHashChange(url: URL): boolean {
200+
return url.pathname + url.search === this.#lastUrl;
201+
}
202+
192203
#updateGridViewFooter(): void {
193204
const hasPagination = this.#pagination.count > 1;
194205
this.#gridViewFooter.hidden = !hasPagination && !this.#selection.selectionBarVisible();

ts/WoltLabSuite/Core/Component/ListView/State.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export class State extends EventTarget {
2828
readonly #selection: Selection;
2929
readonly #sorting: Sorting;
3030
readonly #listViewFooter: HTMLElement;
31+
#lastUrl: string;
3132
#pageNo: number;
3233

3334
constructor(
@@ -96,6 +97,7 @@ export class State extends EventTarget {
9697
);
9798
});
9899

100+
this.#updateLastUrl();
99101
this.#updatePaginationUrl();
100102
this.#updateListViewFooter();
101103
}
@@ -125,6 +127,7 @@ export class State extends EventTarget {
125127
this.#pagination.count = count;
126128
this.#updatePaginationUrl();
127129
this.#selection.refresh();
130+
this.#updateLastUrl();
128131

129132
if (cause === StateChangeCause.Change || cause === StateChangeCause.Pagination) {
130133
this.#updateQueryString();
@@ -145,26 +148,7 @@ export class State extends EventTarget {
145148
return;
146149
}
147150

148-
const url = new URL(this.#baseUrl);
149-
150-
const parameters: [string, string][] = [];
151-
if (this.#pageNo > 1) {
152-
parameters.push(["pageNo", this.#pageNo.toString()]);
153-
}
154-
155-
for (const parameter of this.#sorting.getQueryParameters()) {
156-
parameters.push(parameter);
157-
}
158-
159-
for (const parameter of this.#filter.getQueryParameters()) {
160-
parameters.push(parameter);
161-
}
162-
163-
if (parameters.length > 0) {
164-
url.search += url.search !== "" ? "&" : "?";
165-
url.search += new URLSearchParams(parameters).toString();
166-
}
167-
151+
const url = this.#getUrl();
168152
window.history.pushState({}, document.title, url.toString());
169153
}
170154

@@ -173,9 +157,18 @@ export class State extends EventTarget {
173157
return;
174158
}
175159

160+
const url = this.#getUrl(false);
161+
this.#pagination.url = url.toString();
162+
}
163+
164+
#getUrl(withPageNo: boolean = true): URL {
176165
const url = new URL(this.#baseUrl);
177166

178167
const parameters: [string, string][] = [];
168+
if (withPageNo && this.#pageNo > 1) {
169+
parameters.push(["pageNo", this.#pageNo.toString()]);
170+
}
171+
179172
for (const parameter of this.#sorting.getQueryParameters()) {
180173
parameters.push(parameter);
181174
}
@@ -189,27 +182,45 @@ export class State extends EventTarget {
189182
url.search += new URLSearchParams(parameters).toString();
190183
}
191184

192-
this.#pagination.url = url.toString();
185+
return url;
193186
}
194187

195188
#handlePopState(): void {
189+
const url = new URL(window.location.href);
190+
191+
if (this.#isOnlyHashChange(url)) {
192+
return;
193+
}
194+
196195
let pageNo = 1;
197196

198-
const { searchParams } = new URL(window.location.href);
199-
const value = searchParams.get("pageNo");
197+
const value = url.searchParams.get("pageNo");
200198
if (value !== null) {
201199
pageNo = parseInt(value);
202200
if (Number.isNaN(pageNo) || pageNo < 1) {
203201
pageNo = 1;
204202
}
205203
}
206204

207-
this.#filter.updateFromSearchParams(searchParams);
208-
this.#sorting.updateFromSearchParams(searchParams);
205+
this.#filter.updateFromSearchParams(url.searchParams);
206+
this.#sorting.updateFromSearchParams(url.searchParams);
209207

210208
this.#switchPage(pageNo, StateChangeCause.History);
211209
}
212210

211+
#updateLastUrl(): void {
212+
if (!this.#baseUrl) {
213+
return;
214+
}
215+
216+
const url = this.#getUrl();
217+
this.#lastUrl = url.pathname + url.search;
218+
}
219+
220+
#isOnlyHashChange(url: URL): boolean {
221+
return url.pathname + url.search === this.#lastUrl;
222+
}
223+
213224
#updateListViewFooter(): void {
214225
const hasPagination = this.#pagination.count > 1;
215226
this.#listViewFooter.hidden = !hasPagination && !this.#selection.selectionBarVisible();

wcfsetup/install/files/js/WoltLabSuite/Core/Component/GridView/State.js

Lines changed: 29 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)