Skip to content

Commit

Permalink
fix issue hnvn#19: Add hour and minute formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
LoritoTiago committed Aug 3, 2023
1 parent ae793e2 commit 1e5d694
Show file tree
Hide file tree
Showing 15 changed files with 288 additions and 67 deletions.
25 changes: 5 additions & 20 deletions example/.metadata
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled.

version:
revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
revision: 4b12645012342076800eb701bcdfe18f87da21cf
channel: stable

project_type: app
Expand All @@ -13,26 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
create_revision: 4b12645012342076800eb701bcdfe18f87da21cf
base_revision: 4b12645012342076800eb701bcdfe18f87da21cf
- platform: android
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: ios
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: linux
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: macos
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: web
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: windows
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
create_revision: 4b12645012342076800eb701bcdfe18f87da21cf
base_revision: 4b12645012342076800eb701bcdfe18f87da21cf

# User provided section

Expand Down
1 change: 0 additions & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
namespace "vn.hunghd.example"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion

Expand Down
3 changes: 2 additions & 1 deletion example/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="vn.hunghd.example">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
Expand Down
5 changes: 3 additions & 2 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="vn.hunghd.example">
<application
android:label="example"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
Expand Down
3 changes: 2 additions & 1 deletion example/android/app/src/profile/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="vn.hunghd.example">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
Expand Down
4 changes: 2 additions & 2 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand All @@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}

tasks.register("clean", Delete) {
task clean(type: Delete) {
delete rootProject.buildDir
}
10 changes: 5 additions & 5 deletions example/ios/Flutter/flutter_export_environment.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/hahung/Developer/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/hahung/Developer/Workspace/flutter/flutter_pattern_formatter/example"
export "FLUTTER_ROOT=/Users/loritombuta/development/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/loritombuta/Documents/GitHub/flutter_pattern_formatter/example"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=/Users/hahung/Developer/Workspace/flutter/flutter_pattern_formatter/example/lib/main.dart"
export "FLUTTER_TARGET=/Users/loritombuta/Documents/GitHub/flutter_pattern_formatter/example/lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iNGZiMTEyMTRkZDJkZGE2Y2UwMTJkZDk4ZWE0OThlOWU4YjkxMjYyLw=="
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=/Users/hahung/Developer/Workspace/flutter/flutter_pattern_formatter/example/.dart_tool/package_config.json"
export "PACKAGE_CONFIG=/Users/loritombuta/Documents/GitHub/flutter_pattern_formatter/example/.dart_tool/package_config.json"
17 changes: 17 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pattern_formatter/hour_minute_formatter.dart';
import 'package:pattern_formatter/pattern_formatter.dart';

void main() => runApp(MyApp());
Expand Down Expand Up @@ -96,6 +97,22 @@ class MyHomePage extends StatelessWidget {
],
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0, vertical: 24.0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
isDense: true,
hintText: 'HH:MM'),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'\d+|-|:')),
HourMinuteInputFormatter(),
],
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
)
],
),
Expand Down
34 changes: 17 additions & 17 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
url: "https://pub.dev"
source: hosted
version: "2.11.0"
version: "2.10.0"
boolean_selector:
dependency: transitive
description:
Expand All @@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.2.1"
clock:
dependency: transitive
description:
Expand All @@ -37,10 +37,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
url: "https://pub.dev"
source: hosted
version: "1.17.1"
version: "1.17.0"
cupertino_icons:
dependency: "direct main"
description:
Expand Down Expand Up @@ -79,18 +79,18 @@ packages:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
url: "https://pub.dev"
source: hosted
version: "0.6.7"
version: "0.6.5"
matcher:
dependency: transitive
description:
name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
url: "https://pub.dev"
source: hosted
version: "0.12.15"
version: "0.12.13"
material_color_utilities:
dependency: transitive
description:
Expand All @@ -103,18 +103,18 @@ packages:
dependency: transitive
description:
name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.8.0"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
url: "https://pub.dev"
source: hosted
version: "1.8.3"
version: "1.8.2"
pattern_formatter:
dependency: "direct main"
description:
Expand Down Expand Up @@ -171,10 +171,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
url: "https://pub.dev"
source: hosted
version: "0.5.1"
version: "0.4.16"
vector_math:
dependency: transitive
description:
Expand All @@ -184,4 +184,4 @@ packages:
source: hosted
version: "2.1.4"
sdks:
dart: ">=3.0.0-0 <4.0.0"
dart: ">=2.18.0 <3.0.0"
30 changes: 30 additions & 0 deletions example/test/widget_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:example/main.dart';

