mattermost-mobile/app/components/post_draft/quick_actions/quick_actions.tsx
Felipe Martin 714c3dc769
feat: AI rewrite (#9280)
* feat: ai rewrite

* feat: allow crating content apart from editing it

* feat: feature parity with webapp

* feat: feature parity with webapp

* chore: fixed padding

* map ux to webapp

* refactored ai rewrite logic to separate package

* chore: tests and lint

* Update app/products/ai/rewrite/screens/options/options.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* rewrite post editor animation

* i18n

* ui feedback, centered icon and less top padding

* chore: lint

* Consolidate @ai product into @agents

Move all rewrite functionality from app/products/ai/ into
app/products/agents/ to unify under a single namespace.

- Add rewrite types, store, hooks, components, and screens to agents
- Merge AI client methods into agents client
- Update screen constants (AI_* -> AGENTS_*)
- Update all consumer imports
- Remove AI state from EphemeralStore
- Remove @ai path alias from config
- Delete app/products/ai/ directory

* refactor: load screens from product package

* refactor: move detection logic to the agents pacakge

* refactor: remove "backwards compatibility"

* refactor: move hooks to proper package

* refactor: styles

* refactor: remove unneedd position attribute

* refactor: remove unneeded cancel animation calls

* refactor: "backwards compat"

* refactor: optimize renderContent with useCallback for performance

* refactor: rename variable to avoid confusion

* refactor: update handleRewrite to use async/await for better error handling

* refactor: simplify handleRewrite by always dismissing keyboard

* refactor: use hook, always all keyboard.dismiss

* chore: enhance AgentSelector component with FlatList support

* feat: add rewriteMessage function for AI message rewriting and integrate it into useRewrite hook

* refactor: simplify message length calculation in useHandleSendMessage hook

* refactor: consolidate agent screen constants and integrate with existing screens

* fix: update dependency array in useMemo for isUnrevealedPost to include post expiration metadata

* refactor: remove unused variable to clean up Typing component

* refactor: simplify logic for atDisabled and slashDisabled flags in QuickActions component

* feat: add AIRewriteAction component for AI message rewriting functionality

* revert: thread.ts changes manually

* refactor: integrate useSafeAreaInsets

* refactor: cleanup unused methods

* chore: add comment to clarify casting

* refactor: use_agents

* chore: lint and test

* fix: trim

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-16 16:48:57 +01:00

147 lines
4.5 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import AIRewriteAction from '@agents/components/ai_rewrite_action';
import React from 'react';
import {StyleSheet, View} from 'react-native';
import BoRQuickAction from '@components/post_draft/quick_actions/bor_quick_action';
import {Screens} from '@constants';
import AttachmentAction from './attachment_quick_action';
import EmojiAction from './emoji_quick_action';
import InputAction from './input_quick_action';
import PostPriorityAction from './post_priority_action';
import type {AvailableScreens} from '@typings/screens/navigation';
type Props = {
testID?: string;
canUploadFiles: boolean;
fileCount: number;
isAgentsEnabled: boolean;
isPostPriorityEnabled: boolean;
isBoREnabled: boolean;
canShowPostPriority?: boolean;
canShowSlashCommands?: boolean;
canShowEmojiPicker?: boolean;
maxFileCount: number;
location?: AvailableScreens;
// Draft Handler
value: string;
updateValue: (value: string) => void;
addFiles: (file: FileInfo[]) => void;
postPriority: PostPriority;
updatePostPriority: (postPriority: PostPriority) => void;
postBoRConfig?: PostBoRConfig;
updatePostBoRStatus?: (config: PostBoRConfig) => void;
focus: () => void;
}
export const QUICK_ACTIONS_HEIGHT = 44;
const style = StyleSheet.create({
quickActionsContainer: {
display: 'flex',
flexDirection: 'row',
height: QUICK_ACTIONS_HEIGHT,
marginLeft: 8,
},
});
export default function QuickActions({
testID,
canUploadFiles,
value,
fileCount,
isAgentsEnabled,
isPostPriorityEnabled,
isBoREnabled,
canShowSlashCommands = true,
canShowPostPriority,
canShowEmojiPicker = true,
maxFileCount,
updateValue,
addFiles,
postPriority,
updatePostPriority,
focus,
updatePostBoRStatus,
postBoRConfig,
location,
}: Props) {
const atDisabled = value.endsWith('@');
const slashDisabled = value.length > 0;
const showBoRAction = isBoREnabled && updatePostBoRStatus && location === Screens.CHANNEL;
const atInputActionTestID = `${testID}.at_input_action`;
const slashInputActionTestID = `${testID}.slash_input_action`;
const emojiActionTestID = `${testID}.emoji_action`;
const attachmentActionTestID = `${testID}.attachment_action`;
const aiRewriteActionTestID = `${testID}.ai_rewrite_action`;
const postPriorityActionTestID = `${testID}.post_priority_action`;
const borPriorityActionTestID = `${testID}.bor_action`;
const uploadProps = {
disabled: !canUploadFiles,
fileCount,
maxFileCount,
maxFilesReached: fileCount >= maxFileCount,
onUploadFiles: addFiles,
};
return (
<View
testID={testID}
style={style.quickActionsContainer}
>
<AttachmentAction
testID={attachmentActionTestID}
{...uploadProps}
/>
<InputAction
testID={atInputActionTestID}
disabled={atDisabled}
inputType='at'
updateValue={updateValue}
focus={focus}
/>
{canShowSlashCommands && (
<InputAction
testID={slashInputActionTestID}
disabled={slashDisabled}
inputType='slash'
updateValue={updateValue}
focus={focus}
/>
)}
{canShowEmojiPicker && (
<EmojiAction
testID={emojiActionTestID}
/>
)}
{isAgentsEnabled && (
<AIRewriteAction
testID={aiRewriteActionTestID}
value={value}
updateValue={updateValue}
/>
)}
{isPostPriorityEnabled && canShowPostPriority && (
<PostPriorityAction
testID={postPriorityActionTestID}
postPriority={postPriority}
updatePostPriority={updatePostPriority}
/>
)}
{showBoRAction &&
<BoRQuickAction
testId={borPriorityActionTestID}
postBoRConfig={postBoRConfig}
updatePostBoRStatus={updatePostBoRStatus}
/>
}
</View>
);
}