showLocal,
updatePersonBlock,
} from "@utils/app";
-import { restoreScrollPosition, saveScrollPosition } from "@utils/browser";
import {
getPageFromString,
getQueryParams,
TransferCommunity,
} from "lemmy-js-client";
import { fetchLimit, relTags, trendingFetchLimit } from "../../config";
-import { i18n } from "../../i18next";
import {
CommentViewType,
DataType,
InitialFetchRequest,
} from "../../interfaces";
import { mdToHtml } from "../../markdown";
-import { UserService } from "../../services";
-import { FirstLoadService } from "../../services/FirstLoadService";
+import {
+ FirstLoadService,
+ HomeCacheService,
+ I18NextService,
+ UserService,
+} from "../../services";
import { HttpService, RequestState } from "../../services/HttpService";
import { setupTippy } from "../../tippy";
import { toast } from "../../toast";
showTrendingMobile: boolean;
showSidebarMobile: boolean;
subscribedCollapsed: boolean;
+ scrolled: boolean;
tagline?: string;
siteRes: GetSiteResponse;
finished: Map<CommentId, boolean | undefined>;
}
interface HomeProps {
- listingType: ListingType;
+ listingType?: ListingType;
dataType: DataType;
sort: SortType;
page: number;
return type ? DataType[type] : DataType.Post;
}
-function getListingTypeFromQuery(type?: string): ListingType {
+function getListingTypeFromQuery(type?: string): ListingType | undefined {
const myListingType =
UserService.Instance.myUserInfo?.local_user_view?.local_user
?.default_listing_type;
- return (type ? (type as ListingType) : myListingType) ?? "Local";
+ return type ? (type as ListingType) : myListingType;
}
function getSortTypeFromQuery(type?: string): SortType {
className="btn btn-secondary d-inline-block mb-2 me-3"
onClick={onClick}
>
- {i18n.t(textKey)}{" "}
+ {I18NextService.i18n.t(textKey)}{" "}
<Icon icon={show ? `minus-square` : `plus-square`} classes="icon-inline" />
</button>
);
translationKey: NoOptionI18nKeys;
}) => (
<Link className="btn btn-secondary d-block" to={path}>
- {i18n.t(translationKey)}
+ {I18NextService.i18n.t(translationKey)}
</Link>
);
postsRes: { state: "empty" },
commentsRes: { state: "empty" },
trendingCommunitiesRes: { state: "empty" },
+ scrolled: true,
siteRes: this.isoData.site_res,
showSubscribedMobile: false,
showTrendingMobile: false,
trendingCommunitiesRes,
commentsRes,
postsRes,
- tagline: getRandomFromList(this.state?.siteRes?.taglines ?? [])
- ?.content,
isIsomorphic: true,
};
+
+ HomeCacheService.postsRes = postsRes;
}
+
+ this.state.tagline = getRandomFromList(
+ this.state?.siteRes?.taglines ?? []
+ )?.content;
+ }
+
+ componentWillUnmount() {
+ HomeCacheService.activate();
}
async componentDidMount() {
setupTippy();
}
- componentWillUnmount() {
- saveScrollPosition(this.context);
- }
-
static async fetchInitialData({
client,
auth,
query: { dataType: urlDataType, listingType, page: urlPage, sort: urlSort },
+ site,
}: InitialFetchRequest<QueryParams<HomeProps>>): Promise<HomeData> {
const dataType = getDataTypeFromQuery(urlDataType);
-
- // TODO figure out auth default_listingType, default_sort_type
- const type_ = getListingTypeFromQuery(listingType);
+ const type_ =
+ getListingTypeFromQuery(listingType) ??
+ site.site_view.local_site.default_post_listing_type;
const sort = getSortTypeFromQuery(urlSort);
const page = urlPage ? Number(urlPage) : 1;
/>
{site_setup && (
<div className="row">
- <main role="main" className="col-12 col-md-8">
+ <main role="main" className="col-12 col-md-8 col-lg-9">
{tagline && (
<div
id="tagline"
<div className="d-block d-md-none">{this.mobileView}</div>
{this.posts}
</main>
- <aside className="d-none d-md-block col-md-4">
+ <aside className="d-none d-md-block col-md-4 col-lg-3">
{this.mySidebar}
</aside>
</div>
className="btn btn-sm text-muted"
onClick={linkEvent(this, this.handleCollapseSubscribe)}
aria-label={
- subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
+ subscribedCollapsed
+ ? I18NextService.i18n.t("expand")
+ : I18NextService.i18n.t("collapse")
}
data-tippy-content={
- subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
+ subscribedCollapsed
+ ? I18NextService.i18n.t("expand")
+ : I18NextService.i18n.t("collapse")
}
aria-expanded="true"
aria-controls="sidebarSubscribedBody"
search: getQueryString(queryParams),
});
+ if (!this.state.scrolled) {
+ this.setState({ scrolled: true });
+ setTimeout(() => window.scrollTo(0, 0), 0);
+ }
+
await this.fetchData();
}
const siteRes = this.state.siteRes;
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":
return (
<h5>
</div>
<div className="col-auto">
<ListingTypeSelect
- type_={listingType}
+ type_={
+ listingType ??
+ this.state.siteRes.site_view.local_site.default_post_listing_type
+ }
showLocal={showLocal(this.isoData)}
showSubscribed
onChange={this.handleListingTypeChange}
<div className="col-auto">
<SortSelect sort={sort} onChange={this.handleSortChange} />
</div>
- <div className="col-auto ps-0">{getRss(listingType)}</div>
+ <div className="col-auto ps-0">
+ {getRss(
+ listingType ??
+ this.state.siteRes.site_view.local_site.default_post_listing_type
+ )}
+ </div>
</div>
);
}
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({
});
}
- restoreScrollPosition(this.context);
setupTippy();
}
}
handlePageChange(page: number) {
+ this.setState({ scrolled: false });
this.updateUrl({ page });
- window.scrollTo(0, 0);
}
handleSortChange(val: SortType) {
+ this.setState({ scrolled: false });
this.updateUrl({ sort: val, page: 1 });
- window.scrollTo(0, 0);
}
handleListingTypeChange(val: ListingType) {
+ this.setState({ scrolled: false });
this.updateUrl({ listingType: val, page: 1 });
- window.scrollTo(0, 0);
}
handleDataTypeChange(val: DataType) {
+ this.setState({ scrolled: false });
this.updateUrl({ dataType: val, page: 1 });
- window.scrollTo(0, 0);
}
async handleAddModToCommunity(form: AddModToCommunity) {
async handleCommentReport(form: CreateCommentReport) {
const reportRes = await HttpService.client.createCommentReport(form);
if (reportRes.state == "success") {
- toast(i18n.t("report_created"));
+ toast(I18NextService.i18n.t("report_created"));
}
}
async handlePostReport(form: CreatePostReport) {
const reportRes = await HttpService.client.createPostReport(form);
if (reportRes.state == "success") {
- toast(i18n.t("report_created"));
+ toast(I18NextService.i18n.t("report_created"));
}
}
async handleTransferCommunity(form: TransferCommunity) {
await HttpService.client.transferCommunity(form);
- toast(i18n.t("transfer_community"));
+ toast(I18NextService.i18n.t("transfer_community"));
}
async handleCommentReplyRead(form: MarkCommentReplyAsRead) {
purgeItem(purgeRes: RequestState<PurgeItemResponse>) {
if (purgeRes.state == "success") {
- toast(i18n.t("purge_success"));
+ toast(I18NextService.i18n.t("purge_success"));
this.context.router.history.push(`/`);
}
}