diff options
author | crupest <crupest@outlook.com> | 2023-09-21 21:05:04 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2023-09-21 21:05:04 +0800 |
commit | a8a8385cd959e4d9d57b8a35381d2851049c07ff (patch) | |
tree | a933e8a6c1e8b577149dba624514148507a61a50 | |
parent | 04863bd8ebb543a436bde0d49250010038ab9f90 (diff) | |
download | timeline-a8a8385cd959e4d9d57b8a35381d2851049c07ff.tar.gz timeline-a8a8385cd959e4d9d57b8a35381d2851049c07ff.tar.bz2 timeline-a8a8385cd959e4d9d57b8a35381d2851049c07ff.zip |
...
-rw-r--r-- | FrontEnd/src/components/hooks/index.ts | 2 | ||||
-rw-r--r-- | FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts | 24 | ||||
-rw-r--r-- | FrontEnd/src/components/hooks/useReloadKey.ts | 9 | ||||
-rw-r--r-- | FrontEnd/src/components/utilities/index.ts | 2 | ||||
-rw-r--r-- | FrontEnd/src/locales/en/translation.json | 10 | ||||
-rw-r--r-- | FrontEnd/src/locales/zh/translation.json | 10 | ||||
-rw-r--r-- | FrontEnd/src/pages/timeline/Timeline.tsx | 21 | ||||
-rw-r--r-- | FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx | 23 | ||||
-rw-r--r-- | FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx | 23 | ||||
-rw-r--r-- | FrontEnd/src/utilities/index.ts | 1 | ||||
-rw-r--r-- | FrontEnd/src/utilities/promise.ts | 35 |
11 files changed, 81 insertions, 79 deletions
diff --git a/FrontEnd/src/components/hooks/index.ts b/FrontEnd/src/components/hooks/index.ts index 98ce729e..972bf5ce 100644 --- a/FrontEnd/src/components/hooks/index.ts +++ b/FrontEnd/src/components/hooks/index.ts @@ -2,4 +2,4 @@ export { useMobile } from "./responsive"; export { default as useClickOutside } from "./useClickOutside"; export { default as useScrollToBottom } from "./useScrollToBottom"; export { default as useWindowLeave } from "./useWindowLeave"; -export { default as useAutoUnsubscribePromise } from "./useAutoUnsubscribePromise"; +export { default as useReloadKey } from "./useReloadKey"; diff --git a/FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts b/FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts deleted file mode 100644 index 01c5a1db..00000000 --- a/FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useEffect, DependencyList } from "react"; - -export default function useAutoUnsubscribePromise<T>( - promiseGenerator: () => Promise<T> | null | undefined, - resultHandler: (data: T) => void, - dependencies?: DependencyList | undefined, -) { - useEffect(() => { - let subscribe = true; - const promise = promiseGenerator(); - if (promise) { - void promise.then((data) => { - if (subscribe) { - resultHandler(data); - } - }); - - return () => { - subscribe = false; - }; - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [promiseGenerator, resultHandler, ...(dependencies ?? [])]); -} diff --git a/FrontEnd/src/components/hooks/useReloadKey.ts b/FrontEnd/src/components/hooks/useReloadKey.ts new file mode 100644 index 00000000..4f63f914 --- /dev/null +++ b/FrontEnd/src/components/hooks/useReloadKey.ts @@ -0,0 +1,9 @@ +import { useState } from "react"; + +export default function useReloadKey(): [ + key: number | string, + reload: () => void, +] { + const [key, setKey] = useState(0); + return [key, () => setKey((k) => k + 1)]; +} diff --git a/FrontEnd/src/components/utilities/index.ts b/FrontEnd/src/components/utilities/index.ts new file mode 100644 index 00000000..000c2640 --- /dev/null +++ b/FrontEnd/src/components/utilities/index.ts @@ -0,0 +1,2 @@ +export * from "~src/utilities"; + diff --git a/FrontEnd/src/locales/en/translation.json b/FrontEnd/src/locales/en/translation.json index a7e4efe5..1b43357c 100644 --- a/FrontEnd/src/locales/en/translation.json +++ b/FrontEnd/src/locales/en/translation.json @@ -38,14 +38,6 @@ "registerCodeInvalid": "Register code is invalid." } }, - "serviceWorker": { - "availableOffline": "Timeline is now cached in your computer and you can use it offline. 🎉🎉🎉", - "upgradePrompt": "App is getting a new version!", - "upgradeNow": "Update Now", - "upgradeSuccess": "Congratulations! App update succeeded! Still you can use it offline. 🎉🎉🎉", - "externalActivatedPrompt": "A new version of app is activated. Please refresh the page. Or it may be broken.", - "reloadNow": "Refresh Now" - }, "nav": { "settings": "Settings", "login": "Login", @@ -233,4 +225,4 @@ "admin": { "title": "admin" } -}
\ No newline at end of file +} diff --git a/FrontEnd/src/locales/zh/translation.json b/FrontEnd/src/locales/zh/translation.json index 8a2f628f..dc0d6672 100644 --- a/FrontEnd/src/locales/zh/translation.json +++ b/FrontEnd/src/locales/zh/translation.json @@ -38,14 +38,6 @@ "Disconnecting": "正在断开连接", "Reconnecting": "正在重新连接" }, - "serviceWorker": { - "availableOffline": "Timeline 已经缓存在本地,你可以离线使用它。🎉🎉🎉", - "upgradePrompt": "App 有新版本!", - "upgradeNow": "现在升级", - "upgradeSuccess": "App 升级成功,当然,你仍可以离线使用它。 🎉🎉🎉", - "externalActivatedPrompt": "一个新的 App 版本已经激活,请刷新页面使用,否则页面可能会出现故障。", - "reloadNow": "立刻刷新" - }, "nav": { "settings": "设置", "login": "登陆", @@ -246,4 +238,4 @@ "admin": { "title": "管理" } -}
\ No newline at end of file +} diff --git a/FrontEnd/src/pages/timeline/Timeline.tsx b/FrontEnd/src/pages/timeline/Timeline.tsx index 32cbf8c8..e2ab5c71 100644 --- a/FrontEnd/src/pages/timeline/Timeline.tsx +++ b/FrontEnd/src/pages/timeline/Timeline.tsx @@ -15,7 +15,7 @@ import { import { getTimelinePostUpdate$ } from "~src/services/timeline"; -import { useScrollToBottom } from "~src/components/hooks"; +import { useReloadKey, useScrollToBottom } from "~src/components/hooks"; import TimelinePostList from "./TimelinePostList"; import TimelineInfoCard from "./TimelineInfoCard"; @@ -44,11 +44,8 @@ export function Timeline(props: TimelineProps) { const [currentPage, setCurrentPage] = useState(1); const [totalPage, setTotalPage] = useState(0); - const [timelineReloadKey, setTimelineReloadKey] = useState(0); - const [postsReloadKey, setPostsReloadKey] = useState(0); - - const updateTimeline = (): void => setTimelineReloadKey((o) => o + 1); - const updatePosts = (): void => setPostsReloadKey((o) => o + 1); + const [timelineKey, reloadTimeline] = useReloadKey(); + const [postsKey, reloadPosts] = useReloadKey(); useEffect(() => { setTimeline(null); @@ -77,7 +74,7 @@ export function Timeline(props: TimelineProps) { } }, ); - }, [timelineOwner, timelineName, timelineReloadKey]); + }, [timelineOwner, timelineName, timelineKey]); useEffect(() => { getHttpTimelineClient() @@ -102,7 +99,7 @@ export function Timeline(props: TimelineProps) { } }, ); - }, [timelineOwner, timelineName, postsReloadKey]); + }, [timelineOwner, timelineName, postsKey]); useEffect(() => { const timelinePostUpdate$ = getTimelinePostUpdate$( @@ -111,7 +108,7 @@ export function Timeline(props: TimelineProps) { ); const subscription = timelinePostUpdate$.subscribe(({ update, state }) => { if (update) { - setPostsReloadKey((o) => o + 1); + reloadPosts(); } setSignalrState(state); }); @@ -162,15 +159,15 @@ export function Timeline(props: TimelineProps) { <TimelineInfoCard timeline={timeline} connectionStatus={signalrState} - onReload={updateTimeline} + onReload={reloadTimeline} /> )} {posts && ( <div className={classNames("timeline", className)}> {timeline?.postable && ( - <TimelinePostEdit timeline={timeline} onPosted={updatePosts} /> + <TimelinePostEdit timeline={timeline} onPosted={reloadPosts} /> )} - <TimelinePostList posts={posts} onReload={updatePosts} /> + <TimelinePostList posts={posts} onReload={reloadPosts} /> </div> )} </div> diff --git a/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx b/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx index 9bb9f980..d0a43f7d 100644 --- a/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx +++ b/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx @@ -1,4 +1,4 @@ -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { marked } from "marked"; import classNames from "classnames"; @@ -7,7 +7,7 @@ import { getHttpTimelineClient, } from "~src/http/timeline"; -import { useAutoUnsubscribePromise } from "~src/components/hooks"; +import { subscribePromise } from "~src/components/utilities"; import Skeleton from "~src/components/Skeleton"; import "./MarkdownPostView.css"; @@ -23,19 +23,18 @@ export default function MarkdownPostView({ }: MarkdownPostViewProps) { const [markdown, setMarkdown] = useState<string | null>(null); - useAutoUnsubscribePromise( - () => { - if (post) { - return getHttpTimelineClient().getPostDataAsString( + useEffect(() => { + if (post) { + return subscribePromise( + getHttpTimelineClient().getPostDataAsString( post.timelineOwnerV2, post.timelineNameV2, post.id, - ); - } - }, - setMarkdown, - [post], - ); + ), + setMarkdown, + ); + } + }, [post]); const markdownHtml = useMemo<string | null>(() => { if (markdown == null) return null; diff --git a/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx b/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx index b964187d..d66bf05b 100644 --- a/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx +++ b/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import classNames from "classnames"; import { @@ -6,8 +6,8 @@ import { getHttpTimelineClient, } from "~src/http/timeline"; +import { subscribePromise } from "~src/components/utilities"; import Skeleton from "~src/components/Skeleton"; -import { useAutoUnsubscribePromise } from "~src/components/hooks"; import "./PlainTextPostView.css"; @@ -22,19 +22,18 @@ export default function PlainTextPostView({ }: PlainTextPostViewProps) { const [text, setText] = useState<string | null>(null); - useAutoUnsubscribePromise( - () => { - if (post) { - return getHttpTimelineClient().getPostDataAsString( + useEffect(() => { + if (post) { + return subscribePromise( + getHttpTimelineClient().getPostDataAsString( post.timelineOwnerV2, post.timelineNameV2, post.id, - ); - } - }, - setText, - [post], - ); + ), + setText, + ); + } + }, [post]); return ( <div diff --git a/FrontEnd/src/utilities/index.ts b/FrontEnd/src/utilities/index.ts index 7659a8aa..e280274e 100644 --- a/FrontEnd/src/utilities/index.ts +++ b/FrontEnd/src/utilities/index.ts @@ -1,5 +1,6 @@ export { default as base64 } from "./base64"; export { withQuery } from "./url"; +export { subscribePromise } from "./promise"; export function delay(milliseconds: number): Promise<void> { return new Promise<void>((resolve) => { diff --git a/FrontEnd/src/utilities/promise.ts b/FrontEnd/src/utilities/promise.ts new file mode 100644 index 00000000..96bcceac --- /dev/null +++ b/FrontEnd/src/utilities/promise.ts @@ -0,0 +1,35 @@ +export function subscribePromise<T>( + promise: Promise<T>, + resolve: Parameters<Promise<T>["then"]>[0], + reject?: Parameters<Promise<T>["then"]>[1], +): { + promise: ReturnType<Promise<T>["then"]>; + (): void; +} { + let subscribe = true; + + const p = promise.then( + resolve != null + ? (value) => { + if (subscribe) { + resolve(value); + } + } + : undefined, + reject != null + ? (error) => { + if (subscribe) { + reject(error); + } + } + : undefined, + ); + + const result = function () { + subscribe = false; + }; + result.promise = p; + + return result; +} + |