Files
moxxy/lib/ui/widgets/chat/message.dart

210 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:moxxyv2/shared/models/file_metadata.dart';
import 'package:moxxyv2/shared/models/message.dart';
import 'package:moxxyv2/ui/constants.dart';
import 'package:moxxyv2/ui/helpers.dart';
import 'package:moxxyv2/ui/widgets/chat/message/audio.dart';
import 'package:moxxyv2/ui/widgets/chat/message/file.dart';
import 'package:moxxyv2/ui/widgets/chat/message/image.dart';
import 'package:moxxyv2/ui/widgets/chat/message/sticker.dart';
import 'package:moxxyv2/ui/widgets/chat/message/text.dart';
import 'package:moxxyv2/ui/widgets/chat/message/video.dart';
import 'package:moxxyv2/ui/widgets/chat/playbutton.dart';
import 'package:moxxyv2/ui/widgets/chat/quote/audio.dart';
import 'package:moxxyv2/ui/widgets/chat/quote/file.dart';
import 'package:moxxyv2/ui/widgets/chat/quote/image.dart';
import 'package:moxxyv2/ui/widgets/chat/quote/sticker.dart';
import 'package:moxxyv2/ui/widgets/chat/quote/text.dart';
import 'package:moxxyv2/ui/widgets/chat/quote/video.dart';
import 'package:moxxyv2/ui/widgets/chat/shared/audio.dart';
import 'package:moxxyv2/ui/widgets/chat/shared/file.dart';
import 'package:moxxyv2/ui/widgets/chat/shared/image.dart';
import 'package:moxxyv2/ui/widgets/chat/shared/video.dart';
enum MessageType {
text,
image,
video,
audio,
file,
sticker,
}
/// Deduce the type of message we are dealing with to pick the correct
/// widget.
MessageType getMessageType(Message message) {
if (message.isMedia) {
if (message.stickerPackId != null) {
return MessageType.sticker;
}
final mime = message.fileMetadata!.mimeType;
if (mime == null) return MessageType.file;
if (mime.startsWith('image/')) {
return MessageType.image;
} else if (mime.startsWith('video/')) {
return MessageType.video;
} else if (mime.startsWith('audio/')) {
return MessageType.audio;
}
return MessageType.file;
}
return MessageType.text;
}
/// Build an inlinable message widget
Widget buildMessageWidget(
Message message,
double maxWidth,
BorderRadius radius,
bool sent,
double topLeftRadius,
double topRightRadius,
) {
// Retracted messages are always rendered as a text message
if (message.isRetracted) {
return TextChatWidget(
message,
sent,
topWidget: message.quotes != null
? buildQuoteMessageWidget(
message.quotes!,
sent,
topLeftRadius,
topRightRadius,
)
: null,
);
}
switch (getMessageType(message)) {
case MessageType.text:
{
return TextChatWidget(
message,
sent,
topWidget: message.quotes != null
? buildQuoteMessageWidget(
message.quotes!,
sent,
topLeftRadius,
topRightRadius,
)
: null,
);
}
case MessageType.image:
return ImageChatWidget(message, radius, maxWidth, sent);
case MessageType.video:
return VideoChatWidget(message, radius, maxWidth, sent);
case MessageType.sticker:
return StickerChatWidget(
message,
maxWidth,
sent,
quotedMessage: message.quotes != null
? buildQuoteMessageWidget(
message.quotes!,
sent,
radiusLargeSize,
radiusLargeSize,
)
: null,
);
case MessageType.audio:
return AudioChatWidget(message, radius, maxWidth, sent);
case MessageType.file:
return FileChatWidget(message, radius, maxWidth, sent);
}
}
/// Build a widget that represents a quoted message within another bubble.
Widget buildQuoteMessageWidget(
Message message,
bool sent,
double topLeftRadius,
double topRightRadius, {
void Function()? resetQuote,
}) {
switch (getMessageType(message)) {
case MessageType.sticker:
return QuotedStickerWidget(
message,
sent,
topLeftRadius,
topRightRadius,
resetQuote: resetQuote,
);
case MessageType.text:
return QuotedTextWidget(
message,
sent,
topLeftRadius,
topRightRadius,
resetQuote: resetQuote,
);
case MessageType.image:
return QuotedImageWidget(
message,
sent,
topLeftRadius,
topRightRadius,
resetQuote: resetQuote,
);
case MessageType.video:
return QuotedVideoWidget(
message,
sent,
topLeftRadius,
topRightRadius,
resetQuote: resetQuote,
);
case MessageType.audio:
return QuotedAudioWidget(
message,
sent,
topLeftRadius,
topRightRadius,
resetQuote: resetQuote,
);
case MessageType.file:
return QuotedFileWidget(
message,
sent,
topLeftRadius,
topRightRadius,
resetQuote: resetQuote,
);
}
}
Widget buildSharedMediaWidget(FileMetadata metadata, String conversationJid) {
if (metadata.mimeType!.startsWith('image/')) {
return SharedImageWidget(
metadata.path!,
onTap: () => openFile(metadata.path!),
);
} else if (metadata.mimeType!.startsWith('video/')) {
return SharedVideoWidget(
metadata.path!,
conversationJid,
metadata.mimeType!,
onTap: () => openFile(metadata.path!),
child: const PlayButton(size: 32),
);
} else if (metadata.mimeType!.startsWith('audio/')) {
return SharedAudioWidget(
metadata.path!,
onTap: () => openFile(metadata.path!),
);
}
return SharedFileWidget(
metadata.path!,
onTap: () => openFile(metadata.path!),
);
}