TF-736 Apply new design for rich text button
This commit is contained in:
@@ -23,6 +23,8 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
final double sizeIconChecked;
|
||||
final double radiusButton;
|
||||
final double opacity;
|
||||
final Widget? iconArrowDown;
|
||||
final Color? colorButton;
|
||||
|
||||
const DropDownButtonWidget({
|
||||
Key? key,
|
||||
@@ -36,6 +38,8 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
this.sizeIconChecked = 20,
|
||||
this.radiusButton = 10,
|
||||
this.opacity = 1.0,
|
||||
this.iconArrowDown,
|
||||
this.colorButton,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -94,7 +98,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
color: AppColor.colorInputBorderCreateMailbox,
|
||||
width: 0.5,
|
||||
),
|
||||
color: AppColor.colorInputBackgroundCreateMailbox,
|
||||
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
|
||||
),
|
||||
padding: const EdgeInsets.only(left: 12, right: 10),
|
||||
child: Row(children: [
|
||||
@@ -106,12 +110,12 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
overflow: CommonTextStyle.defaultTextOverFlow,
|
||||
)),
|
||||
SvgPicture.asset(_imagePaths.icDropDown)
|
||||
iconArrowDown ?? SvgPicture.asset(_imagePaths.icDropDown)
|
||||
]),
|
||||
)
|
||||
: null,
|
||||
onChanged: onChanged,
|
||||
icon: SvgPicture.asset(_imagePaths.icDropDown),
|
||||
icon: iconArrowDown ?? SvgPicture.asset(_imagePaths.icDropDown),
|
||||
buttonPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
buttonDecoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(radiusButton),
|
||||
@@ -119,7 +123,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
color: AppColor.colorInputBorderCreateMailbox,
|
||||
width: 0.5,
|
||||
),
|
||||
color: AppColor.colorInputBackgroundCreateMailbox,
|
||||
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
|
||||
),
|
||||
itemHeight: heightItem,
|
||||
buttonHeight: heightItem,
|
||||
|
||||
@@ -757,117 +757,144 @@ class ComposerView extends GetWidget<ComposerController>
|
||||
}
|
||||
|
||||
Widget _buildToolbarRichTextWidget(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: RichTextStyleType.values.map((textType) => Obx(() {
|
||||
final opacity = controller.richTextWebController.codeViewEnabled ? 0.5 : 1.0;
|
||||
switch(textType) {
|
||||
case RichTextStyleType.textColor:
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconColorText(
|
||||
iconData: textType.getIconData(),
|
||||
colorSelected: controller.richTextWebController.selectedTextColor.value,
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
|
||||
);
|
||||
case RichTextStyleType.textBackgroundColor:
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
child: AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconColorBackgroundText(
|
||||
iconData: textType.getIconData(),
|
||||
colorSelected: controller.richTextWebController.selectedTextBackgroundColor.value,
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
|
||||
),
|
||||
);
|
||||
case RichTextStyleType.fontName:
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
return Obx(() {
|
||||
final richTextController = controller.richTextWebController;
|
||||
final codeViewEnabled = richTextController.codeViewEnabled;
|
||||
final opacity = codeViewEnabled ? 0.5 : 1.0;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: DropDownMenuHeaderStyleWidget(
|
||||
icon: buildWrapIconStyleText(
|
||||
icon: Tooltip(
|
||||
message: RichTextStyleType.headerStyle.getTooltipButton(context),
|
||||
child: SvgPicture.asset(RichTextStyleType.headerStyle.getIcon(imagePaths),
|
||||
color: AppColor.colorDefaultRichTextButton.withOpacity(opacity),
|
||||
fit: BoxFit.fill),
|
||||
)
|
||||
),
|
||||
items: HeaderStyleType.values,
|
||||
onMenuStateChange: (isOpen) {
|
||||
log('ComposerView::_buildToolbarRichTextWidget(): MenuHeaderStyleStatus: $isOpen');
|
||||
final newStatus = isOpen
|
||||
? DropdownMenuFontStatus.open
|
||||
: DropdownMenuFontStatus.closed;
|
||||
richTextController.menuHeaderStyleStatus = newStatus;
|
||||
},
|
||||
onChanged: (newStyle) => richTextController.applyHeaderStyle(newStyle)),
|
||||
),
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: Container(
|
||||
width: 200,
|
||||
padding: const EdgeInsets.only(right: 2),
|
||||
child: DropDownButtonWidget<FontNameType>(
|
||||
items: FontNameType.values,
|
||||
itemSelected: controller.richTextWebController.selectedFontName.value,
|
||||
onChanged: (newFont) => controller.richTextWebController.applyNewFontStyle(newFont),
|
||||
onMenuStateChange: (isOpen) {
|
||||
log('ComposerView::_buildToolbarRichTextWidget(): MenuFontStatus: $isOpen');
|
||||
final newStatus = isOpen
|
||||
? DropdownMenuFontStatus.open
|
||||
: DropdownMenuFontStatus.closed;
|
||||
controller.richTextWebController.menuFontStatus = newStatus;
|
||||
},
|
||||
heightItem: 35,
|
||||
sizeIconChecked: 16,
|
||||
radiusButton: 5,
|
||||
opacity: opacity,
|
||||
supportSelectionIcon: true)),
|
||||
);
|
||||
case RichTextStyleType.codeView:
|
||||
return buildIconStyleText(
|
||||
path: textType.getIcon(imagePaths),
|
||||
isSelected: controller.richTextWebController.isTextStyleTypeSelected(textType),
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
onTap: () => controller.richTextWebController.toggleCodeView());
|
||||
case RichTextStyleType.headerStyle:
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 35,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.only(right: 2),
|
||||
child: DropDownMenuHeaderStyleWidget(
|
||||
icon: Material(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
side: const BorderSide(
|
||||
color: AppColor.colorInputBorderCreateMailbox,
|
||||
width: 0.5)),
|
||||
color: AppColor.colorInputBackgroundCreateMailbox,
|
||||
child: Tooltip(
|
||||
message: textType.getTooltipButton(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10, top: 10),
|
||||
child: SvgPicture.asset(textType.getIcon(imagePaths),
|
||||
color: AppColor.colorDefaultRichTextButton.withOpacity(opacity),
|
||||
fit: BoxFit.fill),
|
||||
),
|
||||
),
|
||||
),
|
||||
items: HeaderStyleType.values,
|
||||
width: 200,
|
||||
padding: const EdgeInsets.only(left: 8, right: 8),
|
||||
child: DropDownButtonWidget<FontNameType>(
|
||||
items: FontNameType.values,
|
||||
itemSelected: richTextController.selectedFontName.value,
|
||||
onChanged: (newFont) => richTextController.applyNewFontStyle(newFont),
|
||||
onMenuStateChange: (isOpen) {
|
||||
log('ComposerView::_buildToolbarRichTextWidget(): MenuHeaderStyleStatus: $isOpen');
|
||||
log('ComposerView::_buildToolbarRichTextWidget(): MenuFontStatus: $isOpen');
|
||||
final newStatus = isOpen
|
||||
? DropdownMenuFontStatus.open
|
||||
: DropdownMenuFontStatus.closed;
|
||||
controller.richTextWebController.menuHeaderStyleStatus = newStatus;
|
||||
richTextController.menuFontStatus = newStatus;
|
||||
},
|
||||
onChanged: (newStyle) => controller.richTextWebController.applyHeaderStyle(newStyle))),
|
||||
);
|
||||
default:
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconStyleText(
|
||||
path: textType.getIcon(imagePaths),
|
||||
isSelected: controller.richTextWebController.isTextStyleTypeSelected(textType),
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
|
||||
);
|
||||
}
|
||||
})).toList()
|
||||
),
|
||||
);
|
||||
heightItem: 38,
|
||||
sizeIconChecked: 16,
|
||||
radiusButton: 5,
|
||||
opacity: opacity,
|
||||
colorButton: Colors.white,
|
||||
iconArrowDown: SvgPicture.asset(imagePaths.icStyleArrowDown),
|
||||
supportSelectionIcon: true)),
|
||||
),
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: buildWrapIconStyleText(
|
||||
icon: buildIconWithTooltip(
|
||||
path: RichTextStyleType.textColor.getIcon(imagePaths),
|
||||
color: richTextController.selectedTextColor.value,
|
||||
tooltip: RichTextStyleType.textColor.getTooltipButton(context),
|
||||
opacity: opacity),
|
||||
onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.textColor)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: buildWrapIconStyleText(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5),
|
||||
icon: buildIconColorBackgroundText(
|
||||
iconData: RichTextStyleType.textBackgroundColor.getIconData(),
|
||||
colorSelected: richTextController.selectedTextBackgroundColor.value,
|
||||
tooltip: RichTextStyleType.textBackgroundColor.getTooltipButton(context),
|
||||
opacity: opacity),
|
||||
onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.textBackgroundColor)),
|
||||
),
|
||||
),
|
||||
buildWrapIconStyleText(
|
||||
hasDropdown: false,
|
||||
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 5),
|
||||
icon: Wrap(children: [
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: buildIconStyleText(
|
||||
path: RichTextStyleType.bold.getIcon(imagePaths),
|
||||
isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.bold),
|
||||
tooltip: RichTextStyleType.bold.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.bold)),
|
||||
),
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: buildIconStyleText(
|
||||
path: RichTextStyleType.italic.getIcon(imagePaths),
|
||||
isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.italic),
|
||||
tooltip: RichTextStyleType.italic.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.italic)),
|
||||
),
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: buildIconStyleText(
|
||||
path: RichTextStyleType.underline.getIcon(imagePaths),
|
||||
isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.underline),
|
||||
tooltip: RichTextStyleType.underline.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.underline)),
|
||||
),
|
||||
AbsorbPointer(
|
||||
absorbing: codeViewEnabled,
|
||||
child: buildIconStyleText(
|
||||
path: RichTextStyleType.strikeThrough.getIcon(imagePaths),
|
||||
isSelected: richTextController.isTextStyleTypeSelected(
|
||||
RichTextStyleType.strikeThrough),
|
||||
tooltip: RichTextStyleType.strikeThrough.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => richTextController.applyRichTextStyle(context, RichTextStyleType.strikeThrough)),
|
||||
)
|
||||
])),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: buildWrapIconStyleText(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 5),
|
||||
isSelected: richTextController.isTextStyleTypeSelected(RichTextStyleType.codeView),
|
||||
icon: buildIconWithTooltip(
|
||||
path: RichTextStyleType.codeView.getIcon(imagePaths),
|
||||
color: AppColor.colorDefaultRichTextButton.withOpacity(opacity),
|
||||
tooltip: RichTextStyleType.codeView.getTooltipButton(context)),
|
||||
onTap: () => richTextController.toggleCodeView()),
|
||||
)
|
||||
]
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildInlineLoadingView() {
|
||||
|
||||
@@ -1,11 +1,45 @@
|
||||
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
mixin RichTextButtonMixin {
|
||||
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
Widget buildWrapIconStyleText({
|
||||
required Widget icon,
|
||||
VoidCallback? onTap,
|
||||
bool isSelected = false,
|
||||
bool hasDropdown = true,
|
||||
double opacity = 1.0,
|
||||
EdgeInsets? padding,
|
||||
}){
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected == true
|
||||
? AppColor.colorBackgroundWrapIconStyleCode.withOpacity(opacity)
|
||||
: Colors.white.withOpacity(opacity),
|
||||
border: Border.all(
|
||||
color: AppColor.colorBorderWrapIconStyleCode,
|
||||
width: 0.5),
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
child: hasDropdown
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
icon,
|
||||
SvgPicture.asset(_imagePaths.icStyleArrowDown)
|
||||
])
|
||||
: icon,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildIconStyleText({
|
||||
required String path,
|
||||
required bool? isSelected,
|
||||
@@ -28,50 +62,38 @@ mixin RichTextButtonMixin {
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildIconColorText({
|
||||
required IconData? iconData,
|
||||
required Color? colorSelected,
|
||||
required VoidCallback onTap,
|
||||
Widget buildIconWithTooltip({
|
||||
required String path,
|
||||
Color? color,
|
||||
String? tooltip,
|
||||
double opacity = 1.0,
|
||||
}){
|
||||
return buildIconWeb(
|
||||
icon: Icon(iconData,
|
||||
color: (colorSelected ?? Colors.black).withOpacity(opacity),
|
||||
size: 20),
|
||||
iconPadding: const EdgeInsets.all(4),
|
||||
colorSelected: colorSelected == Colors.white
|
||||
? AppColor.colorFocusRichTextButton
|
||||
: Colors.transparent,
|
||||
colorFocus: Colors.white,
|
||||
minSize: 20,
|
||||
tooltip: tooltip,
|
||||
onTap: onTap,
|
||||
final newColor = color == Colors.white
|
||||
? AppColor.colorDefaultRichTextButton
|
||||
: color;
|
||||
|
||||
return Tooltip(
|
||||
child: SvgPicture.asset(path,
|
||||
color: newColor?.withOpacity(opacity),
|
||||
fit: BoxFit.fill),
|
||||
message: tooltip,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildIconColorBackgroundText({
|
||||
required IconData? iconData,
|
||||
required Color? colorSelected,
|
||||
required VoidCallback onTap,
|
||||
String? tooltip,
|
||||
double opacity = 1.0,
|
||||
}){
|
||||
final newColor = colorSelected == Colors.white
|
||||
? AppColor.colorDefaultRichTextButton
|
||||
: colorSelected;
|
||||
return buildIconWeb(
|
||||
icon: Icon(iconData,
|
||||
return Tooltip(
|
||||
child: Icon(iconData,
|
||||
color: (newColor ?? AppColor.colorDefaultRichTextButton).withOpacity(opacity),
|
||||
size: 20),
|
||||
iconPadding: const EdgeInsets.all(4),
|
||||
colorSelected: newColor == Colors.white
|
||||
? AppColor.colorFocusRichTextButton
|
||||
: Colors.transparent,
|
||||
colorFocus: Colors.white,
|
||||
minSize: 20,
|
||||
tooltip: tooltip,
|
||||
onTap: onTap,
|
||||
message: tooltip,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,9 @@ enum RichTextStyleType {
|
||||
return imagePaths.icStyleCodeView;
|
||||
case headerStyle:
|
||||
return imagePaths.icStyleHeader;
|
||||
case textColor:
|
||||
case textBackgroundColor:
|
||||
return imagePaths.icStyleColor;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user