feat: Added animations for giphy and mentions
This commit is contained in:
+165
-137
@@ -536,86 +536,101 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
bottom: size.height + MediaQuery.of(context).viewInsets.bottom,
|
bottom: size.height + MediaQuery.of(context).viewInsets.bottom,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Padding(
|
child: TweenAnimationBuilder<double>(
|
||||||
padding: const EdgeInsets.all(8.0),
|
tween: Tween(begin: 0.0, end: 1.0),
|
||||||
child: Card(
|
duration: Duration(milliseconds: 300),
|
||||||
elevation: 2.0,
|
curve: Curves.easeInOutExpo,
|
||||||
shape: RoundedRectangleBorder(
|
builder: (context, val, wid) {
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
return Transform.scale(
|
||||||
),
|
alignment: Alignment.center,
|
||||||
color: StreamChatTheme.of(context).primaryColor,
|
scale: val,
|
||||||
clipBehavior: Clip.antiAlias,
|
child: Padding(
|
||||||
child: Container(
|
padding: const EdgeInsets.all(8.0),
|
||||||
constraints: BoxConstraints.loose(Size.fromHeight(400)),
|
child: Card(
|
||||||
decoration: BoxDecoration(
|
elevation: 2.0,
|
||||||
color: StreamChatTheme.of(context).primaryColor,
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8.0)),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
child: ListView(
|
),
|
||||||
padding: const EdgeInsets.all(0),
|
color: StreamChatTheme.of(context).primaryColor,
|
||||||
shrinkWrap: true,
|
clipBehavior: Clip.antiAlias,
|
||||||
children: [
|
child: Container(
|
||||||
if (commands.isNotEmpty)
|
constraints: BoxConstraints.loose(Size.fromHeight(400)),
|
||||||
Padding(
|
decoration: BoxDecoration(
|
||||||
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
|
color: StreamChatTheme.of(context).primaryColor,
|
||||||
child: Row(
|
borderRadius: BorderRadius.circular(8.0)),
|
||||||
|
child: ListView(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
shrinkWrap: true,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
if (commands.isNotEmpty)
|
||||||
padding:
|
Padding(
|
||||||
const EdgeInsets.symmetric(horizontal: 8.0),
|
padding:
|
||||||
child: Icon(
|
const EdgeInsets.only(left: 8.0, top: 8.0),
|
||||||
StreamIcons.lightning,
|
child: Row(
|
||||||
color: StreamChatTheme.of(context).accentColor,
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0),
|
||||||
|
child: Icon(
|
||||||
|
StreamIcons.lightning,
|
||||||
|
color: StreamChatTheme.of(context)
|
||||||
|
.accentColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Instant Commands',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black.withOpacity(.5),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
...commands
|
||||||
Text(
|
.map(
|
||||||
'Instant Commands',
|
(c) => ListTile(
|
||||||
style: TextStyle(
|
leading: c.name == 'giphy'
|
||||||
color: Colors.black.withOpacity(.5),
|
? _buildGiphyIcon()
|
||||||
),
|
: null,
|
||||||
)
|
title: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
text: '${c.name.capitalize()}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: ' /${c.name} ${c.args}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w300,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
StreamChatTheme.of(context).accentColor,
|
||||||
|
child: Icon(
|
||||||
|
StreamIcons.lightning,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 12.5,
|
||||||
|
),
|
||||||
|
maxRadius: 12,
|
||||||
|
),
|
||||||
|
//subtitle: Text(c.description),
|
||||||
|
onTap: () {
|
||||||
|
_setCommand(c);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...commands
|
),
|
||||||
.map(
|
),
|
||||||
(c) => ListTile(
|
);
|
||||||
leading: c.name == 'giphy' ? _buildGiphyIcon() : null,
|
}),
|
||||||
title: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
text: '${c.name.capitalize()}',
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: ' /${c.name} ${c.args}',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w300,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
StreamChatTheme.of(context).accentColor,
|
|
||||||
child: Icon(
|
|
||||||
StreamIcons.lightning,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 12.5,
|
|
||||||
),
|
|
||||||
maxRadius: 12,
|
|
||||||
),
|
|
||||||
//subtitle: Text(c.description),
|
|
||||||
onTap: () {
|
|
||||||
_setCommand(c);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -925,71 +940,84 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
bottom: size.height + MediaQuery.of(context).viewInsets.bottom,
|
bottom: size.height + MediaQuery.of(context).viewInsets.bottom,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Card(
|
child: TweenAnimationBuilder<double>(
|
||||||
margin: EdgeInsets.all(8.0),
|
tween: Tween(begin: 0.0, end: 1.0),
|
||||||
elevation: 2.0,
|
duration: Duration(milliseconds: 300),
|
||||||
color: StreamChatTheme.of(context).primaryColor,
|
curve: Curves.easeInOutExpo,
|
||||||
shape: RoundedRectangleBorder(
|
builder: (context, val, wid) {
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
return Transform.scale(
|
||||||
),
|
scale: val,
|
||||||
clipBehavior: Clip.antiAlias,
|
child: Card(
|
||||||
child: Container(
|
margin: EdgeInsets.all(8.0),
|
||||||
constraints: BoxConstraints.loose(Size.fromHeight(400)),
|
elevation: 2.0,
|
||||||
decoration: BoxDecoration(
|
color: StreamChatTheme.of(context).primaryColor,
|
||||||
color: StreamChatTheme.of(context).primaryColor,
|
shape: RoundedRectangleBorder(
|
||||||
),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
child: FutureBuilder<List<Member>>(
|
),
|
||||||
future: queryMembers ?? Future.value(members),
|
clipBehavior: Clip.antiAlias,
|
||||||
initialData: members,
|
child: Container(
|
||||||
builder: (context, snapshot) {
|
constraints: BoxConstraints.loose(Size.fromHeight(400)),
|
||||||
return ListView(
|
decoration: BoxDecoration(
|
||||||
padding: const EdgeInsets.all(0),
|
color: StreamChatTheme.of(context).primaryColor,
|
||||||
shrinkWrap: true,
|
),
|
||||||
children: snapshot.data
|
child: FutureBuilder<List<Member>>(
|
||||||
.map((m) => ListTile(
|
future: queryMembers ?? Future.value(members),
|
||||||
leading: UserAvatar(
|
initialData: members,
|
||||||
constraints: BoxConstraints.tight(
|
builder: (context, snapshot) {
|
||||||
Size(
|
return ListView(
|
||||||
40,
|
padding: const EdgeInsets.all(0),
|
||||||
40,
|
shrinkWrap: true,
|
||||||
),
|
children: snapshot.data
|
||||||
),
|
.map((m) => ListTile(
|
||||||
user: m.user,
|
leading: UserAvatar(
|
||||||
),
|
constraints: BoxConstraints.tight(
|
||||||
title: Text(
|
Size(
|
||||||
'${m.user.name}',
|
40,
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
40,
|
||||||
),
|
),
|
||||||
subtitle: Text('@${m.userId}'),
|
),
|
||||||
trailing: Icon(
|
user: m.user,
|
||||||
StreamIcons.at_mention,
|
),
|
||||||
color: StreamChatTheme.of(context).accentColor,
|
title: Text(
|
||||||
),
|
'${m.user.name}',
|
||||||
onTap: () {
|
style: TextStyle(
|
||||||
_mentionedUsers.add(m.user);
|
fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
subtitle: Text('@${m.userId}'),
|
||||||
|
trailing: Icon(
|
||||||
|
StreamIcons.at_mention,
|
||||||
|
color: StreamChatTheme.of(context)
|
||||||
|
.accentColor,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
_mentionedUsers.add(m.user);
|
||||||
|
|
||||||
splits[splits.length - 1] = m.user.name;
|
splits[splits.length - 1] = m.user.name;
|
||||||
final rejoin = splits.join('@');
|
final rejoin = splits.join('@');
|
||||||
|
|
||||||
textEditingController.value = TextEditingValue(
|
textEditingController.value =
|
||||||
text: rejoin +
|
TextEditingValue(
|
||||||
textEditingController.text.substring(
|
text: rejoin +
|
||||||
textEditingController
|
textEditingController.text
|
||||||
.selection.start),
|
.substring(
|
||||||
selection: TextSelection.collapsed(
|
textEditingController
|
||||||
offset: rejoin.length,
|
.selection.start),
|
||||||
),
|
selection: TextSelection.collapsed(
|
||||||
);
|
offset: rejoin.length,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
_mentionsOverlay?.remove();
|
_mentionsOverlay?.remove();
|
||||||
_mentionsOverlay = null;
|
_mentionsOverlay = null;
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user