diff --git a/.gitignore b/.gitignore index 1985397..9d03e56 100644 --- a/.gitignore +++ b/.gitignore @@ -21,54 +21,11 @@ #.vscode/ # Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +build/ +/pubspec.lock **/doc/api/ .dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies .packages -.pub-cache/ -.pub/ -build/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 +.flutter-plugins +.flutter-plugins-dependencies \ No newline at end of file diff --git a/.metadata b/.metadata deleted file mode 100644 index bfc12cb..0000000 --- a/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 1aafb3a8b9b0c36241c5f5b34ee914770f015818 - channel: stable - -project_type: package diff --git a/CHANGELOG.md b/CHANGELOG.md index 364baf4..51076b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,42 @@ +## [1.4.8] - 2022-05-13 + +- Fix: Remove update external dependencies +- Feat: Create a inputs formatter + +## [1.4.5] - 2022-02-22 + +- Chore: Update dependencies +- Fix: removed unused HtmlWidget + +## [1.4.3] - 2022-01-11 + +- Chore: Update dependencies + ## [1.4.0] - 2021-10-13 + - Feat: add form field + ## [1.3.0] - 2021-02-23 -- Feat: add export file -- Feat: add analyzer in project -- Feat: created new components + +- Feat: add export file +- Feat: add analyzer in project +- Feat: created new components + ## [1.2.1] - 2021-02-23 + - Fix: homepage url + ## [1.2.0] - 2021-02-22 + - HtmlWidget + ## [1.1.0] - 2020-12-04 + - AlwaysDisabledFocusNode + ## [1.0.0] - 2020-12-04 + Hello World! This version contains: + - HorizontalSpacing - VerticalSpacing diff --git a/analysis_options.yaml b/analysis_options.yaml index 356a593..d97a13e 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,26 +1,20 @@ include: package:flutter_lints/flutter.yaml -analyzer: - strong-mode: - implicit-dynamic: true - errors: - import_of_legacy_library_into_null_safe: ignore - undefined_prefixed_name: ignore - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. +dart_code_metrics: + anti-patterns: + - long-method + - long-parameter-list + metrics: + cyclomatic-complexity: 20 + maximum-nesting-level: 5 + number-of-parameters: 4 + source-lines-of-code: 50 + metrics-exclude: + - test/** rules: - avoid_print: false - prefer_single_quotes: true -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options \ No newline at end of file + - newline-before-return + - no-boolean-literal-compare + - no-empty-block + - prefer-trailing-comma + - prefer-conditional-expressions + - no-equal-then-else diff --git a/lib/cubos_widgets.dart b/lib/cubos_widgets.dart index bf83375..78e3397 100644 --- a/lib/cubos_widgets.dart +++ b/lib/cubos_widgets.dart @@ -1,5 +1,8 @@ -export 'always_disabled_focus_node.dart'; -export 'horizontal_spacing.dart'; -export 'vertical_spacing.dart'; -export 'form_fields.dart'; -export 'html_widget.dart'; +export 'src/components/always_disabled_focus_node.dart'; +export 'src/components/horizontal_spacing.dart'; +export 'src/components/vertical_spacing.dart'; +export 'src/components/form_fields.dart'; + +export 'src/formatter/money_masked_text_controller.dart'; +export 'src/formatter/masked_text_controller.dart'; + diff --git a/lib/html_widget.dart b/lib/html_widget.dart deleted file mode 100644 index dace85d..0000000 --- a/lib/html_widget.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_html/flutter_html.dart'; -import 'package:flutter_html/style.dart'; -import 'package:url_launcher/url_launcher.dart'; - -class HtmlWidget extends StatelessWidget { - final String data; - final TextStyle textStyle; - - const HtmlWidget({ - Key? key, - required this.data, - required this.textStyle, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Html( - data: '
$data
', - style: { - 'div': Style( - color: textStyle.color, - fontSize: FontSize(textStyle.fontSize), - fontWeight: textStyle.fontWeight, - ) - }, - onLinkTap: _onLinkTap, - ); - } - - void _onLinkTap(String url) async { - if (await canLaunch(url)) { - await launch(url); - } - } -} diff --git a/lib/always_disabled_focus_node.dart b/lib/src/components/always_disabled_focus_node.dart similarity index 100% rename from lib/always_disabled_focus_node.dart rename to lib/src/components/always_disabled_focus_node.dart diff --git a/lib/form_fields.dart b/lib/src/components/form_fields.dart similarity index 61% rename from lib/form_fields.dart rename to lib/src/components/form_fields.dart index 15615c0..65eabaa 100644 --- a/lib/form_fields.dart +++ b/lib/src/components/form_fields.dart @@ -1,6 +1,7 @@ -import 'package:flutter_masked_text/flutter_masked_text.dart'; import 'package:flutter/material.dart'; +import '../../cubos_widgets.dart'; + /// A component used to centralize Focus and TextEditingController in one place, /// And also the possibility to use a mask just using .mask(....) /// This is useful when a screen has a lot of textFormField @@ -19,7 +20,7 @@ class FormFields { }) : focus = focus ?? FocusNode(), controller = controller ?? TextEditingController(); - factory FormFields.mask({String? mask}) { + factory FormFields.mask({required String mask}) { return FormFields( focus: FocusNode(), controller: MaskedTextController(mask: mask), @@ -35,7 +36,7 @@ class FormFields { bool get isMaskedController => controller != null && controller is MaskedTextController; - void updateMask(String? value) { + void updateMask(String value) { if (isMaskedController) { (controller as MaskedTextController).updateMask(value); } @@ -46,25 +47,3 @@ class FormFields { controller?.dispose(); } } - -class FormFieldsMoney extends FormFields { - FormFieldsMoney({ - FocusNode? focus, - MoneyMaskedTextController? controller, - }) : super(focus: focus, controller: controller); - - factory FormFieldsMoney.money({String? leftSymbol = 'U\$'}) { - return FormFieldsMoney( - focus: FocusNode(), - controller: MoneyMaskedTextController(leftSymbol: leftSymbol), - ); - } - - double get numberValue { - return (controller as MoneyMaskedTextController).numberValue; - } - - void updateValue(double value) { - (controller as MoneyMaskedTextController).updateValue(value); - } -} diff --git a/lib/form_fields_money.dart b/lib/src/components/form_fields_money.dart similarity index 84% rename from lib/form_fields_money.dart rename to lib/src/components/form_fields_money.dart index a3af5d1..00b8df8 100644 --- a/lib/form_fields_money.dart +++ b/lib/src/components/form_fields_money.dart @@ -1,7 +1,6 @@ -import 'package:flutter_masked_text/flutter_masked_text.dart'; import 'package:flutter/material.dart'; -import 'form_fields.dart'; +import '../../cubos_widgets.dart'; /// A component used to centralize Focus and TextEditingController in one place, /// And also the possibility to use a mask just using .mask(....) @@ -17,7 +16,7 @@ class FormFieldsMoney extends FormFields { MoneyMaskedTextController? controller, }) : super(focus: focus, controller: controller); - factory FormFieldsMoney.money({String? leftSymbol = 'U\$'}) { + factory FormFieldsMoney.money({String leftSymbol = 'U\$'}) { return FormFieldsMoney( focus: FocusNode(), controller: MoneyMaskedTextController(leftSymbol: leftSymbol), diff --git a/lib/horizontal_spacing.dart b/lib/src/components/horizontal_spacing.dart similarity index 100% rename from lib/horizontal_spacing.dart rename to lib/src/components/horizontal_spacing.dart diff --git a/lib/responsive_text_scale_factor.dart b/lib/src/components/responsive_text_scale_factor.dart similarity index 100% rename from lib/responsive_text_scale_factor.dart rename to lib/src/components/responsive_text_scale_factor.dart diff --git a/lib/vertical_spacing.dart b/lib/src/components/vertical_spacing.dart similarity index 100% rename from lib/vertical_spacing.dart rename to lib/src/components/vertical_spacing.dart diff --git a/lib/src/formatter/masked_text_controller.dart b/lib/src/formatter/masked_text_controller.dart new file mode 100644 index 0000000..c4fe232 --- /dev/null +++ b/lib/src/formatter/masked_text_controller.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; + +class MaskedTextController extends TextEditingController { + MaskedTextController({ + String? text, + required this.mask, + Map? translator, + }) : super(text: text) { + this.translator = translator ?? MaskedTextController.getDefaultTranslator(); + + addListener(() { + var previous = _lastUpdatedText; + if (beforeChange(previous, this.text)) { + updateText(this.text); + afterChange(previous, this.text); + } else { + updateText(_lastUpdatedText); + } + }); + + updateText(this.text); + } + + String mask; + + late final Map translator; + + Function afterChange = (String previous, String next) {}; + Function beforeChange = (String previous, String next) => true; + + String? _lastUpdatedText = ''; + + void updateText(String? text) { + if (text != null) { + this.text = _applyMask(mask, text); + } else { + this.text = ''; + } + + _lastUpdatedText = this.text; + } + + void updateMask(String mask, {bool moveCursorToEnd = true}) { + this.mask = mask; + updateText(text); + + if (moveCursorToEnd) { + this.moveCursorToEnd(); + } + } + + void moveCursorToEnd() { + final text = _lastUpdatedText; + selection = TextSelection.fromPosition( + TextPosition(offset: (text ?? '').length), + ); + } + + @override + set text(String newText) { + if (super.text != newText) { + super.text = newText; + moveCursorToEnd(); + } + } + + static Map getDefaultTranslator() { + return { + 'A': RegExp(r'[A-Za-z]'), + '0': RegExp(r'[0-9]'), + '@': RegExp(r'[A-Za-z0-9]'), + '*': RegExp(r'.*') + }; + } + + String _applyMask(String mask, String value) { + String result = ''; + + int maskCharIndex = 0; + int valueCharIndex = 0; + + while (true) { + // if mask is ended, break. + if (maskCharIndex == mask.length) { + break; + } + + // if value is ended, break. + if (valueCharIndex == value.length) { + break; + } + + var maskChar = mask[maskCharIndex]; + var valueChar = value[valueCharIndex]; + + // value equals mask, just set + if (maskChar == valueChar) { + result += maskChar; + valueCharIndex += 1; + maskCharIndex += 1; + continue; + } + + // apply translator if match + if (translator.containsKey(maskChar)) { + final hasMatch = translator[maskChar]?.hasMatch(valueChar); + if (hasMatch ?? false) { + result += valueChar; + maskCharIndex += 1; + } + + valueCharIndex += 1; + continue; + } + + // not masked value, fixed char on mask + result += maskChar; + maskCharIndex += 1; + continue; + } + + return result; + } +} diff --git a/lib/src/formatter/money_masked_text_controller.dart b/lib/src/formatter/money_masked_text_controller.dart new file mode 100644 index 0000000..392f960 --- /dev/null +++ b/lib/src/formatter/money_masked_text_controller.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; + +/// Mask for monetary values. +class MoneyMaskedTextController extends TextEditingController { + MoneyMaskedTextController({ + double initialValue = 0.0, + this.decimalSeparator = ',', + this.thousandSeparator = '.', + this.rightSymbol = '', + this.leftSymbol = '', + this.precision = 2, + }) { + _validateConfig(); + + addListener(() { + updateValue(numberValue); + afterChange(text, numberValue); + }); + + updateValue(initialValue); + } + + final String decimalSeparator; + final String thousandSeparator; + final String rightSymbol; + final String leftSymbol; + final int precision; + + Function afterChange = (String maskedValue, double rawValue) {}; + + double _lastValue = 0.0; + + void updateValue(double value) { + double valueToUse = value; + + if (value.toStringAsFixed(0).length > 12) { + valueToUse = _lastValue; + } else { + _lastValue = value; + } + + String masked = _applyMask(valueToUse); + + if (rightSymbol.isNotEmpty) { + masked += rightSymbol; + } + + if (leftSymbol.isNotEmpty) { + masked = leftSymbol + masked; + } + + if (masked != text) { + text = masked; + + var cursorPosition = super.text.length - rightSymbol.length; + selection = + TextSelection.fromPosition(TextPosition(offset: cursorPosition)); + } + } + + double get numberValue { + List parts = _getOnlyNumbers(text).split('').toList(growable: true); + + parts.insert(parts.length - precision, '.'); + + return double.parse(parts.join()); + } + + _validateConfig() { + bool rightSymbolHasNumbers = _getOnlyNumbers(rightSymbol).isNotEmpty; + + if (rightSymbolHasNumbers) { + throw ArgumentError("rightSymbol must not have numbers."); + } + } + + String _getOnlyNumbers(String text) { + String cleanedText = text; + + var onlyNumbersRegex = RegExp(r'[^\d]'); + + cleanedText = cleanedText.replaceAll(onlyNumbersRegex, ''); + + return cleanedText; + } + + String _applyMask(double value) { + List textRepresentation = value + .toStringAsFixed(precision) + .replaceAll('.', '') + .split('') + .reversed + .toList(growable: true); + + textRepresentation.insert(precision, decimalSeparator); + + for (var i = precision + 4; true; i = i + 4) { + if (textRepresentation.length > i) { + textRepresentation.insert(i, thousandSeparator); + } else { + break; + } + } + + return textRepresentation.reversed.join(''); + } +} diff --git a/pubspec.lock b/pubspec.lock index c48d8e1..da6c695 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,13 +1,48 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "39.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.0" + ansicolor: + dependency: transitive + description: + name: ansicolor + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,28 +56,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - chewie: - dependency: transitive - description: - name: chewie - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.2" - chewie_audio: - dependency: transitive - description: - name: chewie_audio - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.2" + version: "1.3.1" clock: dependency: transitive description: @@ -56,169 +77,143 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" - css_colors: + version: "1.16.0" + convert: dependency: transitive description: - name: css_colors + name: convert url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "3.0.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" csslib: dependency: transitive description: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.16.2" - cupertino_icons: - dependency: transitive + version: "0.17.1" + dart_code_metrics: + dependency: "direct dev" description: - name: cupertino_icons + name: dart_code_metrics url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" - fake_async: + version: "4.15.1" + dart_style: dependency: transitive description: - name: fake_async + name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_html: - dependency: "direct main" + version: "2.2.3" + fake_async: + dependency: transitive description: - name: flutter_html + name: fake_async url: "https://pub.dartlang.org" source: hosted version: "1.3.0" - flutter_layout_grid: + file: dependency: transitive description: - name: flutter_layout_grid + name: file url: "https://pub.dartlang.org" source: hosted - version: "0.10.5" + version: "6.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_lints: dependency: "direct dev" description: name: flutter_lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" - flutter_masked_text: - dependency: "direct main" - description: - name: flutter_masked_text - url: "https://pub.dartlang.org" - source: hosted - version: "0.8.0" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - url: "https://pub.dartlang.org" - source: hosted - version: "0.20.0-nullsafety.3" + version: "2.0.1" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - html: + glob: dependency: transitive description: - name: html + name: glob url: "https://pub.dartlang.org" source: hosted - version: "0.14.0+4" - import_js_library: - dependency: transitive - description: - name: import_js_library - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - js: + version: "2.0.2" + html: dependency: transitive description: - name: js + name: html url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.15.0" lints: dependency: transitive description: name: lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "2.0.0" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" - meta: + version: "0.12.11" + material_color_utilities: dependency: transitive description: - name: meta + name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" - path: + version: "0.1.4" + meta: dependency: transitive description: - name: path + name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" - path_drawing: + version: "1.7.0" + package_config: dependency: transitive description: - name: path_drawing + name: package_config url: "https://pub.dartlang.org" source: hosted - version: "0.5.0-nullsafety.0" - path_parsing: + version: "2.0.2" + path: dependency: transitive description: - name: path_parsing + name: path url: "https://pub.dartlang.org" source: hosted - version: "0.2.0-nullsafety.0" + version: "1.8.1" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.0.2" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - quiver: + version: "5.0.0" + pub_semver: dependency: transitive description: - name: quiver + name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.1.1" sky_engine: dependency: transitive description: flutter @@ -230,7 +225,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -265,7 +260,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.9" typed_data: dependency: transitive description: @@ -273,111 +268,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.2" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" - video_player: + version: "2.1.2" + watcher: dependency: transitive description: - name: video_player + name: watcher url: "https://pub.dartlang.org" source: hosted version: "1.0.1" - video_player_platform_interface: - dependency: transitive - description: - name: video_player_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - video_player_web: - dependency: transitive - description: - name: video_player_web - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.4+1" - wakelock: - dependency: transitive - description: - name: wakelock - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.1+1" - wakelock_platform_interface: - dependency: transitive - description: - name: wakelock_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0+1" - wakelock_web: - dependency: transitive - description: - name: wakelock_web - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0+3" - webview_flutter: + xml: dependency: transitive description: - name: webview_flutter + name: xml url: "https://pub.dartlang.org" source: hosted - version: "1.0.7" - xml: + version: "6.0.1" + yaml: dependency: transitive description: - name: xml + name: yaml url: "https://pub.dartlang.org" source: hosted - version: "5.0.2" + version: "3.1.1" sdks: - dart: ">=2.13.0 <3.0.0" - flutter: ">=1.24.0-7.0" + dart: ">=2.17.0-206.0.dev <3.0.0" + flutter: ">=1.17.0" diff --git a/pubspec.yaml b/pubspec.yaml index b054068..0836b68 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,24 +1,23 @@ name: cubos_widgets description: Flutter package containing the most used Widgets in Cubos Tecnologia's projects. -version: 1.4.0 +version: 1.4.8 homepage: https://github.com/daniloapr/cubos_widgets +publish_to: none + environment: - sdk: ">=2.13.0 <3.0.0" + sdk: ">=2.15.0 <3.0.0" flutter: ">=1.17.0" dependencies: flutter: sdk: flutter - - url_launcher: ^6.0.2 - flutter_html: ^1.3.0 - flutter_masked_text: ^0.8.0 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^1.0.4 -flutter: + flutter_lints: ^2.0.1 + dart_code_metrics: ^4.15.1 +flutter: diff --git a/test/src/formatter/masked_text_controller_test.dart b/test/src/formatter/masked_text_controller_test.dart new file mode 100644 index 0000000..17cd687 --- /dev/null +++ b/test/src/formatter/masked_text_controller_test.dart @@ -0,0 +1,71 @@ +import 'package:cubos_widgets/cubos_widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('12345678901 with mask 000.000.000-00 results 123.456.789-01', () { + var cpfController = + MaskedTextController(text: '12345678901', mask: '000.000.000-00'); + + expect(cpfController.text, '123.456.789-01'); + }); + + test( + '12345678901 with mask 000.000.000-00 and changed results 123.456.789.01', + () { + var cpfController = + MaskedTextController(text: '12345678901', mask: '000.000.000-00'); + + expect(cpfController.text, '123.456.789-01'); + + cpfController.updateMask('000.000.0000-0'); + + expect(cpfController.text, '123.456.7890-1'); + }); + + test('abc123 with mask AAA results abc', () { + var controller = MaskedTextController(text: 'abc123', mask: 'AAA'); + + expect(controller.text, 'abc'); + }); + + test('update text to 123456 and mask 000-000 results on 123-456', () { + var controller = MaskedTextController(text: '', mask: '000-000'); + controller.updateText('123456'); + + expect(controller.text, '123-456'); + }); + + test('* must accept all characters', () { + var controller = MaskedTextController(text: 'a0&#', mask: '****'); + + expect(controller.text, 'a0&#'); + }); + + test('@ must accept only letters and numbers', () { + var controller = MaskedTextController(text: 'a0&#', mask: '@@@'); + + expect(controller.text, 'a0'); + }); + + test('remove * translator must keep * in the mask', () { + var translator = MaskedTextController.getDefaultTranslator(); + translator.remove('*'); + + var controller = MaskedTextController( + mask: '0000 **** **** 0000', translator: translator); + controller.updateText('12345678'); + + expect(controller.text, '1234 **** **** 5678'); + }); + + test('remove * translator must keep * in the mask', () { + var translator = MaskedTextController.getDefaultTranslator(); + translator.remove('*'); + + var controller = MaskedTextController( + mask: '0000 **** **** 0000', translator: translator); + controller.updateText('12345678'); + + expect(controller.text, '1234 **** **** 5678'); + }); +} diff --git a/test/src/formatter/money_masked_text_controller_test.dart b/test/src/formatter/money_masked_text_controller_test.dart new file mode 100644 index 0000000..789184e --- /dev/null +++ b/test/src/formatter/money_masked_text_controller_test.dart @@ -0,0 +1,87 @@ +import 'package:cubos_widgets/cubos_widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('0.01 results 0,01', () { + var controller = MoneyMaskedTextController(); + controller.updateValue(0.01); + + expect(controller.text, '0,01'); + }); + + test('1234.56 results 1.234,56', () { + var controller = MoneyMaskedTextController(); + + controller.updateValue(1234.56); + + expect(controller.text, '1.234,56'); + }); + + test('123123.0 results 123.123,00', () { + var controller = MoneyMaskedTextController(); + controller.updateValue(123123.0); + + expect(controller.text, '123.123,00'); + }); + + test('1231231.0 results 1.231.231,00', () { + var controller = MoneyMaskedTextController(); + controller.updateValue(1231231.0); + + expect(controller.text, '1.231.231,00'); + }); + + test('custom decimal and thousando separator results in 1,234.00', () { + var controller = MoneyMaskedTextController( + decimalSeparator: '.', thousandSeparator: ','); + controller.updateValue(1234.0); + + expect(controller.text, '1,234.00'); + }); + + test('number value for 0,10 must be 0.1', () { + var controller = MoneyMaskedTextController( + decimalSeparator: '.', thousandSeparator: ','); + controller.updateValue(0.1); + + expect(controller.numberValue, 0.1); + }); + + test('rightSymbol " US\$" and value 99.99 must resut in 99,99 US\$', () { + var controller = MoneyMaskedTextController(rightSymbol: ' US\$'); + controller.updateValue(99.99); + + expect(controller.text, '99,99 US\$'); + }); + + test('rightSymbol with number must raises an error.', () { + Function executor = () { + MoneyMaskedTextController(rightSymbol: ' U4'); + }; + + expect(executor, throwsArgumentError); + }); + + test( + 'rightSymbol " US\$" with 12345678901234 must results in 123.456.789.012,34 US\$', + () { + var controller = MoneyMaskedTextController(rightSymbol: ' US\$'); + controller.updateValue(123456789012.34); + + expect(controller.text, '123.456.789.012,34 US\$'); + }); + + test('leftSymbol "R\$ " and value 123.45 results in "R\$ 123,45"', () { + var controller = MoneyMaskedTextController(leftSymbol: 'R\$ '); + controller.updateValue(123.45); + + expect(controller.text, 'R\$ 123,45'); + }); + + test('precision 3 and value 123.45 results in "123,450"', () { + var controller = MoneyMaskedTextController(precision: 3); + controller.updateValue(123.45); + + expect(controller.text, '123,450'); + }); +}