From 84228bc5c8755c4b957bc901e6e552ef176ed00c Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 31 Oct 2024 22:06:32 +0800 Subject: [PATCH] feat: add updatelog modal Signed-off-by: Innei --- .../src/components/common/ShadowDOM.tsx | 7 +- .../components/ui/modal/inspire/PeekModal.tsx | 30 +++++---- apps/renderer/src/env.d.ts | 1 + .../src/modules/app/EnvironmentIndicator.tsx | 45 ++++++++++++- apps/renderer/src/modules/debug/registry.ts | 25 ++++++++ .../src/modules/entry-content/index.tsx | 6 +- .../modules/upgrade/lazy/index.electron.ts | 1 + .../src/modules/upgrade/lazy/index.ts | 3 + .../renderer/src/modules/upgrade/provider.tsx | 64 +++++++++++++++++++ apps/renderer/src/pages/(main)/layout.tsx | 21 +----- changelog/next.md | 13 ++++ configs/vite.render.config.ts | 15 ++++- package.json | 3 +- packages/components/src/ui/toast/index.tsx | 1 + pnpm-lock.yaml | 4 +- scripts/apply-changelog.ts | 20 ++++++ 16 files changed, 211 insertions(+), 48 deletions(-) create mode 100644 apps/renderer/src/modules/debug/registry.ts create mode 100644 apps/renderer/src/modules/upgrade/lazy/index.electron.ts create mode 100644 apps/renderer/src/modules/upgrade/lazy/index.ts create mode 100644 apps/renderer/src/modules/upgrade/provider.tsx create mode 100644 changelog/next.md create mode 100644 scripts/apply-changelog.ts diff --git a/apps/renderer/src/components/common/ShadowDOM.tsx b/apps/renderer/src/components/common/ShadowDOM.tsx index 2ebcafcfc..72a563da0 100644 --- a/apps/renderer/src/components/common/ShadowDOM.tsx +++ b/apps/renderer/src/components/common/ShadowDOM.tsx @@ -85,11 +85,7 @@ export const ShadowDOM: FC< const dark = useIsDark() const reduceMotion = useReduceMotion() - const [customCSS, uiFont, usePointerCursor] = useUISettingKeys([ - "customCSS", - "uiFontFamily", - "usePointerCursor", - ]) + const [uiFont, usePointerCursor] = useUISettingKeys(["uiFontFamily", "usePointerCursor"]) return ( @@ -108,7 +104,6 @@ export const ShadowDOM: FC< className="font-theme" > {injectHostStyles ? stylesElements : null} - {customCSS} {props.children} diff --git a/apps/renderer/src/components/ui/modal/inspire/PeekModal.tsx b/apps/renderer/src/components/ui/modal/inspire/PeekModal.tsx index 5a062e492..afbf0056c 100644 --- a/apps/renderer/src/components/ui/modal/inspire/PeekModal.tsx +++ b/apps/renderer/src/components/ui/modal/inspire/PeekModal.tsx @@ -14,7 +14,7 @@ const InPeekModal = createContext(false) export const useInPeekModal = () => useContext(InPeekModal) export const PeekModal = ( props: PropsWithChildren<{ - to: string + to?: string }>, ) => { const { dismissAll } = useModalStack() @@ -40,19 +40,21 @@ export const PeekModal = ( }} className="fixed right-3 flex items-center gap-4 safe-inset-top-2" > - - - - - Go to this link - - - {t("words.expand")} - + {!!to && ( + + + + + Go to this link + + + {t("words.expand")} + + )} diff --git a/apps/renderer/src/env.d.ts b/apps/renderer/src/env.d.ts index fddc8871b..d7d4eec22 100644 --- a/apps/renderer/src/env.d.ts +++ b/apps/renderer/src/env.d.ts @@ -2,3 +2,4 @@ declare const APP_VERSION: string declare const APP_NAME: string declare const RELEASE_CHANNEL: string declare const I18N_COMPLETENESS_MAP: Record +declare const CHANGELOG_CONTENT: string diff --git a/apps/renderer/src/modules/app/EnvironmentIndicator.tsx b/apps/renderer/src/modules/app/EnvironmentIndicator.tsx index 367f93aa5..981e5fef6 100644 --- a/apps/renderer/src/modules/app/EnvironmentIndicator.tsx +++ b/apps/renderer/src/modules/app/EnvironmentIndicator.tsx @@ -1,3 +1,4 @@ +import { Button } from "@follow/components/ui/button/index.js" import { Tooltip, TooltipContent, @@ -7,15 +8,53 @@ import { import { env } from "@follow/shared/env" import { useUserRole } from "~/atoms/user" +import { useModalStack } from "~/components/ui/modal/stacked/hooks" +import { isDev } from "~/constants" + +import { DebugRegistry } from "../debug/registry" export const EnvironmentIndicator = () => { const role = useUserRole() + const { present } = useModalStack() return ( -
- {role}:{import.meta.env.MODE} -
+ + + ) + })} + + ) + }, + }) + }} + > +
+ {role}:{isDev && } + {import.meta.env.MODE} +
+
diff --git a/apps/renderer/src/modules/debug/registry.ts b/apps/renderer/src/modules/debug/registry.ts new file mode 100644 index 000000000..a84dea881 --- /dev/null +++ b/apps/renderer/src/modules/debug/registry.ts @@ -0,0 +1,25 @@ +class Registry { + private actions: Record void> = {} + + add(key: string, action: () => void) { + this.actions[key] = action + + return () => { + delete this.actions[key] + } + } + + remove(key: string) { + delete this.actions[key] + } + + getAll() { + return this.actions + } + + get(key: string) { + return this.actions[key] + } +} + +export const DebugRegistry = new Registry() diff --git a/apps/renderer/src/modules/entry-content/index.tsx b/apps/renderer/src/modules/entry-content/index.tsx index 0d40dc26a..1338e4fff 100644 --- a/apps/renderer/src/modules/entry-content/index.tsx +++ b/apps/renderer/src/modules/entry-content/index.tsx @@ -1,3 +1,4 @@ +import { MemoedDangerousHTMLStyle } from "@follow/components/common/MemoedDangerousHTMLStyle.js" import { AutoResizeHeight } from "@follow/components/ui/auto-resize-height/index.jsx" import { LoadingWithIcon } from "@follow/components/ui/loading/index.jsx" import { RootPortal } from "@follow/components/ui/portal/index.jsx" @@ -159,7 +160,7 @@ export const EntryContentRender: Component<{ ), [entry?.entries.media, data?.entries.media], ) - + const customCSS = useUISettingKey("customCSS") if (!entry) return null const content = entry?.entries.content ?? data?.entries.content @@ -237,6 +238,9 @@ export const EntryContentRender: Component<{ {!isInReadabilityMode ? ( + {!!customCSS && ( + {customCSS} + )} import("../provider")) diff --git a/apps/renderer/src/modules/upgrade/provider.tsx b/apps/renderer/src/modules/upgrade/provider.tsx new file mode 100644 index 000000000..2b6a71f2c --- /dev/null +++ b/apps/renderer/src/modules/upgrade/provider.tsx @@ -0,0 +1,64 @@ +import { useOnce } from "@follow/hooks" +import { repository } from "@pkg" +import type { FC } from "react" +import { toast } from "sonner" + +import { Markdown } from "~/components/ui/markdown/Markdown" +import { PeekModal } from "~/components/ui/modal/inspire/PeekModal" +import { useModalStack } from "~/components/ui/modal/stacked/hooks" +import { Paper } from "~/components/ui/paper" +import { isDev } from "~/constants" +import { DebugRegistry } from "~/modules/debug/registry" + +const AppUpgradeProvider: FC = () => { + const { present } = useModalStack() + useOnce(() => { + const toaster = () => { + toast.success( +
+ App is upgraded to{" "} + {APP_VERSION}, enjoy the new + features! 🎉 +
, + { + duration: 10e8, + action: CHANGELOG_CONTENT + ? { + label: "What's new?", + onClick: () => { + present({ + clickOutsideToDismiss: true, + title: "What's new?", + autoFocus: false, + modalClassName: + "relative mx-auto mt-[10vh] scrollbar-none max-w-full overflow-auto px-2 lg:max-w-[65rem] lg:p-0", + + CustomModalComponent: ({ children }) => { + return {children} + }, + content: Changelog, + overlay: true, + }) + }, + } + : undefined, + }, + ) + } + if (window.__app_is_upgraded__) { + setTimeout(toaster) + } + + isDev && DebugRegistry.add("simulate_app_upgraded_toast", toaster) + }) + + return null +} + +export default AppUpgradeProvider + +const Changelog = () => ( + + {CHANGELOG_CONTENT} + +) diff --git a/apps/renderer/src/pages/(main)/layout.tsx b/apps/renderer/src/pages/(main)/layout.tsx index 06c56fe19..1eed82215 100644 --- a/apps/renderer/src/pages/(main)/layout.tsx +++ b/apps/renderer/src/pages/(main)/layout.tsx @@ -1,7 +1,6 @@ import { useViewport } from "@follow/components/hooks/useViewport.js" import { PanelSplitter } from "@follow/components/ui/divider/index.js" import { RootPortal } from "@follow/components/ui/portal/index.jsx" -import { useOnce } from "@follow/hooks" import { IN_ELECTRON } from "@follow/shared/constants" import { preventDefault } from "@follow/utils/dom" import { cn } from "@follow/utils/utils" @@ -15,7 +14,6 @@ import { useHotkeys } from "react-hotkeys-hook" import { Trans, useTranslation } from "react-i18next" import { useResizable } from "react-resizable-layout" import { Outlet } from "react-router-dom" -import { toast } from "sonner" import { setMainContainerElement } from "~/atoms/dom" import { getUISettings, setUISetting, useUISettingKey } from "~/atoms/settings/ui" @@ -46,6 +44,7 @@ import { useShortcutsModal } from "~/modules/modal/shortcuts" import { CmdF } from "~/modules/panel/cmdf" import { SearchCmdK } from "~/modules/panel/cmdk" import { CmdNTrigger } from "~/modules/panel/cmdn" +import { AppUpgradeProvider } from "~/modules/upgrade/lazy/index" import { AppLayoutGridContainerProvider } from "~/providers/app-grid-layout-container-provider" import { settings } from "~/queries/settings" @@ -87,22 +86,6 @@ const errorTypes = [ ErrorComponentType.FeedNotFound, ] as ErrorComponentType[] -const useAppUpgraded = () => { - useOnce(() => { - if (window.__app_is_upgraded__) { - setTimeout(() => { - toast.success( -
- App is upgraded to{" "} - {APP_VERSION}, enjoy the - new features! 🎉 -
, - ) - }) - } - }) -} - const supportMinWidth = 1024 export function Component() { const isAuthFail = useLoginModalShow() @@ -111,7 +94,6 @@ export function Component() { const containerRef = useRef(null) useDailyTask() - useAppUpgraded() const isNotSupportWidth = useViewport((v) => v.w < supportMinWidth && v.w !== 0) && !IN_ELECTRON @@ -126,6 +108,7 @@ export function Component() { {!import.meta.env.PROD && } + diff --git a/changelog/next.md b/changelog/next.md new file mode 100644 index 000000000..3a07349bc --- /dev/null +++ b/changelog/next.md @@ -0,0 +1,13 @@ +# NEXT_VERSION Changelog + +## Features + +- Custom CSS is now supported, so you can add any CSS style and apply it to the Entry content view. +- New Zen mode has been added, so you can now read the full text in full screen without interruption, and we've optimized the user experience of the ToC component in full screen mode as well as added a new brief timeline on the left side. +- Support for hiding extra badges around the feed, such as Claim or Boost, which you may not want to see. + +## Improvements + +- Fixed the issue that Entry list cannot be loaded offline. +- Optimized the performance experience of some scenarios. +- The UI of some components has been fine-tuned to look more natural. diff --git a/configs/vite.render.config.ts b/configs/vite.render.config.ts index 310a09c6b..9937183e0 100644 --- a/configs/vite.render.config.ts +++ b/configs/vite.render.config.ts @@ -14,10 +14,20 @@ import { twMacro } from "../plugins/vite/tw-macro" import i18nCompleteness from "../plugins/vite/utils/i18n-completeness" import { getGitHash } from "../scripts/lib" -const pkgDir = dirname(fileURLToPath(import.meta.url)) -const pkg = JSON.parse(readFileSync(resolve(pkgDir, "../package.json"), "utf8")) +const pkgDir = resolve(dirname(fileURLToPath(import.meta.url)), "..") +const pkg = JSON.parse(readFileSync(resolve(pkgDir, "./package.json"), "utf8")) const isCI = process.env.CI === "true" || process.env.CI === "1" +const getChangelogFileContent = () => { + const { version } = pkg + const isDev = process.env.NODE_ENV === "development" + try { + return readFileSync(resolve(pkgDir, "./changelog", `${isDev ? "next" : version}.md`), "utf8") + } catch { + return "" + } +} +const changelogFile = getChangelogFileContent() export const viteRenderBaseConfig = { resolve: { alias: { @@ -73,5 +83,6 @@ export const viteRenderBaseConfig = { DEBUG: process.env.DEBUG === "true", I18N_COMPLETENESS_MAP: JSON.stringify({ ...i18nCompleteness, en: 100 }), + CHANGELOG_CONTENT: JSON.stringify(changelogFile), }, } satisfies UserConfig diff --git a/package.json b/package.json index f37093735..92acedede 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,8 @@ }, "bump": { "before": [ - "git pull --rebase" + "git pull --rebase", + "tsx scripts/apply-changelog.ts ${NEW_VERSION}" ], "after": [ "gh pr create --title 'chore: Release v${NEW_VERSION}' --body 'v${NEW_VERSION}' --base main --head dev" diff --git a/packages/components/src/ui/toast/index.tsx b/packages/components/src/ui/toast/index.tsx index da2e85229..60f01f76d 100644 --- a/packages/components/src/ui/toast/index.tsx +++ b/packages/components/src/ui/toast/index.tsx @@ -10,6 +10,7 @@ export const Toaster = ({ ...props }: ToasterProps) => ( className: tw`pointer-events-auto`, classNames: { content: "min-w-0", + icon: tw`self-start translate-y-[2px]`, }, }} {...props} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af2c8d7ce..7049d31c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3607,7 +3607,7 @@ packages: '@radix-ui/react-slot@1.1.0': resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} peerDependencies: - '@types/react': npm:types-react@19.0.0-rc.1 + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -20345,7 +20345,7 @@ snapshots: terser@5.35.0: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.13.0 + acorn: 8.14.0 commander: 2.20.3 source-map-support: 0.5.21 diff --git a/scripts/apply-changelog.ts b/scripts/apply-changelog.ts new file mode 100644 index 000000000..38fb1ad20 --- /dev/null +++ b/scripts/apply-changelog.ts @@ -0,0 +1,20 @@ +import { readFileSync, renameSync, writeFileSync } from "node:fs" +import { dirname, join, resolve } from "node:path" +import { fileURLToPath } from "node:url" + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const changelogDir = join(__dirname, "..", "changelog") + +const nextFile = join(changelogDir, "next.md") + +const new_version = process.argv[2] + +const nextContent = readFileSync(nextFile, "utf-8") +writeFileSync(nextFile, nextContent.replaceAll("NEXT_VERSION", new_version)) + +// Rename the next.md to the new version +renameSync(nextFile, join(changelogDir, `${new_version}.md`)) +// Replace the NEXT_VERSION in the next.md file with the new version + +// Create the new next.md file +writeFileSync(resolve(changelogDir, "next.md"), `# NEXT_VERSION Changelog`)