Skip to content

Conversation

@miya
Copy link
Member

@miya miya commented May 29, 2025

Task

  • #166501 [GROWI AI Next][エディターアシスタント] Diff 作成中に progress indicator を表示できる

Screenrecord

2025-05-29.20.30.10.mov

@miya miya requested review from Copilot and yuki-takei May 29, 2025 03:50
@miya miya self-assigned this May 29, 2025
@changeset-bot
Copy link

changeset-bot bot commented May 29, 2025

⚠️ No Changeset found

Latest commit: 9a21a01

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@miya miya changed the title feat(ai): Display spinner while creating Diff feat(ai): Display spinner while creating diff May 29, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a progress indicator by tracking when a diff is being applied in the Editor Assistant hook.

  • Introduces isApplyingDiffRef to track diff application state.
  • Toggles the ref in SSE handlers to mark start/end of diff processing.
Comments suppressed due to low confidence (1)

apps/app/src/features/openai/client/services/editor-assistant.tsx:217

  • [nitpick] The name isApplyingDiffRef couples implementation detail (Ref) into the variable name. Consider renaming to isApplyingDiff (and using state) for clearer intent.
isApplyingDiffRef.current = true;

// Refs
// const positionRef = useRef<number>(0);
const lineRef = useRef<number>(0);
const isApplyingDiffRef = useRef<boolean>(false);
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isApplyingDiffRef isn't returned or used to trigger re-renders in the UI. Consider using useState and returning the boolean so the spinner can actually subscribe to this state.

Suggested change
const isApplyingDiffRef = useRef<boolean>(false);
const [isApplyingDiff, setIsApplyingDiff] = useState<boolean>(false);

