Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ command:
stream_core_flutter:
git:
url: https://github.com/GetStream/stream-core-flutter.git
ref: 492f6f4ef8c73c64b3f399f92c5e508b7fb39e55
ref: 5572475bb3e4e661cfeca3c9bc232c465a6e08cd
path: packages/stream_core_flutter
synchronized: ^3.1.0+1
thumblr: ^0.0.4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ class StreamCommandPicker extends StatelessWidget {

return OptionDrawer(
margin: EdgeInsets.zero,
title: Padding(
padding: EdgeInsets.symmetric(horizontal: spacing.md),
child: Text(
context.translations.instantCommandsLabel,
style: textTheme.headlineBold,
),
),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: commands.length,
itemCount: commands.length + 1,
itemBuilder: (context, index) {
final command = commands[index];
final command = index == 0 ? null : commands[index - 1];
if (command == null) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: spacing.md),
child: Text(context.translations.instantCommandsLabel, style: textTheme.headlineBold),
);
}

return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: InkWell(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:stream_chat_flutter/scrollable_positioned_list/scrollable_positi
import 'package:stream_chat_flutter/src/message_list_view/floating_date_divider.dart';
import 'package:stream_chat_flutter/src/message_list_view/loading_indicator.dart';
import 'package:stream_chat_flutter/src/message_list_view/mlv_utils.dart';
import 'package:stream_chat_flutter/src/message_list_view/stream_message_list_skeleton_loading.dart';
import 'package:stream_chat_flutter/src/message_list_view/thread_separator.dart';
import 'package:stream_chat_flutter/src/message_list_view/unread_messages_separator.dart';
import 'package:stream_chat_flutter/src/message_widget/ephemeral_message.dart';
Expand Down Expand Up @@ -563,11 +564,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
child: MessageListCore(
paginationLimit: widget.paginationLimit,
messageFilter: widget.messageFilter,
loadingBuilder:
widget.loadingBuilder ??
(context) => const Center(
child: CircularProgressIndicator.adaptive(),
),
loadingBuilder: widget.loadingBuilder ?? (context) => const StreamMessageListSkeletonLoading(),
emptyBuilder:
widget.emptyBuilder ??
(context) => Center(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import 'package:flutter/material.dart';
import 'package:stream_core_flutter/stream_core_flutter.dart';

/// A shimmer loading placeholder for the message list view.
///
/// Displays a skeleton UI with shimmer animation that mimics a chat
/// conversation with incoming (left-aligned) and outgoing (right-aligned)
/// message bubbles using [StreamSkeletonLoading] and [StreamSkeletonBox].
class StreamMessageListSkeletonLoading extends StatelessWidget {
/// Creates a new instance of [StreamMessageListSkeletonLoading].
const StreamMessageListSkeletonLoading({super.key});

@override
Widget build(BuildContext context) {
final spacing = context.streamSpacing;

return StreamSkeletonLoading(
child: LayoutBuilder(
builder: (context, constraints) {
return Padding(
padding: EdgeInsets.all(spacing.md),
child: Column(
children: [
_IncomingBubble(),
SizedBox(height: spacing.lg),
_OutgoingBubble(),
SizedBox(height: spacing.lg),
_IncomingBubble(),
SizedBox(height: spacing.lg),
_OutgoingBubble(),
SizedBox(height: spacing.lg),
_IncomingBubble(),
SizedBox(height: spacing.md),
],
),
);
},
),
);
}
}

class _IncomingBubble extends StatelessWidget {
@override
Widget build(BuildContext context) {
final spacing = context.streamSpacing;

return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const StreamSkeletonBox.circular(radius: 16),
SizedBox(width: spacing.xs),
Expanded(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StreamSkeletonBox(
height: 56,
borderRadius: BorderRadius.only(
topRight: context.streamRadius.xl,
bottomRight: context.streamRadius.xl,
topLeft: context.streamRadius.xl,
),
),
SizedBox(height: spacing.xs),
StreamSkeletonBox(
width: 56,
height: 12,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
SizedBox(height: spacing.xs),
],
),
),
const Spacer(
flex: 1,
),
],
);
}
}

