210 lines
5.6 KiB
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!),
|
|
);
|
|
}
|