From d06d7f81238972020bae1763db25e0de9a789c46 Mon Sep 17 00:00:00 2001 From: dudeami0 Date: Fri, 23 Jun 2023 14:27:35 -0400 Subject: [PATCH] Cache post listings and restore listing state when using browser back navigation buttons. --- src/shared/components/home/home.tsx | 50 ++++++++++++++++----- src/shared/services/HomeCacheService.ts | 60 +++++++++++++++++++++++++ src/shared/services/index.ts | 1 + 3 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 src/shared/services/HomeCacheService.ts diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 71e5842e..7fa942af 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -78,7 +78,12 @@ import { InitialFetchRequest, } from "../../interfaces"; import { mdToHtml } from "../../markdown"; -import { FirstLoadService, I18NextService, UserService } from "../../services"; +import { + FirstLoadService, + HomeCacheService, + I18NextService, + UserService, +} from "../../services"; import { HttpService, RequestState } from "../../services/HttpService"; import { setupTippy } from "../../tippy"; import { toast } from "../../toast"; @@ -278,9 +283,15 @@ export class Home extends Component { ?.content, isIsomorphic: true, }; + + HomeCacheService.postsRes = postsRes; } } + componentWillUnmount() { + HomeCacheService.activate(); + } + async componentDidMount() { if ( !this.state.isIsomorphic || @@ -650,6 +661,8 @@ export class Home extends Component { if (dataType === DataType.Post) { switch (this.state.postsRes?.state) { + case "empty": + return
; case "loading": return (
@@ -777,17 +790,30 @@ export class Home extends Component { const { dataType, page, listingType, sort } = getHomeQueryParams(); if (dataType === DataType.Post) { - this.setState({ postsRes: { state: "loading" } }); - this.setState({ - postsRes: await HttpService.client.getPosts({ - page, - limit: fetchLimit, - sort, - saved_only: false, - type_: listingType, - auth, - }), - }); + 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: await HttpService.client.getPosts({ + page, + limit: fetchLimit, + sort, + saved_only: false, + type_: listingType, + auth, + }), + }); + + HomeCacheService.postsRes = this.state.postsRes; + } } else { this.setState({ commentsRes: { state: "loading" } }); this.setState({ diff --git a/src/shared/services/HomeCacheService.ts b/src/shared/services/HomeCacheService.ts new file mode 100644 index 00000000..9f33dc4e --- /dev/null +++ b/src/shared/services/HomeCacheService.ts @@ -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 = { 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) { + 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(); + } +} diff --git a/src/shared/services/index.ts b/src/shared/services/index.ts index 5856245a..620293c4 100644 --- a/src/shared/services/index.ts +++ b/src/shared/services/index.ts @@ -1,5 +1,6 @@ export { FirstLoadService } from "./FirstLoadService"; export { HistoryService } from "./HistoryService"; +export { HomeCacheService } from "./HomeCacheService"; export { HttpService } from "./HttpService"; export { I18NextService } from "./I18NextService"; export { UserService } from "./UserService";