feat(ui): Improve text overflow and spacing in chat drawer

This commit is contained in:
cogwheel0
2025-11-28 14:59:38 +05:30
parent e15ce5b7b6
commit 98ae65d08f
3 changed files with 220 additions and 198 deletions

View File

@@ -709,12 +709,13 @@ class _ChatPageState extends ConsumerState<ChatPage> {
?.cast<String, dynamic>(); ?.cast<String, dynamic>();
final name = final name =
meta?['name']?.toString() ?? parsed.host; meta?['name']?.toString() ?? parsed.host;
final collectionName = final collectionName = result?['collection_name']
result?['collection_name']?.toString(); ?.toString();
// Add as appropriate type // Add as appropriate type
final notifier = final notifier = ref.read(
ref.read(contextAttachmentsProvider.notifier); contextAttachmentsProvider.notifier,
);
if (isYoutube) { if (isYoutube) {
notifier.addYoutube( notifier.addYoutube(
displayName: name, displayName: name,
@@ -1680,13 +1681,9 @@ class _ChatPageState extends ConsumerState<ChatPage> {
constraints: BoxConstraints( constraints: BoxConstraints(
maxWidth: constraints.maxWidth, maxWidth: constraints.maxWidth,
), ),
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.center,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: crossAxisAlignment: CrossAxisAlignment.center,
CrossAxisAlignment.center,
children: [ children: [
AnimatedSwitcher( AnimatedSwitcher(
duration: const Duration( duration: const Duration(
@@ -1701,7 +1698,12 @@ class _ChatPageState extends ConsumerState<ChatPage> {
), ),
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
StreamingTitleText( ConstrainedBox(
constraints: BoxConstraints(
maxWidth:
constraints.maxWidth,
),
child: StreamingTitleText(
title: title:
displayConversationTitle, displayConversationTitle,
style: AppTypography style: AppTypography
@@ -1720,6 +1722,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
.textPrimary .textPrimary
.withValues(alpha: 0.8), .withValues(alpha: 0.8),
), ),
),
const SizedBox( const SizedBox(
height: Spacing.xs, height: Spacing.xs,
), ),
@@ -1734,12 +1737,9 @@ class _ChatPageState extends ConsumerState<ChatPage> {
Transform.translate( Transform.translate(
offset: const Offset(0, 0), offset: const Offset(0, 0),
child: () { child: () {
const double iconPaddingX = const double iconPaddingX = Spacing.xs;
Spacing.xs; const double iconPaddingY = Spacing.xxs;
const double iconPaddingY = const double iconWidth = IconSize.small;
Spacing.xxs;
const double iconWidth =
IconSize.small;
const double iconBoxWidth = const double iconBoxWidth =
(iconPaddingX * 2) + (iconPaddingX * 2) +
(BorderWidth.thin * 2) + (BorderWidth.thin * 2) +
@@ -1763,8 +1763,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
child: Container( child: Container(
padding: padding:
const EdgeInsets.symmetric( const EdgeInsets.symmetric(
horizontal: horizontal: iconPaddingX,
iconPaddingX,
vertical: iconPaddingY, vertical: iconPaddingY,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -1835,8 +1834,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
Platform.isIOS Platform.isIOS
? CupertinoIcons ? CupertinoIcons
.chevron_down .chevron_down
: Icons : Icons.keyboard_arrow_down,
.keyboard_arrow_down,
color: context color: context
.conduitTheme .conduitTheme
.iconSecondary, .iconSecondary,
@@ -1870,12 +1868,9 @@ class _ChatPageState extends ConsumerState<ChatPage> {
vertical: 1.0, vertical: 1.0,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: context color: context.conduitTheme.success
.conduitTheme
.success
.withValues(alpha: 0.1), .withValues(alpha: 0.1),
borderRadius: borderRadius: BorderRadius.circular(
BorderRadius.circular(
AppBorderRadius.badge, AppBorderRadius.badge,
), ),
border: Border.all( border: Border.all(
@@ -1902,7 +1897,6 @@ class _ChatPageState extends ConsumerState<ChatPage> {
], ],
), ),
), ),
),
); );
}, },
), ),

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../shared/widgets/middle_ellipsis_text.dart';
/// Displays a chat title that reveals characters with a streaming animation /// Displays a chat title that reveals characters with a streaming animation
/// whenever the title changes. /// whenever the title changes.
class StreamingTitleText extends StatefulWidget { class StreamingTitleText extends StatefulWidget {
@@ -141,17 +143,33 @@ class _StreamingTitleTextState extends State<StreamingTitleText>
? widget.style.fontSize! * (widget.style.height ?? 1.1) ? widget.style.fontSize! * (widget.style.height ?? 1.1)
: 18.0); : 18.0);
return Row( // When animation is complete, use middle ellipsis for overflow.
// During animation, show partial text with standard Text widget.
final bool animationComplete = revealedGlyphs >= totalGlyphs;
// Use middle ellipsis when animation is complete
if (animationComplete) {
return MiddleEllipsisText(
_activeTitle,
style: widget.style,
textAlign: TextAlign.center,
semanticsLabel: _activeTitle,
);
}
// During animation, use IntrinsicWidth to size the row to the text,
// then clip any overflow from the cursor
return ClipRect(
child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Flexible( Flexible(
child: Text( child: Text(
// When the animation completes we fall back to the full string. visibleText,
revealedGlyphs >= totalGlyphs ? _activeTitle : visibleText,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.fade, overflow: TextOverflow.clip,
softWrap: false, softWrap: false,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: widget.style, style: widget.style,
@@ -171,6 +189,7 @@ class _StreamingTitleTextState extends State<StreamingTitleText>
), ),
), ),
], ],
),
); );
} }

View File

@@ -29,6 +29,7 @@ import '../../../core/models/folder.dart';
import '../../../core/persistence/persistence_keys.dart'; import '../../../core/persistence/persistence_keys.dart';
import '../../../core/persistence/hive_boxes.dart'; import '../../../core/persistence/hive_boxes.dart';
import 'package:hive_ce/hive.dart'; import 'package:hive_ce/hive.dart';
import '../../../shared/widgets/middle_ellipsis_text.dart';
/// Defines the section types that can be collapsed in the chats drawer /// Defines the section types that can be collapsed in the chats drawer
enum _SectionType { pinned, recent } enum _SectionType { pinned, recent }
@@ -420,16 +421,18 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
); );
out.add( out.add(
const SliverToBoxAdapter( const SliverToBoxAdapter(
child: SizedBox(height: Spacing.xs), child: SizedBox(height: Spacing.sm),
), ),
); );
} } else {
// Only add spacing after collapsed folders
out.add( out.add(
const SliverToBoxAdapter( const SliverToBoxAdapter(
child: SizedBox(height: Spacing.xs), child: SizedBox(height: Spacing.xs),
), ),
); );
} }
}
return out.isEmpty return out.isEmpty
? <Widget>[ ? <Widget>[
const SliverToBoxAdapter( const SliverToBoxAdapter(
@@ -665,6 +668,13 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
child: SizedBox(height: Spacing.sm), child: SizedBox(height: Spacing.sm),
), ),
); );
} else {
// Only add spacing after collapsed folders
out.add(
const SliverToBoxAdapter(
child: SizedBox(height: Spacing.xs),
),
);
} }
} }
return out.isEmpty return out.isEmpty
@@ -1903,11 +1913,10 @@ class _ConversationTileContent extends StatelessWidget {
], ],
Flexible( Flexible(
fit: textFit, fit: textFit,
child: Text( child: MiddleEllipsisText(
title, title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: textStyle, style: textStyle,
semanticsLabel: title,
), ),
), ),
...trailing, ...trailing,