wip: testing positioned list
This commit is contained in:
@@ -2311,75 +2311,78 @@ class _PickerWidgetState extends State<_PickerWidget> {
|
|||||||
if (widget.filePickerIndex != 0) {
|
if (widget.filePickerIndex != 0) {
|
||||||
return const Offstage();
|
return const Offstage();
|
||||||
}
|
}
|
||||||
return FutureBuilder<bool>(
|
return RepaintBoundary(
|
||||||
future: requestPermission,
|
child: FutureBuilder<bool>(
|
||||||
builder: (context, snapshot) {
|
future: requestPermission,
|
||||||
if (!snapshot.hasData) {
|
builder: (context, snapshot) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
if (!snapshot.hasData) {
|
||||||
}
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
|
||||||
if (snapshot.data!) {
|
|
||||||
if (widget.containsFile) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
widget.onAddMoreFilesClick(DefaultAttachmentTypes.file);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
constraints: const BoxConstraints.expand(),
|
|
||||||
color: widget.streamChatTheme.colorTheme.inputBg,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Text(
|
|
||||||
context.translations.addMoreFilesLabel,
|
|
||||||
style: TextStyle(
|
|
||||||
color: widget.streamChatTheme.colorTheme.accentPrimary,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return MediaListView(
|
|
||||||
selectedIds: widget.selectedMedias,
|
|
||||||
onSelect: widget.onMediaSelected,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return InkWell(
|
if (snapshot.data!) {
|
||||||
onTap: () async {
|
if (widget.containsFile) {
|
||||||
PhotoManager.openSetting();
|
return GestureDetector(
|
||||||
},
|
onTap: () {
|
||||||
child: Container(
|
widget.onAddMoreFilesClick(DefaultAttachmentTypes.file);
|
||||||
color: widget.streamChatTheme.colorTheme.inputBg,
|
},
|
||||||
child: Column(
|
child: Container(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
constraints: const BoxConstraints.expand(),
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
color: widget.streamChatTheme.colorTheme.inputBg,
|
||||||
children: [
|
alignment: Alignment.center,
|
||||||
SvgPicture.asset(
|
|
||||||
'svgs/icon_picture_empty_state.svg',
|
|
||||||
package: 'stream_chat_flutter',
|
|
||||||
height: 140,
|
|
||||||
color: widget.streamChatTheme.colorTheme.disabled,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
context.translations.enablePhotoAndVideoAccessMessage,
|
|
||||||
style: widget.streamChatTheme.textTheme.body.copyWith(
|
|
||||||
color: widget.streamChatTheme.colorTheme.textLowEmphasis),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
Center(
|
|
||||||
child: Text(
|
child: Text(
|
||||||
context.translations.allowGalleryAccessMessage,
|
context.translations.addMoreFilesLabel,
|
||||||
style: widget.streamChatTheme.textTheme.bodyBold.copyWith(
|
style: TextStyle(
|
||||||
color: widget.streamChatTheme.colorTheme.accentPrimary,
|
color: widget.streamChatTheme.colorTheme.accentPrimary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
|
}
|
||||||
|
return MediaListView(
|
||||||
|
selectedIds: widget.selectedMedias,
|
||||||
|
onSelect: widget.onMediaSelected,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
PhotoManager.openSetting();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: widget.streamChatTheme.colorTheme.inputBg,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
'svgs/icon_picture_empty_state.svg',
|
||||||
|
package: 'stream_chat_flutter',
|
||||||
|
height: 140,
|
||||||
|
color: widget.streamChatTheme.colorTheme.disabled,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
context.translations.enablePhotoAndVideoAccessMessage,
|
||||||
|
style: widget.streamChatTheme.textTheme.body.copyWith(
|
||||||
|
color:
|
||||||
|
widget.streamChatTheme.colorTheme.textLowEmphasis),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
context.translations.allowGalleryAccessMessage,
|
||||||
|
style: widget.streamChatTheme.textTheme.bodyBold.copyWith(
|
||||||
|
color: widget.streamChatTheme.colorTheme.accentPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
onInBetweenOfPage: () {
|
onInBetweenOfPage: () {
|
||||||
_inBetweenList = true;
|
_inBetweenList = true;
|
||||||
},
|
},
|
||||||
child: ScrollablePositionedList.separated(
|
child: ScrollablePositionedList.builder(
|
||||||
key: _upToDate
|
key: _upToDate
|
||||||
? null
|
? null
|
||||||
: ValueKey(initialIndex + initialAlignment),
|
: ValueKey(initialIndex + initialAlignment),
|
||||||
@@ -465,8 +465,13 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
physics: widget.scrollPhysics,
|
physics: widget.scrollPhysics,
|
||||||
itemScrollController: _scrollController,
|
itemScrollController: _scrollController,
|
||||||
reverse: widget.reverse,
|
reverse: widget.reverse,
|
||||||
addAutomaticKeepAlives: false,
|
itemCount: messages.length,
|
||||||
itemCount: itemCount,
|
findChildIndexCallback: (Key key) {
|
||||||
|
final String data = (key as ValueKey).value;
|
||||||
|
final index =
|
||||||
|
messages.indexWhere((element) => element.id == data);
|
||||||
|
return index + 1;
|
||||||
|
},
|
||||||
|
|
||||||
// Item Count -> 8 (1 parent, 2 header+footer, 2 top+bottom, 3 messages)
|
// Item Count -> 8 (1 parent, 2 header+footer, 2 top+bottom, 3 messages)
|
||||||
// eg: |Type| rev(|Index(item)|) rev(|Index(separator)|) |Index(item)| |Index(separator)|
|
// eg: |Type| rev(|Index(item)|) rev(|Index(separator)|) |Index(item)| |Index(separator)|
|
||||||
@@ -486,72 +491,74 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
// Separator(Footer -> 8??30) -> 0 (count-8)
|
// Separator(Footer -> 8??30) -> 0 (count-8)
|
||||||
// Footer -> 0 (count-8)
|
// Footer -> 0 (count-8)
|
||||||
|
|
||||||
separatorBuilder: (context, i) {
|
// separatorBuilder: (context, i) {
|
||||||
if (i == itemCount - 2) {
|
// if (i == itemCount - 2) {
|
||||||
if (widget.parentMessage == null) {
|
// if (widget.parentMessage == null) {
|
||||||
return const Offstage();
|
// return const Offstage();
|
||||||
}
|
// }
|
||||||
return _buildThreadSeparator();
|
// return _buildThreadSeparator();
|
||||||
}
|
// }
|
||||||
if (i == itemCount - 3) {
|
// if (i == itemCount - 3) {
|
||||||
if (widget.headerBuilder == null) {
|
// if (widget.headerBuilder == null) {
|
||||||
if (_isThreadConversation) return const Offstage();
|
// if (_isThreadConversation) return const Offstage();
|
||||||
return const SizedBox(height: 52);
|
// return const SizedBox(height: 52);
|
||||||
}
|
// }
|
||||||
return const SizedBox(height: 8);
|
// return const SizedBox(height: 8);
|
||||||
}
|
// }
|
||||||
if (i == 0) {
|
// if (i == 0) {
|
||||||
if (widget.footerBuilder == null) {
|
// if (widget.footerBuilder == null) {
|
||||||
return const SizedBox(height: 30);
|
// return const SizedBox(height: 30);
|
||||||
}
|
// }
|
||||||
return const SizedBox(height: 8);
|
// return const SizedBox(height: 8);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (i == 1 || i == itemCount - 4) return const Offstage();
|
// if (i == 1 || i == itemCount - 4) return const Offstage();
|
||||||
|
|
||||||
late final Message message, nextMessage;
|
// late final Message message, nextMessage;
|
||||||
if (widget.reverse) {
|
// if (widget.reverse) {
|
||||||
message = messages[i - 1];
|
// message = messages[i - 1];
|
||||||
nextMessage = messages[i - 2];
|
// nextMessage = messages[i - 2];
|
||||||
} else {
|
// } else {
|
||||||
message = messages[i - 2];
|
// message = messages[i - 2];
|
||||||
nextMessage = messages[i - 1];
|
// nextMessage = messages[i - 1];
|
||||||
}
|
// }
|
||||||
if (!Jiffy(message.createdAt.toLocal()).isSame(
|
// if (!Jiffy(message.createdAt.toLocal()).isSame(
|
||||||
nextMessage.createdAt.toLocal(),
|
// nextMessage.createdAt.toLocal(),
|
||||||
Units.DAY,
|
// Units.DAY,
|
||||||
)) {
|
// )) {
|
||||||
final divider = widget.dateDividerBuilder != null
|
// final divider = widget.dateDividerBuilder != null
|
||||||
? widget.dateDividerBuilder!(
|
// ? widget.dateDividerBuilder!(
|
||||||
nextMessage.createdAt.toLocal(),
|
// nextMessage.createdAt.toLocal(),
|
||||||
)
|
// )
|
||||||
: DateDivider(
|
// : DateDivider(
|
||||||
dateTime: nextMessage.createdAt.toLocal(),
|
// dateTime: nextMessage.createdAt.toLocal(),
|
||||||
);
|
// );
|
||||||
return Padding(
|
// return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
// padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
child: divider,
|
// child: divider,
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
final timeDiff =
|
// final timeDiff =
|
||||||
Jiffy(nextMessage.createdAt.toLocal()).diff(
|
// Jiffy(nextMessage.createdAt.toLocal()).diff(
|
||||||
message.createdAt.toLocal(),
|
// message.createdAt.toLocal(),
|
||||||
Units.MINUTE,
|
// Units.MINUTE,
|
||||||
);
|
// );
|
||||||
|
|
||||||
final isNextUserSame =
|
// final isNextUserSame =
|
||||||
message.user!.id == nextMessage.user?.id;
|
// message.user!.id == nextMessage.user?.id;
|
||||||
final isThread = message.replyCount! > 0;
|
// final isThread = message.replyCount! > 0;
|
||||||
final isDeleted = message.isDeleted;
|
// final isDeleted = message.isDeleted;
|
||||||
if (timeDiff >= 1 ||
|
// if (timeDiff >= 1 ||
|
||||||
!isNextUserSame ||
|
// !isNextUserSame ||
|
||||||
isThread ||
|
// isThread ||
|
||||||
isDeleted) {
|
// isDeleted) {
|
||||||
return const SizedBox(height: 8);
|
// return const SizedBox(height: 8);
|
||||||
}
|
// }
|
||||||
return const SizedBox(height: 2);
|
// return const SizedBox(height: 2);
|
||||||
},
|
// },
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
|
// final myMessage = messages[i];
|
||||||
|
// return buildMessage(myMessage, messages, i, i);
|
||||||
if (i == itemCount - 1) {
|
if (i == itemCount - 1) {
|
||||||
if (widget.parentMessage == null) {
|
if (widget.parentMessage == null) {
|
||||||
return const Offstage();
|
return const Offstage();
|
||||||
@@ -597,7 +604,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
i - 2,
|
i - 2,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
messageWidget = buildMessage(message, messages, i - 2);
|
messageWidget = buildMessage(message, messages, i - 2, i);
|
||||||
}
|
}
|
||||||
return messageWidget;
|
return messageWidget;
|
||||||
},
|
},
|
||||||
@@ -915,16 +922,13 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
return defaultMessageWidget;
|
return defaultMessageWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildMessage(
|
Widget buildMessage(Message message, List<Message> messages, int index,
|
||||||
Message message,
|
[int? actualIndex]) {
|
||||||
List<Message> messages,
|
|
||||||
int index,
|
|
||||||
) {
|
|
||||||
if ((message.type == 'system' || message.type == 'error') &&
|
if ((message.type == 'system' || message.type == 'error') &&
|
||||||
message.text?.isNotEmpty == true) {
|
message.text?.isNotEmpty == true) {
|
||||||
return widget.systemMessageBuilder?.call(context, message) ??
|
return widget.systemMessageBuilder?.call(context, message) ??
|
||||||
SystemMessage(
|
SystemMessage(
|
||||||
key: ValueKey<String>('MESSAGE-${message.id}'),
|
key: ValueKey<String>(message.id),
|
||||||
message: message,
|
message: message,
|
||||||
onMessageTap: (message) {
|
onMessageTap: (message) {
|
||||||
if (widget.onSystemMessageTap != null) {
|
if (widget.onSystemMessageTap != null) {
|
||||||
@@ -1004,7 +1008,8 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
members.firstWhereOrNull((e) => e.user!.id == currentUser!.id);
|
members.firstWhereOrNull((e) => e.user!.id == currentUser!.id);
|
||||||
|
|
||||||
Widget messageWidget = MessageWidget(
|
Widget messageWidget = MessageWidget(
|
||||||
key: ValueKey<String>('MESSAGE-${message.id}'),
|
key: ValueKey<String>(message.id),
|
||||||
|
actualIndex: actualIndex,
|
||||||
message: message,
|
message: message,
|
||||||
reverse: isMyMessage,
|
reverse: isMyMessage,
|
||||||
showReactions: !message.isDeleted,
|
showReactions: !message.isDeleted,
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class MessageWidget extends StatefulWidget {
|
|||||||
this.showInChannelIndicator = false,
|
this.showInChannelIndicator = false,
|
||||||
this.onReplyTap,
|
this.onReplyTap,
|
||||||
this.onThreadTap,
|
this.onThreadTap,
|
||||||
|
this.actualIndex,
|
||||||
this.showUsername = true,
|
this.showUsername = true,
|
||||||
this.showTimestamp = true,
|
this.showTimestamp = true,
|
||||||
this.showReactions = true,
|
this.showReactions = true,
|
||||||
@@ -257,6 +258,8 @@ class MessageWidget extends StatefulWidget {
|
|||||||
}..addAll(customAttachmentBuilders ?? {}),
|
}..addAll(customAttachmentBuilders ?? {}),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
|
final int? actualIndex;
|
||||||
|
|
||||||
/// Function called on mention tap
|
/// Function called on mention tap
|
||||||
final void Function(User)? onMentionTap;
|
final void Function(User)? onMentionTap;
|
||||||
|
|
||||||
@@ -590,6 +593,10 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(border: Border.all()),
|
||||||
|
child: Text('${widget.message.text ?? 'valu'} ${widget.actualIndex}'),
|
||||||
|
);
|
||||||
final avatarWidth =
|
final avatarWidth =
|
||||||
widget.messageTheme.avatarTheme?.constraints.maxWidth ?? 40;
|
widget.messageTheme.avatarTheme?.constraints.maxWidth ?? 40;
|
||||||
final bottomRowPadding =
|
final bottomRowPadding =
|
||||||
@@ -658,6 +665,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
SizedBox(width: avatarWidth + 4),
|
SizedBox(width: avatarWidth + 4),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: PortalEntry(
|
child: PortalEntry(
|
||||||
|
visible: false,
|
||||||
portal: Container(
|
portal: Container(
|
||||||
transform: Matrix4.translationValues(
|
transform: Matrix4.translationValues(
|
||||||
widget.reverse ? 12 : -12, 0, 0),
|
widget.reverse ? 12 : -12, 0, 0),
|
||||||
|
|||||||
Reference in New Issue
Block a user