From 3ca24607fbf5c08f83243fc259dcd159bb0a24f2 Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Sat, 17 Jun 2023 09:37:03 +0100 Subject: [PATCH 01/55] add hours as sorting options --- src/shared/components/common/sort-select.tsx | 3 +++ src/shared/utils.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/shared/components/common/sort-select.tsx b/src/shared/components/common/sort-select.tsx index dac6e20d..1fd32076 100644 --- a/src/shared/components/common/sort-select.tsx +++ b/src/shared/components/common/sort-select.tsx @@ -66,6 +66,9 @@ export class SortSelect extends Component { + + + diff --git a/src/shared/utils.ts b/src/shared/utils.ts index c7fbca6b..abb30629 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -986,6 +986,9 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] { export function convertCommentSortType(sort: SortType): CommentSortType { if ( sort == "TopAll" || + sort == "TopHour" || + sort == "TopSixHour" || + sort == "TopTwelveHour" || sort == "TopDay" || sort == "TopWeek" || sort == "TopMonth" || From 5e9a414dfcbde436d803953871bbe3ada464d90a Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Sun, 18 Jun 2023 00:51:32 +0100 Subject: [PATCH 02/55] clean code --- src/shared/utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/utils.ts b/src/shared/utils.ts index abb30629..86a32d16 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -986,9 +986,9 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] { export function convertCommentSortType(sort: SortType): CommentSortType { if ( sort == "TopAll" || - sort == "TopHour" || - sort == "TopSixHour" || - sort == "TopTwelveHour" || + sort == "TopHour" || + sort == "TopSixHour" || + sort == "TopTwelveHour" || sort == "TopDay" || sort == "TopWeek" || sort == "TopMonth" || From 747bc943a966d45bb2547287a630f1714991e860 Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Wed, 21 Jun 2023 01:21:14 +0100 Subject: [PATCH 03/55] refactor if into switch case --- src/shared/utils.ts | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/shared/utils.ts b/src/shared/utils.ts index be7b11b0..d6946cce 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -853,24 +853,28 @@ export function commentsToFlatNodes(comments: CommentView[]): CommentNodeI[] { } export function convertCommentSortType(sort: SortType): CommentSortType { - if ( - sort == "TopAll" || - sort == "TopHour" || - sort == "TopSixHour" || - sort == "TopTwelveHour" || - sort == "TopDay" || - sort == "TopWeek" || - sort == "TopMonth" || - sort == "TopYear" - ) { - return "Top"; - } else if (sort == "New") { - return "New"; - } else if (sort == "Hot" || sort == "Active") { - return "Hot"; - } else { - return "Hot"; - } + switch(sort) { + case "TopAll": + case "TopHour": + case "TopSixHour": + case "TopTwelveHour": + case "TopDay": + case "TopWeek": + case "TopMonth": + case "TopYear": { + return "Top"; + } + case "New": { + return "New"; + } + case "Hot": + case "Active": { + return "Hot"; + } + default: { + return "Hot"; + } + } } export function buildCommentsTree( From 8e711c6b543f3ce75638d9adcc089d15d5f7e4e3 Mon Sep 17 00:00:00 2001 From: Jay Sitter Date: Wed, 21 Jun 2023 19:24:01 -0400 Subject: [PATCH 04/55] fix: Fix i18n UserService import issue --- src/shared/i18next.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/i18next.ts b/src/shared/i18next.ts index ff5f77f1..aab43014 100644 --- a/src/shared/i18next.ts +++ b/src/shared/i18next.ts @@ -1,6 +1,6 @@ import { isBrowser } from "@utils/browser"; import i18next, { i18nTyped, Resource } from "i18next"; -import { UserService } from "./services"; +import { UserService } from "./services/UserService"; import { ar } from "./translations/ar"; import { bg } from "./translations/bg"; import { ca } from "./translations/ca"; From bf0f80e798b38ee748c0a98ba844d83eac7057b9 Mon Sep 17 00:00:00 2001 From: Jay Sitter Date: Wed, 21 Jun 2023 19:40:24 -0400 Subject: [PATCH 05/55] fix: Add post body preview to desktop post listing view --- src/shared/components/post/post-listing.tsx | 76 +++++++++------------ 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index 46a31ba6..3c271659 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -360,28 +360,25 @@ export class PostListing extends Component { createdLine() { const post_view = this.postView; return ( -
    -
  • - - - {this.creatorIsMod_ && ( - {i18n.t("mod")} - )} - {this.creatorIsAdmin_ && ( - {i18n.t("admin")} - )} - {post_view.creator.bot_account && ( - - {i18n.t("bot_account").toLowerCase()} - - )} - {this.props.showCommunity && ( - <> - {" "} - {i18n.t("to")} - - )} -
  • + + + {this.creatorIsMod_ && ( + {i18n.t("mod")} + )} + {this.creatorIsAdmin_ && ( + {i18n.t("admin")} + )} + {post_view.creator.bot_account && ( + + {i18n.t("bot_account").toLowerCase()} + + )} + {this.props.showCommunity && ( + <> + {" "} + {i18n.t("to")} + + )} {post_view.post.language_id !== 0 && ( { @@ -390,17 +387,13 @@ export class PostListing extends Component { )?.name } - )} -
  • -
  • - - - -
  • -
+ )}{" "} + •{" "} + + ); } @@ -737,10 +730,8 @@ export class PostListing extends Component { to={`/post/${post_view.post.id}?scrollToComments=true`} data-tippy-content={title} > - - - {post_view.counts.comments} - + + {post_view.counts.comments} {this.unreadCount && ( ({this.unreadCount} {i18n.t("new")}) @@ -1068,7 +1059,7 @@ export class PostListing extends Component { const post_view = this.postView; return ( this.state.showAdvanced && ( - <> +
{this.canMod_ && ( <> {!this.creatorIsMod_ && @@ -1221,7 +1212,7 @@ export class PostListing extends Component { )} )} - +
) ); } @@ -1408,11 +1399,11 @@ export class PostListing extends Component { ); } - showMobilePreview() { + showBodyPreview() { const { body, id } = this.postView.post; return !this.showBody && body ? ( - +
{body}
) : ( @@ -1433,7 +1424,7 @@ export class PostListing extends Component { {this.mobileThumbnail()} {/* Show a preview of the post body */} - {this.showMobilePreview()} + {this.showBodyPreview()} {this.commentsLine(true)} {this.userActionsLine()} @@ -1455,6 +1446,7 @@ export class PostListing extends Component {
{this.postTitleLine()} {this.createdLine()} + {this.showBodyPreview()} {this.commentsLine()} {this.duplicatesLine()} {this.userActionsLine()} From 92482cbe6b1003d4c89ba12b628f163483752acb Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 00:48:09 -0300 Subject: [PATCH 09/55] Add local community link parser plugin for Markdown-It --- src/shared/markdown.ts | 75 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index 8f4d5c23..c837dba6 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -14,6 +14,7 @@ import markdown_it_sub from "markdown-it-sub"; import markdown_it_sup from "markdown-it-sup"; import Renderer from "markdown-it/lib/renderer"; import Token from "markdown-it/lib/token"; +import { getHttpBase } from "./env"; export let Tribute: any; @@ -72,6 +73,76 @@ const html5EmbedConfig = { }, }; +function localCommunityLinkParser(md) { + const pattern = + /(!\b[^@\s]+@[^@\s]+\.[^.\s]+\b)|\/c\/([^@\s]+)(@[^@\s]+\.[^.\s]+\b)?/g; + + md.core.ruler.push("replace-text", state => { + const tokens = state.tokens; + + for (let i = 0; i < tokens.length; i++) { + if (tokens[i].type === "inline") { + const token = tokens[i]; + + const originalContent = token.content; + + let lastIndex = 0; + originalContent.replace( + pattern, + (match, fullDomainMatch, name, domainTld, index) => { + let url; + // ex: !Testing@example.com + if (fullDomainMatch) { + const [name, domain, tld] = fullDomainMatch + .slice(1) + .split("@") + .join(".") + .split("."); + url = `${getHttpBase()}/c/${name}@${domain}.${tld}`; + } else { + // ex: /c/Testing or /c/Testing@example.com + url = `${getHttpBase()}/c/${name}${domainTld || ""}`; + } + + const beforeContent = originalContent.slice(lastIndex, index); + lastIndex = index + match.length; + + const beforeToken = new state.Token("text", "", 0); + beforeToken.content = beforeContent; + + const linkOpenToken = new state.Token("link_open", "a", 1); + linkOpenToken.attrs = [["href", url]]; + + const textToken = new state.Token("text", "", 0); + textToken.content = match; + + const linkCloseToken = new state.Token("link_close", "a", -1); + + const afterContent = originalContent.slice(lastIndex); + const afterToken = new state.Token("text", "", 0); + afterToken.content = afterContent; + + tokens.splice(i, 1); + + tokens.splice( + i, + 0, + beforeToken, + linkOpenToken, + textToken, + linkCloseToken, + afterToken + ); + + // Update i to skip the newly added tokens + i += 4; + } + ); + } + } + }); +} + export function setupMarkdown() { const markdownItConfig: MarkdownIt.Options = { html: false, @@ -88,7 +159,8 @@ export function setupMarkdown() { .use(markdown_it_sup) .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) - .use(markdown_it_container, "spoiler", spoilerConfig); + .use(markdown_it_container, "spoiler", spoilerConfig) + .use(localCommunityLinkParser); // .use(markdown_it_emoji, { // defs: emojiDefs, // }); @@ -99,6 +171,7 @@ export function setupMarkdown() { .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) .use(markdown_it_container, "spoiler", spoilerConfig) + .use(localCommunityLinkParser) // .use(markdown_it_emoji, { // defs: emojiDefs, // }) From c06d38633766f466d8b744aa44c7418765ad57de Mon Sep 17 00:00:00 2001 From: Ivo Barros Date: Thu, 22 Jun 2023 04:52:04 +0100 Subject: [PATCH 10/55] prettier --- src/shared/components/common/sort-select.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/shared/components/common/sort-select.tsx b/src/shared/components/common/sort-select.tsx index 33c5c85f..4d03ab5d 100644 --- a/src/shared/components/common/sort-select.tsx +++ b/src/shared/components/common/sort-select.tsx @@ -68,11 +68,17 @@ export class SortSelect extends Component { ───── - - + + - + From 02717be15c7aa94f6ef5e6fd1ecb97ac61d85ad6 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 01:07:33 -0300 Subject: [PATCH 11/55] Add community link class --- src/shared/markdown.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index c837dba6..6e6b504f 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -111,7 +111,10 @@ function localCommunityLinkParser(md) { beforeToken.content = beforeContent; const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [["href", url]]; + linkOpenToken.attrs = [ + ["href", url], + ["class", "community-link"], + ]; const textToken = new state.Token("text", "", 0); textToken.content = match; From 5512ee205ad1b6ee40b99c66af3472db5acc019e Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:32:39 -0400 Subject: [PATCH 12/55] add fallback style tag --- src/server/utils/create-ssr-html.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index ae766b3a..a7a87ac9 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -8,6 +8,8 @@ import { fetchIconPng } from "./fetch-icon-png"; const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || ""; +const fallbackStyleTag = ``; + let appleTouchIcon: string | undefined = undefined; export async function createSsrHtml( @@ -85,7 +87,7 @@ export async function createSsrHtml( - ${helmet.link.toString()} + ${helmet.link.toString() || fallbackStyleTag} From a1d935991b04e491eab392e2115bda3c3442e830 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:43:03 -0400 Subject: [PATCH 13/55] rethink it a bit --- src/server/utils/create-ssr-html.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index a7a87ac9..39725fa5 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -4,12 +4,11 @@ import serialize from "serialize-javascript"; import sharp from "sharp"; import { favIconPngUrl, favIconUrl } from "../../shared/config"; import { ILemmyConfig, IsoDataOptionalSite } from "../../shared/interfaces"; +import { buildThemeList } from "./build-themes-list"; import { fetchIconPng } from "./fetch-icon-png"; const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || ""; -const fallbackStyleTag = ``; - let appleTouchIcon: string | undefined = undefined; export async function createSsrHtml( @@ -18,6 +17,10 @@ export async function createSsrHtml( ) { const site = isoData.site_res; + const fallbackTheme = ``; + if (!appleTouchIcon) { appleTouchIcon = site?.site_view.site.icon ? `data:image/png;base64,${sharp( @@ -87,7 +90,7 @@ export async function createSsrHtml( - ${helmet.link.toString() || fallbackStyleTag} + ${helmet.link.toString() || fallbackTheme} From 63b14accec80de9e440266f3e7d92235a85f24dd Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:22:36 -0400 Subject: [PATCH 14/55] rethink it a bit --- src/shared/components/community/community.tsx | 6 ------ src/shared/components/home/home.tsx | 6 ------ src/shared/utils/browser/restore-scroll-position.ts | 1 + src/shared/utils/browser/save-scroll-position.ts | 1 + 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index 7eefe0eb..111b47cd 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -15,7 +15,6 @@ import { updateCommunityBlock, updatePersonBlock, } from "@utils/app"; -import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -229,10 +228,6 @@ export class Community extends Component< setupTippy(); } - componentWillUnmount() { - saveScrollPosition(this.context); - } - static async fetchInitialData({ client, path, @@ -609,7 +604,6 @@ export class Community extends Component< }); } - restoreScrollPosition(this.context); setupTippy(); } diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 0d91bdbc..4a84664b 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -13,7 +13,6 @@ import { showLocal, updatePersonBlock, } from "@utils/app"; -import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -293,10 +292,6 @@ export class Home extends Component { setupTippy(); } - componentWillUnmount() { - saveScrollPosition(this.context); - } - static async fetchInitialData({ client, auth, @@ -800,7 +795,6 @@ export class Home extends Component { }); } - restoreScrollPosition(this.context); setupTippy(); } diff --git a/src/shared/utils/browser/restore-scroll-position.ts b/src/shared/utils/browser/restore-scroll-position.ts index f1534644..6986ae59 100644 --- a/src/shared/utils/browser/restore-scroll-position.ts +++ b/src/shared/utils/browser/restore-scroll-position.ts @@ -1,5 +1,6 @@ export default function restoreScrollPosition(context: any) { const path: string = context.router.route.location.pathname; const y = Number(sessionStorage.getItem(`scrollPosition_${path}`)); + window.scrollTo(0, y); } diff --git a/src/shared/utils/browser/save-scroll-position.ts b/src/shared/utils/browser/save-scroll-position.ts index 48353287..596d5d9f 100644 --- a/src/shared/utils/browser/save-scroll-position.ts +++ b/src/shared/utils/browser/save-scroll-position.ts @@ -1,5 +1,6 @@ export default function saveScrollPosition(context: any) { const path: string = context.router.route.location.pathname; const y = window.scrollY; + sessionStorage.setItem(`scrollPosition_${path}`, y.toString()); } From 955ca826cd4d8e764578ddd37d302897c91340b8 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Thu, 22 Jun 2023 12:28:27 -0400 Subject: [PATCH 15/55] Enable users to zoom on mobile --- src/server/utils/create-ssr-html.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index 39725fa5..55788ec5 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -73,7 +73,7 @@ export async function createSsrHtml( - + Date: Thu, 22 Jun 2023 13:44:43 -0300 Subject: [PATCH 16/55] Update getHttpBase dependency reference --- src/shared/markdown.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index 6e6b504f..d35b469e 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -8,13 +8,13 @@ import { CustomEmojiView } from "lemmy-js-client"; import { default as MarkdownIt } from "markdown-it"; import markdown_it_container from "markdown-it-container"; // import markdown_it_emoji from "markdown-it-emoji/bare"; +import { getHttpBase } from "@utils/env"; import markdown_it_footnote from "markdown-it-footnote"; import markdown_it_html5_embed from "markdown-it-html5-embed"; import markdown_it_sub from "markdown-it-sub"; import markdown_it_sup from "markdown-it-sup"; import Renderer from "markdown-it/lib/renderer"; import Token from "markdown-it/lib/token"; -import { getHttpBase } from "./env"; export let Tribute: any; From 51a6681d153cc398c1729a9f3972187a4b3581ac Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Thu, 22 Jun 2023 12:50:05 -0400 Subject: [PATCH 17/55] Omit user-scalable to use default --- src/server/utils/create-ssr-html.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/utils/create-ssr-html.tsx b/src/server/utils/create-ssr-html.tsx index 55788ec5..13775981 100644 --- a/src/server/utils/create-ssr-html.tsx +++ b/src/server/utils/create-ssr-html.tsx @@ -73,7 +73,7 @@ export async function createSsrHtml( - + Date: Thu, 22 Jun 2023 16:52:47 +0000 Subject: [PATCH 18/55] Fix avatar alignment issue (#1475) --- src/shared/components/common/pictrs-image.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/components/common/pictrs-image.tsx b/src/shared/components/common/pictrs-image.tsx index 74437490..31fb1229 100644 --- a/src/shared/components/common/pictrs-image.tsx +++ b/src/shared/components/common/pictrs-image.tsx @@ -22,7 +22,7 @@ export class PictrsImage extends Component { render() { return ( - + @@ -31,7 +31,7 @@ export class PictrsImage extends Component { alt={this.alt()} title={this.alt()} loading="lazy" - className={classNames({ + className={classNames("overflow-hidden pictrs-image", { "img-fluid": !this.props.icon && !this.props.iconOverlay, banner: this.props.banner, "thumbnail rounded": From c5779cd9b1e669fe6b8220e5c2dff0c125ed04e9 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 14:28:32 -0300 Subject: [PATCH 19/55] Update community link markdown parsing Remove links without remote servers, add kbin support, add user support --- src/shared/markdown.ts | 114 +++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 61 deletions(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index d35b469e..f56817e6 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -8,7 +8,6 @@ import { CustomEmojiView } from "lemmy-js-client"; import { default as MarkdownIt } from "markdown-it"; import markdown_it_container from "markdown-it-container"; // import markdown_it_emoji from "markdown-it-emoji/bare"; -import { getHttpBase } from "@utils/env"; import markdown_it_footnote from "markdown-it-footnote"; import markdown_it_html5_embed from "markdown-it-html5-embed"; import markdown_it_sub from "markdown-it-sub"; @@ -74,73 +73,66 @@ const html5EmbedConfig = { }; function localCommunityLinkParser(md) { - const pattern = - /(!\b[^@\s]+@[^@\s]+\.[^.\s]+\b)|\/c\/([^@\s]+)(@[^@\s]+\.[^.\s]+\b)?/g; - md.core.ruler.push("replace-text", state => { - const tokens = state.tokens; + /** + * Accepted formats: + * !community@server.com + * /c/community@server.com + * /m/community@server.com + * /u/username@server.com + */ + const pattern = + /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; - for (let i = 0; i < tokens.length; i++) { - if (tokens[i].type === "inline") { - const token = tokens[i]; + for (let i = 0; i < state.tokens.length; i++) { + if (state.tokens[i].type !== "inline") { + continue; + } + const inlineTokens = state.tokens[i].children; + for (let j = inlineTokens.length - 1; j >= 0; j--) { + if ( + inlineTokens[j].type === "text" && + pattern.test(inlineTokens[j].content) + ) { + const textParts = inlineTokens[j].content.split(pattern); + const newTokens: Token[] = []; - const originalContent = token.content; + for (const part of textParts) { + let linkClass = "community-link"; + if (pattern.test(part)) { + // Rewrite !community@server.com and KBin /m/community@server.com to local urls + let href; + if (part.startsWith("!")) { + href = "/c/" + part.substring(1); + } else if (part.startsWith("/m/")) { + href = "/c/" + part.substring(3); + } else { + href = part; + if (part.startsWith("/u/")) { + linkClass = "user-link"; + } + } - let lastIndex = 0; - originalContent.replace( - pattern, - (match, fullDomainMatch, name, domainTld, index) => { - let url; - // ex: !Testing@example.com - if (fullDomainMatch) { - const [name, domain, tld] = fullDomainMatch - .slice(1) - .split("@") - .join(".") - .split("."); - url = `${getHttpBase()}/c/${name}@${domain}.${tld}`; + const linkOpenToken = new state.Token("link_open", "a", 1); + linkOpenToken.attrs = [ + ["href", href], + ["class", linkClass], + ]; + const textToken = new state.Token("text", "", 0); + textToken.content = part; + const linkCloseToken = new state.Token("link_close", "a", -1); + + newTokens.push(linkOpenToken, textToken, linkCloseToken); } else { - // ex: /c/Testing or /c/Testing@example.com - url = `${getHttpBase()}/c/${name}${domainTld || ""}`; + const textToken = new state.Token("text", "", 0); + textToken.content = part; + newTokens.push(textToken); } - - const beforeContent = originalContent.slice(lastIndex, index); - lastIndex = index + match.length; - - const beforeToken = new state.Token("text", "", 0); - beforeToken.content = beforeContent; - - const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [ - ["href", url], - ["class", "community-link"], - ]; - - const textToken = new state.Token("text", "", 0); - textToken.content = match; - - const linkCloseToken = new state.Token("link_close", "a", -1); - - const afterContent = originalContent.slice(lastIndex); - const afterToken = new state.Token("text", "", 0); - afterToken.content = afterContent; - - tokens.splice(i, 1); - - tokens.splice( - i, - 0, - beforeToken, - linkOpenToken, - textToken, - linkCloseToken, - afterToken - ); - - // Update i to skip the newly added tokens - i += 4; } - ); + + // Replace the original token with the new tokens + inlineTokens.splice(j, 1, ...newTokens); + } } } }); From 4a061491c77a0ac784bb9815ff17016e86aa8914 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:04:21 -0400 Subject: [PATCH 20/55] update issue template --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 43 ++++++++++---------- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 47 +++++----------------- .github/ISSUE_TEMPLATE/QUESTION.yml | 17 -------- .github/ISSUE_TEMPLATE/config.yml | 8 ++++ .github/ISSUE_TEMPLATE/hexbear.yml | 11 ----- 5 files changed, 40 insertions(+), 86 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/QUESTION.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/hexbear.yml diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index a43a5a55..72b274e1 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -1,32 +1,30 @@ -name: "\U0001F41E Bug Report" -description: Create a report to help us improve lemmy-ui -title: "[Bug]: " +name: "Bug report" +description: Create a bug report to help us improve Lemmy-UI! +title: "" labels: ["bug", "triage"] body: - type: markdown attributes: value: | - Found a bug? Please fill out the sections below. 👍 - Thanks for taking the time to fill out this bug report! - For backend issues, use [lemmy](https://github.com/LemmyNet/lemmy/issues/new/choose) + Thanks for taking the time to help improve Lemmy-UI by reporting a bug! - type: checkboxes attributes: label: Requirements - description: Before you create a bug report please do the following. + description: Before you create a bug report, please carefully check the following – options: - - label: Is this a bug report? For questions or discussions use https://lemmy.ml/c/lemmy_support + - label: This is a bug report, and if not, I'd post to https://lemmy.ml/c/lemmy_support instead. required: true - - label: Did you check to see if this issue already exists? + - label: I've [checked](https://github.com/LemmyNet/lemmy-ui/issues) to see if this issue already exists. required: true - - label: Is this only a single bug? Do not put multiple bugs in one issue. + - label: It's a single bug. I'm not reporting multiple bugs in one issue. + required: true + - label: It's a frontend issue, not a backend issue; I'd report that to the [backend repo](https://github.com/LemmyNet/lemmy) instead. required: true - - label: Is this a server side (not related to the UI) issue? Use the [Lemmy back end](https://github.com/LemmyNet/lemmy) repo. - required: false - type: textarea id: summary attributes: label: Summary - description: A summary of the bug. + description: Explain the bug and upload images, screenshots or videos if possible. validations: required: true - type: textarea @@ -34,12 +32,14 @@ body: attributes: label: Steps to Reproduce description: | - Describe the steps to reproduce the bug. - The better your description is _(go 'here', click 'there'...)_ the fastest you'll get an _(accurate)_ resolution. + In a numbered list, walk us through the steps needed to reproduce the bug. + The better your description is _(go 'here', click 'there'...)_, the quicker we can fix it. value: | 1. 2. 3. + 4. + 5. validations: required: true - type: textarea @@ -47,20 +47,21 @@ body: attributes: label: Technical Details description: | - - Any browser console errors? + - Describe your environment (OS, browser, model of smartphone, etc) + - If relevant, also share any console errors and/or screenshots here. validations: required: true - type: input id: lemmy-ui-version attributes: - label: Version - description: Which Lemmy UI version do you use? Displayed in the footer. - placeholder: ex. 0.17.4-rc.4 + label: Lemmy Instance Version + description: What's the version of the Lemmy instance where the bug can be reproduced? + placeholder: ex. 0.18-rc.6 validations: required: true - type: input id: lemmy-instance attributes: label: Lemmy Instance URL - description: Which Lemmy instance do you use? The address - placeholder: lemmy.ml, lemmy.world, etc + description: The URL of the Lemmy instance where the bug can be reproduced. + placeholder: https://lemmy.ml diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index 2d656819..7bd7e910 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -1,54 +1,27 @@ -name: "\U0001F680 Feature request" -description: Suggest an idea for improving Lemmy's UI +name: "Feature request" +description: Suggest an idea to improve Lemmy-UI labels: ["enhancement"] body: - type: markdown attributes: value: | - Have a suggestion about Lemmy's UI? - For backend issues, use [lemmy](https://github.com/LemmyNet/lemmy/issues/new/choose) + Thanks for taking the time to help improve Lemmy-UI by suggesting a feature! - type: checkboxes attributes: label: Requirements - description: Before you create a feature request please do the following. + description: Before you create a bug report, please carefully check the following – options: - - label: Is this a feature request? For questions or discussions use https://lemmy.ml/c/lemmy_support + - label: This is a feature request and not a bug report. Otherwise, I'd create a new [bug report](https://github.com/LemmyNet/lemmy-ui/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=BUG_REPORT.yml&title=%5BBug%5D%3A+) instead. required: true - - label: Did you check to see if this issue already exists? + - label: I've [checked](https://github.com/LemmyNet/lemmy-ui/issues) to see if this request (or a similar one) already exists. required: true - - label: Is this only a feature request? Do not put multiple feature requests in one issue. + - label: It's a single feature. I'm not requesting multiple features in one issue. required: true - - label: Is this a server side (not related to the UI) issue? Use the [Lemmy back end](https://github.com/LemmyNet/lemmy) repo. - required: false - - type: textarea - id: problem - attributes: - label: Is your proposal related to a problem? - description: | - Provide a clear and concise description of what the problem is. - For example, "I'm always frustrated when..." - validations: - required: true - type: textarea id: solution attributes: - label: Describe the solution you'd like. + label: Describe the feature you'd like description: | - Provide a clear and concise description of what you want to happen. + Provide a clear and concise description of the feature. Explain why it's needed. validations: - required: true - - type: textarea - id: alternatives - attributes: - label: Describe alternatives you've considered. - description: | - Let us know about other solutions you've tried or researched. - validations: - required: true - - type: textarea - id: context - attributes: - label: Additional context - description: | - Is there anything else you can add about the proposal? - You might want to link to related issues here, if you haven't already. + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/QUESTION.yml b/.github/ISSUE_TEMPLATE/QUESTION.yml deleted file mode 100644 index 734937e9..00000000 --- a/.github/ISSUE_TEMPLATE/QUESTION.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: "? Question" -description: General questions about Lemmy -title: "Question: " -labels: ["question", "triage"] -body: - - type: markdown - attributes: - value: | - Have a question about Lemmy's UI? - Please check the docs first: https://join-lemmy.org/docs/en/index.html - - type: textarea - id: question - attributes: - label: Question - description: What's the question you have about Lemmy's UI? - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..d59c2b1b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Question + url: https://lemmy.ml/c/lemmy_support + about: Please ask and answer general questions here. + - name: Technical Discussion + url: https://github.com/LemmyNet/lemmy-ui/discussions + about: Please discuss technical topics with other contributors here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/hexbear.yml b/.github/ISSUE_TEMPLATE/hexbear.yml deleted file mode 100644 index 73ef5482..00000000 --- a/.github/ISSUE_TEMPLATE/hexbear.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: "Hexbear" -description: For hexbear issues -labels: ["hexbear", "triage"] -body: - - type: textarea - id: question - attributes: - label: Question - description: What's the question you have about hexbear? - validations: - required: true From 0938deedf0e0b5fb121da36de23687531eb80b31 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:08:21 -0400 Subject: [PATCH 21/55] formatting ISSUE_TEMPLATE --- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 2 +- .github/ISSUE_TEMPLATE/config.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index 7bd7e910..d998a63d 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -24,4 +24,4 @@ body: description: | Provide a clear and concise description of the feature. Explain why it's needed. validations: - required: true \ No newline at end of file + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d59c2b1b..59085700 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -5,4 +5,4 @@ contact_links: about: Please ask and answer general questions here. - name: Technical Discussion url: https://github.com/LemmyNet/lemmy-ui/discussions - about: Please discuss technical topics with other contributors here. \ No newline at end of file + about: Please discuss technical topics with other contributors here. From fc0c0634269fb57dad2e75f6b5bf5c1aa06fabf8 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:17:34 -0300 Subject: [PATCH 22/55] Move regex pattern to config --- src/shared/config.ts | 10 ++++++++++ src/shared/markdown.ts | 17 ++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/shared/config.ts b/src/shared/config.ts index 28e8ce51..6b462244 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -25,4 +25,14 @@ export const fetchLimit = 40; export const relTags = "noopener nofollow"; export const emDash = "\u2014"; +/** + * Accepted formats: + * !community@server.com + * /c/community@server.com + * /m/community@server.com + * /u/username@server.com + */ +export const instanceLinkRegex = + /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; + export const testHost = "0.0.0.0:8536"; diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index f56817e6..d8ed9d50 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -14,6 +14,7 @@ import markdown_it_sub from "markdown-it-sub"; import markdown_it_sup from "markdown-it-sup"; import Renderer from "markdown-it/lib/renderer"; import Token from "markdown-it/lib/token"; +import { instanceLinkRegex } from "./config"; export let Tribute: any; @@ -74,16 +75,6 @@ const html5EmbedConfig = { function localCommunityLinkParser(md) { md.core.ruler.push("replace-text", state => { - /** - * Accepted formats: - * !community@server.com - * /c/community@server.com - * /m/community@server.com - * /u/username@server.com - */ - const pattern = - /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; - for (let i = 0; i < state.tokens.length; i++) { if (state.tokens[i].type !== "inline") { continue; @@ -92,14 +83,14 @@ function localCommunityLinkParser(md) { for (let j = inlineTokens.length - 1; j >= 0; j--) { if ( inlineTokens[j].type === "text" && - pattern.test(inlineTokens[j].content) + instanceLinkRegex.test(inlineTokens[j].content) ) { - const textParts = inlineTokens[j].content.split(pattern); + const textParts = inlineTokens[j].content.split(instanceLinkRegex); const newTokens: Token[] = []; for (const part of textParts) { let linkClass = "community-link"; - if (pattern.test(part)) { + if (instanceLinkRegex.test(part)) { // Rewrite !community@server.com and KBin /m/community@server.com to local urls let href; if (part.startsWith("!")) { From dd4b60d22460cda70097a086b852630f2d105083 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:22:29 -0400 Subject: [PATCH 23/55] add emojis back to ISSUE_TEMPLATE --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 2 +- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 72b274e1..aeffa3a6 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -1,4 +1,4 @@ -name: "Bug report" +name: "\U0001F41E Bug report" description: Create a bug report to help us improve Lemmy-UI! title: "" labels: ["bug", "triage"] diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index d998a63d..77d85d27 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -1,4 +1,4 @@ -name: "Feature request" +name: "\U0001F680 Feature request" description: Suggest an idea to improve Lemmy-UI labels: ["enhancement"] body: From a1fc4bbea9e7eb0118bc97be5f98751beac81c14 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:23:43 -0400 Subject: [PATCH 24/55] make suggested changes --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 2 +- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index aeffa3a6..99d612e7 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -18,7 +18,7 @@ body: required: true - label: It's a single bug. I'm not reporting multiple bugs in one issue. required: true - - label: It's a frontend issue, not a backend issue; I'd report that to the [backend repo](https://github.com/LemmyNet/lemmy) instead. + - label: It's a frontend issue, not a backend issue; Otherwise I will create an issue on the [backend repo](https://github.com/LemmyNet/lemmy) instead. required: true - type: textarea id: summary diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index 77d85d27..ed1d6375 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -11,7 +11,7 @@ body: label: Requirements description: Before you create a bug report, please carefully check the following – options: - - label: This is a feature request and not a bug report. Otherwise, I'd create a new [bug report](https://github.com/LemmyNet/lemmy-ui/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=BUG_REPORT.yml&title=%5BBug%5D%3A+) instead. + - label: This is a feature request and not a bug report. Otherwise, I will create a new [bug report](https://github.com/LemmyNet/lemmy-ui/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=BUG_REPORT.yml&title=%5BBug%5D%3A+) instead. required: true - label: I've [checked](https://github.com/LemmyNet/lemmy-ui/issues) to see if this request (or a similar one) already exists. required: true From 5a9d15f8f81307cf401115c215c25e7ba8500622 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:24:12 -0400 Subject: [PATCH 25/55] good catch --- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index ed1d6375..b8ec1b5b 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -9,7 +9,7 @@ body: - type: checkboxes attributes: label: Requirements - description: Before you create a bug report, please carefully check the following – + description: Before you create a feature request, please carefully check the following – options: - label: This is a feature request and not a bug report. Otherwise, I will create a new [bug report](https://github.com/LemmyNet/lemmy-ui/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=BUG_REPORT.yml&title=%5BBug%5D%3A+) instead. required: true From 6a88e8a24ac63158116eed112e88f675e8128a73 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:24:49 -0400 Subject: [PATCH 26/55] change verbiage --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 99d612e7..c88b22e6 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -12,7 +12,7 @@ body: label: Requirements description: Before you create a bug report, please carefully check the following – options: - - label: This is a bug report, and if not, I'd post to https://lemmy.ml/c/lemmy_support instead. + - label: This is a bug report, and if not, I will post to https://lemmy.ml/c/lemmy_support instead. required: true - label: I've [checked](https://github.com/LemmyNet/lemmy-ui/issues) to see if this issue already exists. required: true From 73147ae37c5ba930a4915fc704a01bfb2744b173 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:33:45 -0300 Subject: [PATCH 27/55] Use shorter regex in community link parser --- src/shared/config.ts | 2 +- src/shared/markdown.ts | 69 +++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/shared/config.ts b/src/shared/config.ts index 6b462244..db7e688a 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -33,6 +33,6 @@ export const emDash = "\u2014"; * /u/username@server.com */ export const instanceLinkRegex = - /(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g; + /(\/[c|m|u]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g; export const testHost = "0.0.0.0:8536"; diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index d8ed9d50..faab8756 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -73,7 +73,7 @@ const html5EmbedConfig = { }, }; -function localCommunityLinkParser(md) { +function localCommunityLinkParser(md: MarkdownIt) { md.core.ruler.push("replace-text", state => { for (let i = 0; i < state.tokens.length; i++) { if (state.tokens[i].type !== "inline") { @@ -83,42 +83,49 @@ function localCommunityLinkParser(md) { for (let j = inlineTokens.length - 1; j >= 0; j--) { if ( inlineTokens[j].type === "text" && - instanceLinkRegex.test(inlineTokens[j].content) + new RegExp(instanceLinkRegex).test(inlineTokens[j].content) ) { - const textParts = inlineTokens[j].content.split(instanceLinkRegex); + const text = inlineTokens[j].content; + const matches = Array.from(text.matchAll(instanceLinkRegex)); + + let lastIndex = 0; const newTokens: Token[] = []; - for (const part of textParts) { - let linkClass = "community-link"; - if (instanceLinkRegex.test(part)) { - // Rewrite !community@server.com and KBin /m/community@server.com to local urls - let href; - if (part.startsWith("!")) { - href = "/c/" + part.substring(1); - } else if (part.startsWith("/m/")) { - href = "/c/" + part.substring(3); - } else { - href = part; - if (part.startsWith("/u/")) { - linkClass = "user-link"; - } - } - - const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [ - ["href", href], - ["class", linkClass], - ]; + for (const match: RegExpMatchArray of matches) { + // If there is plain text before the match, add it as a separate token + if (match.index !== undefined && match.index > lastIndex) { const textToken = new state.Token("text", "", 0); - textToken.content = part; - const linkCloseToken = new state.Token("link_close", "a", -1); - - newTokens.push(linkOpenToken, textToken, linkCloseToken); - } else { - const textToken = new state.Token("text", "", 0); - textToken.content = part; + textToken.content = text.slice(lastIndex, match.index); newTokens.push(textToken); } + + // Determine the new href + let href; + if (match[0].startsWith("!")) { + href = "/c/" + match[0].substring(1); + } else if (match[0].startsWith("/m/")) { + href = "/c/" + match[0].substring(3); + } else { + href = match[0]; + } + + const linkOpenToken = new state.Token("link_open", "a", 1); + linkOpenToken.attrs = [["href", href]]; + const textToken = new state.Token("text", "", 0); + textToken.content = match[0]; + const linkCloseToken = new state.Token("link_close", "a", -1); + + newTokens.push(linkOpenToken, textToken, linkCloseToken); + + lastIndex = + (match.index !== undefined ? match.index : 0) + match[0].length; + } + + // If there is plain text after the last match, add it as a separate token + if (lastIndex < text.length) { + const textToken = new state.Token("text", "", 0); + textToken.content = text.slice(lastIndex); + newTokens.push(textToken); } // Replace the original token with the new tokens From d6e9b20a6ce29efdb4efe05014581ab5a4142f3b Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:40:06 -0300 Subject: [PATCH 28/55] Add missing classes --- src/shared/markdown.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index faab8756..062b150d 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -91,6 +91,8 @@ function localCommunityLinkParser(md: MarkdownIt) { let lastIndex = 0; const newTokens: Token[] = []; + let linkClass = "community-link"; + for (const match: RegExpMatchArray of matches) { // If there is plain text before the match, add it as a separate token if (match.index !== undefined && match.index > lastIndex) { @@ -109,8 +111,15 @@ function localCommunityLinkParser(md: MarkdownIt) { href = match[0]; } + if (match[0].startsWith("/u/")) { + linkClass = "user-link"; + } + const linkOpenToken = new state.Token("link_open", "a", 1); - linkOpenToken.attrs = [["href", href]]; + linkOpenToken.attrs = [ + ["href", href], + ["class", linkClass], + ]; const textToken = new state.Token("text", "", 0); textToken.content = match[0]; const linkCloseToken = new state.Token("link_close", "a", -1); From 773eef5126c8381b42bf1833dc7f040ad7f20b19 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:43:01 -0300 Subject: [PATCH 29/55] Remove pipe from community link regex --- src/shared/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/config.ts b/src/shared/config.ts index db7e688a..c56c64b0 100644 --- a/src/shared/config.ts +++ b/src/shared/config.ts @@ -33,6 +33,6 @@ export const emDash = "\u2014"; * /u/username@server.com */ export const instanceLinkRegex = - /(\/[c|m|u]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g; + /(\/[cmu]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g; export const testHost = "0.0.0.0:8536"; From 7571f7ac69e930e0f3c9758792fdc09b87da0f70 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:45:09 -0400 Subject: [PATCH 30/55] bandaid fix our video embeds --- src/shared/components/post/post-listing.tsx | 75 +++++++++++++-------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index 4d0951bb..93b8fff7 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -239,25 +239,40 @@ export class PostListing extends Component { } get img() { - return this.imageSrc ? ( - <> -
- - - + if (this.imageSrc) { + return ( + <> +
+ + + +
+
+ + + +
+ + ); + } + + const { post } = this.postView; + const { url } = post; + + if (url && isVideo(url)) { + return ( +
+
-
- - - -
- - ) : ( - <> - ); + ); + } + + return <>; } imgThumb(src: string) { @@ -325,17 +340,19 @@ export class PostListing extends Component { } else if (url) { if (!this.props.hideImage && isVideo(url)) { return ( -
- -
+ +
+ +
+
); } else { return ( From 110be607c5da59b14d285a8a8b597e202fa42473 Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 15:51:25 -0300 Subject: [PATCH 31/55] Typescript linter fixes --- src/shared/markdown.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index 062b150d..ececf479 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -79,7 +79,7 @@ function localCommunityLinkParser(md: MarkdownIt) { if (state.tokens[i].type !== "inline") { continue; } - const inlineTokens = state.tokens[i].children; + const inlineTokens: Token[] = state.tokens[i].children || []; for (let j = inlineTokens.length - 1; j >= 0; j--) { if ( inlineTokens[j].type === "text" && @@ -93,7 +93,7 @@ function localCommunityLinkParser(md: MarkdownIt) { let linkClass = "community-link"; - for (const match: RegExpMatchArray of matches) { + for (const match of matches) { // If there is plain text before the match, add it as a separate token if (match.index !== undefined && match.index > lastIndex) { const textToken = new state.Token("text", "", 0); From 7bd90da1f84bf1cfccfa192e4aebf93549685e4e Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 16:02:27 -0300 Subject: [PATCH 32/55] Rename function to be more generic, since it parses users --- src/shared/markdown.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index ececf479..adee474f 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -73,7 +73,7 @@ const html5EmbedConfig = { }, }; -function localCommunityLinkParser(md: MarkdownIt) { +function localInstanceLinkParser(md: MarkdownIt) { md.core.ruler.push("replace-text", state => { for (let i = 0; i < state.tokens.length; i++) { if (state.tokens[i].type !== "inline") { From d58fd63113bc2933377ec2d90f8091b34b16e74f Mon Sep 17 00:00:00 2001 From: Zetaphor Date: Thu, 22 Jun 2023 16:05:20 -0300 Subject: [PATCH 33/55] Cleanup, only check for /u/ if /c/ and /m/ checks fail --- src/shared/markdown.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/shared/markdown.ts b/src/shared/markdown.ts index adee474f..9f1ec733 100644 --- a/src/shared/markdown.ts +++ b/src/shared/markdown.ts @@ -101,7 +101,6 @@ function localInstanceLinkParser(md: MarkdownIt) { newTokens.push(textToken); } - // Determine the new href let href; if (match[0].startsWith("!")) { href = "/c/" + match[0].substring(1); @@ -109,10 +108,9 @@ function localInstanceLinkParser(md: MarkdownIt) { href = "/c/" + match[0].substring(3); } else { href = match[0]; - } - - if (match[0].startsWith("/u/")) { - linkClass = "user-link"; + if (match[0].startsWith("/u/")) { + linkClass = "user-link"; + } } const linkOpenToken = new state.Token("link_open", "a", 1); @@ -137,7 +135,6 @@ function localInstanceLinkParser(md: MarkdownIt) { newTokens.push(textToken); } - // Replace the original token with the new tokens inlineTokens.splice(j, 1, ...newTokens); } } @@ -162,7 +159,7 @@ export function setupMarkdown() { .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) .use(markdown_it_container, "spoiler", spoilerConfig) - .use(localCommunityLinkParser); + .use(localInstanceLinkParser); // .use(markdown_it_emoji, { // defs: emojiDefs, // }); @@ -173,7 +170,7 @@ export function setupMarkdown() { .use(markdown_it_footnote) .use(markdown_it_html5_embed, html5EmbedConfig) .use(markdown_it_container, "spoiler", spoilerConfig) - .use(localCommunityLinkParser) + .use(localInstanceLinkParser) // .use(markdown_it_emoji, { // defs: emojiDefs, // }) From 374132923f7527f50b6b001c5683fafae7d6f917 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 22 Jun 2023 16:15:45 -0400 Subject: [PATCH 34/55] Adding jsit to codeowners. --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 76916e60..ee3d7a54 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @dessalines @SleeplessOne1917 @alectrocute +* @dessalines @SleeplessOne1917 @alectrocute @jsit From 46323c91730c120205c32c84b0f270db14fd0193 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:01:04 -0400 Subject: [PATCH 35/55] make suggested changes --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 8 ++++---- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index c88b22e6..5561b888 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -12,13 +12,13 @@ body: label: Requirements description: Before you create a bug report, please carefully check the following – options: - - label: This is a bug report, and if not, I will post to https://lemmy.ml/c/lemmy_support instead. + - label: This is a bug report, and if not, please post to https://lemmy.ml/c/lemmy_support instead. required: true - - label: I've [checked](https://github.com/LemmyNet/lemmy-ui/issues) to see if this issue already exists. + - label: Please [check](https://github.com/LemmyNet/lemmy-ui/issues) to see if this issue already exists. required: true - - label: It's a single bug. I'm not reporting multiple bugs in one issue. + - label: It's a single bug. Do not report multiple bugs in one issue. required: true - - label: It's a frontend issue, not a backend issue; Otherwise I will create an issue on the [backend repo](https://github.com/LemmyNet/lemmy) instead. + - label: It's a frontend issue, not a backend issue; Otherwise please create an issue on the [backend repo](https://github.com/LemmyNet/lemmy) instead. required: true - type: textarea id: summary diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index b8ec1b5b..ed5da331 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -11,11 +11,11 @@ body: label: Requirements description: Before you create a feature request, please carefully check the following – options: - - label: This is a feature request and not a bug report. Otherwise, I will create a new [bug report](https://github.com/LemmyNet/lemmy-ui/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=BUG_REPORT.yml&title=%5BBug%5D%3A+) instead. + - label: This is a feature request and not a bug report. Otherwise, please create a new [bug report](https://github.com/LemmyNet/lemmy-ui/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=BUG_REPORT.yml) instead. required: true - - label: I've [checked](https://github.com/LemmyNet/lemmy-ui/issues) to see if this request (or a similar one) already exists. + - label: Please [check](https://github.com/LemmyNet/lemmy-ui/issues) to see if this request (or a similar one) already exists. required: true - - label: It's a single feature. I'm not requesting multiple features in one issue. + - label: It's a single feature. Please don't request multiple features in one issue. required: true - type: textarea id: solution From 91a07e79fc3f7e345bb59c6471c6bdff3eeeff7b Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:44:15 -0400 Subject: [PATCH 36/55] fix lack of modlog refetch on mount (#1490) Co-authored-by: Dessalines --- src/shared/components/modlog.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index e705bac8..722f6e70 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -686,6 +686,10 @@ export class Modlog extends Component< } } + async componentDidMount() { + await this.refetch(); + } + get combined() { const res = this.state.res; const combined = res.state == "success" ? buildCombined(res.data) : []; From 317c0852500ef8e02b1d597966df96f24a865473 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:53:43 -0400 Subject: [PATCH 37/55] remove title attr (#1492) --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 5561b888..f37b108a 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -1,6 +1,5 @@ name: "\U0001F41E Bug report" description: Create a bug report to help us improve Lemmy-UI! -title: "" labels: ["bug", "triage"] body: - type: markdown From 205cd83b4ace941a1e44e47a8956c3843f4538ff Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 19:04:15 -0400 Subject: [PATCH 38/55] `ISSUE_TEMPLATE` cleanup (#1493) --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 5 ++--- .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index f37b108a..da7fa2bd 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -1,5 +1,5 @@ name: "\U0001F41E Bug report" -description: Create a bug report to help us improve Lemmy-UI! +description: Report a bug to help us improve Lemmy-UI. labels: ["bug", "triage"] body: - type: markdown @@ -38,7 +38,6 @@ body: 2. 3. 4. - 5. validations: required: true - type: textarea @@ -62,5 +61,5 @@ body: id: lemmy-instance attributes: label: Lemmy Instance URL - description: The URL of the Lemmy instance where the bug can be reproduced. + description: What's the URL of the Lemmy instance where the bug can be reproduced? placeholder: https://lemmy.ml diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index ed5da331..ac7d8dc6 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -1,5 +1,5 @@ name: "\U0001F680 Feature request" -description: Suggest an idea to improve Lemmy-UI +description: Suggest an idea for Lemmy-UI. labels: ["enhancement"] body: - type: markdown From d0dff77377a84611ab5cf624123e84c95aedf1ff Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Thu, 22 Jun 2023 19:33:02 -0400 Subject: [PATCH 39/55] Replace momentjs with date-fns --- .gitignore | 2 + .prettierignore | 1 + package.json | 9 +- src/client/index.tsx | 37 ++++-- src/server/index.tsx | 14 ++- .../components/comment/comment-node.tsx | 10 +- src/shared/components/common/moment-time.tsx | 24 ++-- src/shared/components/modlog.tsx | 13 ++- src/shared/components/person/profile.tsx | 8 +- src/shared/utils/helpers/is-cake-day.ts | 34 ++---- webpack.config.js | 9 +- yarn.lock | 105 ++++++++++++++++-- 12 files changed, 187 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index 34454f3f..3234d3df 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ package-lock.json src/shared/translations +stats.json + diff --git a/.prettierignore b/.prettierignore index 98eb0d9b..004c815f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ src/shared/translations lemmy-translations src/assets/css/themes/*.css +stats.json diff --git a/package.json b/package.json index 9e7a0f1b..e2a9ce64 100644 --- a/package.json +++ b/package.json @@ -6,15 +6,15 @@ "license": "AGPL-3.0", "author": "Dessalines ", "scripts": { + "analyze": "webpack --mode=none", "prebuild:dev": "yarn clean && node generate_translations.js", "build:dev": "webpack --mode=development", "prebuild:prod": "yarn clean && node generate_translations.js", "build:prod": "webpack --mode=production", "clean": "yarn run rimraf dist", - "dev": "yarn start", + "dev": "yarn build:dev --watch", "lint": "yarn translations:generate && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx \"src/**\" && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"", "prepare": "husky install", - "start": "yarn build:dev --watch", "themes:build": "sass src/assets/css/themes/:src/assets/css/themes", "themes:watch": "sass --watch src/assets/css/themes/:src/assets/css/themes", "translations:generate": "node generate_translations.js", @@ -51,6 +51,7 @@ "copy-webpack-plugin": "^11.0.0", "cross-fetch": "^3.1.5", "css-loader": "^6.7.3", + "date-fns": "^2.30.0", "emoji-mart": "^5.4.0", "emoji-short-name": "^2.0.0", "express": "~4.18.2", @@ -76,7 +77,7 @@ "markdown-it-sub": "^1.0.0", "markdown-it-sup": "^1.0.0", "mini-css-extract-plugin": "^2.7.5", - "moment": "^2.29.4", + "path-browserify": "^1.0.1", "register-service-worker": "^1.7.2", "run-node-webpack-plugin": "^1.3.0", "sanitize-html": "^2.10.0", @@ -101,6 +102,7 @@ "@types/markdown-it": "^12.2.3", "@types/markdown-it-container": "^2.0.5", "@types/node": "^20.1.2", + "@types/path-browserify": "^1.0.0", "@types/sanitize-html": "^2.9.0", "@types/serialize-javascript": "^5.0.1", "@types/toastify-js": "^1.11.1", @@ -122,6 +124,7 @@ "style-loader": "^3.3.2", "terser": "^5.17.3", "typescript": "^5.0.4", + "webpack-bundle-analyzer": "^4.9.0", "webpack-dev-server": "4.15.0" }, "packageManager": "yarn@1.22.19", diff --git a/src/client/index.tsx b/src/client/index.tsx index eb2bb80f..44d39d0b 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -1,22 +1,39 @@ import { initializeSite } from "@utils/app"; +import setDefaultOptions from "date-fns/setDefaultOptions"; import { hydrate } from "inferno-hydrate"; import { Router } from "inferno-router"; import { App } from "../shared/components/app/app"; -import { HistoryService } from "../shared/services"; +import { HistoryService, I18NextService } from "../shared/services"; import "bootstrap/js/dist/collapse"; import "bootstrap/js/dist/dropdown"; -initializeSite(window.isoData.site_res); +async function startClient() { + initializeSite(window.isoData.site_res); -const wrapper = ( - - - -); + const lang = I18NextService.i18n.language; + const locale = ( + await import( + /* webpackExclude: /\.js\.flow$/ */ + `date-fns/locale/${lang}` + ) + ).default; -const root = document.getElementById("root"); + setDefaultOptions({ + locale, + }); -if (root) { - hydrate(wrapper, root); + const wrapper = ( + + + + ); + + const root = document.getElementById("root"); + + if (root) { + hydrate(wrapper, root); + } } + +startClient(); diff --git a/src/server/index.tsx b/src/server/index.tsx index b65506b0..aecd78bb 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -1,6 +1,8 @@ +import setDefaultOptions from "date-fns/setDefaultOptions"; import express from "express"; import path from "path"; import process from "process"; +import { I18NextService } from "../shared/services"; import CatchAllHandler from "./handlers/catch-all-handler"; import ManifestHandler from "./handlers/manifest-handler"; import RobotsHandler from "./handlers/robots-handler"; @@ -34,7 +36,17 @@ server.listen(Number(port), hostname, () => { console.log(`http://${hostname}:${port}`); }); -process.on("SIGINT", () => { +process.on("SIGINT", async () => { + const lang = I18NextService.i18n.language; + const locale = ( + await import( + /* webpackExclude: /\.js\.flow$/ */ + `date-fns/locale/${lang}` + ) + ).default; + setDefaultOptions({ + locale, + }); console.info("Interrupted"); process.exit(0); }); diff --git a/src/shared/components/comment/comment-node.tsx b/src/shared/components/comment/comment-node.tsx index b558d142..b4d3d662 100644 --- a/src/shared/components/comment/comment-node.tsx +++ b/src/shared/components/comment/comment-node.tsx @@ -16,6 +16,9 @@ import { isMod, } from "@utils/roles"; import classNames from "classnames"; +import isBefore from "date-fns/isBefore"; +import parseISO from "date-fns/parseISO"; +import subMinutes from "date-fns/subMinutes"; import { Component, InfernoNode, linkEvent } from "inferno"; import { Link } from "inferno-router"; import { @@ -46,7 +49,6 @@ import { SaveComment, TransferCommunity, } from "lemmy-js-client"; -import moment from "moment"; import { commentTreeMaxDepth } from "../../config"; import { BanType, @@ -1451,9 +1453,9 @@ export class CommentNode extends Component { } get isCommentNew(): boolean { - const now = moment.utc().subtract(10, "minutes"); - const then = moment.utc(this.commentView.comment.published); - return now.isBefore(then); + const now = subMinutes(new Date(), 10); + const then = parseISO(this.commentView.comment.published); + return isBefore(now, then); } handleCommentCollapse(i: CommentNode) { diff --git a/src/shared/components/common/moment-time.tsx b/src/shared/components/common/moment-time.tsx index 1857a007..eefeeda3 100644 --- a/src/shared/components/common/moment-time.tsx +++ b/src/shared/components/common/moment-time.tsx @@ -1,6 +1,8 @@ import { capitalizeFirstLetter } from "@utils/helpers"; +import format from "date-fns/format"; +import formatDistanceToNow from "date-fns/formatDistanceToNow"; +import parseISO from "date-fns/parseISO"; import { Component } from "inferno"; -import moment from "moment"; import { I18NextService } from "../../services"; import { Icon } from "./icon"; @@ -11,22 +13,24 @@ interface MomentTimeProps { ignoreUpdated?: boolean; } +function momentFormat(input: string) { + return format(parseISO(input), "PPPPpppp"); +} + export class MomentTime extends Component { constructor(props: any, context: any) { super(props, context); - - moment.locale([...I18NextService.i18n.languages]); } createdAndModifiedTimes() { const updated = this.props.updated; let line = `${capitalizeFirstLetter( I18NextService.i18n.t("created") - )}: ${this.format(this.props.published)}`; + )}: ${momentFormat(this.props.published)}`; if (updated) { line += `\n\n\n${capitalizeFirstLetter( I18NextService.i18n.t("modified") - )} ${this.format(updated)}`; + )} ${momentFormat(updated)}`; } return line; } @@ -39,7 +43,7 @@ export class MomentTime extends Component { className="moment-time font-italics pointer unselectable" > - {moment.utc(this.props.updated).fromNow(!this.props.showAgo)} + {formatDistanceToNow(parseISO(this.props.updated))} ); } else { @@ -47,15 +51,11 @@ export class MomentTime extends Component { return ( - {moment.utc(published).fromNow(!this.props.showAgo)} + {formatDistanceToNow(parseISO(published))} ); } } - - format(input: string): string { - return moment.utc(input).local().format("LLLL"); - } } diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index e705bac8..dd4f56fa 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -15,6 +15,8 @@ import { import { amAdmin, amMod } from "@utils/roles"; import type { QueryParams } from "@utils/types"; import { Choice, RouteDataResponse } from "@utils/types"; +import formatDistanceToNowStrict from "date-fns/formatDistanceToNowStrict"; +import parseISO from "date-fns/parseISO"; import { NoOptionI18nKeys } from "i18next"; import { Component, linkEvent } from "inferno"; import { T } from "inferno-i18next-dess"; @@ -44,7 +46,6 @@ import { ModlogActionType, Person, } from "lemmy-js-client"; -import moment from "moment"; import { fetchLimit } from "../config"; import { InitialFetchRequest } from "../interfaces"; import { FirstLoadService, I18NextService } from "../services"; @@ -118,6 +119,10 @@ function getActionFromString(action?: string): ModlogActionType { return action !== undefined ? (action as ModlogActionType) : "All"; } +function getExpires(expires: string) { + return formatDistanceToNowStrict(parseISO(expires)); +} + const getModlogActionMapper = ( actionType: ModlogActionType, @@ -371,7 +376,7 @@ function renderModlogType({ type_, view }: ModlogType) { )} {expires && ( -
expires: {moment.utc(expires).fromNow()}
+
expires: {getExpires(expires)}
)} @@ -403,7 +408,7 @@ function renderModlogType({ type_, view }: ModlogType) { )} {expires && ( -
expires: {moment.utc(expires).fromNow()}
+
expires: {getExpires(expires)}
)} @@ -467,7 +472,7 @@ function renderModlogType({ type_, view }: ModlogType) { )} {expires && ( -
expires: {moment.utc(expires).fromNow()}
+
expires: {getExpires(expires)}
)} diff --git a/src/shared/components/person/profile.tsx b/src/shared/components/person/profile.tsx index d0003687..70bada82 100644 --- a/src/shared/components/person/profile.tsx +++ b/src/shared/components/person/profile.tsx @@ -23,6 +23,8 @@ import { canMod, isAdmin, isBanned } from "@utils/roles"; import type { QueryParams } from "@utils/types"; import { RouteDataResponse } from "@utils/types"; import classNames from "classnames"; +import format from "date-fns/format"; +import parseISO from "date-fns/parseISO"; import { NoOptionI18nKeys } from "i18next"; import { Component, linkEvent } from "inferno"; import { Link } from "inferno-router"; @@ -70,7 +72,6 @@ import { SortType, TransferCommunity, } from "lemmy-js-client"; -import moment from "moment"; import { fetchLimit, relTags } from "../../config"; import { InitialFetchRequest, PersonDetailsView } from "../../interfaces"; import { mdToHtml } from "../../markdown"; @@ -613,10 +614,7 @@ export class Profile extends Component< {I18NextService.i18n.t("cake_day_title")}{" "} - {moment - .utc(pv.person.published) - .local() - .format("MMM DD, YYYY")} + {format(parseISO(pv.person.published), "PPP")}
{!UserService.Instance.myUserInfo && ( diff --git a/src/shared/utils/helpers/is-cake-day.ts b/src/shared/utils/helpers/is-cake-day.ts index 694be170..f1e1c3d7 100644 --- a/src/shared/utils/helpers/is-cake-day.ts +++ b/src/shared/utils/helpers/is-cake-day.ts @@ -1,33 +1,13 @@ -import moment from "moment"; - -moment.updateLocale("en", { - relativeTime: { - future: "in %s", - past: "%s ago", - s: "<1m", - ss: "%ds", - m: "1m", - mm: "%dm", - h: "1h", - hh: "%dh", - d: "1d", - dd: "%dd", - w: "1w", - ww: "%dw", - M: "1M", - MM: "%dM", - y: "1Y", - yy: "%dY", - }, -}); +import getDayOfYear from "date-fns/getDayOfYear"; +import getYear from "date-fns/getYear"; +import parseISO from "date-fns/parseISO"; export default function isCakeDay(published: string): boolean { - const createDate = moment.utc(published).local(); - const currentDate = moment(new Date()); + const createDate = parseISO(published); + const currentDate = new Date(); return ( - createDate.date() === currentDate.date() && - createDate.month() === currentDate.month() && - createDate.year() !== currentDate.year() + getDayOfYear(createDate) === getDayOfYear(currentDate) && + getYear(createDate) !== getYear(currentDate) ); } diff --git a/webpack.config.js b/webpack.config.js index ba3ea60d..f14707a1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,6 +6,8 @@ const CopyPlugin = require("copy-webpack-plugin"); const RunNodeWebpackPlugin = require("run-node-webpack-plugin"); const merge = require("lodash/merge"); const { ServiceWorkerPlugin } = require("service-worker-webpack"); +const BundleAnalyzerPlugin = + require("webpack-bundle-analyzer").BundleAnalyzerPlugin; const banner = ` hash:[contentHash], chunkhash:[chunkhash], name:[name], filebase:[base], query:[query], file:[file] Source code: https://github.com/LemmyNet/lemmy-ui @@ -153,11 +155,8 @@ const createClientConfig = (_env, mode) => { ], }); - if (mode === "development") { - // config.cache = { - // type: "filesystem", - // name: "client", - // }; + if (mode === "none") { + config.plugins.push(new BundleAnalyzerPlugin()); } return config; diff --git a/yarn.lock b/yarn.lock index f874cb53..486729b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1202,7 +1202,7 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/runtime@^7.20.7": +"@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== @@ -1243,7 +1243,7 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@discoveryjs/json-ext@^0.5.0": +"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== @@ -1412,6 +1412,11 @@ picocolors "^1.0.0" tslib "^2.5.0" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@popperjs/core@^2.9.0", "@popperjs/core@^2.9.2": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" @@ -1630,6 +1635,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== +"@types/path-browserify@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/path-browserify/-/path-browserify-1.0.0.tgz#294ec6e88b6b0d340a3897b7120e5b393f16690e" + integrity sha512-XMCcyhSvxcch8b7rZAtFAaierBYdeHXVvg2iYnxOV0MCQHmPuRRmGZPFDRzPayxcGiiSL1Te9UIO+f3cuj0tfw== + "@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" @@ -1977,6 +1987,16 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== +acorn-walk@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.0.4: + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== + acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.2: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" @@ -2714,7 +2734,7 @@ chalk@^2.0.0, chalk@^2.0.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.0.2: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2959,6 +2979,11 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + common-tags@^1.8.0: version "1.8.2" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" @@ -3200,6 +3225,13 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^2.30.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3481,6 +3513,11 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -4576,6 +4613,13 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -6302,11 +6346,6 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: dependencies: minimist "^1.2.6" -moment@^2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -6319,6 +6358,11 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mrmime@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6916,6 +6960,11 @@ opencollective-postinstall@^2.0.3: resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + opener@~1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" @@ -7129,6 +7178,11 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -8247,6 +8301,15 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -8913,6 +8976,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -9258,6 +9326,22 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webpack-bundle-analyzer@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.0.tgz#fc093c4ab174fd3dcbd1c30b763f56d10141209d" + integrity sha512-+bXGmO1LyiNx0i9enBu3H8mv42sj/BJWhZNFwjz92tVnBa9J3JMGo2an2IXlEleoDOPn/Hofl5hr/xCpObUDtw== + dependencies: + "@discoveryjs/json-ext" "0.5.7" + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^7.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + webpack-cli@^5.1.1: version "5.1.3" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.3.tgz#6b6186270efec62394f6fefeebed0872a779f345" @@ -9710,6 +9794,11 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +ws@^7.3.1: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + ws@^8.13.0: version "8.13.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" From ca6d2fbbfb95151531c655e302b9473af6ce2434 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 20:27:27 -0400 Subject: [PATCH 40/55] remove bullet list items --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 5561b888..4931726e 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -47,8 +47,8 @@ body: attributes: label: Technical Details description: | - - Describe your environment (OS, browser, model of smartphone, etc) - - If relevant, also share any console errors and/or screenshots here. + Describe your environment (OS, browser, model of smartphone, etc) + If relevant, also share any console errors and/or screenshots here. validations: required: true - type: input From fdb370a88d0c785c377174513132e5de2cd65134 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 22 Jun 2023 21:16:51 -0400 Subject: [PATCH 41/55] v0.18.0-rc.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e7a0f1b..aaf623a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lemmy-ui", - "version": "0.18.0-rc.6", + "version": "0.18.0-rc.7", "description": "An isomorphic UI for lemmy", "repository": "https://github.com/LemmyNet/lemmy-ui", "license": "AGPL-3.0", From d127b5626da30d746aaacd37b4a0f7da5fc6ca22 Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 22:46:38 -0400 Subject: [PATCH 42/55] Fix inability to go to Home from Settings (#1506) --- src/shared/components/home/home.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 4a84664b..bad771fc 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -642,7 +642,7 @@ export class Home extends Component { const siteRes = this.state.siteRes; if (dataType === DataType.Post) { - switch (this.state.postsRes.state) { + switch (this.state.postsRes?.state) { case "loading": return (
From e5e8f29c67b6c154fa46164329a4cb30ee1c82db Mon Sep 17 00:00:00 2001 From: Alec Armbruster <35377827+alectrocute@users.noreply.github.com> Date: Thu, 22 Jun 2023 22:56:51 -0400 Subject: [PATCH 43/55] Remove `noIndent` prop from comment nodes on person view (#1491) * remove noIdent prop from person details comment nodes * remove noIndent prop from usage in Inbox --- src/shared/components/person/inbox.tsx | 4 ---- src/shared/components/person/person-details.tsx | 1 - 2 files changed, 5 deletions(-) diff --git a/src/shared/components/person/inbox.tsx b/src/shared/components/person/inbox.tsx index 062fc01c..395875be 100644 --- a/src/shared/components/person/inbox.tsx +++ b/src/shared/components/person/inbox.tsx @@ -449,7 +449,6 @@ export class Inbox extends Component { ]} viewType={CommentViewType.Flat} finished={this.state.finished} - noIndent markable showCommunity showContext @@ -489,7 +488,6 @@ export class Inbox extends Component { ]} finished={this.state.finished} viewType={CommentViewType.Flat} - noIndent markable showCommunity showContext @@ -567,7 +565,6 @@ export class Inbox extends Component { nodes={commentsToFlatNodes(replies)} viewType={CommentViewType.Flat} finished={this.state.finished} - noIndent markable showCommunity showContext @@ -617,7 +614,6 @@ export class Inbox extends Component { nodes={[{ comment_view: umv, children: [], depth: 0 }]} viewType={CommentViewType.Flat} finished={this.state.finished} - noIndent markable showCommunity showContext diff --git a/src/shared/components/person/person-details.tsx b/src/shared/components/person/person-details.tsx index 3771b844..b2b74b6e 100644 --- a/src/shared/components/person/person-details.tsx +++ b/src/shared/components/person/person-details.tsx @@ -145,7 +145,6 @@ export class PersonDetails extends Component { finished={this.props.finished} admins={this.props.admins} noBorder - noIndent showCommunity showContext enableDownvotes={this.props.enableDownvotes} From 8dc38c7cee35b54186c726e7d95c9f457e08a3c9 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Thu, 22 Jun 2023 23:30:41 -0400 Subject: [PATCH 44/55] Remove unused dep --- package.json | 1 - yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/package.json b/package.json index e2a9ce64..aab8ecb7 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,6 @@ "markdown-it-sub": "^1.0.0", "markdown-it-sup": "^1.0.0", "mini-css-extract-plugin": "^2.7.5", - "path-browserify": "^1.0.1", "register-service-worker": "^1.7.2", "run-node-webpack-plugin": "^1.3.0", "sanitize-html": "^2.10.0", diff --git a/yarn.lock b/yarn.lock index 486729b6..76d9355f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7178,11 +7178,6 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -path-browserify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" From 2c85c87e4494210f55522653deb8e552b84cbc23 Mon Sep 17 00:00:00 2001 From: dudeami0 Date: Thu, 22 Jun 2023 23:30:42 -0400 Subject: [PATCH 45/55] Fix server-side rendering after first load. --- src/shared/components/community/communities.tsx | 3 ++- src/shared/components/community/community.tsx | 3 ++- src/shared/components/home/admin-settings.tsx | 3 ++- src/shared/components/home/home.tsx | 3 ++- src/shared/components/home/instances.tsx | 3 ++- src/shared/components/modlog.tsx | 3 ++- src/shared/components/person/inbox.tsx | 3 ++- src/shared/components/person/profile.tsx | 8 ++++++-- .../components/person/registration-applications.tsx | 3 ++- src/shared/components/person/reports.tsx | 3 ++- src/shared/components/post/create-post.tsx | 3 ++- src/shared/components/post/post.tsx | 2 +- .../components/private_message/create-private-message.tsx | 3 ++- src/shared/components/search.tsx | 8 ++++++-- 14 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/shared/components/community/communities.tsx b/src/shared/components/community/communities.tsx index a84ec055..35e89c36 100644 --- a/src/shared/components/community/communities.tsx +++ b/src/shared/components/community/communities.tsx @@ -5,6 +5,7 @@ import { setIsoData, showLocal, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -67,7 +68,7 @@ export class Communities extends Component { this.handleListingTypeChange = this.handleListingTypeChange.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { listCommunitiesResponse } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index 111b47cd..3e7615a9 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -15,6 +15,7 @@ import { updateCommunityBlock, updatePersonBlock, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -197,7 +198,7 @@ export class Community extends Component< this.handleFeaturePost = this.handleFeaturePost.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { communityRes, commentsRes, postsRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index 7ac69fed..6ab5b659 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -4,6 +4,7 @@ import { setIsoData, showLocal, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { capitalizeFirstLetter } from "@utils/helpers"; import { RouteDataResponse } from "@utils/types"; import classNames from "classnames"; @@ -74,7 +75,7 @@ export class AdminSettings extends Component { this.handleCreateEmoji = this.handleCreateEmoji.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { bannedRes, instancesRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index bad771fc..da1be70b 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -13,6 +13,7 @@ import { showLocal, updatePersonBlock, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -263,7 +264,7 @@ export class Home extends Component { this.handleFeaturePost = this.handleFeaturePost.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { trendingCommunitiesRes, commentsRes, postsRes } = this.isoData.routeData; diff --git a/src/shared/components/home/instances.tsx b/src/shared/components/home/instances.tsx index b54c96af..9c38cf41 100644 --- a/src/shared/components/home/instances.tsx +++ b/src/shared/components/home/instances.tsx @@ -1,4 +1,5 @@ import { setIsoData } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component } from "inferno"; import { @@ -35,7 +36,7 @@ export class Instances extends Component { super(props, context); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { this.state = { ...this.state, instancesRes: this.isoData.routeData.federatedInstancesResponse, diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index 722f6e70..e8c707ed 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -5,6 +5,7 @@ import { personToChoice, setIsoData, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { debounce, getIdFromString, @@ -660,7 +661,7 @@ export class Modlog extends Component< this.handleModChange = this.handleModChange.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { res, communityRes, modUserResponse, userResponse } = this.isoData.routeData; diff --git a/src/shared/components/person/inbox.tsx b/src/shared/components/person/inbox.tsx index 395875be..3c913701 100644 --- a/src/shared/components/person/inbox.tsx +++ b/src/shared/components/person/inbox.tsx @@ -11,6 +11,7 @@ import { setIsoData, updatePersonBlock, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component, linkEvent } from "inferno"; import { @@ -163,7 +164,7 @@ export class Inbox extends Component { this.handleEditMessage = this.handleEditMessage.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { mentionsRes, messagesRes, repliesRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/person/profile.tsx b/src/shared/components/person/profile.tsx index d0003687..6e0530d9 100644 --- a/src/shared/components/person/profile.tsx +++ b/src/shared/components/person/profile.tsx @@ -10,7 +10,11 @@ import { setIsoData, updatePersonBlock, } from "@utils/app"; -import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; +import { + isBrowser, + restoreScrollPosition, + saveScrollPosition, +} from "@utils/browser"; import { capitalizeFirstLetter, futureDaysToUnixTime, @@ -206,7 +210,7 @@ export class Profile extends Component< this.handleFeaturePost = this.handleFeaturePost.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { this.state = { ...this.state, personRes: this.isoData.routeData.personResponse, diff --git a/src/shared/components/person/registration-applications.tsx b/src/shared/components/person/registration-applications.tsx index d9eb6ad0..5e92c073 100644 --- a/src/shared/components/person/registration-applications.tsx +++ b/src/shared/components/person/registration-applications.tsx @@ -3,6 +3,7 @@ import { myAuthRequired, setIsoData, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component, linkEvent } from "inferno"; import { @@ -58,7 +59,7 @@ export class RegistrationApplications extends Component< this.handleApproveApplication = this.handleApproveApplication.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { this.state = { ...this.state, appsRes: this.isoData.routeData.listRegistrationApplicationsResponse, diff --git a/src/shared/components/person/reports.tsx b/src/shared/components/person/reports.tsx index 8f5eaf36..9d04c8a7 100644 --- a/src/shared/components/person/reports.tsx +++ b/src/shared/components/person/reports.tsx @@ -5,6 +5,7 @@ import { myAuthRequired, setIsoData, } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { amAdmin } from "@utils/roles"; import { RouteDataResponse } from "@utils/types"; import { Component, linkEvent } from "inferno"; @@ -108,7 +109,7 @@ export class Reports extends Component { this.handleResolvePrivateMessageReport.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { commentReportsRes, postReportsRes, messageReportsRes } = this.isoData.routeData; diff --git a/src/shared/components/post/create-post.tsx b/src/shared/components/post/create-post.tsx index fe941830..ed686f31 100644 --- a/src/shared/components/post/create-post.tsx +++ b/src/shared/components/post/create-post.tsx @@ -1,4 +1,5 @@ import { enableDownvotes, enableNsfw, myAuth, setIsoData } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { getIdFromString, getQueryParams } from "@utils/helpers"; import type { QueryParams } from "@utils/types"; import { Choice, RouteDataResponse } from "@utils/types"; @@ -69,7 +70,7 @@ export class CreatePost extends Component< this.handleSelectedCommunityChange.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { communityResponse: communityRes, initialCommunitiesRes } = this.isoData.routeData; diff --git a/src/shared/components/post/post.tsx b/src/shared/components/post/post.tsx index f0aa3ff5..54823f22 100644 --- a/src/shared/components/post/post.tsx +++ b/src/shared/components/post/post.tsx @@ -174,7 +174,7 @@ export class Post extends Component { this.state = { ...this.state, commentSectionRef: createRef() }; // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { commentsRes, postRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/private_message/create-private-message.tsx b/src/shared/components/private_message/create-private-message.tsx index 8afd3488..89ed7598 100644 --- a/src/shared/components/private_message/create-private-message.tsx +++ b/src/shared/components/private_message/create-private-message.tsx @@ -1,4 +1,5 @@ import { getRecipientIdFromProps, myAuth, setIsoData } from "@utils/app"; +import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component } from "inferno"; import { @@ -44,7 +45,7 @@ export class CreatePrivateMessage extends Component< this.handlePrivateMessageCreate.bind(this); // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { this.state = { ...this.state, recipientRes: this.isoData.routeData.recipientDetailsResponse, diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx index 473b18c4..3d04c500 100644 --- a/src/shared/components/search.tsx +++ b/src/shared/components/search.tsx @@ -11,7 +11,11 @@ import { setIsoData, showLocal, } from "@utils/app"; -import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; +import { + isBrowser, + restoreScrollPosition, + saveScrollPosition, +} from "@utils/browser"; import { capitalizeFirstLetter, debounce, @@ -270,7 +274,7 @@ export class Search extends Component { }; // Only fetch the data if coming from another route - if (FirstLoadService.isFirstLoad) { + if (!isBrowser() || FirstLoadService.isFirstLoad) { const { communityResponse: communityRes, creatorDetailsResponse: creatorDetailsRes, From d706b6ba27866ad8b57d9b48743f04e63ba2dcbe Mon Sep 17 00:00:00 2001 From: dudeami0 Date: Fri, 23 Jun 2023 01:04:03 -0400 Subject: [PATCH 46/55] Moved `!isBrowser()` check to `FirstLoadServer.isFirstLoad` --- src/shared/components/community/communities.tsx | 3 +-- src/shared/components/community/community.tsx | 3 +-- src/shared/components/home/admin-settings.tsx | 3 +-- src/shared/components/home/home.tsx | 3 +-- src/shared/components/home/instances.tsx | 3 +-- src/shared/components/modlog.tsx | 3 +-- src/shared/components/person/inbox.tsx | 3 +-- src/shared/components/person/profile.tsx | 8 ++------ .../components/person/registration-applications.tsx | 3 +-- src/shared/components/person/reports.tsx | 3 +-- src/shared/components/post/create-post.tsx | 3 +-- src/shared/components/post/post.tsx | 2 +- .../components/private_message/create-private-message.tsx | 3 +-- src/shared/components/search.tsx | 8 ++------ src/shared/services/FirstLoadService.ts | 4 +++- 15 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/shared/components/community/communities.tsx b/src/shared/components/community/communities.tsx index 35e89c36..a84ec055 100644 --- a/src/shared/components/community/communities.tsx +++ b/src/shared/components/community/communities.tsx @@ -5,7 +5,6 @@ import { setIsoData, showLocal, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -68,7 +67,7 @@ export class Communities extends Component { this.handleListingTypeChange = this.handleListingTypeChange.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { listCommunitiesResponse } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index 3e7615a9..111b47cd 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -15,7 +15,6 @@ import { updateCommunityBlock, updatePersonBlock, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -198,7 +197,7 @@ export class Community extends Component< this.handleFeaturePost = this.handleFeaturePost.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { communityRes, commentsRes, postsRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index 6ab5b659..7ac69fed 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -4,7 +4,6 @@ import { setIsoData, showLocal, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { capitalizeFirstLetter } from "@utils/helpers"; import { RouteDataResponse } from "@utils/types"; import classNames from "classnames"; @@ -75,7 +74,7 @@ export class AdminSettings extends Component { this.handleCreateEmoji = this.handleCreateEmoji.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { bannedRes, instancesRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index da1be70b..bad771fc 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -13,7 +13,6 @@ import { showLocal, updatePersonBlock, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { getPageFromString, getQueryParams, @@ -264,7 +263,7 @@ export class Home extends Component { this.handleFeaturePost = this.handleFeaturePost.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { trendingCommunitiesRes, commentsRes, postsRes } = this.isoData.routeData; diff --git a/src/shared/components/home/instances.tsx b/src/shared/components/home/instances.tsx index 9c38cf41..b54c96af 100644 --- a/src/shared/components/home/instances.tsx +++ b/src/shared/components/home/instances.tsx @@ -1,5 +1,4 @@ import { setIsoData } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component } from "inferno"; import { @@ -36,7 +35,7 @@ export class Instances extends Component { super(props, context); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { this.state = { ...this.state, instancesRes: this.isoData.routeData.federatedInstancesResponse, diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index e8c707ed..722f6e70 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -5,7 +5,6 @@ import { personToChoice, setIsoData, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { debounce, getIdFromString, @@ -661,7 +660,7 @@ export class Modlog extends Component< this.handleModChange = this.handleModChange.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { res, communityRes, modUserResponse, userResponse } = this.isoData.routeData; diff --git a/src/shared/components/person/inbox.tsx b/src/shared/components/person/inbox.tsx index 3c913701..395875be 100644 --- a/src/shared/components/person/inbox.tsx +++ b/src/shared/components/person/inbox.tsx @@ -11,7 +11,6 @@ import { setIsoData, updatePersonBlock, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component, linkEvent } from "inferno"; import { @@ -164,7 +163,7 @@ export class Inbox extends Component { this.handleEditMessage = this.handleEditMessage.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { mentionsRes, messagesRes, repliesRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/person/profile.tsx b/src/shared/components/person/profile.tsx index 6e0530d9..d0003687 100644 --- a/src/shared/components/person/profile.tsx +++ b/src/shared/components/person/profile.tsx @@ -10,11 +10,7 @@ import { setIsoData, updatePersonBlock, } from "@utils/app"; -import { - isBrowser, - restoreScrollPosition, - saveScrollPosition, -} from "@utils/browser"; +import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; import { capitalizeFirstLetter, futureDaysToUnixTime, @@ -210,7 +206,7 @@ export class Profile extends Component< this.handleFeaturePost = this.handleFeaturePost.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { this.state = { ...this.state, personRes: this.isoData.routeData.personResponse, diff --git a/src/shared/components/person/registration-applications.tsx b/src/shared/components/person/registration-applications.tsx index 5e92c073..d9eb6ad0 100644 --- a/src/shared/components/person/registration-applications.tsx +++ b/src/shared/components/person/registration-applications.tsx @@ -3,7 +3,6 @@ import { myAuthRequired, setIsoData, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component, linkEvent } from "inferno"; import { @@ -59,7 +58,7 @@ export class RegistrationApplications extends Component< this.handleApproveApplication = this.handleApproveApplication.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { this.state = { ...this.state, appsRes: this.isoData.routeData.listRegistrationApplicationsResponse, diff --git a/src/shared/components/person/reports.tsx b/src/shared/components/person/reports.tsx index 9d04c8a7..8f5eaf36 100644 --- a/src/shared/components/person/reports.tsx +++ b/src/shared/components/person/reports.tsx @@ -5,7 +5,6 @@ import { myAuthRequired, setIsoData, } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { amAdmin } from "@utils/roles"; import { RouteDataResponse } from "@utils/types"; import { Component, linkEvent } from "inferno"; @@ -109,7 +108,7 @@ export class Reports extends Component { this.handleResolvePrivateMessageReport.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { commentReportsRes, postReportsRes, messageReportsRes } = this.isoData.routeData; diff --git a/src/shared/components/post/create-post.tsx b/src/shared/components/post/create-post.tsx index ed686f31..fe941830 100644 --- a/src/shared/components/post/create-post.tsx +++ b/src/shared/components/post/create-post.tsx @@ -1,5 +1,4 @@ import { enableDownvotes, enableNsfw, myAuth, setIsoData } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { getIdFromString, getQueryParams } from "@utils/helpers"; import type { QueryParams } from "@utils/types"; import { Choice, RouteDataResponse } from "@utils/types"; @@ -70,7 +69,7 @@ export class CreatePost extends Component< this.handleSelectedCommunityChange.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { communityResponse: communityRes, initialCommunitiesRes } = this.isoData.routeData; diff --git a/src/shared/components/post/post.tsx b/src/shared/components/post/post.tsx index 54823f22..f0aa3ff5 100644 --- a/src/shared/components/post/post.tsx +++ b/src/shared/components/post/post.tsx @@ -174,7 +174,7 @@ export class Post extends Component { this.state = { ...this.state, commentSectionRef: createRef() }; // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { commentsRes, postRes } = this.isoData.routeData; this.state = { diff --git a/src/shared/components/private_message/create-private-message.tsx b/src/shared/components/private_message/create-private-message.tsx index 89ed7598..8afd3488 100644 --- a/src/shared/components/private_message/create-private-message.tsx +++ b/src/shared/components/private_message/create-private-message.tsx @@ -1,5 +1,4 @@ import { getRecipientIdFromProps, myAuth, setIsoData } from "@utils/app"; -import { isBrowser } from "@utils/browser"; import { RouteDataResponse } from "@utils/types"; import { Component } from "inferno"; import { @@ -45,7 +44,7 @@ export class CreatePrivateMessage extends Component< this.handlePrivateMessageCreate.bind(this); // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { this.state = { ...this.state, recipientRes: this.isoData.routeData.recipientDetailsResponse, diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx index 3d04c500..473b18c4 100644 --- a/src/shared/components/search.tsx +++ b/src/shared/components/search.tsx @@ -11,11 +11,7 @@ import { setIsoData, showLocal, } from "@utils/app"; -import { - isBrowser, - restoreScrollPosition, - saveScrollPosition, -} from "@utils/browser"; +import { restoreScrollPosition, saveScrollPosition } from "@utils/browser"; import { capitalizeFirstLetter, debounce, @@ -274,7 +270,7 @@ export class Search extends Component { }; // Only fetch the data if coming from another route - if (!isBrowser() || FirstLoadService.isFirstLoad) { + if (FirstLoadService.isFirstLoad) { const { communityResponse: communityRes, creatorDetailsResponse: creatorDetailsRes, diff --git a/src/shared/services/FirstLoadService.ts b/src/shared/services/FirstLoadService.ts index b7558eff..926e3acd 100644 --- a/src/shared/services/FirstLoadService.ts +++ b/src/shared/services/FirstLoadService.ts @@ -1,3 +1,5 @@ +import { isBrowser } from "@utils/browser"; + export class FirstLoadService { #isFirstLoad: boolean; static #instance: FirstLoadService; @@ -20,6 +22,6 @@ export class FirstLoadService { } static get isFirstLoad() { - return this.#Instance.isFirstLoad; + return !isBrowser() || this.#Instance.isFirstLoad; } } From 2f5933240084c309e634b6fd9158881f51f4d21a Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 23 Jun 2023 07:06:05 -0400 Subject: [PATCH 47/55] v0.18.0-rc.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aaf623a6..b43a568b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lemmy-ui", - "version": "0.18.0-rc.7", + "version": "0.18.0-rc.8", "description": "An isomorphic UI for lemmy", "repository": "https://github.com/LemmyNet/lemmy-ui", "license": "AGPL-3.0", From 4a7bfe41d9ba053649fd57259fa9b8fba913ea41 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 23 Jun 2023 08:40:00 -0400 Subject: [PATCH 48/55] v0.18.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b43a568b..45d4daf1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lemmy-ui", - "version": "0.18.0-rc.8", + "version": "0.18.0", "description": "An isomorphic UI for lemmy", "repository": "https://github.com/LemmyNet/lemmy-ui", "license": "AGPL-3.0", From 955afeac3c084c0db9df426f6e960cf76c0bf2f4 Mon Sep 17 00:00:00 2001 From: dudeami0 Date: Fri, 23 Jun 2023 08:54:55 -0400 Subject: [PATCH 49/55] Fix homepage `scrollTo(0, 0)` failing when document size changes. --- src/shared/components/home/home.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index bad771fc..71e5842e 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -101,6 +101,7 @@ interface HomeState { showTrendingMobile: boolean; showSidebarMobile: boolean; subscribedCollapsed: boolean; + scrolled: boolean; tagline?: string; siteRes: GetSiteResponse; finished: Map; @@ -217,6 +218,7 @@ export class Home extends Component { postsRes: { state: "empty" }, commentsRes: { state: "empty" }, trendingCommunitiesRes: { state: "empty" }, + scrolled: true, siteRes: this.isoData.site_res, showSubscribedMobile: false, showTrendingMobile: false, @@ -620,6 +622,11 @@ export class Home extends Component { search: getQueryString(queryParams), }); + if (!this.state.scrolled) { + this.setState({ scrolled: true }); + setTimeout(() => window.scrollTo(0, 0), 0); + } + await this.fetchData(); } @@ -815,23 +822,23 @@ export class Home extends Component { } 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) { From 5d664656a208776f7c596c23fe61ef9c190435f5 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Fri, 23 Jun 2023 10:10:41 -0400 Subject: [PATCH 50/55] Extract date fns setup --- src/client/index.tsx | 17 +++-------------- src/server/index.tsx | 16 +++------------- src/shared/utils/app/index.ts | 2 ++ src/shared/utils/app/setup-date-fns.ts | 19 +++++++++++++++++++ 4 files changed, 27 insertions(+), 27 deletions(-) create mode 100644 src/shared/utils/app/setup-date-fns.ts diff --git a/src/client/index.tsx b/src/client/index.tsx index 44d39d0b..1b7dde85 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -1,9 +1,8 @@ -import { initializeSite } from "@utils/app"; -import setDefaultOptions from "date-fns/setDefaultOptions"; +import { initializeSite, setupI18Next as setupDateFns } from "@utils/app"; import { hydrate } from "inferno-hydrate"; import { Router } from "inferno-router"; import { App } from "../shared/components/app/app"; -import { HistoryService, I18NextService } from "../shared/services"; +import { HistoryService } from "../shared/services"; import "bootstrap/js/dist/collapse"; import "bootstrap/js/dist/dropdown"; @@ -11,17 +10,7 @@ import "bootstrap/js/dist/dropdown"; async function startClient() { initializeSite(window.isoData.site_res); - const lang = I18NextService.i18n.language; - const locale = ( - await import( - /* webpackExclude: /\.js\.flow$/ */ - `date-fns/locale/${lang}` - ) - ).default; - - setDefaultOptions({ - locale, - }); + await setupDateFns(); const wrapper = ( diff --git a/src/server/index.tsx b/src/server/index.tsx index aecd78bb..8135e650 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -1,8 +1,7 @@ -import setDefaultOptions from "date-fns/setDefaultOptions"; +import { setupI18Next as setupDateFns } from "@utils/app"; import express from "express"; import path from "path"; import process from "process"; -import { I18NextService } from "../shared/services"; import CatchAllHandler from "./handlers/catch-all-handler"; import ManifestHandler from "./handlers/manifest-handler"; import RobotsHandler from "./handlers/robots-handler"; @@ -33,20 +32,11 @@ server.get("/css/themelist", ThemesListHandler); server.get("/*", CatchAllHandler); server.listen(Number(port), hostname, () => { + setupDateFns(); console.log(`http://${hostname}:${port}`); }); -process.on("SIGINT", async () => { - const lang = I18NextService.i18n.language; - const locale = ( - await import( - /* webpackExclude: /\.js\.flow$/ */ - `date-fns/locale/${lang}` - ) - ).default; - setDefaultOptions({ - locale, - }); +process.on("SIGINT", () => { console.info("Interrupted"); process.exit(0); }); diff --git a/src/shared/utils/app/index.ts b/src/shared/utils/app/index.ts index cdae2677..378ebb75 100644 --- a/src/shared/utils/app/index.ts +++ b/src/shared/utils/app/index.ts @@ -46,6 +46,7 @@ import searchCommentTree from "./search-comment-tree"; import selectableLanguages from "./selectable-languages"; import setIsoData from "./set-iso-data"; import setTheme from "./set-theme"; +import setupI18Next from "./setup-date-fns"; import showAvatars from "./show-avatars"; import showLocal from "./show-local"; import showScores from "./show-scores"; @@ -102,6 +103,7 @@ export { selectableLanguages, setIsoData, setTheme, + setupI18Next, showAvatars, showLocal, showScores, diff --git a/src/shared/utils/app/setup-date-fns.ts b/src/shared/utils/app/setup-date-fns.ts new file mode 100644 index 00000000..fe957205 --- /dev/null +++ b/src/shared/utils/app/setup-date-fns.ts @@ -0,0 +1,19 @@ +import setDefaultOptions from "date-fns/setDefaultOptions"; +import { I18NextService } from "../../services"; + +export default async function () { + let lang = I18NextService.i18n.language; + if (lang === "en") { + lang = "en-US"; + } + + const locale = ( + await import( + /* webpackExclude: /\.js\.flow$/ */ + `date-fns/locale/${lang}` + ) + ).default; + setDefaultOptions({ + locale, + }); +} From 8f9b231487cfc22aa25f6103db94e755e9e4c544 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Fri, 23 Jun 2023 10:33:07 -0400 Subject: [PATCH 51/55] Make date distance format use correct verbiage --- src/shared/components/common/moment-time.tsx | 7 +++---- src/shared/components/modlog.tsx | 13 ++++--------- src/shared/utils/helpers/format-past-date.ts | 12 ++++++++++++ src/shared/utils/helpers/index.ts | 2 ++ 4 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 src/shared/utils/helpers/format-past-date.ts diff --git a/src/shared/components/common/moment-time.tsx b/src/shared/components/common/moment-time.tsx index eefeeda3..fc83ab46 100644 --- a/src/shared/components/common/moment-time.tsx +++ b/src/shared/components/common/moment-time.tsx @@ -1,6 +1,5 @@ -import { capitalizeFirstLetter } from "@utils/helpers"; +import { capitalizeFirstLetter, formatPastDate } from "@utils/helpers"; import format from "date-fns/format"; -import formatDistanceToNow from "date-fns/formatDistanceToNow"; import parseISO from "date-fns/parseISO"; import { Component } from "inferno"; import { I18NextService } from "../../services"; @@ -43,7 +42,7 @@ export class MomentTime extends Component { className="moment-time font-italics pointer unselectable" > - {formatDistanceToNow(parseISO(this.props.updated))} + {formatPastDate(this.props.updated)} ); } else { @@ -53,7 +52,7 @@ export class MomentTime extends Component { className="moment-time pointer unselectable" data-tippy-content={momentFormat(published)} > - {formatDistanceToNow(parseISO(published))} + {formatPastDate(published)} ); } diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index 0d5afbaa..f12f5b63 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -7,6 +7,7 @@ import { } from "@utils/app"; import { debounce, + formatPastDate, getIdFromString, getPageFromString, getQueryParams, @@ -15,8 +16,6 @@ import { import { amAdmin, amMod } from "@utils/roles"; import type { QueryParams } from "@utils/types"; import { Choice, RouteDataResponse } from "@utils/types"; -import formatDistanceToNowStrict from "date-fns/formatDistanceToNowStrict"; -import parseISO from "date-fns/parseISO"; import { NoOptionI18nKeys } from "i18next"; import { Component, linkEvent } from "inferno"; import { T } from "inferno-i18next-dess"; @@ -119,10 +118,6 @@ function getActionFromString(action?: string): ModlogActionType { return action !== undefined ? (action as ModlogActionType) : "All"; } -function getExpires(expires: string) { - return formatDistanceToNowStrict(parseISO(expires)); -} - const getModlogActionMapper = ( actionType: ModlogActionType, @@ -376,7 +371,7 @@ function renderModlogType({ type_, view }: ModlogType) { )} {expires && ( -
expires: {getExpires(expires)}
+
expires: {formatPastDate(expires)}
)} @@ -408,7 +403,7 @@ function renderModlogType({ type_, view }: ModlogType) { )} {expires && ( -
expires: {getExpires(expires)}
+
expires: {formatPastDate(expires)}
)} @@ -472,7 +467,7 @@ function renderModlogType({ type_, view }: ModlogType) { )} {expires && ( -
expires: {getExpires(expires)}
+
expires: {formatPastDate(expires)}
)} diff --git a/src/shared/utils/helpers/format-past-date.ts b/src/shared/utils/helpers/format-past-date.ts new file mode 100644 index 00000000..78bc2a2d --- /dev/null +++ b/src/shared/utils/helpers/format-past-date.ts @@ -0,0 +1,12 @@ +import formatDistanceStrict from "date-fns/formatDistanceStrict"; +import parseISO from "date-fns/parseISO"; + +export default function (dateString?: string) { + return formatDistanceStrict( + parseISO(dateString ?? Date.now().toString()), + new Date(), + { + addSuffix: true, + } + ); +} diff --git a/src/shared/utils/helpers/index.ts b/src/shared/utils/helpers/index.ts index 36ae83fa..3420adbc 100644 --- a/src/shared/utils/helpers/index.ts +++ b/src/shared/utils/helpers/index.ts @@ -1,6 +1,7 @@ import capitalizeFirstLetter from "./capitalize-first-letter"; import debounce from "./debounce"; import editListImmutable from "./edit-list-immutable"; +import formatPastDate from "./format-past-date"; import futureDaysToUnixTime from "./future-days-to-unix-time"; import getIdFromString from "./get-id-from-string"; import getPageFromString from "./get-page-from-string"; @@ -26,6 +27,7 @@ export { capitalizeFirstLetter, debounce, editListImmutable, + formatPastDate, futureDaysToUnixTime, getIdFromString, getPageFromString, From 847b71319bfafeccc9dc1982229aefaa46493153 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Fri, 23 Jun 2023 10:36:21 -0400 Subject: [PATCH 52/55] Change function name --- src/client/index.tsx | 2 +- src/server/index.tsx | 2 +- src/shared/utils/app/index.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/index.tsx b/src/client/index.tsx index 1b7dde85..36059f97 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -1,4 +1,4 @@ -import { initializeSite, setupI18Next as setupDateFns } from "@utils/app"; +import { initializeSite, setupDateFns } from "@utils/app"; import { hydrate } from "inferno-hydrate"; import { Router } from "inferno-router"; import { App } from "../shared/components/app/app"; diff --git a/src/server/index.tsx b/src/server/index.tsx index 8135e650..25a1be64 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -1,4 +1,4 @@ -import { setupI18Next as setupDateFns } from "@utils/app"; +import { setupDateFns } from "@utils/app"; import express from "express"; import path from "path"; import process from "process"; diff --git a/src/shared/utils/app/index.ts b/src/shared/utils/app/index.ts index 378ebb75..9993ac72 100644 --- a/src/shared/utils/app/index.ts +++ b/src/shared/utils/app/index.ts @@ -46,7 +46,7 @@ import searchCommentTree from "./search-comment-tree"; import selectableLanguages from "./selectable-languages"; import setIsoData from "./set-iso-data"; import setTheme from "./set-theme"; -import setupI18Next from "./setup-date-fns"; +import setupDateFns from "./setup-date-fns"; import showAvatars from "./show-avatars"; import showLocal from "./show-local"; import showScores from "./show-scores"; @@ -103,7 +103,7 @@ export { selectableLanguages, setIsoData, setTheme, - setupI18Next, + setupDateFns, showAvatars, showLocal, showScores, From d06d7f81238972020bae1763db25e0de9a789c46 Mon Sep 17 00:00:00 2001 From: dudeami0 Date: Fri, 23 Jun 2023 14:27:35 -0400 Subject: [PATCH 53/55] 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"; From 2b8ee2fa31c2647559334cc9a5b61e101334ad47 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Fri, 23 Jun 2023 14:33:26 -0400 Subject: [PATCH 54/55] Give function better name --- src/shared/components/common/moment-time.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/components/common/moment-time.tsx b/src/shared/components/common/moment-time.tsx index fc83ab46..7c5693ed 100644 --- a/src/shared/components/common/moment-time.tsx +++ b/src/shared/components/common/moment-time.tsx @@ -12,7 +12,7 @@ interface MomentTimeProps { ignoreUpdated?: boolean; } -function momentFormat(input: string) { +function formatDate(input: string) { return format(parseISO(input), "PPPPpppp"); } @@ -25,11 +25,11 @@ export class MomentTime extends Component { const updated = this.props.updated; let line = `${capitalizeFirstLetter( I18NextService.i18n.t("created") - )}: ${momentFormat(this.props.published)}`; + )}: ${formatDate(this.props.published)}`; if (updated) { line += `\n\n\n${capitalizeFirstLetter( I18NextService.i18n.t("modified") - )} ${momentFormat(updated)}`; + )} ${formatDate(updated)}`; } return line; } @@ -50,7 +50,7 @@ export class MomentTime extends Component { return ( {formatPastDate(published)} From 5e5e05c808fe6ddb0265dce29da684a7d3fb7499 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Fri, 23 Jun 2023 15:16:04 -0400 Subject: [PATCH 55/55] Fix issue when navigating awat from settings --- src/shared/components/community/create-community.tsx | 4 +++- src/shared/components/home/legal.tsx | 4 +++- src/shared/components/home/login.tsx | 4 +++- src/shared/components/home/setup.tsx | 4 +++- src/shared/components/home/signup.tsx | 4 +++- src/shared/components/person/password-change.tsx | 9 ++++++++- src/shared/components/person/settings.tsx | 5 +++-- src/shared/components/person/verify-email.tsx | 4 +++- 8 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/shared/components/community/create-community.tsx b/src/shared/components/community/create-community.tsx index 2ce5af5a..aad6630e 100644 --- a/src/shared/components/community/create-community.tsx +++ b/src/shared/components/community/create-community.tsx @@ -4,7 +4,7 @@ import { CreateCommunity as CreateCommunityI, GetSiteResponse, } from "lemmy-js-client"; -import { HttpService, I18NextService } from "../../services"; +import { FirstLoadService, HttpService, I18NextService } from "../../services"; import { HtmlTags } from "../common/html-tags"; import { CommunityForm } from "./community-form"; @@ -22,6 +22,8 @@ export class CreateCommunity extends Component { constructor(props: any, context: any) { super(props, context); this.handleCommunityCreate = this.handleCommunityCreate.bind(this); + + FirstLoadService.isFirstLoad; } get documentTitle(): string { diff --git a/src/shared/components/home/legal.tsx b/src/shared/components/home/legal.tsx index 85a413eb..750a91e9 100644 --- a/src/shared/components/home/legal.tsx +++ b/src/shared/components/home/legal.tsx @@ -2,7 +2,7 @@ import { setIsoData } from "@utils/app"; import { Component } from "inferno"; import { GetSiteResponse } from "lemmy-js-client"; import { mdToHtml } from "../../markdown"; -import { I18NextService } from "../../services"; +import { FirstLoadService, I18NextService } from "../../services"; import { HtmlTags } from "../common/html-tags"; interface LegalState { @@ -17,6 +17,8 @@ export class Legal extends Component { constructor(props: any, context: any) { super(props, context); + + FirstLoadService.isFirstLoad; } get documentTitle(): string { diff --git a/src/shared/components/home/login.tsx b/src/shared/components/home/login.tsx index 1853a82b..d5dd4d29 100644 --- a/src/shared/components/home/login.tsx +++ b/src/shared/components/home/login.tsx @@ -3,7 +3,7 @@ import { isBrowser } from "@utils/browser"; import { validEmail } from "@utils/helpers"; import { Component, linkEvent } from "inferno"; import { GetSiteResponse, LoginResponse } from "lemmy-js-client"; -import { I18NextService, UserService } from "../../services"; +import { FirstLoadService, I18NextService, UserService } from "../../services"; import { HttpService, RequestState } from "../../services/HttpService"; import { toast } from "../../toast"; import { HtmlTags } from "../common/html-tags"; @@ -32,6 +32,8 @@ export class Login extends Component { constructor(props: any, context: any) { super(props, context); + + FirstLoadService.isFirstLoad; } componentDidMount() { diff --git a/src/shared/components/home/setup.tsx b/src/shared/components/home/setup.tsx index bed12620..fb4c710f 100644 --- a/src/shared/components/home/setup.tsx +++ b/src/shared/components/home/setup.tsx @@ -7,7 +7,7 @@ import { LoginResponse, Register, } from "lemmy-js-client"; -import { I18NextService, UserService } from "../../services"; +import { FirstLoadService, I18NextService, UserService } from "../../services"; import { HttpService, RequestState } from "../../services/HttpService"; import { Spinner } from "../common/icon"; import { SiteForm } from "./site-form"; @@ -47,6 +47,8 @@ export class Setup extends Component { super(props, context); this.handleCreateSite = this.handleCreateSite.bind(this); + + FirstLoadService.isFirstLoad; } async componentDidMount() { diff --git a/src/shared/components/home/signup.tsx b/src/shared/components/home/signup.tsx index a2d960dc..3bb7ea0e 100644 --- a/src/shared/components/home/signup.tsx +++ b/src/shared/components/home/signup.tsx @@ -14,7 +14,7 @@ import { } from "lemmy-js-client"; import { joinLemmyUrl } from "../../config"; import { mdToHtml } from "../../markdown"; -import { I18NextService, UserService } from "../../services"; +import { FirstLoadService, I18NextService, UserService } from "../../services"; import { HttpService, RequestState } from "../../services/HttpService"; import { toast } from "../../toast"; import { HtmlTags } from "../common/html-tags"; @@ -84,6 +84,8 @@ export class Signup extends Component { super(props, context); this.handleAnswerChange = this.handleAnswerChange.bind(this); + + FirstLoadService.isFirstLoad; } async componentDidMount() { diff --git a/src/shared/components/person/password-change.tsx b/src/shared/components/person/password-change.tsx index dd85e05b..0403c553 100644 --- a/src/shared/components/person/password-change.tsx +++ b/src/shared/components/person/password-change.tsx @@ -2,7 +2,12 @@ import { myAuth, setIsoData } from "@utils/app"; import { capitalizeFirstLetter } from "@utils/helpers"; import { Component, linkEvent } from "inferno"; import { GetSiteResponse, LoginResponse } from "lemmy-js-client"; -import { HttpService, I18NextService, UserService } from "../../services"; +import { + FirstLoadService, + HttpService, + I18NextService, + UserService, +} from "../../services"; import { RequestState } from "../../services/HttpService"; import { HtmlTags } from "../common/html-tags"; import { Spinner } from "../common/icon"; @@ -30,6 +35,8 @@ export class PasswordChange extends Component { constructor(props: any, context: any) { super(props, context); + + FirstLoadService.isFirstLoad; } get documentTitle(): string { diff --git a/src/shared/components/person/settings.tsx b/src/shared/components/person/settings.tsx index dc542e72..1ef95f5a 100644 --- a/src/shared/components/person/settings.tsx +++ b/src/shared/components/person/settings.tsx @@ -29,7 +29,7 @@ import { SortType, } from "lemmy-js-client"; import { elementUrl, emDash, relTags } from "../../config"; -import { UserService } from "../../services"; +import { FirstLoadService, UserService } from "../../services"; import { HttpService, RequestState } from "../../services/HttpService"; import { I18NextService, languages } from "../../services/I18NextService"; import { setupTippy } from "../../tippy"; @@ -170,6 +170,8 @@ export class Settings extends Component { this.handleBlockPerson = this.handleBlockPerson.bind(this); this.handleBlockCommunity = this.handleBlockCommunity.bind(this); + FirstLoadService.isFirstLoad; + const mui = UserService.Instance.myUserInfo; if (mui) { const { @@ -1177,7 +1179,6 @@ export class Settings extends Component { }); if (saveRes.state === "success") { UserService.Instance.login(saveRes.data); - location.reload(); toast(I18NextService.i18n.t("saved")); window.scrollTo(0, 0); } diff --git a/src/shared/components/person/verify-email.tsx b/src/shared/components/person/verify-email.tsx index 1800c3f2..a13df2d9 100644 --- a/src/shared/components/person/verify-email.tsx +++ b/src/shared/components/person/verify-email.tsx @@ -1,7 +1,7 @@ import { setIsoData } from "@utils/app"; import { Component } from "inferno"; import { GetSiteResponse, VerifyEmailResponse } from "lemmy-js-client"; -import { I18NextService } from "../../services"; +import { FirstLoadService, I18NextService } from "../../services"; import { HttpService, RequestState } from "../../services/HttpService"; import { toast } from "../../toast"; import { HtmlTags } from "../common/html-tags"; @@ -22,6 +22,8 @@ export class VerifyEmail extends Component { constructor(props: any, context: any) { super(props, context); + + FirstLoadService.isFirstLoad; } async verify() {