Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/532627 text reply #222

Closed
wants to merge 13 commits into from
Closed
7 changes: 5 additions & 2 deletions lib/src/services/ds_file.service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ abstract class DSFileService {
return null;
}

static String getFileExtensionFromMime(String? mimeType) =>
extensionFromMime(mimeType ?? '');
static String getFileExtensionFromMime(String? mimeType) {
return mimeType == 'application/vnd.ms-powerpoint'
? 'ppt'
: extensionFromMime(mimeType ?? '');
}
}
1 change: 1 addition & 0 deletions lib/src/themes/colors/ds_colors.theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ abstract class DSColors {
static const Color surface1 = Color(0xFFF6F6F6);
static const Color surface3 = Color(0xFFC7C7C7);
static const Color contentDefault = Color(0xFF454545);
static const Color contentGhost = Color(0xFF949494);

static const Color disabledText = Color(0xFF637798);
static const Color disabledBg = Color(0xFFE8F2FF);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ class DSAudioMessageBubble extends StatelessWidget {
final DSMessageBubbleStyle style;
final String? uniqueId;
final bool shouldAuthenticate;
final dynamic replyContent;

DSAudioMessageBubble({
super.key,
required this.uri,
required this.align,
this.uniqueId,
this.replyContent,
this.borderRadius = const [DSBorderRadius.all],
this.shouldAuthenticate = false,
final DSMessageBubbleStyle? style,
Expand All @@ -33,6 +35,7 @@ class DSAudioMessageBubble extends StatelessWidget {
return DSMessageBubble(
borderRadius: borderRadius,
align: align,
replyContent: replyContent,
style: style,
padding: const EdgeInsets.only(
left: 4.0,
Expand Down
3 changes: 3 additions & 0 deletions lib/src/widgets/chat/ds_contact_message_bubble.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class DSContactMessageBubble extends StatelessWidget {
final String? phone;
final String? email;
final String? address;
final dynamic replyContent;
final DSAlign align;
final List<DSBorderRadius> borderRadius;
final DSMessageBubbleStyle style;
Expand All @@ -25,6 +26,7 @@ class DSContactMessageBubble extends StatelessWidget {
required this.address,
required this.email,
required this.align,
this.replyContent,
this.borderRadius = const [DSBorderRadius.all],
DSMessageBubbleStyle? style,
}) : style = style ?? DSMessageBubbleStyle();
Expand All @@ -37,6 +39,7 @@ class DSContactMessageBubble extends StatelessWidget {
padding: const EdgeInsets.all(16.0),
shouldUseDefaultSize: true,
style: style,
replyContent: replyContent,
child: _buildContactCard(),
);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/src/widgets/chat/ds_file_message_bubble.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class DSFileMessageBubble extends StatelessWidget {
final List<DSBorderRadius> borderRadius;
final DSMessageBubbleStyle style;
final bool shouldAuthenticate;
final dynamic replyContent;

/// Creates a Design System's [DSMessageBubble] used on files other than image, audio, or video
DSFileMessageBubble({
Expand All @@ -30,6 +31,7 @@ class DSFileMessageBubble extends StatelessWidget {
required this.url,
required this.size,
required this.filename,
this.replyContent,
this.borderRadius = const [DSBorderRadius.all],
this.shouldAuthenticate = false,
DSMessageBubbleStyle? style,
Expand All @@ -45,6 +47,7 @@ class DSFileMessageBubble extends StatelessWidget {
),
child: DSMessageBubble(
borderRadius: borderRadius,
replyContent: replyContent,
padding: EdgeInsets.zero,
align: align,
style: style,
Expand Down Expand Up @@ -105,7 +108,6 @@ class DSFileMessageBubble extends StatelessWidget {
filename,
color: color,
textAlign: TextAlign.center,
isSelectable: true,
shouldLinkify: false,
),
Visibility(
Expand Down
3 changes: 3 additions & 0 deletions lib/src/widgets/chat/ds_image_message_bubble.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class DSImageMessageBubble extends StatefulWidget {
this.showSelect = false,
this.onSelected,
this.onOpenLink,
this.replyContent,
this.shouldAuthenticate = false,
this.mediaType,
this.imageMaxHeight,
Expand All @@ -44,6 +45,7 @@ class DSImageMessageBubble extends StatefulWidget {
final String? text;
final String appBarText;
final Uri? appBarPhotoUri;
final dynamic replyContent;
final DSMessageBubbleStyle style;
final List<DSDocumentSelectOption> selectOptions;
final bool showSelect;
Expand Down Expand Up @@ -85,6 +87,7 @@ class _DSImageMessageBubbleState extends State<DSImageMessageBubble>
defaultMaxSize: 360.0,
shouldUseDefaultSize: true,
align: widget.align,
replyContent: widget.replyContent,
borderRadius: widget.borderRadius,
padding: EdgeInsets.zero,
hasSpacer: widget.hasSpacer,
Expand Down
3 changes: 3 additions & 0 deletions lib/src/widgets/chat/ds_location_message_bubble.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class DSLocationMessageBubble extends StatelessWidget {
final DSAlign align;
final DSMessageBubbleStyle style;
final String? title;
final dynamic replyContent;
final String latitude;
final String longitude;
final List<DSBorderRadius> borderRadius;
Expand All @@ -25,6 +26,7 @@ class DSLocationMessageBubble extends StatelessWidget {
required this.align,
required this.latitude,
required this.longitude,
this.replyContent,
this.borderRadius = const [DSBorderRadius.all],
DSMessageBubbleStyle? style,
this.title,
Expand Down Expand Up @@ -56,6 +58,7 @@ class DSLocationMessageBubble extends StatelessWidget {
defaultMaxSize: 240.0,
defaultMinSize: 240.0,
borderRadius: borderRadius,
replyContent: replyContent,
padding: EdgeInsets.zero,
align: align,
style: style,
Expand Down
59 changes: 37 additions & 22 deletions lib/src/widgets/chat/ds_message_bubble.widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import '../../models/ds_message_bubble_style.model.dart';
import '../../utils/ds_bubble.util.dart';
import '../../utils/ds_utils.util.dart';
import '../animations/ds_animated_size.widget.dart';
import 'ds_reply_container.widget.dart';

class DSMessageBubble extends StatelessWidget {
final DSAlign align;
final Widget child;
final dynamic replyContent;
final List<DSBorderRadius> borderRadius;
final EdgeInsets padding;
final bool shouldUseDefaultSize;
Expand All @@ -22,6 +24,7 @@ class DSMessageBubble extends StatelessWidget {
Key? key,
required this.align,
required this.child,
this.replyContent,
this.borderRadius = const [DSBorderRadius.all],
this.padding = const EdgeInsets.symmetric(
vertical: 8.0,
Expand All @@ -34,12 +37,21 @@ class DSMessageBubble extends StatelessWidget {
this.hasSpacer = true,
}) : super(key: key);

BorderRadius _getBorderRadius() {
return borderRadius.getCircularBorderRadius(
maxRadius: 22.0,
minRadius: 2.0,
);
}
@override
Widget build(BuildContext context) => Column(
children: [
Row(
mainAxisAlignment: align == DSAlign.right
? MainAxisAlignment.end
: MainAxisAlignment.start,
children: DSBubbleUtils.addSpacer(
align: align,
hasSpacer: hasSpacer,
child: _messageContainer(),
),
),
],
);

Widget _messageContainer() {
return DSAnimatedSize(
Expand All @@ -60,26 +72,29 @@ class DSMessageBubble extends StatelessWidget {
: null,
padding: padding,
color: style.bubbleBackgroundColor(align),
child: child,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (replyContent != null)
DSReplyContainer(
replyContent: replyContent!,
style: style,
align: align,
),
child,
],
),
),
),
),
);
}

@override
Widget build(BuildContext context) => Column(
children: [
Row(
mainAxisAlignment: align == DSAlign.right
? MainAxisAlignment.end
: MainAxisAlignment.start,
children: DSBubbleUtils.addSpacer(
align: align,
hasSpacer: hasSpacer,
child: _messageContainer(),
),
),
],
);
BorderRadius _getBorderRadius() {
return borderRadius.getCircularBorderRadius(
maxRadius: 22.0,
minRadius: 2.0,
);
}
}
135 changes: 135 additions & 0 deletions lib/src/widgets/chat/ds_reply_container.widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'package:flutter/material.dart';

import '../../enums/ds_align.enum.dart';
import '../../models/ds_message_bubble_style.model.dart';
import '../../themes/colors/ds_colors.theme.dart';
import '../../themes/icons/ds_icons.dart';
import '../../utils/ds_message_content_type.util.dart';
import '../texts/ds_body_text.widget.dart';
import '../texts/ds_caption_text.widget.dart';

class DSReplyContainer extends StatelessWidget {
const DSReplyContainer({
super.key,
required this.replyContent,
required this.style,
required this.align,
});

final DSAlign align;
final dynamic replyContent;
final DSMessageBubbleStyle style;

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(
8.0,
),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
DSIcons.undo_outline,
color: style.isLightBubbleBackground(align)
? DSColors.neutralDarkCity
: DSColors.neutralLightSnow,
),
const SizedBox(width: 8.0),
DSCaptionText(
'Reply',
fontStyle: FontStyle.italic,
color: style.isLightBubbleBackground(align)
? DSColors.neutralDarkCity
: DSColors.neutralLightSnow,
),
],
),
const SizedBox(height: 4.0),
DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.0),
border: Border.all(
color: style.isLightBubbleBackground(align)
? DSColors.contentGhost
: DSColors.contentDisable,
),
color: style.isLightBubbleBackground(align)
? DSColors.surface3
: DSColors.contentDefault,
),
child: IntrinsicHeight(
child: Row(
children: [
Container(
decoration: const ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8.0),
bottomLeft: Radius.circular(8.0),
),
),
color: DSColors.primary,
),
width: 4.0,
),
Flexible(
child: Padding(
padding: const EdgeInsets.only(
top: 8.0,
left: 8.0,
bottom: 8.0,
),
child: _replyWidget(replyContent, style, align),
),
),
],
),
),
),
],
),
);
}
}

Widget _replyWidget(
dynamic replyContent,
DSMessageBubbleStyle style,
DSAlign align,
) {
switch (replyContent['type']) {
case DSMessageContentType.textPlain:
return DSBodyText(
replyContent['value'] is String ? replyContent['value'] : '**********',
color: _color(align, style),
overflow: TextOverflow.visible,
);
default:
return Row(
mainAxisSize: MainAxisSize.max,
children: [
Icon(
DSIcons.warning_outline,
color: _color(align, style),
),
const SizedBox(width: 8.0),
Flexible(
child: DSBodyText(
'Failed to load message',
overflow: TextOverflow.visible,
color: _color(align, style),
),
),
],
);
}
}

Color _color(DSAlign align, DSMessageBubbleStyle style) {
return style.isLightBubbleBackground(align)
? DSColors.contentDefault
: DSColors.surface1;
}
Loading