void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp());

// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);

// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();

// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}
1 change: 1 addition & 0 deletions lib/consts.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const INDEX_NOT_FOUND = -1;
2 changes: 1 addition & 1 deletion lib/date_formatter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:flutter/services.dart';
import 'package:flutter/material.dart' show TextField;
import 'dart:math';

const INDEX_NOT_FOUND = -1;
import 'package:pattern_formatter/consts.dart';

///
/// An implementation of [TextInputFormatter] provides a way to input date form
Expand Down
113 changes: 113 additions & 0 deletions lib/hour_minute_formatter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:pattern_formatter/consts.dart';

class HourMinuteInputFormatter extends TextInputFormatter {
String _placeholder = '--:--';
TextEditingValue? _lastNewValue;

@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
/// provides placeholder text when user start editing
if (oldValue.text.isEmpty) {
oldValue = oldValue.copyWith(
text: _placeholder,
);
newValue = newValue.copyWith(
text: _fillInputToPlaceholder(newValue.text),
);
return newValue;
}

/// nothing changes, nothing to do
if (newValue == _lastNewValue) {
return oldValue;
}
_lastNewValue = newValue;

int offset = newValue.selection.baseOffset;

/// restrict user's input within the length of date form
if (offset > 5) {
return oldValue;
}

if (oldValue.text == newValue.text && oldValue.text.length > 0) {
return newValue;
}

final String oldText = oldValue.text;
final String newText = newValue.text;
String? resultText;

/// handle user editing, there're two cases:
/// 1. user add new digit: replace '-' at cursor's position by user's input.
/// 2. user delete digit: replace digit at cursor's position by '-'
int index = _indexOfDifference(newText, oldText);
if (oldText.length < newText.length) {
/// add new digit
String newChar = newText[index];
if (index == 2) {
index++;
offset++;
}
resultText = oldText.replaceRange(index, index + 1, newChar);
if (offset == 2) {
offset++;
}
} else if (oldText.length > newText.length) {
/// delete digit
if (oldText[index] != ':') {
resultText = oldText.replaceRange(index, index + 1, '-');
if (offset == 3) {
offset--;
}
} else {
resultText = oldText;
}
}

return oldValue.copyWith(
text: resultText,
selection: TextSelection.collapsed(offset: offset),
composing: defaultTargetPlatform == TargetPlatform.iOS
? TextRange(start: 0, end: 0)
: TextRange.empty,
);
}

int _indexOfDifference(String? cs1, String? cs2) {
if (cs1 == cs2) {
return INDEX_NOT_FOUND;
}
if (cs1 == null || cs2 == null) {
return 0;
}
int i;
for (i = 0; i < cs1.length && i < cs2.length; ++i) {
if (cs1[i] != cs2[i]) {
break;
}
}
if (i < cs2.length || i < cs1.length) {
return i;
}
return INDEX_NOT_FOUND;
}

String _fillInputToPlaceholder(String? input) {
if (input == null || input.isEmpty) {
return _placeholder;
}
String result = _placeholder;
final index = [0, 1, 3, 4];
final length = min(index.length, input.length);
for (int i = 0; i < length; i++) {
result = result.replaceRange(index[i], index[i] + 1, input[i]);
}
return result;
}
}
Loading

0 comments on commit 1e5d694

Please sign in to comment.