mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-12-18 02:42:34 +01:00
fix: Emoji picker
This commit is contained in:
parent
37c40a2cb5
commit
e1bd4e174c
@ -3,7 +3,6 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
|
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:file_picker_cross/file_picker_cross.dart';
|
import 'package:file_picker_cross/file_picker_cross.dart';
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
@ -23,7 +22,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:scroll_to_index/scroll_to_index.dart';
|
import 'package:scroll_to_index/scroll_to_index.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import 'send_file_dialog.dart';
|
import 'send_file_dialog.dart';
|
||||||
@ -78,6 +76,8 @@ class ChatController extends State<Chat> {
|
|||||||
|
|
||||||
bool get canLoadMore => timeline.events.last.type != EventTypes.RoomCreate;
|
bool get canLoadMore => timeline.events.last.type != EventTypes.RoomCreate;
|
||||||
|
|
||||||
|
bool showEmojiPicker = false;
|
||||||
|
|
||||||
void startCallAction() async {
|
void startCallAction() async {
|
||||||
final url =
|
final url =
|
||||||
'${AppConfig.jitsiInstance}${Uri.encodeComponent(Matrix.of(context).client.generateUniqueTransactionId())}';
|
'${AppConfig.jitsiInstance}${Uri.encodeComponent(Matrix.of(context).client.generateUniqueTransactionId())}';
|
||||||
@ -478,39 +478,24 @@ class ChatController extends State<Chat> {
|
|||||||
|
|
||||||
void scrollDown() => scrollController.jumpTo(0);
|
void scrollDown() => scrollController.jumpTo(0);
|
||||||
|
|
||||||
void pickEmojiAction(Iterable<Event> allReactionEvents) async {
|
void onEmojiSelected(category, emoji) {
|
||||||
final emoji = await showModalBottomSheet(
|
setState(() => showEmojiPicker = false);
|
||||||
context: context,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
builder: (innerContext) => Column(
|
|
||||||
children: [
|
|
||||||
Spacer(),
|
|
||||||
Material(
|
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
child: EmojiPicker(
|
|
||||||
onEmojiSelected: (category, emoji) {
|
|
||||||
// recent emojis don't work, so we sadly have to re-implement them
|
|
||||||
// https://github.com/JeffG05/emoji_picker/issues/31
|
|
||||||
SharedPreferences.getInstance().then((prefs) {
|
|
||||||
final recents = prefs.getStringList('recents') ?? <String>[];
|
|
||||||
recents.insert(0, emoji.name);
|
|
||||||
// make sure we remove duplicates
|
|
||||||
prefs.setStringList('recents', recents.toSet().toList());
|
|
||||||
});
|
|
||||||
Navigator.of(innerContext, rootNavigator: false).pop(emoji);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (emoji == null) return;
|
if (emoji == null) return;
|
||||||
// make sure we don't send the same emoji twice
|
// make sure we don't send the same emoji twice
|
||||||
if (allReactionEvents
|
if (_allReactionEvents
|
||||||
.any((e) => e.content['m.relates_to']['key'] == emoji.emoji)) return;
|
.any((e) => e.content['m.relates_to']['key'] == emoji.emoji)) return;
|
||||||
return sendEmojiAction(emoji.emoji);
|
return sendEmojiAction(emoji.emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Iterable<Event> _allReactionEvents;
|
||||||
|
|
||||||
|
void cancelEmojiPicker() => setState(() => showEmojiPicker = false);
|
||||||
|
|
||||||
|
void pickEmojiAction(Iterable<Event> allReactionEvents) async {
|
||||||
|
_allReactionEvents = allReactionEvents;
|
||||||
|
setState(() => showEmojiPicker = true);
|
||||||
|
}
|
||||||
|
|
||||||
void sendEmojiAction(String emoji) async {
|
void sendEmojiAction(String emoji) async {
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -522,7 +507,10 @@ class ChatController extends State<Chat> {
|
|||||||
setState(() => selectedEvents.clear());
|
setState(() => selectedEvents.clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearSelectedEvents() => setState(() => selectedEvents.clear());
|
void clearSelectedEvents() => setState(() {
|
||||||
|
selectedEvents.clear();
|
||||||
|
showEmojiPicker = false;
|
||||||
|
});
|
||||||
|
|
||||||
void editSelectedEventAction() {
|
void editSelectedEventAction() {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:math';
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
|
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/views/chat.dart';
|
import 'package:fluffychat/views/chat.dart';
|
||||||
import 'package:fluffychat/views/widgets/avatar.dart';
|
import 'package:fluffychat/views/widgets/avatar.dart';
|
||||||
@ -415,68 +416,70 @@ class ChatUI extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
AnimatedContainer(
|
if (!controller.showEmojiPicker)
|
||||||
duration: Duration(milliseconds: 300),
|
AnimatedContainer(
|
||||||
height: (controller.editEvent == null &&
|
duration: Duration(milliseconds: 300),
|
||||||
controller.replyEvent == null &&
|
height: (controller.editEvent == null &&
|
||||||
controller.room.canSendDefaultMessages &&
|
controller.replyEvent == null &&
|
||||||
controller.selectedEvents.length == 1)
|
controller.room.canSendDefaultMessages &&
|
||||||
? 56
|
controller.selectedEvents.length == 1)
|
||||||
: 0,
|
? 56
|
||||||
child: Material(
|
: 0,
|
||||||
color: Theme.of(context).secondaryHeaderColor,
|
child: Material(
|
||||||
child: Builder(builder: (context) {
|
color: Theme.of(context).secondaryHeaderColor,
|
||||||
if (!(controller.editEvent == null &&
|
child: Builder(builder: (context) {
|
||||||
controller.replyEvent == null &&
|
if (!(controller.editEvent == null &&
|
||||||
controller.selectedEvents.length == 1)) {
|
controller.replyEvent == null &&
|
||||||
return Container();
|
controller.selectedEvents.length == 1)) {
|
||||||
}
|
return Container();
|
||||||
final emojis = List<String>.from(AppEmojis.emojis);
|
}
|
||||||
final allReactionEvents = controller.selectedEvents.first
|
final emojis = List<String>.from(AppEmojis.emojis);
|
||||||
.aggregatedEvents(
|
final allReactionEvents = controller
|
||||||
controller.timeline, RelationshipTypes.reaction)
|
.selectedEvents.first
|
||||||
?.where((event) =>
|
.aggregatedEvents(
|
||||||
event.senderId == event.room.client.userID &&
|
controller.timeline, RelationshipTypes.reaction)
|
||||||
event.type == 'm.reaction');
|
?.where((event) =>
|
||||||
|
event.senderId == event.room.client.userID &&
|
||||||
|
event.type == 'm.reaction');
|
||||||
|
|
||||||
allReactionEvents.forEach((event) {
|
allReactionEvents.forEach((event) {
|
||||||
try {
|
try {
|
||||||
emojis.remove(event.content['m.relates_to']['key']);
|
emojis.remove(event.content['m.relates_to']['key']);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
});
|
});
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemCount: emojis.length + 1,
|
itemCount: emojis.length + 1,
|
||||||
itemBuilder: (c, i) => i == emojis.length
|
itemBuilder: (c, i) => i == emojis.length
|
||||||
? InkWell(
|
? InkWell(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
onTap: () => controller
|
onTap: () => controller
|
||||||
.pickEmojiAction(allReactionEvents),
|
.pickEmojiAction(allReactionEvents),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 56,
|
width: 56,
|
||||||
height: 56,
|
height: 56,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Icon(Icons.add_outlined),
|
child: Icon(Icons.add_outlined),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: InkWell(
|
: InkWell(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
controller.sendEmojiAction(emojis[i]),
|
controller.sendEmojiAction(emojis[i]),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 56,
|
width: 56,
|
||||||
height: 56,
|
height: 56,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Text(
|
child: Text(
|
||||||
emojis[i],
|
emojis[i],
|
||||||
style: TextStyle(fontSize: 30),
|
style: TextStyle(fontSize: 30),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}),
|
||||||
}),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
AnimatedContainer(
|
AnimatedContainer(
|
||||||
duration: Duration(milliseconds: 300),
|
duration: Duration(milliseconds: 300),
|
||||||
height: controller.editEvent != null ||
|
height: controller.editEvent != null ||
|
||||||
@ -507,204 +510,207 @@ class ChatUI extends StatelessWidget {
|
|||||||
height: 1,
|
height: 1,
|
||||||
thickness: 1,
|
thickness: 1,
|
||||||
),
|
),
|
||||||
controller.room.canSendDefaultMessages &&
|
if (controller.room.canSendDefaultMessages &&
|
||||||
controller.room.membership == Membership.join
|
controller.room.membership == Membership.join &&
|
||||||
? Container(
|
!controller.showEmojiPicker)
|
||||||
decoration: BoxDecoration(
|
Container(
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
decoration: BoxDecoration(
|
||||||
),
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
child: Row(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: controller.selectMode
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
? <Widget>[
|
children: controller.selectMode
|
||||||
Container(
|
? <Widget>[
|
||||||
height: 56,
|
Container(
|
||||||
child: TextButton(
|
height: 56,
|
||||||
onPressed: controller.forwardEventsAction,
|
child: TextButton(
|
||||||
child: Row(
|
onPressed: controller.forwardEventsAction,
|
||||||
children: <Widget>[
|
child: Row(
|
||||||
Icon(Icons
|
children: <Widget>[
|
||||||
.keyboard_arrow_left_outlined),
|
Icon(Icons.keyboard_arrow_left_outlined),
|
||||||
Text(L10n.of(context).forward),
|
Text(L10n.of(context).forward),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
controller.selectedEvents.length == 1
|
),
|
||||||
? controller.selectedEvents.first
|
),
|
||||||
.getDisplayEvent(
|
controller.selectedEvents.length == 1
|
||||||
controller.timeline)
|
? controller.selectedEvents.first
|
||||||
.status >
|
.getDisplayEvent(
|
||||||
0
|
controller.timeline)
|
||||||
? Container(
|
.status >
|
||||||
height: 56,
|
0
|
||||||
child: TextButton(
|
? Container(
|
||||||
onPressed:
|
height: 56,
|
||||||
controller.replyAction,
|
child: TextButton(
|
||||||
child: Row(
|
onPressed: controller.replyAction,
|
||||||
children: <Widget>[
|
child: Row(
|
||||||
Text(
|
children: <Widget>[
|
||||||
L10n.of(context).reply),
|
Text(L10n.of(context).reply),
|
||||||
Icon(Icons
|
Icon(
|
||||||
.keyboard_arrow_right),
|
Icons.keyboard_arrow_right),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
height: 56,
|
|
||||||
child: TextButton(
|
|
||||||
onPressed:
|
|
||||||
controller.sendAgainAction,
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Text(L10n.of(context)
|
|
||||||
.tryToSendAgain),
|
|
||||||
SizedBox(width: 4),
|
|
||||||
Icon(Icons.send_outlined,
|
|
||||||
size: 16),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
]
|
|
||||||
: <Widget>[
|
|
||||||
AnimatedContainer(
|
|
||||||
duration: Duration(milliseconds: 200),
|
|
||||||
height: 56,
|
|
||||||
width:
|
|
||||||
controller.inputText.isEmpty ? 56 : 0,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
clipBehavior: Clip.hardEdge,
|
|
||||||
decoration: BoxDecoration(),
|
|
||||||
child: PopupMenuButton<String>(
|
|
||||||
icon: Icon(Icons.add_outlined),
|
|
||||||
onSelected: controller
|
|
||||||
.onAddPopupMenuButtonSelected,
|
|
||||||
itemBuilder: (BuildContext context) =>
|
|
||||||
<PopupMenuEntry<String>>[
|
|
||||||
PopupMenuItem<String>(
|
|
||||||
value: 'file',
|
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
child: Icon(
|
|
||||||
Icons.attachment_outlined),
|
|
||||||
),
|
),
|
||||||
title:
|
|
||||||
Text(L10n.of(context).sendFile),
|
|
||||||
contentPadding: EdgeInsets.all(0),
|
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
height: 56,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed:
|
||||||
|
controller.sendAgainAction,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(L10n.of(context)
|
||||||
|
.tryToSendAgain),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Icon(Icons.send_outlined,
|
||||||
|
size: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
]
|
||||||
|
: <Widget>[
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: Duration(milliseconds: 200),
|
||||||
|
height: 56,
|
||||||
|
width: controller.inputText.isEmpty ? 56 : 0,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
clipBehavior: Clip.hardEdge,
|
||||||
|
decoration: BoxDecoration(),
|
||||||
|
child: PopupMenuButton<String>(
|
||||||
|
icon: Icon(Icons.add_outlined),
|
||||||
|
onSelected:
|
||||||
|
controller.onAddPopupMenuButtonSelected,
|
||||||
|
itemBuilder: (BuildContext context) =>
|
||||||
|
<PopupMenuEntry<String>>[
|
||||||
|
PopupMenuItem<String>(
|
||||||
|
value: 'file',
|
||||||
|
child: ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
child:
|
||||||
|
Icon(Icons.attachment_outlined),
|
||||||
),
|
),
|
||||||
PopupMenuItem<String>(
|
title: Text(L10n.of(context).sendFile),
|
||||||
value: 'image',
|
contentPadding: EdgeInsets.all(0),
|
||||||
child: ListTile(
|
),
|
||||||
leading: CircleAvatar(
|
),
|
||||||
backgroundColor: Colors.blue,
|
PopupMenuItem<String>(
|
||||||
foregroundColor: Colors.white,
|
value: 'image',
|
||||||
child: Icon(Icons.image_outlined),
|
child: ListTile(
|
||||||
),
|
leading: CircleAvatar(
|
||||||
title: Text(
|
backgroundColor: Colors.blue,
|
||||||
L10n.of(context).sendImage),
|
foregroundColor: Colors.white,
|
||||||
contentPadding: EdgeInsets.all(0),
|
child: Icon(Icons.image_outlined),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (PlatformInfos.isMobile)
|
title: Text(L10n.of(context).sendImage),
|
||||||
PopupMenuItem<String>(
|
contentPadding: EdgeInsets.all(0),
|
||||||
value: 'camera',
|
),
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: Colors.purple,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
child: Icon(
|
|
||||||
Icons.camera_alt_outlined),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context).openCamera),
|
|
||||||
contentPadding: EdgeInsets.all(0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (PlatformInfos.isMobile)
|
|
||||||
PopupMenuItem<String>(
|
|
||||||
value: 'voice',
|
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
child: Icon(
|
|
||||||
Icons.mic_none_outlined),
|
|
||||||
),
|
|
||||||
title: Text(L10n.of(context)
|
|
||||||
.voiceMessage),
|
|
||||||
contentPadding: EdgeInsets.all(0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
if (PlatformInfos.isMobile)
|
||||||
Container(
|
PopupMenuItem<String>(
|
||||||
height: 56,
|
value: 'camera',
|
||||||
alignment: Alignment.center,
|
child: ListTile(
|
||||||
child: EncryptionButton(controller.room),
|
leading: CircleAvatar(
|
||||||
),
|
backgroundColor: Colors.purple,
|
||||||
Expanded(
|
foregroundColor: Colors.white,
|
||||||
child: Padding(
|
child:
|
||||||
padding: const EdgeInsets.symmetric(
|
Icon(Icons.camera_alt_outlined),
|
||||||
vertical: 4.0),
|
),
|
||||||
child: InputBar(
|
title:
|
||||||
room: controller.room,
|
Text(L10n.of(context).openCamera),
|
||||||
minLines: 1,
|
contentPadding: EdgeInsets.all(0),
|
||||||
maxLines: kIsWeb ? 1 : 8,
|
|
||||||
autofocus: !PlatformInfos.isMobile,
|
|
||||||
keyboardType: !PlatformInfos.isMobile
|
|
||||||
? TextInputType.text
|
|
||||||
: TextInputType.multiline,
|
|
||||||
onSubmitted:
|
|
||||||
controller.onInputBarSubmitted,
|
|
||||||
focusNode: controller.inputFocus,
|
|
||||||
controller: controller.sendController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText:
|
|
||||||
L10n.of(context).writeAMessage,
|
|
||||||
hintMaxLines: 1,
|
|
||||||
border: InputBorder.none,
|
|
||||||
enabledBorder: InputBorder.none,
|
|
||||||
filled: false,
|
|
||||||
),
|
),
|
||||||
onChanged: controller.onInputBarChanged,
|
|
||||||
),
|
),
|
||||||
|
if (PlatformInfos.isMobile)
|
||||||
|
PopupMenuItem<String>(
|
||||||
|
value: 'voice',
|
||||||
|
child: ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
child:
|
||||||
|
Icon(Icons.mic_none_outlined),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context).voiceMessage),
|
||||||
|
contentPadding: EdgeInsets.all(0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 56,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: EncryptionButton(controller.room),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: InputBar(
|
||||||
|
room: controller.room,
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: kIsWeb ? 1 : 8,
|
||||||
|
autofocus: !PlatformInfos.isMobile,
|
||||||
|
keyboardType: !PlatformInfos.isMobile
|
||||||
|
? TextInputType.text
|
||||||
|
: TextInputType.multiline,
|
||||||
|
onSubmitted: controller.onInputBarSubmitted,
|
||||||
|
focusNode: controller.inputFocus,
|
||||||
|
controller: controller.sendController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: L10n.of(context).writeAMessage,
|
||||||
|
hintMaxLines: 1,
|
||||||
|
border: InputBorder.none,
|
||||||
|
enabledBorder: InputBorder.none,
|
||||||
|
filled: false,
|
||||||
),
|
),
|
||||||
|
onChanged: controller.onInputBarChanged,
|
||||||
),
|
),
|
||||||
if (PlatformInfos.isMobile &&
|
),
|
||||||
controller.inputText.isEmpty)
|
),
|
||||||
Container(
|
if (PlatformInfos.isMobile &&
|
||||||
height: 56,
|
controller.inputText.isEmpty)
|
||||||
alignment: Alignment.center,
|
Container(
|
||||||
child: IconButton(
|
height: 56,
|
||||||
tooltip: L10n.of(context).voiceMessage,
|
alignment: Alignment.center,
|
||||||
icon: Icon(Icons.mic_none_outlined),
|
child: IconButton(
|
||||||
onPressed:
|
tooltip: L10n.of(context).voiceMessage,
|
||||||
controller.voiceMessageAction,
|
icon: Icon(Icons.mic_none_outlined),
|
||||||
),
|
onPressed: controller.voiceMessageAction,
|
||||||
),
|
),
|
||||||
if (!PlatformInfos.isMobile ||
|
),
|
||||||
controller.inputText.isNotEmpty)
|
if (!PlatformInfos.isMobile ||
|
||||||
Container(
|
controller.inputText.isNotEmpty)
|
||||||
height: 56,
|
Container(
|
||||||
alignment: Alignment.center,
|
height: 56,
|
||||||
child: IconButton(
|
alignment: Alignment.center,
|
||||||
icon: Icon(Icons.send_outlined),
|
child: IconButton(
|
||||||
onPressed: controller.send,
|
icon: Icon(Icons.send_outlined),
|
||||||
tooltip: L10n.of(context).send,
|
onPressed: controller.send,
|
||||||
),
|
tooltip: L10n.of(context).send,
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
)
|
),
|
||||||
: Container(),
|
),
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: Duration(milliseconds: 300),
|
||||||
|
height: controller.showEmojiPicker
|
||||||
|
? MediaQuery.of(context).size.height / 2
|
||||||
|
: 0,
|
||||||
|
child: controller.showEmojiPicker
|
||||||
|
? EmojiPicker(
|
||||||
|
onEmojiSelected: controller.onEmojiSelected,
|
||||||
|
onBackspacePressed: controller.cancelEmojiPicker,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -217,7 +217,7 @@ packages:
|
|||||||
name: emoji_picker_flutter
|
name: emoji_picker_flutter
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.5"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,7 @@ dependencies:
|
|||||||
cupertino_icons: any
|
cupertino_icons: any
|
||||||
desktop_notifications: ^0.4.0
|
desktop_notifications: ^0.4.0
|
||||||
email_validator: ^2.0.1
|
email_validator: ^2.0.1
|
||||||
emoji_picker_flutter: ^1.0.3
|
emoji_picker_flutter: ^1.0.5
|
||||||
famedlysdk:
|
famedlysdk:
|
||||||
git:
|
git:
|
||||||
url: https://gitlab.com/famedly/famedlysdk.git
|
url: https://gitlab.com/famedly/famedlysdk.git
|
||||||
|
Loading…
Reference in New Issue
Block a user