diff --git a/lib/screens/common_widgets/env_regexp_span_builder.dart b/lib/screens/common_widgets/env_regexp_span_builder.dart new file mode 100644 index 00000000..25124cb4 --- /dev/null +++ b/lib/screens/common_widgets/env_regexp_span_builder.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:extended_text_field/extended_text_field.dart'; +import 'package:apidash/consts.dart'; +import 'envvar_span.dart'; + +class EnvRegExpSpanBuilder extends RegExpSpecialTextSpanBuilder { + @override + List get regExps => [ + RegExpEnvText(), + ]; +} + +class RegExpEnvText extends RegExpSpecialText { + @override + RegExp get regExp => kEnvVarRegEx; + @override + InlineSpan finishText(int start, Match match, + {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) { + final String value = '${match[0]}'; + return ExtendedWidgetSpan( + actualText: value, + start: start, + alignment: PlaceholderAlignment.middle, + child: EnvVarSpan(variableKey: value.substring(2, value.length - 2)), + ); + } +} diff --git a/lib/screens/common_widgets/env_trigger_field.dart b/lib/screens/common_widgets/env_trigger_field.dart new file mode 100644 index 00000000..cfc12455 --- /dev/null +++ b/lib/screens/common_widgets/env_trigger_field.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart'; +import 'package:extended_text_field/extended_text_field.dart'; +import 'env_regexp_span_builder.dart'; +import 'env_trigger_options.dart'; + +class EnvironmentTriggerField extends StatefulWidget { + const EnvironmentTriggerField({ + super.key, + required this.keyId, + this.initialValue, + this.onChanged, + this.onFieldSubmitted, + this.style, + this.decoration, + }); + + final String keyId; + final String? initialValue; + final void Function(String)? onChanged; + final void Function(String)? onFieldSubmitted; + final TextStyle? style; + final InputDecoration? decoration; + + @override + State createState() => + _EnvironmentTriggerFieldState(); +} + +class _EnvironmentTriggerFieldState extends State { + final TextEditingController controller = TextEditingController(); + final FocusNode focusNode = FocusNode(); + + @override + void initState() { + super.initState(); + controller.text = widget.initialValue ?? ''; + controller.selection = + TextSelection.collapsed(offset: controller.text.length); + } + + @override + void dispose() { + controller.dispose(); + focusNode.dispose(); + super.dispose(); + } + + @override + void didUpdateWidget(EnvironmentTriggerField oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.initialValue != widget.initialValue) { + controller.text = widget.initialValue ?? ""; + controller.selection = + TextSelection.collapsed(offset: controller.text.length); + } + } + + @override + Widget build(BuildContext context) { + return MultiTriggerAutocomplete( + key: Key(widget.keyId), + textEditingController: controller, + focusNode: focusNode, + autocompleteTriggers: [ + AutocompleteTrigger( + trigger: '{', + triggerEnd: "}}", + triggerOnlyAfterSpace: false, + optionsViewBuilder: (context, autocompleteQuery, controller) { + return EnvironmentAutocompleteOptions( + query: autocompleteQuery.query, + onSuggestionTap: (suggestion) { + final autocomplete = MultiTriggerAutocomplete.of(context); + autocomplete.acceptAutocompleteOption( + '{${suggestion.variable.key}', + ); + widget.onChanged?.call(controller.text); + }); + }), + AutocompleteTrigger( + trigger: '{{', + triggerEnd: "}}", + triggerOnlyAfterSpace: false, + optionsViewBuilder: (context, autocompleteQuery, controller) { + return EnvironmentAutocompleteOptions( + query: autocompleteQuery.query, + onSuggestionTap: (suggestion) { + final autocomplete = MultiTriggerAutocomplete.of(context); + autocomplete.acceptAutocompleteOption( + suggestion.variable.key, + ); + widget.onChanged?.call(controller.text); + }); + }), + ], + fieldViewBuilder: (context, textEditingController, focusnode) { + return ExtendedTextField( + controller: textEditingController, + focusNode: focusnode, + decoration: widget.decoration, + style: widget.style, + onChanged: widget.onChanged, + onSubmitted: widget.onFieldSubmitted, + specialTextSpanBuilder: EnvRegExpSpanBuilder(), + ); + }, + ); + } +} diff --git a/lib/screens/common_widgets/env_trigger_options.dart b/lib/screens/common_widgets/env_trigger_options.dart new file mode 100644 index 00000000..e6550503 --- /dev/null +++ b/lib/screens/common_widgets/env_trigger_options.dart @@ -0,0 +1,66 @@ +import 'package:apidash/consts.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:apidash/models/models.dart'; +import 'package:apidash/providers/providers.dart'; +import 'package:apidash/utils/utils.dart'; + +import 'envvar_indicator.dart'; + +class EnvironmentAutocompleteOptions extends ConsumerWidget { + const EnvironmentAutocompleteOptions({ + super.key, + required this.query, + required this.onSuggestionTap, + }); + + final String query; + final ValueSetter onSuggestionTap; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final envMap = ref.watch(availableEnvironmentVariablesStateProvider); + final activeEnvironmentId = ref.watch(activeEnvironmentIdStateProvider); + final suggestions = + getEnvironmentTriggerSuggestions(query, envMap, activeEnvironmentId); + return suggestions == null || suggestions.isEmpty + ? const SizedBox.shrink() + : ClipRRect( + borderRadius: kBorderRadius8, + child: Material( + type: MaterialType.card, + elevation: 8, + child: ConstrainedBox( + constraints: + const BoxConstraints(maxHeight: kSuggestionsMenuMaxHeight), + child: Ink( + width: kSuggestionsMenuWidth, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: kBorderRadius8, + border: Border.all( + color: Theme.of(context).colorScheme.outlineVariant, + ), + ), + child: ListView.separated( + shrinkWrap: true, + itemCount: suggestions.length, + separatorBuilder: (context, index) => + const Divider(height: 2), + itemBuilder: (context, index) { + final suggestion = suggestions[index]; + return ListTile( + dense: true, + leading: EnvVarIndicator(suggestion: suggestion), + title: Text(suggestion.variable.key), + subtitle: Text(suggestion.variable.value), + onTap: () => onSuggestionTap(suggestion), + ); + }, + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/common_widgets/envfield_cell.dart b/lib/screens/common_widgets/envfield_cell.dart index a2593af6..609a2ea8 100644 --- a/lib/screens/common_widgets/envfield_cell.dart +++ b/lib/screens/common_widgets/envfield_cell.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; -import 'environment_field.dart'; +import 'env_trigger_field.dart'; class EnvCellField extends StatelessWidget { const EnvCellField({ @@ -21,7 +21,7 @@ class EnvCellField extends StatelessWidget { @override Widget build(BuildContext context) { var clrScheme = colorScheme ?? Theme.of(context).colorScheme; - return EnvironmentField( + return EnvironmentTriggerField( keyId: keyId, initialValue: initialValue, style: kCodeStyle.copyWith( diff --git a/lib/screens/common_widgets/envfield_url.dart b/lib/screens/common_widgets/envfield_url.dart index d4982f5b..5d43e914 100644 --- a/lib/screens/common_widgets/envfield_url.dart +++ b/lib/screens/common_widgets/envfield_url.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; -import 'environment_field.dart'; +import 'env_trigger_field.dart'; class EnvURLField extends StatelessWidget { const EnvURLField({ @@ -18,7 +18,7 @@ class EnvURLField extends StatelessWidget { @override Widget build(BuildContext context) { - return EnvironmentField( + return EnvironmentTriggerField( keyId: "url-$selectedId", initialValue: initialValue, style: kCodeStyle, diff --git a/lib/screens/common_widgets/environment_field.dart b/lib/screens/common_widgets/environment_field.dart deleted file mode 100644 index 21188030..00000000 --- a/lib/screens/common_widgets/environment_field.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:apidash/providers/providers.dart'; -import 'package:apidash/utils/envvar_utils.dart'; -import 'package:apidash/widgets/widgets.dart'; - -class EnvironmentField extends HookConsumerWidget { - const EnvironmentField({ - super.key, - required this.keyId, - this.initialValue, - this.onChanged, - this.onFieldSubmitted, - this.style, - this.decoration, - }); - - final String keyId; - final String? initialValue; - final void Function(String)? onChanged; - final void Function(String)? onFieldSubmitted; - final TextStyle? style; - final InputDecoration? decoration; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final mentionValue = ref.watch(environmentFieldEditStateProvider); - final envMap = ref.watch(availableEnvironmentVariablesStateProvider); - final activeEnvironmentId = ref.watch(activeEnvironmentIdStateProvider); - final initialMentions = - getMentions(initialValue, envMap, activeEnvironmentId); - final suggestions = getEnvironmentVariableSuggestions( - mentionValue, envMap, activeEnvironmentId); - return EnvironmentFieldBase( - key: Key(keyId), - mentionValue: mentionValue, - onMentionValueChanged: (value) { - ref.read(environmentFieldEditStateProvider.notifier).state = value; - }, - initialValue: initialValue, - initialMentions: initialMentions, - suggestions: suggestions, - onChanged: onChanged, - onFieldSubmitted: onFieldSubmitted, - style: style, - decoration: decoration, - ); - } -} diff --git a/lib/screens/common_widgets/envvar_span.dart b/lib/screens/common_widgets/envvar_span.dart index 5c698db2..c9038d28 100644 --- a/lib/screens/common_widgets/envvar_span.dart +++ b/lib/screens/common_widgets/envvar_span.dart @@ -3,7 +3,6 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/utils/utils.dart'; import 'envvar_popover.dart'; @@ -11,10 +10,10 @@ import 'envvar_popover.dart'; class EnvVarSpan extends HookConsumerWidget { const EnvVarSpan({ super.key, - required this.suggestion, + required this.variableKey, }); - final EnvironmentVariableSuggestion suggestion; + final String variableKey; @override Widget build(BuildContext context, WidgetRef ref) { @@ -22,20 +21,19 @@ class EnvVarSpan extends HookConsumerWidget { final envMap = ref.watch(availableEnvironmentVariablesStateProvider); final activeEnvironmentId = ref.watch(activeEnvironmentIdStateProvider); - final currentSuggestion = - getCurrentVariableStatus(suggestion, envMap, activeEnvironmentId); + final suggestion = + getVariableStatus(variableKey, envMap, activeEnvironmentId); final showPopover = useState(false); - final isMissingVariable = currentSuggestion.isUnknown; + final isMissingVariable = suggestion.isUnknown; final String scope = isMissingVariable ? 'unknown' - : getEnvironmentTitle( - environments?[currentSuggestion.environmentId]?.name); + : getEnvironmentTitle(environments?[suggestion.environmentId]?.name); final colorScheme = Theme.of(context).colorScheme; var text = Text( - '{{${currentSuggestion.variable.key}}}', + '{{${suggestion.variable.key}}}', style: TextStyle( color: isMissingVariable ? colorScheme.error : colorScheme.primary, fontWeight: FontWeight.w600), @@ -50,7 +48,7 @@ class EnvVarSpan extends HookConsumerWidget { onExit: (_) { showPopover.value = false; }, - child: EnvVarPopover(suggestion: currentSuggestion, scope: scope), + child: EnvVarPopover(suggestion: suggestion, scope: scope), ), anchor: const Aligned( follower: Alignment.bottomCenter, diff --git a/lib/utils/envvar_utils.dart b/lib/utils/envvar_utils.dart index f3157dce..aec71567 100644 --- a/lib/utils/envvar_utils.dart +++ b/lib/utils/envvar_utils.dart @@ -1,8 +1,6 @@ import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/models/models.dart'; -import '../screens/common_widgets/common_widgets.dart'; String getEnvironmentTitle(String? name) { if (name == null || name.trim() == "") { @@ -92,92 +90,16 @@ HttpRequestModel substituteHttpRequestModel( return newRequestModel; } -List<(String, Object?, Widget?)> getMentions( - String? text, - Map> envMap, - String? activeEnvironmentId) { - if (text == null) { - return []; - } - final mentions = <(String, Object?, Widget?)>[]; - - final matches = kEnvVarRegEx.allMatches(text); - - for (final match in matches) { - final variableName = match.group(1); - EnvironmentVariableModel? variable; - String? environmentId; - - for (final entry in envMap.entries) { - variable = entry.value.firstWhereOrNull((v) => v.key == variableName); - if (variable != null) { - environmentId = entry.key; - break; - } - } - - final suggestion = EnvironmentVariableSuggestion( - environmentId: variable == null ? "unknown" : environmentId!, - variable: variable ?? - kEnvironmentVariableEmptyModel.copyWith( - key: variableName ?? "", - ), - isUnknown: variable == null); - mentions.add(( - '{{${variable?.key ?? variableName}}}', - suggestion, - EnvVarSpan(suggestion: suggestion) - )); - } - - return mentions; -} - -EnvironmentVariableSuggestion getCurrentVariableStatus( - EnvironmentVariableSuggestion currentSuggestion, - Map> envMap, - String? activeEnvironmentId) { - if (activeEnvironmentId != null) { - final variable = envMap[activeEnvironmentId]! - .firstWhereOrNull((v) => v.key == currentSuggestion.variable.key); - if (variable != null) { - return currentSuggestion.copyWith( - environmentId: activeEnvironmentId, - variable: variable, - isUnknown: false, - ); - } - } - - final globalVariable = envMap[kGlobalEnvironmentId] - ?.firstWhereOrNull((v) => v.key == currentSuggestion.variable.key); - if (globalVariable != null) { - return currentSuggestion.copyWith( - environmentId: kGlobalEnvironmentId, - variable: globalVariable, - isUnknown: false, - ); - } - - return currentSuggestion.copyWith( - isUnknown: true, - variable: currentSuggestion.variable.copyWith(value: "unknown")); -} - -List? getEnvironmentVariableSuggestions( +List? getEnvironmentTriggerSuggestions( String? query, Map> envMap, String? activeEnvironmentId) { - if (query == null || kEnvVarRegEx.hasMatch(query)) return null; - - query = query.substring(1); - final suggestions = []; final Set addedVariableKeys = {}; if (activeEnvironmentId != null && envMap[activeEnvironmentId] != null) { for (final variable in envMap[activeEnvironmentId]!) { - if ((query.isEmpty || variable.key.contains(query)) && + if ((query!.isEmpty || variable.key.contains(query)) && !addedVariableKeys.contains(variable.key)) { suggestions.add(EnvironmentVariableSuggestion( environmentId: activeEnvironmentId, variable: variable)); @@ -197,3 +119,36 @@ List? getEnvironmentVariableSuggestions( return suggestions; } + +EnvironmentVariableSuggestion getVariableStatus( + String key, + Map> envMap, + String? activeEnvironmentId) { + if (activeEnvironmentId != null) { + final variable = + envMap[activeEnvironmentId]!.firstWhereOrNull((v) => v.key == key); + if (variable != null) { + return EnvironmentVariableSuggestion( + environmentId: activeEnvironmentId, + variable: variable, + isUnknown: false, + ); + } + } + + final globalVariable = + envMap[kGlobalEnvironmentId]?.firstWhereOrNull((v) => v.key == key); + if (globalVariable != null) { + return EnvironmentVariableSuggestion( + environmentId: kGlobalEnvironmentId, + variable: globalVariable, + isUnknown: false, + ); + } + + return EnvironmentVariableSuggestion( + isUnknown: true, + environmentId: "unknown", + variable: EnvironmentVariableModel( + key: key, type: EnvironmentVariableType.variable, value: "unknown")); +} diff --git a/lib/widgets/environment_field_base.dart b/lib/widgets/environment_field_base.dart deleted file mode 100644 index fee6f587..00000000 --- a/lib/widgets/environment_field_base.dart +++ /dev/null @@ -1,104 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:flutter_portal/flutter_portal.dart'; -import 'package:mention_tag_text_field/mention_tag_text_field.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/widgets/field_mention.dart'; -import '../screens/common_widgets/common_widgets.dart'; -import 'suggestions_menu.dart'; - -class EnvironmentFieldBase extends StatefulHookWidget { - const EnvironmentFieldBase({ - super.key, - this.initialValue, - this.onChanged, - this.onFieldSubmitted, - this.style, - this.decoration, - this.initialMentions, - this.suggestions, - this.mentionValue, - required this.onMentionValueChanged, - }); - - final String? initialValue; - final void Function(String)? onChanged; - final void Function(String)? onFieldSubmitted; - final TextStyle? style; - final InputDecoration? decoration; - final List<(String, Object?, Widget?)>? initialMentions; - final List? suggestions; - final String? mentionValue; - final void Function(String?) onMentionValueChanged; - - @override - State createState() => - _EnvironmentAutocompleteFieldBaseState(); -} - -class _EnvironmentAutocompleteFieldBaseState - extends State { - final MentionTagTextEditingController controller = - MentionTagTextEditingController(); - - final FocusNode focusNode = FocusNode(); - - @override - void initState() { - super.initState(); - controller.text = widget.initialValue ?? ""; - } - - @override - Widget build(BuildContext context) { - final isSuggestionsVisible = useState(false); - - return PortalTarget( - visible: isSuggestionsVisible.value && focusNode.hasFocus, - portalFollower: SuggestionsMenu( - mentionController: controller, - suggestions: widget.suggestions, - suggestionBuilder: (context, index) { - final suggestion = widget.suggestions![index]; - return ListTile( - dense: true, - leading: EnvVarIndicator(suggestion: suggestion), - title: Text(suggestion.variable.key), - subtitle: Text(suggestion.variable.value), - onTap: () { - controller.addMention( - label: '{${suggestion.variable.key}}}', - data: suggestion, - stylingWidget: EnvVarSpan(suggestion: suggestion)); - widget.onChanged?.call(controller.text); - widget.onMentionValueChanged.call(null); - isSuggestionsVisible.value = false; - }, - ); - }, - ), - anchor: const Aligned( - follower: Alignment.topLeft, - target: Alignment.bottomLeft, - backup: Aligned( - follower: Alignment.bottomLeft, - target: Alignment.topLeft, - ), - ), - child: MentionField( - focusNode: focusNode, - controller: controller, - initialMentions: widget.initialMentions ?? [], - mentionValue: widget.mentionValue, - onMentionValueChanged: widget.onMentionValueChanged, - isSuggestionsVisible: isSuggestionsVisible, - onChanged: widget.onChanged, - onFieldSubmitted: widget.onFieldSubmitted, - style: widget.style, - decoration: widget.decoration, - mentionStart: const ['{'], - maxWords: 1, - ), - ); - } -} diff --git a/lib/widgets/field_mention.dart b/lib/widgets/field_mention.dart deleted file mode 100644 index cfad0f2f..00000000 --- a/lib/widgets/field_mention.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mention_tag_text_field/mention_tag_text_field.dart'; - -class MentionField extends StatelessWidget { - const MentionField({ - super.key, - required this.focusNode, - required this.controller, - required this.initialMentions, - required this.mentionValue, - required this.onMentionValueChanged, - required this.isSuggestionsVisible, - this.onChanged, - this.onFieldSubmitted, - this.style, - this.decoration, - required this.mentionStart, - this.mentionBreak = "", - this.maxWords, - this.allowDecrement = false, - this.allowEmbedding = true, - this.showMentionStartSymbol = false, - }); - - final FocusNode focusNode; - final MentionTagTextEditingController controller; - final List<(String, Object?, Widget?)> initialMentions; - final String? mentionValue; - final void Function(String?) onMentionValueChanged; - final ValueNotifier isSuggestionsVisible; - final void Function(String)? onChanged; - final void Function(String)? onFieldSubmitted; - final TextStyle? style; - final InputDecoration? decoration; - final List mentionStart; - final String mentionBreak; - final int? maxWords; - final bool allowDecrement; - final bool allowEmbedding; - final bool showMentionStartSymbol; - - void onMention(String? value) { - onMentionValueChanged.call(value); - if (value != null) { - isSuggestionsVisible.value = true; - } else { - isSuggestionsVisible.value = false; - } - } - - @override - Widget build(BuildContext context) { - return MentionTagTextField( - focusNode: focusNode, - onTap: () { - focusNode.requestFocus(); - }, - onTapOutside: (event) { - focusNode.unfocus(); - isSuggestionsVisible.value = false; - }, - controller: controller, - style: style, - initialMentions: initialMentions, - onMention: onMention, - onChanged: (value) { - onChanged?.call(controller.text); - }, - onEditingComplete: () { - focusNode.unfocus(); - onFieldSubmitted?.call(controller.text); - isSuggestionsVisible.value = false; - }, - decoration: decoration, - mentionTagDecoration: MentionTagDecoration( - mentionStart: mentionStart, - mentionBreak: mentionBreak, - maxWords: maxWords, - allowDecrement: allowDecrement, - allowEmbedding: allowEmbedding, - showMentionStartSymbol: showMentionStartSymbol, - ), - ); - } -} diff --git a/lib/widgets/suggestions_menu.dart b/lib/widgets/suggestions_menu.dart deleted file mode 100644 index a6ab063d..00000000 --- a/lib/widgets/suggestions_menu.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mention_tag_text_field/mention_tag_text_field.dart'; -import 'package:apidash/consts.dart'; - -class SuggestionsMenu extends StatelessWidget { - const SuggestionsMenu({ - super.key, - required this.mentionController, - required this.suggestions, - required this.suggestionBuilder, - this.menuWidth = kSuggestionsMenuWidth, - this.menuMaxHeight = kSuggestionsMenuMaxHeight, - }); - - final MentionTagTextEditingController mentionController; - final List? suggestions; - final double menuWidth; - final double menuMaxHeight; - final Widget? Function(BuildContext, int) suggestionBuilder; - - @override - Widget build(BuildContext context) { - return suggestions == null || suggestions!.isEmpty - ? const SizedBox.shrink() - : ClipRRect( - borderRadius: kBorderRadius8, - child: Material( - type: MaterialType.card, - elevation: 8, - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: menuMaxHeight), - child: Ink( - width: menuWidth, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: kBorderRadius8, - border: Border.all( - color: Theme.of(context).colorScheme.outlineVariant, - ), - ), - child: ListView.separated( - shrinkWrap: true, - itemCount: suggestions?.length ?? 0, - separatorBuilder: (context, index) => - const Divider(height: 2), - itemBuilder: suggestionBuilder, - ), - ), - ), - ), - ); - } -} diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index 6b480b52..efd56fa5 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -17,13 +17,11 @@ export 'dropdown_formdata.dart'; export 'dropdown_http_method.dart'; export 'editor_json.dart'; export 'editor.dart'; -export 'environment_field_base.dart'; export 'error_message.dart'; export 'field_cell_obscurable.dart'; export 'field_cell.dart'; export 'field_header.dart'; export 'field_json_search.dart'; -export 'field_mention.dart'; export 'field_raw.dart'; export 'field_url.dart'; export 'intro_message.dart'; @@ -41,7 +39,6 @@ export 'snackbars.dart'; export 'splitview_drawer.dart'; export 'splitview_dashboard.dart'; export 'splitview_equal.dart'; -export 'suggestions_menu.dart'; export 'tables.dart'; export 'tabs.dart'; export 'texts.dart'; diff --git a/pubspec.lock b/pubspec.lock index 13ee81cf..f74a370d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -258,7 +258,7 @@ packages: source: hosted version: "1.0.1" extended_text_field: - dependency: transitive + dependency: "direct main" description: name: extended_text_field sha256: "954c7eea1e82728a742f7ddf09b9a51cef087d4f52b716ba88cb3eb78ccd7c6e" @@ -817,14 +817,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.8.0" - mention_tag_text_field: - dependency: "direct main" - description: - name: mention_tag_text_field - sha256: "9768a0a6fe5771cb8eb98f94b26b4c595ca2487b0eb28b9d5624f8d71a2ac17a" - url: "https://pub.dev" - source: hosted - version: "0.0.5" meta: dependency: transitive description: @@ -865,6 +857,15 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.1" + multi_trigger_autocomplete: + dependency: "direct main" + description: + path: "." + ref: master + resolved-ref: "7ca8778e47f80c913cee33a3a01447039acc6936" + url: "https://github.com/DenserMeerkat/multi_trigger_autocomplete.git" + source: git + version: "1.0.1" nested: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 883128b2..92cf4eb8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,7 +63,11 @@ dependencies: hooks_riverpod: ^2.5.1 flutter_hooks: ^0.20.5 flutter_portal: ^1.1.4 - mention_tag_text_field: ^0.0.5 + multi_trigger_autocomplete: + git: + url: https://github.com/DenserMeerkat/multi_trigger_autocomplete.git + ref: master + extended_text_field: ^15.0.0 dependency_overrides: web: ^0.5.0 diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 41726dca..9856b4a5 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -15,12 +15,12 @@ import 'package:apidash/screens/intro_page.dart'; import 'package:apidash/screens/settings_page.dart'; import 'package:apidash/services/hive_services.dart'; import 'package:apidash/widgets/widgets.dart'; +import 'package:extended_text_field/extended_text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mention_tag_text_field/mention_tag_text_field.dart'; import '../extensions/widget_tester_extensions.dart'; import '../test_consts.dart'; @@ -446,7 +446,7 @@ void main() { // Add some data in URLTextField Finder field = find.descendant( of: find.byType(EnvURLField), - matching: find.byType(MentionTagTextField), + matching: find.byType(ExtendedTextField), ); await tester.enterText(field, kTestUrl); await tester.pump(); @@ -493,7 +493,7 @@ void main() { // Add some data in URLTextField Finder field = find.descendant( of: find.byType(EnvURLField), - matching: find.byType(MentionTagTextField), + matching: find.byType(ExtendedTextField), ); await tester.enterText(field, kTestUrl); await tester.pump(); @@ -544,7 +544,7 @@ void main() { // Add some data in URLTextField Finder field = find.descendant( of: find.byType(EnvURLField), - matching: find.byType(MentionTagTextField), + matching: find.byType(ExtendedTextField), ); await tester.enterText(field, kTestUrl); await tester.pump(); @@ -604,7 +604,7 @@ void main() { // Add some data in URLTextField Finder field = find.descendant( of: find.byType(EnvURLField), - matching: find.byType(MentionTagTextField), + matching: find.byType(ExtendedTextField), ); await tester.enterText(field, kTestUrl); await tester.pump();