double tap on messages to show options #63
@@ -101,6 +101,169 @@ class _ChatBubbleState extends State<ChatBubble> {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void showOptionsDialog() {
 | 
			
		||||
    showDialog(context: context, builder: (context) {
 | 
			
		||||
      List<String> commonReactions = ['👍', '👎', '😆', '❤️', '👀'];
 | 
			
		||||
      bool 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) {
 | 
			
		||||
                          return 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) {
 | 
			
		||||
@@ -129,6 +292,58 @@ class _ChatBubbleState extends State<ChatBubble> {
 | 
			
		||||
 | 
			
		||||
      children: [
 | 
			
		||||
        GestureDetector(
 | 
			
		||||
          onDoubleTap: showOptionsDialog,
 | 
			
		||||
          onLongPress: showOptionsDialog,
 | 
			
		||||
          onTap: () {
 | 
			
		||||
            if(message.file == null) return;
 | 
			
		||||
 | 
			
		||||
            if(downloadProgress > 0) {
 | 
			
		||||
              showDialog(context: context, builder: (context) {
 | 
			
		||||
                return 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) {
 | 
			
		||||
                  return AlertDialog(
 | 
			
		||||
                    content: Text(result.message),
 | 
			
		||||
                  );
 | 
			
		||||
                });
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          },
 | 
			
		||||
          child: Bubble(
 | 
			
		||||
            style: getStyle(),
 | 
			
		||||
            child: Container(
 | 
			
		||||
@@ -184,218 +399,6 @@ class _ChatBubbleState extends State<ChatBubble> {
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          onLongPress: () {
 | 
			
		||||
            showDialog(context: context, builder: (context) {
 | 
			
		||||
              List<String> commonReactions = ['👍', '👎', '😆', '❤️', '👀'];
 | 
			
		||||
              bool 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) {
 | 
			
		||||
                                  return 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) {
 | 
			
		||||
                return 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) {
 | 
			
		||||
                  return AlertDialog(
 | 
			
		||||
                    content: Text(result.message),
 | 
			
		||||
                  );
 | 
			
		||||
                });
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          },
 | 
			
		||||
        ),
 | 
			
		||||
        Visibility(
 | 
			
		||||
          visible: widget.bubbleData.reactions != null,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user