Conversation
This comment has been minimized.
This comment has been minimized.
|
Warning Review limit reached
Next review available in: 21 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe update aligns chatbot API payload handling with nested ChangesChatbot flow and chat behavior
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant openChannel
participant ChatbotScreen
participant MessageActionsSheet
participant ChatbotAPI
openChannel->>ChatbotScreen: route chatbot channel to /chatbot
ChatbotScreen->>MessageActionsSheet: open actions for long-pressed message
MessageActionsSheet->>ChatbotScreen: select copy, edit, flag, or pin
ChatbotScreen->>ChatbotAPI: submit trimmed edited message
ChatbotAPI-->>ChatbotScreen: return chatbot message data
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
src/components/chat/message-actions-sheet.tsx (1)
31-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
React.FCforMessageActionsSheet.
MessageActionsSheethas typed props but is declared as a function. Declare it asReact.FC<MessageActionsSheetProps>.As per coding guidelines, use
React.FCfor defining functional components with props.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/chat/message-actions-sheet.tsx` at line 31, Update the MessageActionsSheet component declaration to use React.FC<MessageActionsSheetProps> while preserving its existing props, defaults, and implementation behavior.Source: Coding guidelines
src/app/(app)/chatbot.tsx (1)
153-202: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueExtract the assistant action handlers.
These inline callbacks are recreated on every
ChatbotScreenrender. Define named callbacks for copy, edit, flag, pin, and save, then pass stable references to the action sheet and button.As per coding guidelines, avoid anonymous functions in
renderItemor event handlers to prevent re-renders.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/`(app)/chatbot.tsx around lines 153 - 202, Extract the inline copy, edit, flag, pin, and edit-save handlers from ChatbotScreen into named callbacks, using the existing state and store operations. Pass those callbacks directly to MessageActionsSheet and the save Button, preserving current behavior and guarding channel/message availability as currently implemented.Source: Coding guidelines
src/components/chat/message-composer.tsx (1)
32-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
React.FC<MessageComposerProps>for this updated component.The changed public component still uses a function declaration. Convert it to the required typed functional-component form.
As per coding guidelines, utilize
React.FCfor defining functional components with props.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/chat/message-composer.tsx` at line 32, Convert the MessageComposer function declaration to a React.FC<MessageComposerProps> component while preserving its existing props, defaults, and behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/api/chat/chatbot.ts`:
- Around line 8-10: Update getChatbotChannel and the other affected chatbot
helpers to use the required createApiEndpoint or createCachedApiEndpoint wrapper
instead of calling api.get directly, while preserving their typed
ChatbotChannelResponse handling, abort signal support, and existing response
values.
In `@src/app/`(app)/chatbot.tsx:
- Line 75: Update the MessageBubble usage in renderItem to explicitly disable
reactions for assistant messages, using the component’s existing assistant or
disableReactions prop so reaction controls are hidden. Replace the inline no-op
onToggleReaction callback with the appropriate stable handler or omit it when
reactions are disabled, avoiding anonymous functions in renderItem.
In `@src/app/chat/`[channelId].tsx:
- Around line 260-264: Update the channel resolution flow before the generic
conversation render so a missing channel is fetched or resolved using channelId
before evaluating the ChatChannelType.Chatbot redirect. Ensure chatbot deep
links redirect to /chatbot on the initial render, and only render the generic
conversation after confirming the resolved channel is not a chatbot.
In `@src/components/chat/message-composer.tsx`:
- Around line 28-32: Enforce allowUrgent across MessageComposer’s send handlers:
pass allowUrgent && urgent to the callbacks in handleSend, handlePickImage, and
handleShareLocation, and reset urgent whenever allowUrgent changes to false so
hidden controls cannot send urgent messages.
---
Nitpick comments:
In `@src/app/`(app)/chatbot.tsx:
- Around line 153-202: Extract the inline copy, edit, flag, pin, and edit-save
handlers from ChatbotScreen into named callbacks, using the existing state and
store operations. Pass those callbacks directly to MessageActionsSheet and the
save Button, preserving current behavior and guarding channel/message
availability as currently implemented.
In `@src/components/chat/message-actions-sheet.tsx`:
- Line 31: Update the MessageActionsSheet component declaration to use
React.FC<MessageActionsSheetProps> while preserving its existing props,
defaults, and implementation behavior.
In `@src/components/chat/message-composer.tsx`:
- Line 32: Convert the MessageComposer function declaration to a
React.FC<MessageComposerProps> component while preserving its existing props,
defaults, and behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 55401197-cbcc-409c-97b9-330d9e429e37
📒 Files selected for processing (9)
src/api/chat/chatbot.tssrc/app/(app)/chat.tsxsrc/app/(app)/chatbot.tsxsrc/app/chat/[channelId].tsxsrc/app/chat/thread/[messageId].tsxsrc/components/chat/message-actions-sheet.tsxsrc/components/chat/message-composer.tsxsrc/models/v4/chat/chatbotModels.tssrc/stores/chat/store.ts
| export const getChatbotChannel = async (signal?: AbortSignal) => { | ||
| const response = await api.get<ChatbotChannelResponse>(`${CHATBOT}/GetChatChannel`, { signal }); | ||
| return response.data; | ||
| return response.data?.Data ?? null; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use the required API endpoint wrapper.
These helpers call the Axios client directly. Route them through createApiEndpoint or createCachedApiEndpoint to follow the required API-module boundary.
As per coding guidelines, always use createApiEndpoint or createCachedApiEndpoint for API endpoints with typed response generics.
Also applies to: 17-22
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/api/chat/chatbot.ts` around lines 8 - 10, Update getChatbotChannel and
the other affected chatbot helpers to use the required createApiEndpoint or
createCachedApiEndpoint wrapper instead of calling api.get directly, while
preserving their typed ChatbotChannelResponse handling, abort signal support,
and existing response values.
Source: Coding guidelines
| const renderItem = useCallback( | ||
| ({ item }: { item: ChatMessageResultData }) => ( | ||
| <MessageBubble message={item} isOwn={!!item.SenderUserId && item.SenderUserId === currentUserId} showSender={false} currentUserId={currentUserId} onLongPress={() => undefined} onToggleReaction={() => undefined} /> | ||
| <MessageBubble message={item} isOwn={!!item.SenderUserId && item.SenderUserId === currentUserId} showSender={false} currentUserId={currentUserId} onLongPress={setActionsMessage} onToggleReaction={() => undefined} /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Hide reaction controls in assistant messages.
If an assistant message has existing reactions, MessageBubble renders pressable reaction controls and invokes this no-op callback. The user can tap a visible control that does nothing.
Pass an explicit assistant or disableReactions prop to MessageBubble and hide those controls in assistant mode.
As per coding guidelines, avoid anonymous functions in renderItem or event handlers to prevent re-renders.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/`(app)/chatbot.tsx at line 75, Update the MessageBubble usage in
renderItem to explicitly disable reactions for assistant messages, using the
component’s existing assistant or disableReactions prop so reaction controls are
hidden. Replace the inline no-op onToggleReaction callback with the appropriate
stable handler or omit it when reactions are disabled, avoiding anonymous
functions in renderItem.
Source: Coding guidelines
| /** Urgent priority is channel-level only; thread replies pass false to hide the toggle. */ | ||
| allowUrgent?: boolean; | ||
| } | ||
|
|
||
| export function MessageComposer({ onSendText, onSendImage, onSendLocation, onOpenGif, onTyping, disabled, placeholder }: MessageComposerProps) { | ||
| export function MessageComposer({ onSendText, onSendImage, onSendLocation, onOpenGif, onTyping, disabled, placeholder, allowUrgent = true }: MessageComposerProps) { |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Enforce allowUrgent on every send path.
The new prop only changes rendering. If urgent is already true when allowUrgent changes to false, handleSend, handlePickImage, and handleShareLocation still pass true to their callbacks. A hidden control can therefore still send an urgent message. Derive the callback value from allowUrgent && urgent and clear urgent when allowUrgent becomes false.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/chat/message-composer.tsx` around lines 28 - 32, Enforce
allowUrgent across MessageComposer’s send handlers: pass allowUrgent && urgent
to the callbacks in handleSend, handlePickImage, and handleShareLocation, and
reset urgent whenever allowUrgent changes to false so hidden controls cannot
send urgent messages.
| // (text only, no reactions/threads/deletes) instead of the generic conversation. | ||
| const channel = useChatStore.getState().channels.find((c) => c.ChatChannelId === channelId); | ||
| if (channel?.ChannelType === ChatChannelType.Chatbot) { | ||
| router.push('/chatbot' as Href); |
There was a problem hiding this comment.
Magic string vulnerability caused by hardcoding the route path '/chatbot' as a raw string literal. Define a centralized routes module (e.g., export const Routes = { Chatbot: '/chatbot' } as const) and reference it here to ensure refactor safety.
Kody rule violation: Centralize string constants
Prompt for LLM
File src/app/(app)/chat.tsx:
Line 110:
Magic string vulnerability caused by hardcoding the route path '/chatbot' as a raw string literal. Define a centralized routes module (e.g., `export const Routes = { Chatbot: '/chatbot' } as const`) and reference it here to ensure refactor safety.
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
| const renderItem = useCallback( | ||
| ({ item }: { item: ChatMessageResultData }) => ( | ||
| <MessageBubble message={item} isOwn={!!item.SenderUserId && item.SenderUserId === currentUserId} showSender={false} currentUserId={currentUserId} onLongPress={() => undefined} onToggleReaction={() => undefined} /> | ||
| <MessageBubble message={item} isOwn={!!item.SenderUserId && item.SenderUserId === currentUserId} showSender={false} currentUserId={currentUserId} onLongPress={setActionsMessage} onToggleReaction={() => undefined} /> |
There was a problem hiding this comment.
Performance regression caused by inline arrow functions in JSX props, which create new function instances on every render. Move these function definitions outside the render method to prevent unnecessary re-renders.
Kody rule violation: Avoid using .bind() or arrow functions in JSX props
Prompt for LLM
File src/app/(app)/chatbot.tsx:
Line 75:
Performance regression caused by inline arrow functions in JSX props, which create new function instances on every render. Move these function definitions outside the render method to prevent unnecessary re-renders.
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
| setEditText(m.Body ?? ''); | ||
| }} | ||
| onDelete={() => undefined} | ||
| onFlag={(m, reason) => useChatStore.getState().flagMessage(m.ChatMessageId, reason)} |
There was a problem hiding this comment.
Unhandled promise rejection occurs because the flagMessage store action lacks a .catch() handler when invoked by the UI event handler. Append .catch(() => useToastStore.getState().showToast('error', t('chat.flag_failed'))) to the useChatStore.getState().flagMessage call to display an error toast on failure.
Kody rule violation: Handle async operations with proper error handling
Prompt for LLM
File src/app/(app)/chatbot.tsx:
Line 172:
Unhandled promise rejection occurs because the `flagMessage` store action lacks a `.catch()` handler when invoked by the UI event handler. Append `.catch(() => useToastStore.getState().showToast('error', t('chat.flag_failed')))` to the `useChatStore.getState().flagMessage` call to display an error toast on failure.
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
Code Review Completed! 🔥The code review was successfully completed based on your current configurations. Kody Guide: Usage and ConfigurationInteracting with Kody
Current Kody ConfigurationReview OptionsThe following review options are enabled or disabled:
|
| void useChatStore | ||
| .getState() | ||
| .fetchChannels() | ||
| .finally(() => setResolveAttempted(true)); |
There was a problem hiding this comment.
Unhandled promise rejection occurs because the fetchChannels() promise chains .finally() without a .catch() handler, risking app crashes and leaving resolveAttempted unset. Add a .catch() block to log the error context before executing .finally(() => setResolveAttempted(true)).
Kody rule violation: Handle async operations with proper error handling
Prompt for LLM
File src/app/chat/[channelId].tsx:
Line 79 to 82:
Unhandled promise rejection occurs because the `fetchChannels()` promise chains `.finally()` without a `.catch()` handler, risking app crashes and leaving `resolveAttempted` unset. Add a `.catch()` block to log the error context before executing `.finally(() => setResolveAttempted(true))`.
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
| try { | ||
| return await Clipboard.setStringAsync(text); | ||
| } catch { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Void return mismatch causes a successful native copy to evaluate as falsy, triggering the 'copy_unavailable' toast in [channelId].tsx:362 and chatbot.tsx:164 because Clipboard.setStringAsync resolves void instead of a boolean. Explicitly return true after the awaited call and update the test's .mockResolvedValue(true) to match the library.
try {
await Clipboard.setStringAsync(text);
return true;
} catch {
return false;
}Prompt for LLM
File src/components/chat/chat-utils.ts:
Line 123 to 127:
Void return mismatch causes a successful native copy to evaluate as falsy, triggering the 'copy_unavailable' toast in `[channelId].tsx:362` and `chatbot.tsx:164` because `Clipboard.setStringAsync` resolves `void` instead of a boolean. Explicitly return `true` after the awaited call and update the test's `.mockResolvedValue(true)` to match the library.
Suggested Code:
try {
await Clipboard.setStringAsync(text);
return true;
} catch {
return false;
}
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
|
Approve |
PR Description
This PR addresses several chatbot (assistant) chat issues and related chat improvements:
Fixed chatbot API response parsing — The chatbot endpoints were assumed to return plain payloads, but they actually use the standard v4
{ Data }envelope. The API calls and model interfaces have been corrected to unwrapresponse.data.Data.Restricted chatbot conversations to the dedicated screen — Opening or deep-linking to a chatbot channel now redirects to the purpose-built chatbot screen instead of the generic conversation screen, ensuring text-only behavior with no reactions, threads, or deletes.
Added message actions to the chatbot screen — Long-pressing a message now offers a restricted action sheet (copy, edit own, pin for moderators, flag). The
MessageActionsSheetgained anassistantprop to hide reactions, reply-in-thread, and delete options in that context.Hid the urgent toggle in thread replies — The
MessageComposernow accepts anallowUrgentprop (defaulting to true) and thread replies passfalse, since urgent priority is a channel-level setting only.Prevented self-acknowledgment of urgent messages — The sender of an urgent message is no longer prompted to acknowledge their own message.