Merge pull request #152 from GetStream/feature/typingAnimation
This commit is contained in:
File diff suppressed because one or more lines are too long
+15
-8
@@ -215,7 +215,9 @@ class ChannelPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: ChannelHeader(),
|
appBar: ChannelHeader(
|
||||||
|
showTypingIndicator: false,
|
||||||
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -228,14 +230,19 @@ class ChannelPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Positioned.fill(
|
Positioned(
|
||||||
child: Padding(
|
bottom: 0,
|
||||||
padding: const EdgeInsets.symmetric(
|
left: 0,
|
||||||
horizontal: 8.0,
|
right: 0,
|
||||||
vertical: 4,
|
child: Container(
|
||||||
),
|
alignment: Alignment.centerLeft,
|
||||||
|
color: Color(0xffFCFCFC).withOpacity(.9),
|
||||||
child: TypingIndicator(
|
child: TypingIndicator(
|
||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.centerLeft,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -64,12 +64,16 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
/// Callback to call when the image is tapped.
|
/// Callback to call when the image is tapped.
|
||||||
final VoidCallback onImageTap;
|
final VoidCallback onImageTap;
|
||||||
|
|
||||||
|
/// If true the typing indicator will be rendered if a user is typing
|
||||||
|
final bool showTypingIndicator;
|
||||||
|
|
||||||
/// Creates a channel header
|
/// Creates a channel header
|
||||||
ChannelHeader({
|
ChannelHeader({
|
||||||
Key key,
|
Key key,
|
||||||
this.showBackButton = true,
|
this.showBackButton = true,
|
||||||
this.onBackPressed,
|
this.onBackPressed,
|
||||||
this.onTitleTap,
|
this.onTitleTap,
|
||||||
|
this.showTypingIndicator = true,
|
||||||
this.onImageTap,
|
this.onImageTap,
|
||||||
}) : preferredSize = Size.fromHeight(kToolbarHeight),
|
}) : preferredSize = Size.fromHeight(kToolbarHeight),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
@@ -116,6 +120,7 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 2),
|
SizedBox(height: 2),
|
||||||
ChannelInfo(
|
ChannelInfo(
|
||||||
|
showTypingIndicator: showTypingIndicator,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
textStyle:
|
textStyle:
|
||||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle,
|
StreamChatTheme.of(context).channelPreviewTheme.subtitle,
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ class ChannelInfo extends StatelessWidget {
|
|||||||
/// The style of the text displayed
|
/// The style of the text displayed
|
||||||
final TextStyle textStyle;
|
final TextStyle textStyle;
|
||||||
|
|
||||||
|
/// If true the typing indicator will be rendered if a user is typing
|
||||||
|
final bool showTypingIndicator;
|
||||||
|
|
||||||
const ChannelInfo({
|
const ChannelInfo({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.channel,
|
@required this.channel,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
|
this.showTypingIndicator = true,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -75,6 +79,10 @@ class ChannelInfo extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!showTypingIndicator) {
|
||||||
|
return alternativeWidget;
|
||||||
|
}
|
||||||
|
|
||||||
return TypingIndicator(
|
return TypingIndicator(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
alternativeWidget: alternativeWidget,
|
alternativeWidget: alternativeWidget,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:lottie/lottie.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ class TypingIndicator extends StatelessWidget {
|
|||||||
this.alternativeWidget,
|
this.alternativeWidget,
|
||||||
this.style,
|
this.style,
|
||||||
this.alignment = Alignment.centerLeft,
|
this.alignment = Alignment.centerLeft,
|
||||||
|
this.padding = const EdgeInsets.all(0),
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Style of the text widget
|
/// Style of the text widget
|
||||||
@@ -22,6 +24,9 @@ class TypingIndicator extends StatelessWidget {
|
|||||||
/// Widget built when no typings is happening
|
/// Widget built when no typings is happening
|
||||||
final Widget alternativeWidget;
|
final Widget alternativeWidget;
|
||||||
|
|
||||||
|
/// The padding of this widget
|
||||||
|
final EdgeInsets padding;
|
||||||
|
|
||||||
final Alignment alignment;
|
final Alignment alignment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -35,13 +40,26 @@ class TypingIndicator extends StatelessWidget {
|
|||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
duration: Duration(milliseconds: 300),
|
duration: Duration(milliseconds: 300),
|
||||||
child: snapshot.data?.isNotEmpty == true
|
child: snapshot.data?.isNotEmpty == true
|
||||||
? Align(
|
? Padding(
|
||||||
key: Key('typings'),
|
padding: padding,
|
||||||
alignment: alignment,
|
child: Align(
|
||||||
child: Text(
|
key: Key('typings'),
|
||||||
'${snapshot.data.map((u) => u.name).join(',')} ${snapshot.data.length == 1 ? 'is' : 'are'} typing...',
|
alignment: alignment,
|
||||||
maxLines: 1,
|
child: Row(
|
||||||
style: style,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Lottie.asset(
|
||||||
|
'animations/typing_dots.json',
|
||||||
|
package: 'stream_chat_flutter',
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
' ${snapshot.data.map((u) => u.name).join(',')} ${snapshot.data.length == 1 ? 'is' : 'are'} typing',
|
||||||
|
maxLines: 1,
|
||||||
|
style: style,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Align(
|
: Align(
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ dependencies:
|
|||||||
mime: ^0.9.6+3
|
mime: ^0.9.6+3
|
||||||
visibility_detector: ^0.1.5
|
visibility_detector: ^0.1.5
|
||||||
http_parser: ^3.1.4
|
http_parser: ^3.1.4
|
||||||
|
lottie: ^0.7.0+1
|
||||||
substring_highlight: ^0.1.2
|
substring_highlight: ^0.1.2
|
||||||
flutter_slidable: ^0.5.4
|
flutter_slidable: ^0.5.4
|
||||||
carousel_slider: ^2.2.1
|
carousel_slider: ^2.2.1
|
||||||
@@ -47,6 +48,7 @@ flutter:
|
|||||||
- images/
|
- images/
|
||||||
- svgs/
|
- svgs/
|
||||||
- lib/svgs/
|
- lib/svgs/
|
||||||
|
- animations/
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
pedantic: ^1.9.0
|
pedantic: ^1.9.0
|
||||||
|
|||||||
Reference in New Issue
Block a user