diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 00000000..134db5c4 --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,73 @@ +PODS: + - Flutter (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - path_provider (0.0.1): + - Flutter + - screen (0.0.1): + - Flutter + - sqflite (0.0.1): + - Flutter + - FMDB (~> 2.7.2) + - url_launcher (0.0.1): + - Flutter + - url_launcher_macos (0.0.1): + - Flutter + - url_launcher_web (0.0.1): + - Flutter + - video_player (0.0.1): + - Flutter + - video_player_web (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - path_provider (from `.symlinks/plugins/path_provider/ios`) + - screen (from `.symlinks/plugins/screen/ios`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + - url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`) + - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`) + - video_player (from `.symlinks/plugins/video_player/ios`) + - video_player_web (from `.symlinks/plugins/video_player_web/ios`) + +SPEC REPOS: + trunk: + - FMDB + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + path_provider: + :path: ".symlinks/plugins/path_provider/ios" + screen: + :path: ".symlinks/plugins/screen/ios" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + url_launcher_macos: + :path: ".symlinks/plugins/url_launcher_macos/ios" + url_launcher_web: + :path: ".symlinks/plugins/url_launcher_web/ios" + video_player: + :path: ".symlinks/plugins/video_player/ios" + video_player_web: + :path: ".symlinks/plugins/video_player_web/ios" + +SPEC CHECKSUMS: + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d + screen: abd91ca7bf3426e1cc3646d27e9b2358d6bf07b0 + sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 + url_launcher: a1c0cc845906122c4784c542523d8cacbded5626 + url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313 + url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c + video_player: 69c5f029fac4ffe4fc8a85ea7f7b793709661549 + video_player_web: da8cadb8274ed4f8dbee8d7171b420dedd437ce7 + +PODFILE CHECKSUM: 1b66dae606f75376c5f2135a8290850eeb09ae83 + +COCOAPODS: 1.8.4 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 0d45b982..308cdaf9 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7DEC2743BD66C91B700A3B97 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BB2E5E4E236267EDF0D8817 /* Pods_Runner.framework */; }; 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -37,11 +38,15 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2452A9E77396497EB4CF3072 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 68F846A6DB42D92393F5F7E0 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7BF51EE28C89025F73A5211F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 8BB2E5E4E236267EDF0D8817 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; @@ -59,6 +64,7 @@ files = ( 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + 7DEC2743BD66C91B700A3B97 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -84,6 +90,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + CF168B61BAB91958681C7C21 /* Pods */, + BC09A38346C8B2CD72199469 /* Frameworks */, ); sourceTree = ""; }; @@ -118,6 +126,25 @@ name = "Supporting Files"; sourceTree = ""; }; + BC09A38346C8B2CD72199469 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8BB2E5E4E236267EDF0D8817 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + CF168B61BAB91958681C7C21 /* Pods */ = { + isa = PBXGroup; + children = ( + 2452A9E77396497EB4CF3072 /* Pods-Runner.debug.xcconfig */, + 7BF51EE28C89025F73A5211F /* Pods-Runner.release.xcconfig */, + 68F846A6DB42D92393F5F7E0 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -125,12 +152,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 9E02B5C38D6CC2455D9E48E9 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 5702861DACEDB848A3E454E8 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -203,6 +232,21 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; }; + 5702861DACEDB848A3E454E8 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -217,6 +261,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + 9E02B5C38D6CC2455D9E48E9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16..21a3cc14 100644 --- a/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/example/lib/single_conversation.dart b/example/lib/single_conversation.dart index fd1fd596..8028a84a 100644 --- a/example/lib/single_conversation.dart +++ b/example/lib/single_conversation.dart @@ -17,8 +17,18 @@ void main() async { // ignore: unawaited_futures channel.watch(); - runApp( - MaterialApp( + runApp(MyApp(client, channel)); +} + +class MyApp extends StatelessWidget { + final Client client; + final Channel channel; + + MyApp(this.client, this.channel); + + @override + Widget build(BuildContext context) { + return MaterialApp( home: StreamChat( client: client, child: StreamChannel( @@ -26,8 +36,8 @@ void main() async { child: ChannelPage(), ), ), - ), - ); + ); + } } class ChannelPage extends StatelessWidget { diff --git a/example/lib/threads.dart b/example/lib/threads.dart index 20481baf..56b483b7 100644 --- a/example/lib/threads.dart +++ b/example/lib/threads.dart @@ -19,9 +19,15 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ThemeData( + primarySwatch: Colors.orange, + ); + return MaterialApp( + theme: theme, home: Container( child: StreamChat( + streamChatThemeData: StreamChatThemeData.fromTheme(theme), client: client, child: ChannelListPage(), ), diff --git a/lib/src/channel_list_view.dart b/lib/src/channel_list_view.dart index b80c2db6..d8e34a78 100644 --- a/lib/src/channel_list_view.dart +++ b/lib/src/channel_list_view.dart @@ -96,7 +96,7 @@ class _ChannelListViewState extends State { if (i < channels.length) { final channel = channels[i]; - final channelClient = streamChat.client.channelClients[channel.id]; + final channelClient = streamChat.client.channels[channel.id]; ChannelTapCallback onTap; if (widget.onChannelTap != null) { diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 0576e867..d6cb0f00 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -25,72 +25,74 @@ class _MessageInputState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - width: MediaQuery.of(context).size.width, - padding: EdgeInsets.all(2), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), - gradient: _typingStarted - ? StreamChatTheme.of(context).channelTheme.inputGradient - : null, - ), + return SafeArea( + child: Padding( + padding: const EdgeInsets.all(8.0), child: Container( + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(2), decoration: BoxDecoration( - color: Colors.white, borderRadius: BorderRadius.circular(10.0), + gradient: _typingStarted + ? StreamChatTheme.of(context).channelTheme.inputGradient + : null, ), child: Container( decoration: BoxDecoration( - color: StreamChatTheme.of(context).channelTheme.inputBackground, + color: Colors.white, borderRadius: BorderRadius.circular(10.0), - border: Border.all( - color: _typingStarted - ? Colors.transparent - : Colors.black.withOpacity(.2)), ), - child: Flex( - direction: Axis.horizontal, - children: [ - Expanded( - child: TextField( - minLines: null, - maxLines: null, - onSubmitted: (_) { - _sendMessage(context); - }, - controller: _textController, - onChanged: (s) { - StreamChannel.of(context).channel.keyStroke(); - setState(() { - _messageIsPresent = s.trim().isNotEmpty; - }); - }, - onTap: () { - setState(() { - _typingStarted = true; - }); - }, - style: Theme.of(context).textTheme.body1, - autofocus: false, - decoration: InputDecoration( - hintText: 'Write a message', - prefixText: ' ', - border: InputBorder.none, + child: Container( + decoration: BoxDecoration( + color: StreamChatTheme.of(context).channelTheme.inputBackground, + borderRadius: BorderRadius.circular(10.0), + border: Border.all( + color: _typingStarted + ? Colors.transparent + : Colors.black.withOpacity(.2)), + ), + child: Flex( + direction: Axis.horizontal, + children: [ + Expanded( + child: TextField( + minLines: null, + maxLines: null, + onSubmitted: (_) { + _sendMessage(context); + }, + controller: _textController, + onChanged: (s) { + StreamChannel.of(context).channel.keyStroke(); + setState(() { + _messageIsPresent = s.trim().isNotEmpty; + }); + }, + onTap: () { + setState(() { + _typingStarted = true; + }); + }, + style: Theme.of(context).textTheme.body1, + autofocus: false, + decoration: InputDecoration( + hintText: 'Write a message', + prefixText: ' ', + border: InputBorder.none, + ), ), ), - ), - AnimatedCrossFade( - crossFadeState: _messageIsPresent - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - firstChild: _buildSendButton(context), - secondChild: SizedBox(), - duration: Duration(milliseconds: 300), - alignment: Alignment.center, - ), - ], + AnimatedCrossFade( + crossFadeState: _messageIsPresent + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + firstChild: _buildSendButton(context), + secondChild: SizedBox(), + duration: Duration(milliseconds: 300), + alignment: Alignment.center, + ), + ], + ), ), ), ), diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 75092334..4db16f9d 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -218,7 +218,7 @@ class _MessageListViewState extends State { } Widget _buildBottomMessage( - StreamChannelState channelBloc, + StreamChannelState channel, Message previousMessage, Message message, BuildContext context, @@ -244,8 +244,8 @@ class _MessageListViewState extends State { onVisibilityChanged: (visibility) { _isBottom = visibility.visibleBounds != Rect.zero; if (_isBottom) { - if (channelBloc.channel.state.unreadCount > 0) { - channelBloc.channel.markRead(); + if (channel.channel.state.unreadCount > 0) { + channel.channel.markRead(); } } }, diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index d9d83ce3..9c3aa322 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -133,8 +133,7 @@ class _MessageWidgetState extends State var row = [ Text( 'Replies: ${widget.message.replyCount}', - style: - Theme.of(context).textTheme.subtitle.copyWith(color: Colors.blue), + style: StreamChatTheme.of(context).messageTheme.replies, ), Transform( transform: Matrix4.rotationY(isMyMessage ? 0 : pi), @@ -360,88 +359,90 @@ class _MessageWidgetState extends State final textStyle = TextStyle( fontSize: fontSize, ); - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - color: Colors.black87, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: reactionToEmoji.keys.map((reactionType) { - final ownReactionIndex = widget.message.ownReactions - .indexWhere( - (reaction) => reaction.type == reactionType); - return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - IconButton( - iconSize: fontSize + 10, - icon: Text( - reactionToEmoji[reactionType], - style: textStyle, + return SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + color: Colors.black87, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: reactionToEmoji.keys.map((reactionType) { + final ownReactionIndex = widget.message.ownReactions + .indexWhere( + (reaction) => reaction.type == reactionType); + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + IconButton( + iconSize: fontSize + 10, + icon: Text( + reactionToEmoji[reactionType], + style: textStyle, + ), + onPressed: () { + if (ownReactionIndex != -1) { + removeReaction(reactionType); + } else { + sendReaction(reactionType); + } + }, ), - onPressed: () { - if (ownReactionIndex != -1) { - removeReaction(reactionType); - } else { - sendReaction(reactionType); - } - }, - ), - ownReactionIndex != -1 - ? Padding( - padding: const EdgeInsets.only(bottom: 4.0), - child: Text( - widget.message.ownReactions[ownReactionIndex] - .score - .toString(), - style: TextStyle(color: Colors.white), - ), - ) - : SizedBox(), - ], - ); - }).toList(), - ), - ), - isMyMessage - ? FlatButton( - child: Padding( - padding: const EdgeInsets.all(28.0), - child: Text( - 'Delete message', - style: Theme.of(context) - .textTheme - .headline - .copyWith(color: Colors.red), - ), - ), - onPressed: () { - StreamChat.of(context) - .client - .deleteMessage(widget.message.id); - Navigator.pop(context); - }, - ) - : SizedBox(), - FlatButton( - child: Padding( - padding: const EdgeInsets.all(28.0), - child: Text( - 'Start a thread', - style: Theme.of(context).textTheme.headline, + ownReactionIndex != -1 + ? Padding( + padding: const EdgeInsets.only(bottom: 4.0), + child: Text( + widget.message + .ownReactions[ownReactionIndex].score + .toString(), + style: TextStyle(color: Colors.white), + ), + ) + : SizedBox(), + ], + ); + }).toList(), ), ), - onPressed: () { - Navigator.pop(context); - widget.onThreadTap(widget.message); - }, - ), - ], + isMyMessage + ? FlatButton( + child: Padding( + padding: const EdgeInsets.all(28.0), + child: Text( + 'Delete message', + style: Theme.of(context) + .textTheme + .headline + .copyWith(color: Colors.red), + ), + ), + onPressed: () { + StreamChat.of(context) + .client + .deleteMessage(widget.message.id); + Navigator.pop(context); + }, + ) + : SizedBox(), + FlatButton( + child: Padding( + padding: const EdgeInsets.all(28.0), + child: Text( + 'Start a thread', + style: Theme.of(context).textTheme.headline, + ), + ), + onPressed: () { + Navigator.pop(context); + widget.onThreadTap(widget.message); + }, + ), + ], + ), ); }); } @@ -491,7 +492,7 @@ class _MessageWidgetState extends State } final Map reactionToEmoji = { - 'love': '♥️', + 'love': '❤️️', 'haha': '😂', 'like': '👍', 'sad': '😕', diff --git a/lib/src/stream_chat.dart b/lib/src/stream_chat.dart index 45e07723..2ce338a5 100644 --- a/lib/src/stream_chat.dart +++ b/lib/src/stream_chat.dart @@ -44,15 +44,15 @@ class StreamChatState extends State { @override Widget build(BuildContext context) { - final theme = _computeTheme(context); + final theme = _getTheme(context, widget.streamChatThemeData); return StreamChatTheme( data: theme, child: Builder( builder: (context) => Theme( data: Theme.of(context).copyWith( accentColor: StreamChatTheme.of(context).accentColor, - scaffoldBackgroundColor: theme.primaryColor, - backgroundColor: theme.primaryColor, + scaffoldBackgroundColor: Colors.white, + backgroundColor: Colors.white, ), child: WillPopScope( onWillPop: () async { @@ -79,146 +79,66 @@ class StreamChatState extends State { ); } - StreamChatThemeData _computeTheme(BuildContext context) { - final defaultTheme = _getDefaultTheme(context); + StreamChatThemeData _getTheme( + BuildContext context, + StreamChatThemeData themeData, + ) { + final defaultTheme = StreamChatThemeData.getDefaultTheme(Theme.of(context)); final theme = defaultTheme.copyWith( - primaryColor: widget.streamChatThemeData?.primaryColor, + primaryColor: themeData?.primaryColor, channelTheme: defaultTheme.channelTheme.copyWith( - channelHeaderTheme: defaultTheme.channelTheme.channelHeaderTheme - .copyWith( - color: widget.streamChatThemeData?.channelTheme - ?.channelHeaderTheme?.color, - lastMessageAt: widget.streamChatThemeData?.channelTheme - ?.channelHeaderTheme?.lastMessageAt, - title: widget.streamChatThemeData?.channelTheme - ?.channelHeaderTheme?.title, - avatarTheme: - defaultTheme.channelPreviewTheme.avatarTheme.copyWith( - constraints: widget.streamChatThemeData?.channelTheme - ?.channelHeaderTheme?.avatarTheme?.constraints, - borderRadius: widget.streamChatThemeData?.channelTheme - ?.channelHeaderTheme?.avatarTheme?.borderRadius, - )), - inputBackground: - widget.streamChatThemeData?.channelTheme?.inputBackground, - messageInputButtonIconTheme: widget - .streamChatThemeData?.channelTheme?.messageInputButtonIconTheme, - inputGradient: widget.streamChatThemeData?.channelTheme?.inputGradient, + channelHeaderTheme: + defaultTheme.channelTheme.channelHeaderTheme.copyWith( + color: themeData?.channelTheme?.channelHeaderTheme?.color, + lastMessageAt: + themeData?.channelTheme?.channelHeaderTheme?.lastMessageAt, + title: themeData?.channelTheme?.channelHeaderTheme?.title, + avatarTheme: defaultTheme.channelPreviewTheme.avatarTheme.copyWith( + constraints: themeData + ?.channelTheme?.channelHeaderTheme?.avatarTheme?.constraints, + borderRadius: themeData + ?.channelTheme?.channelHeaderTheme?.avatarTheme?.borderRadius, + ), + ), + inputBackground: themeData?.channelTheme?.inputBackground, + messageInputButtonIconTheme: + themeData?.channelTheme?.messageInputButtonIconTheme, + inputGradient: themeData?.channelTheme?.inputGradient, messageInputButtonTheme: - widget.streamChatThemeData?.channelTheme?.messageInputButtonTheme, + themeData?.channelTheme?.messageInputButtonTheme, ), messageTheme: defaultTheme.messageTheme.copyWith( - createdAt: widget.streamChatThemeData?.messageTheme?.createdAt, - messageText: widget.streamChatThemeData?.messageTheme?.messageText, - otherMessageBackgroundColor: widget - .streamChatThemeData?.messageTheme?.otherMessageBackgroundColor, + replies: themeData?.messageTheme?.replies, + createdAt: themeData?.messageTheme?.createdAt, + messageText: themeData?.messageTheme?.messageText, + otherMessageBackgroundColor: + themeData?.messageTheme?.otherMessageBackgroundColor, ownMessageBackgroundColor: - widget.streamChatThemeData?.messageTheme?.ownMessageBackgroundColor, - fontFamily: widget.streamChatThemeData?.messageTheme?.fontFamily, - messageAuthor: widget.streamChatThemeData?.messageTheme?.messageAuthor, - messageMention: - widget.streamChatThemeData?.messageTheme?.messageMention, + themeData?.messageTheme?.ownMessageBackgroundColor, + fontFamily: themeData?.messageTheme?.fontFamily, + messageAuthor: themeData?.messageTheme?.messageAuthor, + messageMention: themeData?.messageTheme?.messageMention, avatarTheme: defaultTheme.messageTheme.avatarTheme.copyWith( - constraints: widget - .streamChatThemeData?.messageTheme?.avatarTheme?.constraints, - borderRadius: widget - .streamChatThemeData?.messageTheme?.avatarTheme?.borderRadius, + constraints: themeData?.messageTheme?.avatarTheme?.constraints, + borderRadius: themeData?.messageTheme?.avatarTheme?.borderRadius, ), ), - accentColor: widget.streamChatThemeData?.accentColor, - secondaryColor: widget.streamChatThemeData?.secondaryColor, + accentColor: themeData?.accentColor, + secondaryColor: themeData?.secondaryColor, channelPreviewTheme: defaultTheme.channelPreviewTheme.copyWith( avatarTheme: defaultTheme.channelPreviewTheme.avatarTheme.copyWith( - constraints: widget.streamChatThemeData?.channelPreviewTheme - ?.avatarTheme?.constraints, - borderRadius: widget.streamChatThemeData?.channelPreviewTheme - ?.avatarTheme?.borderRadius, + constraints: themeData?.channelPreviewTheme?.avatarTheme?.constraints, + borderRadius: + themeData?.channelPreviewTheme?.avatarTheme?.borderRadius, ), - title: widget.streamChatThemeData?.channelPreviewTheme?.title, - lastMessageAt: - widget.streamChatThemeData?.channelPreviewTheme?.lastMessageAt, - subtitle: widget.streamChatThemeData?.channelPreviewTheme?.subtitle, + title: themeData?.channelPreviewTheme?.title, + lastMessageAt: themeData?.channelPreviewTheme?.lastMessageAt, + subtitle: themeData?.channelPreviewTheme?.subtitle, ), ); return theme; } - StreamChatThemeData _getDefaultTheme(BuildContext context) { - final accentColor = Color(0xff006cff); - return StreamChatThemeData( - accentColor: accentColor, - primaryColor: Colors.white, - channelPreviewTheme: ChannelPreviewTheme( - avatarTheme: AvatarTheme( - borderRadius: BorderRadius.circular(20), - constraints: BoxConstraints.tightFor( - height: 40, - width: 40, - ), - ), - title: TextStyle( - fontSize: 14, - color: Colors.black, - ), - subtitle: TextStyle( - fontSize: 13, - color: Colors.black, - ), - lastMessageAt: TextStyle( - fontSize: 11, - color: Colors.black.withOpacity(.5), - ), - ), - channelTheme: ChannelTheme( - messageInputButtonIconTheme: Theme.of(context).iconTheme.copyWith( - color: accentColor, - ), - channelHeaderTheme: ChannelHeaderTheme( - avatarTheme: AvatarTheme( - borderRadius: BorderRadius.circular(20), - constraints: BoxConstraints.tightFor( - height: 40, - width: 40, - ), - ), - color: Colors.white, - title: TextStyle( - fontSize: 14, - color: Colors.black, - ), - lastMessageAt: TextStyle( - fontSize: 11, - color: Colors.black.withOpacity(.5), - ), - ), - inputBackground: Colors.black.withAlpha(12), - inputGradient: LinearGradient(colors: [ - Color(0xFF00AEFF), - Color(0xFF0076FF), - ]), - ), - messageTheme: MessageTheme( - messageText: TextStyle( - fontSize: 15, - color: Colors.black, - ), - createdAt: TextStyle( - color: Colors.black.withOpacity(.5), - fontSize: 11, - ), - ownMessageBackgroundColor: Color(0xffebebeb), - otherMessageBackgroundColor: Colors.white, - avatarTheme: AvatarTheme( - borderRadius: BorderRadius.circular(20), - constraints: BoxConstraints.tightFor( - height: 32, - width: 32, - ), - ), - ), - ); - } - @override void initState() { super.initState(); diff --git a/lib/src/stream_chat_theme.dart b/lib/src/stream_chat_theme.dart index cbe1c6c1..d7ab1b4e 100644 --- a/lib/src/stream_chat_theme.dart +++ b/lib/src/stream_chat_theme.dart @@ -40,10 +40,23 @@ class StreamChatThemeData { }); factory StreamChatThemeData.fromTheme(ThemeData theme) { + final defaultTheme = getDefaultTheme(theme); + return StreamChatThemeData( accentColor: theme.accentColor, primaryColor: theme.colorScheme.primary, secondaryColor: theme.colorScheme.secondary, + channelTheme: ChannelTheme( + inputGradient: LinearGradient(colors: [ + theme.accentColor.withOpacity(.5), + theme.accentColor, + ]), + ), + messageTheme: MessageTheme( + replies: defaultTheme.messageTheme.replies.copyWith( + color: theme.accentColor, + ), + ), ); } @@ -63,6 +76,87 @@ class StreamChatThemeData { channelTheme: channelTheme ?? this.channelTheme, messageTheme: messageTheme ?? this.messageTheme, ); + + static StreamChatThemeData getDefaultTheme(ThemeData theme) { + final accentColor = Color(0xff006cff); + return StreamChatThemeData( + accentColor: accentColor, + primaryColor: Colors.white, + channelPreviewTheme: ChannelPreviewTheme( + avatarTheme: AvatarTheme( + borderRadius: BorderRadius.circular(20), + constraints: BoxConstraints.tightFor( + height: 40, + width: 40, + ), + ), + title: TextStyle( + fontSize: 14, + color: Colors.black, + ), + subtitle: TextStyle( + fontSize: 13, + color: Colors.black, + ), + lastMessageAt: TextStyle( + fontSize: 11, + color: Colors.black.withOpacity(.5), + ), + ), + channelTheme: ChannelTheme( + messageInputButtonIconTheme: theme.iconTheme.copyWith( + color: accentColor, + ), + channelHeaderTheme: ChannelHeaderTheme( + avatarTheme: AvatarTheme( + borderRadius: BorderRadius.circular(20), + constraints: BoxConstraints.tightFor( + height: 40, + width: 40, + ), + ), + color: Colors.white, + title: TextStyle( + fontSize: 14, + color: Colors.black, + ), + lastMessageAt: TextStyle( + fontSize: 11, + color: Colors.black.withOpacity(.5), + ), + ), + inputBackground: Colors.black.withAlpha(12), + inputGradient: LinearGradient(colors: [ + Color(0xFF00AEFF), + Color(0xFF0076FF), + ]), + ), + messageTheme: MessageTheme( + messageText: TextStyle( + fontSize: 15, + color: Colors.black, + ), + createdAt: TextStyle( + color: Colors.black.withOpacity(.5), + fontSize: 11, + ), + replies: TextStyle( + color: accentColor, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ownMessageBackgroundColor: Color(0xffebebeb), + otherMessageBackgroundColor: Colors.white, + avatarTheme: AvatarTheme( + borderRadius: BorderRadius.circular(20), + constraints: BoxConstraints.tightFor( + height: 32, + width: 32, + ), + ), + ), + ); + } } class ChannelTheme { @@ -122,12 +216,14 @@ class MessageTheme { final TextStyle messageAuthor; final TextStyle messageMention; final TextStyle createdAt; + final TextStyle replies; final String fontFamily; final Color ownMessageBackgroundColor; final Color otherMessageBackgroundColor; final AvatarTheme avatarTheme; const MessageTheme({ + this.replies, this.messageText, this.messageAuthor, this.messageMention, @@ -143,6 +239,7 @@ class MessageTheme { TextStyle messageAuthor, TextStyle messageMention, TextStyle createdAt, + TextStyle replies, String fontFamily, Color ownMessageBackgroundColor, Color otherMessageBackgroundColor, @@ -159,6 +256,7 @@ class MessageTheme { otherMessageBackgroundColor: otherMessageBackgroundColor ?? this.otherMessageBackgroundColor, avatarTheme: avatarTheme ?? this.avatarTheme, + replies: replies ?? this.replies, ); } diff --git a/pubspec.yaml b/pubspec.yaml index 816e660d..3ee0f8b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ dependencies: video_player: ^0.10.7 chewie: ^0.9.8+1 animations: ^1.0.0+3 - stream_chat: ^0.1.8 + stream_chat: ^0.1.10 dev_dependencies: pedantic: ^1.8.0+1