Copilot uses AI. Check for mistakes.
const processMessage: ProcessMessage = useCallback((data, handler) => {
handleIfSuccessfullyParsed(data, SseMessageSchema, (data: SseMessage) => {
handler.onMessage(data);
isApplyingDiffRef.current = false;
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resetting the ref immediately after handler.onMessage may hide the spinner before the diff has actually been applied. You might want to move this reset to after the diff application completes.

Suggested change
isApplyingDiffRef.current = false;

Copilot uses AI. Check for mistakes.
@miya miya requested a review from Copilot May 29, 2025 11:32
timerRef.current = setTimeout(() => {
setIsGeneratingEditorText(true);
}, 500);
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stream でデータを受信してから 500ms の間に次のデータが来ない時にスピナーを表示する

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a progress spinner for the editor assistant while generating diffs by introducing a new isGeneratingEditorText state in the hook and passing it down to the sidebar UI.

  • Added isGeneratingEditorText flag to useEditorAssistant and implemented timer-based show/hide logic.
  • Updated MessageCard and AiAssistantSidebar to render a LoadingSpinner when isGeneratingEditorText is true.
  • Added corresponding translation keys for the spinner label in all locales.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

File Description
apps/app/src/features/openai/client/services/editor-assistant.tsx Introduced isGeneratingEditorText, timer logic in processMessage, and a new ref for handling spinner timing.
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx Extended MessageCard API to accept isGeneratingEditorText and render the spinner UI.
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx Passed isGeneratingEditorText prop to MessageCard in the sidebar.
apps/app/public/static/locales/*/translation.json Added text_generation_by_editor_assistant_label entries to all locale files.
Comments suppressed due to low confidence (2)

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx:71

  • The new spinner UI controlled by isGeneratingEditorText is untested. Consider adding a unit or integration test to verify the spinner shows and hides correctly based on the state.
{isGeneratingEditorText && (

apps/app/src/features/openai/client/services/editor-assistant.tsx:73

  • [nitpick] The return type for useEditorAssistant has been extended with isGeneratingEditorText. Consider updating any accompanying JSDoc or README docs to describe this new property.
type UseEditorAssistant = () => {

// Refs\
const lineRef = useRef<number>(0);
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout stored in timerRef isn’t cleared on component unmount, which may lead to memory leaks or unexpected calls. Consider adding a useEffect cleanup to clearTimeout(timerRef.current) when the component unmounts.

Suggested change
useEffect(() => {
return () => {
if (timerRef.current !== null) {
clearTimeout(timerRef.current);
timerRef.current = null;
}
};
}, []);

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

メモリリークの可能性を指摘されている

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

修正しました
commit: d55a671

}

// Hide spinner since data is flowing
setIsGeneratingEditorText(false);
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling setIsGeneratingEditorText(false) on every incoming data chunk may trigger redundant renders. You can add a guard to only update the state when its value actually changes.

Suggested change
setIsGeneratingEditorText(false);
if (isGeneratingEditorText) {
setIsGeneratingEditorText(false);
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レンダリング回数削減のために入れておくべきか

Copy link
Member Author

@miya miya May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

修正しました
commit: 6fc97e1

<LoadingSpinner />
<span className="ms-2">{t('sidebar_ai_assistant.text_generation_by_editor_assistant_label')}</span>
</div>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

下の方の <span className="text-thinking"> と、少なくともスタイルだけでも揃えるべきかな

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text-thinking を適用し、スピナーを消しました (text-thinking 自体がスピナー的な役割をしていると判断したため)

role: MessageCardRole,
children: string,
showActionButtons?: boolean,
isGeneratingEditorText?: boolean,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boolean じゃなくて

                  <div className="text-muted mb-3">
                    <LoadingSpinner />
                    <span className="ms-2">{t('sidebar_ai_assistant.text_generation_by_editor_assistant_label')}</span>
                  </div>

を丸っと外から入れる方が綺麗だね (editor-assistant.tsx 内で定義したものを props を通じてここまで持ってくる)

そういう意味では action buttons もエディターアシスタント特有のものなのでそうすべきかもしれないが

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageCard 側にはエディターアシスタント特有の要素は削除し、additionaltem という Props を設け外からコンポーネントを渡せるようにした。

エディター書き込み時のラベルコンポーネントと、既存の ActionButtons を EditorAssistant の Hook から提供し、AiAssistantSidebar 経由で MessageCard の additionaltem に渡すように改修した。

commit: 73c4b40

// Refs\
const lineRef = useRef<number>(0);
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

メモリリークの可能性を指摘されている

}

// Hide spinner since data is flowing
setIsGeneratingEditorText(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レンダリング回数削減のために入れておくべきか

@miya miya requested a review from Copilot May 30, 2025 07:14
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request introduces a spinner to indicate progress while generating a diff during the AI assistant process. Key changes include the removal or deprecation of the generateMessageCard functionality in the knowledge assistant service, the addition of spinner state management and timer logic in the editor assistant service, and updates to the UI and translation files to support the new spinner indicator.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
apps/app/src/features/openai/client/services/knowledge-assistant.tsx Removed the generateMessageCard logic and related interfaces, and added a dependency update in the fetch logs effect.
apps/app/src/features/openai/client/services/editor-assistant.tsx Introduced spinner state and timer logic, and refactored action button generation for the editor assistant.
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx Removed redundant state and callbacks, and introduced a new prop for additional content.
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx Adjusted MessageCard usage to support the new additional content prop, and refactored related variables.
Translation files (zh_CN, ja_JP, fr_FR, en_US) Added spinner label translations for the editor assistant.
Comments suppressed due to low confidence (2)

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx:37

  • [nitpick] The prop name 'additionaltem' is ambiguous; consider renaming it to 'additionalItem' or 'extraContent' to provide better clarity.
additionaltem,

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx:361

  • [nitpick] The variable name 'messageCardAdditionaltemForGeneratingMessage' is unclear; consider renaming it to a more descriptive name such as 'messageCardExtraContentForGenerating' to maintain consistency with other naming conventions.
const messageCardAdditionaltemForGeneratingMessage = useMemo(() => {

// Views
initialView: JSX.Element
generateMessageCard: GenerateMessageCard
// generateMessageCard: GenerateMessageCard
Copy link

Copilot AI May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the generateMessageCard functionality is no longer in use, consider removing the commented-out code entirely to improve clarity and maintainability.

Suggested change
// generateMessageCard: GenerateMessageCard

Copilot uses AI. Check for mistakes.
@miya miya requested a review from Copilot May 30, 2025 07:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds a delayed spinner indicator in the editor assistant while diff chunks are streaming, refactors message rendering to use a new prop instead of in-card action button logic, and updates translations and cleanup in the knowledge assistant.

  • Introduce isGeneratingEditorText state and timer logic in useEditorAssistant to show a spinner after 500 ms of no data.
  • Refactor MessageCard to accept an additionaltem element and update AiAssistantSidebar to render action buttons and the spinner label via that prop.
  • Remove unused generateMessageCard helpers in the knowledge assistant, adjust effect dependencies, and add new translation keys.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/app/src/features/openai/client/services/knowledge-assistant.tsx Remove unused generateMessageCard, update SWR effect dependencies
apps/app/src/features/openai/client/services/editor-assistant.tsx Add timer/spinner logic, state & callbacks for editor assistant, refactor views
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx Replace in-card action buttons with additionaltem prop, remove unused state & callbacks
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx Wire up new additionaltem prop, remove commented code
apps/app/public/static/locales/*/translation.json Add text_generation_by_editor_assistant_label key in all supported locales
Comments suppressed due to low confidence (3)

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx:40

  • [nitpick] The prop name "additionaltem" appears misspelled and unclear; consider renaming it to "additionalItem" or a more descriptive name.
additionaltem?: JSX.Element,

apps/app/src/features/openai/client/services/editor-assistant.tsx:148

  • Introduced spinner logic for text generation, but there are no tests verifying the spinner appears after a delay and hides during streaming; consider adding unit or integration tests.
const [isGeneratingEditorText, setIsGeneratingEditorText] = useState<boolean>(false);

apps/app/src/features/openai/client/services/knowledge-assistant.tsx:315

  • [nitpick] Adding "aiAssistantSidebarData?.isEditorAssistant" to the fetch-and-set-logs effect dependencies may trigger redundant refetches when toggling the editor assistant UI; consider removing it unless intentional.
}, [threadId, mutateMessageData, setMessageLogs, aiAssistantSidebarData?.isEditorAssistant]);

handler.onFinalized(data);
});
}, [mutateIsEnableUnifiedMergeView]);
}, [isGeneratingEditorText, mutateIsEnableUnifiedMergeView]);
Copy link

