This commit is contained in:
Deven Joshi
2021-05-05 17:23:30 +05:30
parent d63540ba9b
commit 9d05cd20e0
3 changed files with 142 additions and 132 deletions
@@ -1,27 +1,38 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'stream_chat_theme.dart'; /// Widget to make a swipeable tile
///
class Swipeable extends StatefulWidget { class Swipeable extends StatefulWidget {
final Widget child; /// Constructor for creating a [Swipeable] widget
final Widget backgroundIcon;
final VoidCallback? onSwipeStart;
final VoidCallback? onSwipeCancel;
final VoidCallback? onSwipeEnd;
final double threshold;
///
const Swipeable({ const Swipeable({
Key? key,
required this.child, required this.child,
required this.backgroundIcon, required this.backgroundIcon,
this.onSwipeStart, this.onSwipeStart,
this.onSwipeCancel, this.onSwipeCancel,
this.onSwipeEnd, this.onSwipeEnd,
this.threshold = 82.0, this.threshold = 82.0,
}); }) : super(key: key);
/// Child to make swipeable
final Widget child;
/// Background icon after swipe
final Widget backgroundIcon;
/// Callback when swipe starts
final VoidCallback? onSwipeStart;
/// Callback when swipe is cancelled
final VoidCallback? onSwipeCancel;
/// Callback when swipe ends
final VoidCallback? onSwipeEnd;
/// Threshold for swipe
final double threshold;
@override @override
State<StatefulWidget> createState() => _SwipeableState(); State<StatefulWidget> createState() => _SwipeableState();
@@ -45,10 +56,10 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin {
AnimationController(duration: _animationDuration, vsync: this); AnimationController(duration: _animationDuration, vsync: this);
_iconMoveController = _iconMoveController =
AnimationController(duration: _animationDuration, vsync: this); AnimationController(duration: _animationDuration, vsync: this);
_moveAnimation = Tween<Offset>(begin: Offset.zero, end: Offset(1, 0)) _moveAnimation = Tween<Offset>(begin: Offset.zero, end: const Offset(1, 0))
.animate(_moveController); .animate(_moveController);
_iconTransitionAnimation = _iconTransitionAnimation =
Tween<Offset>(begin: Offset(-0.1, 0), end: Offset(0.4, 0)) Tween<Offset>(begin: const Offset(-0.1, 0), end: const Offset(0.4, 0))
.animate(_moveController); .animate(_moveController);
_iconFadeAnimation = _iconFadeAnimation =
Tween<double>(begin: 0.7, end: 1).animate(_iconMoveController); Tween<double>(begin: 0.7, end: 1).animate(_iconMoveController);
@@ -120,44 +131,42 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin {
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => GestureDetector(
return GestureDetector( onHorizontalDragStart: _handleDragStart,
onHorizontalDragStart: _handleDragStart, onHorizontalDragUpdate: _handleDragUpdate,
onHorizontalDragUpdate: _handleDragUpdate, onHorizontalDragEnd: _handleDragEnd,
onHorizontalDragEnd: _handleDragEnd, behavior: HitTestBehavior.opaque,
behavior: HitTestBehavior.opaque, child: Stack(
child: Stack( alignment: Alignment.center,
alignment: Alignment.center, fit: StackFit.passthrough,
fit: StackFit.passthrough, children: [
children: [ SlideTransition(
SlideTransition( position: _iconTransitionAnimation,
position: _iconTransitionAnimation, child: Row(
child: Row( children: [
children: [ FadeTransition(
FadeTransition( opacity: _iconFadeAnimation,
opacity: _iconFadeAnimation, child: Container(
child: Container( padding: const EdgeInsets.all(4),
padding: const EdgeInsets.all(4), decoration: BoxDecoration(
decoration: BoxDecoration( shape: BoxShape.circle,
shape: BoxShape.circle, border: Border.all(
border: Border.all( color: StreamChatTheme.of(context)
color: StreamChatTheme.of(context) .colorTheme
.colorTheme .greyGainsboro,
.greyGainsboro, ),
), ),
child: widget.backgroundIcon,
), ),
child: widget.backgroundIcon,
), ),
), ],
], ),
), ),
), SlideTransition(
SlideTransition( position: _moveAnimation,
position: _moveAnimation, child: widget.child,
child: widget.child, ),
), ],
], ),
), );
);
}
} }
@@ -3,18 +3,20 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// It shows a date divider depending on the date difference /// It shows a date divider depending on the date difference
class SystemMessage extends StatelessWidget { class SystemMessage extends StatelessWidget {
/// This message /// Constructor for creating a [SystemMessage]
final Message message;
/// The function called when tapping on the message when the message is not failed
final void Function(Message)? onMessageTap;
const SystemMessage({ const SystemMessage({
Key? key, Key? key,
required this.message, required this.message,
this.onMessageTap, this.onMessageTap,
}) : super(key: key); }) : super(key: key);
/// This message
final Message message;
// ignore: lines_longer_than_80_chars
/// The function called when tapping on the message when the message is not failed
final void Function(Message)? onMessageTap;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = StreamChatTheme.of(context); final theme = StreamChatTheme.of(context);
@@ -3,9 +3,6 @@ import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'back_button.dart';
import 'channel_name.dart';
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/thread_header.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/thread_header.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/thread_header_paint.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/thread_header_paint.png)
/// ///
@@ -46,16 +43,34 @@ import 'channel_name.dart';
/// Usually you would use this widget as an [AppBar] inside a [Scaffold]. /// Usually you would use this widget as an [AppBar] inside a [Scaffold].
/// However you can also use it as a normal widget. /// However you can also use it as a normal widget.
/// ///
/// Make sure to have a [StreamChannel] ancestor in order to provide the information about the channel. /// Make sure to have a [StreamChannel] ancestor in order to provide the
/// Every part of the widget uses a [StreamBuilder] to render the channel information as soon as it updates. /// information about the channel.
/// Every part of the widget uses a [StreamBuilder] to render the channel
/// information as soon as it updates.
/// ///
/// By default the widget shows a backButton that calls [Navigator.pop]. /// By default the widget shows a backButton that calls [Navigator.pop].
/// You can disable this button using the [showBackButton] property of just override the behaviour /// You can disable this button using the [showBackButton] property of just
/// override the behaviour
/// with [onBackPressed]. /// with [onBackPressed].
/// ///
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property. /// The widget components render the ui based on the first ancestor of type
/// [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property.
/// Modify it to change the widget appearance. /// Modify it to change the widget appearance.
class ThreadHeader extends StatelessWidget implements PreferredSizeWidget { class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
/// Instantiate a new ThreadHeader
const ThreadHeader({
Key? key,
required this.parent,
this.showBackButton = true,
this.onBackPressed,
this.title,
this.subtitle,
this.leading,
this.actions,
this.onTitleTap,
}) : preferredSize = const Size.fromHeight(kToolbarHeight),
super(key: key);
/// True if this header shows the leading back button /// True if this header shows the leading back button
final bool showBackButton; final bool showBackButton;
@@ -81,82 +96,66 @@ class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
/// AppBar actions /// AppBar actions
final List<Widget>? actions; final List<Widget>? actions;
/// Instantiate a new ThreadHeader
ThreadHeader({
Key? key,
required this.parent,
this.showBackButton = true,
this.onBackPressed,
this.title,
this.subtitle,
this.leading,
this.actions,
this.onTitleTap,
}) : preferredSize = Size.fromHeight(kToolbarHeight),
super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => AppBar(
return AppBar( automaticallyImplyLeading: false,
automaticallyImplyLeading: false, brightness: Theme.of(context).brightness,
brightness: Theme.of(context).brightness, elevation: 1,
elevation: 1, leading: leading ??
leading: leading ?? (showBackButton
(showBackButton ? StreamBackButton(
? StreamBackButton( cid: StreamChannel.of(context).channel.cid,
cid: StreamChannel.of(context).channel.cid, onPressed: onBackPressed,
onPressed: onBackPressed, showUnreads: true,
showUnreads: true, )
) : const SizedBox()),
: SizedBox()), backgroundColor:
backgroundColor: StreamChatTheme.of(context).channelTheme.channelHeaderTheme.color,
StreamChatTheme.of(context).channelTheme.channelHeaderTheme.color, centerTitle: true,
centerTitle: true, actions: actions,
actions: actions, title: InkWell(
title: InkWell( onTap: onTitleTap,
onTap: onTitleTap, child: SizedBox(
child: Container( height: preferredSize.height,
height: preferredSize.height, child: Column(
child: Column( mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, children: [
children: [ title ??
title ?? Text(
Text( 'Thread Reply',
'Thread Reply', style: StreamChatTheme.of(context)
style: StreamChatTheme.of(context) .channelTheme
.channelTheme .channelHeaderTheme
.channelHeaderTheme .title,
.title, ),
), const SizedBox(height: 2),
SizedBox(height: 2), subtitle ??
subtitle ?? Row(
Row( mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, children: [
children: [ Text(
Text( 'with ',
'with ', style: StreamChatTheme.of(context)
style: StreamChatTheme.of(context)
.channelTheme
.channelHeaderTheme
.subtitle,
),
Flexible(
child: ChannelName(
textStyle: StreamChatTheme.of(context)
.channelTheme .channelTheme
.channelHeaderTheme .channelHeaderTheme
.subtitle, .subtitle,
), ),
), Flexible(
], child: ChannelName(
), textStyle: StreamChatTheme.of(context)
], .channelTheme
.channelHeaderTheme
.subtitle,
),
),
],
),
],
),
), ),
), ),
), );
);
}
@override @override
final Size preferredSize; final Size preferredSize;