double tap on messages to show options #63
@ -99,6 +99,167 @@ class _ChatBubbleState extends State<ChatBubble> {
|
||||
}
|
||||
}
|
||||
|
||||
void showOptionsDialog() {
|
||||
showDialog(context: context, builder: (context) {
|
||||
var commonReactions = <String>['👍', '👎', '😆', '❤️', '👀'];
|
||||
var canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment;
|
||||
return SimpleDialog(
|
||||
children: [
|
||||
Visibility(
|
||||
visible: canReact,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
...commonReactions.map((e) => TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
minimumSize: const Size(40, 40)
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
ReactMessage(
|
||||
chatToken: widget.chatData.token,
|
||||
messageId: widget.bubbleData.id,
|
||||
params: ReactMessageParams(e),
|
||||
).run().then((value) => widget.refetch(renew: true));
|
||||
},
|
||||
child: Text(e),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
contentPadding: const EdgeInsets.all(15),
|
||||
titlePadding: const EdgeInsets.only(left: 6, top: 15),
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
const Text('Reagieren'),
|
||||
],
|
||||
),
|
||||
content: SizedBox(
|
||||
width: 256,
|
||||
height: 270,
|
||||
child: Column(
|
||||
children: [
|
||||
emojis.EmojiPicker(
|
||||
config: emojis.Config(
|
||||
height: 256,
|
||||
swapCategoryAndBottomBar: true,
|
||||
emojiViewConfig: emojis.EmojiViewConfig(
|
||||
backgroundColor: Theme.of(context).canvasColor,
|
||||
recentsLimit: 67,
|
||||
emojiSizeMax: 25,
|
||||
noRecents: const Text('Keine zuletzt verwendeten Emojis'),
|
||||
columns: 7,
|
||||
),
|
||||
bottomActionBarConfig: const emojis.BottomActionBarConfig(
|
||||
enabled: false,
|
||||
),
|
||||
categoryViewConfig: emojis.CategoryViewConfig(
|
||||
backgroundColor: Theme.of(context).hoverColor,
|
||||
iconColorSelected: Theme.of(context).primaryColor,
|
||||
indicatorColor: Theme.of(context).primaryColor,
|
||||
),
|
||||
searchViewConfig: emojis.SearchViewConfig(
|
||||
backgroundColor: Theme.of(context).dividerColor,
|
||||
buttonColor: Theme.of(context).dividerColor,
|
||||
hintText: 'Suchen',
|
||||
buttonIconColor: Colors.white,
|
||||
),
|
||||
),
|
||||
onEmojiSelected: (emojis.Category? category, emojis.Emoji emoji) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
ReactMessage(
|
||||
chatToken: widget.chatData.token,
|
||||
messageId: widget.bubbleData.id,
|
||||
params: ReactMessageParams(emoji.emoji),
|
||||
).run().then((value) => widget.refetch(renew: true));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
},
|
||||
style: IconButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
minimumSize: const Size(40, 40),
|
||||
),
|
||||
icon: const Icon(Icons.add_circle_outline_outlined),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: canReact,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.emoji_emotions_outlined),
|
||||
title: const Text('Reaktionen'),
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => MessageReactions(
|
||||
token: widget.chatData.token,
|
||||
messageId: widget.bubbleData.id,
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: !message.containsFile,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.copy),
|
||||
title: const Text('Nachricht kopieren'),
|
||||
onTap: () => {
|
||||
Clipboard.setData(ClipboardData(text: widget.bubbleData.message)),
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: !kReleaseMode && !widget.isSender && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.sms_outlined),
|
||||
title: Text("Private Nachricht an '${widget.bubbleData.actorDisplayName}'"),
|
||||
onTap: () => {
|
||||
Navigator.of(context).pop()
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: widget.isSender && DateTime.fromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).add(const Duration(hours: 6)).isAfter(DateTime.now()),
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.delete_outline),
|
||||
title: const Text('Nachricht löschen'),
|
||||
onTap: () {
|
||||
DeleteMessage(widget.chatData.token, widget.bubbleData.id).run().then((value) {
|
||||
Provider.of<ChatProps>(context, listen: false).run();
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
DebugTile(context).jsonData(widget.bubbleData.toJson()),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -127,6 +288,54 @@ class _ChatBubbleState extends State<ChatBubble> {
|
||||
|
||||
children: [
|
||||
GestureDetector(
|
||||
onLongPress: showOptionsDialog,
|
||||
onDoubleTap: showOptionsDialog,
|
||||
onTap: () {
|
||||
if(message.file == null) return;
|
||||
|
||||
if(downloadProgress > 0) {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
title: const Text('Download abbrechen?'),
|
||||
content: const Text('Möchtest du den Download abbrechen?'),
|
||||
actions: [
|
||||
TextButton(onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
}, child: const Text('Nein')),
|
||||
TextButton(onPressed: () {
|
||||
downloadCore?.then((value) {
|
||||
if(!value.isCancelled) value.cancel();
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
setState(() {
|
||||
downloadProgress = 0;
|
||||
downloadCore = null;
|
||||
});
|
||||
}, child: const Text('Ja, Abbrechen'))
|
||||
],
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
downloadProgress = 1;
|
||||
downloadCore = FileElement.download(context, message.file!.path!, message.file!.name, (progress) {
|
||||
if(progress > 1) {
|
||||
setState(() {
|
||||
downloadProgress = progress;
|
||||
});
|
||||
}
|
||||
}, (result) {
|
||||
setState(() {
|
||||
downloadProgress = 0;
|
||||
});
|
||||
|
||||
if(result.type != ResultType.done) {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
content: Text(result.message),
|
||||
));
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Bubble(
|
||||
style: getStyle(),
|
||||
child: Container(
|
||||
@ -182,212 +391,6 @@ class _ChatBubbleState extends State<ChatBubble> {
|
||||
),
|
||||
),
|
||||
),
|
||||
onLongPress: () {
|
||||
showDialog(context: context, builder: (context) {
|
||||
var commonReactions = <String>['👍', '👎', '😆', '❤️', '👀'];
|
||||
var canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment;
|
||||
return SimpleDialog(
|
||||
children: [
|
||||
Visibility(
|
||||
visible: canReact,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
...commonReactions.map((e) => TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
minimumSize: const Size(40, 40)
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
ReactMessage(
|
||||
chatToken: widget.chatData.token,
|
||||
messageId: widget.bubbleData.id,
|
||||
params: ReactMessageParams(e),
|
||||
).run().then((value) => widget.refetch(renew: true));
|
||||
},
|
||||
child: Text(e),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
contentPadding: const EdgeInsets.all(15),
|
||||
titlePadding: const EdgeInsets.only(left: 6, top: 15),
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
const Text('Reagieren'),
|
||||
],
|
||||
),
|
||||
content: SizedBox(
|
||||
width: 256,
|
||||
height: 270,
|
||||
child: Column(
|
||||
children: [
|
||||
emojis.EmojiPicker(
|
||||
config: emojis.Config(
|
||||
height: 256,
|
||||
swapCategoryAndBottomBar: true,
|
||||
emojiViewConfig: emojis.EmojiViewConfig(
|
||||
backgroundColor: Theme.of(context).canvasColor,
|
||||
recentsLimit: 67,
|
||||
emojiSizeMax: 25,
|
||||
noRecents: const Text('Keine zuletzt verwendeten Emojis'),
|
||||
columns: 7,
|
||||
),
|
||||
bottomActionBarConfig: const emojis.BottomActionBarConfig(
|
||||
enabled: false,
|
||||
),
|
||||
categoryViewConfig: emojis.CategoryViewConfig(
|
||||
backgroundColor: Theme.of(context).hoverColor,
|
||||
iconColorSelected: Theme.of(context).primaryColor,
|
||||
indicatorColor: Theme.of(context).primaryColor,
|
||||
),
|
||||
searchViewConfig: emojis.SearchViewConfig(
|
||||
backgroundColor: Theme.of(context).dividerColor,
|
||||
buttonColor: Theme.of(context).dividerColor,
|
||||
hintText: 'Suchen',
|
||||
buttonIconColor: Colors.white,
|
||||
),
|
||||
),
|
||||
onEmojiSelected: (emojis.Category? category, emojis.Emoji emoji) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
ReactMessage(
|
||||
chatToken: widget.chatData.token,
|
||||
messageId: widget.bubbleData.id,
|
||||
params: ReactMessageParams(emoji.emoji),
|
||||
).run().then((value) => widget.refetch(renew: true));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
},
|
||||
style: IconButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
minimumSize: const Size(40, 40),
|
||||
),
|
||||
icon: const Icon(Icons.add_circle_outline_outlined),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: canReact,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.emoji_emotions_outlined),
|
||||
title: const Text('Reaktionen'),
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => MessageReactions(
|
||||
token: widget.chatData.token,
|
||||
messageId: widget.bubbleData.id,
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: !message.containsFile,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.copy),
|
||||
title: const Text('Nachricht kopieren'),
|
||||
onTap: () => {
|
||||
Clipboard.setData(ClipboardData(text: widget.bubbleData.message)),
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: !kReleaseMode && !widget.isSender && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.sms_outlined),
|
||||
title: Text("Private Nachricht an '${widget.bubbleData.actorDisplayName}'"),
|
||||
onTap: () => {
|
||||
Navigator.of(context).pop()
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: widget.isSender && DateTime.fromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).add(const Duration(hours: 6)).isAfter(DateTime.now()),
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.delete_outline),
|
||||
title: const Text('Nachricht löschen'),
|
||||
onTap: () {
|
||||
DeleteMessage(widget.chatData.token, widget.bubbleData.id).run().then((value) {
|
||||
Provider.of<ChatProps>(context, listen: false).run();
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
DebugTile(context).jsonData(widget.bubbleData.toJson()),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
onTap: () {
|
||||
if(message.file == null) return;
|
||||
|
||||
if(downloadProgress > 0) {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
title: const Text('Download abbrechen?'),
|
||||
content: const Text('Möchtest du den Download abbrechen?'),
|
||||
actions: [
|
||||
TextButton(onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
}, child: const Text('Nein')),
|
||||
TextButton(onPressed: () {
|
||||
downloadCore?.then((value) {
|
||||
if(!value.isCancelled) value.cancel();
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
setState(() {
|
||||
downloadProgress = 0;
|
||||
downloadCore = null;
|
||||
});
|
||||
}, child: const Text('Ja, Abbrechen'))
|
||||
],
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
downloadProgress = 1;
|
||||
downloadCore = FileElement.download(context, message.file!.path!, message.file!.name, (progress) {
|
||||
if(progress > 1) {
|
||||
setState(() {
|
||||
downloadProgress = progress;
|
||||
});
|
||||
}
|
||||
}, (result) {
|
||||
setState(() {
|
||||
downloadProgress = 0;
|
||||
});
|
||||
|
||||
if(result.type != ResultType.done) {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
content: Text(result.message),
|
||||
));
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: widget.bubbleData.reactions != null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user