feat: Added pinned message screen. TODO: Add new logo

This commit is contained in:
Deven Joshi
2021-05-28 20:17:59 +05:30
parent 66ea6ae875
commit 4978d45763
3 changed files with 352 additions and 0 deletions
@@ -6,6 +6,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'channel_file_display_screen.dart';
import 'channel_media_display_screen.dart';
import 'pinned_messages_screen.dart';
import 'main.dart';
import 'routes/routes.dart';
@@ -199,6 +200,65 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
// ),
// onTap: () {},
// ),
OptionListTile(
title: 'Pinned Messages',
tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
titleTextStyle: StreamChatTheme.of(context).textTheme.body,
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: StreamSvgIcon.pictures(
size: 36.0,
color:
StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5),
),
),
trailing: StreamSvgIcon.right(
color: StreamChatTheme.of(context).colorTheme.grey,
),
onTap: () {
final channel = StreamChannel.of(context).channel;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: MessageSearchBloc(
child: PinnedMessagesScreen(
messageTheme: widget.messageTheme,
sortOptions: [
SortOption(
'created_at',
direction: SortOption.ASC,
),
],
paginationParams: PaginationParams(limit: 20),
onShowMessage: (m, c) async {
final client = StreamChat.of(context).client;
final message = m;
final channel = client.channel(
c.type,
id: c.id,
);
if (channel.state == null) {
await channel.watch();
}
Navigator.pushNamed(
context,
Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs(
channel: channel,
initialMessage: message,
),
);
},
),
),
),
),
);
},
),
OptionListTile(
title: 'Photos & Videos',
tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
@@ -10,6 +10,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'channel_file_display_screen.dart';
import 'channel_media_display_screen.dart';
import 'pinned_messages_screen.dart';
import 'chat_info_screen.dart';
import 'main.dart';
import 'routes/routes.dart';
@@ -482,6 +483,65 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
onTap: () {},
);
}),
OptionListTile(
title: 'Pinned Messages',
tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
titleTextStyle: StreamChatTheme.of(context).textTheme.body,
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: StreamSvgIcon.pictures(
size: 32.0,
color:
StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5),
),
),
trailing: StreamSvgIcon.right(
color: StreamChatTheme.of(context).colorTheme.grey,
),
onTap: () {
final channel = StreamChannel.of(context).channel;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: MessageSearchBloc(
child: PinnedMessagesScreen(
messageTheme: widget.messageTheme,
sortOptions: [
SortOption(
'created_at',
direction: SortOption.ASC,
),
],
paginationParams: PaginationParams(limit: 20),
onShowMessage: (m, c) async {
final client = StreamChat.of(context).client;
final message = m;
final channel = client.channel(
c.type,
id: c.id,
);
if (channel.state == null) {
await channel.watch();
}
Navigator.pushNamed(
context,
Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs(
channel: channel,
initialMessage: message,
),
);
},
),
),
),
),
);
},
),
OptionListTile(
tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro,
@@ -0,0 +1,232 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:video_player/video_player.dart';
class PinnedMessagesScreen extends StatefulWidget {
/// The sorting used for the channels matching the filters.
/// Sorting is based on field and direction, multiple sorting options can be provided.
/// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count.
/// Direction can be ascending or descending.
final List<SortOption>? sortOptions;
/// Pagination parameters
/// limit: the number of users to return (max is 30)
/// offset: the offset (max is 1000)
/// message_limit: how many messages should be included to each channel
final PaginationParams? paginationParams;
/// The builder used when the file list is empty.
final WidgetBuilder? emptyBuilder;
final ShowMessageCallback? onShowMessage;
final MessageTheme messageTheme;
const PinnedMessagesScreen({
required this.messageTheme,
this.sortOptions,
this.paginationParams,
this.emptyBuilder,
this.onShowMessage,
});
@override
_PinnedMessagesScreenState createState() => _PinnedMessagesScreenState();
}
class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
Map<String?, VideoPlayerController?> controllerCache = {};
@override
void initState() {
super.initState();
final messageSearchBloc = MessageSearchBloc.of(context);
messageSearchBloc.search(
filter: Filter.in_(
'cid',
[StreamChannel.of(context).channel.cid!],
),
messageFilter: Filter.equal(
'pinned',
true,
),
sort: widget.sortOptions,
pagination: widget.paginationParams,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: StreamChatTheme.of(context).colorTheme.white,
appBar: AppBar(
brightness: Theme.of(context).brightness,
elevation: 1,
centerTitle: true,
title: Text(
'Pinned Messages',
style: TextStyle(
color: StreamChatTheme.of(context).colorTheme.black,
fontSize: 16.0,
),
),
leading: Center(
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Container(
width: 24.0,
height: 24.0,
child: StreamSvgIcon.left(
color: StreamChatTheme.of(context).colorTheme.black,
size: 24.0,
),
),
),
),
backgroundColor: StreamChatTheme.of(context).colorTheme.white,
),
body: _buildMediaGrid(),
);
}
Widget _buildMediaGrid() {
final messageSearchBloc = MessageSearchBloc.of(context);
return StreamBuilder<List<GetMessageResponse>>(
builder: (context, snapshot) {
if (snapshot.data == null) {
return Center(
child: const CircularProgressIndicator(),
);
}
if (snapshot.data!.isEmpty) {
if (widget.emptyBuilder != null) {
return widget.emptyBuilder!(context);
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StreamSvgIcon.message(
size: 136.0,
color: StreamChatTheme.of(context).colorTheme.greyGainsboro,
),
SizedBox(height: 16.0),
Text(
'No pinned items',
style: TextStyle(
fontSize: 17.0,
color: StreamChatTheme.of(context).colorTheme.black,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8.0),
RichText(
textAlign: TextAlign.center,
text: TextSpan(children: [
TextSpan(
text: 'Long-press an important message and\nchoose ',
style: TextStyle(
fontSize: 14.0,
color: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.5),
),
),
TextSpan(
text: 'Pin to conversation',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.5),
),
),
]),
),
],
),
);
}
var data = snapshot.data ?? [];
return LazyLoadScrollView(
onEndOfPage: () => messageSearchBloc.search(
filter: Filter.in_(
'cid',
[StreamChannel.of(context).channel.cid!],
),
messageFilter: Filter.equal(
'pinned',
true,
),
sort: widget.sortOptions,
pagination: widget.paginationParams!.copyWith(
offset: messageSearchBloc.messageResponses?.length ?? 0,
),
),
child: ListView.builder(
itemBuilder: (context, position) {
var user = data[position].message.user!;
var attachments = data[position].message.attachments;
var text = data[position].message.text ?? '';
return ListTile(
leading: UserAvatar(
user: user,
constraints: BoxConstraints(
maxWidth: 56.0,
minHeight: 56.0,
),
borderRadius: BorderRadius.circular(28),
),
title: Text(
user.name,
style: TextStyle(
color: StreamChatTheme.of(context).colorTheme.black,
fontWeight: FontWeight.bold),
),
subtitle: Text(
text != ''
? text
: (attachments.isNotEmpty
? '${attachments.length} attachment${attachments.length > 1 ? 's' : ''}'
: ''),
),
onTap: () {
widget.onShowMessage?.call(data[position].message,
StreamChannel.of(context).channel);
},
);
},
itemCount: snapshot.data!.length,
),
);
},
stream: messageSearchBloc.messagesStream,
);
}
@override
void dispose() {
super.dispose();
for (var c in controllerCache.values) {
c!.dispose();
}
}
}
class _AssetPackage {
Attachment attachment;
Message message;
VideoPlayerController? videoPlayer;
_AssetPackage(this.attachment, this.message, this.videoPlayer);
}