mediaAttachment static method

Widget mediaAttachment(
  1. BuildContext context,
  2. Attachment e,
  3. Iterable<Attachment> media, {
  4. GlobalKey<State<StatefulWidget>>? key,
  5. ChatItem? item,
  6. Paginated<ChatItemId, Rx<ChatItem>> onGallery()?,
  7. Future<void> onError(
    1. ChatItem?
    )?,
  8. bool filled = true,
})

Returns a visual representation of the provided media-Attachment.

Implementation

static Widget mediaAttachment(
  BuildContext context,
  Attachment e,
  Iterable<Attachment> media, {
  GlobalKey? key,
  ChatItem? item,
  Paginated<ChatItemId, Rx<ChatItem>> Function()? onGallery,
  Future<void> Function(ChatItem?)? onError,
  bool filled = true,
}) {
  final style = Theme.of(context).style;

  final bool isLocal = e is LocalAttachment;

  final bool isVideo;
  if (isLocal) {
    isVideo = e.file.isVideo;
  } else {
    isVideo = e is FileAttachment;
  }

  Widget attachment;
  if (isVideo) {
    attachment = Stack(
      alignment: Alignment.center,
      fit: filled ? StackFit.expand : StackFit.loose,
      children: [
        MediaAttachment(
          key: key,
          attachment: e,
          height: 300,
          onError: () async => await onError?.call(null),
        ),
        Center(
          child: Container(
            width: 60,
            height: 60,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: style.colors.onBackgroundOpacity50,
            ),
            child: Icon(
              Icons.play_arrow,
              color: style.colors.onPrimary,
              size: 48,
            ),
          ),
        ),
      ],
    );
  } else {
    attachment = MediaAttachment(
      key: key,
      attachment: e,
      width: filled ? double.infinity : null,
      height: filled ? double.infinity : null,
      onError: () async => await onError?.call(null),
    );

    if (!isLocal) {
      attachment = KeyedSubtree(
        key: const Key('SentImage'),
        child: attachment,
      );
    }
  }

  return Padding(
    padding: EdgeInsets.zero,
    child: MouseRegion(
      cursor: isLocal ? MouseCursor.defer : SystemMouseCursors.click,
      child: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: isLocal
            ? null
            : () {
                if (onGallery == null) {
                  // [onTap] still needs to be invoked to ensure [ContextMenu]
                  // doesn't get closed, when this is being built within it.
                  return;
                }

                GalleryPopup.show(
                  context: context,
                  gallery: ChatGallery(
                    paginated: onGallery(),
                    initial: (item, e),
                    rect: key,
                    onForbidden: onError,
                  ),
                );
              },
        child: Stack(
          alignment: Alignment.center,
          children: [
            filled
                ? Positioned.fill(child: attachment)
                : Container(
                    constraints: const BoxConstraints(minWidth: 300),
                    width: double.infinity,
                    child: attachment,
                  ),
            ElasticAnimatedSwitcher(
              key: Key('AttachmentStatus_${e.id}'),
              child: !isLocal || e.status.value == SendingStatus.sent
                  ? Container(key: const Key('Sent'))
                  : Container(
                      constraints: filled
                          ? const BoxConstraints(
                              minWidth: 300,
                              minHeight: 300,
                            )
                          : null,
                      child: e.status.value == SendingStatus.sending
                          ? SizedBox(
                              width: 60,
                              height: 60,
                              child: Center(
                                child: CircularProgressIndicator(
                                  key: const Key('Sending'),
                                  value: e.progress.value,
                                  backgroundColor: style.colors.onPrimary,
                                  strokeWidth: 10,
                                ),
                              ),
                            )
                          : Icon(
                              Icons.error,
                              key: const Key('Error'),
                              size: 48,
                              color: style.colors.danger,
                            ),
                    ),
            ),
          ],
        ),
      ),
    ),
  );
}