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:mvvm_builder/mvvm_builder.dart';
5 : import 'package:pal/src/database/entity/graphic_entity.dart';
6 : import 'package:pal/src/database/entity/helper/helper_entity.dart';
7 : import 'package:pal/src/injectors/editor_app/editor_app_injector.dart';
8 : import 'package:pal/src/services/editor/helper/helper_editor_service.dart';
9 : import 'package:pal/src/services/pal/pal_state_service.dart';
10 : import 'package:pal/src/ui/editor/pages/helper_editor/font_editor/pickers/font_weight_picker/font_weight_picker_loader.dart';
11 : import 'package:pal/src/ui/editor/pages/helper_editor/helper_editor.dart';
12 : import 'package:pal/src/ui/editor/pages/helper_editor/helper_editor_notifiers.dart';
13 : import 'package:pal/src/ui/editor/pages/helper_editor/helper_editor_viewmodel.dart';
14 : import 'package:pal/src/ui/editor/pages/helper_editor/widgets/color_picker.dart';
15 : import 'package:pal/src/ui/editor/pages/helper_editor/widgets/editor_actionsbar.dart';
16 : import 'package:pal/src/ui/editor/pages/helper_editor/widgets/editor_sending_overlay.dart';
17 : import 'package:pal/src/ui/editor/pages/media_gallery/media_gallery.dart';
18 : import 'package:pal/src/ui/editor/widgets/editable_background.dart';
19 : import 'package:pal/src/ui/editor/widgets/editable_media.dart';
20 : import 'package:pal/src/ui/editor/widgets/editable_textfield.dart';
21 : import 'package:pal/src/ui/shared/widgets/overlayed.dart';
22 :
23 : import '../../../../../../router.dart';
24 : import 'editor_fullscreen_helper_presenter.dart';
25 : import 'editor_fullscreen_helper_viewmodel.dart';
26 :
27 : abstract class EditorFullScreenHelperView {
28 :
29 : void showColorPickerDialog(
30 : FullscreenHelperViewModel viewModel,
31 : EditorFullScreenHelperPresenter presenter,
32 : );
33 :
34 : Future<GraphicEntity> pushToMediaGallery(final String mediaId);
35 :
36 : void closeColorPickerDialog();
37 :
38 : TextStyle googleCustomFont(String fontFamily);
39 :
40 : Future showLoadingScreen(ValueNotifier<SendingStatus> status);
41 :
42 : Future closeEditor();
43 :
44 : void closeLoadingScreen();
45 : }
46 :
47 : class EditorFullScreenHelper with EditorSendingOverlayMixin, EditorNavigationMixin implements EditorFullScreenHelperView {
48 :
49 : BuildContext context;
50 :
51 : final PalEditModeStateService palEditModeStateService;
52 :
53 : EditorSendingOverlay sendingOverlay;
54 :
55 1 : EditorFullScreenHelper(this.context, this.palEditModeStateService) {
56 2 : overlayContext = context;
57 : }
58 :
59 1 : @override
60 : void showColorPickerDialog(
61 : FullscreenHelperViewModel viewModel,
62 : EditorFullScreenHelperPresenter presenter,
63 : ) {
64 1 : HapticFeedback.selectionClick();
65 1 : showOverlayedInContext(
66 2 : (context) => ColorPickerDialog(
67 3 : placeholderColor: viewModel.bodyBox.backgroundColor?.value,
68 1 : onColorSelected: presenter.updateBackgroundColor,
69 1 : onCancel: presenter.cancelUpdateBackgroundColor
70 : ),
71 : key: OverlayKeys.PAGE_OVERLAY_KEY
72 : );
73 : }
74 :
75 2 : void closeColorPickerDialog() => closeOverlayed(OverlayKeys.PAGE_OVERLAY_KEY);
76 :
77 : @override
78 0 : Future<GraphicEntity> pushToMediaGallery(final String mediaId) async {
79 0 : final media = await Navigator.of(context).pushNamed(
80 : '/editor/media-gallery',
81 0 : arguments: MediaGalleryPageArguments(
82 : mediaId,
83 : ),
84 : ) as GraphicEntity;
85 : return media;
86 : }
87 :
88 1 : @override
89 : TextStyle googleCustomFont(String fontFamily) {
90 2 : return (fontFamily != null && fontFamily.length > 0)
91 1 : ? GoogleFonts.getFont(fontFamily)
92 : : null;
93 : }
94 :
95 : }
96 :
97 : typedef OnFormChanged(bool isValid);
98 :
99 : /// [EditorFullScreenHelperPage]
100 : /// can be created from entity or nothing
101 : /// use [EditorHelperService] to create a fullscreen helper
102 : class EditorFullScreenHelperPage extends StatelessWidget {
103 :
104 : final PresenterBuilder<EditorFullScreenHelperPresenter> presenterBuilder;
105 :
106 : final GlobalKey<FormState> formKey = GlobalKey();
107 :
108 1 : EditorFullScreenHelperPage._({
109 : Key key,
110 : @required this.presenterBuilder,
111 1 : }) : super(key: key);
112 :
113 1 : factory EditorFullScreenHelperPage.create({
114 : Key key,
115 : HelperEditorPageArguments parameters,
116 : EditorHelperService helperService,
117 : PalEditModeStateService palEditModeStateService,
118 : @required HelperViewModel helperViewModel
119 1 : }) => EditorFullScreenHelperPage._(
120 : key: key,
121 2 : presenterBuilder: (context) => EditorFullScreenHelperPresenter(
122 1 : new EditorFullScreenHelper(
123 : context,
124 0 : palEditModeStateService ?? EditorInjector.of(context).palEditModeStateService),
125 1 : FullscreenHelperViewModel.fromHelperViewModel(helperViewModel),
126 0 : helperService ?? EditorInjector.of(context).helperService,
127 : parameters
128 : ),
129 : );
130 :
131 1 : factory EditorFullScreenHelperPage.edit({
132 : Key key,
133 : HelperEditorPageArguments parameters,
134 : EditorHelperService helperService,
135 : PalEditModeStateService palEditModeStateService,
136 : @required HelperEntity helperEntity //FIXME should be an id and not entire entity
137 1 : }) => EditorFullScreenHelperPage._(
138 : key: key,
139 1 : presenterBuilder: (context)
140 1 : => EditorFullScreenHelperPresenter(
141 1 : new EditorFullScreenHelper(
142 : context,
143 0 : palEditModeStateService ?? EditorInjector.of(context).palEditModeStateService),
144 1 : FullscreenHelperViewModel.fromHelperEntity(helperEntity),
145 0 : helperService ?? EditorInjector.of(context).helperService,
146 : parameters
147 : ),
148 : );
149 :
150 1 : @override
151 : Widget build(BuildContext context) {
152 1 : return MVVMPageBuilder<EditorFullScreenHelperPresenter, FullscreenHelperViewModel>()
153 1 : .build(
154 1 : key: ValueKey('palEditorFullscreenHelperWidgetBuilder'),
155 : context: context,
156 1 : presenterBuilder: presenterBuilder,
157 3 : builder: (context, presenter, model) => _buildPage(context.buildContext, presenter, model),
158 : );
159 : }
160 :
161 1 : Widget _buildPage(
162 : final BuildContext context,
163 : final EditorFullScreenHelperPresenter presenter,
164 : final FullscreenHelperViewModel model,
165 : ) {
166 1 : return Scaffold(
167 : backgroundColor: Colors.transparent,
168 : resizeToAvoidBottomPadding: true,
169 1 : body: EditorActionsBar(
170 1 : canValidate: model.canValidate,
171 1 : onCancel: presenter.onCancel,
172 1 : onValidate: presenter.onValidate,
173 1 : child: GestureDetector(
174 1 : key: ValueKey('palEditorFullscreenHelperWidget'),
175 1 : onTap: presenter.onOutsideTap,
176 1 : child: AnimatedOpacity(
177 1 : duration: Duration(milliseconds: 500),
178 : curve: Curves.fastOutSlowIn,
179 1 : opacity: model.helperOpacity,
180 1 : child: Form(
181 1 : key: formKey,
182 : autovalidateMode: AutovalidateMode.onUserInteraction,
183 1 : child: EditableBackground(
184 3 : backgroundColor: model.bodyBox.backgroundColor?.value,
185 : circleIconKey: 'pal_EditorFullScreenHelperPage_BackgroundColorPicker',
186 2 : onColorChange: () => presenter.changeBackgroundColor(),
187 1 : widget: Center(
188 1 : child: Padding(
189 1 : padding: EdgeInsets.symmetric(horizontal: 16),
190 1 : child: SafeArea(
191 1 : child: SingleChildScrollView(
192 1 : padding: EdgeInsets.only(top: 25.0, bottom: 32.0),
193 1 : child: Column(
194 : mainAxisAlignment: MainAxisAlignment.center,
195 1 : children: [
196 1 : EditableMedia(
197 : mediaSize: 240.0,
198 1 : onEdit: presenter.editMedia,
199 3 : url: model.media?.url?.value,
200 : editKey: 'pal_EditorFullScreenHelperPage_EditableMedia_EditButton',
201 : ),
202 1 : SizedBox(height: 24),
203 1 : editableField(
204 2 : model.editableTextFieldController.stream,
205 1 : model?.titleField,
206 1 : presenter.onTitleChanged,
207 1 : presenter.onTitleTextStyleChanged,
208 4 : baseStyle: presenter.googleCustomFont(model?.titleField?.fontFamily?.value),
209 1 : helperToolbarKey: ValueKey('palEditorFullscreenHelperWidgetToolbar'),
210 1 : textFormFieldKey: ValueKey('palFullscreenHelperTitleField'),
211 : ),
212 1 : SizedBox(height: 24),
213 1 : editableField(
214 2 : model.editableTextFieldController.stream,
215 1 : model?.descriptionField,
216 1 : presenter.onDescriptionChanged,
217 1 : presenter.onDescriptionTextStyleChanged,
218 4 : baseStyle: presenter.googleCustomFont(model?.titleField?.fontFamily?.value),
219 1 : helperToolbarKey: ValueKey('palEditorFullscreenHelperWidgetToolbar'),
220 1 : textFormFieldKey: ValueKey('palFullscreenHelperDescriptionField'),
221 : ),
222 1 : Padding(
223 : padding: const EdgeInsets.only(top: 40.0),
224 1 : child: editableButton(
225 2 : model.editableTextFieldController.stream,
226 1 : model.positivButtonField,
227 1 : presenter.onPositivTextChanged,
228 1 : presenter.onPositivTextStyleChanged
229 : ),
230 : ),
231 1 : Padding(
232 : padding: const EdgeInsets.only(top: 12.0),
233 1 : child: editableButton(
234 2 : model.editableTextFieldController.stream,
235 1 : model.negativButtonField,
236 1 : presenter.onNegativTextChanged,
237 1 : presenter.onNegativTextStyleChanged
238 : ),
239 : ),
240 : ],
241 : ),
242 : ),
243 : ),
244 : ),
245 : ),
246 : ),
247 : ),
248 : ),
249 : ),
250 : ),
251 : );
252 : }
253 :
254 1 : EditableTextField editableField(
255 : Stream<bool> outsideTapStream,
256 : TextFormFieldNotifier textNotifier,
257 : OnFieldChanged onFieldValueChange,
258 : OnTextStyleChanged onTextStyleChanged,
259 : { Key helperToolbarKey,
260 : Key textFormFieldKey,
261 : TextStyle baseStyle,
262 : int minimumCharacterLength = 1,
263 : int maximumCharacterLength = 255,
264 : int maxLines = 5,
265 : BoxDecoration backgroundDecoration})
266 1 : => EditableTextField.text(
267 : backgroundBoxDecoration: backgroundDecoration,
268 : outsideTapStream: outsideTapStream,
269 : helperToolbarKey: helperToolbarKey,
270 : textFormFieldKey: textFormFieldKey,
271 : onChanged: onFieldValueChange,
272 : onTextStyleChanged: onTextStyleChanged,
273 : maximumCharacterLength: maximumCharacterLength,
274 : minimumCharacterLength: minimumCharacterLength,
275 : maxLines: maxLines,
276 2 : fontFamilyKey: textNotifier?.fontFamily?.value,
277 2 : initialValue: textNotifier?.text?.value,
278 1 : textStyle: TextStyle(
279 2 : color: textNotifier?.fontColor?.value,
280 : decoration: TextDecoration.none,
281 3 : fontSize: textNotifier?.fontSize?.value?.toDouble(),
282 3 : fontWeight: FontWeightMapper.toFontWeight(textNotifier?.fontWeight?.value),
283 : )
284 1 : .merge(baseStyle),
285 : );
286 :
287 :
288 1 : Widget editableButton(
289 : Stream<bool> outsideTapStream,
290 : TextFormFieldNotifier textNotifier,
291 : OnFieldChanged onFieldValueChange,
292 : OnTextStyleChanged onTextStyleChanged,
293 : { int minimumCharacterLength = 1,
294 : int maximumCharacterLength = 255,
295 : int maxLines = 1})
296 1 : => InkWell(
297 1 : child: editableField(
298 : outsideTapStream,
299 : textNotifier,
300 : onFieldValueChange,
301 : onTextStyleChanged,
302 : minimumCharacterLength: minimumCharacterLength,
303 : maximumCharacterLength: maximumCharacterLength,
304 : maxLines: maxLines,
305 1 : backgroundDecoration: BoxDecoration(
306 1 : border: Border.all(
307 : color: Colors.white,
308 : width: 2
309 : ),
310 : // color: Colors.redAccent.withOpacity(0.8),
311 1 : borderRadius: BorderRadius.circular(10.0),
312 : )
313 : ),
314 : );
315 :
316 : }
|