Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 144 additions & 95 deletions client/lib/core/widgets/custom_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
import 'package:client/styles/styles.dart';
import 'package:client/core/localization/localization_helper.dart';
import 'package:universal_html/js.dart' as universal_js;
import 'package:markdown_editor_plus/markdown_editor_plus.dart';

enum BorderType {
none,
Expand Down Expand Up @@ -190,6 +191,8 @@ class CustomTextField extends StatefulWidget {
/// Allow for custom input formatters
final TextInputFormatter? inputFormatters;

final bool markdownEditor;

const CustomTextField({
Key? key,
this.padding = const EdgeInsets.only(top: 15),
Expand Down Expand Up @@ -237,6 +240,7 @@ class CustomTextField extends StatefulWidget {
this.suffixIcon,
this.keyboardType = TextInputType.text,
this.inputFormatters,
this.markdownEditor = false,
}) : super(key: key);

@override
Expand Down Expand Up @@ -364,102 +368,147 @@ class _CustomTextFieldState extends State<CustomTextField> {
),
child: Stack(
children: [
TextFormField(
onTap: () {
_unfocus();
final localOnTap = widget.onTap;
if (localOnTap != null) {
localOnTap();
}
},
onChanged: (text) {
final onChanged = widget.onChanged;
if (onChanged != null) {
onChanged(text);
}
},
onFieldSubmitted: (value) {
widget.onEditingComplete?.call();
},
focusNode: _focusNode,
textInputAction: TextInputAction.none,
controller: _controller,
style: widget.textStyle ?? context.theme.textTheme.bodyMedium,
onEditingComplete: widget.onEditingComplete,
// This is absolutely nuts, but this is needed for now in order to allow a unit test to succeed,
// while not having to specify max lines for every single usage 🙄
maxLines: widget.maxLines == null
? null
: !widget.minLines.compareTo(widget.maxLines!).isNegative
? widget.minLines
: widget.maxLines,
minLines: widget.minLines,
obscureText: widget.obscureText,
cursorColor:
widget.cursorColor ?? context.theme.colorScheme.primary,
cursorHeight: 20,
autovalidateMode: widget.autovalidateMode,
maxLength: widget.maxLength,
buildCounter: (
_, {
required currentLength,
required maxLength,
required isFocused,
}) =>
maxLength != null && !widget.hideCounter
? Container(
margin: EdgeInsets.only(left: 10),
alignment: widget.counterAlignment ??
Alignment.centerRight,
child: isFocused
? Text(
'$currentLength/$maxLength',
style: widget.counterStyle ??
AppTextStyle.bodySmall,
)
: SizedBox.square(
dimension: widget.counterStyle?.fontSize ??
AppTextStyle.bodySmall.fontSize,
),
)
: null,
maxLengthEnforcement: widget.maxLengthEnforcement,
inputFormatters: [
if (widget.isOnlyDigits)
FilteringTextInputFormatter.digitsOnly,
if (widget.numberThreshold != null)
NumberThresholdFormatter(widget.numberThreshold!)
else if (widget.inputFormatters != null)
widget.inputFormatters!,
],
validator: widget.validator,
decoration: InputDecoration(
contentPadding: widget.contentPadding,
border: _getBorder(),
focusedBorder: _getFocusedBorder(),
enabledBorder: _getBorder(),
errorBorder: _getBorder(isError: true),
focusedErrorBorder: _getFocusedBorder(isError: true),
labelText: widget.labelText,
labelStyle: _buildLabelStyle(),
errorStyle: context.theme.textTheme.labelMedium!
.copyWith(color: context.theme.colorScheme.error),
prefixText: widget.prefixText,
prefixStyle: widget.textStyle,
alignLabelWithHint: true,
hintText: widget.hintText,
hintStyle: context.theme.textTheme.bodyMedium,
helperText: widget.helperText,
fillColor: widget.fillColor,
filled: widget.fillColor != null,
suffixIcon: widget.suffixIcon,
if (widget.markdownEditor)
MarkdownAutoPreview(
emojiConvert: true,
minLines: 4,
maxLines: 10,
writeOnly: true,
onChanged: (text) {
final onChanged = widget.onChanged;
if (onChanged != null) {
onChanged(text);
}
},
toolbarBackground: Colors.transparent,
controller: _controller,
decoration: InputDecoration(
// make room with contentPadding for toolbar
contentPadding: EdgeInsets.fromLTRB(
widget.contentPadding?.left ?? 12,
(widget.contentPadding?.top ?? 12) + 110,
widget.contentPadding?.right ?? 12,
widget.contentPadding?.bottom ?? 12,
),
border: _getBorder(),
focusedBorder: _getFocusedBorder(),
enabledBorder: _getBorder(),
errorBorder: _getBorder(isError: true),
focusedErrorBorder: _getFocusedBorder(isError: true),
labelText: widget.labelText,
labelStyle: _buildLabelStyle(),
errorStyle: context.theme.textTheme.labelMedium!
.copyWith(color: context.theme.colorScheme.error),
prefixText: widget.prefixText,
prefixStyle: widget.textStyle,
alignLabelWithHint: true,
hintText: widget.hintText,
hintStyle: context.theme.textTheme.bodyMedium,
helperText: widget.helperText,
fillColor: widget.fillColor,
filled: widget.fillColor != null,
suffixIcon: widget.suffixIcon,
),
borderColor: _getBorderColor(),
),
if (!widget.markdownEditor)
TextFormField(
onTap: () {
_unfocus();
final localOnTap = widget.onTap;
if (localOnTap != null) {
localOnTap();
}
},
onChanged: (text) {
final onChanged = widget.onChanged;
if (onChanged != null) {
onChanged(text);
}
},
onFieldSubmitted: (value) {
widget.onEditingComplete?.call();
},
focusNode: _focusNode,
textInputAction: TextInputAction.none,
controller: _controller,
style: widget.textStyle ?? context.theme.textTheme.bodyMedium,
onEditingComplete: widget.onEditingComplete,
// This is absolutely nuts, but this is needed for now in order to allow a unit test to succeed,
// while not having to specify max lines for every single usage 🙄
maxLines: widget.maxLines == null
? null
: !widget.minLines.compareTo(widget.maxLines!).isNegative
? widget.minLines
: widget.maxLines,
minLines: widget.minLines,
obscureText: widget.obscureText,
cursorColor:
widget.cursorColor ?? context.theme.colorScheme.primary,
cursorHeight: 20,
autovalidateMode: widget.autovalidateMode,
maxLength: widget.maxLength,
buildCounter: (
_, {
required currentLength,
required maxLength,
required isFocused,
}) =>
maxLength != null && !widget.hideCounter
? Container(
margin: EdgeInsets.only(left: 10),
alignment: widget.counterAlignment ??
Alignment.centerRight,
child: isFocused
? Text(
'$currentLength/$maxLength',
style: widget.counterStyle ??
AppTextStyle.bodySmall,
)
: SizedBox.square(
dimension: widget.counterStyle?.fontSize ??
AppTextStyle.bodySmall.fontSize,
),
)
: null,
maxLengthEnforcement: widget.maxLengthEnforcement,
inputFormatters: [
if (widget.isOnlyDigits)
FilteringTextInputFormatter.digitsOnly,
if (widget.numberThreshold != null)
NumberThresholdFormatter(widget.numberThreshold!)
else if (widget.inputFormatters != null)
widget.inputFormatters!,
],
validator: widget.validator,
decoration: InputDecoration(
contentPadding: widget.contentPadding,
border: _getBorder(),
focusedBorder: _getFocusedBorder(),
enabledBorder: _getBorder(),
errorBorder: _getBorder(isError: true),
focusedErrorBorder: _getFocusedBorder(isError: true),
labelText: widget.labelText,
labelStyle: _buildLabelStyle(),
errorStyle: context.theme.textTheme.labelMedium!
.copyWith(color: context.theme.colorScheme.error),
prefixText: widget.prefixText,
prefixStyle: widget.textStyle,
alignLabelWithHint: true,
hintText: widget.hintText,
hintStyle: context.theme.textTheme.bodyMedium,
helperText: widget.helperText,
fillColor: widget.fillColor,
filled: widget.fillColor != null,
suffixIcon: widget.suffixIcon,
),
autofocus: widget.autofocus,
readOnly: widget.readOnly,
enabled: !widget.readOnly,
keyboardType: widget.keyboardType,
),
autofocus: widget.autofocus,
readOnly: widget.readOnly,
enabled: !widget.readOnly,
keyboardType: widget.keyboardType,
),
if (widget.isOptional &&
if (!widget.markdownEditor &&
widget.isOptional &&
!_focusNode.hasFocus &&
_controller.text.isEmpty)
Align(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:client/features/events/features/live_meeting/features/meeting_agenda/data/models/agenda_item_text_data.dart';
import 'package:client/core/widgets/custom_text_field.dart';
import 'package:client/styles/styles.dart';
import 'package:markdown_editor_plus/markdown_editor_plus.dart';

class AgendaItemText extends StatelessWidget {
final bool isEditMode;
Expand Down Expand Up @@ -37,6 +38,7 @@ class AgendaItemText extends StatelessWidget {
SizedBox(height: 20),
CustomTextField(
initialValue: agendaItemTextData.content,
markdownEditor: true,
labelText: 'Content',
hintText:
'Keep it short! You don’t want people to spend time reading.',
Expand Down
23 changes: 20 additions & 3 deletions client/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
expandable:
dependency: transitive
description:
name: expandable
sha256: "9604d612d4d1146dafa96c6d8eec9c2ff0994658d6d09fed720ab788c7f5afc2"
url: "https://pub.dev"
source: hosted
version: "5.0.1"
fake_async:
dependency: transitive
description:
Expand Down Expand Up @@ -645,10 +653,10 @@ packages:
dependency: "direct main"
description:
name: flutter_markdown
sha256: "04c4722cc36ec5af38acc38ece70d22d3c2123c61305d555750a091517bbe504"
sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
url: "https://pub.dev"
source: hosted
version: "0.6.23"
version: "0.7.7+1"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
Expand Down Expand Up @@ -1046,6 +1054,15 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.2.2"
markdown_editor_plus:
dependency: "direct main"
description:
path: "."
ref: main
resolved-ref: b6b78c6ebb63f09f1f02d84bfa4e9ae234c3828e
url: "https://github.com/dariusk/markdown_editor_plus.git"
source: git
version: "0.2.15"
matcher:
dependency: transitive
description:
Expand Down Expand Up @@ -1949,4 +1966,4 @@ packages:
version: "2.0.2"
sdks:
dart: ">=3.4.1 <4.0.0"
flutter: ">=3.19.0"
flutter: ">=3.22.0"
6 changes: 5 additions & 1 deletion client/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ environment:
sdk: ">=2.17.0 <4.0.0"

dependencies:
markdown_editor_plus:
git:
url: https://github.com/dariusk/markdown_editor_plus.git
ref: main
json_annotation: ^4.9.0
crypto: ^3.0.2
duration: ^3.0.13
Expand Down Expand Up @@ -44,7 +48,7 @@ dependencies:
responsive_builder: ^0.7.0
datetime_picker_formfield: ^2.0.1
flutter_form_builder: ^9.2.1
flutter_markdown: ^0.6.15
flutter_markdown: ^0.7.2+1
ntp: ^2.0.0
transparent_image: ^2.0.1
timezone: ^0.9.2
Expand Down
Loading