LCOV - code coverage report
Current view: top level - src/ui/editor/pages/helpers_list - helpers_list_modal.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 126 162 77.8 %
Date: 2020-12-04 18:41:24 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:typed_data';
       2             : import 'dart:ui' as ui;
       3             : 
       4             : import 'package:flutter/material.dart';
       5             : import 'package:flutter/rendering.dart';
       6             : import 'package:flutter/services.dart';
       7             : import 'package:mvvm_builder/mvvm_builder.dart';
       8             : import 'package:pal/src/database/entity/helper/helper_entity.dart';
       9             : import 'package:pal/src/database/entity/helper/helper_trigger_type.dart';
      10             : import 'package:pal/src/database/entity/helper/helper_type.dart';
      11             : import 'package:pal/src/injectors/editor_app/editor_app_injector.dart';
      12             : import 'package:pal/src/services/editor/helper/helper_editor_service.dart';
      13             : import 'package:pal/src/services/pal/pal_state_service.dart';
      14             : import 'package:pal/src/ui/editor/pages/helper_details/helper_details_view.dart';
      15             : import 'package:pal/src/ui/editor/pages/helpers_list/helpers_list_loader.dart';
      16             : import 'package:pal/src/ui/editor/pages/helpers_list/helpers_list_modal_presenter.dart';
      17             : import 'package:pal/src/ui/editor/pages/helpers_list/helpers_list_modal_viewmodel.dart';
      18             : import 'package:pal/src/ui/editor/pages/helpers_list/widgets/helper_tile_widget.dart';
      19             : import 'package:pal/src/ui/editor/pages/create_helper/create_helper.dart';
      20             : import 'package:pal/src/ui/editor/pages/helper_details/helper_details_model.dart';
      21             : 
      22             : abstract class HelpersListModalView {
      23             : 
      24             :   void lookupHostedAppStruct(GlobalKey<NavigatorState> hostedAppNavigatorKey);
      25             : 
      26             :   void processElement(Element element, {int n = 0});
      27             : 
      28             :   Future<void> capturePng(
      29             :     final HelpersListModalPresenter presenter,
      30             :     final HelpersListModalModel model,
      31             :   );
      32             : 
      33             :   Future<bool> openHelperCreationPage(
      34             :     final String pageId,
      35             :   );
      36             : 
      37             :   Future<void> openAppSettingsPage();
      38             : 
      39             :   Future<HelperDetailsPopState> openHelperDetailPage(
      40             :     final HelperEntity helperEntity,
      41             :     final String pageId,
      42             :     final String pageRouteName,
      43             :   );
      44             : 
      45             :   void reorganizeHelper(
      46             :     final int oldIndex,
      47             :     final int newIndex,
      48             :     final HelpersListModalPresenter presenter,
      49             :     final List<HelperEntity> helpers,
      50             :   );
      51             : 
      52             :   void onCloseButton();
      53             : 
      54             :   void popModalDialog();
      55             : }
      56             : 
      57             : class HelpersListModal extends StatefulWidget {
      58             :   final GlobalKey<NavigatorState>
      59             :       hostedAppNavigatorKey; //FIXME remove this from here
      60             : 
      61             :   final GlobalKey repaintBoundaryKey;
      62             :   final BuildContext bottomModalContext;
      63             :   final HelpersListModalLoader loader;
      64             :   final PalEditModeStateService palEditModeStateService;
      65             :   final EditorHelperService helperService;
      66             : 
      67           2 :   HelpersListModal({
      68             :     Key key,
      69             :     this.loader,
      70             :     this.helperService,
      71             :     this.hostedAppNavigatorKey,
      72             :     this.repaintBoundaryKey,
      73             :     this.bottomModalContext,
      74             :     this.palEditModeStateService,
      75             :   });
      76             : 
      77           2 :   @override
      78           2 :   _HelpersListModalState createState() => _HelpersListModalState();
      79             : }
      80             : 
      81             : class _HelpersListModalState extends State<HelpersListModal>
      82             :     implements HelpersListModalView {
      83             :   final ScrollController _listController = ScrollController();
      84             : 
      85             :   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey(); // ignore: unused_field
      86             :   final _mvvmPageBuilder =
      87             :       MVVMPageBuilder<HelpersListModalPresenter, HelpersListModalModel>();
      88             : 
      89           2 :   @override
      90             :   Widget build(BuildContext context) {
      91           4 :     return _mvvmPageBuilder.build(
      92           2 :       key: ValueKey('pal_HelpersListModal_MvvmBuilder'),
      93             :       context: context,
      94           4 :       presenterBuilder: (context) => HelpersListModalPresenter(
      95             :         this,
      96           4 :         loader: this.widget.loader ??
      97           1 :             HelpersListModalLoader(
      98           2 :                 EditorInjector.of(context).pageEditorService,
      99           2 :                 EditorInjector.of(context).helperService,
     100           2 :                 EditorInjector.of(context).routeObserver),
     101           4 :         palEditModeStateService: this.widget.palEditModeStateService ??
     102           2 :             EditorInjector.of(context).palEditModeStateService,
     103           4 :         helperService: this.widget.helperService ??
     104           2 :             EditorInjector.of(context).helperService,
     105             :       ),
     106           2 :       builder: (context, presenter, model) {
     107           2 :         return Scaffold(
     108           2 :           body: this._buildPage(
     109           2 :             context.buildContext,
     110             :             presenter,
     111             :             model,
     112             :           ),
     113             :         );
     114             :       },
     115             :     );
     116             :   }
     117             : 
     118           2 :   Widget _buildPage(
     119             :     final BuildContext context,
     120             :     final HelpersListModalPresenter presenter,
     121             :     final HelpersListModalModel model,
     122             :   ) {
     123           2 :     return SafeArea(
     124           2 :       child: Padding(
     125             :         padding: const EdgeInsets.only(top: 15.0, bottom: 5.0),
     126           2 :         child: Column(
     127             :           mainAxisSize: MainAxisSize.max,
     128           2 :           children: [
     129           2 :             Padding(
     130             :               padding: const EdgeInsets.symmetric(horizontal: 24.0),
     131           2 :               child: _buildHeader(context, model, presenter),
     132             :             ),
     133           2 :             Expanded(
     134           2 :               child: Padding(
     135             :                 padding: const EdgeInsets.symmetric(vertical: 5.0),
     136           2 :                 child: _buildList(context, presenter, model),
     137             :               ),
     138             :             ),
     139           2 :             Padding(
     140             :               padding: const EdgeInsets.only(
     141             :                 bottom: 5.0,
     142             :                 top: 2.0,
     143             :               ),
     144           6 :               child: !model.isLoading && model.helpers != null && model.helpers.isNotEmpty
     145           1 :                   ? Text(
     146             :                       '💡 You can re-order helpers by long tap on them.',
     147           1 :                       key: ValueKey('pal_HelpersListModal_ReorderTip'),
     148           1 :                       style: TextStyle(
     149             :                         fontSize: 12.0,
     150             :                       ),
     151             :                     )
     152           2 :                   : Container(),
     153             :             ),
     154           2 :             Padding(
     155             :               padding: const EdgeInsets.symmetric(horizontal: 24.0),
     156           2 :               child: Align(
     157             :                 alignment: Alignment.bottomCenter,
     158           2 :                 child: _buildCloseButton(context),
     159             :               ),
     160             :             )
     161             :           ],
     162             :         ),
     163             :       ),
     164             :     );
     165             :   }
     166             : 
     167           2 :   Widget _buildCloseButton(
     168             :     final BuildContext context,
     169             :   ) {
     170           2 :     return SizedBox(
     171             :       width: double.infinity,
     172           2 :       child: OutlineButton(
     173           2 :         key: ValueKey('pal_HelpersListModal_Close'),
     174           2 :         child: Text(
     175             :           'Close',
     176           2 :           style: TextStyle(
     177             :             fontWeight: FontWeight.w300,
     178           4 :             color: Theme.of(context).accentColor,
     179             :           ),
     180             :         ),
     181           2 :         onPressed: onCloseButton,
     182           2 :         borderSide: BorderSide(
     183           4 :           color: Theme.of(context).accentColor,
     184             :         ),
     185           2 :         shape: RoundedRectangleBorder(
     186           2 :           borderRadius: BorderRadius.circular(8.0),
     187             :         ),
     188             :       ),
     189             :     );
     190             :   }
     191             : 
     192           2 :   Widget _buildList(
     193             :     final BuildContext context,
     194             :     final HelpersListModalPresenter presenter,
     195             :     final HelpersListModalModel model,
     196             :   ) {
     197           5 :     return (model.helpers != null && model.helpers.length > 0)
     198           1 :         ? ReorderableListView(
     199           2 :             onReorder: (oldIndex, newIndex) => this.reorganizeHelper(
     200             :               oldIndex,
     201             :               newIndex,
     202             :               presenter,
     203           1 :               model.helpers,
     204             :             ),
     205             :             padding: const EdgeInsets.only(top: 8.0),
     206           1 :             key: ValueKey('palHelpersListModalContent'),
     207           1 :             scrollController: _listController
     208           1 :               ..addListener(() {
     209           0 :                 if (_listController.position.extentAfter <= 100) {
     210           0 :                   presenter.loadMore();
     211             :                 }
     212             :               }),
     213           1 :             children: _buildHelpersList(model, presenter),
     214             :           )
     215           2 :         : Center(
     216           2 :             key: ValueKey('palHelpersListModalNoHelpers'),
     217           3 :             child: (model.isLoading || model.loadingMore)
     218           2 :                 ? CircularProgressIndicator()
     219           1 :                 : Text('No helpers on this page.'),
     220             :           );
     221             :   }
     222             : 
     223           1 :   List<Widget> _buildHelpersList(
     224             :       HelpersListModalModel model, HelpersListModalPresenter presenter) {
     225           1 :     List<Widget> helpers = [];
     226             : 
     227             :     int index = 0;
     228           2 :     for (HelperEntity anHelper in model.helpers) {
     229           1 :       Widget cell = Padding(
     230           3 :         key: ValueKey('pal_HelpersListModal_Tile${index++}'),
     231             :         padding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 24.0),
     232           1 :         child: HelperTileWidget(
     233           1 :           name: anHelper?.name,
     234           2 :           trigger: getHelperTriggerTypeDescription(anHelper?.triggerType),
     235           1 :           versionMin: anHelper?.versionMin,
     236           1 :           versionMax: anHelper?.versionMax,
     237             :           isDisabled: false,
     238           2 :           type: getHelperTypeDescription(anHelper?.type),
     239           1 :           onTapCallback: () {
     240           1 :             HapticFeedback.selectionClick();
     241           1 :             presenter.onClickHelper(anHelper);
     242             :           },
     243             :           // onTapCallback: () =>
     244             :           //     this.openHelperDetailPage(anHelper, model.pageId, presenter),
     245             :         ),
     246             :       );
     247           1 :       helpers.add(cell);
     248             :     }
     249             :     return helpers;
     250             :   }
     251             : 
     252           2 :   Widget _buildHeader(
     253             :     final BuildContext context,
     254             :     final HelpersListModalModel model,
     255             :     final HelpersListModalPresenter presenter,
     256             :   ) {
     257           2 :     return Row(
     258             :       mainAxisAlignment: MainAxisAlignment.spaceBetween,
     259             :       crossAxisAlignment: CrossAxisAlignment.center,
     260           2 :       children: [
     261           2 :         Image.asset(
     262             :           'packages/pal/assets/images/logo.png',
     263             :           height: 36.0,
     264             :         ),
     265           2 :         SizedBox(width: 12),
     266           2 :         Column(
     267             :           crossAxisAlignment: CrossAxisAlignment.start,
     268           2 :           children: [
     269           2 :             Text(
     270             :               'PAL editor',
     271           2 :               style: TextStyle(
     272             :                 fontSize: 20,
     273             :                 fontWeight: FontWeight.w500,
     274             :               ),
     275             :             ),
     276           2 :             SizedBox(height: 3.0),
     277           2 :             Text(
     278             :               'List of available helpers on this page',
     279           2 :               style: TextStyle(fontSize: 10.0, fontWeight: FontWeight.w300),
     280             :             )
     281             :           ],
     282             :         ),
     283           2 :         Flexible(
     284           2 :           child: Row(
     285             :             mainAxisAlignment: MainAxisAlignment.end,
     286             :             mainAxisSize: MainAxisSize.max,
     287           2 :             children: [
     288           2 :               _buildCircleButton(
     289             :                 'pal_HelpersListModal_Settings',
     290           2 :                 Icon(
     291             :                   Icons.settings,
     292             :                   size: 20,
     293             :                 ),
     294           2 :                 presenter.onClickSettings,
     295             :               ),
     296           2 :               SizedBox(width: 14.0),
     297           2 :               _buildCircleButton(
     298             :                 'pal_HelpersListModal_New',
     299           2 :                 Icon(
     300             :                   Icons.add,
     301             :                   size: 25,
     302             :                 ),
     303           2 :                 presenter.onClickAdd,
     304             :               ),
     305             :             ],
     306             :           ),
     307             :         ),
     308             :       ],
     309             :     );
     310             :   }
     311             : 
     312           0 :   @override
     313             :   void lookupHostedAppStruct(GlobalKey<NavigatorState> hostedAppNavigatorKey) {
     314             :     if (hostedAppNavigatorKey == null) {
     315             :       return;
     316             :     }
     317             :   }
     318             : 
     319           0 :   @override
     320             :   processElement(Element element, {int n = 0}) {
     321           0 :     if (element.widget.key != null) {
     322             :       var parentObject =
     323           0 :           widget.repaintBoundaryKey.currentContext.findRenderObject();
     324           0 :       if (element.widget is Scaffold) {
     325           0 :         print("SCAFFOLD");
     326             :       }
     327             :       var translation =
     328           0 :           element.renderObject.getTransformTo(parentObject).getTranslation();
     329           0 :       print("$n - key " +
     330           0 :           element.widget.key.toString() +
     331           0 :           " " +
     332           0 :           element.size.toString());
     333           0 :       print("translation ${translation.t} ${translation.r} ${translation.s}");
     334           0 :       print(
     335           0 :           "::bounds ${element.renderObject.paintBounds.shift(Offset(translation.x, translation.y))}");
     336           0 :       print("::bounds ${parentObject.paintBounds}");
     337             :     }
     338           0 :     element.visitChildElements((visitor) => processElement(visitor, n: n + 1));
     339             :   }
     340             : 
     341             :   @override
     342           0 :   Future<void> capturePng(
     343             :     final HelpersListModalPresenter presenter,
     344             :     final HelpersListModalModel model,
     345             :   ) async {
     346             :     try {
     347             :       RenderRepaintBoundary boundary =
     348           0 :           widget.repaintBoundaryKey.currentContext.findRenderObject();
     349           0 :       ui.Image image = await boundary.toImage(pixelRatio: 3.0);
     350             :       ByteData byteData =
     351           0 :           await image.toByteData(format: ui.ImageByteFormat.png);
     352             : 
     353           0 :       presenter.setImage(byteData);
     354             :     } catch (e) {
     355           0 :       print('error while catching screenshot');
     356           0 :       print(e);
     357             :     }
     358             :   }
     359             : 
     360             :   @override
     361           1 :   Future<bool> openHelperCreationPage(
     362             :     final String pageId,
     363             :   ) async {
     364           1 :     HapticFeedback.selectionClick();
     365             :     // Display the helper creation view
     366           2 :     final shouldOpenEditor = await Navigator.pushNamed(
     367           1 :       context,
     368             :       '/editor/new',
     369           1 :       arguments: CreateHelperPageArguments(
     370           2 :         widget.hostedAppNavigatorKey,
     371             :         pageId,
     372             :       ),
     373             :     );
     374             : 
     375             :     if (shouldOpenEditor != null && shouldOpenEditor) {
     376             :       // Dismiss the bottom modal when next was tapped
     377           0 :       Navigator.pop(widget.bottomModalContext);
     378             :     }
     379             :     return shouldOpenEditor;
     380             :   }
     381             : 
     382             :   @override
     383           1 :   Future<HelperDetailsPopState> openHelperDetailPage(
     384             :     final HelperEntity helperEntity,
     385             :     final String pageId,
     386             :     final String pageRouteName,
     387             :   ) async {
     388             :     // Display the helper detail view
     389           2 :     final helperDetailsPopState = await Navigator.pushNamed(
     390           1 :       context,
     391             :       '/editor/helper',
     392           1 :       arguments: HelperDetailsComponentArguments(
     393           2 :         widget.hostedAppNavigatorKey,
     394             :         helperEntity,
     395             :         pageId,
     396             :         pageRouteName
     397             :       ),
     398             :     ) as HelperDetailsPopState;
     399             : 
     400             :     return helperDetailsPopState;
     401             :   }
     402             : 
     403             :   @override
     404           0 :   Future openAppSettingsPage() async {
     405           0 :     HapticFeedback.selectionClick();
     406             :     // Display the helper creation view
     407           0 :     final shouldOpenEditor = await Navigator.pushNamed(
     408           0 :       context,
     409             :       '/settings',
     410             :     );
     411             : 
     412             :     if (shouldOpenEditor != null && shouldOpenEditor) {
     413             :       // Dismiss the bottom modal when next was tapped
     414           0 :       Navigator.pop(widget.bottomModalContext);
     415             :     }
     416             :   }
     417             : 
     418           2 :   Widget _buildCircleButton(
     419             :     final String key,
     420             :     final Icon icon,
     421             :     final Function callback,
     422             :   ) {
     423           2 :     return SizedBox(
     424             :       height: 32.0,
     425             :       width: 32.0,
     426           2 :       child: FloatingActionButton(
     427             :         heroTag: key,
     428           2 :         key: ValueKey(key),
     429             :         onPressed: callback,
     430             :         child: icon,
     431           2 :         shape: CircleBorder(),
     432             :       ),
     433             :     );
     434             :   }
     435             : 
     436           1 :   @override
     437             :   void reorganizeHelper(
     438             :     int oldIndex,
     439             :     int newIndex,
     440             :     HelpersListModalPresenter presenter,
     441             :     List<HelperEntity> helpers,
     442             :   ) {
     443             :     // First backup list before re-organize
     444           1 :     presenter.backupHelpersList();
     445             : 
     446             :     // Change on Front
     447           1 :     if (newIndex > oldIndex) {
     448           1 :       newIndex -= 1;
     449             :     }
     450           1 :     final HelperEntity helperEntity = helpers.removeAt(oldIndex);
     451           1 :     helpers.insert(newIndex, helperEntity);
     452           1 :     presenter.refreshView();
     453             : 
     454             :     // Then submit change on back
     455           1 :     presenter.sendNewHelpersOrder(oldIndex, newIndex);
     456             :   }
     457             : 
     458           0 :   @override
     459             :   void onCloseButton() {
     460           0 :     HapticFeedback.selectionClick();
     461           0 :     Navigator.pop(context);
     462             :   }
     463             : 
     464           0 :   @override
     465             :   void popModalDialog() {
     466           0 :     Navigator.pop(widget.bottomModalContext);
     467             :   }
     468             : }

Generated by: LCOV version 1.14