From 09b3374e18bbba85cd4c80ff7edd718882ccadf2 Mon Sep 17 00:00:00 2001 From: plyght Date: Sun, 22 Jun 2025 12:23:20 -0700 Subject: [PATCH] init title gen animation --- .../editor-area/note-header/index.tsx | 18 +++++--- .../editor-area/note-header/title-input.tsx | 15 ++++-- .../editor-area/note-header/title-shimmer.tsx | 46 +++++++++++++++++++ apps/desktop/src/hooks/enhance-pending.ts | 14 ++++++ apps/desktop/src/locales/en/messages.po | 6 ++- apps/desktop/src/locales/ko/messages.po | 6 ++- apps/docs/data/i18n.json | 6 +-- 7 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 apps/desktop/src/components/editor-area/note-header/title-shimmer.tsx diff --git a/apps/desktop/src/components/editor-area/note-header/index.tsx b/apps/desktop/src/components/editor-area/note-header/index.tsx index 2c89724fb..eb71ba061 100644 --- a/apps/desktop/src/components/editor-area/note-header/index.tsx +++ b/apps/desktop/src/components/editor-area/note-header/index.tsx @@ -3,9 +3,11 @@ import { type ChangeEvent } from "react"; import { getCurrentWebviewWindowLabel } from "@hypr/plugin-windows"; import { useSession } from "@hypr/utils/contexts"; +import { useTitleGenerationPendingState } from "../../../hooks/enhance-pending"; import Chips from "./chips"; import ListenButton from "./listen-button"; import TitleInput from "./title-input"; +import TitleShimmer from "./title-shimmer"; interface NoteHeaderProps { onNavigateToEditor?: () => void; @@ -19,6 +21,7 @@ export function NoteHeader( ) { const updateTitle = useSession(sessionId, (s) => s.updateTitle); const sessionTitle = useSession(sessionId, (s) => s.session.title); + const isTitleGenerating = useTitleGenerationPendingState(sessionId); const handleTitleChange = (e: ChangeEvent) => { updateTitle(e.target.value); @@ -31,12 +34,15 @@ export function NoteHeader( return (
- + + +
diff --git a/apps/desktop/src/components/editor-area/note-header/title-input.tsx b/apps/desktop/src/components/editor-area/note-header/title-input.tsx index a7bfca536..8188bd829 100644 --- a/apps/desktop/src/components/editor-area/note-header/title-input.tsx +++ b/apps/desktop/src/components/editor-area/note-header/title-input.tsx @@ -6,6 +6,7 @@ interface TitleInputProps { onChange: (e: ChangeEvent) => void; onNavigateToEditor?: () => void; editable?: boolean; + isGenerating?: boolean; } export default function TitleInput({ @@ -13,6 +14,7 @@ export default function TitleInput({ onChange, onNavigateToEditor, editable, + isGenerating = false, }: TitleInputProps) { const { t } = useLingui(); @@ -23,15 +25,22 @@ export default function TitleInput({ } }; + const getPlaceholder = () => { + if (isGenerating) { + return t`Generating title...`; + } + return t`Untitled`; + }; + return ( ); diff --git a/apps/desktop/src/components/editor-area/note-header/title-shimmer.tsx b/apps/desktop/src/components/editor-area/note-header/title-shimmer.tsx new file mode 100644 index 000000000..20d52c3f4 --- /dev/null +++ b/apps/desktop/src/components/editor-area/note-header/title-shimmer.tsx @@ -0,0 +1,46 @@ +import { cn } from "@hypr/ui/lib/utils"; +import { motion } from "motion/react"; +import { useEffect, useState } from "react"; + +interface TitleShimmerProps { + children: React.ReactNode; + className?: string; + isShimmering?: boolean; +} + +export default function TitleShimmer({ children, className, isShimmering = false }: TitleShimmerProps) { + const [key, setKey] = useState(0); + + useEffect(() => { + const handleResize = () => setKey(prev => prev + 1); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + if (!isShimmering) { + return
{children}
; + } + + return ( +
+ +
+ {children} +
+
+ ); +} diff --git a/apps/desktop/src/hooks/enhance-pending.ts b/apps/desktop/src/hooks/enhance-pending.ts index 8acb1e7bd..6adf35dad 100644 --- a/apps/desktop/src/hooks/enhance-pending.ts +++ b/apps/desktop/src/hooks/enhance-pending.ts @@ -14,3 +14,17 @@ export function useEnhancePendingState(sessionId: string) { return isEnhancePending; } + +export function useTitleGenerationPendingState(sessionId: string) { + const titleStates = useMutationState({ + filters: { mutationKey: ["generateTitle", sessionId], exact: true }, + select: (mutation) => mutation.state.status, + }); + + const isTitleGenerationPending = useMemo( + () => titleStates.some((s) => s === "pending"), + [titleStates], + ); + + return isTitleGenerationPending; +} diff --git a/apps/desktop/src/locales/en/messages.po b/apps/desktop/src/locales/en/messages.po index 092884c3e..660093fc7 100644 --- a/apps/desktop/src/locales/en/messages.po +++ b/apps/desktop/src/locales/en/messages.po @@ -620,6 +620,10 @@ msgstr "Full name" msgid "General" msgstr "General" +#: src/components/editor-area/note-header/title-input.tsx:30 +msgid "Generating title..." +msgstr "Generating title..." + #: src/components/welcome-modal/welcome-view.tsx:36 msgid "Get Started" msgstr "Get Started" @@ -1076,7 +1080,7 @@ msgstr "Type to search..." msgid "Ugh! Can't use it!" msgstr "Ugh! Can't use it!" -#: src/components/editor-area/note-header/title-input.tsx:33 +#: src/components/editor-area/note-header/title-input.tsx:32 msgid "Untitled" msgstr "Untitled" diff --git a/apps/desktop/src/locales/ko/messages.po b/apps/desktop/src/locales/ko/messages.po index 7dec6ad2c..d24f3b420 100644 --- a/apps/desktop/src/locales/ko/messages.po +++ b/apps/desktop/src/locales/ko/messages.po @@ -620,6 +620,10 @@ msgstr "" msgid "General" msgstr "" +#: src/components/editor-area/note-header/title-input.tsx:30 +msgid "Generating title..." +msgstr "" + #: src/components/welcome-modal/welcome-view.tsx:36 msgid "Get Started" msgstr "" @@ -1076,7 +1080,7 @@ msgstr "" msgid "Ugh! Can't use it!" msgstr "" -#: src/components/editor-area/note-header/title-input.tsx:33 +#: src/components/editor-area/note-header/title-input.tsx:32 msgid "Untitled" msgstr "" diff --git a/apps/docs/data/i18n.json b/apps/docs/data/i18n.json index e3bf13c71..69d61cd36 100644 --- a/apps/docs/data/i18n.json +++ b/apps/docs/data/i18n.json @@ -1,12 +1,12 @@ [ { "language": "ko", - "total": 267, - "missing": 267 + "total": 268, + "missing": 268 }, { "language": "en (source)", - "total": 267, + "total": 268, "missing": 0 } ]