diff --git a/CHANGELOG.md b/CHANGELOG.md
index add2d3e..860be78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,12 @@
-## [1.0.1] - 2020/06/18
+## [1.0.2] - 2021/02/11
+
+* Reposition cursor if style applied while no text were selected
+
+## [1.0.1] - 2020/08/13
* Add web support
-## [1.0.0] - 2020/06/18
+## [1.0.0] - 2020/07/07
* Add RTL support
@@ -11,6 +15,6 @@
* Remove unused dependency
* Add more docs
-## [0.0.1] - 2020/01/31
+## [0.0.1] - 2020/02/18
* Initialize project
diff --git a/README.md b/README.md
index e5cd1d1..034f8ce 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,6 @@ MarkdownEditableTextInput is a TextField Widget that allow you to convert easily
## Features
- [x] Convert to Bold, Italic, Title (h1,h2,h3), List and Link
- [x] Support text direction
-- [ ] Customize textInput colors
## Demo
![](pictures/test_edition.gif)
diff --git a/example/android/app/src/main/kotlin/epsi/example/MainActivity.kt b/example/android/app/src/main/kotlin/epsi/example/MainActivity.kt
new file mode 100644
index 0000000..862c9eb
--- /dev/null
+++ b/example/android/app/src/main/kotlin/epsi/example/MainActivity.kt
@@ -0,0 +1,6 @@
+package epsi.example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..449a9f9
--- /dev/null
+++ b/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/ios/Flutter/.last_build_id b/example/ios/Flutter/.last_build_id
new file mode 100644
index 0000000..2ac0bdb
--- /dev/null
+++ b/example/ios/Flutter/.last_build_id
@@ -0,0 +1 @@
+2ba6af71af99db6e035eee54ae4f354f
\ No newline at end of file
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/example/lib/main.dart b/example/lib/main.dart
index ff05dd4..c18e76a 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -4,6 +4,7 @@ import 'package:markdown_editable_textinput/markdown_text_input.dart';
void main() => runApp(MyApp());
+// ignore: public_member_api_docs
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
@@ -17,10 +18,10 @@ class _MyAppState extends State {
return MaterialApp(
home: Theme(
data: ThemeData(
- primaryColor: const Color(0xFF2B3409),
- accentColor: const Color(0xFF71881B),
- cardColor: const Color(0xFFF7FBEA),
- textTheme: const TextTheme(body1: TextStyle(fontSize: 20)),
+ primaryColor: const Color(0xFF2C1C6B),
+ accentColor: const Color(0xFF200681),
+ cardColor: const Color(0xFFF8F9FC),
+ textTheme: const TextTheme(bodyText2: TextStyle(fontSize: 20)),
),
child: Scaffold(
appBar: AppBar(
@@ -41,7 +42,7 @@ class _MyAppState extends State {
(String value) => setState(() => description = value),
description,
label: 'Description',
- maxLines: 3,
+ maxLines: 2,
),
Padding(
padding: const EdgeInsets.only(top: 10),
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 5f5125b..1a93713 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -1,13 +1,6 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.13"
args:
dependency: transitive
description:
@@ -21,42 +14,42 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.1"
+ version: "2.5.0-nullsafety.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
- charcode:
+ version: "2.1.0-nullsafety.1"
+ characters:
dependency: transitive
description:
- name: charcode
+ name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.3"
- collection:
+ version: "1.1.0-nullsafety.3"
+ charcode:
dependency: transitive
description:
- name: collection
+ name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.12"
- convert:
+ version: "1.2.0-nullsafety.1"
+ clock:
dependency: transitive
description:
- name: convert
+ name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
- crypto:
+ version: "1.1.0-nullsafety.1"
+ collection:
dependency: transitive
description:
- name: crypto
+ name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.4"
+ version: "1.15.0-nullsafety.3"
cupertino_icons:
dependency: "direct main"
description:
@@ -70,7 +63,14 @@ packages:
name: effective_dart
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.1"
+ version: "1.3.0"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0-nullsafety.1"
flutter:
dependency: "direct main"
description: flutter
@@ -82,68 +82,47 @@ packages:
name: flutter_markdown
url: "https://pub.dartlang.org"
source: hosted
- version: "0.3.3"
+ version: "0.3.5"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
- image:
- dependency: transitive
- description:
- name: image
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.12"
markdown:
dependency: transitive
description:
name: markdown
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.3"
+ version: "2.1.8"
markdown_editable_textinput:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
- version: "1.0.1"
+ version: "1.0.2"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.6"
+ version: "0.12.10-nullsafety.1"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.8"
+ version: "1.3.0-nullsafety.3"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.6.4"
- petitparser:
- dependency: transitive
- description:
- name: petitparser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.4.0"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.3"
+ version: "1.8.0-nullsafety.1"
sky_engine:
dependency: transitive
description: flutter
@@ -155,63 +134,56 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.0-nullsafety.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.9.3"
+ version: "1.10.0-nullsafety.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.1.0-nullsafety.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0-nullsafety.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0-nullsafety.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.15"
+ version: "0.2.19-nullsafety.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.6"
+ version: "1.3.0-nullsafety.3"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.6.1"
+ version: "2.1.0-nullsafety.3"
sdks:
- dart: ">=2.6.0 <3.0.0"
+ dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.10.7 <2.0.0"
diff --git a/example/web/favicon.png b/example/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
Binary files /dev/null and b/example/web/favicon.png differ
diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
Binary files /dev/null and b/example/web/icons/Icon-192.png differ
diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
Binary files /dev/null and b/example/web/icons/Icon-512.png differ
diff --git a/example/web/index.html b/example/web/index.html
new file mode 100644
index 0000000..1460b5e
--- /dev/null
+++ b/example/web/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ example
+
+
+
+
+
+
+
+
diff --git a/example/web/manifest.json b/example/web/manifest.json
new file mode 100644
index 0000000..8c01291
--- /dev/null
+++ b/example/web/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "example",
+ "short_name": "example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/lib/format_markdown.dart b/lib/format_markdown.dart
index d36eebc..ee8e943 100644
--- a/lib/format_markdown.dart
+++ b/lib/format_markdown.dart
@@ -6,19 +6,24 @@ class FormatMarkdown {
static ResultMarkdown convertToMarkdown(MarkdownType type, String data, int fromIndex, int toIndex,
{int titleSize = 1}) {
String changedData;
+ int replaceCursorIndex;
switch (type) {
case MarkdownType.bold:
changedData = '**${data.substring(fromIndex, toIndex)}**';
+ replaceCursorIndex = 2;
break;
case MarkdownType.italic:
changedData = '_${data.substring(fromIndex, toIndex)}_';
+ replaceCursorIndex = 1;
break;
case MarkdownType.link:
changedData = '[${data.substring(fromIndex, toIndex)}](${data.substring(fromIndex, toIndex)})';
+ replaceCursorIndex = 3;
break;
case MarkdownType.title:
changedData = "${"#" * titleSize} ${data.substring(fromIndex, toIndex)}";
+ replaceCursorIndex = 0;
break;
case MarkdownType.list:
var index = 0;
@@ -27,12 +32,14 @@ class FormatMarkdown {
index++;
return index == splitedData.length ? '* $value' : '* $value\n';
}).join();
+ replaceCursorIndex = 0;
break;
}
+
final cursorIndex = changedData.length;
- return ResultMarkdown(
- data.substring(0, fromIndex) + changedData + data.substring(toIndex, data.length), cursorIndex);
+ return ResultMarkdown(data.substring(0, fromIndex) + changedData + data.substring(toIndex, data.length),
+ cursorIndex, replaceCursorIndex);
}
}
@@ -44,8 +51,11 @@ class ResultMarkdown {
/// cursor index just after the converted part in markdown
int cursorIndex;
+ /// index at which cursor need to be replaced if no text selected
+ int replaceCursorIndex;
+
/// Return [ResultMarkdown]
- ResultMarkdown(this.data, this.cursorIndex);
+ ResultMarkdown(this.data, this.cursorIndex, this.replaceCursorIndex);
}
/// Represent markdown possible type to convert
diff --git a/lib/markdown_text_input.dart b/lib/markdown_text_input.dart
index 009a677..51049f1 100644
--- a/lib/markdown_text_input.dart
+++ b/lib/markdown_text_input.dart
@@ -10,7 +10,7 @@ class MarkdownTextInput extends StatefulWidget {
final String initialValue;
/// Validator for the TextFormField
- final Function validators;
+ final String Function(String value) validators;
/// String displayed at hintText in TextFormField
final String label;
@@ -23,7 +23,7 @@ class MarkdownTextInput extends StatefulWidget {
/// Constructor for [MarkdownTextInput]
MarkdownTextInput(this.onTextChanged, this.initialValue,
- {this.label, this.validators, this.textDirection, this.maxLines});
+ {this.label = '', this.validators, this.textDirection = TextDirection.ltr, this.maxLines = 10});
@override
_MarkdownTextInputState createState() => _MarkdownTextInputState();
@@ -35,6 +35,7 @@ class _MarkdownTextInputState extends State {
void onTap(MarkdownType type, {int titleSize = 1}) {
final basePosition = textSelection.baseOffset;
+ var noTextSelected = (textSelection.baseOffset - textSelection.extentOffset) == 0;
final result = FormatMarkdown.convertToMarkdown(
type, _controller.text, textSelection.baseOffset, textSelection.extentOffset,
@@ -42,6 +43,10 @@ class _MarkdownTextInputState extends State {
_controller.value = _controller.value
.copyWith(text: result.data, selection: TextSelection.collapsed(offset: basePosition + result.cursorIndex));
+
+ if (noTextSelected) {
+ _controller.selection = TextSelection.collapsed(offset: _controller.selection.end - result.replaceCursorIndex);
+ }
}
@override
@@ -75,7 +80,7 @@ class _MarkdownTextInputState extends State {
maxLines: widget.maxLines,
controller: _controller,
textCapitalization: TextCapitalization.sentences,
- validator: widget.validators != null ? (value) => widget.validators(value) as String : null,
+ validator: (value) => widget.validators(value),
cursorColor: Theme.of(context).primaryColor,
textDirection: widget.textDirection ?? TextDirection.ltr,
decoration: InputDecoration(
diff --git a/pictures/test_edition.gif b/pictures/test_edition.gif
index 30b8771..5782354 100644
Binary files a/pictures/test_edition.gif and b/pictures/test_edition.gif differ
diff --git a/pubspec.lock b/pubspec.lock
index 10ac605..5b0798c 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,69 +1,62 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.13"
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.6.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.1"
+ version: "2.5.0-nullsafety.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
- charcode:
+ version: "2.1.0-nullsafety.1"
+ characters:
dependency: transitive
description:
- name: charcode
+ name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.3"
- collection:
+ version: "1.1.0-nullsafety.3"
+ charcode:
dependency: transitive
description:
- name: collection
+ name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.12"
- convert:
+ version: "1.2.0-nullsafety.1"
+ clock:
dependency: transitive
description:
- name: convert
+ name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
- crypto:
+ version: "1.1.0-nullsafety.1"
+ collection:
dependency: transitive
description:
- name: crypto
+ name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.4"
+ version: "1.15.0-nullsafety.3"
effective_dart:
dependency: "direct main"
description:
name: effective_dart
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.3"
+ version: "1.3.0"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0-nullsafety.1"
flutter:
dependency: "direct main"
description: flutter
@@ -74,48 +67,27 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- image:
- dependency: transitive
- description:
- name: image
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.12"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.6"
+ version: "0.12.10-nullsafety.1"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.8"
+ version: "1.3.0-nullsafety.3"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.6.4"
- petitparser:
- dependency: transitive
- description:
- name: petitparser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.4.0"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.3"
+ version: "1.8.0-nullsafety.1"
sky_engine:
dependency: transitive
description: flutter
@@ -127,62 +99,55 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.0-nullsafety.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.9.3"
+ version: "1.10.0-nullsafety.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.1.0-nullsafety.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0-nullsafety.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0-nullsafety.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.15"
+ version: "0.2.19-nullsafety.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.6"
+ version: "1.3.0-nullsafety.3"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.6.1"
+ version: "2.1.0-nullsafety.3"
sdks:
- dart: ">=2.6.0 <3.0.0"
+ dart: ">=2.10.0-110 <2.11.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 0da79dc..df45755 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: markdown_editable_textinput
description: A TextField Widget that allow you to convert easily what's in the TextField to Markdown.
-version: 1.0.1
+version: 1.0.2
homepage: https://github.com/playmoweb/markdown-editable-textinput
repository: https://github.com/playmoweb/markdown-editable-textinput