mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-06-15 10:42:14 +00:00
fix the response view
This commit is contained in:
parent
b49b9cf452
commit
f66e1f17bf
3 changed files with 180 additions and 229 deletions
|
|
@ -31,34 +31,27 @@ class ChatAudioEntry extends StatelessWidget {
|
|||
return Container(); // media file was purged
|
||||
}
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final textWidth = measureTextWidth(info.text);
|
||||
const timeWidth = 60.0;
|
||||
final isExpanded =
|
||||
info.expanded ||
|
||||
(textWidth + timeWidth + 20 > constraints.maxWidth);
|
||||
final effectiveSpacerWidth =
|
||||
constraints.minWidth - textWidth - timeWidth;
|
||||
final spacerWidth = effectiveSpacerWidth > 0
|
||||
? effectiveSpacerWidth
|
||||
: 0.0;
|
||||
final showTime = info.displayTime || message.modifiedAt != null;
|
||||
|
||||
return Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.8,
|
||||
minWidth: 250,
|
||||
),
|
||||
padding: info.padding,
|
||||
decoration: BoxDecoration(
|
||||
color: info.color,
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (info.displayUserName != '')
|
||||
Text(
|
||||
return IntrinsicWidth(
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.8,
|
||||
minWidth: 280,
|
||||
),
|
||||
padding: info.padding,
|
||||
decoration: BoxDecoration(
|
||||
color: info.color,
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (info.displayUserName != '')
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 2),
|
||||
child: Text(
|
||||
info.displayUserName,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
|
|
@ -66,42 +59,37 @@ class ChatAudioEntry extends StatelessWidget {
|
|||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (isExpanded && info.text != '')
|
||||
Expanded(
|
||||
child: BetterText(
|
||||
text: info.text,
|
||||
textColor: info.textColor,
|
||||
),
|
||||
)
|
||||
else if (info.text != '') ...[
|
||||
BetterText(text: info.text, textColor: info.textColor),
|
||||
SizedBox(width: spacerWidth),
|
||||
] else ...[
|
||||
if (mediaService.mediaFile.downloadState ==
|
||||
DownloadState.ready ||
|
||||
mediaService.mediaFile.downloadState == null)
|
||||
mediaService.tempPath.existsSync()
|
||||
? InChatAudioPlayer(
|
||||
path: mediaService.tempPath.path,
|
||||
message: message,
|
||||
)
|
||||
: Container()
|
||||
else
|
||||
MessageSendStateIcon([message], [mediaService.mediaFile]),
|
||||
SizedBox(width: spacerWidth),
|
||||
],
|
||||
if (info.displayTime || message.modifiedAt != null)
|
||||
FriendlyMessageTime(message: message),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (info.text != '')
|
||||
Expanded(
|
||||
child: BetterText(
|
||||
text: info.text,
|
||||
textColor: info.textColor,
|
||||
),
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: mediaService.mediaFile.downloadState ==
|
||||
DownloadState.ready ||
|
||||
mediaService.mediaFile.downloadState == null
|
||||
? (mediaService.tempPath.existsSync()
|
||||
? InChatAudioPlayer(
|
||||
path: mediaService.tempPath.path,
|
||||
message: message,
|
||||
)
|
||||
: Container())
|
||||
: MessageSendStateIcon([message], [mediaService.mediaFile]),
|
||||
),
|
||||
if (showTime) FriendlyMessageTime(message: message),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,34 +34,27 @@ class ChatTextEntry extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final textWidth = measureTextWidth(info.text);
|
||||
const timeWidth = 60.0;
|
||||
final isExpanded =
|
||||
info.expanded ||
|
||||
(textWidth + timeWidth + 20 > constraints.maxWidth);
|
||||
final effectiveSpacerWidth =
|
||||
constraints.minWidth - textWidth - timeWidth;
|
||||
final spacerWidth = effectiveSpacerWidth > 0
|
||||
? effectiveSpacerWidth
|
||||
: 0.0;
|
||||
final showTime = info.displayTime || message.modifiedAt != null;
|
||||
|
||||
return Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.8,
|
||||
minWidth: info.minWidth,
|
||||
),
|
||||
padding: info.padding,
|
||||
decoration: BoxDecoration(
|
||||
color: info.color,
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (info.displayUserName != '')
|
||||
Text(
|
||||
return IntrinsicWidth(
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.8,
|
||||
minWidth: info.minWidth,
|
||||
),
|
||||
padding: info.padding,
|
||||
decoration: BoxDecoration(
|
||||
color: info.color,
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (info.displayUserName != '')
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 2),
|
||||
child: Text(
|
||||
info.displayUserName,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
|
|
@ -69,31 +62,23 @@ class ChatTextEntry extends StatelessWidget {
|
|||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (isExpanded)
|
||||
Expanded(
|
||||
child: BetterText(
|
||||
text: info.text,
|
||||
textColor: info.textColor,
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
BetterText(text: info.text, textColor: info.textColor),
|
||||
SizedBox(
|
||||
width: spacerWidth,
|
||||
),
|
||||
],
|
||||
if (info.displayTime || message.modifiedAt != null)
|
||||
FriendlyMessageTime(message: message),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: BetterText(
|
||||
text: info.text,
|
||||
textColor: info.textColor,
|
||||
),
|
||||
),
|
||||
if (showTime) FriendlyMessageTime(message: message),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
|||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/visual/views/chats/chat_messages.view.dart';
|
||||
|
||||
class ResponseContainer extends StatefulWidget {
|
||||
class ResponseContainer extends StatelessWidget {
|
||||
const ResponseContainer({
|
||||
required this.msg,
|
||||
required this.group,
|
||||
|
|
@ -27,86 +27,55 @@ class ResponseContainer extends StatefulWidget {
|
|||
final BorderRadius borderRadius;
|
||||
final void Function(String)? scrollToMessage;
|
||||
|
||||
@override
|
||||
State<ResponseContainer> createState() => _ResponseContainerState();
|
||||
}
|
||||
|
||||
class _ResponseContainerState extends State<ResponseContainer> {
|
||||
double? minWidth;
|
||||
final GlobalKey _message = GlobalKey();
|
||||
final GlobalKey _preview = GlobalKey();
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final messageBox =
|
||||
_message.currentContext?.findRenderObject() as RenderBox?;
|
||||
final previewBox =
|
||||
_preview.currentContext?.findRenderObject() as RenderBox?;
|
||||
if (messageBox == null || previewBox == null) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
if (messageBox.size.width > previewBox.size.width) {
|
||||
minWidth = messageBox.size.width;
|
||||
} else {
|
||||
minWidth = previewBox.size.width;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.msg.quotesMessageId == null) {
|
||||
if (widget.child == null) {
|
||||
if (msg.quotesMessageId == null) {
|
||||
if (child == null) {
|
||||
return Container();
|
||||
}
|
||||
return widget.child!;
|
||||
return child!;
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: widget.scrollToMessage == null
|
||||
onTap: scrollToMessage == null
|
||||
? null
|
||||
: () => widget.scrollToMessage!(widget.msg.quotesMessageId!),
|
||||
: () => scrollToMessage!(msg.quotesMessageId!),
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: getMessageColor(widget.msg.senderId != null),
|
||||
borderRadius: widget.borderRadius,
|
||||
color: getMessageColor(msg.senderId != null),
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
key: _preview,
|
||||
padding: const EdgeInsets.only(top: 4, right: 4, left: 4),
|
||||
child: Container(
|
||||
width: minWidth,
|
||||
decoration: BoxDecoration(
|
||||
color: context.color.surface.withAlpha(150),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(8),
|
||||
topLeft: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(4),
|
||||
bottomRight: Radius.circular(4),
|
||||
child: IntrinsicWidth(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4, right: 4, left: 4),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.color.surface.withAlpha(150),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(8),
|
||||
topLeft: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(4),
|
||||
bottomRight: Radius.circular(4),
|
||||
),
|
||||
),
|
||||
child: ResponsePreview(
|
||||
group: group,
|
||||
messageId: msg.quotesMessageId,
|
||||
showBorder: false,
|
||||
showLeftBorder: false,
|
||||
colorUsername: false,
|
||||
),
|
||||
),
|
||||
child: ResponsePreview(
|
||||
group: widget.group,
|
||||
messageId: widget.msg.quotesMessageId,
|
||||
showBorder: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
key: _message,
|
||||
width: minWidth,
|
||||
child: widget.child,
|
||||
),
|
||||
],
|
||||
if (child != null) child!,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -119,6 +88,8 @@ class ResponsePreview extends StatefulWidget {
|
|||
required this.showBorder,
|
||||
this.message,
|
||||
this.messageId,
|
||||
this.showLeftBorder = true,
|
||||
this.colorUsername = false,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -126,6 +97,8 @@ class ResponsePreview extends StatefulWidget {
|
|||
final String? messageId;
|
||||
final Group group;
|
||||
final bool showBorder;
|
||||
final bool showLeftBorder;
|
||||
final bool colorUsername;
|
||||
|
||||
@override
|
||||
State<ResponsePreview> createState() => _ResponsePreviewState();
|
||||
|
|
@ -212,80 +185,85 @@ class _ResponsePreviewState extends State<ResponsePreview> {
|
|||
|
||||
if (_message!.senderId == null) {
|
||||
_username = context.lang.you;
|
||||
// _username = _message!.senderId.toString();
|
||||
}
|
||||
|
||||
color = getMessageColor(_message!.senderId != null);
|
||||
}
|
||||
|
||||
if (!_message!.mediaStored) {
|
||||
return Container(
|
||||
padding: widget.showBorder
|
||||
? const EdgeInsets.only(left: 10, right: 10)
|
||||
: const EdgeInsets.symmetric(horizontal: 5),
|
||||
decoration: (widget.showBorder)
|
||||
? BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: color,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
_username,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (subtitle != null) Text(subtitle),
|
||||
],
|
||||
final hasImage =
|
||||
_message != null &&
|
||||
_message!.mediaStored &&
|
||||
_mediaService != null &&
|
||||
_mediaService!.mediaFile.type != MediaType.audio;
|
||||
|
||||
Widget? imageWidget;
|
||||
if (hasImage) {
|
||||
final isVideo = _mediaService!.mediaFile.type == MediaType.video;
|
||||
final pathToCheck = isVideo
|
||||
? _mediaService!.thumbnailPath
|
||||
: _mediaService!.storedPath;
|
||||
if (pathToCheck.existsSync() && pathToCheck.lengthSync() > 0) {
|
||||
imageWidget = Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
margin: const EdgeInsets.only(left: 8),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: Image.file(
|
||||
pathToCheck,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
width: 200,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: color,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.only(
|
||||
left: widget.showLeftBorder ? 8 : 4,
|
||||
right: 6,
|
||||
top: 4,
|
||||
bottom: 4,
|
||||
),
|
||||
constraints: BoxConstraints(
|
||||
minWidth: 60,
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.7,
|
||||
),
|
||||
decoration: widget.showLeftBorder
|
||||
? BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: color,
|
||||
width: 2.5,
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
_username,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: widget.colorUsername ? color : null,
|
||||
),
|
||||
),
|
||||
if (subtitle != null) Text(subtitle),
|
||||
if (subtitle != null)
|
||||
Text(
|
||||
subtitle,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_mediaService != null &&
|
||||
_mediaService!.mediaFile.type != MediaType.audio)
|
||||
() {
|
||||
final isVideo = _mediaService!.mediaFile.type == MediaType.video;
|
||||
final pathToCheck = isVideo
|
||||
? _mediaService!.thumbnailPath
|
||||
: _mediaService!.storedPath;
|
||||
if (pathToCheck.existsSync() && pathToCheck.lengthSync() > 0) {
|
||||
return SizedBox(
|
||||
height: widget.showBorder ? 100 : 210,
|
||||
child: Image.file(pathToCheck),
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
}(),
|
||||
if (imageWidget != null) imageWidget,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue