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
parent d0a40f6690
commit d06d7f8123
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,17 +790,30 @@ 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) {
this.setState({ postsRes: { state: "loading" } }); if (HomeCacheService.active) {
this.setState({ const { postsRes, scrollY } = HomeCacheService;
postsRes: await HttpService.client.getPosts({ HomeCacheService.deactivate();
page, this.setState({ postsRes });
limit: fetchLimit, window.scrollTo({
sort, left: 0,
saved_only: false, top: scrollY,
type_: listingType, behavior: "instant",
auth, });
}), } else {
}); this.setState({ postsRes: { state: "loading" } });
this.setState({
postsRes: await HttpService.client.getPosts({
page,
limit: fetchLimit,
sort,
saved_only: false,
type_: listingType,
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";