Copilot AI May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including "isGeneratingEditorText" in processMessage's dependency array causes the callback to be recreated on every spinner toggle, which may trigger unnecessary re-subscriptions or re-renders. Consider removing it to stabilize the callback.

Copilot uses AI. Check for mistakes.
// Views
initialView: initialViewForKnowledgeAssistant,
generateMessageCard: generateMessageCardForKnowledgeAssistant,
// generateMessageCard: generateMessageCardForKnowledgeAssistant,
Copy link

Copilot AI May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] There are multiple commented-out references to generateMessageCard that should be removed to clean up dead code.

Suggested change
// generateMessageCard: generateMessageCardForKnowledgeAssistant,

Copilot uses AI. Check for mistakes.
@miya miya requested a review from Copilot May 30, 2025 07:20
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a delayed spinner indicator during diff/text generation and refactors the message card to support additional embedded items (e.g., buttons or spinner).

  • Added isGeneratingEditorText state, timer logic, and generatingEditorTextLabel in useEditorAssistant.
  • Refactored MessageCard to take an additionalItem prop instead of inline action buttons.
  • Updated AiAssistantSidebar to inject action buttons and spinner via additionalItem.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
apps/app/src/features/openai/client/services/knowledge-assistant.tsx Extended SWR effect dependencies to include isEditorAssistant state
apps/app/src/features/openai/client/services/editor-assistant.tsx Introduced spinner state/timer logic and new generateActionButtons
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx Replaced action-button props with additionalItem prop
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx Updated mapping to supply additionalItem for messages
apps/app/public/static/locales/*/translation.json Added translation key for spinner label in multiple locales
Comments suppressed due to low confidence (4)

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx:399

  • Elements in a list should have a key prop. Add a key={message.id} to the fragment or the MessageCard.
{ messageLogs.map(message => (

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx:1

  • The import of type JSX is unused; you can remove it to clean up unused imports.
import { type JSX } from 'react';

apps/app/src/features/openai/client/services/editor-assistant.tsx:2

  • The imported type FC is not used in this file; consider removing it.
useCallback, useEffect, useState, useRef, useMemo, type FC,

apps/app/src/features/openai/client/services/knowledge-assistant.tsx:315

  • The effect doesn't reference isEditorAssistant, so removing it from the dependency array will avoid unnecessary reruns.
}, [threadId, mutateMessageData, setMessageLogs, aiAssistantSidebarData?.isEditorAssistant]); // Dependencies

@miya miya requested a review from Copilot May 30, 2025 07:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a progress spinner for diff creation and refactors message card rendering for the Growi AI Editor Assistant. Key changes include:

  • Removal of the generateMessageCard helper function and associated interface in favor of new action button components.
  • Integration of spinner logic with timer management in the editor assistant service.
  • Updates to locale translations to support the new spinner label.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
apps/app/src/features/openai/client/services/knowledge-assistant.tsx Removed dead code and updated dependency arrays to reflect new spinner state.
apps/app/src/features/openai/client/services/editor-assistant.tsx Added spinner timeout logic and new state for displaying the spinner.
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx Refactored message card props, removing action button logic in favor of an additionalItem prop.
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx Updated message card rendering to use the new action buttons mechanism based on spinner state.
Locale files Added translations for the spinner label in multiple locales.
Comments suppressed due to low confidence (4)

apps/app/src/features/openai/client/services/editor-assistant.tsx:224

  • [nitpick] The spinner delay of 500ms is hard-coded. Consider defining this timeout as a named constant to improve clarity and facilitate potential adjustments in the future.
timerRef.current = setTimeout(() => { setIsGeneratingEditorText(true); }, 500);

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx:366

  • The callback for generating an additional item relies on messageLogs; ensure that messageLogs is always defined in this context to avoid unintentionally omitting the action buttons when they should be displayed.
if (messageId == null || messageLogs == null) {

apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/MessageCard.tsx:37

  • [nitpick] The renaming of props from action button related properties to 'additionalItem' helps clarify the component's role in rendering extra UI content. Please verify that all intended usages have been updated accordingly.
additionalItem,

apps/app/src/features/openai/client/services/knowledge-assistant.tsx:315

  • Including 'aiAssistantSidebarData?.isEditorAssistant' in the dependency array may trigger extra re-renders. Please verify that this change is intentional to correctly tie the diff logs update to the spinner state.
}, [threadId, mutateMessageData, setMessageLogs, aiAssistantSidebarData?.isEditorAssistant]); // Dependencies

@miya miya merged commit fa28964 into master May 30, 2025
33 of 37 checks passed
@miya miya deleted the feat/166531-display-spinner-while-creating-diff branch May 30, 2025 07:52
@github-actions github-actions bot mentioned this pull request May 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants