diff --git a/stream_chat_v1/lib/advanced_options_page.dart b/stream_chat_v1/lib/advanced_options_page.dart index 023ce32..ee50514 100644 --- a/stream_chat_v1/lib/advanced_options_page.dart +++ b/stream_chat_v1/lib/advanced_options_page.dart @@ -1,17 +1,12 @@ -import 'dart:io'; - -import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; import 'package:example/stream_version.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'choose_user_page.dart'; -import 'notifications_service.dart'; +import 'main.dart'; class AdvancedOptionsPage extends StatefulWidget { @override @@ -272,14 +267,10 @@ class _AdvancedOptionsPageState extends State { ), ); - final client = Client( + final client = StreamChatClient( apiKey, logLevel: Level.INFO, - showLocalNotification: (!kIsWeb && Platform.isAndroid) - ? showLocalNotification - : null, - persistenceEnabled: true, - ); + )..chatPersistenceClient = chatPersistentClient; try { await client.setUser( @@ -289,10 +280,6 @@ class _AdvancedOptionsPageState extends State { userToken, ); - if (!kIsWeb) { - initNotifications(client); - } - final secureStorage = FlutterSecureStorage(); secureStorage.write( key: kStreamApiKey, @@ -319,73 +306,13 @@ class _AdvancedOptionsPageState extends State { await client.disconnect(); return; } - - if (!kIsWeb) { - initNotifications(client); - } - - Navigator.pop(context); - Navigator.pop(context); - await Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) { - return FutureBuilder( - future: StreamingSharedPreferences.instance, - builder: (context, snapshot) { - if (!snapshot.hasData) { - return SizedBox(); - } - return PreferenceBuilder( - preference: snapshot.data.getInt( - 'theme', - defaultValue: 0, - ), - builder: (context, snapshot) => MaterialApp( - builder: (context, child) { - return StreamChat( - client: client, - child: Builder( - builder: (context) => - AnnotatedRegion< - SystemUiOverlayStyle>( - child: child, - value: SystemUiOverlayStyle( - systemNavigationBarColor: - StreamChatTheme.of(context) - .colorTheme - .white, - systemNavigationBarIconBrightness: - Theme.of(context) - .brightness == - Brightness.dark - ? Brightness.light - : Brightness.dark, - ), - ), - ), - ); - }, - debugShowCheckedModeBanner: false, - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: { - -1: ThemeMode.dark, - 0: ThemeMode.system, - 1: ThemeMode.light, - }[snapshot], - onGenerateRoute: AppRoutes.generateRoute, - initialRoute: client.state.user == null - ? Routes.CHOOSE_USER - : Routes.HOME, - ), - ); - }, - ); - }, - ), - ); loading = false; + await Navigator.pushNamedAndRemoveUntil( + context, + Routes.APP, + ModalRoute.withName(Routes.APP), + arguments: client, + ); } }, ), diff --git a/stream_chat_v1/lib/chat_info_screen.dart b/stream_chat_v1/lib/chat_info_screen.dart index a6b14de..8db438c 100644 --- a/stream_chat_v1/lib/chat_info_screen.dart +++ b/stream_chat_v1/lib/chat_info_screen.dart @@ -1,7 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; - import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'main.dart'; @@ -285,7 +284,7 @@ class _ChatInfoScreenState extends State { titleTextStyle: StreamChatTheme.of(context).textTheme.body, leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 22.0), - child: StreamSvgIcon.Icon_group( + child: StreamSvgIcon.iconGroup( size: 24.0, color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.5), diff --git a/stream_chat_v1/lib/choose_user_page.dart b/stream_chat_v1/lib/choose_user_page.dart index 8e36e74..a23db66 100644 --- a/stream_chat_v1/lib/choose_user_page.dart +++ b/stream_chat_v1/lib/choose_user_page.dart @@ -1,11 +1,9 @@ import 'package:example/stream_version.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'notifications_service.dart'; import 'routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; @@ -187,10 +185,6 @@ class ChooseUserPage extends StatelessWidget { key: kStreamToken, value: token, ); - - if (!kIsWeb) { - initNotifications(client); - } Navigator.pushNamedAndRemoveUntil( context, Routes.HOME, @@ -219,7 +213,7 @@ class ChooseUserPage extends StatelessWidget { .grey, ), ), - trailing: StreamSvgIcon.arrow_right( + trailing: StreamSvgIcon.arrowRight( color: StreamChatTheme.of(context) .colorTheme .accentBlue, diff --git a/stream_chat_v1/lib/custom_message.dart b/stream_chat_v1/lib/custom_message.dart index 5da4541..e275643 100644 --- a/stream_chat_v1/lib/custom_message.dart +++ b/stream_chat_v1/lib/custom_message.dart @@ -15,7 +15,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// you can use [StreamChat.of], [StreamChannel.of] and [StreamChatTheme.of] to use the API client directly /// or to retrieve outer scope needed such as messages from the [Channel.state]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -29,7 +29,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/lib/custom_theme.dart b/stream_chat_v1/lib/custom_theme.dart index 817d2e6..a7ad5ba 100644 --- a/stream_chat_v1/lib/custom_theme.dart +++ b/stream_chat_v1/lib/custom_theme.dart @@ -19,7 +19,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// We also change the message color posted by the current user. /// You can perform these more granular style changes using [StreamChatTheme.copyWith]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -33,7 +33,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/lib/customize_channel_preview.dart b/stream_chat_v1/lib/customize_channel_preview.dart index 9b7deb6..2f28fa8 100644 --- a/stream_chat_v1/lib/customize_channel_preview.dart +++ b/stream_chat_v1/lib/customize_channel_preview.dart @@ -20,7 +20,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// - We retrieve the count of unread messages from [Channel.state] void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -34,7 +34,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/lib/customize_message_widget.dart b/stream_chat_v1/lib/customize_message_widget.dart index 14233dd..d19d602 100644 --- a/stream_chat_v1/lib/customize_message_widget.dart +++ b/stream_chat_v1/lib/customize_message_widget.dart @@ -15,7 +15,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// you can use [StreamChat.of], [StreamChannel.of] and [StreamChatTheme.of] to use the API client directly /// or to retrieve outer scope needed such as messages from the [Channel.state]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -29,7 +29,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/lib/group_chat_details_screen.dart b/stream_chat_v1/lib/group_chat_details_screen.dart index 83ec94b..afc9d12 100644 --- a/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/stream_chat_v1/lib/group_chat_details_screen.dart @@ -150,116 +150,116 @@ class _GroupChatDetailsScreenState extends State { ), ], ), - body: ValueListenableBuilder( - valueListenable: StreamChat.of(context).client.wsConnectionStatus, - builder: (context, status, _) { - String statusString = ''; - bool showStatus = true; + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; - switch (status) { - case ConnectionStatus.connected: - statusString = 'Connected'; - showStatus = false; - break; - case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; - break; - case ConnectionStatus.disconnected: - statusString = 'Disconnected'; - break; - } - return InfoTile( - showMessage: showStatus, - tileAnchor: Alignment.topCenter, - childAnchor: Alignment.topCenter, - message: statusString, - child: Column( - children: [ - Container( - width: double.maxFinite, - decoration: BoxDecoration( - gradient: - StreamChatTheme.of(context).colorTheme.bgGradient, + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: Column( + children: [ + Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 8, - ), - child: Text( - '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', - style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.grey, - ), + child: Text( + '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.grey, ), ), ), - Expanded( - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: ListView.separated( - itemCount: _selectedUsers.length + 1, - separatorBuilder: (_, __) => Container( - height: 1, - color: StreamChatTheme.of(context) - .colorTheme - .greyWhisper, - ), - itemBuilder: (_, index) { - if (index == _selectedUsers.length) { - return Container( - height: 1, + ), + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: ListView.separated( + itemCount: _selectedUsers.length + 1, + separatorBuilder: (_, __) => Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ), + itemBuilder: (_, index) { + if (index == _selectedUsers.length) { + return Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ); + } + final user = _selectedUsers[index]; + return ListTile( + key: ObjectKey(user), + leading: UserAvatar( + user: user, + constraints: BoxConstraints.tightFor( + width: 40, + height: 40, + ), + ), + title: Text( + user.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + trailing: IconButton( + icon: Icon( + Icons.clear_rounded, color: StreamChatTheme.of(context) .colorTheme - .greyWhisper, - ); - } - final user = _selectedUsers[index]; - return ListTile( - key: ObjectKey(user), - leading: UserAvatar( - user: user, - constraints: BoxConstraints.tightFor( - width: 40, - height: 40, - ), + .black, ), - title: Text( - user.name, - style: TextStyle(fontWeight: FontWeight.bold), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - trailing: IconButton( - icon: Icon( - Icons.clear_rounded, - color: StreamChatTheme.of(context) - .colorTheme - .black, - ), - padding: const EdgeInsets.all(0), - splashRadius: 24, - onPressed: () { - setState(() { - _selectedUsers.remove(user); - }); - if (_selectedUsers.isEmpty) { - Navigator.pop(context, _selectedUsers); - } - }, - ), - ); - }, - ), + padding: const EdgeInsets.all(0), + splashRadius: 24, + onPressed: () { + setState(() { + _selectedUsers.remove(user); + }); + if (_selectedUsers.isEmpty) { + Navigator.pop(context, _selectedUsers); + } + }, + ), + ); + }, ), ), - ], - ), - ); - }), + ), + ], + ), + ); + }, + ), ), ); } diff --git a/stream_chat_v1/lib/group_info_screen.dart b/stream_chat_v1/lib/group_info_screen.dart index 0f200c8..d22b1ce 100644 --- a/stream_chat_v1/lib/group_info_screen.dart +++ b/stream_chat_v1/lib/group_info_screen.dart @@ -377,7 +377,7 @@ class _GroupInfoScreenState extends State { mainAxisSize: MainAxisSize.min, children: [ InkWell( - child: StreamSvgIcon.close_small(), + child: StreamSvgIcon.closeSmall(), onTap: () { setState(() { _nameController.text = @@ -739,7 +739,7 @@ class _GroupInfoScreenState extends State { ), SizedBox(width: 16.0), IconButton( - icon: StreamSvgIcon.close_small( + icon: StreamSvgIcon.closeSmall( color: theme.colorTheme.grey, ), constraints: BoxConstraints.tightFor( @@ -869,7 +869,7 @@ class _GroupInfoScreenState extends State { isUserAdmin) _buildModalListTile( context, - StreamSvgIcon.Icon_user_settings( + StreamSvgIcon.iconUserSettings( color: StreamChatTheme.of(context).colorTheme.grey, size: 24.0, ), @@ -891,7 +891,7 @@ class _GroupInfoScreenState extends State { }, color: StreamChatTheme.of(context).colorTheme.accentRed), _buildModalListTile( context, - StreamSvgIcon.close_small( + StreamSvgIcon.closeSmall( color: StreamChatTheme.of(context).colorTheme.grey, size: 24.0, ), diff --git a/stream_chat_v1/lib/main.dart b/stream_chat_v1/lib/main.dart index 10d7399..45f86f0 100644 --- a/stream_chat_v1/lib/main.dart +++ b/stream_chat_v1/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:example/chat_info_screen.dart'; import 'package:example/choose_user_page.dart'; @@ -10,6 +9,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'notifications_service.dart'; @@ -17,6 +17,11 @@ import 'routes/app_routes.dart'; import 'routes/routes.dart'; import 'search_text_field.dart'; +final chatPersistentClient = StreamChatPersistenceClient( + logLevel: Level.INFO, + connectionMode: ConnectionMode.background, +); + void main() async { WidgetsFlutterBinding.ensureInitialized(); final secureStorage = FlutterSecureStorage(); @@ -24,13 +29,10 @@ void main() async { final apiKey = await secureStorage.read(key: kStreamApiKey); final userId = await secureStorage.read(key: kStreamUserId); - final client = Client( + final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, logLevel: Level.INFO, - showLocalNotification: - (!kIsWeb && Platform.isAndroid) ? showLocalNotification : null, - persistenceEnabled: true, - ); + )..chatPersistenceClient = chatPersistentClient; if (userId != null) { final token = await secureStorage.read(key: kStreamToken); @@ -38,16 +40,13 @@ void main() async { User(id: userId), token, ); - if (!kIsWeb) { - initNotifications(client); - } } runApp(MyApp(client)); } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); @@ -68,6 +67,7 @@ class MyApp extends StatelessWidget { builder: (context, child) { return StreamChat( client: client, + onBackgroundEventReceived: showLocalNotification, child: Builder( builder: (context) => AnnotatedRegion( child: child, @@ -294,7 +294,7 @@ class _HomePageState extends State { ), ), trailing: IconButton( - icon: StreamSvgIcon.Icon_moon( + icon: StreamSvgIcon.iconMoon( size: 24, ), color: StreamChatTheme.of(context).colorTheme.grey, diff --git a/stream_chat_v1/lib/multiple_conversation.dart b/stream_chat_v1/lib/multiple_conversation.dart index b5fdd5a..f810231 100644 --- a/stream_chat_v1/lib/multiple_conversation.dart +++ b/stream_chat_v1/lib/multiple_conversation.dart @@ -19,7 +19,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// In this case we are showing the list of channels the current user is a member and we order them based on the time they had a new message. /// [ChannelListView] handles pagination and updates automatically out of the box when new channels are created or when a new message is added to a channel. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -33,7 +33,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/lib/new_chat_screen.dart b/stream_chat_v1/lib/new_chat_screen.dart index baddd57..7f47e87 100644 --- a/stream_chat_v1/lib/new_chat_screen.dart +++ b/stream_chat_v1/lib/new_chat_screen.dart @@ -134,9 +134,8 @@ class _NewChatScreenState extends State { ), centerTitle: true, ), - body: ValueListenableBuilder( - valueListenable: StreamChat.of(context).client.wsConnectionStatus, - builder: (context, status, _) { + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; diff --git a/stream_chat_v1/lib/new_group_chat_screen.dart b/stream_chat_v1/lib/new_group_chat_screen.dart index 4d0274e..209d372 100644 --- a/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/stream_chat_v1/lib/new_group_chat_screen.dart @@ -67,7 +67,7 @@ class _NewGroupChatScreenState extends State { actions: [ if (_selectedUsers.isNotEmpty) IconButton( - icon: StreamSvgIcon.arrow_right( + icon: StreamSvgIcon.arrowRight( color: StreamChatTheme.of(context).colorTheme.accentBlue, ), onPressed: () async { @@ -87,227 +87,225 @@ class _NewGroupChatScreenState extends State { ) ], ), - body: ValueListenableBuilder( - valueListenable: StreamChat.of(context).client.wsConnectionStatus, - builder: (context, status, _) { - String statusString = ''; - bool showStatus = true; + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; - switch (status) { - case ConnectionStatus.connected: - statusString = 'Connected'; - showStatus = false; - break; - case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; - break; - case ConnectionStatus.disconnected: - statusString = 'Disconnected'; - break; - } - return InfoTile( - showMessage: showStatus, - tileAnchor: Alignment.topCenter, - childAnchor: Alignment.topCenter, - message: statusString, - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - ), + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, ), - if (_selectedUsers.isNotEmpty) - SliverToBoxAdapter( - child: Container( - height: 104, - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: _selectedUsers.length, - padding: const EdgeInsets.all(8), - separatorBuilder: (_, __) => SizedBox(width: 16), - itemBuilder: (_, index) { - final user = _selectedUsers.elementAt(index); - return Column( - children: [ - Stack( - children: [ - UserAvatar( - onlineIndicatorAlignment: - Alignment(0.9, 0.9), - user: user, - showOnlineStatus: true, - borderRadius: BorderRadius.circular(32), - constraints: BoxConstraints.tightFor( - height: 64, - width: 64, - ), + ), + if (_selectedUsers.isNotEmpty) + SliverToBoxAdapter( + child: Container( + height: 104, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: _selectedUsers.length, + padding: const EdgeInsets.all(8), + separatorBuilder: (_, __) => SizedBox(width: 16), + itemBuilder: (_, index) { + final user = _selectedUsers.elementAt(index); + return Column( + children: [ + Stack( + children: [ + UserAvatar( + onlineIndicatorAlignment: + Alignment(0.9, 0.9), + user: user, + showOnlineStatus: true, + borderRadius: BorderRadius.circular(32), + constraints: BoxConstraints.tightFor( + height: 64, + width: 64, ), - Positioned( - top: -4, - right: -4, - child: GestureDetector( - onTap: () { - if (_selectedUsers.contains(user)) { - setState(() => - _selectedUsers.remove(user)); - } - }, - child: Container( - decoration: BoxDecoration( + ), + Positioned( + top: -4, + right: -4, + child: GestureDetector( + onTap: () { + if (_selectedUsers.contains(user)) { + setState(() => + _selectedUsers.remove(user)); + } + }, + child: Container( + decoration: BoxDecoration( + color: StreamChatTheme.of(context) + .colorTheme + .white, + shape: BoxShape.circle, + border: Border.all( color: StreamChatTheme.of(context) .colorTheme - .white, - shape: BoxShape.circle, - border: Border.all( - color: - StreamChatTheme.of(context) - .colorTheme - .whiteSnow, - ), - ), - child: StreamSvgIcon.close( - color: StreamChatTheme.of(context) - .colorTheme - .black, - size: 24, + .whiteSnow, ), ), - ), - ) - ], - ), - SizedBox(height: 4), - Text( - user.name.split(' ')[0], - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12, - ), - ), - ], - ); - }, - ), - ), - ), - SliverPersistentHeader( - pinned: true, - delegate: _HeaderDelegate( - height: 30, - child: Container( - width: double.maxFinite, - decoration: BoxDecoration( - gradient: StreamChatTheme.of(context) - .colorTheme - .bgGradient, - ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 8, - ), - child: Text( - _isSearchActive - ? 'Matches for \"$_userNameQuery\"' - : 'On the platform', - style: TextStyle( - color: - StreamChatTheme.of(context).colorTheme.grey, - ), - ), - ), - ), - ), - ), - ]; - }, - body: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: UsersBloc( - child: UserListView( - selectedUsers: _selectedUsers, - pullToRefresh: false, - groupAlphabetically: _isSearchActive ? false : true, - onUserTap: (user, _) { - if (!_selectedUsers.contains(user)) { - setState(() { - _selectedUsers.add(user); - }); - } else { - setState(() { - _selectedUsers.remove(user); - }); - } - }, - pagination: PaginationParams( - limit: 25, - ), - filter: { - if (_userNameQuery.isNotEmpty) - 'name': { - r'$autocomplete': _userNameQuery, - }, - 'id': { - r'$ne': StreamChat.of(context).user.id, - } - }, - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .grey, + child: StreamSvgIcon.close( + color: StreamChatTheme.of(context) + .colorTheme + .black, + size: 24, + ), ), ), - Text( - 'No user matches these keywords...', - style: StreamChatTheme.of(context) - .textTheme - .footnote - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .grey, - ), - ), - ], + ) + ], + ), + SizedBox(height: 4), + Text( + user.name.split(' ')[0], + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12, ), ), - ), + ], ); }, - ); - }, + ), + ), ), + SliverPersistentHeader( + pinned: true, + delegate: _HeaderDelegate( + height: 30, + child: Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Text( + _isSearchActive + ? 'Matches for \"$_userNameQuery\"' + : 'On the platform', + style: TextStyle( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ), + ), + ), + ), + ]; + }, + body: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: UsersBloc( + child: UserListView( + selectedUsers: _selectedUsers, + pullToRefresh: false, + groupAlphabetically: _isSearchActive ? false : true, + onUserTap: (user, _) { + if (!_selectedUsers.contains(user)) { + setState(() { + _selectedUsers.add(user); + }); + } else { + setState(() { + _selectedUsers.remove(user); + }); + } + }, + pagination: PaginationParams( + limit: 25, + ), + filter: { + if (_userNameQuery.isNotEmpty) + 'name': { + r'$autocomplete': _userNameQuery, + }, + 'id': { + r'$ne': StreamChat.of(context).user.id, + } + }, + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + Text( + 'No user matches these keywords...', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + ], + ), + ), + ), + ); + }, + ); + }, ), ), ), - ); - }), + ), + ); + }, + ), ); } } diff --git a/stream_chat_v1/lib/notifications_service.dart b/stream_chat_v1/lib/notifications_service.dart index 298ab3a..246923d 100644 --- a/stream_chat_v1/lib/notifications_service.dart +++ b/stream_chat_v1/lib/notifications_service.dart @@ -1,11 +1,9 @@ -import 'dart:io'; - -import 'package:flutter_apns/flutter_apns.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -void showLocalNotification(Message message, ChannelModel channel) async { +void showLocalNotification(Event event) async { + if (event.message == null) return; final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); final initializationSettingsAndroid = AndroidInitializationSettings('launch_background'); @@ -16,9 +14,9 @@ void showLocalNotification(Message message, ChannelModel channel) async { ); await flutterLocalNotificationsPlugin.initialize(initializationSettings); await flutterLocalNotificationsPlugin.show( - message.id.hashCode, - '${message.user.name} @ ${channel.name}', - message.text, + event.message.id.hashCode, + event.message.user.name, + event.message.text, NotificationDetails( android: AndroidNotificationDetails( 'message channel', @@ -31,33 +29,3 @@ void showLocalNotification(Message message, ChannelModel channel) async { ), ); } - -Future backgroundHandler(Map notification) async { - print('new notification ${notification}'); - final messageId = notification['data']['id']; - - final notificationData = - await NotificationService.getAndStoreMessage(messageId); - - showLocalNotification( - notificationData.message, - notificationData.channel, - ); -} - -void initNotifications(Client client) { - final connector = createPushConnector(); - connector.configure( - onBackgroundMessage: backgroundHandler, - ); - - connector.requestNotificationPermissions(); - connector.token.addListener(() { - if (connector.token.value != null) { - client.addDevice( - connector.token.value, - Platform.isAndroid ? PushProvider.firebase : PushProvider.apn, - ); - } - }); -} diff --git a/stream_chat_v1/lib/routes/app_routes.dart b/stream_chat_v1/lib/routes/app_routes.dart index 0c8a899..e7c7e31 100644 --- a/stream_chat_v1/lib/routes/app_routes.dart +++ b/stream_chat_v1/lib/routes/app_routes.dart @@ -15,6 +15,12 @@ class AppRoutes { static Route generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { + case Routes.APP: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.APP), + builder: (_) { + return MyApp(args); + }); case Routes.HOME: return MaterialPageRoute( settings: const RouteSettings(name: Routes.HOME), diff --git a/stream_chat_v1/lib/routes/routes.dart b/stream_chat_v1/lib/routes/routes.dart index 0d2f4e5..2280ca3 100644 --- a/stream_chat_v1/lib/routes/routes.dart +++ b/stream_chat_v1/lib/routes/routes.dart @@ -1,5 +1,6 @@ /// Define all the route names here class Routes { + static const String APP = '/app'; static const String HOME = '/home'; static const String CHOOSE_USER = '/choose_user'; static const String ADVANCED_OPTIONS = '/advance_options'; diff --git a/stream_chat_v1/lib/search_text_field.dart b/stream_chat_v1/lib/search_text_field.dart index ff34e8a..9628ddb 100644 --- a/stream_chat_v1/lib/search_text_field.dart +++ b/stream_chat_v1/lib/search_text_field.dart @@ -71,7 +71,7 @@ class SearchTextField extends StatelessWidget { color: Colors.transparent, child: IconButton( padding: const EdgeInsets.all(0), - icon: StreamSvgIcon.close_small( + icon: StreamSvgIcon.closeSmall( color: Colors.grey, ), splashRadius: 24, diff --git a/stream_chat_v1/lib/single_conversation.dart b/stream_chat_v1/lib/single_conversation.dart index 2093d38..66a1091 100644 --- a/stream_chat_v1/lib/single_conversation.dart +++ b/stream_chat_v1/lib/single_conversation.dart @@ -5,8 +5,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// There are three important things to notice that are common to all Flutter application using StreamChat: /// -/// 1. The Dart API [Client] is initialized with your API Key -/// 2. The current user is set by calling [Client.setUser] +/// 1. The Dart API [StreamChatClient] is initialized with your API Key +/// 2. The current user is set by calling [StreamChatClient.setUser] /// 3. The client is then passed to the top-level [StreamChat] widget /// [StreamChat] is an inherited widget and must be the parent of all Chat related widgets. /// @@ -15,9 +15,9 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// Let's have a look at what we've built: /// -/// - We set up the Chat [Client] with the API key +/// - We set up the Chat [StreamChatClient] with the API key /// -/// - We set the the current user for Chat with [Client.setUser] and a pre-generated user token +/// - We set the the current user for Chat with [StreamChatClient.setUser] and a pre-generated user token /// /// - We make [StreamChat] the root Widget of our application /// @@ -25,7 +25,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// If you now run the simulator you will see a single channel UI. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -44,7 +44,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; final Channel channel; MyApp(this.client, this.channel); diff --git a/stream_chat_v1/lib/split_view.dart b/stream_chat_v1/lib/split_view.dart index f99e69f..0832475 100644 --- a/stream_chat_v1/lib/split_view.dart +++ b/stream_chat_v1/lib/split_view.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -16,7 +16,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/lib/threads.dart b/stream_chat_v1/lib/threads.dart index f89e6fc..6a3c776 100644 --- a/stream_chat_v1/lib/threads.dart +++ b/stream_chat_v1/lib/threads.dart @@ -10,7 +10,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// Now we can open threads and create new ones as well, if you long press a message you can tap on Reply and it will open the same [ThreadPage]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -24,7 +24,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/stream_chat_v1/pubspec.yaml b/stream_chat_v1/pubspec.yaml index 4814f3b..9b387e3 100644 --- a/stream_chat_v1/pubspec.yaml +++ b/stream_chat_v1/pubspec.yaml @@ -9,8 +9,10 @@ environment: dependencies: flutter: sdk: flutter - stream_chat_flutter: + stream_chat_flutter: path: ../ + stream_chat_persistence: + path: ../../stream_chat_persistence flutter_apns: ^1.4.1 flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.1