Skip to content

Commit

Permalink
added dialog on mistake tap
Browse files Browse the repository at this point in the history
  • Loading branch information
nazarski committed Apr 28, 2023
1 parent 9833fb9 commit 2c7d8a6
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 28 deletions.
22 changes: 1 addition & 21 deletions example/lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,14 @@ class _AppState extends State<App> {
/// Initialize LanguageTool
static final LanguageTool _languageTool = LanguageTool();

/// Initialize DebounceLangToolService
static final DebounceLangToolService _debouncedLangService =
DebounceLangToolService(
LangToolService(_languageTool),
const Duration(milliseconds: 500),
);

/// Initialize ColoredTextEditingController
final ColoredTextEditingController _controller =
ColoredTextEditingController(languageCheckService: _debouncedLangService);

@override
Widget build(BuildContext context) {
return Material(
child: LanguageToolTextField(
style: const TextStyle(),
decoration: const InputDecoration(),
mistakeBuilder: () {
return Container();
},
coloredController: _controller,
languageTool: _languageTool,
),
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
31 changes: 30 additions & 1 deletion lib/core/controllers/colored_text_editing_controller.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import 'dart:developer';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:language_tool/language_tool.dart';
import 'package:languagetool_textfield/core/enums/mistake_type.dart';
import 'package:languagetool_textfield/domain/highlight_style.dart';
import 'package:languagetool_textfield/domain/language_check_service.dart';
import 'package:languagetool_textfield/domain/mistake.dart';
import 'package:languagetool_textfield/implementations/lang_tool_service.dart';

/// A TextEditingController with overrides buildTextSpan for building
/// marked TextSpans with tap recognizer
Expand All @@ -13,6 +18,10 @@ class ColoredTextEditingController extends TextEditingController {
/// Language tool API index
final LanguageCheckService languageCheckService;

/// Register tap to show overlay popup
final Function(Offset globalPosition, Color color, Mistake mistake)
onMistakeTap;

/// List which contains Mistake objects spans are built from
List<Mistake> _mistakes = [];

Expand All @@ -24,8 +33,9 @@ class ColoredTextEditingController extends TextEditingController {

/// Controller constructor
ColoredTextEditingController({
required this.onMistakeTap,
required this.languageCheckService,
this.highlightStyle = const HighlightStyle(),
required this.highlightStyle,
});

/// Clear mistakes list when text mas modified and get a new list of mistakes
Expand Down Expand Up @@ -92,6 +102,16 @@ class ColoredTextEditingController extends TextEditingController {
decorationColor: mistakeColor,
decorationThickness: highlightStyle.mistakeLineThickness,
),

/// Recognizes user tap on highlighted area
recognizer: TapGestureRecognizer()
..onTapDown = (TapDownDetails details) {
_openPopup(
details: details,
color: mistakeColor,
mistake: mistake,
);
},
),
],
);
Expand All @@ -106,6 +126,15 @@ class ColoredTextEditingController extends TextEditingController {
);
}

void _openPopup({
required TapDownDetails details,
required Color color,
required Mistake mistake,
}) {
log(details.globalPosition.toString());
onMistakeTap(details.globalPosition, color, mistake);
}

/// Returns color for mistake TextSpan style
Color _getMistakeColor(MistakeType type) {
switch (type) {
Expand Down
1 change: 1 addition & 0 deletions lib/languagetool_textfield.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export 'implementations/debounce_lang_tool_service.dart';
export 'implementations/lang_tool_service.dart';
export 'implementations/throttling_lang_tool_service.dart';
export "presentation/language_tool_text_field.dart";
export 'presentation/widgets/create_popup_entry.dart';
49 changes: 43 additions & 6 deletions lib/presentation/language_tool_text_field.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:languagetool_textfield/core/controllers/colored_text_editing_controller.dart';
import 'package:languagetool_textfield/languagetool_textfield.dart';

/// A TextField widget that checks the grammar using the given
/// [coloredController]
/// [languageTool]
class LanguageToolTextField extends StatefulWidget {
/// A style to use for the text being edited.
final TextStyle style;
Expand All @@ -13,30 +13,67 @@ class LanguageToolTextField extends StatefulWidget {
/// A builder function used to build errors.
final Widget Function()? mistakeBuilder;

/// Color scheme to highlight mistakes
final ColoredTextEditingController coloredController;
/// A Service to get mistakes from API
final LanguageTool languageTool;

/// User customization for mistake highlighting
final HighlightStyle mistakeHighlightStyle;

/// Creates a widget that checks grammar errors.
const LanguageToolTextField({
Key? key,
required this.style,
required this.decoration,
required this.languageTool,
this.mistakeHighlightStyle = const HighlightStyle(),
this.mistakeBuilder,
required this.coloredController,
}) : super(key: key);

@override
State<LanguageToolTextField> createState() => _LanguageToolTextFieldState();
}

class _LanguageToolTextFieldState extends State<LanguageToolTextField> {
/// Initialize ColoredTextEditingController
ColoredTextEditingController? _controller;

@override
void initState() {
/// Creating an instance of DebounceLangToolService
final DebounceLangToolService _debouncedLangService =
DebounceLangToolService(
LangToolService(widget.languageTool),
const Duration(milliseconds: 500),
);

/// Setting ColoredTextEditingController with DebounceLangToolService and
/// a Dialog trigger function
_controller = ColoredTextEditingController(
languageCheckService: _debouncedLangService,
highlightStyle: widget.mistakeHighlightStyle,
onMistakeTap: (
Offset globalPosition,
Color color,
Mistake mistake,
) {
createPopupEntry(
globalPosition: globalPosition,
context: context,
mistake: mistake,
color: color,
);
},
);
super.initState();
}

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(24.0),
child: Center(
child: TextField(
controller: widget.coloredController,
controller: _controller,
style: widget.style,
decoration: widget.decoration,
),
Expand Down
92 changes: 92 additions & 0 deletions lib/presentation/widgets/create_popup_entry.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import 'package:flutter/material.dart';
import 'package:languagetool_textfield/languagetool_textfield.dart';

/// Creates a popup with mistake description on highlighted text tap
void createPopupEntry({
required Offset globalPosition,
required BuildContext context,
required Mistake mistake,
required Color color,
}) {
showDialog<Dialog>(
context: context,
builder: (BuildContext context) {
///Default value for radius, margin, circle size
const double defaultValue = 8;

///Capitalizing mistake type
final String mistakeType =
mistake.type.name[0].toUpperCase() + mistake.type.name.substring(1);

return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
insetPadding: EdgeInsets.zero,
child: Stack(
children: [
Positioned(
left: globalPosition.dx,
top: globalPosition.dy,
child: Material(
elevation: defaultValue,
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(defaultValue),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
height: defaultValue,
width: defaultValue,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
),
),
const SizedBox(
width: defaultValue,
),
Text(
mistakeType,
style: const TextStyle(
color: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
const SizedBox(
height: defaultValue,
),
Text(
mistake.message,
style: const TextStyle(
color: Colors.black,
fontSize: 11,
),
),
],
),
),
),
),

/// Dismiss Dialog
GestureDetector(
onTap: () {
Navigator.pop(context);
},
)
],
),
);
},
barrierColor: Colors.transparent,
);
}

0 comments on commit 2c7d8a6

Please sign in to comment.