Skip to content

Commit

Permalink
Fix toolbar paste btn #61
Browse files Browse the repository at this point in the history
  • Loading branch information
ManeraKai committed Oct 22, 2021
1 parent 195110d commit 8a19a7c
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 61 deletions.
2 changes: 2 additions & 0 deletions lib/data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ bool isMaximizedTtsOutputCanceled = false;

bool isFirst = true;

late double textFieldHeight;

var instances = [
"https://simplytranslate.org",
"https://st.alefvanoon.xyz",
Expand Down
96 changes: 40 additions & 56 deletions lib/google/widgets/translation_input/translation_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class _TranslationInputState extends State<GoogleTranslationInput> {
void initState() {
googleTranslationInputController.addListener(() async {
final tmp = googleTranslationInputController.selection;

if (!tmp.isCollapsed && isFirst) {
print('selection');
googleTranslationInputController.selection =
Expand All @@ -44,12 +43,13 @@ class _TranslationInputState extends State<GoogleTranslationInput> {

@override
Widget build(BuildContext context) {
textFieldHeight = MediaQuery.of(context).orientation == Orientation.portrait
? MediaQuery.of(context).size.height / 3 < 250
? 250
: MediaQuery.of(context).size.height / 3
: 250;
return Container(
height: MediaQuery.of(context).orientation == Orientation.portrait
? MediaQuery.of(context).size.height / 3 < 250
? 250
: MediaQuery.of(context).size.height / 3
: 250,
height: textFieldHeight,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: theme == Brightness.dark ? Color(0xff131618) : null,
Expand All @@ -70,7 +70,7 @@ class _TranslationInputState extends State<GoogleTranslationInput> {
onTap: () {
isFirst = true;
},
selectionControls: MyMaterialTextSelectionControls(),
selectionControls: _MyMaterialTextSelectionControls(),
textDirection: googleTranslationInputController.text.length == 0
? intl.Bidi.detectRtlDirectionality(
AppLocalizations.of(context)!.arabic,
Expand Down Expand Up @@ -155,7 +155,9 @@ class _TranslationInputState extends State<GoogleTranslationInput> {
}
}

class MyMaterialTextSelectionControls extends MaterialTextSelectionControls {
var _isVisible = true;

class _MyMaterialTextSelectionControls extends MaterialTextSelectionControls {
// Padding between the toolbar and the anchor.
static const double _kToolbarContentDistanceBelow = 20.0;
static const double _kToolbarContentDistance = 8.0;
Expand All @@ -172,52 +174,32 @@ class MyMaterialTextSelectionControls extends MaterialTextSelectionControls {
ClipboardStatusNotifier clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
final TextSelectionPoint startTextSelectionPoint = endpoints[0];
final TextSelectionPoint endTextSelectionPoint =
final TextSelectionPoint startSelectionPoint = endpoints[0];
final TextSelectionPoint endSelectionPoint =
endpoints.length > 1 ? endpoints[1] : endpoints[0];
final Offset anchorAbove = () {
if (startTextSelectionPoint.point.dy < 10 &&
MediaQuery.of(context).orientation == Orientation.portrait) {
return Offset(
Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
startTextSelectionPoint.point.dy -
textLineHeight -
_kToolbarContentDistance,
).dx,
140,
);
} else if (startTextSelectionPoint.point.dy >
70 + MediaQuery.of(context).size.height / 3) {
return Offset(
Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
endTextSelectionPoint.point.dy +
_kToolbarContentDistanceBelow,
).dx,
200 + MediaQuery.of(context).size.height / 3,
);
} else {
return Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
startTextSelectionPoint.point.dy -
textLineHeight -
_kToolbarContentDistance,
);
}
}();

final Offset anchorAbove = Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
startSelectionPoint.point.dy -
textLineHeight -
_kToolbarContentDistance,
);

final Offset anchorBelow = Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
endTextSelectionPoint.point.dy +
endSelectionPoint.point.dy +
_kToolbarContentDistanceBelow,
);

return MyTextSelectionToolbar(
_isVisible = () {
if (MediaQuery.of(context).orientation == Orientation.portrait) {
if (startSelectionPoint.point.dy < 20) return false;
if (startSelectionPoint.point.dy > textFieldHeight + 65) return false;
}
return true;
}();
return _MyTextSelectionToolbar(
anchorAbove: anchorAbove,
anchorBelow: anchorBelow,
clipboardStatus: clipboardStatus,
Expand All @@ -241,8 +223,8 @@ class _TextSelectionToolbarItemData {
final VoidCallback onPressed;
}

class MyTextSelectionToolbar extends StatefulWidget {
const MyTextSelectionToolbar({
class _MyTextSelectionToolbar extends StatefulWidget {
const _MyTextSelectionToolbar({
Key? key,
required this.anchorAbove,
required this.anchorBelow,
Expand All @@ -262,10 +244,10 @@ class MyTextSelectionToolbar extends StatefulWidget {
final VoidCallback handleSelectAll;

@override
MyTextSelectionToolbarState createState() => MyTextSelectionToolbarState();
_MyTextSelectionToolbarState createState() => _MyTextSelectionToolbarState();
}

class MyTextSelectionToolbarState extends State<MyTextSelectionToolbar> {
class _MyTextSelectionToolbarState extends State<_MyTextSelectionToolbar> {
void _onChangedClipboardStatus() {
setState(() {});
}
Expand All @@ -278,7 +260,7 @@ class MyTextSelectionToolbarState extends State<MyTextSelectionToolbar> {
}

@override
void didUpdateWidget(MyTextSelectionToolbar oldWidget) {
void didUpdateWidget(_MyTextSelectionToolbar oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.clipboardStatus != oldWidget.clipboardStatus) {
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
Expand Down Expand Up @@ -327,10 +309,12 @@ class MyTextSelectionToolbarState extends State<MyTextSelectionToolbar> {
anchorAbove: widget.anchorAbove,
anchorBelow: widget.anchorBelow,
toolbarBuilder: (BuildContext context, Widget child) {
return Container(
color: theme == Brightness.dark ? secondgreyColor : greenColor,
child: child,
);
if (_isVisible)
return Container(
color: theme == Brightness.dark ? secondgreyColor : greenColor,
child: child,
);
return SizedBox.shrink();
},
children: itemDatas.map((_TextSelectionToolbarItemData itemData) {
return TextSelectionToolbarTextButton(
Expand Down
190 changes: 185 additions & 5 deletions lib/google/widgets/translation_output/translation_output.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:intl/intl.dart' as intl;
import '/data.dart';
import '/google/screens/maximized/maximized.dart';
Expand All @@ -19,11 +20,7 @@ class _TranslationOutputState extends State<GoogleTranslationOutput> {
Widget build(BuildContext context) {
String translatedText = googleTranslationOutput;
return Container(
height: MediaQuery.of(context).orientation == Orientation.portrait
? MediaQuery.of(context).size.height / 3 < 250
? 250
: MediaQuery.of(context).size.height / 3
: 250,
height: textFieldHeight,
decoration: BoxDecoration(
color: theme == Brightness.dark ? Color(0xff131618) : null,
border: Border.all(
Expand All @@ -48,6 +45,7 @@ class _TranslationOutputState extends State<GoogleTranslationOutput> {
: TextDirection.ltr,
child: SelectableText(
translatedText,
selectionControls: _MyMaterialTextSelectionControls(),
style: TextStyle(fontSize: _outputFontSize),
),
),
Expand Down Expand Up @@ -96,3 +94,185 @@ class _TranslationOutputState extends State<GoogleTranslationOutput> {
);
}
}

var _isVisible = true;

class _MyMaterialTextSelectionControls extends MaterialTextSelectionControls {
// Padding between the toolbar and the anchor.
static const double _kToolbarContentDistanceBelow = 20.0;
static const double _kToolbarContentDistance = 8.0;

/// Builder for material-style copy/paste text selection toolbar.
@override
Widget buildToolbar(
BuildContext context,
Rect globalEditableRegion,
double textLineHeight,
Offset selectionMidpoint,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
final TextSelectionPoint startSelectionPoint = endpoints[0];
final TextSelectionPoint endSelectionPoint =
endpoints.length > 1 ? endpoints[1] : endpoints[0];
final Offset anchorAbove = Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
startSelectionPoint.point.dy -
textLineHeight -
_kToolbarContentDistance,
);

final Offset anchorBelow = Offset(
globalEditableRegion.left + selectionMidpoint.dx,
globalEditableRegion.top +
endSelectionPoint.point.dy +
_kToolbarContentDistanceBelow,
);
_isVisible = () {
if (MediaQuery.of(context).orientation == Orientation.portrait) {
if (startSelectionPoint.point.dy < 20) return false;
if (startSelectionPoint.point.dy > textFieldHeight + 65) return false;
}
return true;
}();

return _MyTextSelectionToolbar(
anchorAbove: anchorAbove,
anchorBelow: anchorBelow,
clipboardStatus: clipboardStatus,
handleCopy: canCopy(delegate)
? () => handleCopy(delegate, clipboardStatus)
: () {},
handleCut: canCut(delegate) ? () => handleCut(delegate) : () {},
handlePaste: canPaste(delegate)
? () {
handlePaste(delegate);
isFirst = true;
}
: () {},
handleSelectAll:
canSelectAll(delegate) ? () => handleSelectAll(delegate) : () {},
);
}
}

class _TextSelectionToolbarItemData {
const _TextSelectionToolbarItemData({
required this.label,
required this.onPressed,
});
final String label;
final VoidCallback onPressed;
}

class _MyTextSelectionToolbar extends StatefulWidget {
const _MyTextSelectionToolbar({
Key? key,
required this.anchorAbove,
required this.anchorBelow,
required this.clipboardStatus,
required this.handleCopy,
required this.handleCut,
required this.handlePaste,
required this.handleSelectAll,
}) : super(key: key);

final Offset anchorAbove;
final Offset anchorBelow;
final ClipboardStatusNotifier clipboardStatus;
final VoidCallback handleCopy;
final VoidCallback handleCut;
final VoidCallback handlePaste;
final VoidCallback handleSelectAll;

@override
__MyTextSelectionToolbarState createState() =>
__MyTextSelectionToolbarState();
}

class __MyTextSelectionToolbarState extends State<_MyTextSelectionToolbar> {
void _onChangedClipboardStatus() {
setState(() {});
}

@override
void initState() {
super.initState();
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
widget.clipboardStatus.update();
}

@override
void didUpdateWidget(_MyTextSelectionToolbar oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.clipboardStatus != oldWidget.clipboardStatus) {
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
oldWidget.clipboardStatus.removeListener(_onChangedClipboardStatus);
}
widget.clipboardStatus.update();
}

@override
void dispose() {
super.dispose();
if (!widget.clipboardStatus.disposed) {
widget.clipboardStatus.removeListener(_onChangedClipboardStatus);
}
}

@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final MaterialLocalizations localizations =
MaterialLocalizations.of(context);

final List<_TextSelectionToolbarItemData> itemDatas =
<_TextSelectionToolbarItemData>[
_TextSelectionToolbarItemData(
label: localizations.cutButtonLabel,
onPressed: widget.handleCut,
),
_TextSelectionToolbarItemData(
label: localizations.copyButtonLabel,
onPressed: widget.handleCopy,
),
if (widget.clipboardStatus.value == ClipboardStatus.pasteable)
_TextSelectionToolbarItemData(
label: localizations.pasteButtonLabel,
onPressed: widget.handlePaste,
),
_TextSelectionToolbarItemData(
label: localizations.selectAllButtonLabel,
onPressed: widget.handleSelectAll,
),
];

int childIndex = 0;
return TextSelectionToolbar(
anchorAbove: widget.anchorAbove,
anchorBelow: widget.anchorBelow,
toolbarBuilder: (BuildContext context, Widget child) {
if (_isVisible)
return Container(
color: theme == Brightness.dark ? secondgreyColor : greenColor,
child: child,
);
return SizedBox.shrink();
},
children: itemDatas.map((_TextSelectionToolbarItemData itemData) {
return TextSelectionToolbarTextButton(
padding: TextSelectionToolbarTextButton.getPadding(
childIndex++, itemDatas.length),
onPressed: itemData.onPressed,
child: Text(
itemData.label,
style: TextStyle(color: Colors.white),
),
);
}).toList(),
);
}
}

0 comments on commit 8a19a7c

Please sign in to comment.