LCOV - code coverage report
Current view: top level - src/ui/editor/pages/helper_editor/helpers/editor_update_helper - editor_update_helper.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 138 144 95.8 %
Date: 2020-12-04 18:41:24 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/material.dart';
       2             : import 'package:flutter/services.dart';
       3             : import 'package:google_fonts/google_fonts.dart';
       4             : import 'package:keyboard_visibility/keyboard_visibility.dart';
       5             : import 'package:mvvm_builder/mvvm_builder.dart';
       6             : import 'package:pal/src/database/entity/graphic_entity.dart';
       7             : import 'package:pal/src/database/entity/helper/helper_entity.dart';
       8             : import 'package:pal/src/injectors/editor_app/editor_app_injector.dart';
       9             : import 'package:pal/src/services/editor/helper/helper_editor_service.dart';
      10             : import 'package:pal/src/services/pal/pal_state_service.dart';
      11             : import 'package:pal/src/theme.dart';
      12             : import 'package:pal/src/ui/editor/pages/helper_editor/font_editor/pickers/font_weight_picker/font_weight_picker_loader.dart';
      13             : import 'package:pal/src/ui/editor/pages/helper_editor/helper_editor.dart';
      14             : import 'package:pal/src/ui/editor/pages/helper_editor/helper_editor_notifiers.dart';
      15             : import 'package:pal/src/ui/editor/pages/helper_editor/helper_editor_viewmodel.dart';
      16             : import 'package:pal/src/ui/editor/pages/helper_editor/widgets/color_picker.dart';
      17             : import 'package:pal/src/ui/editor/pages/helper_editor/widgets/editor_actionsbar.dart';
      18             : import 'package:pal/src/ui/editor/pages/helper_editor/widgets/editor_sending_overlay.dart';
      19             : import 'package:pal/src/ui/editor/pages/media_gallery/media_gallery.dart';
      20             : import 'package:pal/src/ui/editor/widgets/editable_background.dart';
      21             : import 'package:pal/src/ui/editor/widgets/editable_media.dart';
      22             : import 'package:pal/src/ui/editor/widgets/editable_textfield.dart';
      23             : import 'package:pal/src/ui/shared/widgets/circle_button.dart';
      24             : import 'package:pal/src/ui/shared/widgets/overlayed.dart';
      25             : 
      26             : import '../../../../../../router.dart';
      27             : import 'editor_update_helper_presenter.dart';
      28             : import 'editor_update_helper_viewmodel.dart';
      29             : 
      30             : abstract class EditorUpdateHelperView {
      31             : 
      32             :   void showColorPickerDialog(Color color, OnColorSelected onColorSelected, OnCancelPicker onCancel);
      33             : 
      34             :   void closeColorPickerDialog();
      35             : 
      36             :   void hidePalBubble();
      37             : 
      38             :   Future<void> scrollToBottomChangelogList();
      39             : 
      40             :   Future<GraphicEntity> pushToMediaGallery(final String mediaId);
      41             : 
      42             :   Future showLoadingScreen(ValueNotifier<SendingStatus> status);
      43             : 
      44             :   Future closeEditor();
      45             : 
      46             :   void closeLoadingScreen();
      47             : 
      48             : }
      49             : 
      50             : class EditorUpdateHelperPage extends StatelessWidget {
      51             : 
      52             :   // required params
      53             :   final UpdateHelperViewModel baseviewModel;
      54             :   final HelperEditorPageArguments arguments;
      55             :   final EditorHelperService helperService;
      56             :   final PalEditModeStateService palEditModeStateService;
      57             : 
      58             :   // inner page widgets
      59             :   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
      60             :   final GlobalKey<FormState> formKey = GlobalKey<FormState>();
      61             :   final ScrollController scrollController = ScrollController();
      62             : 
      63           1 :   EditorUpdateHelperPage._({
      64             :     Key key,
      65             :     this.helperService,
      66             :     this.palEditModeStateService,
      67             :     @required this.baseviewModel,
      68             :     @required this.arguments,
      69           1 :   }) : super(key: key);
      70             : 
      71           1 :   factory EditorUpdateHelperPage.create({
      72             :     Key key,
      73             :     HelperEditorPageArguments parameters,
      74             :     EditorHelperService helperService,
      75             :     PalEditModeStateService palEditModeStateService,
      76             :     @required HelperViewModel helperViewModel
      77           1 :   }) => EditorUpdateHelperPage._(
      78             :     key: key,
      79             :     helperService: helperService,
      80             :     palEditModeStateService: palEditModeStateService,
      81           1 :     baseviewModel: UpdateHelperViewModel.fromHelperViewModel(helperViewModel),
      82             :     arguments: parameters,
      83             :   );
      84             : 
      85           1 :   factory EditorUpdateHelperPage.edit({
      86             :     Key key,
      87             :     HelperEditorPageArguments parameters,
      88             :     PalEditModeStateService palEditModeStateService,
      89             :     EditorHelperService helperService,
      90             :     @required HelperEntity helperEntity //FIXME should be an id and not entire entity
      91           1 :   }) => EditorUpdateHelperPage._(
      92             :     key: key,
      93             :     helperService: helperService,
      94             :     palEditModeStateService: palEditModeStateService,
      95           1 :     baseviewModel: UpdateHelperViewModel.fromHelperEntity(helperEntity),
      96             :     arguments: parameters,
      97             :   );
      98             : 
      99             : 
     100           1 :   @override
     101             :   Widget build(BuildContext context) {
     102           2 :     return MVVMPageBuilder<EditorUpdateHelperPresenter, UpdateHelperViewModel>().build(
     103           1 :       key: ValueKey('pal_EditorUpdateHelperWidget_Builder'),
     104             :       context: context,
     105           1 :       presenterBuilder: (context) {
     106           1 :         var presenter = EditorUpdateHelperPresenter(
     107           1 :           _EditorUpdateHelperPage(
     108           2 :             context, _scaffoldKey, scrollController,
     109           3 :             palEditModeStateService ?? EditorInjector.of(context).palEditModeStateService
     110             :           ),
     111           1 :           baseviewModel,
     112           1 :           helperService ?? EditorInjector.of(context).helperService,
     113           1 :           arguments
     114             :         );
     115           1 :         KeyboardVisibilityNotification()
     116           2 :           .addNewListener(onChange: presenter.onKeyboardVisibilityChange);
     117             :         return presenter;
     118             :       },
     119           3 :       builder: (context, presenter, model) => this._buildPage(context.buildContext, presenter, model),
     120             :     );
     121             :   }
     122             : 
     123           1 :   Widget _buildPage(
     124             :     final BuildContext context,
     125             :     final EditorUpdateHelperPresenter presenter,
     126             :     final UpdateHelperViewModel viewModel,
     127             :   ) {
     128           1 :     return Scaffold(
     129           1 :       key: _scaffoldKey,
     130             :       resizeToAvoidBottomPadding: true,
     131             :       backgroundColor: Colors.transparent,
     132           1 :       body: EditorActionsBar(
     133           1 :         onCancel: presenter.onCancel,
     134           1 :         onValidate: presenter.onValidate,
     135           1 :         canValidate: viewModel.canValidate,
     136           1 :         child: GestureDetector(
     137           1 :           onTap: presenter.onOutsideTap,
     138           1 :           child: SafeArea(
     139             :             bottom: false,
     140           1 :             child: Form(
     141           1 :               key: formKey,
     142             :               autovalidateMode: AutovalidateMode.always,
     143           1 :               child: EditableBackground(
     144           3 :                 backgroundColor: viewModel.bodyBox?.backgroundColor?.value,
     145             :                 circleIconKey: 'pal_EditorUpdateHelperWidget_BackgroundColorPicker',
     146           1 :                 onColorChange: presenter.changeBackgroundColor,
     147           1 :                 widget: Padding(
     148             :                   padding: const EdgeInsets.all(2.0),
     149           1 :                   child: Container(
     150             :                     width: double.infinity,
     151           3 :                     color: viewModel.bodyBox?.backgroundColor?.value,
     152           1 :                     child: Column(
     153             :                       mainAxisAlignment: MainAxisAlignment.spaceBetween,
     154           1 :                       children: _buildEditableContent(presenter, viewModel, context),
     155             :                     ),
     156             :                   ),
     157             :                 ),
     158             :               ),
     159             :             ),
     160             :           ),
     161             :         ),
     162             :       ),
     163             :     );
     164             :   }
     165             : 
     166           1 :   List<Widget> _buildEditableContent(
     167             :     final EditorUpdateHelperPresenter presenter,
     168             :     final UpdateHelperViewModel viewModel,
     169             :     final BuildContext context)
     170           1 :     => [
     171           1 :       Expanded(
     172           1 :         child: Center(
     173           1 :           child: SingleChildScrollView(
     174             :             reverse: false,
     175           1 :             controller: scrollController,
     176           1 :             child: Padding(
     177             :               padding: const EdgeInsets.only(
     178             :                 left: 10.0,
     179             :                 right: 10.0,
     180             :                 top: 25.0,
     181             :               ),
     182           1 :               child: Column(
     183             :                 crossAxisAlignment: CrossAxisAlignment.center,
     184           1 :                 children: [
     185           1 :                   EditableMedia(
     186             :                     editKey: 'pal_EditorUpdateHelperWidget_EditableMedia_EditButton',
     187             :                     mediaSize: 123.0,
     188           1 :                     onEdit: presenter.editMedia,
     189           3 :                     url: viewModel.media?.url?.value,
     190             :                   ),
     191           1 :                   SizedBox(height: 40),
     192           1 :                   _buildTitleField(context, presenter, viewModel),
     193           1 :                   SizedBox(height: 25.0),
     194           1 :                   _buildChangelogFields(context, presenter, viewModel),
     195             :                 ],
     196             :               ),
     197             :             ),
     198             :           ),
     199             :         ),
     200             :       ),
     201           1 :       Padding(
     202             :         padding: const EdgeInsets.only(
     203             :           bottom: 15.0,
     204             :           left: 10.0,
     205             :           right: 10.0,
     206             :         ),
     207           1 :         child: _buildThanksButton(context, presenter, viewModel),
     208             :       ),
     209             :     ];
     210             : 
     211           1 :   Widget _buildTitleField(
     212             :     final BuildContext context,
     213             :     final EditorUpdateHelperPresenter presenter,
     214             :     final UpdateHelperViewModel viewModel,
     215             :   ) {
     216           1 :     return EditableTextField.text(
     217           1 :       helperToolbarKey: ValueKey(
     218             :         'pal_EditorUpdateHelperWidget_TitleToolbar',
     219             :       ),
     220           1 :       textFormFieldKey: ValueKey(
     221             :         'pal_EditorUpdateHelperWidget_TitleField',
     222             :       ),
     223           2 :       hintText: viewModel.titleField?.hintText,
     224           1 :       onChanged: presenter.onTitleFieldChanged,
     225           1 :       onTextStyleChanged: presenter.onTitleTextStyleChanged,
     226           1 :       validator: presenter.validateTitleTextField,
     227             :       autovalidate: AutovalidateMode.disabled,
     228             :       maximumCharacterLength: 60,
     229             :       minimumCharacterLength: 1,
     230           3 :       fontFamilyKey: viewModel?.titleField?.fontFamily?.value,
     231           2 :       outsideTapStream: presenter.editableTextFieldController.stream,
     232           3 :       initialValue: viewModel?.titleField?.text?.value,
     233           1 :       textStyle: TextStyle(
     234           3 :         color: viewModel.titleField?.fontColor?.value,
     235           4 :         fontSize: viewModel.titleField?.fontSize?.value?.toDouble(),
     236           1 :         fontWeight: FontWeightMapper.toFontWeight(
     237           3 :           viewModel.titleField?.fontWeight?.value,
     238             :         ),
     239           5 :       ).merge(googleCustomFont(viewModel.titleField?.fontFamily?.value)),
     240             :     );
     241             :   }
     242             : 
     243           1 :   Widget _buildChangelogFields(
     244             :     final BuildContext context,
     245             :     final EditorUpdateHelperPresenter presenter,
     246             :     final UpdateHelperViewModel viewmodel,
     247             :   ) {
     248           1 :     List<Widget> changelogsTextfieldWidgets = List();
     249           3 :     viewmodel.changelogsFields.forEach((key, field) {
     250           2 :       changelogsTextfieldWidgets.add(editableField(
     251           2 :         presenter.editableTextFieldController.stream,
     252             :         field,
     253           1 :         presenter.onChangelogTextChanged,
     254           1 :         presenter.onChangelogTextStyleFieldChanged,
     255             :         id: key
     256             :       ));
     257             :     });
     258           1 :     return Column(
     259           1 :       children: [
     260           1 :         Wrap(
     261             :           children: changelogsTextfieldWidgets,
     262             :           spacing: 5.0,
     263             :           runSpacing: 5.0,
     264             :         ),
     265           1 :         Padding(
     266             :           padding: const EdgeInsets.only(top: 5.0, bottom: 16.0),
     267           1 :           child: CircleIconButton(
     268           1 :             key: ValueKey('pal_EditorUpdateHelperWidget_AddNote'),
     269             :             backgroundColor: Colors.transparent,
     270           1 :             icon: Icon(
     271             :               Icons.add,
     272           1 :               color: Colors.white.withAlpha(170),
     273             :               size: 35.0,
     274             :             ),
     275             :             displayShadow: false,
     276           1 :             onTapCallback: () {
     277           1 :               HapticFeedback.selectionClick();
     278           1 :               presenter.addChangelogNote();
     279             :             },
     280             :           ),
     281             :         ),
     282             :       ],
     283             :     );
     284             :   }
     285             : 
     286           1 :   Widget _buildThanksButton(
     287             :     final BuildContext context,
     288             :     final EditorUpdateHelperPresenter presenter,
     289             :     final UpdateHelperViewModel viewModel,
     290             :   ) {
     291           1 :     return SizedBox(
     292             :       width: double.infinity,
     293           1 :       child: EditableTextField.text(
     294           1 :         helperToolbarKey: ValueKey('pal_EditorUpdateHelperWidget_ThanksButtonToolbar',),
     295           1 :         textFormFieldKey: ValueKey('pal_EditorUpdateHelperWidget_ThanksButtonField',),
     296           2 :         outsideTapStream: presenter.editableTextFieldController.stream,
     297           1 :         onChanged: presenter.onThanksFieldChanged,
     298           1 :         onTextStyleChanged: presenter.onThanksTextStyleFieldChanged,
     299           2 :         hintText: viewModel.thanksButton?.hintText,
     300             :         maximumCharacterLength: 25,
     301           3 :         fontFamilyKey: viewModel?.thanksButton?.fontFamily?.value,
     302           3 :         initialValue: viewModel?.thanksButton?.text?.value,
     303           1 :         backgroundBoxDecoration: BoxDecoration(
     304           3 :           color: PalTheme.of(context).colors.dark,
     305           1 :           borderRadius: BorderRadius.circular(10.0),
     306             :         ),
     307           1 :         textStyle: TextStyle(
     308           3 :           color: viewModel.thanksButton?.fontColor?.value ?? Colors.white,
     309           4 :           fontSize: viewModel.thanksButton?.fontSize?.value?.toDouble() ?? 22.0,
     310           4 :           fontWeight: FontWeightMapper.toFontWeight(viewModel.thanksButton?.fontWeight?.value) ?? FontWeight.w400,
     311           5 :         ).merge(googleCustomFont(viewModel.thanksButton?.fontFamily?.value)),
     312             :       ),
     313             :     );
     314             :   }
     315             : 
     316             : 
     317             : 
     318           1 :   EditableTextField editableField(
     319             :     Stream<bool> outsideTapStream,
     320             :     TextFormFieldNotifier textNotifier,
     321             :     OnFieldChanged onFieldValueChange,
     322             :     OnTextStyleChanged onTextStyleChanged,
     323             :     { String id,
     324             :       Key helperToolbarKey,
     325             :       Key textFormFieldKey,
     326             :       TextStyle baseStyle,
     327             :       int minimumCharacterLength = 1,
     328             :       int maximumCharacterLength = 255,
     329             :       int maxLines = 5,
     330             :       BoxDecoration backgroundDecoration})
     331           1 :   => EditableTextField.text(
     332             :     id: id,
     333             :     backgroundBoxDecoration: backgroundDecoration,
     334             :     outsideTapStream: outsideTapStream,
     335             :     helperToolbarKey: helperToolbarKey,
     336             :     textFormFieldKey: textFormFieldKey,
     337             :     onChanged: onFieldValueChange,
     338             :     onTextStyleChanged: onTextStyleChanged,
     339             :     maximumCharacterLength: maximumCharacterLength,
     340             :     minimumCharacterLength: minimumCharacterLength,
     341             :     maxLines: maxLines,
     342           2 :     fontFamilyKey: textNotifier?.fontFamily?.value,
     343           2 :     initialValue: textNotifier?.text?.value,
     344           1 :     textStyle: TextStyle(
     345           2 :       color: textNotifier?.fontColor?.value,
     346             :       decoration: TextDecoration.none,
     347           3 :       fontSize: textNotifier?.fontSize?.value?.toDouble(),
     348           3 :       fontWeight: FontWeightMapper.toFontWeight(textNotifier?.fontWeight?.value),
     349             :     )
     350           1 :       .merge(baseStyle),
     351             :   );
     352             : 
     353             : 
     354             :   //FIXME CONsider extension
     355           1 :   TextStyle googleCustomFont(String fontFamily) {
     356           2 :     return (fontFamily != null && fontFamily.length > 0)
     357           1 :         ? GoogleFonts.getFont(fontFamily)
     358             :         : null;
     359             :   }
     360             : }
     361             : 
     362             : class _EditorUpdateHelperPage with EditorSendingOverlayMixin, EditorNavigationMixin implements EditorUpdateHelperView {
     363             : 
     364             :   final BuildContext context;
     365             :   final GlobalKey<ScaffoldState> scaffoldKey;
     366             :   final ScrollController scrollController;
     367             :   final PalEditModeStateService palEditModeStateService;
     368             : 
     369           1 :   _EditorUpdateHelperPage(this.context, this.scaffoldKey, this.scrollController, this.palEditModeStateService);
     370             : 
     371           2 :   BuildContext get overlayContext => context;
     372             : 
     373           1 :   @override
     374             :   void showColorPickerDialog(Color color, OnColorSelected onColorSelected, OnCancelPicker onCancel) {
     375           1 :     HapticFeedback.selectionClick();
     376           1 :     showOverlayedInContext(
     377           2 :       (context) => ColorPickerDialog(
     378             :         placeholderColor: color,
     379             :         onColorSelected: onColorSelected,
     380             :         onCancel: onCancel
     381             :       ),
     382             :       key: OverlayKeys.PAGE_OVERLAY_KEY
     383             :     );
     384             :   }
     385             : 
     386           0 :   @override
     387           0 :   void closeColorPickerDialog() => closeOverlayed(OverlayKeys.PAGE_OVERLAY_KEY);
     388             : 
     389             :   @override
     390           0 :   Future<GraphicEntity> pushToMediaGallery(final String mediaId) async {
     391           0 :     final media = await Navigator.pushNamed(
     392           0 :       scaffoldKey.currentContext,
     393             :       '/editor/media-gallery',
     394           0 :       arguments: MediaGalleryPageArguments(
     395             :         mediaId,
     396             :       ),
     397             :     ) as GraphicEntity;
     398             :     return media;
     399             :   }
     400             : 
     401           1 :   Future scrollToBottomChangelogList() async {
     402           2 :     if (scrollController.hasClients) {
     403           3 :       await scrollController.animateTo(
     404           3 :         scrollController.position.maxScrollExtent,
     405             :         curve: Curves.easeOut,
     406             :         duration: const Duration(milliseconds: 500),
     407             :       );
     408             :     }
     409             :   }
     410             : 
     411           1 :   @override
     412           3 :   void hidePalBubble() => this.palEditModeStateService.showBubble(context, false);
     413             : 
     414             : }

Generated by: LCOV version 1.14