Merge pull request #87 from GetStream/chore/update-package-lints

chore: update package lints and apply fixes
This commit is contained in:
Salvatore Giordano
2022-10-06 15:19:13 +02:00
committed by GitHub
29 changed files with 481 additions and 462 deletions
@@ -5,8 +5,6 @@ import 'package:imessage/utils.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'
show Channel; show Channel;
import 'utils.dart';
class ChannelPreview extends StatelessWidget { class ChannelPreview extends StatelessWidget {
final VoidCallback onTap; final VoidCallback onTap;
final Channel channel; final Channel channel;
@@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+8 -6
View File
@@ -45,12 +45,14 @@ StreamChatClient buildStreamChatClient(
)..chatPersistenceClient = chatPersistentClient; )..chatPersistenceClient = chatPersistentClient;
} }
class MyApp extends StatefulWidget { class StreamChatSampleApp extends StatefulWidget {
const StreamChatSampleApp({super.key});
@override @override
_MyAppState createState() => _MyAppState(); State<StreamChatSampleApp> createState() => _StreamChatSampleAppState();
} }
class _MyAppState extends State<MyApp> class _StreamChatSampleAppState extends State<StreamChatSampleApp>
with SplashScreenStateMixin, TickerProviderStateMixin { with SplashScreenStateMixin, TickerProviderStateMixin {
InitData? _initData; InitData? _initData;
@@ -58,7 +60,7 @@ class _MyAppState extends State<MyApp>
String? apiKey, userId, token; String? apiKey, userId, token;
if (!kIsWeb) { if (!kIsWeb) {
final secureStorage = FlutterSecureStorage(); const secureStorage = FlutterSecureStorage();
apiKey = await secureStorage.read(key: kStreamApiKey); apiKey = await secureStorage.read(key: kStreamApiKey);
userId = await secureStorage.read(key: kStreamUserId); userId = await secureStorage.read(key: kStreamUserId);
token = await secureStorage.read(key: kStreamToken); token = await secureStorage.read(key: kStreamToken);
@@ -95,7 +97,7 @@ class _MyAppState extends State<MyApp>
forwardAnimations(); forwardAnimations();
}); });
} else { } else {
Future.delayed(Duration(milliseconds: 1500)).then((value) { Future.delayed(const Duration(milliseconds: 1500)).then((value) {
forwardAnimations(); forwardAnimations();
}); });
} }
@@ -157,7 +159,7 @@ class _MyAppState extends State<MyApp>
} }
return [ return [
AppRoutes.generateRoute( AppRoutes.generateRoute(
RouteSettings( const RouteSettings(
name: Routes.CHOOSE_USER, name: Routes.CHOOSE_USER,
), ),
)! )!
+3 -3
View File
@@ -19,7 +19,7 @@ void main() async {
} }
}; };
Future<void> _reportError(dynamic error, StackTrace stackTrace) async { Future<void> reportError(dynamic error, StackTrace stackTrace) async {
// Print the exception to the console. // Print the exception to the console.
if (kDebugMode) { if (kDebugMode) {
// Print the full stacktrace in debug mode. // Print the full stacktrace in debug mode.
@@ -36,8 +36,8 @@ void main() async {
await SentryFlutter.init( await SentryFlutter.init(
(options) => options.dsn = sentryDsn, (options) => options.dsn = sentryDsn,
); );
runApp(MyApp()); runApp(const StreamChatSampleApp());
}, },
_reportError, reportError,
); );
} }
@@ -10,8 +10,10 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'choose_user_page.dart'; import 'choose_user_page.dart';
class AdvancedOptionsPage extends StatefulWidget { class AdvancedOptionsPage extends StatefulWidget {
const AdvancedOptionsPage({super.key});
@override @override
_AdvancedOptionsPageState createState() => _AdvancedOptionsPageState(); State<AdvancedOptionsPage> createState() => _AdvancedOptionsPageState();
} }
class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> { class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
@@ -88,7 +90,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
.textHighEmphasis, .textHighEmphasis,
), ),
decoration: InputDecoration( decoration: InputDecoration(
errorStyle: TextStyle(height: 0, fontSize: 0), errorStyle: const TextStyle(height: 0, fontSize: 0),
labelStyle: TextStyle( labelStyle: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -110,7 +112,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
), ),
SizedBox(height: 8), const SizedBox(height: 8),
TextFormField( TextFormField(
controller: _userIdController, controller: _userIdController,
onChanged: (_) { onChanged: (_) {
@@ -139,7 +141,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( decoration: InputDecoration(
errorStyle: TextStyle(height: 0, fontSize: 0), errorStyle: const TextStyle(height: 0, fontSize: 0),
labelStyle: TextStyle( labelStyle: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 14, fontSize: 14,
@@ -160,7 +162,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
: AppLocalizations.of(context).userId, : AppLocalizations.of(context).userId,
), ),
), ),
SizedBox(height: 8), const SizedBox(height: 8),
TextFormField( TextFormField(
onChanged: (_) { onChanged: (_) {
if (_userTokenError != null) { if (_userTokenError != null) {
@@ -189,7 +191,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( decoration: InputDecoration(
errorStyle: TextStyle(height: 0, fontSize: 0), errorStyle: const TextStyle(height: 0, fontSize: 0),
labelStyle: TextStyle( labelStyle: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 14, fontSize: 14,
@@ -210,7 +212,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
: AppLocalizations.of(context).userToken, : AppLocalizations.of(context).userToken,
), ),
), ),
SizedBox(height: 8), const SizedBox(height: 8),
TextFormField( TextFormField(
controller: _usernameController, controller: _usernameController,
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
@@ -231,7 +233,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
labelText: AppLocalizations.of(context).usernameOptional, labelText: AppLocalizations.of(context).usernameOptional,
), ),
), ),
Spacer(), const Spacer(),
ElevatedButton( ElevatedButton(
style: ButtonStyle( style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>( backgroundColor: MaterialStateProperty.all<Color>(
@@ -286,7 +288,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
height: 100, height: 100,
width: 100, width: 100,
child: Center( child: const Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
), ),
@@ -294,6 +296,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
); );
final client = buildStreamChatClient(apiKey); final client = buildStreamChatClient(apiKey);
final navigator = Navigator.of(context);
try { try {
await client.connectUser( await client.connectUser(
@@ -303,7 +306,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
userToken, userToken,
); );
final secureStorage = FlutterSecureStorage(); const secureStorage = FlutterSecureStorage();
secureStorage.write( secureStorage.write(
key: kStreamApiKey, key: kStreamApiKey,
value: apiKey, value: apiKey,
@@ -330,8 +333,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
return; return;
} }
loading = false; loading = false;
await Navigator.pushNamedAndRemoveUntil( await navigator.pushNamedAndRemoveUntil(
context,
Routes.HOME, Routes.HOME,
ModalRoute.withName(Routes.HOME), ModalRoute.withName(Routes.HOME),
arguments: HomePageArgs(client), arguments: HomePageArgs(client),
@@ -339,7 +341,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
} }
}, },
), ),
StreamVersion(), const StreamVersion(),
], ],
), ),
), ),
@@ -27,10 +27,10 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
), ),
messageFilter: Filter.in_( messageFilter: Filter.in_(
'attachments.type', 'attachments.type',
['file'], const ['file'],
), ),
sort: [ sort: [
SortOption( const SortOption(
'created_at', 'created_at',
direction: SortOption.ASC, direction: SortOption.ASC,
), ),
@@ -52,7 +52,7 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
fontSize: 16.0, fontSize: 16.0,
), ),
), ),
leading: StreamBackButton(), leading: const StreamBackButton(),
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
), ),
body: ValueListenableBuilder( body: ValueListenableBuilder(
@@ -73,7 +73,7 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
size: 136.0, size: 136.0,
color: StreamChatTheme.of(context).colorTheme.disabled, color: StreamChatTheme.of(context).colorTheme.disabled,
), ),
SizedBox(height: 16.0), const SizedBox(height: 16.0),
Text( Text(
AppLocalizations.of(context).noFiles, AppLocalizations.of(context).noFiles,
style: TextStyle( style: TextStyle(
@@ -83,7 +83,7 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
.textHighEmphasis, .textHighEmphasis,
), ),
), ),
SizedBox(height: 8.0), const SizedBox(height: 8.0),
Text( Text(
AppLocalizations.of(context).filesAppearHere, AppLocalizations.of(context).filesAppearHere,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@@ -132,10 +132,10 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
), ),
); );
}, },
loading: () => Center( loading: () => const Center(
child: const CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
error: (_) => Offstage(), error: (_) => const Offstage(),
); );
}, },
), ),
@@ -18,7 +18,7 @@ class ChannelListPage extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_ChannelListPageState createState() => _ChannelListPageState(); State<ChannelListPage> createState() => _ChannelListPageState();
} }
class _ChannelListPageState extends State<ChannelListPage> { class _ChannelListPageState extends State<ChannelListPage> {
@@ -37,7 +37,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
? StreamChatTheme.of(context).colorTheme.textHighEmphasis ? StreamChatTheme.of(context).colorTheme.textHighEmphasis
: Colors.grey, : Colors.grey,
), ),
Positioned( const Positioned(
top: -3, top: -3,
right: -16, right: -16,
child: StreamUnreadIndicator(), child: StreamUnreadIndicator(),
@@ -66,7 +66,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final user = StreamChat.of(context).currentUser; final user = StreamChat.of(context).currentUser;
if (user == null) { if (user == null) {
return Offstage(); return const Offstage();
} }
return Scaffold( return Scaffold(
backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, backgroundColor: StreamChatTheme.of(context).colorTheme.appBg,
@@ -99,7 +99,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
), ),
body: IndexedStack( body: IndexedStack(
index: _currentIndex, index: _currentIndex,
children: [ children: const [
ChannelList(), ChannelList(),
UserMentionsPage(), UserMentionsPage(),
], ],
@@ -164,13 +164,14 @@ class LeftDrawer extends StatelessWidget {
StreamUserAvatar( StreamUserAvatar(
user: user, user: user,
showOnlineStatus: false, showOnlineStatus: false,
constraints: BoxConstraints.tight(Size.fromRadius(20)), constraints:
BoxConstraints.tight(const Size.fromRadius(20)),
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 16.0), padding: const EdgeInsets.only(left: 16.0),
child: Text( child: Text(
user.name, user.name,
style: TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -194,7 +195,7 @@ class LeftDrawer extends StatelessWidget {
}, },
title: Text( title: Text(
AppLocalizations.of(context).newDirectMessage, AppLocalizations.of(context).newDirectMessage,
style: TextStyle( style: const TextStyle(
fontSize: 14.5, fontSize: 14.5,
), ),
), ),
@@ -214,7 +215,7 @@ class LeftDrawer extends StatelessWidget {
}, },
title: Text( title: Text(
AppLocalizations.of(context).newGroup, AppLocalizations.of(context).newGroup,
style: TextStyle( style: const TextStyle(
fontSize: 14.5, fontSize: 14.5,
), ),
), ),
@@ -224,21 +225,20 @@ class LeftDrawer extends StatelessWidget {
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
child: ListTile( child: ListTile(
onTap: () async { onTap: () async {
final client = StreamChat.of(context).client;
final navigator =
Navigator.of(context, rootNavigator: true);
Navigator.pop(context); Navigator.pop(context);
if (!kIsWeb) { if (!kIsWeb) {
final secureStorage = FlutterSecureStorage(); const secureStorage = FlutterSecureStorage();
await secureStorage.deleteAll(); await secureStorage.deleteAll();
} }
final client = StreamChat.of(context).client;
client.disconnectUser(); client.disconnectUser();
await client.dispose(); await client.dispose();
await Navigator.of( await navigator.pushNamedAndRemoveUntil(
context,
rootNavigator: true,
).pushNamedAndRemoveUntil(
Routes.CHOOSE_USER, Routes.CHOOSE_USER,
ModalRoute.withName(Routes.CHOOSE_USER), ModalRoute.withName(Routes.CHOOSE_USER),
); );
@@ -251,7 +251,7 @@ class LeftDrawer extends StatelessWidget {
), ),
title: Text( title: Text(
AppLocalizations.of(context).signOut, AppLocalizations.of(context).signOut,
style: TextStyle( style: const TextStyle(
fontSize: 14.5, fontSize: 14.5,
), ),
), ),
@@ -263,12 +263,11 @@ class LeftDrawer extends StatelessWidget {
.colorTheme .colorTheme
.textLowEmphasis, .textLowEmphasis,
onPressed: () async { onPressed: () async {
final theme = Theme.of(context);
final sp = await StreamingSharedPreferences.instance; final sp = await StreamingSharedPreferences.instance;
sp.setInt( sp.setInt(
'theme', 'theme',
Theme.of(context).brightness == Brightness.dark theme.brightness == Brightness.dark ? 1 : -1,
? 1
: -1,
); );
}, },
), ),
@@ -30,10 +30,10 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
), ),
messageFilter: Filter.in_( messageFilter: Filter.in_(
'attachments.type', 'attachments.type',
['image', 'video'], const ['image', 'video'],
), ),
sort: [ sort: [
SortOption( const SortOption(
'created_at', 'created_at',
direction: SortOption.ASC, direction: SortOption.ASC,
), ),
@@ -55,7 +55,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
fontSize: 16.0, fontSize: 16.0,
), ),
), ),
leading: StreamBackButton(), leading: const StreamBackButton(),
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
), ),
body: ValueListenableBuilder( body: ValueListenableBuilder(
@@ -73,7 +73,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
size: 136.0, size: 136.0,
color: StreamChatTheme.of(context).colorTheme.disabled, color: StreamChatTheme.of(context).colorTheme.disabled,
), ),
SizedBox(height: 16.0), const SizedBox(height: 16.0),
Text( Text(
AppLocalizations.of(context).noMedia, AppLocalizations.of(context).noMedia,
style: TextStyle( style: TextStyle(
@@ -83,7 +83,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
.textHighEmphasis, .textHighEmphasis,
), ),
), ),
SizedBox(height: 8.0), const SizedBox(height: 8.0),
Text( Text(
AppLocalizations.of(context) AppLocalizations.of(context)
.photosOrVideosWillAppearHere, .photosOrVideosWillAppearHere,
@@ -131,7 +131,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
} }
}, },
child: GridView.builder( child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3), crossAxisCount: 3),
itemBuilder: (context, position) { itemBuilder: (context, position) {
var channel = StreamChannel.of(context).channel; var channel = StreamChannel.of(context).channel;
@@ -158,6 +158,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
onShowMessage: (m, c) async { onShowMessage: (m, c) async {
final client = final client =
StreamChat.of(context).client; StreamChat.of(context).client;
final navigator = Navigator.of(context);
final message = m; final message = m;
final channel = client.channel( final channel = client.channel(
c.type, c.type,
@@ -166,8 +167,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
if (channel.state == null) { if (channel.state == null) {
await channel.watch(); await channel.watch();
} }
Navigator.pushNamed( navigator.pushNamed(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs( arguments: ChannelPageArgs(
channel: channel, channel: channel,
@@ -197,10 +197,10 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
), ),
); );
}, },
loading: () => Center( loading: () => const Center(
child: const CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
error: (_) => Offstage(), error: (_) => const Offstage(),
); );
}, },
), ),
@@ -30,12 +30,12 @@ class ChannelPage extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_ChannelPageState createState() => _ChannelPageState(); State<ChannelPage> createState() => _ChannelPageState();
} }
class _ChannelPageState extends State<ChannelPage> { class _ChannelPageState extends State<ChannelPage> {
FocusNode? _focusNode; FocusNode? _focusNode;
StreamMessageInputController _messageInputController = final StreamMessageInputController _messageInputController =
StreamMessageInputController(); StreamMessageInputController();
@override @override
@@ -64,7 +64,8 @@ class _ChannelPageState extends State<ChannelPage> {
appBar: StreamChannelHeader( appBar: StreamChannelHeader(
showTypingIndicator: false, showTypingIndicator: false,
onImageTap: () async { onImageTap: () async {
var channel = StreamChannel.of(context).channel; final channel = StreamChannel.of(context).channel;
final navigator = Navigator.of(context);
if (channel.memberCount == 2 && channel.isDistinct) { if (channel.memberCount == 2 && channel.isDistinct) {
final currentUser = StreamChat.of(context).currentUser; final currentUser = StreamChat.of(context).currentUser;
@@ -76,17 +77,17 @@ class _ChannelPageState extends State<ChannelPage> {
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => StreamChannel( builder: (context) => StreamChannel(
channel: channel,
child: ChatInfoScreen( child: ChatInfoScreen(
messageTheme: StreamChatTheme.of(context).ownMessageTheme, messageTheme: StreamChatTheme.of(context).ownMessageTheme,
user: otherUser.user, user: otherUser.user,
), ),
channel: channel,
), ),
), ),
); );
if (pop == true) { if (pop == true) {
Navigator.pop(context); navigator.pop();
} }
} }
} else { } else {
@@ -94,10 +95,10 @@ class _ChannelPageState extends State<ChannelPage> {
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => StreamChannel( builder: (context) => StreamChannel(
channel: channel,
child: GroupInfoScreen( child: GroupInfoScreen(
messageTheme: StreamChatTheme.of(context).ownMessageTheme, messageTheme: StreamChatTheme.of(context).ownMessageTheme,
), ),
channel: channel,
), ),
), ),
); );
@@ -116,6 +117,7 @@ class _ChannelPageState extends State<ChannelPage> {
onMessageSwiped: _reply, onMessageSwiped: _reply,
messageFilter: defaultFilter, messageFilter: defaultFilter,
messageBuilder: (context, details, messages, defaultMessage) { messageBuilder: (context, details, messages, defaultMessage) {
final navigator = Navigator.of(context);
return defaultMessage.copyWith( return defaultMessage.copyWith(
onReplyTap: _reply, onReplyTap: _reply,
onShowMessage: (m, c) async { onShowMessage: (m, c) async {
@@ -128,8 +130,7 @@ class _ChannelPageState extends State<ChannelPage> {
if (channel.state == null) { if (channel.state == null) {
await channel.watch(); await channel.watch();
} }
Navigator.pushReplacementNamed( navigator.pushReplacementNamed(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs( arguments: ChannelPageArgs(
channel: channel, channel: channel,
@@ -184,8 +185,8 @@ class _ChannelPageState extends State<ChannelPage> {
} }
bool defaultFilter(Message m) { bool defaultFilter(Message m) {
var _currentUser = StreamChat.of(context).currentUser; final currentUser = StreamChat.of(context).currentUser;
final isMyMessage = m.user?.id == _currentUser?.id; final isMyMessage = m.user?.id == currentUser?.id;
final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true; final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true;
if (isDeletedOrShadowed && !isMyMessage) return false; if (isDeletedOrShadowed && !isMyMessage) return false;
return true; return true;
@@ -20,7 +20,7 @@ class ChatInfoScreen extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_ChatInfoScreenState createState() => _ChatInfoScreenState(); State<ChatInfoScreen> createState() => _ChatInfoScreenState();
} }
class _ChatInfoScreenState extends State<ChatInfoScreen> { class _ChatInfoScreenState extends State<ChatInfoScreen> {
@@ -69,7 +69,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: StreamUserAvatar( child: StreamUserAvatar(
user: widget.user!, user: widget.user!,
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
width: 72.0, width: 72.0,
height: 72.0, height: 72.0,
), ),
@@ -79,11 +79,12 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
), ),
Text( Text(
widget.user!.name, widget.user!.name,
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), style: const TextStyle(
fontSize: 16.0, fontWeight: FontWeight.bold),
), ),
SizedBox(height: 7.0), const SizedBox(height: 7.0),
_buildConnectedTitleState(), _buildConnectedTitleState(),
SizedBox(height: 15.0), const SizedBox(height: 15.0),
StreamOptionListTile( StreamOptionListTile(
title: '@${widget.user!.id}', title: '@${widget.user!.id}',
tileColor: StreamChatTheme.of(context).colorTheme.appBg, tileColor: StreamChatTheme.of(context).colorTheme.appBg,
@@ -103,7 +104,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
), ),
], ],
), ),
Positioned( const Positioned(
top: 0, top: 0,
left: 0, left: 0,
width: 58, width: 58,
@@ -120,18 +121,6 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
return Column( return Column(
children: [ children: [
// _OptionListTile(
// title: 'Notifications',
// leading: StreamSvgIcon.Icon_notification(
// size: 24.0,
// color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5),
// ),
// trailing: CupertinoSwitch(
// value: true,
// onChanged: (val) {},
// ),
// onTap: () {},
// ),
StreamBuilder<bool>( StreamBuilder<bool>(
stream: StreamChannel.of(context).channel.isMutedStream, stream: StreamChannel.of(context).channel.isMutedStream,
builder: (context, snapshot) { builder: (context, snapshot) {
@@ -152,7 +141,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
), ),
), ),
trailing: snapshot.data == null trailing: snapshot.data == null
? CircularProgressIndicator() ? const CircularProgressIndicator()
: ValueListenableBuilder<bool?>( : ValueListenableBuilder<bool?>(
valueListenable: mutedBool, valueListenable: mutedBool,
builder: (context, value, _) { builder: (context, value, _) {
@@ -172,24 +161,6 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
onTap: () {}, onTap: () {},
); );
}), }),
// _OptionListTile(
// title: 'Block User',
// leading: StreamSvgIcon.Icon_user_delete(
// size: 24.0,
// color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5),
// ),
// trailing: CupertinoSwitch(
// value: widget.user.banned,
// onChanged: (val) {
// if (widget.user.banned) {
// channel.channel.shadowBan(widget.user.id, {});
// } else {
// channel.channel.unbanUser(widget.user.id);
// }
// },
// ),
// onTap: () {},
// ),
StreamOptionListTile( StreamOptionListTile(
title: AppLocalizations.of(context).pinnedMessages, title: AppLocalizations.of(context).pinnedMessages,
tileColor: StreamChatTheme.of(context).colorTheme.appBg, tileColor: StreamChatTheme.of(context).colorTheme.appBg,
@@ -215,7 +186,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
MaterialPageRoute( MaterialPageRoute(
builder: (context) => StreamChannel( builder: (context) => StreamChannel(
channel: channel, channel: channel,
child: PinnedMessagesScreen(), child: const PinnedMessagesScreen(),
), ),
), ),
); );
@@ -338,6 +309,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
} }
void _showDeleteDialog() async { void _showDeleteDialog() async {
final streamChannel = StreamChannel.of(context);
final res = await showConfirmationBottomSheet( final res = await showConfirmationBottomSheet(
context, context,
title: AppLocalizations.of(context).deleteConversationTitle, title: AppLocalizations.of(context).deleteConversationTitle,
@@ -348,7 +320,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
color: StreamChatTheme.of(context).colorTheme.accentError, color: StreamChatTheme.of(context).colorTheme.accentError,
), ),
); );
var channel = StreamChannel.of(context).channel; final channel = streamChannel.channel;
if (res == true) { if (res == true) {
await channel.delete().then((value) { await channel.delete().then((value) {
Navigator.pop(context); Navigator.pop(context);
@@ -358,7 +330,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
} }
Widget _buildConnectedTitleState() { Widget _buildConnectedTitleState() {
var alternativeWidget; late Text alternativeWidget;
final otherMember = widget.user; final otherMember = widget.user;
@@ -390,22 +362,22 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
if (widget.user!.online) if (widget.user!.online)
Material( Material(
type: MaterialType.circle, type: MaterialType.circle,
color: StreamChatTheme.of(context).colorTheme.barsBg,
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(horizontal: 8.0),
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
width: 24, width: 24,
height: 12, height: 12,
), ),
child: Material( child: Material(
shape: CircleBorder(), shape: const CircleBorder(),
color: StreamChatTheme.of(context).colorTheme.accentInfo, color: StreamChatTheme.of(context).colorTheme.accentInfo,
), ),
), ),
color: StreamChatTheme.of(context).colorTheme.barsBg,
), ),
alternativeWidget, alternativeWidget,
if (widget.user!.online) if (widget.user!.online)
SizedBox( const SizedBox(
width: 24.0, width: 24.0,
), ),
], ],
@@ -417,7 +389,7 @@ class _SharedGroupsScreen extends StatefulWidget {
final User? mainUser; final User? mainUser;
final User? otherUser; final User? otherUser;
_SharedGroupsScreen(this.mainUser, this.otherUser); const _SharedGroupsScreen(this.mainUser, this.otherUser);
@override @override
__SharedGroupsScreenState createState() => __SharedGroupsScreenState(); __SharedGroupsScreenState createState() => __SharedGroupsScreenState();
@@ -439,7 +411,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, color: StreamChatTheme.of(context).colorTheme.textHighEmphasis,
fontSize: 16.0), fontSize: 16.0),
), ),
leading: StreamBackButton(), leading: const StreamBackButton(),
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
), ),
body: StreamBuilder<List<Channel>>( body: StreamBuilder<List<Channel>>(
@@ -451,7 +423,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
), ),
builder: (context, snapshot) { builder: (context, snapshot) {
if (!snapshot.hasData) { if (!snapshot.hasData) {
return Center( return const Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
); );
} }
@@ -465,7 +437,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
size: 136.0, size: 136.0,
color: StreamChatTheme.of(context).colorTheme.disabled, color: StreamChatTheme.of(context).colorTheme.disabled,
), ),
SizedBox(height: 16.0), const SizedBox(height: 16.0),
Text( Text(
AppLocalizations.of(context).noSharedGroups, AppLocalizations.of(context).noSharedGroups,
style: TextStyle( style: TextStyle(
@@ -475,7 +447,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
.textHighEmphasis, .textHighEmphasis,
), ),
), ),
SizedBox(height: 8.0), const SizedBox(height: 8.0),
Text( Text(
AppLocalizations.of(context).groupSharedWithUserAppearHere, AppLocalizations.of(context).groupSharedWithUserAppearHere,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@@ -515,84 +487,86 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
} }
Widget _buildListTile(Channel channel) { Widget _buildListTile(Channel channel) {
var extraData = channel.extraData; final extraData = channel.extraData;
var members = channel.state!.members; final members = channel.state!.members;
var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); const textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold);
return Container( return SizedBox(
height: 64.0, height: 64.0,
child: LayoutBuilder(builder: (context, constraints) { child: LayoutBuilder(
String? title; builder: (context, constraints) {
if (extraData['name'] == null) { String? title;
final otherMembers = members.where((member) => if (extraData['name'] == null) {
member.userId != StreamChat.of(context).currentUser!.id); final otherMembers = members.where((member) =>
if (otherMembers.isNotEmpty) { member.userId != StreamChat.of(context).currentUser!.id);
final maxWidth = constraints.maxWidth; if (otherMembers.isNotEmpty) {
final maxChars = maxWidth / textStyle.fontSize!; final maxWidth = constraints.maxWidth;
var currentChars = 0; final maxChars = maxWidth / textStyle.fontSize!;
final currentMembers = <Member>[]; var currentChars = 0;
otherMembers.forEach((element) { final currentMembers = <Member>[];
final newLength = currentChars + element.user!.name.length; for (var element in otherMembers) {
if (newLength < maxChars) { final newLength = currentChars + element.user!.name.length;
currentChars = newLength; if (newLength < maxChars) {
currentMembers.add(element); currentChars = newLength;
currentMembers.add(element);
}
} }
});
final exceedingMembers = final exceedingMembers =
otherMembers.length - currentMembers.length; otherMembers.length - currentMembers.length;
title = title =
'${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}';
} else {
title = 'No title';
}
} else { } else {
title = 'No title'; title = extraData['name'] as String;
} }
} else {
title = extraData['name'] as String;
}
return Column( return Column(
children: [ children: [
Expanded( Expanded(
child: Row( child: Row(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: StreamChannelAvatar( child: StreamChannelAvatar(
channel: channel, channel: channel,
constraints: constraints: const BoxConstraints(
BoxConstraints(maxWidth: 40.0, maxHeight: 40.0), maxWidth: 40.0, maxHeight: 40.0),
),
), ),
), Expanded(
Expanded( child: Text(
title,
style: textStyle,
)),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
title, '${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}',
style: textStyle, style: TextStyle(
)), color: StreamChatTheme.of(context)
Padding( .colorTheme
padding: const EdgeInsets.all(8.0), .textHighEmphasis
child: Text( .withOpacity(0.5)),
'${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}', ),
style: TextStyle( )
color: StreamChatTheme.of(context) ],
.colorTheme ),
.textHighEmphasis
.withOpacity(0.5)),
),
)
],
), ),
), Container(
Container( height: 1.0,
height: 1.0, color: StreamChatTheme.of(context)
color: StreamChatTheme.of(context) .colorTheme
.colorTheme .textHighEmphasis
.textHighEmphasis .withOpacity(.08),
.withOpacity(.08), ),
), ],
], );
); },
}), ),
); );
} }
} }
@@ -16,6 +16,8 @@ const kStreamUserId = 'STREAM_USER_ID';
const kStreamToken = 'STREAM_TOKEN'; const kStreamToken = 'STREAM_TOKEN';
class ChooseUserPage extends StatelessWidget { class ChooseUserPage extends StatelessWidget {
const ChooseUserPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final users = defaultUsers; final users = defaultUsers;
@@ -85,7 +87,7 @@ class ChooseUserPage extends StatelessWidget {
), ),
height: 100, height: 100,
width: 100, width: 100,
child: Center( child: const Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
), ),
@@ -97,13 +99,15 @@ class ChooseUserPage extends StatelessWidget {
logLevel: Level.INFO, logLevel: Level.INFO,
)..chatPersistenceClient = chatPersistentClient; )..chatPersistenceClient = chatPersistentClient;
final navigator = Navigator.of(context);
await client.connectUser( await client.connectUser(
user, user,
token, token,
); );
if (!kIsWeb) { if (!kIsWeb) {
final secureStorage = FlutterSecureStorage(); const secureStorage = FlutterSecureStorage();
secureStorage.write( secureStorage.write(
key: kStreamApiKey, key: kStreamApiKey,
value: kDefaultStreamApiKey, value: kDefaultStreamApiKey,
@@ -117,8 +121,7 @@ class ChooseUserPage extends StatelessWidget {
value: token, value: token,
); );
} }
Navigator.pushNamedAndRemoveUntil( navigator.pushNamedAndRemoveUntil(
context,
Routes.HOME, Routes.HOME,
ModalRoute.withName(Routes.HOME), ModalRoute.withName(Routes.HOME),
arguments: HomePageArgs(client), arguments: HomePageArgs(client),
@@ -127,7 +130,7 @@ class ChooseUserPage extends StatelessWidget {
leading: StreamUserAvatar( leading: StreamUserAvatar(
user: user, user: user,
constraints: BoxConstraints.tight( constraints: BoxConstraints.tight(
Size.fromRadius(20), const Size.fromRadius(20),
), ),
), ),
title: Text( title: Text(
@@ -158,13 +161,13 @@ class ChooseUserPage extends StatelessWidget {
Navigator.pushNamed(context, Routes.ADVANCED_OPTIONS); Navigator.pushNamed(context, Routes.ADVANCED_OPTIONS);
}, },
leading: CircleAvatar( leading: CircleAvatar(
backgroundColor:
StreamChatTheme.of(context).colorTheme.borders,
child: StreamSvgIcon.settings( child: StreamSvgIcon.settings(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
.textHighEmphasis, .textHighEmphasis,
), ),
backgroundColor:
StreamChatTheme.of(context).colorTheme.borders,
), ),
title: Text( title: Text(
AppLocalizations.of(context).advancedOptions, AppLocalizations.of(context).advancedOptions,
@@ -193,7 +196,7 @@ class ChooseUserPage extends StatelessWidget {
), ),
), ),
), ),
StreamVersion(), const StreamVersion(),
], ],
), ),
), ),
@@ -14,7 +14,7 @@ class GroupChatDetailsScreen extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_GroupChatDetailsScreenState createState() => _GroupChatDetailsScreenState(); State<GroupChatDetailsScreen> createState() => _GroupChatDetailsScreenState();
} }
class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> { class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
@@ -73,7 +73,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
), ),
centerTitle: true, centerTitle: true,
bottom: PreferredSize( bottom: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight), preferredSize: const Size.fromHeight(kToolbarHeight),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 16), padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 16),
child: Row( child: Row(
@@ -87,7 +87,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
.textLowEmphasis, .textLowEmphasis,
), ),
), ),
SizedBox(width: 16), const SizedBox(width: 16),
Expanded( Expanded(
child: TextField( child: TextField(
controller: _groupNameController, controller: _groupNameController,
@@ -130,8 +130,9 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
try { try {
final groupName = _groupNameController!.text; final groupName = _groupNameController!.text;
final client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
final channel = client.channel('messaging', final channel = client.channel('messaging',
id: Uuid().v4(), id: const Uuid().v4(),
extraData: { extraData: {
'members': [ 'members': [
client.state.currentUser!.id, client.state.currentUser!.id,
@@ -140,8 +141,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
'name': groupName, 'name': groupName,
}); });
await channel.watch(); await channel.watch();
Navigator.pushNamedAndRemoveUntil( navigator.pushNamedAndRemoveUntil(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
ModalRoute.withName(Routes.CHANNEL_LIST_PAGE), ModalRoute.withName(Routes.CHANNEL_LIST_PAGE),
arguments: ChannelPageArgs(channel: channel), arguments: ChannelPageArgs(channel: channel),
@@ -223,14 +223,15 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
key: ObjectKey(user), key: ObjectKey(user),
leading: StreamUserAvatar( leading: StreamUserAvatar(
user: user, user: user,
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
width: 40, width: 40,
height: 40, height: 40,
), ),
), ),
title: Text( title: Text(
user.name, user.name,
style: TextStyle(fontWeight: FontWeight.bold), style:
const TextStyle(fontWeight: FontWeight.bold),
), ),
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(
horizontal: 12, horizontal: 12,
@@ -273,7 +274,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
useRootNavigator: false, useRootNavigator: false,
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
context: context, context: context,
shape: RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0), topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0), topRight: Radius.circular(16.0),
@@ -282,25 +283,25 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox( const SizedBox(
height: 26.0, height: 26.0,
), ),
StreamSvgIcon.error( StreamSvgIcon.error(
color: StreamChatTheme.of(context).colorTheme.accentError, color: StreamChatTheme.of(context).colorTheme.accentError,
size: 24.0, size: 24.0,
), ),
SizedBox( const SizedBox(
height: 26.0, height: 26.0,
), ),
Text( Text(
AppLocalizations.of(context).somethingWentWrongErrorMessage, AppLocalizations.of(context).somethingWentWrongErrorMessage,
style: StreamChatTheme.of(context).textTheme.headlineBold, style: StreamChatTheme.of(context).textTheme.headlineBold,
), ),
SizedBox( const SizedBox(
height: 7.0, height: 7.0,
), ),
Text(AppLocalizations.of(context).operationCouldNotBeCompleted), Text(AppLocalizations.of(context).operationCouldNotBeCompleted),
SizedBox( const SizedBox(
height: 36.0, height: 36.0,
), ),
Container( Container(
@@ -21,7 +21,7 @@ class GroupInfoScreen extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_GroupInfoScreenState createState() => _GroupInfoScreenState(); State<GroupInfoScreen> createState() => _GroupInfoScreenState();
} }
class _GroupInfoScreenState extends State<GroupInfoScreen> { class _GroupInfoScreenState extends State<GroupInfoScreen> {
@@ -101,7 +101,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
], ],
), ),
sort: [ sort: [
SortOption( const SortOption(
'name', 'name',
direction: 1, direction: 1,
), ),
@@ -124,7 +124,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
if (!snapshot.hasData) { if (!snapshot.hasData) {
return Container( return Container(
color: StreamChatTheme.of(context).colorTheme.disabled, color: StreamChatTheme.of(context).colorTheme.disabled,
child: Center(child: CircularProgressIndicator()), child: const Center(child: CircularProgressIndicator()),
); );
} }
@@ -134,7 +134,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
elevation: 1.0, elevation: 1.0,
toolbarHeight: 56.0, toolbarHeight: 56.0,
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
leading: StreamBackButton(), leading: const StreamBackButton(),
title: Column( title: Column(
children: [ children: [
StreamBuilder<ChannelState>( StreamBuilder<ChannelState>(
@@ -171,7 +171,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
); );
}), }),
SizedBox( const SizedBox(
height: 3.0, height: 3.0,
), ),
Text( Text(
@@ -242,11 +242,12 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
children: [ children: [
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemCount: groupMembersLength, itemCount: groupMembersLength,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final member = groupMembers[index]; final member = groupMembers[index];
return Material( return Material(
color: StreamChatTheme.of(context).colorTheme.appBg,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
final userMember = groupMembers.firstWhereOrNull( final userMember = groupMembers.firstWhereOrNull(
@@ -255,7 +256,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
_showUserInfoModal( _showUserInfoModal(
member.user, userMember?.userId == channel.createdBy?.id); member.user, userMember?.userId == channel.createdBy?.id);
}, },
child: Container( child: SizedBox(
height: 65.0, height: 65.0,
child: Column( child: Column(
children: [ children: [
@@ -268,7 +269,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
child: StreamUserAvatar( child: StreamUserAvatar(
user: member.user!, user: member.user!,
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 40.0, height: 40.0,
width: 40.0, width: 40.0,
), ),
@@ -281,9 +282,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
children: [ children: [
Text( Text(
member.user!.name, member.user!.name,
style: TextStyle(fontWeight: FontWeight.bold), style: const TextStyle(
fontWeight: FontWeight.bold),
), ),
SizedBox( const SizedBox(
height: 1.0, height: 1.0,
), ),
Text( Text(
@@ -320,7 +322,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
), ),
), ),
color: StreamChatTheme.of(context).colorTheme.appBg,
); );
}, },
), ),
@@ -333,7 +334,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
}, },
child: Material( child: Material(
color: StreamChatTheme.of(context).colorTheme.appBg, color: StreamChatTheme.of(context).colorTheme.appBg,
child: Container( child: SizedBox(
height: 65.0, height: 65.0,
child: Column( child: Column(
children: [ children: [
@@ -401,7 +402,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
.withOpacity(0.5)), .withOpacity(0.5)),
), ),
), ),
SizedBox( const SizedBox(
width: 7.0, width: 7.0,
), ),
Expanded( Expanded(
@@ -422,7 +423,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
.colorTheme .colorTheme
.textHighEmphasis .textHighEmphasis
.withOpacity(0.5))), .withOpacity(0.5))),
style: TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
height: 0.82, height: 0.82,
), ),
@@ -478,18 +479,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
Widget _buildOptionListTiles() { Widget _buildOptionListTiles() {
return Column( return Column(
children: [ children: [
// OptionListTile(
// title: 'Notifications',
// leading: StreamSvgIcon.Icon_notification(
// size: 24.0,
// color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5),
// ),
// trailing: CupertinoSwitch(
// value: true,
// onChanged: (val) {},
// ),
// onTap: () {},
// ),
if (channel.ownCapabilities.contains(PermissionType.muteChannel)) if (channel.ownCapabilities.contains(PermissionType.muteChannel))
StreamBuilder<bool>( StreamBuilder<bool>(
stream: channel.isMutedStream, stream: channel.isMutedStream,
@@ -513,7 +502,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
), ),
trailing: snapshot.data == null trailing: snapshot.data == null
? CircularProgressIndicator() ? const CircularProgressIndicator()
: ValueListenableBuilder<bool?>( : ValueListenableBuilder<bool?>(
valueListenable: mutedBool, valueListenable: mutedBool,
builder: (context, value, _) { builder: (context, value, _) {
@@ -558,7 +547,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
MaterialPageRoute( MaterialPageRoute(
builder: (context) => StreamChannel( builder: (context) => StreamChannel(
channel: channel, channel: channel,
child: PinnedMessagesScreen(), child: const PinnedMessagesScreen(),
), ),
), ),
); );
@@ -649,11 +638,14 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
.withOpacity(0.5), .withOpacity(0.5),
), ),
), ),
trailing: Container( trailing: const SizedBox(
height: 24.0, height: 24.0,
width: 24.0, width: 24.0,
), ),
onTap: () async { onTap: () async {
final streamChannel = StreamChannel.of(context);
final streamChat = StreamChat.of(context);
final navigator = Navigator.of(context);
final res = await showConfirmationBottomSheet( final res = await showConfirmationBottomSheet(
context, context,
title: AppLocalizations.of(context).leaveConversation, title: AppLocalizations.of(context).leaveConversation,
@@ -666,10 +658,9 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
); );
if (res == true) { if (res == true) {
final channel = StreamChannel.of(context).channel; final channel = streamChannel.channel;
await channel await channel.removeMembers([streamChat.currentUser!.id]);
.removeMembers([StreamChat.of(context).currentUser!.id]); navigator.pop();
Navigator.pop(context);
} }
}, },
), ),
@@ -684,9 +675,9 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
barrierColor: StreamChatTheme.of(context).colorTheme.overlay, barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) { builder: (context) {
return Padding( return Padding(
padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0), padding: const EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0),
child: Material( child: Material(
borderRadius: BorderRadius.only( borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16.0), topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0), topRight: Radius.circular(16.0),
), ),
@@ -703,16 +694,17 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
controller: userListController, controller: userListController,
onUserTap: (user) async { onUserTap: (user) async {
_searchController!.clear(); _searchController!.clear();
final navigator = Navigator.of(context);
await channel.addMembers([user.id]); await channel.addMembers([user.id]);
Navigator.pop(context); navigator.pop();
setState(() {}); setState(() {});
}, },
emptyBuilder: (_) { emptyBuilder: (_) {
return LayoutBuilder( return LayoutBuilder(
builder: (context, viewportConstraints) { builder: (context, viewportConstraints) {
return SingleChildScrollView( return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight, minHeight: viewportConstraints.maxHeight,
@@ -760,7 +752,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( Expanded(
child: Container( child: SizedBox(
height: 36, height: 36,
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
@@ -771,7 +763,8 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
hintStyle: theme.textTheme.body.copyWith( hintStyle: theme.textTheme.body.copyWith(
color: theme.colorTheme.textLowEmphasis, color: theme.colorTheme.textLowEmphasis,
), ),
prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), prefixIconConstraints:
BoxConstraints.tight(const Size(40, 24)),
prefixIcon: StreamSvgIcon.search( prefixIcon: StreamSvgIcon.search(
color: theme.colorTheme.textHighEmphasis, color: theme.colorTheme.textHighEmphasis,
size: 24, size: 24,
@@ -792,12 +785,12 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
), ),
), ),
SizedBox(width: 16.0), const SizedBox(width: 16.0),
IconButton( IconButton(
icon: StreamSvgIcon.closeSmall( icon: StreamSvgIcon.closeSmall(
color: theme.colorTheme.textLowEmphasis, color: theme.colorTheme.textLowEmphasis,
), ),
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 24, height: 24,
width: 24, width: 24,
), ),
@@ -829,19 +822,19 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox( const SizedBox(
height: 24.0, height: 24.0,
), ),
Center( Center(
child: Text( child: Text(
user!.name, user!.name,
style: TextStyle( style: const TextStyle(
fontSize: 16.0, fontSize: 16.0,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
), ),
SizedBox( const SizedBox(
height: 5.0, height: 5.0,
), ),
_buildConnectedTitleState(user)!, _buildConnectedTitleState(user)!,
@@ -850,7 +843,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: StreamUserAvatar( child: StreamUserAvatar(
user: user, user: user,
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 64.0, height: 64.0,
width: 64.0, width: 64.0,
), ),
@@ -869,9 +862,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
AppLocalizations.of(context).viewInfo, AppLocalizations.of(context).viewInfo,
() async { () async {
var client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
var c = client.channel('messaging', extraData: { final c = client.channel('messaging', extraData: {
'members': [ 'members': [
user.id, user.id,
StreamChat.of(context).currentUser!.id, StreamChat.of(context).currentUser!.id,
@@ -880,8 +874,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
await c.watch(); await c.watch();
await Navigator.push( await navigator.push(
context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => StreamChannel( builder: (context) => StreamChannel(
channel: c, channel: c,
@@ -905,9 +898,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
AppLocalizations.of(context).message, AppLocalizations.of(context).message,
() async { () async {
var client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
var c = client.channel('messaging', extraData: { final c = client.channel('messaging', extraData: {
'members': [ 'members': [
user.id, user.id,
StreamChat.of(context).currentUser!.id, StreamChat.of(context).currentUser!.id,
@@ -916,12 +910,11 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
await c.watch(); await c.watch();
await Navigator.push( await navigator.push(
context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => StreamChannel( builder: (context) => StreamChannel(
channel: c, channel: c,
child: ChannelPage(), child: const ChannelPage(),
), ),
), ),
); );
@@ -939,6 +932,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
size: 24.0, size: 24.0,
), ),
AppLocalizations.of(context).removeFromGroup, () async { AppLocalizations.of(context).removeFromGroup, () async {
final navigator = Navigator.of(context);
final res = await showConfirmationBottomSheet( final res = await showConfirmationBottomSheet(
context, context,
title: AppLocalizations.of(context).removeMember, title: AppLocalizations.of(context).removeMember,
@@ -953,7 +947,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
if (res == true) { if (res == true) {
await channel.removeMembers([user.id]); await channel.removeMembers([user.id]);
} }
Navigator.pop(context); navigator.pop();
}, },
color: color:
StreamChatTheme.of(context).colorTheme.accentError), StreamChatTheme.of(context).colorTheme.accentError),
@@ -974,7 +968,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
); );
}, },
shape: RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0), topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0), topRight: Radius.circular(16.0),
@@ -984,7 +978,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
} }
Widget? _buildConnectedTitleState(User? user) { Widget? _buildConnectedTitleState(User? user) {
var alternativeWidget; late Text alternativeWidget;
final otherMember = user; final otherMember = user;
@@ -1028,7 +1022,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
height: 1.0, height: 1.0,
color: StreamChatTheme.of(context).colorTheme.disabled, color: StreamChatTheme.of(context).colorTheme.disabled,
), ),
Container( SizedBox(
height: 64.0, height: 64.0,
child: Row( child: Row(
children: [ children: [
@@ -1068,13 +1062,13 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
final maxChars = maxWidth / maxFontSize!; final maxChars = maxWidth / maxFontSize!;
var currentChars = 0; var currentChars = 0;
final currentMembers = <Member>[]; final currentMembers = <Member>[];
otherMembers.forEach((element) { for (var element in otherMembers) {
final newLength = currentChars + element.user!.name.length; final newLength = currentChars + element.user!.name.length;
if (newLength < maxChars) { if (newLength < maxChars) {
currentChars = newLength; currentChars = newLength;
currentMembers.add(element); currentMembers.add(element);
} }
}); }
final exceedingMembers = otherMembers.length - currentMembers.length; final exceedingMembers = otherMembers.length - currentMembers.length;
title = title =
@@ -72,7 +72,7 @@ class HomePageArgs {
} }
class HomePage extends StatefulWidget { class HomePage extends StatefulWidget {
HomePage({ const HomePage({
Key? key, Key? key,
required this.chatClient, required this.chatClient,
}) : super(key: key); }) : super(key: key);
@@ -80,7 +80,7 @@ class HomePage extends StatefulWidget {
final StreamChatClient chatClient; final StreamChatClient chatClient;
@override @override
_HomePageState createState() => _HomePageState(); State<HomePage> createState() => _HomePageState();
} }
class _HomePageState extends State<HomePage> { class _HomePageState extends State<HomePage> {
@@ -9,8 +9,10 @@ import '../widgets/chips_input_text_field.dart';
import '../routes/routes.dart'; import '../routes/routes.dart';
class NewChatScreen extends StatefulWidget { class NewChatScreen extends StatefulWidget {
const NewChatScreen({super.key});
@override @override
_NewChatScreenState createState() => _NewChatScreenState(); State<NewChatScreen> createState() => _NewChatScreenState();
} }
class _NewChatScreenState extends State<NewChatScreen> { class _NewChatScreenState extends State<NewChatScreen> {
@@ -26,7 +28,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
Filter.notEqual('id', StreamChat.of(context).currentUser!.id), Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
]), ]),
sort: [ sort: [
SortOption( const SortOption(
'name', 'name',
direction: 1, direction: 1,
), ),
@@ -54,11 +56,12 @@ class _NewChatScreenState extends State<NewChatScreen> {
void _userNameListener() { void _userNameListener() {
if (_debounce?.isActive ?? false) _debounce!.cancel(); if (_debounce?.isActive ?? false) _debounce!.cancel();
_debounce = Timer(const Duration(milliseconds: 350), () { _debounce = Timer(const Duration(milliseconds: 350), () {
if (mounted) if (mounted) {
setState(() { setState(() {
_userNameQuery = _controller.text; _userNameQuery = _controller.text;
_isSearchActive = _userNameQuery.isNotEmpty; _isSearchActive = _userNameQuery.isNotEmpty;
}); });
}
userListController.filter = Filter.and([ userListController.filter = Filter.and([
if (_userNameQuery.isNotEmpty) if (_userNameQuery.isNotEmpty)
Filter.autoComplete('name', _userNameQuery), Filter.autoComplete('name', _userNameQuery),
@@ -97,13 +100,13 @@ class _NewChatScreenState extends State<NewChatScreen> {
'distinct': true, 'distinct': true,
}), }),
messageLimit: 0, messageLimit: 0,
paginationParams: PaginationParams( paginationParams: const PaginationParams(
limit: 1, limit: 1,
), ),
); );
final _channelExisted = res.length == 1; final channelExisted = res.length == 1;
if (_channelExisted) { if (channelExisted) {
channel = res.first; channel = res.first;
await channel!.watch(); await channel!.watch();
} else { } else {
@@ -224,7 +227,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
child: StreamUserAvatar( child: StreamUserAvatar(
showOnlineStatus: false, showOnlineStatus: false,
user: user, user: user,
constraints: BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 24, height: 24,
width: 24, width: 24,
), ),
@@ -243,37 +246,35 @@ class _NewChatScreenState extends State<NewChatScreen> {
}, },
), ),
if (!_isSearchActive && !_selectedUsers.isNotEmpty) if (!_isSearchActive && !_selectedUsers.isNotEmpty)
Container( InkWell(
child: InkWell( onTap: () {
onTap: () { Navigator.pushNamed(
Navigator.pushNamed( context,
context, Routes.NEW_GROUP_CHAT,
Routes.NEW_GROUP_CHAT, );
); },
}, child: Padding(
child: Padding( padding: const EdgeInsets.symmetric(vertical: 8),
padding: const EdgeInsets.symmetric(vertical: 8), child: Row(
child: Row( children: [
children: [ StreamNeumorphicButton(
StreamNeumorphicButton( child: Center(
child: Center( child: StreamSvgIcon.contacts(
child: StreamSvgIcon.contacts( color: StreamChatTheme.of(context)
color: StreamChatTheme.of(context) .colorTheme
.colorTheme .accentPrimary,
.accentPrimary, size: 24,
size: 24,
),
), ),
), ),
SizedBox(width: 8), ),
Text( const SizedBox(width: 8),
AppLocalizations.of(context).createAGroup, Text(
style: StreamChatTheme.of(context) AppLocalizations.of(context).createAGroup,
.textTheme style: StreamChatTheme.of(context)
.bodyBold, .textTheme
), .bodyBold,
], ),
), ],
), ),
), ),
), ),
@@ -337,7 +338,8 @@ class _NewChatScreenState extends State<NewChatScreen> {
return LayoutBuilder( return LayoutBuilder(
builder: (context, viewportConstraints) { builder: (context, viewportConstraints) {
return SingleChildScrollView( return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(), physics:
const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: minHeight:
@@ -382,7 +384,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
future: channel!.initialized, future: channel!.initialized,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.data == true) { if (snapshot.data == true) {
return StreamMessageListView(); return const StreamMessageListView();
} }
return Center( return Center(
@@ -8,8 +8,10 @@ import '../routes/routes.dart';
import '../widgets/search_text_field.dart'; import '../widgets/search_text_field.dart';
class NewGroupChatScreen extends StatefulWidget { class NewGroupChatScreen extends StatefulWidget {
const NewGroupChatScreen({super.key});
@override @override
_NewGroupChatScreenState createState() => _NewGroupChatScreenState(); State<NewGroupChatScreen> createState() => _NewGroupChatScreenState();
} }
class _NewGroupChatScreenState extends State<NewGroupChatScreen> { class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
@@ -26,7 +28,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
late final userListController = StreamUserListController( late final userListController = StreamUserListController(
client: StreamChat.of(context).client, client: StreamChat.of(context).client,
sort: [ sort: [
SortOption( const SortOption(
'name', 'name',
direction: 1, direction: 1,
), ),
@@ -144,13 +146,14 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
), ),
if (_selectedUsers.isNotEmpty) if (_selectedUsers.isNotEmpty)
SliverToBoxAdapter( SliverToBoxAdapter(
child: Container( child: SizedBox(
height: 104, height: 104,
child: ListView.separated( child: ListView.separated(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: _selectedUsers.length, itemCount: _selectedUsers.length,
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
separatorBuilder: (_, __) => SizedBox(width: 16), separatorBuilder: (_, __) =>
const SizedBox(width: 16),
itemBuilder: (_, index) { itemBuilder: (_, index) {
final user = _selectedUsers.elementAt(index); final user = _selectedUsers.elementAt(index);
return Column( return Column(
@@ -159,11 +162,12 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
children: [ children: [
StreamUserAvatar( StreamUserAvatar(
onlineIndicatorAlignment: onlineIndicatorAlignment:
Alignment(0.9, 0.9), const Alignment(0.9, 0.9),
user: user, user: user,
showOnlineStatus: true, showOnlineStatus: true,
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
constraints: BoxConstraints.tightFor( constraints:
const BoxConstraints.tightFor(
height: 64, height: 64,
width: 64, width: 64,
), ),
@@ -201,10 +205,10 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
) )
], ],
), ),
SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
user.name.split(' ')[0], user.name.split(' ')[0],
style: TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12, fontSize: 12,
), ),
@@ -218,7 +222,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
SliverPersistentHeader( SliverPersistentHeader(
pinned: true, pinned: true,
delegate: _HeaderDelegate( delegate: _HeaderDelegate(
height: 30, height: 32,
child: Container( child: Container(
width: double.maxFinite, width: double.maxFinite,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -232,7 +236,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
), ),
child: Text( child: Text(
_isSearchActive _isSearchActive
? '${AppLocalizations.of(context).matchesFor} \"$_userNameQuery\"' ? '${AppLocalizations.of(context).matchesFor} "$_userNameQuery"'
: AppLocalizations.of(context).onThePlatorm, : AppLocalizations.of(context).onThePlatorm,
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
@@ -271,7 +275,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
return LayoutBuilder( return LayoutBuilder(
builder: (context, viewportConstraints) { builder: (context, viewportConstraints) {
return SingleChildScrollView( return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight, minHeight: viewportConstraints.maxHeight,
@@ -6,6 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'channel_page.dart'; import 'channel_page.dart';
class PinnedMessagesScreen extends StatefulWidget { class PinnedMessagesScreen extends StatefulWidget {
const PinnedMessagesScreen({super.key});
@override @override
State<PinnedMessagesScreen> createState() => _PinnedMessagesScreenState(); State<PinnedMessagesScreen> createState() => _PinnedMessagesScreenState();
} }
@@ -22,7 +24,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
true, true,
), ),
sort: [ sort: [
SortOption( const SortOption(
'created_at', 'created_at',
direction: SortOption.ASC, direction: SortOption.ASC,
), ),
@@ -44,7 +46,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
fontSize: 16.0, fontSize: 16.0,
), ),
), ),
leading: StreamBackButton(), leading: const StreamBackButton(),
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
), ),
body: StreamMessageSearchListView( body: StreamMessageSearchListView(
@@ -58,7 +60,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
size: 136.0, size: 136.0,
color: StreamChatTheme.of(context).colorTheme.disabled, color: StreamChatTheme.of(context).colorTheme.disabled,
), ),
SizedBox(height: 16.0), const SizedBox(height: 16.0),
Text( Text(
AppLocalizations.of(context).noPinnedItems, AppLocalizations.of(context).noPinnedItems,
style: TextStyle( style: TextStyle(
@@ -68,7 +70,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
SizedBox(height: 8.0), const SizedBox(height: 8.0),
RichText( RichText(
textAlign: TextAlign.center, textAlign: TextAlign.center,
text: TextSpan(children: [ text: TextSpan(children: [
@@ -101,6 +103,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
}, },
onMessageTap: (messageResponse) async { onMessageTap: (messageResponse) async {
final client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
final message = messageResponse.message; final message = messageResponse.message;
final channel = client.channel( final channel = client.channel(
messageResponse.channel!.type, messageResponse.channel!.type,
@@ -109,8 +112,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
if (channel.state == null) { if (channel.state == null) {
await channel.watch(); await channel.watch();
} }
Navigator.pushNamed( navigator.pushNamed(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs( arguments: ChannelPageArgs(
channel: channel, channel: channel,
@@ -12,7 +12,7 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
_scaleAnimationController = AnimationController( _scaleAnimationController = AnimationController(
vsync: this, vsync: this,
value: 0, value: 0,
duration: Duration( duration: const Duration(
milliseconds: 500, milliseconds: 500,
), ),
); );
@@ -26,7 +26,7 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
_animationController = AnimationController( _animationController = AnimationController(
vsync: this, vsync: this,
duration: Duration( duration: const Duration(
milliseconds: 1000, milliseconds: 1000,
), ),
); );
@@ -38,14 +38,14 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
curve: Curves.easeInOut, curve: Curves.easeInOut,
)); ));
colorAnimation = ColorTween( colorAnimation = ColorTween(
begin: Color(0xff005FFF), begin: const Color(0xff005FFF),
end: Color(0xff005FFF), end: const Color(0xff005FFF),
).animate(CurvedAnimation( ).animate(CurvedAnimation(
parent: _animationController, parent: _animationController,
curve: Curves.easeInOut, curve: Curves.easeInOut,
)); ));
colorAnimation = ColorTween( colorAnimation = ColorTween(
begin: Color(0xff005FFF), begin: const Color(0xff005FFF),
end: Colors.transparent, end: Colors.transparent,
).animate(CurvedAnimation( ).animate(CurvedAnimation(
parent: _animationController, parent: _animationController,
@@ -73,14 +73,14 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
builder: (context, snapshot) { builder: (context, snapshot) {
return Container( return Container(
alignment: Alignment.center, alignment: Alignment.center,
constraints: BoxConstraints.expand(), constraints: const BoxConstraints.expand(),
color: colorAnimation.value, color: colorAnimation.value,
child: !_animationController.isAnimating child: !_animationController.isAnimating
? Lottie.asset( ? Lottie.asset(
'assets/floating_boat.json', 'assets/floating_boat.json',
alignment: Alignment.center, alignment: Alignment.center,
) )
: SizedBox(), : const SizedBox(),
); );
}), }),
); );
@@ -6,7 +6,7 @@ class ThreadPage extends StatefulWidget {
final int? initialScrollIndex; final int? initialScrollIndex;
final double? initialAlignment; final double? initialAlignment;
ThreadPage({ const ThreadPage({
Key? key, Key? key,
required this.parent, required this.parent,
this.initialScrollIndex, this.initialScrollIndex,
@@ -14,11 +14,11 @@ class ThreadPage extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
_ThreadPageState createState() => _ThreadPageState(); State<ThreadPage> createState() => _ThreadPageState();
} }
class _ThreadPageState extends State<ThreadPage> { class _ThreadPageState extends State<ThreadPage> {
FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
late StreamMessageInputController _messageInputController; late StreamMessageInputController _messageInputController;
@override @override
@@ -82,8 +82,8 @@ class _ThreadPageState extends State<ThreadPage> {
} }
bool defaultFilter(Message m) { bool defaultFilter(Message m) {
var _currentUser = StreamChat.of(context).currentUser; final currentUser = StreamChat.of(context).currentUser;
final isMyMessage = m.user?.id == _currentUser?.id; final isMyMessage = m.user?.id == currentUser?.id;
final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true; final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true;
if (isDeletedOrShadowed && !isMyMessage) return false; if (isDeletedOrShadowed && !isMyMessage) return false;
return true; return true;
@@ -6,6 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'channel_page.dart'; import 'channel_page.dart';
class UserMentionsPage extends StatefulWidget { class UserMentionsPage extends StatefulWidget {
const UserMentionsPage({super.key});
@override @override
State<UserMentionsPage> createState() => _UserMentionsPageState(); State<UserMentionsPage> createState() => _UserMentionsPageState();
} }
@@ -20,7 +22,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
value: StreamChat.of(context).currentUser!.id, value: StreamChat.of(context).currentUser!.id,
), ),
sort: [ sort: [
SortOption( const SortOption(
'created_at', 'created_at',
direction: SortOption.ASC, direction: SortOption.ASC,
), ),
@@ -35,7 +37,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
return LayoutBuilder( return LayoutBuilder(
builder: (context, viewportConstraints) { builder: (context, viewportConstraints) {
return SingleChildScrollView( return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight, minHeight: viewportConstraints.maxHeight,
@@ -70,6 +72,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
}, },
onMessageTap: (messageResponse) async { onMessageTap: (messageResponse) async {
final client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
final message = messageResponse.message; final message = messageResponse.message;
final channel = client.channel( final channel = client.channel(
messageResponse.channel!.type, messageResponse.channel!.type,
@@ -78,8 +81,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
if (channel.state == null) { if (channel.state == null) {
await channel.watch(); await channel.watch();
} }
Navigator.pushNamed( navigator.pushNamed(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs( arguments: ChannelPageArgs(
channel: channel, channel: channel,
@@ -25,7 +25,7 @@ class AppRoutes {
return MaterialPageRoute( return MaterialPageRoute(
settings: RouteSettings(arguments: args, name: Routes.APP), settings: RouteSettings(arguments: args, name: Routes.APP),
builder: (_) { builder: (_) {
return MyApp(); return const StreamChatSampleApp();
}); });
case Routes.HOME: case Routes.HOME:
return MaterialPageRoute( return MaterialPageRoute(
@@ -40,13 +40,13 @@ class AppRoutes {
return MaterialPageRoute( return MaterialPageRoute(
settings: RouteSettings(arguments: args, name: Routes.CHOOSE_USER), settings: RouteSettings(arguments: args, name: Routes.CHOOSE_USER),
builder: (_) { builder: (_) {
return ChooseUserPage(); return const ChooseUserPage();
}); });
case Routes.ADVANCED_OPTIONS: case Routes.ADVANCED_OPTIONS:
return MaterialPageRoute( return MaterialPageRoute(
settings: settings:
RouteSettings(arguments: args, name: Routes.ADVANCED_OPTIONS), RouteSettings(arguments: args, name: Routes.ADVANCED_OPTIONS),
builder: (_) => AdvancedOptionsPage(), builder: (_) => const AdvancedOptionsPage(),
); );
case Routes.CHANNEL_PAGE: case Routes.CHANNEL_PAGE:
return MaterialPageRoute( return MaterialPageRoute(
@@ -83,14 +83,14 @@ class AppRoutes {
return MaterialPageRoute( return MaterialPageRoute(
settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT), settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT),
builder: (_) { builder: (_) {
return NewChatScreen(); return const NewChatScreen();
}); });
case Routes.NEW_GROUP_CHAT: case Routes.NEW_GROUP_CHAT:
return MaterialPageRoute( return MaterialPageRoute(
settings: settings:
RouteSettings(arguments: args, name: Routes.NEW_GROUP_CHAT), RouteSettings(arguments: args, name: Routes.NEW_GROUP_CHAT),
builder: (_) { builder: (_) {
return NewGroupChatScreen(); return const NewGroupChatScreen();
}); });
case Routes.NEW_GROUP_CHAT_DETAILS: case Routes.NEW_GROUP_CHAT_DETAILS:
return MaterialPageRoute( return MaterialPageRoute(
@@ -125,7 +125,7 @@ class AppRoutes {
settings: settings:
RouteSettings(arguments: args, name: Routes.CHANNEL_LIST_PAGE), RouteSettings(arguments: args, name: Routes.CHANNEL_LIST_PAGE),
builder: (context) { builder: (context) {
return ChannelListPage(); return const ChannelListPage();
}); });
// Default case, should not reach here. // Default case, should not reach here.
default: default:
@@ -1,3 +1,5 @@
// ignore_for_file: constant_identifier_names
/// Application routes /// Application routes
abstract class Routes { abstract class Routes {
static const String APP = '/app'; static const String APP = '/app';
@@ -9,7 +9,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8':
User( User(
id: 'salvatore', id: 'salvatore',
extraData: { extraData: const {
'name': 'Salvatore Giordano', 'name': 'Salvatore Giordano',
'image': 'image':
'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4', 'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4',
@@ -18,7 +18,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo':
User( User(
id: 'sahil', id: 'sahil',
extraData: { extraData: const {
'name': 'Sahil Kumar', 'name': 'Sahil Kumar',
'image': 'image':
'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4', 'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4',
@@ -27,7 +27,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg':
User( User(
id: 'ben', id: 'ben',
extraData: { extraData: const {
'name': 'Ben Golden', 'name': 'Ben Golden',
'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4', 'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4',
}, },
@@ -35,7 +35,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY':
User( User(
id: 'thierry', id: 'thierry',
extraData: { extraData: const {
'name': 'Thierry Schellenbach', 'name': 'Thierry Schellenbach',
'image': 'image':
'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4', 'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4',
@@ -44,7 +44,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o':
User( User(
id: 'tommaso', id: 'tommaso',
extraData: { extraData: const {
'name': 'Tommaso Barbugli', 'name': 'Tommaso Barbugli',
'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4', 'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4',
}, },
@@ -52,7 +52,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc':
User( User(
id: 'deven', id: 'deven',
extraData: { extraData: const {
'name': 'Deven Joshi', 'name': 'Deven Joshi',
'image': 'image':
'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4', 'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4',
@@ -61,7 +61,7 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw':
User( User(
id: 'neevash', id: 'neevash',
extraData: { extraData: const {
'name': 'Neevash Ramdial', 'name': 'Neevash Ramdial',
'image': 'image':
'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4', 'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4',
@@ -70,14 +70,14 @@ final defaultUsers = <String, User>{
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU':
User( User(
id: 'qatest1', id: 'qatest1',
extraData: { extraData: const {
'name': 'QA test 1', 'name': 'QA test 1',
}, },
), ),
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM':
User( User(
id: 'qatest2', id: 'qatest2',
extraData: { extraData: const {
'name': 'QA test 2', 'name': 'QA test 2',
}, },
), ),
@@ -20,18 +20,23 @@ void showLocalNotification(
} }
if (event.message == null) return; if (event.message == null) return;
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
final initializationSettingsAndroid = const initializationSettingsAndroid =
AndroidInitializationSettings('launch_background'); AndroidInitializationSettings('launch_background');
final initializationSettingsIOS = IOSInitializationSettings(); const initializationSettingsIOS = IOSInitializationSettings();
final initializationSettings = InitializationSettings( const initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, android: initializationSettingsAndroid,
iOS: initializationSettingsIOS, iOS: initializationSettingsIOS,
); );
final appLocalizations = AppLocalizations.of(context);
await flutterLocalNotificationsPlugin.initialize( await flutterLocalNotificationsPlugin.initialize(
initializationSettings, initializationSettings,
onSelectNotification: (channelCid) async { onSelectNotification: (channelCid) async {
if (channelCid != null) { if (channelCid != null) {
final client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
var channel = client.state.channels[channelCid]; var channel = client.state.channels[channelCid];
if (channel == null) { if (channel == null) {
@@ -45,8 +50,7 @@ void showLocalNotification(
await channel.watch(); await channel.watch();
} }
Navigator.pushNamed( navigator.pushNamed(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs( arguments: ChannelPageArgs(
channel: channel, channel: channel,
@@ -62,13 +66,12 @@ void showLocalNotification(
NotificationDetails( NotificationDetails(
android: AndroidNotificationDetails( android: AndroidNotificationDetails(
'message channel', 'message channel',
AppLocalizations.of(context).messageChannelName, appLocalizations.messageChannelName,
channelDescription: channelDescription: appLocalizations.messageChannelDescription,
AppLocalizations.of(context).messageChannelDescription,
priority: Priority.high, priority: Priority.high,
importance: Importance.high, importance: Importance.high,
), ),
iOS: IOSNotificationDetails(), iOS: const IOSNotificationDetails(),
), ),
payload: '${event.channelType}:${event.channelId}', payload: '${event.channelType}:${event.channelId}',
); );
@@ -13,21 +13,23 @@ import '../pages/chat_info_screen.dart';
import '../pages/group_info_screen.dart'; import '../pages/group_info_screen.dart';
class ChannelList extends StatefulWidget { class ChannelList extends StatefulWidget {
const ChannelList({super.key});
@override @override
_ChannelList createState() => _ChannelList(); State<ChannelList> createState() => _ChannelList();
} }
class _ChannelList extends State<ChannelList> { class _ChannelList extends State<ChannelList> {
ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
late StreamMessageSearchListController _messageSearchListController = late final StreamMessageSearchListController _messageSearchListController =
StreamMessageSearchListController( StreamMessageSearchListController(
client: StreamChat.of(context).client, client: StreamChat.of(context).client,
filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]), filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]),
limit: 5, limit: 5,
searchQuery: '', searchQuery: '',
sort: [ sort: [
SortOption( const SortOption(
'created_at', 'created_at',
direction: SortOption.ASC, direction: SortOption.ASC,
), ),
@@ -116,7 +118,7 @@ class _ChannelList extends State<ChannelList> {
return LayoutBuilder( return LayoutBuilder(
builder: (context, viewportConstraints) { builder: (context, viewportConstraints) {
return SingleChildScrollView( return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight, minHeight: viewportConstraints.maxHeight,
@@ -153,6 +155,7 @@ class _ChannelList extends State<ChannelList> {
final messageResponse = messageResponses[index]; final messageResponse = messageResponses[index];
FocusScope.of(context).requestFocus(FocusNode()); FocusScope.of(context).requestFocus(FocusNode());
final client = StreamChat.of(context).client; final client = StreamChat.of(context).client;
final navigator = Navigator.of(context);
final message = messageResponse.message; final message = messageResponse.message;
final channel = client.channel( final channel = client.channel(
messageResponse.channel!.type, messageResponse.channel!.type,
@@ -161,8 +164,7 @@ class _ChannelList extends State<ChannelList> {
if (channel.state == null) { if (channel.state == null) {
await channel.watch(); await channel.watch();
} }
Navigator.pushNamed( navigator.pushNamed(
context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs( arguments: ChannelPageArgs(
channel: channel, channel: channel,
@@ -192,7 +194,6 @@ class _ChannelList extends State<ChannelList> {
motion: const BehindMotion(), motion: const BehindMotion(),
children: [ children: [
CustomSlidableAction( CustomSlidableAction(
child: Icon(Icons.more_horiz),
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
onPressed: (_) { onPressed: (_) {
showChannelInfoModalBottomSheet( showChannelInfoModalBottomSheet(
@@ -236,6 +237,7 @@ class _ChannelList extends State<ChannelList> {
}, },
); );
}, },
child: const Icon(Icons.more_horiz),
), ),
if (canDeleteChannel) if (canDeleteChannel)
CustomSlidableAction( CustomSlidableAction(
@@ -68,97 +68,95 @@ class ChipInputTextFieldState<T> extends State<ChipsInputTextField<T>> {
child: Material( child: Material(
elevation: 1, elevation: 1,
color: StreamChatTheme.of(context).colorTheme.barsBg, color: StreamChatTheme.of(context).colorTheme.barsBg,
child: Container( child: Padding(
child: Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
padding: const EdgeInsets.fromLTRB(16, 16, 16, 16), child: Row(
child: Row( children: [
children: [ Padding(
Padding( padding: const EdgeInsets.symmetric(vertical: 4.0),
padding: const EdgeInsets.symmetric(vertical: 4.0), child: Text(
child: Text( '${AppLocalizations.of(context).to.toUpperCase()}:',
'${AppLocalizations.of(context).to.toUpperCase()}:', style: StreamChatTheme.of(context)
style: StreamChatTheme.of(context) .textTheme
.textTheme .footnote
.footnote .copyWith(
.copyWith( color: StreamChatTheme.of(context)
color: StreamChatTheme.of(context) .colorTheme
.colorTheme .textHighEmphasis
.textHighEmphasis .withOpacity(.5)),
.withOpacity(.5)),
),
), ),
SizedBox(width: 12), ),
Expanded( const SizedBox(width: 12),
child: Column( Expanded(
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start,
children: [ mainAxisSize: MainAxisSize.min,
Wrap( children: [
spacing: 8.0, Wrap(
runSpacing: 4.0, spacing: 8.0,
children: _chips.map((item) { runSpacing: 4.0,
return widget.chipBuilder(context, item); children: _chips.map((item) {
}).toList(), return widget.chipBuilder(context, item);
), }).toList(),
if (!_pauseItemAddition)
TextField(
controller: widget.controller,
onChanged: widget.onInputChanged,
focusNode: widget.focusNode,
decoration: InputDecoration(
isDense: true,
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: const EdgeInsets.only(top: 4.0),
hintText: widget.hint,
hintStyle: StreamChatTheme.of(context)
.textTheme
.body
.copyWith(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
.withOpacity(.5)),
),
),
],
),
),
SizedBox(width: 12),
Align(
alignment: Alignment.bottomCenter,
child: IconButton(
icon: _chips.isEmpty
? StreamSvgIcon.user(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
.withOpacity(0.5),
size: 24,
)
: StreamSvgIcon.userAdd(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
.withOpacity(0.5),
size: 24,
),
onPressed: resumeItemAddition,
alignment: Alignment.topRight,
visualDensity: VisualDensity.compact,
padding: const EdgeInsets.all(0),
splashRadius: 24,
constraints: BoxConstraints.tightFor(
height: 24,
width: 24,
), ),
if (!_pauseItemAddition)
TextField(
controller: widget.controller,
onChanged: widget.onInputChanged,
focusNode: widget.focusNode,
decoration: InputDecoration(
isDense: true,
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: const EdgeInsets.only(top: 4.0),
hintText: widget.hint,
hintStyle: StreamChatTheme.of(context)
.textTheme
.body
.copyWith(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
.withOpacity(.5)),
),
),
],
),
),
const SizedBox(width: 12),
Align(
alignment: Alignment.bottomCenter,
child: IconButton(
icon: _chips.isEmpty
? StreamSvgIcon.user(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
.withOpacity(0.5),
size: 24,
)
: StreamSvgIcon.userAdd(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
.withOpacity(0.5),
size: 24,
),
onPressed: resumeItemAddition,
alignment: Alignment.topRight,
visualDensity: VisualDensity.compact,
padding: const EdgeInsets.all(0),
splashRadius: 24,
constraints: const BoxConstraints.tightFor(
height: 24,
width: 24,
), ),
), ),
], ),
), ],
), ),
), ),
), ),
@@ -41,7 +41,7 @@ class SearchTextField extends StatelessWidget {
onChanged: onChanged, onChanged: onChanged,
decoration: InputDecoration( decoration: InputDecoration(
prefixText: ' ', prefixText: ' ',
prefixIconConstraints: BoxConstraints.tight(Size(40, 24)), prefixIconConstraints: BoxConstraints.tight(const Size(40, 24)),
prefixIcon: Padding( prefixIcon: Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: 8, left: 8,
@@ -18,7 +18,7 @@ class StreamVersion extends StatelessWidget {
future: rootBundle.loadString('pubspec.lock'), future: rootBundle.loadString('pubspec.lock'),
builder: (context, snapshot) { builder: (context, snapshot) {
if (!snapshot.hasData) { if (!snapshot.hasData) {
return SizedBox(); return const SizedBox();
} }
final pubspec = snapshot.data!; final pubspec = snapshot.data!;
+1
View File
@@ -39,6 +39,7 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_launcher_icons: ^0.9.2 flutter_launcher_icons: ^0.9.2
test: any test: any
flutter_lints: ^2.0.0
dependency_overrides: dependency_overrides:
stream_chat: stream_chat: