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";
?.content,
isIsomorphic: true,
};
+
+ HomeCacheService.postsRes = postsRes;
}
}
+ componentWillUnmount() {
+ HomeCacheService.activate();
+ }
+
async componentDidMount() {
if (
!this.state.isIsomorphic ||
if (dataType === DataType.Post) {
switch (this.state.postsRes?.state) {
+ case "empty":
+ return <div style="min-height: 20000px;"></div>;
case "loading":
return (
<h5>
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({
--- /dev/null
+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();
+ }
+}
export { FirstLoadService } from "./FirstLoadService";
export { HistoryService } from "./HistoryService";
+export { HomeCacheService } from "./HomeCacheService";
export { HttpService } from "./HttpService";
export { I18NextService } from "./I18NextService";
export { UserService } from "./UserService";