mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-12-27 15:13:46 +00:00
chore(flutter_desktop): ai chat ui improvements (#7025)
* chore: improve hover action bar inner radius * chore: improve ai input appearance
This commit is contained in:
parent
30131fd9e4
commit
7ab68dcc2c
@ -114,6 +114,7 @@ class _DesktopAIPromptInputState extends State<DesktopAIPromptInput> {
|
||||
color: focusNode.hasFocus
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
width: focusNode.hasFocus ? 1.5 : 1.0,
|
||||
),
|
||||
borderRadius: DesktopAIPromptSizes.promptFrameRadius,
|
||||
),
|
||||
@ -138,9 +139,10 @@ class _DesktopAIPromptInputState extends State<DesktopAIPromptInput> {
|
||||
Stack(
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: DesktopAIPromptSizes.textFieldMinHeight +
|
||||
DesktopAIPromptSizes.actionBarHeight,
|
||||
DesktopAIPromptSizes.actionBarHeight +
|
||||
DesktopAIPromptSizes.actionBarPadding.vertical,
|
||||
maxHeight: 300,
|
||||
),
|
||||
child: inputTextField(),
|
||||
@ -504,11 +506,10 @@ class _PromptBottomActions extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: DesktopAIPromptSizes.actionBarHeight,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
margin: DesktopAIPromptSizes.actionBarPadding,
|
||||
child: BlocBuilder<AIPromptInputBloc, AIPromptInputState>(
|
||||
builder: (context, state) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// predefinedFormatButton(),
|
||||
const Spacer(),
|
||||
|
||||
@ -15,6 +15,7 @@ import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../layout_define.dart';
|
||||
import 'chat_mention_page_menu.dart';
|
||||
|
||||
class PromptInputDesktopSelectSourcesButton extends StatefulWidget {
|
||||
@ -128,13 +129,13 @@ class _IndicatorButton extends StatelessWidget {
|
||||
onTap: onTap,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: SizedBox(
|
||||
height: 24,
|
||||
height: DesktopAIPromptSizes.actionBarButtonSize,
|
||||
child: FlowyHover(
|
||||
style: const HoverStyle(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(4, 4, 2, 4),
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(6, 6, 4, 6),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
||||
@ -11,7 +11,7 @@ class AIChatUILayout {
|
||||
query.padding.right,
|
||||
query.viewInsets.bottom + query.padding.bottom,
|
||||
)
|
||||
: const EdgeInsets.only(bottom: 16);
|
||||
: const EdgeInsets.only(bottom: 24);
|
||||
}
|
||||
|
||||
static EdgeInsets get messageMargin => UniversalPlatform.isMobile
|
||||
@ -20,22 +20,23 @@ class AIChatUILayout {
|
||||
}
|
||||
|
||||
class DesktopAIPromptSizes {
|
||||
static const promptFrameRadius = BorderRadius.all(Radius.circular(8));
|
||||
static const promptFrameRadius = BorderRadius.all(Radius.circular(12.0));
|
||||
|
||||
static const attachedFilesBarPadding =
|
||||
EdgeInsets.only(top: 8.0, left: 8.0, right: 8.0);
|
||||
static const attachedFilesPreviewHeight = 48.0;
|
||||
static const attachedFilesPreviewSpacing = 12.0;
|
||||
|
||||
static const textFieldMinHeight = 36.0;
|
||||
static const textFieldMinHeight = 40.0;
|
||||
static const textFieldContentPadding =
|
||||
EdgeInsetsDirectional.fromSTEB(12.0, 12.0, 12.0, 4.0);
|
||||
EdgeInsetsDirectional.fromSTEB(14.0, 12.0, 14.0, 8.0);
|
||||
|
||||
static const actionBarHeight = 28.0;
|
||||
static const actionBarButtonSize = 24.0;
|
||||
static const actionBarHeight = 32.0;
|
||||
static const actionBarPadding = EdgeInsetsDirectional.fromSTEB(8, 0, 8, 4);
|
||||
static const actionBarButtonSize = 28.0;
|
||||
static const actionBarIconSize = 16.0;
|
||||
static const actionBarButtonSpacing = 4.0;
|
||||
static const sendButtonSize = 20.0;
|
||||
static const sendButtonSize = 24.0;
|
||||
}
|
||||
|
||||
class MobileAIPromptSizes {
|
||||
@ -60,7 +61,11 @@ class DesktopAIConvoSizes {
|
||||
|
||||
static const avatarAndChatBubbleSpacing = 12.0;
|
||||
|
||||
static const actionBarIconSize = 24.0;
|
||||
static const actionBarIconSize = 28.0;
|
||||
static const actionBarIconSpacing = 8.0;
|
||||
static const hoverActionBarPadding = EdgeInsets.all(2.0);
|
||||
static const hoverActionBarRadius = BorderRadius.all(Radius.circular(8.0));
|
||||
static const hoverActionBarIconRadius =
|
||||
BorderRadius.all(Radius.circular(6.0));
|
||||
static const actionBarIconRadius = BorderRadius.all(Radius.circular(8.0));
|
||||
}
|
||||
|
||||
@ -109,15 +109,9 @@ class ChatAIBottomInlineActions extends StatelessWidget {
|
||||
DesktopAIConvoSizes.avatarAndChatBubbleSpacing,
|
||||
),
|
||||
child: AIResponseActionBar(
|
||||
message: message,
|
||||
showDecoration: false,
|
||||
children: [
|
||||
CopyButton(
|
||||
textMessage: message as TextMessage,
|
||||
),
|
||||
RegenerateButton(
|
||||
onTap: () => onRegenerate?.call(message.id),
|
||||
),
|
||||
],
|
||||
onRegenerate: onRegenerate,
|
||||
),
|
||||
),
|
||||
const VSpace(32.0),
|
||||
@ -206,23 +200,17 @@ class _ChatAIMessageHoverState extends State<ChatAIMessageHover> {
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: 784,
|
||||
maxHeight: 28,
|
||||
maxHeight: DesktopAIConvoSizes.actionBarIconSize +
|
||||
DesktopAIConvoSizes.hoverActionBarPadding.vertical,
|
||||
),
|
||||
alignment: Alignment.topLeft,
|
||||
child: hoverBubble || hoverActionBar
|
||||
? AIResponseActionBar(
|
||||
message: widget.message,
|
||||
showDecoration: true,
|
||||
children: [
|
||||
CopyButton(
|
||||
textMessage: widget.message as TextMessage,
|
||||
),
|
||||
RegenerateButton(
|
||||
onTap: () =>
|
||||
widget.onRegenerate?.call(widget.message.id),
|
||||
),
|
||||
],
|
||||
onRegenerate: widget.onRegenerate,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
@ -285,12 +273,14 @@ class _ChatAIMessageHoverState extends State<ChatAIMessageHover> {
|
||||
class AIResponseActionBar extends StatelessWidget {
|
||||
const AIResponseActionBar({
|
||||
super.key,
|
||||
required this.message,
|
||||
required this.showDecoration,
|
||||
required this.children,
|
||||
this.onRegenerate,
|
||||
});
|
||||
|
||||
final List<Widget> children;
|
||||
final Message message;
|
||||
final bool showDecoration;
|
||||
final void Function(String)? onRegenerate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -300,14 +290,14 @@ class AIResponseActionBar extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
separatorBuilder: () =>
|
||||
const HSpace(DesktopAIConvoSizes.actionBarIconSpacing),
|
||||
children: children,
|
||||
children: _buildChildren(),
|
||||
);
|
||||
|
||||
return showDecoration
|
||||
? Container(
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesktopAIConvoSizes.actionBarIconRadius,
|
||||
borderRadius: DesktopAIConvoSizes.hoverActionBarRadius,
|
||||
border: Border.all(
|
||||
color: isLightMode
|
||||
? const Color(0x1F1F2329)
|
||||
@ -344,13 +334,29 @@ class AIResponseActionBar extends StatelessWidget {
|
||||
)
|
||||
: child;
|
||||
}
|
||||
|
||||
List<Widget> _buildChildren() {
|
||||
return [
|
||||
CopyButton(
|
||||
isInHoverBar: showDecoration,
|
||||
textMessage: message as TextMessage,
|
||||
),
|
||||
RegenerateButton(
|
||||
isInHoverBar: showDecoration,
|
||||
onTap: () => onRegenerate?.call(message.id),
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class CopyButton extends StatelessWidget {
|
||||
const CopyButton({
|
||||
super.key,
|
||||
required this.isInHoverBar,
|
||||
required this.textMessage,
|
||||
});
|
||||
|
||||
final bool isInHoverBar;
|
||||
final TextMessage textMessage;
|
||||
|
||||
@override
|
||||
@ -360,7 +366,9 @@ class CopyButton extends StatelessWidget {
|
||||
child: FlowyIconButton(
|
||||
width: DesktopAIConvoSizes.actionBarIconSize,
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
radius: DesktopAIConvoSizes.actionBarIconRadius,
|
||||
radius: isInHoverBar
|
||||
? DesktopAIConvoSizes.hoverActionBarIconRadius
|
||||
: DesktopAIConvoSizes.actionBarIconRadius,
|
||||
icon: FlowySvg(
|
||||
FlowySvgs.copy_s,
|
||||
color: Theme.of(context).hintColor,
|
||||
@ -389,9 +397,11 @@ class CopyButton extends StatelessWidget {
|
||||
class RegenerateButton extends StatelessWidget {
|
||||
const RegenerateButton({
|
||||
super.key,
|
||||
required this.isInHoverBar,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
final bool isInHoverBar;
|
||||
final void Function() onTap;
|
||||
|
||||
@override
|
||||
@ -401,7 +411,9 @@ class RegenerateButton extends StatelessWidget {
|
||||
child: FlowyIconButton(
|
||||
width: DesktopAIConvoSizes.actionBarIconSize,
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
radius: DesktopAIConvoSizes.actionBarIconRadius,
|
||||
radius: isInHoverBar
|
||||
? DesktopAIConvoSizes.hoverActionBarIconRadius
|
||||
: DesktopAIConvoSizes.actionBarIconRadius,
|
||||
icon: FlowySvg(
|
||||
FlowySvgs.ai_undo_s,
|
||||
color: Theme.of(context).hintColor,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user