Cache post listings and restore listing state when using browser back navigation buttons.

This commit is contained in:
dudeami0 2023-06-23 14:27:35 -04:00 committed by Jay Sitter
parent 1ef245d4f2
commit 34e70f3128
3 changed files with 99 additions and 12 deletions

View file

@ -78,7 +78,12 @@ import {
InitialFetchRequest, InitialFetchRequest,
} from "../../interfaces"; } from "../../interfaces";
import { mdToHtml } from "../../markdown"; import { mdToHtml } from "../../markdown";
import { FirstLoadService, I18NextService, UserService } from "../../services"; import {
FirstLoadService,
HomeCacheService,
I18NextService,
UserService,
} from "../../services";
import { HttpService, RequestState } from "../../services/HttpService"; import { HttpService, RequestState } from "../../services/HttpService";
import { setupTippy } from "../../tippy"; import { setupTippy } from "../../tippy";
import { toast } from "../../toast"; import { toast } from "../../toast";
@ -278,9 +283,15 @@ export class Home extends Component<any, HomeState> {
?.content, ?.content,
isIsomorphic: true, isIsomorphic: true,
}; };
HomeCacheService.postsRes = postsRes;
} }
} }
componentWillUnmount() {
HomeCacheService.activate();
}
async componentDidMount() { async componentDidMount() {
if ( if (
!this.state.isIsomorphic || !this.state.isIsomorphic ||
@ -650,6 +661,8 @@ export class Home extends Component<any, HomeState> {
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
switch (this.state.postsRes?.state) { switch (this.state.postsRes?.state) {
case "empty":
return <div style="min-height: 20000px;"></div>;
case "loading": case "loading":
return ( return (
<h5> <h5>
@ -777,6 +790,16 @@ export class Home extends Component<any, HomeState> {
const { dataType, page, listingType, sort } = getHomeQueryParams(); const { dataType, page, listingType, sort } = getHomeQueryParams();
if (dataType === DataType.Post) { if (dataType === DataType.Post) {
if (HomeCacheService.active) {
const { postsRes, scrollY } = HomeCacheService;
HomeCacheService.deactivate();
this.setState({ postsRes });
window.scrollTo({
left: 0,
top: scrollY,
behavior: "instant",
});
} else {
this.setState({ postsRes: { state: "loading" } }); this.setState({ postsRes: { state: "loading" } });
this.setState({ this.setState({
postsRes: await HttpService.client.getPosts({ postsRes: await HttpService.client.getPosts({
@ -788,6 +811,9 @@ export class Home extends Component<any, HomeState> {
auth, auth,
}), }),
}); });
HomeCacheService.postsRes = this.state.postsRes;
}
} else { } else {
this.setState({ commentsRes: { state: "loading" } }); this.setState({ commentsRes: { state: "loading" } });
this.setState({ this.setState({

View file

@ -0,0 +1,60 @@
import { GetPostsResponse } from "lemmy-js-client";
import { RequestState } from "./HttpService.js";
/**
* Service to cache home post listings and restore home state when user uses the browser back buttons.
*/
export class HomeCacheService {
static #_instance: HomeCacheService;
historyIdx = 0;
scrollY = 0;
posts: RequestState<GetPostsResponse> = { state: "empty" };
get active() {
return (
this.historyIdx === window.history.state.idx + 1 &&
this.posts.state === "success"
);
}
deactivate() {
this.historyIdx = 0;
}
activate() {
this.scrollY = window.scrollY;
this.historyIdx = window.history.state.idx;
}
static get #Instance() {
return this.#_instance ?? (this.#_instance = new this());
}
public static get scrollY() {
return this.#Instance.scrollY;
}
public static get historyIdx() {
return this.#Instance.historyIdx;
}
public static set postsRes(posts: RequestState<GetPostsResponse>) {
this.#Instance.posts = posts;
}
public static get postsRes() {
return this.#Instance.posts;
}
public static get active() {
return this.#Instance.active;
}
public static deactivate() {
this.#Instance.deactivate();
}
public static activate() {
this.#Instance.activate();
}
}

View file

@ -1,5 +1,6 @@
export { FirstLoadService } from "./FirstLoadService"; export { FirstLoadService } from "./FirstLoadService";
export { HistoryService } from "./HistoryService"; export { HistoryService } from "./HistoryService";
export { HomeCacheService } from "./HomeCacheService";
export { HttpService } from "./HttpService"; export { HttpService } from "./HttpService";
export { I18NextService } from "./I18NextService"; export { I18NextService } from "./I18NextService";
export { UserService } from "./UserService"; export { UserService } from "./UserService";