"start": "yarn build:dev --watch"
},
"lint-staged": {
- "*.{ts,tsx,js}": ["prettier --write", "eslint --fix"],
- "*.{css, scss}": ["prettier --write"],
- "package.json": ["sortpack"]
+ "*.{ts,tsx,js}": [
+ "prettier --write",
+ "eslint --fix"
+ ],
+ "*.{css, scss}": [
+ "prettier --write"
+ ],
+ "package.json": [
+ "sortpack"
+ ]
},
"dependencies": {
"@babel/plugin-proposal-decorators": "^7.21.0",
ILemmyConfig,
InitialFetchRequest,
IsoDataOptionalSite,
+ RouteData,
} from "../shared/interfaces";
import { routes } from "../shared/routes";
-import {
- FailedRequestState,
- RequestState,
- wrapClient,
-} from "../shared/services/HttpService";
+import { FailedRequestState, wrapClient } from "../shared/services/HttpService";
import {
ErrorPageData,
favIconPngUrl,
// This bypasses errors, so that the client can hit the error on its own,
// in order to remove the jwt on the browser. Necessary for wrong jwts
let site: GetSiteResponse | undefined = undefined;
- let routeData: Record<string, RequestState<any>> = {};
+ let routeData: RouteData = {};
let errorPageData: ErrorPageData | undefined = undefined;
let try_site = await client.getSite(getSiteForm);
if (try_site.state === "failed" && try_site.msg == "not_logged_in") {
return res.redirect("/setup");
}
- if (site) {
+ if (site && activeRoute?.fetchInitialData) {
const initialFetchReq: InitialFetchRequest = {
client,
auth,
site,
};
- if (activeRoute?.fetchInitialData) {
- const routeDataKeysAndVals = await Promise.all(
- Object.entries(activeRoute.fetchInitialData(initialFetchReq)).map(
- async ([key, val]) => [key, await val]
- )
- );
-
- routeData = routeDataKeysAndVals.reduce((acc, [key, val]) => {
- acc[key] = val;
-
- return acc;
- }, {});
- }
+ routeData = await activeRoute.fetchInitialData(initialFetchReq);
}
} else if (try_site.state === "failed") {
errorPageData = getErrorPageData(new Error(try_site.msg), site);
trendingCommunitiesRes: ListCommunitiesResponse;
}>;
+function getRss(listingType: ListingType) {
+ const { sort } = getHomeQueryParams();
+ const auth = myAuth();
+
+ let rss: string | undefined = undefined;
+
+ switch (listingType) {
+ case "All": {
+ rss = `/feeds/all.xml?sort=${sort}`;
+ break;
+ }
+ case "Local": {
+ rss = `/feeds/local.xml?sort=${sort}`;
+ break;
+ }
+ case "Subscribed": {
+ rss = auth ? `/feeds/front/${auth}.xml?sort=${sort}` : undefined;
+ break;
+ }
+ }
+
+ return (
+ rss && (
+ <>
+ <a href={rss} rel={relTags} title="RSS">
+ <Icon icon="rss" classes="text-muted small" />
+ </a>
+ <link rel="alternate" type="application/atom+xml" href={rss} />
+ </>
+ )
+ );
+}
+
function getDataTypeFromQuery(type?: string): DataType {
return type ? DataType[type] : DataType.Post;
}
// Only fetch the data if coming from another route
if (FirstLoadService.isFirstLoad) {
- const {
- trendingCommunitiesRes: trendingCommunitiesRes,
- commentsRes: commentsRes,
- postsRes: postsRes,
- } = this.isoData.routeData;
+ const { trendingCommunitiesRes, commentsRes, postsRes } =
+ this.isoData.routeData;
this.state = {
...this.state,
></div>
)}
<div className="d-block d-md-none">{this.mobileView}</div>
- {this.posts()}
+ {this.posts}
</main>
<aside className="d-none d-md-block col-md-4">
{this.mySidebar}
await this.fetchData();
}
- posts() {
+ get posts() {
const { page } = getHomeQueryParams();
return (
const siteRes = this.state.siteRes;
if (dataType === DataType.Post) {
- switch (this.state.postsRes?.state) {
+ switch (this.state.postsRes.state) {
case "loading":
return (
<h5>
<span className="mr-2">
<SortSelect sort={sort} onChange={this.handleSortChange} />
</span>
- {this.getRss(listingType)}
+ {getRss(listingType)}
</div>
);
}
- getRss(listingType: ListingType) {
- const { sort } = getHomeQueryParams();
- const auth = myAuth();
-
- let rss: string | undefined = undefined;
-
- switch (listingType) {
- case "All": {
- rss = `/feeds/all.xml?sort=${sort}`;
- break;
- }
- case "Local": {
- rss = `/feeds/local.xml?sort=${sort}`;
- break;
- }
- case "Subscribed": {
- rss = auth ? `/feeds/front/${auth}.xml?sort=${sort}` : undefined;
- break;
- }
- }
-
- return (
- rss && (
- <>
- <a href={rss} rel={relTags} title="RSS">
- <Icon icon="rss" classes="text-muted small" />
- </a>
- <link rel="alternate" type="application/atom+xml" href={rss} />
- </>
- )
- );
- }
-
async fetchTrendingCommunities() {
this.setState({ trendingCommunitiesRes: { state: "loading" } });
this.setState({
}
type CreatePostData = RouteDataResponse<{
- communityResponse?: GetCommunityResponse;
+ communityResponse: GetCommunityResponse;
initialCommunitiesRes: ListCommunitiesResponse;
}>;
>): Promise<CreatePostData> {
const data: CreatePostData = {
initialCommunitiesRes: await fetchCommunitiesForOptions(client),
+ communityResponse: { state: "empty" },
};
if (communityId) {
/**
* This contains serialized data, it needs to be deserialized before use.
*/
-export interface IsoData<T extends Record<string, RequestState<any>> = any> {
+export interface IsoData<T extends RouteData = any> {
path: string;
routeData: T;
site_res: GetSiteResponse;
errorPageData?: ErrorPageData;
}
-export type IsoDataOptionalSite<
- T extends Record<string, RequestState<any>> = any
-> = Partial<IsoData<T>> &
+export type IsoDataOptionalSite<T extends RouteData = any> = Partial<
+ IsoData<T>
+> &
Pick<IsoData<T>, Exclude<keyof IsoData<T>, "site_res">>;
export interface ILemmyConfig {
children: Array<CommentNodeI>;
depth: number;
}
+
+export type RouteData = Record<string, RequestState<any>>;
import { Post } from "./components/post/post";
import { CreatePrivateMessage } from "./components/private_message/create-private-message";
import { Search } from "./components/search";
-import { InitialFetchRequest } from "./interfaces";
-import { RequestState } from "./services/HttpService";
+import { InitialFetchRequest, RouteData } from "./interfaces";
-interface IRoutePropsWithFetch<T extends Record<string, RequestState<any>>>
- extends IRouteProps {
- // TODO Make sure this one is good.
- fetchInitialData?(req: InitialFetchRequest): T;
+interface IRoutePropsWithFetch<T extends RouteData> extends IRouteProps {
+ fetchInitialData?(req: InitialFetchRequest): Promise<T>;
}
export const routes: IRoutePropsWithFetch<Record<string, any>>[] = [
import Toastify from "toastify-js";
import { getHttpBase } from "./env";
import { i18n, languages } from "./i18next";
-import { CommentNodeI, DataType, IsoData, VoteType } from "./interfaces";
+import {
+ CommentNodeI,
+ DataType,
+ IsoData,
+ RouteData,
+ VoteType,
+} from "./interfaces";
import { HttpService, UserService } from "./services";
import { RequestState } from "./services/HttpService";
return typeof window !== "undefined";
}
-export function setIsoData<T extends Record<string, RequestState<any>>>(
- context: any
-): IsoData<T> {
+export function setIsoData<T extends RouteData>(context: any): IsoData<T> {
// If its the browser, you need to deserialize the data from the window
if (isBrowser()) {
return window.isoData;