From feb4c434d1723a38a8991e1be0fc8ca5536d9b08 Mon Sep 17 00:00:00 2001 From: abias Date: Mon, 29 May 2023 20:40:00 -0400 Subject: [PATCH 1/3] Refactor route data --- src/server/index.tsx | 21 +++- .../components/community/communities.tsx | 20 +++- src/shared/components/community/community.tsx | 51 ++++---- src/shared/components/home/admin-settings.tsx | 38 +++--- src/shared/components/home/home.tsx | 48 ++++---- src/shared/components/home/instances.tsx | 24 ++-- src/shared/components/modlog.tsx | 69 ++++++----- src/shared/components/person/inbox.tsx | 107 +++++++++-------- src/shared/components/person/profile.tsx | 17 ++- .../person/registration-applications.tsx | 41 ++++--- src/shared/components/person/reports.tsx | 111 ++++++++++-------- src/shared/components/post/create-post.tsx | 29 +++-- src/shared/components/post/post.tsx | 41 ++++--- .../create-private-message.tsx | 26 ++-- src/shared/components/search.tsx | 95 +++++++++------ src/shared/interfaces.ts | 8 +- src/shared/routes.ts | 7 +- src/shared/utils.ts | 6 +- 18 files changed, 451 insertions(+), 308 deletions(-) diff --git a/src/server/index.tsx b/src/server/index.tsx index a93595e0..4ab4f76f 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -129,7 +129,7 @@ server.get("/*", async (req, res) => { // 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: any[] = []; + let routeData: Record = {}; let errorPageData: ErrorPageData | undefined; try { let try_site: any = await client.getSite(getSiteForm); @@ -160,18 +160,27 @@ server.get("/*", async (req, res) => { }; if (activeRoute?.fetchInitialData) { - routeData = await Promise.all([ - ...activeRoute.fetchInitialData(initialFetchReq), - ]); + 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; + }, {}); } } } catch (error) { errorPageData = getErrorPageData(error, site); } + const error = Object.values(routeData).find(val => val?.error)?.error; + // Redirect to the 404 if there's an API error - if (routeData[0] && routeData[0].error) { - const error = routeData[0].error; + if (error) { console.error(error); if (error === "instance_is_private") { return res.redirect(`/signup`); diff --git a/src/shared/components/community/communities.tsx b/src/shared/components/community/communities.tsx index 2e147b83..53e0e967 100644 --- a/src/shared/components/community/communities.tsx +++ b/src/shared/components/community/communities.tsx @@ -16,6 +16,7 @@ import { i18n } from "../../i18next"; import { WebSocketService } from "../../services"; import { QueryParams, + WithPromiseKeys, getPageFromString, getQueryParams, getQueryString, @@ -36,6 +37,10 @@ import { CommunityLink } from "./community-link"; const communityLimit = 50; +interface CommunitiesData { + listCommunitiesResponse: ListCommunitiesResponse; +} + interface CommunitiesState { listCommunitiesResponse?: ListCommunitiesResponse; loading: boolean; @@ -88,7 +93,7 @@ function refetch() { export class Communities extends Component { private subscription?: Subscription; - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); state: CommunitiesState = { loading: true, siteRes: this.isoData.site_res, @@ -105,10 +110,11 @@ export class Communities extends Component { // Only fetch the data if coming from another route if (this.isoData.path === this.context.router.route.match.url) { - const listRes = this.isoData.routeData[0] as ListCommunitiesResponse; + const { listCommunitiesResponse } = this.isoData.routeData; + this.state = { ...this.state, - listCommunitiesResponse: listRes, + listCommunitiesResponse, loading: false, }; } else { @@ -312,7 +318,9 @@ export class Communities extends Component { query: { listingType, page }, client, auth, - }: InitialFetchRequest>): Promise[] { + }: InitialFetchRequest< + QueryParams + >): WithPromiseKeys { const listCommunitiesForm: ListCommunities = { type_: getListingTypeFromQuery(listingType), sort: "TopMonth", @@ -321,7 +329,9 @@ export class Communities extends Component { auth: auth, }; - return [client.listCommunities(listCommunitiesForm)]; + return { + listCommunitiesResponse: client.listCommunities(listCommunitiesForm), + }; } parseMessage(msg: any) { diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index af562c19..f3ab1e21 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -33,6 +33,7 @@ import { import { UserService, WebSocketService } from "../../services"; import { QueryParams, + WithPromiseKeys, commentsToFlatNodes, communityRSSUrl, createCommentLikeRes, @@ -76,6 +77,12 @@ import { SiteSidebar } from "../home/site-sidebar"; import { PostListings } from "../post/post-listings"; import { CommunityLink } from "./community-link"; +interface CommunityData { + communityResponse: GetCommunityResponse; + postsResponse?: GetPostsResponse; + commentsResponse?: GetCommentsResponse; +} + interface State { communityRes?: GetCommunityResponse; communityLoading: boolean; @@ -115,7 +122,7 @@ export class Community extends Component< RouteComponentProps<{ name: string }>, State > { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: State = { communityLoading: true, @@ -137,23 +144,20 @@ export class Community extends Component< // Only fetch the data if coming from another route if (this.isoData.path == this.context.router.route.match.url) { + const { communityResponse, commentsResponse, postsResponse } = + this.isoData.routeData; + this.state = { ...this.state, - communityRes: this.isoData.routeData[0] as GetCommunityResponse, + communityRes: communityResponse, }; - const postsRes = this.isoData.routeData[1] as - | GetPostsResponse - | undefined; - const commentsRes = this.isoData.routeData[2] as - | GetCommentsResponse - | undefined; - if (postsRes) { - this.state = { ...this.state, posts: postsRes.posts }; + if (postsResponse) { + this.state = { ...this.state, posts: postsResponse.posts }; } - if (commentsRes) { - this.state = { ...this.state, comments: commentsRes.comments }; + if (commentsResponse) { + this.state = { ...this.state, comments: commentsResponse.comments }; } this.state = { @@ -189,16 +193,16 @@ export class Community extends Component< path, query: { dataType: urlDataType, page: urlPage, sort: urlSort }, auth, - }: InitialFetchRequest>): Promise[] { + }: InitialFetchRequest< + QueryParams + >): WithPromiseKeys { const pathSplit = path.split("/"); - const promises: Promise[] = []; const communityName = pathSplit[2]; const communityForm: GetCommunity = { name: communityName, auth, }; - promises.push(client.getCommunity(communityForm)); const dataType = getDataTypeFromQuery(urlDataType); @@ -206,6 +210,9 @@ export class Community extends Component< const page = getPageFromString(urlPage); + let postsResponse: Promise | undefined = undefined; + let commentsResponse: Promise | undefined = undefined; + if (dataType === DataType.Post) { const getPostsForm: GetPosts = { community_name: communityName, @@ -216,8 +223,8 @@ export class Community extends Component< saved_only: false, auth, }; - promises.push(client.getPosts(getPostsForm)); - promises.push(Promise.resolve()); + + postsResponse = client.getPosts(getPostsForm); } else { const getCommentsForm: GetComments = { community_name: communityName, @@ -228,11 +235,15 @@ export class Community extends Component< saved_only: false, auth, }; - promises.push(Promise.resolve()); - promises.push(client.getComments(getCommentsForm)); + + commentsResponse = client.getComments(getCommentsForm); } - return promises; + return { + communityResponse: client.getCommunity(communityForm), + commentsResponse, + postsResponse, + }; } get documentTitle(): string { diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index d266db58..4419cf36 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -2,7 +2,6 @@ import autosize from "autosize"; import { Component, linkEvent } from "inferno"; import { BannedPersonsResponse, - GetBannedPersons, GetFederatedInstancesResponse, GetSiteResponse, PersonView, @@ -16,6 +15,7 @@ import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; import { WebSocketService } from "../../services"; import { + WithPromiseKeys, capitalizeFirstLetter, isBrowser, myAuth, @@ -35,6 +35,11 @@ import RateLimitForm from "./rate-limit-form"; import { SiteForm } from "./site-form"; import { TaglineForm } from "./tagline-form"; +interface AdminSettingsData { + bannedPersonsResponse: BannedPersonsResponse; + federatedInstancesResponse: GetFederatedInstancesResponse; +} + interface AdminSettingsState { siteRes: GetSiteResponse; instancesRes?: GetFederatedInstancesResponse; @@ -45,7 +50,7 @@ interface AdminSettingsState { export class AdminSettings extends Component { private siteConfigTextAreaId = `site-config-${randomStr()}`; - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: AdminSettingsState = { siteRes: this.isoData.site_res, @@ -62,11 +67,13 @@ export class AdminSettings extends Component { // Only fetch the data if coming from another route if (this.isoData.path == this.context.router.route.match.url) { + const { bannedPersonsResponse, federatedInstancesResponse } = + this.isoData.routeData; + this.state = { ...this.state, - banned: (this.isoData.routeData[0] as BannedPersonsResponse).banned, - instancesRes: this.isoData - .routeData[1] as GetFederatedInstancesResponse, + banned: bannedPersonsResponse.banned, + instancesRes: federatedInstancesResponse, loading: false, }; } else { @@ -84,17 +91,16 @@ export class AdminSettings extends Component { } } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let promises: Promise[] = []; - - let auth = req.auth; - if (auth) { - let bannedPersonsForm: GetBannedPersons = { auth }; - promises.push(req.client.getBannedPersons(bannedPersonsForm)); - promises.push(req.client.getFederatedInstances({ auth })); - } - - return promises; + static fetchInitialData({ + auth, + client, + }: InitialFetchRequest): WithPromiseKeys { + return { + bannedPersonsResponse: client.getBannedPersons({ auth: auth as string }), + federatedInstancesResponse: client.getFederatedInstances({ + auth: auth as string, + }) as Promise, + }; } componentDidMount() { diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 52a82126..e85c3e66 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -69,6 +69,7 @@ import { toast, trendingFetchLimit, updatePersonBlock, + WithPromiseKeys, wsClient, wsSubscribe, } from "../../utils"; @@ -103,6 +104,12 @@ interface HomeProps { page: number; } +interface HomeData { + postsResponse?: GetPostsResponse; + commentsResponse?: GetCommentsResponse; + trendingResponse: ListCommunitiesResponse; +} + function getDataTypeFromQuery(type?: string): DataType { return type ? DataType[type] : DataType.Post; } @@ -237,7 +244,7 @@ function getRss(listingType: ListingType) { } export class Home extends Component { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: HomeState = { trendingCommunities: [], @@ -264,22 +271,15 @@ export class Home extends Component { // Only fetch the data if coming from another route if (this.isoData.path === this.context.router.route.match.url) { - const postsRes = this.isoData.routeData[0] as - | GetPostsResponse - | undefined; - const commentsRes = this.isoData.routeData[1] as - | GetCommentsResponse - | undefined; - const trendingRes = this.isoData.routeData[2] as - | ListCommunitiesResponse - | undefined; + const { trendingResponse, commentsResponse, postsResponse } = + this.isoData.routeData; - if (postsRes) { - this.state = { ...this.state, posts: postsRes.posts }; + if (postsResponse) { + this.state = { ...this.state, posts: postsResponse.posts }; } - if (commentsRes) { - this.state = { ...this.state, comments: commentsRes.comments }; + if (commentsResponse) { + this.state = { ...this.state, comments: commentsResponse.comments }; } if (isBrowser()) { @@ -290,7 +290,7 @@ export class Home extends Component { const taglines = this.state?.siteRes?.taglines ?? []; this.state = { ...this.state, - trendingCommunities: trendingRes?.communities ?? [], + trendingCommunities: trendingResponse?.communities ?? [], loading: false, tagline: getRandomFromList(taglines)?.content, }; @@ -317,7 +317,7 @@ export class Home extends Component { client, auth, query: { dataType: urlDataType, listingType, page: urlPage, sort: urlSort }, - }: InitialFetchRequest>): Promise[] { + }: InitialFetchRequest>): WithPromiseKeys { const dataType = getDataTypeFromQuery(urlDataType); // TODO figure out auth default_listingType, default_sort_type @@ -328,6 +328,9 @@ export class Home extends Component { const promises: Promise[] = []; + let postsResponse: Promise | undefined = undefined; + let commentsResponse: Promise | undefined = undefined; + if (dataType === DataType.Post) { const getPostsForm: GetPosts = { type_, @@ -338,8 +341,7 @@ export class Home extends Component { auth, }; - promises.push(client.getPosts(getPostsForm)); - promises.push(Promise.resolve()); + postsResponse = client.getPosts(getPostsForm); } else { const getCommentsForm: GetComments = { page, @@ -349,8 +351,8 @@ export class Home extends Component { saved_only: false, auth, }; - promises.push(Promise.resolve()); - promises.push(client.getComments(getCommentsForm)); + + commentsResponse = client.getComments(getCommentsForm); } const trendingCommunitiesForm: ListCommunities = { @@ -361,7 +363,11 @@ export class Home extends Component { }; promises.push(client.listCommunities(trendingCommunitiesForm)); - return promises; + return { + trendingResponse: client.listCommunities(trendingCommunitiesForm), + commentsResponse, + postsResponse, + }; } get documentTitle(): string { diff --git a/src/shared/components/home/instances.tsx b/src/shared/components/home/instances.tsx index 674374d0..fd1ed617 100644 --- a/src/shared/components/home/instances.tsx +++ b/src/shared/components/home/instances.tsx @@ -12,6 +12,7 @@ import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; import { WebSocketService } from "../../services"; import { + WithPromiseKeys, isBrowser, relTags, setIsoData, @@ -21,6 +22,10 @@ import { } from "../../utils"; import { HtmlTags } from "../common/html-tags"; +interface InstancesData { + federatedInstancesResponse: GetFederatedInstancesResponse; +} + interface InstancesState { siteRes: GetSiteResponse; instancesRes?: GetFederatedInstancesResponse; @@ -28,7 +33,7 @@ interface InstancesState { } export class Instances extends Component { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); state: InstancesState = { siteRes: this.isoData.site_res, loading: true, @@ -45,8 +50,7 @@ export class Instances extends Component { if (this.isoData.path == this.context.router.route.match.url) { this.state = { ...this.state, - instancesRes: this.isoData - .routeData[0] as GetFederatedInstancesResponse, + instancesRes: this.isoData.routeData.federatedInstancesResponse, loading: false, }; } else { @@ -54,12 +58,14 @@ export class Instances extends Component { } } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let promises: Promise[] = []; - - promises.push(req.client.getFederatedInstances({})); - - return promises; + static fetchInitialData({ + client, + }: InitialFetchRequest): WithPromiseKeys { + return { + federatedInstancesResponse: client.getFederatedInstances( + {} + ) as Promise, + }; } get documentTitle(): string { diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index ef28816b..cb4b37f4 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -39,6 +39,7 @@ import { WebSocketService } from "../services"; import { Choice, QueryParams, + WithPromiseKeys, amAdmin, amMod, debounce, @@ -83,6 +84,13 @@ type View = | AdminPurgePostView | AdminPurgeCommentView; +interface ModlogData { + modlogResponse: GetModlogResponse; + communityResponse?: GetCommunityResponse; + modUserResponse?: GetPersonDetailsResponse; + userResponse?: GetPersonDetailsResponse; +} + interface ModlogType { id: number; type_: ModlogActionType; @@ -642,7 +650,7 @@ export class Modlog extends Component< RouteComponentProps<{ communityId?: string }>, ModlogState > { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: ModlogState = { @@ -667,35 +675,35 @@ export class Modlog extends Component< // Only fetch the data if coming from another route if (this.isoData.path === this.context.router.route.match.url) { + const { + modlogResponse, + communityResponse, + modUserResponse, + userResponse, + } = this.isoData.routeData; + this.state = { ...this.state, - res: this.isoData.routeData[0] as GetModlogResponse, + res: modlogResponse, }; - const communityRes: GetCommunityResponse | undefined = - this.isoData.routeData[1]; - // Getting the moderators this.state = { ...this.state, - communityMods: communityRes?.moderators, + communityMods: communityResponse?.moderators, }; - const filteredModRes: GetPersonDetailsResponse | undefined = - this.isoData.routeData[2]; - if (filteredModRes) { + if (modUserResponse) { this.state = { ...this.state, - modSearchOptions: [personToChoice(filteredModRes.person_view)], + modSearchOptions: [personToChoice(modUserResponse.person_view)], }; } - const filteredUserRes: GetPersonDetailsResponse | undefined = - this.isoData.routeData[3]; - if (filteredUserRes) { + if (userResponse) { this.state = { ...this.state, - userSearchOptions: [personToChoice(filteredUserRes.person_view)], + userSearchOptions: [personToChoice(userResponse.person_view)], }; } @@ -986,9 +994,10 @@ export class Modlog extends Component< query: { modId: urlModId, page, userId: urlUserId, actionType }, auth, site, - }: InitialFetchRequest>): Promise[] { + }: InitialFetchRequest< + QueryParams + >): WithPromiseKeys { const pathSplit = path.split("/"); - const promises: Promise[] = []; const communityId = getIdFromString(pathSplit[2]); const modId = !site.site_view.local_site.hide_modlog_mod_names ? getIdFromString(urlModId) @@ -1005,41 +1014,47 @@ export class Modlog extends Component< auth, }; - promises.push(client.getModlog(modlogForm)); + let communityResponse: Promise | undefined = + undefined; if (communityId) { const communityForm: GetCommunity = { id: communityId, auth, }; - promises.push(client.getCommunity(communityForm)); - } else { - promises.push(Promise.resolve()); + + communityResponse = client.getCommunity(communityForm); } + let modUserResponse: Promise | undefined = + undefined; + if (modId) { const getPersonForm: GetPersonDetails = { person_id: modId, auth, }; - promises.push(client.getPersonDetails(getPersonForm)); - } else { - promises.push(Promise.resolve()); + modUserResponse = client.getPersonDetails(getPersonForm); } + let userResponse: Promise | undefined = undefined; + if (userId) { const getPersonForm: GetPersonDetails = { person_id: userId, auth, }; - promises.push(client.getPersonDetails(getPersonForm)); - } else { - promises.push(Promise.resolve()); + userResponse = client.getPersonDetails(getPersonForm); } - return promises; + return { + modlogResponse: client.getModlog(modlogForm), + communityResponse, + modUserResponse, + userResponse, + }; } parseMessage(msg: any) { diff --git a/src/shared/components/person/inbox.tsx b/src/shared/components/person/inbox.tsx index 8145ab62..6393fc62 100644 --- a/src/shared/components/person/inbox.tsx +++ b/src/shared/components/person/inbox.tsx @@ -29,6 +29,7 @@ import { i18n } from "../../i18next"; import { CommentViewType, InitialFetchRequest } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { + WithPromiseKeys, commentsToFlatNodes, createCommentLikeRes, editCommentRes, @@ -69,6 +70,13 @@ enum ReplyEnum { Mention, Message, } + +interface InboxData { + repliesResponse: GetRepliesResponse; + personMentionsResponse: GetPersonMentionsResponse; + privateMessagesResponse: PrivateMessagesResponse; +} + type ReplyType = { id: number; type_: ReplyEnum; @@ -90,7 +98,7 @@ interface InboxState { } export class Inbox extends Component { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: InboxState = { unreadOrAll: UnreadOrAll.Unread, @@ -115,17 +123,18 @@ export class Inbox extends Component { this.subscription = wsSubscribe(this.parseMessage); // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (this.isoData.path === this.context.router.route.match.url) { + const { + personMentionsResponse, + privateMessagesResponse, + repliesResponse, + } = this.isoData.routeData; + this.state = { ...this.state, - replies: - (this.isoData.routeData[0] as GetRepliesResponse).replies || [], - mentions: - (this.isoData.routeData[1] as GetPersonMentionsResponse).mentions || - [], - messages: - (this.isoData.routeData[2] as PrivateMessagesResponse) - .private_messages || [], + replies: repliesResponse.replies ?? [], + mentions: personMentionsResponse.mentions ?? [], + messages: privateMessagesResponse.private_messages ?? [], loading: false, }; this.state = { ...this.state, combined: this.buildCombined() }; @@ -481,53 +490,51 @@ export class Inbox extends Component { i.refetch(); } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let promises: Promise[] = []; + static fetchInitialData({ + auth, + client, + }: InitialFetchRequest): WithPromiseKeys { + const sort: CommentSortType = "New"; - let sort: CommentSortType = "New"; - let auth = req.auth; + // It can be /u/me, or /username/1 + const repliesForm: GetReplies = { + sort, + unread_only: true, + page: 1, + limit: fetchLimit, + auth: auth as string, + }; - if (auth) { - // It can be /u/me, or /username/1 - let repliesForm: GetReplies = { - sort: "New", - unread_only: true, - page: 1, - limit: fetchLimit, - auth, - }; - promises.push(req.client.getReplies(repliesForm)); + const personMentionsForm: GetPersonMentions = { + sort, + unread_only: true, + page: 1, + limit: fetchLimit, + auth: auth as string, + }; - let personMentionsForm: GetPersonMentions = { - sort, - unread_only: true, - page: 1, - limit: fetchLimit, - auth, - }; - promises.push(req.client.getPersonMentions(personMentionsForm)); + const privateMessagesForm: GetPrivateMessages = { + unread_only: true, + page: 1, + limit: fetchLimit, + auth: auth as string, + }; - let privateMessagesForm: GetPrivateMessages = { - unread_only: true, - page: 1, - limit: fetchLimit, - auth, - }; - promises.push(req.client.getPrivateMessages(privateMessagesForm)); - } - - return promises; + return { + privateMessagesResponse: client.getPrivateMessages(privateMessagesForm), + personMentionsResponse: client.getPersonMentions(personMentionsForm), + repliesResponse: client.getReplies(repliesForm), + }; } refetch() { - let sort = this.state.sort; - let unread_only = this.state.unreadOrAll == UnreadOrAll.Unread; - let page = this.state.page; - let limit = fetchLimit; - let auth = myAuth(); + const { sort, page, unreadOrAll } = this.state; + const unread_only = unreadOrAll === UnreadOrAll.Unread; + const limit = fetchLimit; + const auth = myAuth(); if (auth) { - let repliesForm: GetReplies = { + const repliesForm: GetReplies = { sort, unread_only, page, @@ -536,7 +543,7 @@ export class Inbox extends Component { }; WebSocketService.Instance.send(wsClient.getReplies(repliesForm)); - let personMentionsForm: GetPersonMentions = { + const personMentionsForm: GetPersonMentions = { sort, unread_only, page, @@ -547,7 +554,7 @@ export class Inbox extends Component { wsClient.getPersonMentions(personMentionsForm) ); - let privateMessagesForm: GetPrivateMessages = { + const privateMessagesForm: GetPrivateMessages = { unread_only, page, limit, diff --git a/src/shared/components/person/profile.tsx b/src/shared/components/person/profile.tsx index 42c7c306..00a44197 100644 --- a/src/shared/components/person/profile.tsx +++ b/src/shared/components/person/profile.tsx @@ -29,6 +29,7 @@ import { InitialFetchRequest, PersonDetailsView } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { QueryParams, + WithPromiseKeys, canMod, capitalizeFirstLetter, createCommentLikeRes, @@ -67,6 +68,10 @@ import { CommunityLink } from "../community/community-link"; import { PersonDetails } from "./person-details"; import { PersonListing } from "./person-listing"; +interface ProfileData { + personResponse: GetPersonDetailsResponse; +} + interface ProfileState { personRes?: GetPersonDetailsResponse; loading: boolean; @@ -152,7 +157,7 @@ export class Profile extends Component< RouteComponentProps<{ username: string }>, ProfileState > { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: ProfileState = { loading: true, @@ -175,7 +180,7 @@ export class Profile extends Component< if (this.isoData.path === this.context.router.route.match.url) { this.state = { ...this.state, - personRes: this.isoData.routeData[0] as GetPersonDetailsResponse, + personRes: this.isoData.routeData.personResponse, loading: false, }; } else { @@ -223,7 +228,9 @@ export class Profile extends Component< path, query: { page, sort, view: urlView }, auth, - }: InitialFetchRequest>): Promise[] { + }: InitialFetchRequest< + QueryParams + >): WithPromiseKeys { const pathSplit = path.split("/"); const username = pathSplit[2]; @@ -238,7 +245,9 @@ export class Profile extends Component< auth, }; - return [client.getPersonDetails(form)]; + return { + personResponse: client.getPersonDetails(form), + }; } componentDidMount() { diff --git a/src/shared/components/person/registration-applications.tsx b/src/shared/components/person/registration-applications.tsx index 39b65900..72ac5016 100644 --- a/src/shared/components/person/registration-applications.tsx +++ b/src/shared/components/person/registration-applications.tsx @@ -13,6 +13,7 @@ import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { + WithPromiseKeys, fetchLimit, isBrowser, myAuth, @@ -33,6 +34,10 @@ enum UnreadOrAll { All, } +interface RegistrationApplicationsData { + listRegistrationApplicationsResponse: ListRegistrationApplicationsResponse; +} + interface RegistrationApplicationsState { listRegistrationApplicationsResponse?: ListRegistrationApplicationsResponse; siteRes: GetSiteResponse; @@ -45,7 +50,7 @@ export class RegistrationApplications extends Component< any, RegistrationApplicationsState > { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: RegistrationApplicationsState = { siteRes: this.isoData.site_res, @@ -63,11 +68,11 @@ export class RegistrationApplications extends Component< this.subscription = wsSubscribe(this.parseMessage); // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (this.isoData.path === this.context.router.route.match.url) { this.state = { ...this.state, - listRegistrationApplicationsResponse: this.isoData - .routeData[0] as ListRegistrationApplicationsResponse, + listRegistrationApplicationsResponse: + this.isoData.routeData.listRegistrationApplicationsResponse, loading: false, }; } else { @@ -192,21 +197,21 @@ export class RegistrationApplications extends Component< this.refetch(); } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let promises: Promise[] = []; + static fetchInitialData({ + auth, + client, + }: InitialFetchRequest): WithPromiseKeys { + const form: ListRegistrationApplications = { + unread_only: true, + page: 1, + limit: fetchLimit, + auth: auth as string, + }; - let auth = req.auth; - if (auth) { - let form: ListRegistrationApplications = { - unread_only: true, - page: 1, - limit: fetchLimit, - auth, - }; - promises.push(req.client.listRegistrationApplications(form)); - } - - return promises; + return { + listRegistrationApplicationsResponse: + client.listRegistrationApplications(form), + }; } refetch() { diff --git a/src/shared/components/person/reports.tsx b/src/shared/components/person/reports.tsx index 3c00f545..51b41c92 100644 --- a/src/shared/components/person/reports.tsx +++ b/src/shared/components/person/reports.tsx @@ -22,6 +22,7 @@ import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { + WithPromiseKeys, amAdmin, fetchLimit, isBrowser, @@ -60,6 +61,12 @@ enum MessageEnum { PrivateMessageReport, } +interface ReportsData { + commentReportsResponse: ListCommentReportsResponse; + postReportsResponse: ListPostReportsResponse; + privateMessageReportsResponse?: ListPrivateMessageReportsResponse; +} + type ItemType = { id: number; type_: MessageEnum; @@ -80,7 +87,7 @@ interface ReportsState { } export class Reports extends Component { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: ReportsState = { unreadOrAll: UnreadOrAll.Unread, @@ -100,21 +107,20 @@ export class Reports extends Component { this.subscription = wsSubscribe(this.parseMessage); // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (this.isoData.path === this.context.router.route.match.url) { + const { + commentReportsResponse, + postReportsResponse, + privateMessageReportsResponse, + } = this.isoData.routeData; + this.state = { ...this.state, - listCommentReportsResponse: this.isoData - .routeData[0] as ListCommentReportsResponse, - listPostReportsResponse: this.isoData - .routeData[1] as ListPostReportsResponse, + listCommentReportsResponse: commentReportsResponse, + listPostReportsResponse: postReportsResponse, + listPrivateMessageReportsResponse: privateMessageReportsResponse, }; - if (amAdmin()) { - this.state = { - ...this.state, - listPrivateMessageReportsResponse: this.isoData - .routeData[2] as ListPrivateMessageReportsResponse, - }; - } + this.state = { ...this.state, combined: this.buildCombined(), @@ -432,73 +438,78 @@ export class Reports extends Component { i.refetch(); } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let promises: Promise[] = []; + static fetchInitialData({ + auth, + client, + }: InitialFetchRequest): WithPromiseKeys { + const unresolved_only = true; + const page = 1; + const limit = fetchLimit; - let unresolved_only = true; - let page = 1; - let limit = fetchLimit; - let auth = req.auth; + const commentReportsForm: ListCommentReports = { + unresolved_only, + page, + limit, + auth: auth as string, + }; - if (auth) { - let commentReportsForm: ListCommentReports = { + const postReportsForm: ListPostReports = { + unresolved_only, + page, + limit, + auth: auth as string, + }; + + const data: WithPromiseKeys = { + commentReportsResponse: client.listCommentReports(commentReportsForm), + postReportsResponse: client.listPostReports(postReportsForm), + }; + + if (amAdmin()) { + const privateMessageReportsForm: ListPrivateMessageReports = { unresolved_only, page, limit, - auth, + auth: auth as string, }; - promises.push(req.client.listCommentReports(commentReportsForm)); - let postReportsForm: ListPostReports = { - unresolved_only, - page, - limit, - auth, - }; - promises.push(req.client.listPostReports(postReportsForm)); - - if (amAdmin()) { - let privateMessageReportsForm: ListPrivateMessageReports = { - unresolved_only, - page, - limit, - auth, - }; - promises.push( - req.client.listPrivateMessageReports(privateMessageReportsForm) - ); - } + data.privateMessageReportsResponse = client.listPrivateMessageReports( + privateMessageReportsForm + ); } - return promises; + return data; } refetch() { - let unresolved_only = this.state.unreadOrAll == UnreadOrAll.Unread; - let page = this.state.page; - let limit = fetchLimit; - let auth = myAuth(); + const unresolved_only = this.state.unreadOrAll === UnreadOrAll.Unread; + const page = this.state.page; + const limit = fetchLimit; + const auth = myAuth(); + if (auth) { - let commentReportsForm: ListCommentReports = { + const commentReportsForm: ListCommentReports = { unresolved_only, page, limit, auth, }; + WebSocketService.Instance.send( wsClient.listCommentReports(commentReportsForm) ); - let postReportsForm: ListPostReports = { + const postReportsForm: ListPostReports = { unresolved_only, page, limit, auth, }; + WebSocketService.Instance.send(wsClient.listPostReports(postReportsForm)); if (amAdmin()) { - let privateMessageReportsForm: ListPrivateMessageReports = { + const privateMessageReportsForm: ListPrivateMessageReports = { unresolved_only, page, limit, diff --git a/src/shared/components/post/create-post.tsx b/src/shared/components/post/create-post.tsx index d8a2ccef..f43cbb07 100644 --- a/src/shared/components/post/create-post.tsx +++ b/src/shared/components/post/create-post.tsx @@ -16,6 +16,7 @@ import { WebSocketService } from "../../services"; import { Choice, QueryParams, + WithPromiseKeys, enableDownvotes, enableNsfw, getIdFromString, @@ -36,6 +37,10 @@ export interface CreatePostProps { communityId?: number; } +interface CreatePostData { + communityResponse?: GetCommunityResponse; +} + function getCreatePostQueryParams() { return getQueryParams({ communityId: getIdFromString, @@ -52,7 +57,7 @@ export class CreatePost extends Component< RouteComponentProps>, CreatePostState > { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: CreatePostState = { siteRes: this.isoData.site_res, @@ -71,14 +76,12 @@ export class CreatePost extends Component< // Only fetch the data if coming from another route if (this.isoData.path === this.context.router.route.match.url) { - const communityRes = this.isoData.routeData[0] as - | GetCommunityResponse - | undefined; + const { communityResponse } = this.isoData.routeData; - if (communityRes) { + if (communityResponse) { const communityChoice: Choice = { - label: communityRes.community_view.community.name, - value: communityRes.community_view.community.id.toString(), + label: communityResponse.community_view.community.name, + value: communityResponse.community_view.community.id.toString(), }; this.state = { @@ -206,8 +209,10 @@ export class CreatePost extends Component< client, query: { communityId }, auth, - }: InitialFetchRequest>): Promise[] { - const promises: Promise[] = []; + }: InitialFetchRequest< + QueryParams + >): WithPromiseKeys { + const data: WithPromiseKeys = {}; if (communityId) { const form: GetCommunity = { @@ -215,12 +220,10 @@ export class CreatePost extends Component< id: getIdFromString(communityId), }; - promises.push(client.getCommunity(form)); - } else { - promises.push(Promise.resolve()); + data.communityResponse = client.getCommunity(form); } - return promises; + return data; } parseMessage(msg: any) { diff --git a/src/shared/components/post/post.tsx b/src/shared/components/post/post.tsx index 96d7911e..fc8245de 100644 --- a/src/shared/components/post/post.tsx +++ b/src/shared/components/post/post.tsx @@ -60,6 +60,7 @@ import { toast, trendingFetchLimit, updatePersonBlock, + WithPromiseKeys, wsClient, wsSubscribe, } from "../../utils"; @@ -72,6 +73,11 @@ import { PostListing } from "./post-listing"; const commentsShownInterval = 15; +interface PostData { + postResponse: GetPostResponse; + commentsResponse: GetCommentsResponse; +} + interface PostState { postId?: number; commentId?: number; @@ -91,7 +97,7 @@ interface PostState { export class Post extends Component { private subscription?: Subscription; - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private commentScrollDebounced: () => void; state: PostState = { postId: getIdFromProps(this.props), @@ -115,11 +121,13 @@ export class Post extends Component { this.state = { ...this.state, commentSectionRef: createRef() }; // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (this.isoData.path === this.context.router.route.match.url) { + const { commentsResponse, postResponse } = this.isoData.routeData; + this.state = { ...this.state, - postRes: this.isoData.routeData[0] as GetPostResponse, - commentsRes: this.isoData.routeData[1] as GetCommentsResponse, + postRes: postResponse, + commentsRes: commentsResponse, }; if (this.state.commentsRes) { @@ -197,19 +205,18 @@ export class Post extends Component { } } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let pathSplit = req.path.split("/"); - let promises: Promise[] = []; + static fetchInitialData(req: InitialFetchRequest): WithPromiseKeys { + const pathSplit = req.path.split("/"); - let pathType = pathSplit.at(1); - let id = pathSplit.at(2) ? Number(pathSplit.at(2)) : undefined; - let auth = req.auth; + const pathType = pathSplit.at(1); + const id = pathSplit.at(2) ? Number(pathSplit.at(2)) : undefined; + const auth = req.auth; - let postForm: GetPost = { + const postForm: GetPost = { auth, }; - let commentsForm: GetComments = { + const commentsForm: GetComments = { max_depth: commentTreeMaxDepth, sort: "Hot", type_: "All", @@ -218,7 +225,7 @@ export class Post extends Component { }; // Set the correct id based on the path type - if (pathType == "post") { + if (pathType === "post") { postForm.id = id; commentsForm.post_id = id; } else { @@ -226,10 +233,10 @@ export class Post extends Component { commentsForm.parent_id = id; } - promises.push(req.client.getPost(postForm)); - promises.push(req.client.getComments(commentsForm)); - - return promises; + return { + postResponse: req.client.getPost(postForm), + commentsResponse: req.client.getComments(commentsForm), + }; } componentWillUnmount() { diff --git a/src/shared/components/private_message/create-private-message.tsx b/src/shared/components/private_message/create-private-message.tsx index 327386cb..c897c44e 100644 --- a/src/shared/components/private_message/create-private-message.tsx +++ b/src/shared/components/private_message/create-private-message.tsx @@ -12,6 +12,7 @@ import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; import { WebSocketService } from "../../services"; import { + WithPromiseKeys, getRecipientIdFromProps, isBrowser, myAuth, @@ -24,6 +25,10 @@ import { HtmlTags } from "../common/html-tags"; import { Spinner } from "../common/icon"; import { PrivateMessageForm } from "./private-message-form"; +interface CreatePrivateMessageData { + recipientDetailsResponse: GetPersonDetailsResponse; +} + interface CreatePrivateMessageState { siteRes: GetSiteResponse; recipientDetailsRes?: GetPersonDetailsResponse; @@ -35,7 +40,7 @@ export class CreatePrivateMessage extends Component< any, CreatePrivateMessageState > { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: CreatePrivateMessageState = { siteRes: this.isoData.site_res, @@ -52,11 +57,10 @@ export class CreatePrivateMessage extends Component< this.subscription = wsSubscribe(this.parseMessage); // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (this.isoData.path === this.context.router.route.match.url) { this.state = { ...this.state, - recipientDetailsRes: this.isoData - .routeData[0] as GetPersonDetailsResponse, + recipientDetailsRes: this.isoData.routeData.recipientDetailsResponse, loading: false, }; } else { @@ -74,15 +78,21 @@ export class CreatePrivateMessage extends Component< WebSocketService.Instance.send(wsClient.getPersonDetails(form)); } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let person_id = Number(req.path.split("/").pop()); - let form: GetPersonDetails = { + static fetchInitialData( + req: InitialFetchRequest + ): WithPromiseKeys { + const person_id = Number(req.path.split("/").pop()); + + const form: GetPersonDetails = { person_id, sort: "New", saved_only: false, auth: req.auth, }; - return [req.client.getPersonDetails(form)]; + + return { + recipientDetailsResponse: req.client.getPersonDetails(form), + }; } get documentTitle(): string { diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx index 9f762785..c62c7a98 100644 --- a/src/shared/components/search.tsx +++ b/src/shared/components/search.tsx @@ -32,6 +32,7 @@ import { WebSocketService } from "../services"; import { Choice, QueryParams, + WithPromiseKeys, capitalizeFirstLetter, commentsToFlatNodes, communityToChoice, @@ -80,6 +81,14 @@ interface SearchProps { page: number; } +interface SearchData { + communityResponse?: GetCommunityResponse; + listCommunitiesResponse?: ListCommunitiesResponse; + creatorDetailsResponse?: GetPersonDetailsResponse; + searchResponse?: SearchResponse; + resolveObjectResponse?: ResolveObjectResponse; +} + type FilterType = "creator" | "community"; interface SearchState { @@ -237,7 +246,7 @@ function getListing( } export class Search extends Component { - private isoData = setIsoData(this.context); + private isoData = setIsoData(this.context); private subscription?: Subscription; state: SearchState = { searchLoading: false, @@ -271,45 +280,44 @@ export class Search extends Component { // Only fetch the data if coming from another route if (this.isoData.path === this.context.router.route.match.url) { - const communityRes = this.isoData.routeData[0] as - | GetCommunityResponse - | undefined; - const communitiesRes = this.isoData.routeData[1] as - | ListCommunitiesResponse - | undefined; + const { + communityResponse, + creatorDetailsResponse, + listCommunitiesResponse, + resolveObjectResponse, + searchResponse, + } = this.isoData.routeData; + // This can be single or multiple communities given - if (communitiesRes) { + if (listCommunitiesResponse) { this.state = { ...this.state, - communities: communitiesRes.communities, + communities: listCommunitiesResponse.communities, }; } - if (communityRes) { + if (communityResponse) { this.state = { ...this.state, - communities: [communityRes.community_view], + communities: [communityResponse.community_view], communitySearchOptions: [ - communityToChoice(communityRes.community_view), + communityToChoice(communityResponse.community_view), ], }; } - const creatorRes = this.isoData.routeData[2] as GetPersonDetailsResponse; - this.state = { ...this.state, - creatorDetails: creatorRes, - creatorSearchOptions: creatorRes - ? [personToChoice(creatorRes.person_view)] + creatorDetails: creatorDetailsResponse, + creatorSearchOptions: creatorDetailsResponse + ? [personToChoice(creatorDetailsResponse.person_view)] : [], }; if (q !== "") { this.state = { ...this.state, - searchResponse: this.isoData.routeData[3] as SearchResponse, - resolveObjectResponse: this.isoData - .routeData[4] as ResolveObjectResponse, + searchResponse, + resolveObjectResponse, searchLoading: false, }; } else { @@ -342,17 +350,21 @@ export class Search extends Component { client, auth, query: { communityId, creatorId, q, type, sort, listingType, page }, - }: InitialFetchRequest>): Promise[] { - const promises: Promise[] = []; - + }: InitialFetchRequest< + QueryParams + >): WithPromiseKeys { const community_id = getIdFromString(communityId); + let communityResponse: Promise | undefined = + undefined; + let listCommunitiesResponse: Promise | undefined = + undefined; if (community_id) { const getCommunityForm: GetCommunity = { id: community_id, auth, }; - promises.push(client.getCommunity(getCommunityForm)); - promises.push(Promise.resolve()); + + communityResponse = client.getCommunity(getCommunityForm); } else { const listCommunitiesForm: ListCommunities = { type_: defaultListingType, @@ -360,23 +372,29 @@ export class Search extends Component { limit: fetchLimit, auth, }; - promises.push(Promise.resolve()); - promises.push(client.listCommunities(listCommunitiesForm)); + + listCommunitiesResponse = client.listCommunities(listCommunitiesForm); } const creator_id = getIdFromString(creatorId); + let creatorDetailsResponse: Promise | undefined = + undefined; if (creator_id) { const getCreatorForm: GetPersonDetails = { person_id: creator_id, auth, }; - promises.push(client.getPersonDetails(getCreatorForm)); - } else { - promises.push(Promise.resolve()); + + creatorDetailsResponse = client.getPersonDetails(getCreatorForm); } const query = getSearchQueryFromQuery(q); + let searchResponse: Promise | undefined = undefined; + let resolveObjectResponse: + | Promise + | undefined = undefined; + if (query) { const form: SearchForm = { q: query, @@ -391,21 +409,26 @@ export class Search extends Component { }; if (query !== "") { - promises.push(client.search(form)); + searchResponse = client.search(form); if (auth) { const resolveObjectForm: ResolveObject = { q: query, auth, }; - promises.push(client.resolveObject(resolveObjectForm)); + resolveObjectResponse = client + .resolveObject(resolveObjectForm) + .catch(() => undefined); } - } else { - promises.push(Promise.resolve()); - promises.push(Promise.resolve()); } } - return promises; + return { + communityResponse, + creatorDetailsResponse, + listCommunitiesResponse, + resolveObjectResponse, + searchResponse, + }; } get documentTitle(): string { diff --git a/src/shared/interfaces.ts b/src/shared/interfaces.ts index a6b2ae47..dc4490cb 100644 --- a/src/shared/interfaces.ts +++ b/src/shared/interfaces.ts @@ -5,15 +5,15 @@ import { ErrorPageData } from "./utils"; /** * This contains serialized data, it needs to be deserialized before use. */ -export interface IsoData { +export interface IsoData { path: string; - routeData: any[]; + routeData: T; site_res: GetSiteResponse; errorPageData?: ErrorPageData; } -export type IsoDataOptionalSite = Partial & - Pick>; +export type IsoDataOptionalSite = Partial> & + Pick, Exclude, "site_res">>; export interface ILemmyConfig { wsHost?: string; diff --git a/src/shared/routes.ts b/src/shared/routes.ts index b5c28189..81771d03 100644 --- a/src/shared/routes.ts +++ b/src/shared/routes.ts @@ -22,13 +22,14 @@ 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 { WithPromiseKeys } from "./utils"; -interface IRoutePropsWithFetch extends IRouteProps { +interface IRoutePropsWithFetch extends IRouteProps { // TODO Make sure this one is good. - fetchInitialData?(req: InitialFetchRequest): Promise[]; + fetchInitialData?(req: InitialFetchRequest): WithPromiseKeys; } -export const routes: IRoutePropsWithFetch[] = [ +export const routes: IRoutePropsWithFetch>[] = [ { path: `/`, component: Home, diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 5648df00..fe83977d 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -1262,7 +1262,7 @@ export function isBrowser() { return typeof window !== "undefined"; } -export function setIsoData(context: any): IsoData { +export function setIsoData(context: any): IsoData { // If its the browser, you need to deserialize the data from the window if (isBrowser()) { return window.isoData; @@ -1557,6 +1557,10 @@ export type QueryParams> = { [key in keyof T]?: string; }; +export type WithPromiseKeys = { + [K in keyof T]: Promise; +}; + export function getQueryParams>(processors: { [K in keyof T]: (param: string) => T[K]; }): T { From 2a16c85ed028c7e08f3b6612e0ffce908f96b7f2 Mon Sep 17 00:00:00 2001 From: abias Date: Thu, 15 Jun 2023 22:39:04 -0400 Subject: [PATCH 2/3] Cleanup --- src/shared/components/community/community.tsx | 49 +++++------------ src/shared/components/home/admin-settings.tsx | 13 ++--- src/shared/components/home/home.tsx | 54 +++++++++---------- src/shared/components/home/instances.tsx | 8 +-- src/shared/components/modlog.tsx | 47 +++++++--------- src/shared/components/person/inbox.tsx | 18 +++---- src/shared/components/person/reports.tsx | 27 +++++----- src/shared/components/post/create-post.tsx | 14 ++--- src/shared/components/search.tsx | 38 ++++++------- src/shared/utils.ts | 2 +- 10 files changed, 114 insertions(+), 156 deletions(-) diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index e8412e76..6b4eecff 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -102,9 +102,9 @@ import { PostListings } from "../post/post-listings"; import { CommunityLink } from "./community-link"; type CommunityData = RouteDataResponse<{ - communityResponse: GetCommunityResponse; - postsResponse?: GetPostsResponse; - commentsResponse?: GetCommentsResponse; + communityRes: GetCommunityResponse; + postsRes: GetPostsResponse; + commentsRes: GetCommentsResponse; }>; interface State { @@ -201,37 +201,15 @@ export class Community extends Component< // Only fetch the data if coming from another route if (FirstLoadService.isFirstLoad) { - const { - communityResponse: communityRes, - commentsResponse: commentsRes, - postsResponse: postsRes, - } = this.isoData.routeData; + const { communityRes, commentsRes, postsRes } = this.isoData.routeData; this.state = { ...this.state, isIsomorphic: true, + commentsRes, + communityRes, + postsRes, }; - - if (communityRes.state === "success") { - this.state = { - ...this.state, - communityRes, - }; - } - - if (postsRes?.state === "success") { - this.state = { - ...this.state, - postsRes, - }; - } - - if (commentsRes?.state === "success") { - this.state = { - ...this.state, - commentsRes, - }; - } } } @@ -279,9 +257,10 @@ export class Community extends Component< const page = getPageFromString(urlPage); - let postsResponse: RequestState | undefined = undefined; - let commentsResponse: RequestState | undefined = - undefined; + let postsResponse: RequestState = { state: "empty" }; + let commentsResponse: RequestState = { + state: "empty", + }; if (dataType === DataType.Post) { const getPostsForm: GetPosts = { @@ -310,9 +289,9 @@ export class Community extends Component< } return { - communityResponse: await client.getCommunity(communityForm), - commentsResponse, - postsResponse, + communityRes: await client.getCommunity(communityForm), + commentsRes: commentsResponse, + postsRes: postsResponse, }; } diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index 11be7257..91ba727f 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -34,8 +34,8 @@ import { SiteForm } from "./site-form"; import { TaglineForm } from "./tagline-form"; type AdminSettingsData = RouteDataResponse<{ - bannedPersonsResponse: BannedPersonsResponse; - federatedInstancesResponse: GetFederatedInstancesResponse; + bannedRes: BannedPersonsResponse; + instancesRes: GetFederatedInstancesResponse; }>; interface AdminSettingsState { @@ -72,10 +72,7 @@ export class AdminSettings extends Component { // Only fetch the data if coming from another route if (FirstLoadService.isFirstLoad) { - const { - bannedPersonsResponse: bannedRes, - federatedInstancesResponse: instancesRes, - } = this.isoData.routeData; + const { bannedRes, instancesRes } = this.isoData.routeData; this.state = { ...this.state, @@ -91,10 +88,10 @@ export class AdminSettings extends Component { client, }: InitialFetchRequest): Promise { return { - bannedPersonsResponse: await client.getBannedPersons({ + bannedRes: await client.getBannedPersons({ auth: auth as string, }), - federatedInstancesResponse: await client.getFederatedInstances({ + instancesRes: await client.getFederatedInstances({ auth: auth as string, }), }; diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 3daaa4fd..4dc797ce 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -119,9 +119,9 @@ interface HomeProps { } type HomeData = RouteDataResponse<{ - postsResponse?: GetPostsResponse; - commentsResponse?: GetCommentsResponse; - trendingResponse: ListCommunitiesResponse; + postsRes: GetPostsResponse; + commentsRes: GetCommentsResponse; + trendingCommunitiesRes: ListCommunitiesResponse; }>; function getDataTypeFromQuery(type?: string): DataType { @@ -236,37 +236,30 @@ export class Home extends Component { // Only fetch the data if coming from another route if (FirstLoadService.isFirstLoad) { const { - trendingResponse: trendingCommunitiesRes, - commentsResponse: commentsRes, - postsResponse: postsRes, + trendingCommunitiesRes: trendingCommunitiesRes, + commentsRes: commentsRes, + postsRes: postsRes, } = this.isoData.routeData; this.state = { ...this.state, trendingCommunitiesRes, + commentsRes, + postsRes, tagline: getRandomFromList(this.state?.siteRes?.taglines ?? []) ?.content, isIsomorphic: true, }; - - if (commentsRes?.state === "success") { - this.state = { - ...this.state, - commentsRes, - }; - } - - if (postsRes?.state === "success") { - this.state = { - ...this.state, - postsRes, - }; - } } } async componentDidMount() { - if (!this.state.isIsomorphic || !this.isoData.routeData.length) { + if ( + !this.state.isIsomorphic || + !Object.values(this.isoData.routeData).some( + res => res.state === "success" || res.state === "failed" + ) + ) { await Promise.all([this.fetchTrendingCommunities(), this.fetchData()]); } @@ -290,9 +283,10 @@ export class Home extends Component { const page = urlPage ? Number(urlPage) : 1; - let postsResponse: RequestState | undefined = undefined; - let commentsResponse: RequestState | undefined = - undefined; + let postsRes: RequestState = { state: "empty" }; + let commentsRes: RequestState = { + state: "empty", + }; if (dataType === DataType.Post) { const getPostsForm: GetPosts = { @@ -304,7 +298,7 @@ export class Home extends Component { auth, }; - postsResponse = await client.getPosts(getPostsForm); + postsRes = await client.getPosts(getPostsForm); } else { const getCommentsForm: GetComments = { page, @@ -315,7 +309,7 @@ export class Home extends Component { auth, }; - commentsResponse = await client.getComments(getCommentsForm); + commentsRes = await client.getComments(getCommentsForm); } const trendingCommunitiesForm: ListCommunities = { @@ -326,9 +320,11 @@ export class Home extends Component { }; return { - trendingResponse: await client.listCommunities(trendingCommunitiesForm), - commentsResponse, - postsResponse, + trendingCommunitiesRes: await client.listCommunities( + trendingCommunitiesForm + ), + commentsRes, + postsRes, }; } diff --git a/src/shared/components/home/instances.tsx b/src/shared/components/home/instances.tsx index bec472cf..ec2ff635 100644 --- a/src/shared/components/home/instances.tsx +++ b/src/shared/components/home/instances.tsx @@ -59,11 +59,11 @@ export class Instances extends Component { }); } - static async fetchInitialData( - req: InitialFetchRequest - ): Promise { + static async fetchInitialData({ + client, + }: InitialFetchRequest): Promise { return { - federatedInstancesResponse: await req.client.getFederatedInstances({}), + federatedInstancesResponse: await client.getFederatedInstances({}), }; } diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index 48be10b6..b3f1fff1 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -77,10 +77,10 @@ type View = | AdminPurgeCommentView; type ModlogData = RouteDataResponse<{ - modlogResponse: GetModlogResponse; - communityResponse?: GetCommunityResponse; - modUserResponse?: GetPersonDetailsResponse; - userResponse?: GetPersonDetailsResponse; + res: GetModlogResponse; + communityRes: GetCommunityResponse; + modUserResponse: GetPersonDetailsResponse; + userResponse: GetPersonDetailsResponse; }>; interface ModlogType { @@ -662,33 +662,23 @@ export class Modlog extends Component< // Only fetch the data if coming from another route if (FirstLoadService.isFirstLoad) { - const { - modlogResponse: res, - communityResponse: communityRes, - modUserResponse, - userResponse, - } = this.isoData.routeData; + const { res, communityRes, modUserResponse, userResponse } = + this.isoData.routeData; this.state = { ...this.state, res, + communityRes, }; - if (communityRes?.state === "success") { - this.state = { - ...this.state, - communityRes, - }; - } - - if (modUserResponse?.state === "success") { + if (modUserResponse.state === "success") { this.state = { ...this.state, modSearchOptions: [personToChoice(modUserResponse.data.person_view)], }; } - if (userResponse?.state === "success") { + if (userResponse.state === "success") { this.state = { ...this.state, userSearchOptions: [personToChoice(userResponse.data.person_view)], @@ -1002,8 +992,9 @@ export class Modlog extends Component< auth, }; - let communityResponse: RequestState | undefined = - undefined; + let communityResponse: RequestState = { + state: "empty", + }; if (communityId) { const communityForm: GetCommunity = { @@ -1014,8 +1005,9 @@ export class Modlog extends Component< communityResponse = await client.getCommunity(communityForm); } - let modUserResponse: RequestState | undefined = - undefined; + let modUserResponse: RequestState = { + state: "empty", + }; if (modId) { const getPersonForm: GetPersonDetails = { @@ -1026,8 +1018,9 @@ export class Modlog extends Component< modUserResponse = await client.getPersonDetails(getPersonForm); } - let userResponse: RequestState | undefined = - undefined; + let userResponse: RequestState = { + state: "empty", + }; if (userId) { const getPersonForm: GetPersonDetails = { @@ -1039,8 +1032,8 @@ export class Modlog extends Component< } return { - modlogResponse: await client.getModlog(modlogForm), - communityResponse, + res: await client.getModlog(modlogForm), + communityRes: communityResponse, modUserResponse, userResponse, }; diff --git a/src/shared/components/person/inbox.tsx b/src/shared/components/person/inbox.tsx index b0550f22..c65d897b 100644 --- a/src/shared/components/person/inbox.tsx +++ b/src/shared/components/person/inbox.tsx @@ -92,9 +92,9 @@ enum ReplyEnum { } type InboxData = RouteDataResponse<{ - repliesResponse: GetRepliesResponse; - personMentionsResponse: GetPersonMentionsResponse; - privateMessagesResponse: PrivateMessagesResponse; + repliesRes: GetRepliesResponse; + mentionsRes: GetPersonMentionsResponse; + messagesRes: PrivateMessagesResponse; }>; type ReplyType = { @@ -167,11 +167,7 @@ export class Inbox extends Component { // Only fetch the data if coming from another route if (FirstLoadService.isFirstLoad) { - const { - personMentionsResponse: mentionsRes, - privateMessagesResponse: messagesRes, - repliesResponse: repliesRes, - } = this.isoData.routeData; + const { mentionsRes, messagesRes, repliesRes } = this.isoData.routeData; this.state = { ...this.state, @@ -702,7 +698,7 @@ export class Inbox extends Component { const sort: CommentSortType = "New"; return { - personMentionsResponse: auth + mentionsRes: auth ? await client.getPersonMentions({ sort, unread_only: true, @@ -711,7 +707,7 @@ export class Inbox extends Component { auth, }) : { state: "empty" }, - privateMessagesResponse: auth + messagesRes: auth ? await client.getPrivateMessages({ unread_only: true, page: 1, @@ -719,7 +715,7 @@ export class Inbox extends Component { auth, }) : { state: "empty" }, - repliesResponse: auth + repliesRes: auth ? await client.getReplies({ sort, unread_only: true, diff --git a/src/shared/components/person/reports.tsx b/src/shared/components/person/reports.tsx index fb8e8b83..99a03336 100644 --- a/src/shared/components/person/reports.tsx +++ b/src/shared/components/person/reports.tsx @@ -58,9 +58,9 @@ enum MessageEnum { } type ReportsData = RouteDataResponse<{ - commentReportsResponse: ListCommentReportsResponse; - postReportsResponse: ListPostReportsResponse; - privateMessageReportsResponse?: ListPrivateMessageReportsResponse; + commentReportsRes: ListCommentReportsResponse; + postReportsRes: ListPostReportsResponse; + messageReportsRes: ListPrivateMessageReportsResponse; }>; type ItemType = { @@ -106,11 +106,8 @@ export class Reports extends Component { // Only fetch the data if coming from another route if (FirstLoadService.isFirstLoad) { - const { - commentReportsResponse: commentReportsRes, - postReportsResponse: postReportsRes, - privateMessageReportsResponse: messageReportsRes, - } = this.isoData.routeData; + const { commentReportsRes, postReportsRes, messageReportsRes } = + this.isoData.routeData; this.state = { ...this.state, @@ -122,7 +119,7 @@ export class Reports extends Component { if (amAdmin()) { this.state = { ...this.state, - messageReportsRes: messageReportsRes ?? { state: "empty" }, + messageReportsRes: messageReportsRes, }; } } @@ -515,10 +512,9 @@ export class Reports extends Component { }; const data: ReportsData = { - commentReportsResponse: await client.listCommentReports( - commentReportsForm - ), - postReportsResponse: await client.listPostReports(postReportsForm), + commentReportsRes: await client.listCommentReports(commentReportsForm), + postReportsRes: await client.listPostReports(postReportsForm), + messageReportsRes: { state: "empty" }, }; if (amAdmin()) { @@ -529,8 +525,9 @@ export class Reports extends Component { auth: auth as string, }; - data.privateMessageReportsResponse = - await client.listPrivateMessageReports(privateMessageReportsForm); + data.messageReportsRes = await client.listPrivateMessageReports( + privateMessageReportsForm + ); } return data; diff --git a/src/shared/components/post/create-post.tsx b/src/shared/components/post/create-post.tsx index bb39cdad..a0e439bb 100644 --- a/src/shared/components/post/create-post.tsx +++ b/src/shared/components/post/create-post.tsx @@ -81,6 +81,13 @@ export class CreatePost extends Component< const { communityResponse: communityRes, initialCommunitiesRes } = this.isoData.routeData; + this.state = { + ...this.state, + loading: false, + initialCommunitiesRes, + isIsomorphic: true, + }; + if (communityRes?.state === "success") { const communityChoice: Choice = { label: communityRes.data.community_view.community.title, @@ -92,13 +99,6 @@ export class CreatePost extends Component< selectedCommunityChoice: communityChoice, }; } - - this.state = { - ...this.state, - loading: false, - initialCommunitiesRes, - isIsomorphic: true, - }; } } diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx index 9f466730..054cab01 100644 --- a/src/shared/components/search.tsx +++ b/src/shared/components/search.tsx @@ -72,11 +72,11 @@ interface SearchProps { } type SearchData = RouteDataResponse<{ - communityResponse?: GetCommunityResponse; - listCommunitiesResponse?: ListCommunitiesResponse; - creatorDetailsResponse?: GetPersonDetailsResponse; - searchResponse?: SearchResponse; - resolveObjectResponse?: ResolveObjectResponse; + communityResponse: GetCommunityResponse; + listCommunitiesResponse: ListCommunitiesResponse; + creatorDetailsResponse: GetPersonDetailsResponse; + searchResponse: SearchResponse; + resolveObjectResponse: ResolveObjectResponse; }>; type FilterType = "creator" | "community"; @@ -365,11 +365,12 @@ export class Search extends Component { query: { communityId, creatorId, q, type, sort, listingType, page }, }: InitialFetchRequest>): Promise { const community_id = getIdFromString(communityId); - let communityResponse: RequestState | undefined = - undefined; - let listCommunitiesResponse: - | RequestState - | undefined = undefined; + let communityResponse: RequestState = { + state: "empty", + }; + let listCommunitiesResponse: RequestState = { + state: "empty", + }; if (community_id) { const getCommunityForm: GetCommunity = { id: community_id, @@ -391,9 +392,9 @@ export class Search extends Component { } const creator_id = getIdFromString(creatorId); - let creatorDetailsResponse: - | RequestState - | undefined = undefined; + let creatorDetailsResponse: RequestState = { + state: "empty", + }; if (creator_id) { const getCreatorForm: GetPersonDetails = { person_id: creator_id, @@ -405,9 +406,10 @@ export class Search extends Component { const query = getSearchQueryFromQuery(q); - let searchResponse: RequestState | undefined = undefined; - let resolveObjectResponse: RequestState | undefined = - undefined; + let searchResponse: RequestState = { state: "empty" }; + let resolveObjectResponse: RequestState = { + state: "empty", + }; if (query) { const form: SearchForm = { @@ -429,9 +431,7 @@ export class Search extends Component { q: query, auth, }; - resolveObjectResponse = await client - .resolveObject(resolveObjectForm) - .catch(() => undefined); + resolveObjectResponse = await client.resolveObject(resolveObjectForm); } } } diff --git a/src/shared/utils.ts b/src/shared/utils.ts index cf59086b..e1a0c14e 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -1499,7 +1499,7 @@ export function newVote(voteType: VoteType, myVote?: number): number { } export type RouteDataResponse> = { - [K in keyof T]: RequestState>; + [K in keyof T]: RequestState; }; function sleep(millis: number): Promise { From 71336002e7276698088d3fa1c6b3e9808983cbc8 Mon Sep 17 00:00:00 2001 From: abias Date: Fri, 16 Jun 2023 18:12:14 -0400 Subject: [PATCH 3/3] Fix first loads not working --- package.json | 13 +++- src/server/index.tsx | 25 ++----- src/shared/components/home/home.tsx | 81 +++++++++++----------- src/shared/components/post/create-post.tsx | 3 +- src/shared/interfaces.ts | 10 +-- src/shared/routes.ts | 9 +-- src/shared/utils.ts | 12 ++-- 7 files changed, 73 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index 2298d9e1..df264eb0 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,16 @@ "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", diff --git a/src/server/index.tsx b/src/server/index.tsx index 783845fb..4cff98b5 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -17,13 +17,10 @@ import { 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, @@ -140,7 +137,7 @@ server.get("/*", async (req, res) => { // 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> = {}; + 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") { @@ -164,7 +161,7 @@ server.get("/*", async (req, res) => { return res.redirect("/setup"); } - if (site) { + if (site && activeRoute?.fetchInitialData) { const initialFetchReq: InitialFetchRequest = { client, auth, @@ -173,19 +170,7 @@ server.get("/*", async (req, res) => { 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); diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 4dc797ce..ed379b84 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -124,6 +124,39 @@ type HomeData = RouteDataResponse<{ 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 && ( + <> + + + + + + ) + ); +} + function getDataTypeFromQuery(type?: string): DataType { return type ? DataType[type] : DataType.Post; } @@ -235,11 +268,8 @@ export class Home extends Component { // 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, @@ -360,7 +390,7 @@ export class Home extends Component { > )}
{this.mobileView}
- {this.posts()} + {this.posts}