class _OutgoingBubble extends StatelessWidget {
@override
Widget build(BuildContext context) {
final spacing = context.streamSpacing;

return Row(
children: [
const Spacer(
flex: 1,
),
Expanded(
flex: 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
StreamSkeletonBox(
height: 56,
borderRadius: BorderRadius.all(
context.streamRadius.xl,
),
),
SizedBox(height: spacing.xs),
StreamSkeletonBox(
width: 56,
height: 12,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
],
),
),
],
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:stream_core_flutter/stream_core_flutter.dart';

/// A shimmer loading placeholder for the channel list view.
///
/// Displays a skeleton UI with shimmer animation using
/// [StreamSkeletonLoading] and [StreamSkeletonBox] from the core package.
class StreamChannelListSkeletonLoading extends StatelessWidget {
/// Creates a new instance of [StreamChannelListSkeletonLoading].
const StreamChannelListSkeletonLoading({
super.key,
this.itemCount = 7,
});

/// The number of skeleton items to display.
final int itemCount;

@override
Widget build(BuildContext context) {
return StreamSkeletonLoading(
child: ListView.separated(
physics: const NeverScrollableScrollPhysics(),
itemCount: itemCount,
separatorBuilder: (context, index) => const SizedBox(height: 1),
itemBuilder: (context, index) => const _StreamChannelListItemSkeleton(),
),
);
}
}

class _StreamChannelListItemSkeleton extends StatelessWidget {
const _StreamChannelListItemSkeleton();

@override
Widget build(BuildContext context) {
final spacing = context.streamSpacing;

return Padding(
padding: EdgeInsets.all(spacing.md),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
spacing: spacing.md,
children: [
const StreamSkeletonBox.circular(radius: 24),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: spacing.xs,
children: [
Row(
children: [
Expanded(
child: StreamSkeletonBox(
width: double.infinity,
height: 16,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
),
SizedBox(width: spacing.md),
StreamSkeletonBox(
width: 48,
height: 16,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
],
),
Row(
children: [
Expanded(
flex: 3,
child: StreamSkeletonBox(
width: double.infinity,
height: 16,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
),
const Spacer(
flex: 2,
),
],
),
],
),
),
],
),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/scroll_view/channel_scroll_view/stream_channel_list_skeleton_loading.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_error_widget.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_load_more_error.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_load_more_indicator.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_loading_widget.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';

/// Default separator builder for [StreamChannelListView].
Expand Down Expand Up @@ -347,11 +347,7 @@ class StreamChannelListView extends StatelessWidget {
child: StreamScrollViewLoadMoreIndicator(),
),
),
loadingBuilder: (context) =>
loadingBuilder?.call(context) ??
const Center(
child: StreamScrollViewLoadingWidget(),
),
loadingBuilder: (context) => loadingBuilder?.call(context) ?? const StreamChannelListSkeletonLoading(),
errorBuilder: (context, error) =>
errorBuilder?.call(context, error) ??
Center(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import 'package:flutter/material.dart';
import 'package:stream_core_flutter/stream_core_flutter.dart';

/// A shimmer loading placeholder for the thread list view.
///
/// Displays a skeleton UI with shimmer animation using
/// [StreamSkeletonLoading] and [StreamSkeletonBox] from the core package.
class StreamThreadListSkeletonLoading extends StatelessWidget {
/// Creates a new instance of [StreamThreadListSkeletonLoading].
const StreamThreadListSkeletonLoading({
super.key,
this.itemCount = 6,
});

/// The number of skeleton items to display.
final int itemCount;

@override
Widget build(BuildContext context) {
return StreamSkeletonLoading(
child: ListView.separated(
physics: const NeverScrollableScrollPhysics(),
itemCount: itemCount,
separatorBuilder: (context, index) => const SizedBox(height: 1),
itemBuilder: (context, index) => const _StreamThreadListItemSkeleton(),
),
);
}
}

class _StreamThreadListItemSkeleton extends StatelessWidget {
const _StreamThreadListItemSkeleton();

@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(context.streamSpacing.sm),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const StreamSkeletonBox.circular(radius: 24),
SizedBox(width: context.streamSpacing.sm),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
flex: 2,
child: StreamSkeletonBox(
width: double.infinity,
height: 12,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
),
SizedBox(width: context.streamSpacing.sm),
const Spacer(
flex: 2,
),
StreamSkeletonBox(
width: 48,
height: 16,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
],
),
SizedBox(height: context.streamSpacing.xs),
Row(
children: [
Expanded(
child: StreamSkeletonBox(
width: double.infinity,
height: 20,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
),
SizedBox(width: context.streamSpacing.sm),
const SizedBox(width: 48),
],
),
SizedBox(height: context.streamSpacing.xs),
Row(
children: [
const StreamSkeletonBox.circular(radius: 12),
SizedBox(width: context.streamSpacing.xs),
StreamSkeletonBox(
width: 64,
height: 12,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
SizedBox(width: context.streamSpacing.xs),
StreamSkeletonBox(
width: 64,
height: 12,
borderRadius: BorderRadius.all(context.streamRadius.max),
),
],
),
],
),
),
],
),
);
}
}
Loading
Loading