Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
32547dcc
Unverified
Commit
32547dcc
authored
May 15, 2020
by
nturgut
Committed by
GitHub
May 15, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert " Bring back paste button hide behavior 3 (#57139)" (#57286)
This reverts commit
8de07d55
.
parent
3b4f6864
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
119 additions
and
752 deletions
+119
-752
text_field_constants.dart
...semantics_testing/lib/src/tests/text_field_constants.dart
+0
-3
text_field_page.dart
...roid_semantics_testing/lib/src/tests/text_field_page.dart
+1
-2
main_test.dart
...ests/android_semantics_testing/test_driver/main_test.dart
+0
-32
text_selection.dart
packages/flutter/lib/src/cupertino/text_selection.dart
+41
-154
text_selection.dart
packages/flutter/lib/src/material/text_selection.dart
+12
-90
editable_text.dart
packages/flutter/lib/src/widgets/editable_text.dart
+2
-17
text_selection.dart
packages/flutter/lib/src/widgets/text_selection.dart
+4
-102
text_field_test.dart
packages/flutter/test/cupertino/text_field_test.dart
+15
-18
text_selection_test.dart
packages/flutter/test/cupertino/text_selection_test.dart
+2
-71
date_picker_test.dart
packages/flutter/test/material/date_picker_test.dart
+2
-29
search_test.dart
packages/flutter/test/material/search_test.dart
+0
-30
text_field_test.dart
packages/flutter/test/material/text_field_test.dart
+23
-100
text_selection_test.dart
packages/flutter/test/material/text_selection_test.dart
+5
-84
editable_text_cursor_test.dart
packages/flutter/test/widgets/editable_text_cursor_test.dart
+2
-7
editable_text_test.dart
packages/flutter/test/widgets/editable_text_test.dart
+10
-13
No files found.
dev/integration_tests/android_semantics_testing/lib/src/tests/text_field_constants.dart
View file @
32547dcc
...
...
@@ -10,6 +10,3 @@ const String normalTextFieldKeyValue = 'textFieldNormal';
/// The string supplied to the [ValueKey] for the password text field.
const
String
passwordTextFieldKeyValue
=
'passwordField'
;
/// The string supplied to the [ValueKey] for the page navigation back button.
const
String
backButtonKeyValue
=
'back'
;
dev/integration_tests/android_semantics_testing/lib/src/tests/text_field_page.dart
View file @
32547dcc
...
...
@@ -17,14 +17,13 @@ class TextFieldPage extends StatefulWidget {
class
_TextFieldPageState
extends
State
<
TextFieldPage
>
{
final
TextEditingController
_normalController
=
TextEditingController
();
final
TextEditingController
_passwordController
=
TextEditingController
();
final
Key
backButtonKey
=
const
ValueKey
<
String
>(
backButtonKeyValue
);
final
Key
normalTextFieldKey
=
const
ValueKey
<
String
>(
normalTextFieldKeyValue
);
final
Key
passwordTextFieldKey
=
const
ValueKey
<
String
>(
passwordTextFieldKeyValue
);
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
leading:
BackButton
(
key:
backButtonKey
)),
appBar:
AppBar
(
leading:
const
BackButton
(
key:
ValueKey
<
String
>(
'back'
)
)),
body:
Material
(
child:
Column
(
children:
<
Widget
>[
TextField
(
...
...
dev/integration_tests/android_semantics_testing/test_driver/main_test.dart
View file @
32547dcc
...
...
@@ -63,38 +63,6 @@ void main() {
await
driver
.
tap
(
find
.
text
(
textFieldRoute
));
// Delay for TalkBack to update focus as of November 2019 with Pixel 3 and Android API 28
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
// The text selection menu and related semantics vary depending on if
// the clipboard contents are pasteable. Copy some text into the
// clipboard to make sure these tests always run with pasteable content
// in the clipboard.
// Ideally this should test the case where there is nothing on the
// clipboard as well, but there is no reliable way to clear the
// clipboard on Android devices.
final
SerializableFinder
normalTextField
=
find
.
descendant
(
of:
find
.
byValueKey
(
normalTextFieldKeyValue
),
matching:
find
.
byType
(
'Semantics'
),
firstMatchOnly:
true
,
);
await
driver
.
tap
(
normalTextField
);
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
await
driver
.
enterText
(
'hello world'
);
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
await
driver
.
tap
(
normalTextField
);
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
50
));
await
driver
.
tap
(
normalTextField
);
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
await
driver
.
tap
(
find
.
text
(
'SELECT ALL'
));
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
await
driver
.
tap
(
find
.
text
(
'COPY'
));
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
50
));
await
driver
.
enterText
(
''
);
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
// Go back to previous page and forward again to unfocus the field.
await
driver
.
tap
(
find
.
byValueKey
(
backButtonKeyValue
));
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
await
driver
.
tap
(
find
.
text
(
textFieldRoute
));
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
500
));
});
test
(
'TextField has correct Android semantics'
,
()
async
{
...
...
packages/flutter/lib/src/cupertino/text_selection.dart
View file @
32547dcc
...
...
@@ -8,7 +8,6 @@ import 'dart:ui' as ui;
import
'package:flutter/widgets.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'button.dart'
;
import
'colors.dart'
;
...
...
@@ -63,151 +62,6 @@ const TextStyle _kToolbarButtonDisabledFontStyle = TextStyle(
// Eyeballed value.
const
EdgeInsets
_kToolbarButtonPadding
=
EdgeInsets
.
symmetric
(
vertical:
10.0
,
horizontal:
18.0
);
// Generates the child that's passed into CupertinoTextSelectionToolbar.
class
_CupertinoTextSelectionToolbarWrapper
extends
StatefulWidget
{
const
_CupertinoTextSelectionToolbarWrapper
({
Key
key
,
this
.
arrowTipX
,
this
.
barTopY
,
this
.
clipboardStatus
,
this
.
handleCut
,
this
.
handleCopy
,
this
.
handlePaste
,
this
.
handleSelectAll
,
this
.
isArrowPointingDown
,
})
:
super
(
key:
key
);
final
double
arrowTipX
;
final
double
barTopY
;
final
ClipboardStatusNotifier
clipboardStatus
;
final
VoidCallback
handleCut
;
final
VoidCallback
handleCopy
;
final
VoidCallback
handlePaste
;
final
VoidCallback
handleSelectAll
;
final
bool
isArrowPointingDown
;
@override
_CupertinoTextSelectionToolbarWrapperState
createState
()
=>
_CupertinoTextSelectionToolbarWrapperState
();
}
class
_CupertinoTextSelectionToolbarWrapperState
extends
State
<
_CupertinoTextSelectionToolbarWrapper
>
{
ClipboardStatusNotifier
_clipboardStatus
;
void
_onChangedClipboardStatus
()
{
setState
(()
{
// Inform the widget that the value of clipboardStatus has changed.
});
}
@override
void
initState
()
{
super
.
initState
();
_clipboardStatus
=
widget
.
clipboardStatus
??
ClipboardStatusNotifier
();
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
_clipboardStatus
.
update
();
}
@override
void
didUpdateWidget
(
_CupertinoTextSelectionToolbarWrapper
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
if
(
oldWidget
.
clipboardStatus
==
null
&&
widget
.
clipboardStatus
!=
null
)
{
_clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
_clipboardStatus
.
dispose
();
_clipboardStatus
=
widget
.
clipboardStatus
;
}
else
if
(
oldWidget
.
clipboardStatus
!=
null
)
{
if
(
widget
.
clipboardStatus
==
null
)
{
_clipboardStatus
=
ClipboardStatusNotifier
();
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
oldWidget
.
clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
}
else
if
(
widget
.
clipboardStatus
!=
oldWidget
.
clipboardStatus
)
{
_clipboardStatus
=
widget
.
clipboardStatus
;
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
oldWidget
.
clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
}
}
if
(
widget
.
handlePaste
!=
null
)
{
_clipboardStatus
.
update
();
}
}
@override
void
dispose
()
{
super
.
dispose
();
// When used in an Overlay, this can be disposed after its creator has
// already disposed _clipboardStatus.
if
(!
_clipboardStatus
.
disposed
)
{
_clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
if
(
widget
.
clipboardStatus
==
null
)
{
_clipboardStatus
.
dispose
();
}
}
}
@override
Widget
build
(
BuildContext
context
)
{
// Don't render the menu until the state of the clipboard is known.
if
(
widget
.
handlePaste
!=
null
&&
_clipboardStatus
.
value
==
ClipboardStatus
.
unknown
)
{
return
const
SizedBox
(
width:
0.0
,
height:
0.0
);
}
final
List
<
Widget
>
items
=
<
Widget
>[];
final
CupertinoLocalizations
localizations
=
CupertinoLocalizations
.
of
(
context
);
final
EdgeInsets
arrowPadding
=
widget
.
isArrowPointingDown
?
EdgeInsets
.
only
(
bottom:
_kToolbarArrowSize
.
height
)
:
EdgeInsets
.
only
(
top:
_kToolbarArrowSize
.
height
);
final
Widget
onePhysicalPixelVerticalDivider
=
SizedBox
(
width:
1.0
/
MediaQuery
.
of
(
context
).
devicePixelRatio
);
void
addToolbarButton
(
String
text
,
VoidCallback
onPressed
,
)
{
if
(
items
.
isNotEmpty
)
{
items
.
add
(
onePhysicalPixelVerticalDivider
);
}
items
.
add
(
CupertinoButton
(
child:
Text
(
text
,
overflow:
TextOverflow
.
ellipsis
,
style:
_kToolbarButtonFontStyle
,
),
borderRadius:
null
,
color:
_kToolbarBackgroundColor
,
minSize:
_kToolbarHeight
,
onPressed:
onPressed
,
padding:
_kToolbarButtonPadding
.
add
(
arrowPadding
),
pressedOpacity:
0.7
,
));
}
if
(
widget
.
handleCut
!=
null
)
{
addToolbarButton
(
localizations
.
cutButtonLabel
,
widget
.
handleCut
);
}
if
(
widget
.
handleCopy
!=
null
)
{
addToolbarButton
(
localizations
.
copyButtonLabel
,
widget
.
handleCopy
);
}
if
(
widget
.
handlePaste
!=
null
&&
_clipboardStatus
.
value
==
ClipboardStatus
.
pasteable
)
{
addToolbarButton
(
localizations
.
pasteButtonLabel
,
widget
.
handlePaste
);
}
if
(
widget
.
handleSelectAll
!=
null
)
{
addToolbarButton
(
localizations
.
selectAllButtonLabel
,
widget
.
handleSelectAll
);
}
return
CupertinoTextSelectionToolbar
.
_
(
barTopY:
widget
.
barTopY
,
arrowTipX:
widget
.
arrowTipX
,
isArrowPointingDown:
widget
.
isArrowPointingDown
,
child:
items
.
isEmpty
?
null
:
_CupertinoTextSelectionToolbarContent
(
isArrowPointingDown:
widget
.
isArrowPointingDown
,
children:
items
,
),
);
}
}
/// An iOS-style toolbar that appears in response to text selection.
///
/// Typically displays buttons for text manipulation, e.g. copying and pasting text.
...
...
@@ -458,7 +312,6 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
Offset
position
,
List
<
TextSelectionPoint
>
endpoints
,
TextSelectionDelegate
delegate
,
ClipboardStatusNotifier
clipboardStatus
,
)
{
assert
(
debugCheckHasMediaQuery
(
context
));
final
MediaQueryData
mediaQuery
=
MediaQuery
.
of
(
context
);
...
...
@@ -485,15 +338,49 @@ class _CupertinoTextSelectionControls extends TextSelectionControls {
?
endpoints
.
first
.
point
.
dy
-
textLineHeight
-
_kToolbarContentDistance
-
_kToolbarHeight
:
endpoints
.
last
.
point
.
dy
+
_kToolbarContentDistance
;
return
_CupertinoTextSelectionToolbarWrapper
(
arrowTipX:
arrowTipX
,
final
List
<
Widget
>
items
=
<
Widget
>[];
final
CupertinoLocalizations
localizations
=
CupertinoLocalizations
.
of
(
context
);
final
EdgeInsets
arrowPadding
=
isArrowPointingDown
?
EdgeInsets
.
only
(
bottom:
_kToolbarArrowSize
.
height
)
:
EdgeInsets
.
only
(
top:
_kToolbarArrowSize
.
height
);
void
addToolbarButtonIfNeeded
(
String
text
,
bool
Function
(
TextSelectionDelegate
)
predicate
,
void
Function
(
TextSelectionDelegate
)
onPressed
,
)
{
if
(!
predicate
(
delegate
))
{
return
;
}
items
.
add
(
CupertinoButton
(
child:
Text
(
text
,
overflow:
TextOverflow
.
ellipsis
,
style:
_kToolbarButtonFontStyle
,
),
color:
_kToolbarBackgroundColor
,
minSize:
_kToolbarHeight
,
padding:
_kToolbarButtonPadding
.
add
(
arrowPadding
),
borderRadius:
null
,
pressedOpacity:
0.7
,
onPressed:
()
=>
onPressed
(
delegate
),
));
}
addToolbarButtonIfNeeded
(
localizations
.
cutButtonLabel
,
canCut
,
handleCut
);
addToolbarButtonIfNeeded
(
localizations
.
copyButtonLabel
,
canCopy
,
handleCopy
);
addToolbarButtonIfNeeded
(
localizations
.
pasteButtonLabel
,
canPaste
,
handlePaste
);
addToolbarButtonIfNeeded
(
localizations
.
selectAllButtonLabel
,
canSelectAll
,
handleSelectAll
);
return
CupertinoTextSelectionToolbar
.
_
(
barTopY:
localBarTopY
+
globalEditableRegion
.
top
,
clipboardStatus:
clipboardStatus
,
handleCut:
canCut
(
delegate
)
?
()
=>
handleCut
(
delegate
)
:
null
,
handleCopy:
canCopy
(
delegate
)
?
()
=>
handleCopy
(
delegate
,
clipboardStatus
)
:
null
,
handlePaste:
canPaste
(
delegate
)
?
()
=>
handlePaste
(
delegate
)
:
null
,
handleSelectAll:
canSelectAll
(
delegate
)
?
()
=>
handleSelectAll
(
delegate
)
:
null
,
arrowTipX:
arrowTipX
,
isArrowPointingDown:
isArrowPointingDown
,
child:
items
.
isEmpty
?
null
:
_CupertinoTextSelectionToolbarContent
(
isArrowPointingDown:
isArrowPointingDown
,
children:
items
,
),
);
}
...
...
packages/flutter/lib/src/material/text_selection.dart
View file @
32547dcc
...
...
@@ -6,7 +6,6 @@ import 'dart:math' as math;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter/widgets.dart'
;
import
'debug.dart'
;
...
...
@@ -30,7 +29,6 @@ const double _kToolbarContentDistance = 8.0;
/// Manages a copy/paste text selection toolbar.
class
_TextSelectionToolbar
extends
StatefulWidget
{
const
_TextSelectionToolbar
({
this
.
clipboardStatus
,
Key
key
,
this
.
handleCut
,
this
.
handleCopy
,
...
...
@@ -39,7 +37,6 @@ class _TextSelectionToolbar extends StatefulWidget {
this
.
isAbove
,
})
:
super
(
key:
key
);
final
ClipboardStatusNotifier
clipboardStatus
;
final
VoidCallback
handleCut
;
final
VoidCallback
handleCopy
;
final
VoidCallback
handlePaste
;
...
...
@@ -53,8 +50,6 @@ class _TextSelectionToolbar extends StatefulWidget {
}
class
_TextSelectionToolbarState
extends
State
<
_TextSelectionToolbar
>
with
TickerProviderStateMixin
{
ClipboardStatusNotifier
_clipboardStatus
;
// Whether or not the overflow menu is open. When it is closed, the menu
// items that don't overflow are shown. When it is open, only the overflowing
// menu items are shown.
...
...
@@ -71,93 +66,33 @@ class _TextSelectionToolbarState extends State<_TextSelectionToolbar> with Ticke
);
}
// Close the menu and reset layout calculations, as in when the menu has
// changed and saved values are no longer relevant. This should be called in
// setState or another context where a rebuild is happening.
void
_reset
()
{
// Change _TextSelectionToolbarContainer's key when the menu changes in
// order to cause it to rebuild. This lets it recalculate its
// saved width for the new set of children, and it prevents AnimatedSize
// from animating the size change.
_containerKey
=
UniqueKey
();
// If the menu items change, make sure the overflow menu is closed. This
// prevents an empty overflow menu.
_overflowOpen
=
false
;
}
void
_onChangedClipboardStatus
()
{
setState
(()
{
// Inform the widget that the value of clipboardStatus has changed.
});
}
@override
void
initState
()
{
super
.
initState
();
_clipboardStatus
=
widget
.
clipboardStatus
??
ClipboardStatusNotifier
();
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
_clipboardStatus
.
update
();
}
@override
void
didUpdateWidget
(
_TextSelectionToolbar
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
// If the children are changing, the current page should be reset.
if
(((
widget
.
handleCut
==
null
)
!=
(
oldWidget
.
handleCut
==
null
))
||
((
widget
.
handleCopy
==
null
)
!=
(
oldWidget
.
handleCopy
==
null
))
||
((
widget
.
handlePaste
==
null
)
!=
(
oldWidget
.
handlePaste
==
null
))
||
((
widget
.
handleSelectAll
==
null
)
!=
(
oldWidget
.
handleSelectAll
==
null
)))
{
_reset
();
}
if
(
oldWidget
.
clipboardStatus
==
null
&&
widget
.
clipboardStatus
!=
null
)
{
_clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
_clipboardStatus
.
dispose
();
_clipboardStatus
=
widget
.
clipboardStatus
;
}
else
if
(
oldWidget
.
clipboardStatus
!=
null
)
{
if
(
widget
.
clipboardStatus
==
null
)
{
_clipboardStatus
=
ClipboardStatusNotifier
();
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
oldWidget
.
clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
}
else
if
(
widget
.
clipboardStatus
!=
oldWidget
.
clipboardStatus
)
{
_clipboardStatus
=
widget
.
clipboardStatus
;
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
oldWidget
.
clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
}
}
if
(
widget
.
handlePaste
!=
null
)
{
_clipboardStatus
.
update
();
}
}
@override
void
dispose
()
{
super
.
dispose
();
// When used in an Overlay, this can be disposed after its creator has
// already disposed _clipboardStatus.
if
(!
_clipboardStatus
.
disposed
)
{
_clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
if
(
widget
.
clipboardStatus
==
null
)
{
_clipboardStatus
.
dispose
();
}
// Change _TextSelectionToolbarContainer's key when the menu changes in
// order to cause it to rebuild. This lets it recalculate its
// saved width for the new set of children, and it prevents AnimatedSize
// from animating the size change.
_containerKey
=
UniqueKey
();
// If the menu items change, make sure the overflow menu is closed. This
// prevents an empty overflow menu.
_overflowOpen
=
false
;
}
super
.
didUpdateWidget
(
oldWidget
);
}
@override
Widget
build
(
BuildContext
context
)
{
// Don't render the menu until the state of the clipboard is known.
if
(
widget
.
handlePaste
!=
null
&&
_clipboardStatus
.
value
==
ClipboardStatus
.
unknown
)
{
return
const
SizedBox
(
width:
0.0
,
height:
0.0
);
}
final
MaterialLocalizations
localizations
=
MaterialLocalizations
.
of
(
context
);
final
List
<
Widget
>
items
=
<
Widget
>[
if
(
widget
.
handleCut
!=
null
)
_getItem
(
widget
.
handleCut
,
localizations
.
cutButtonLabel
),
if
(
widget
.
handleCopy
!=
null
)
_getItem
(
widget
.
handleCopy
,
localizations
.
copyButtonLabel
),
if
(
widget
.
handlePaste
!=
null
&&
_clipboardStatus
.
value
==
ClipboardStatus
.
pasteable
)
if
(
widget
.
handlePaste
!=
null
)
_getItem
(
widget
.
handlePaste
,
localizations
.
pasteButtonLabel
),
if
(
widget
.
handleSelectAll
!=
null
)
_getItem
(
widget
.
handleSelectAll
,
localizations
.
selectAllButtonLabel
),
...
...
@@ -168,6 +103,7 @@ class _TextSelectionToolbarState extends State<_TextSelectionToolbar> with Ticke
return
const
SizedBox
(
width:
0.0
,
height:
0.0
);
}
return
_TextSelectionToolbarContainer
(
key:
_containerKey
,
overflowOpen:
_overflowOpen
,
...
...
@@ -591,18 +527,6 @@ class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRender
}
return
false
;
}
// Visit only the children that should be painted.
@override
void
visitChildrenForSemantics
(
RenderObjectVisitor
visitor
)
{
visitChildren
((
RenderObject
renderObjectChild
)
{
final
RenderBox
child
=
renderObjectChild
as
RenderBox
;
final
ToolbarItemsParentData
childParentData
=
child
.
parentData
as
ToolbarItemsParentData
;
if
(
childParentData
.
shouldPaint
)
{
visitor
(
renderObjectChild
);
}
});
}
}
/// Centers the toolbar around the given anchor, ensuring that it remains on
...
...
@@ -706,7 +630,6 @@ class _MaterialTextSelectionControls extends TextSelectionControls {
Offset
selectionMidpoint
,
List
<
TextSelectionPoint
>
endpoints
,
TextSelectionDelegate
delegate
,
ClipboardStatusNotifier
clipboardStatus
,
)
{
assert
(
debugCheckHasMediaQuery
(
context
));
assert
(
debugCheckHasMaterialLocalizations
(
context
));
...
...
@@ -742,9 +665,8 @@ class _MaterialTextSelectionControls extends TextSelectionControls {
fitsAbove
,
),
child:
_TextSelectionToolbar
(
clipboardStatus:
clipboardStatus
,
handleCut:
canCut
(
delegate
)
?
()
=>
handleCut
(
delegate
)
:
null
,
handleCopy:
canCopy
(
delegate
)
?
()
=>
handleCopy
(
delegate
,
clipboardStatus
)
:
null
,
handleCopy:
canCopy
(
delegate
)
?
()
=>
handleCopy
(
delegate
)
:
null
,
handlePaste:
canPaste
(
delegate
)
?
()
=>
handlePaste
(
delegate
)
:
null
,
handleSelectAll:
canSelectAll
(
delegate
)
?
()
=>
handleSelectAll
(
delegate
)
:
null
,
isAbove:
fitsAbove
,
...
...
packages/flutter/lib/src/widgets/editable_text.dart
View file @
32547dcc
...
...
@@ -1144,7 +1144,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
bool
_targetCursorVisibility
=
false
;
final
ValueNotifier
<
bool
>
_cursorVisibilityNotifier
=
ValueNotifier
<
bool
>(
true
);
final
GlobalKey
_editableKey
=
GlobalKey
();
final
ClipboardStatusNotifier
_clipboardStatus
=
ClipboardStatusNotifier
();
TextInputConnection
_textInputConnection
;
TextSelectionOverlay
_selectionOverlay
;
...
...
@@ -1191,18 +1190,11 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
@override
bool
get
selectAllEnabled
=>
widget
.
toolbarOptions
.
selectAll
;
void
_onChangedClipboardStatus
()
{
setState
(()
{
// Inform the widget that the value of clipboardStatus has changed.
});
}
// State lifecycle:
@override
void
initState
()
{
super
.
initState
();
_clipboardStatus
.
addListener
(
_onChangedClipboardStatus
);
widget
.
controller
.
addListener
(
_didChangeTextEditingValue
);
_focusAttachment
=
widget
.
focusNode
.
attach
(
context
);
widget
.
focusNode
.
addListener
(
_handleFocusChanged
);
...
...
@@ -1276,9 +1268,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
);
}
}
if
(
widget
.
selectionEnabled
&&
pasteEnabled
&&
widget
.
selectionControls
?.
canPaste
(
this
)
==
true
)
{
_clipboardStatus
.
update
();
}
}
@override
...
...
@@ -1295,9 +1284,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_selectionOverlay
=
null
;
_focusAttachment
.
detach
();
widget
.
focusNode
.
removeListener
(
_handleFocusChanged
);
WidgetsBinding
.
instance
.
removeObserver
(
this
);
_clipboardStatus
.
removeListener
(
_onChangedClipboardStatus
);
_clipboardStatus
.
dispose
();
super
.
dispose
();
}
...
...
@@ -1624,7 +1610,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if
(
widget
.
selectionControls
!=
null
)
{
_selectionOverlay
=
TextSelectionOverlay
(
clipboardStatus:
_clipboardStatus
,
context:
context
,
value:
_value
,
debugRequiredFor:
widget
,
...
...
@@ -1995,7 +1980,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
VoidCallback
_semanticsOnCopy
(
TextSelectionControls
controls
)
{
return
widget
.
selectionEnabled
&&
copyEnabled
&&
_hasFocus
&&
controls
?.
canCopy
(
this
)
==
true
?
()
=>
controls
.
handleCopy
(
this
,
_clipboardStatus
)
?
()
=>
controls
.
handleCopy
(
this
)
:
null
;
}
...
...
@@ -2006,7 +1991,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
}
VoidCallback
_semanticsOnPaste
(
TextSelectionControls
controls
)
{
return
widget
.
selectionEnabled
&&
pasteEnabled
&&
_hasFocus
&&
controls
?.
canPaste
(
this
)
==
true
&&
_clipboardStatus
.
value
==
ClipboardStatus
.
pasteabl
e
return
widget
.
selectionEnabled
&&
pasteEnabled
&&
_hasFocus
&&
controls
?.
canPaste
(
this
)
==
tru
e
?
()
=>
controls
.
handlePaste
(
this
)
:
null
;
}
...
...
packages/flutter/lib/src/widgets/text_selection.dart
View file @
32547dcc
...
...
@@ -12,7 +12,6 @@ import 'package:flutter/scheduler.dart';
import
'package:flutter/services.dart'
;
import
'basic.dart'
;
import
'binding.dart'
;
import
'constants.dart'
;
import
'container.dart'
;
import
'editable_text.dart'
;
...
...
@@ -138,7 +137,6 @@ abstract class TextSelectionControls {
Offset
position
,
List
<
TextSelectionPoint
>
endpoints
,
TextSelectionDelegate
delegate
,
ClipboardStatusNotifier
clipboardStatus
,
);
/// Returns the size of the selection handle.
...
...
@@ -167,16 +165,13 @@ abstract class TextSelectionControls {
return
delegate
.
copyEnabled
&&
!
delegate
.
textEditingValue
.
selection
.
isCollapsed
;
}
/// Whether the
text field managed by the given `delegate` supports pasting
///
from the clipboard
.
/// Whether the
current [Clipboard] content can be pasted into the text field
///
managed by the given `delegate`
.
///
/// Subclasses can use this to decide if they should expose the paste
/// functionality to the user.
///
/// This does not consider the contents of the clipboard. Subclasses may want
/// to, for example, disallow pasting when the clipboard contains an empty
/// string.
bool
canPaste
(
TextSelectionDelegate
delegate
)
{
// TODO(goderbauer): return false when clipboard is empty, https://github.com/flutter/flutter/issues/11254
return
delegate
.
pasteEnabled
;
}
...
...
@@ -218,12 +213,11 @@ abstract class TextSelectionControls {
///
/// This is called by subclasses when their copy affordance is activated by
/// the user.
void
handleCopy
(
TextSelectionDelegate
delegate
,
ClipboardStatusNotifier
clipboardStatus
)
{
void
handleCopy
(
TextSelectionDelegate
delegate
)
{
final
TextEditingValue
value
=
delegate
.
textEditingValue
;
Clipboard
.
setData
(
ClipboardData
(
text:
value
.
selection
.
textInside
(
value
.
text
),
));
clipboardStatus
?.
update
();
delegate
.
textEditingValue
=
TextEditingValue
(
text:
value
.
text
,
selection:
TextSelection
.
collapsed
(
offset:
value
.
selection
.
end
),
...
...
@@ -300,7 +294,6 @@ class TextSelectionOverlay {
this
.
selectionDelegate
,
this
.
dragStartBehavior
=
DragStartBehavior
.
start
,
this
.
onSelectionHandleTapped
,
this
.
clipboardStatus
,
})
:
assert
(
value
!=
null
),
assert
(
context
!=
null
),
assert
(
handlesVisible
!=
null
),
...
...
@@ -372,13 +365,6 @@ class TextSelectionOverlay {
/// {@endtemplate}
final
VoidCallback
onSelectionHandleTapped
;
/// Maintains the status of the clipboard for determining if its contents can
/// be pasted or not.
///
/// Useful because the actual value of the clipboard can only be checked
/// asynchronously (see [Clipboard.getData]).
final
ClipboardStatusNotifier
clipboardStatus
;
/// Controls the fade-in and fade-out animations for the toolbar and handles.
static
const
Duration
fadeDuration
=
Duration
(
milliseconds:
150
);
...
...
@@ -590,7 +576,6 @@ class TextSelectionOverlay {
midpoint
,
endpoints
,
selectionDelegate
,
clipboardStatus
,
),
),
);
...
...
@@ -1501,86 +1486,3 @@ class _TransparentTapGestureRecognizer extends TapGestureRecognizer {
}
}
}
/// A [ValueNotifier] whose [value] indicates whether the current contents of
/// the clipboard can be pasted.
///
/// The contents of the clipboard can only be read asynchronously, via
/// [Clipboard.getData], so this maintains a value that can be used
/// synchronously. Call [update] to asynchronously update value if needed.
class
ClipboardStatusNotifier
extends
ValueNotifier
<
ClipboardStatus
>
with
WidgetsBindingObserver
{
/// Create a new ClipboardStatusNotifier.
ClipboardStatusNotifier
({
ClipboardStatus
value
=
ClipboardStatus
.
unknown
,
})
:
super
(
value
);
bool
_disposed
=
false
;
/// True iff this instance has been disposed.
bool
get
disposed
=>
_disposed
;
/// Check the [Clipboard] and update [value] if needed.
void
update
()
{
Clipboard
.
getData
(
Clipboard
.
kTextPlain
).
then
((
ClipboardData
data
)
{
final
ClipboardStatus
clipboardStatus
=
data
!=
null
&&
data
.
text
!=
null
&&
data
.
text
.
isNotEmpty
?
ClipboardStatus
.
pasteable
:
ClipboardStatus
.
notPasteable
;
if
(
_disposed
||
clipboardStatus
==
value
)
{
return
;
}
value
=
clipboardStatus
;
});
}
@override
void
addListener
(
VoidCallback
listener
)
{
if
(!
hasListeners
)
{
WidgetsBinding
.
instance
.
addObserver
(
this
);
}
if
(
value
==
ClipboardStatus
.
unknown
)
{
update
();
}
super
.
addListener
(
listener
);
}
@override
void
removeListener
(
VoidCallback
listener
)
{
super
.
removeListener
(
listener
);
if
(!
hasListeners
)
{
WidgetsBinding
.
instance
.
removeObserver
(
this
);
}
}
@override
void
didChangeAppLifecycleState
(
AppLifecycleState
state
)
{
switch
(
state
)
{
case
AppLifecycleState
.
resumed
:
update
();
break
;
case
AppLifecycleState
.
detached
:
case
AppLifecycleState
.
inactive
:
case
AppLifecycleState
.
paused
:
// Nothing to do.
}
}
@override
void
dispose
()
{
super
.
dispose
();
WidgetsBinding
.
instance
.
removeObserver
(
this
);
_disposed
=
true
;
}
}
/// An enumeration of the status of the content on the user's clipboard.
enum
ClipboardStatus
{
/// The clipboard content can be pasted, such as a String of nonzero length.
pasteable
,
/// The status of the clipboard is unknown. Since getting clipboard data is
/// asynchronous (see [Clipboard.getData]), this status often exists while
/// waiting to receive the clipboard contents for the first time.
unknown
,
/// The content on the clipboard is not pasteable, such as when it is empty.
notPasteable
,
}
packages/flutter/test/cupertino/text_field_test.dart
View file @
32547dcc
...
...
@@ -171,11 +171,8 @@ void main() {
Offset
textOffsetToPosition
(
WidgetTester
tester
,
int
offset
)
=>
textOffsetToBottomLeftPosition
(
tester
,
offset
)
+
const
Offset
(
0
,
-
2
);
setUp
(()
async
{
setUp
(()
{
EditableText
.
debugDeterministicCursor
=
false
;
// Fill the clipboard so that the PASTE option is available in the text
// selection menu.
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
'Clipboard data'
));
});
testWidgets
(
...
...
@@ -1548,7 +1545,7 @@ void main() {
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
controller
.
selection
,
const
TextSelection
(
baseOffset:
0
,
extentOffset:
7
),
...
...
@@ -1588,7 +1585,7 @@ void main() {
const
TextSelection
.
collapsed
(
offset:
8
,
affinity:
TextAffinity
.
downstream
),
);
await
tester
.
tapAt
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// Second tap selects the word around the cursor.
expect
(
...
...
@@ -1624,7 +1621,7 @@ void main() {
final
TestGesture
gesture
=
await
tester
.
startGesture
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
));
// Hold the press.
await
tester
.
pump
AndSettle
(
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
)
);
expect
(
controller
.
selection
,
...
...
@@ -1763,7 +1760,7 @@ void main() {
final
TestGesture
gesture
=
await
tester
.
startGesture
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
));
// Hold the press.
await
tester
.
pump
AndSettle
(
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
)
);
// The obscured text is treated as one word, should select all
expect
(
...
...
@@ -1849,7 +1846,7 @@ void main() {
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
CupertinoTextField
));
await
tester
.
longPressAt
(
textfieldStart
+
const
Offset
(
50.0
,
5.0
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// Collapsed cursor for iOS long press.
expect
(
...
...
@@ -1949,7 +1946,7 @@ void main() {
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
await
gesture
.
up
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// The selection isn't affected by the gesture lift.
expect
(
...
...
@@ -2024,7 +2021,7 @@ void main() {
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
await
gesture
.
up
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// The selection isn't affected by the gesture lift.
expect
(
...
...
@@ -2079,7 +2076,7 @@ void main() {
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
await
tester
.
longPressAt
(
textfieldStart
+
const
Offset
(
100.0
,
5.0
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// Plain collapsed selection at the exact tap position.
expect
(
...
...
@@ -2121,7 +2118,7 @@ void main() {
const
TextSelection
.
collapsed
(
offset:
8
,
affinity:
TextAffinity
.
downstream
),
);
await
tester
.
tapAt
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// Double tap selection.
expect
(
...
...
@@ -2158,7 +2155,7 @@ void main() {
const
TextSelection
.
collapsed
(
offset:
7
,
affinity:
TextAffinity
.
upstream
),
);
await
tester
.
tapAt
(
textfieldStart
+
const
Offset
(
50.0
,
5.0
));
await
tester
.
pump
AndSettle
(
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
)
);
expect
(
controller
.
selection
,
const
TextSelection
(
baseOffset:
0
,
extentOffset:
7
),
...
...
@@ -2174,7 +2171,7 @@ void main() {
const
TextSelection
.
collapsed
(
offset:
7
,
affinity:
TextAffinity
.
upstream
),
);
await
tester
.
tapAt
(
textfieldStart
+
const
Offset
(
100.0
,
5.0
));
await
tester
.
pump
AndSettle
(
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
)
);
expect
(
controller
.
selection
,
const
TextSelection
(
baseOffset:
0
,
extentOffset:
7
),
...
...
@@ -2189,7 +2186,7 @@ void main() {
const
TextSelection
.
collapsed
(
offset:
8
,
affinity:
TextAffinity
.
downstream
),
);
await
tester
.
tapAt
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
));
await
tester
.
pump
AndSettle
(
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
)
);
expect
(
controller
.
selection
,
const
TextSelection
(
baseOffset:
8
,
extentOffset:
12
),
...
...
@@ -2233,7 +2230,7 @@ void main() {
);
await
gesture
.
up
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// Shows toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
3
));
});
...
...
@@ -3845,7 +3842,7 @@ void main() {
// Long press shows the selection menu.
await
tester
.
longPressAt
(
textOffsetToPosition
(
tester
,
0
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'Paste'
),
findsOneWidget
);
},
);
...
...
packages/flutter/test/cupertino/text_selection_test.dart
View file @
32547dcc
...
...
@@ -8,26 +8,9 @@ import 'package:flutter/cupertino.dart';
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter/widgets.dart'
;
import
'../widgets/text.dart'
show
textOffsetToPosition
;
class
MockClipboard
{
Object
_clipboardData
=
<
String
,
dynamic
>{
'text'
:
null
,
};
Future
<
dynamic
>
handleMethodCall
(
MethodCall
methodCall
)
async
{
switch
(
methodCall
.
method
)
{
case
'Clipboard.getData'
:
return
_clipboardData
;
case
'Clipboard.setData'
:
_clipboardData
=
methodCall
.
arguments
;
break
;
}
}
}
class
_LongCupertinoLocalizationsDelegate
extends
LocalizationsDelegate
<
CupertinoLocalizations
>
{
const
_LongCupertinoLocalizationsDelegate
();
...
...
@@ -66,9 +49,6 @@ class _LongCupertinoLocalizations extends DefaultCupertinoLocalizations {
const
_LongCupertinoLocalizations
longLocalizations
=
_LongCupertinoLocalizations
();
void
main
(
)
{
TestWidgetsFlutterBinding
.
ensureInitialized
();
final
MockClipboard
mockClipboard
=
MockClipboard
();
SystemChannels
.
platform
.
setMockMethodCallHandler
(
mockClipboard
.
handleMethodCall
);
// Returns true iff the button is visually enabled.
bool
appearsEnabled
(
WidgetTester
tester
,
String
text
)
{
...
...
@@ -174,55 +154,6 @@ void main() {
});
});
testWidgets
(
'Paste only appears when clipboard has contents'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidget
(
CupertinoApp
(
home:
Column
(
children:
<
Widget
>[
CupertinoTextField
(
controller:
controller
,
),
],
),
),
);
// Make sure the clipboard is empty to start.
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
''
));
// Double tap to selet the first word.
const
int
index
=
4
;
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pumpAndSettle
();
// No Paste yet, because nothing has been copied.
expect
(
find
.
text
(
'Paste'
),
findsNothing
);
expect
(
find
.
text
(
'Copy'
),
findsOneWidget
);
expect
(
find
.
text
(
'Cut'
),
findsOneWidget
);
// Tap copy to add something to the clipboard and close the menu.
await
tester
.
tapAt
(
tester
.
getCenter
(
find
.
text
(
'Copy'
)));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Copy'
),
findsNothing
);
expect
(
find
.
text
(
'Cut'
),
findsNothing
);
// Double tap to show the menu again.
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pumpAndSettle
();
// Paste now shows.
expect
(
find
.
text
(
'Paste'
),
findsOneWidget
);
expect
(
find
.
text
(
'Copy'
),
findsOneWidget
);
expect
(
find
.
text
(
'Cut'
),
findsOneWidget
);
},
skip:
isBrowser
,
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
iOS
}));
group
(
'Text selection menu overflow (iOS)'
,
()
{
testWidgets
(
'All menu items show when they fit.'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
text:
'abc def ghi'
);
...
...
@@ -250,7 +181,7 @@ void main() {
// Long press on an empty space to show the selection menu.
await
tester
.
longPressAt
(
textOffsetToPosition
(
tester
,
4
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'Cut'
),
findsNothing
);
expect
(
find
.
text
(
'Copy'
),
findsNothing
);
expect
(
find
.
text
(
'Paste'
),
findsOneWidget
);
...
...
@@ -474,7 +405,7 @@ void main() {
// Long press on an empty space to show the selection menu, with only the
// paste button visible.
await
tester
.
longPressAt
(
textOffsetToPosition
(
tester
,
4
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
longLocalizations
.
cutButtonLabel
),
findsNothing
);
expect
(
find
.
text
(
longLocalizations
.
copyButtonLabel
),
findsNothing
);
expect
(
find
.
text
(
longLocalizations
.
pasteButtonLabel
),
findsOneWidget
);
...
...
packages/flutter/test/material/date_picker_test.dart
View file @
32547dcc
...
...
@@ -3,31 +3,12 @@
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../rendering/mock_canvas.dart'
;
import
'feedback_tester.dart'
;
class
MockClipboard
{
Object
_clipboardData
=
<
String
,
dynamic
>{
'text'
:
null
,
};
Future
<
dynamic
>
handleMethodCall
(
MethodCall
methodCall
)
async
{
switch
(
methodCall
.
method
)
{
case
'Clipboard.getData'
:
return
_clipboardData
;
case
'Clipboard.setData'
:
_clipboardData
=
methodCall
.
arguments
;
break
;
}
}
}
void
main
(
)
{
TestWidgetsFlutterBinding
.
ensureInitialized
();
final
MockClipboard
mockClipboard
=
MockClipboard
();
DateTime
firstDate
;
DateTime
lastDate
;
...
...
@@ -54,7 +35,7 @@ void main() {
return
tester
.
widget
<
TextField
>(
find
.
byType
(
TextField
));
}
setUp
(()
async
{
setUp
(()
{
firstDate
=
DateTime
(
2001
,
DateTime
.
january
,
1
);
lastDate
=
DateTime
(
2031
,
DateTime
.
december
,
31
);
initialDate
=
DateTime
(
2016
,
DateTime
.
january
,
15
);
...
...
@@ -70,15 +51,6 @@ void main() {
fieldHintText
=
null
;
fieldLabelText
=
null
;
helpText
=
null
;
// Fill the clipboard so that the PASTE option is available in the text
// selection menu.
SystemChannels
.
platform
.
setMockMethodCallHandler
(
mockClipboard
.
handleMethodCall
);
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
'Clipboard data'
));
});
tearDown
(()
{
SystemChannels
.
platform
.
setMockMethodCallHandler
(
null
);
});
Future
<
void
>
prepareDatePicker
(
WidgetTester
tester
,
Future
<
void
>
callback
(
Future
<
DateTime
>
date
))
async
{
...
...
@@ -1103,6 +1075,7 @@ void main() {
semantics
.
dispose
();
});
});
group
(
'Screen configurations'
,
()
{
...
...
packages/flutter/test/material/search_test.dart
View file @
32547dcc
...
...
@@ -9,37 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
import
'../widgets/semantics_tester.dart'
;
class
MockClipboard
{
Object
_clipboardData
=
<
String
,
dynamic
>{
'text'
:
null
,
};
Future
<
dynamic
>
handleMethodCall
(
MethodCall
methodCall
)
async
{
switch
(
methodCall
.
method
)
{
case
'Clipboard.getData'
:
return
_clipboardData
;
case
'Clipboard.setData'
:
_clipboardData
=
methodCall
.
arguments
;
break
;
}
}
}
void
main
(
)
{
TestWidgetsFlutterBinding
.
ensureInitialized
();
final
MockClipboard
mockClipboard
=
MockClipboard
();
setUp
(()
async
{
// Fill the clipboard so that the PASTE option is available in the text
// selection menu.
SystemChannels
.
platform
.
setMockMethodCallHandler
(
mockClipboard
.
handleMethodCall
);
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
'Clipboard data'
));
});
tearDown
(()
{
SystemChannels
.
platform
.
setMockMethodCallHandler
(
null
);
});
testWidgets
(
'Can open and close search'
,
(
WidgetTester
tester
)
async
{
final
_TestSearchDelegate
delegate
=
_TestSearchDelegate
();
final
List
<
String
>
selectedResults
=
<
String
>[];
...
...
packages/flutter/test/material/text_field_test.dart
View file @
32547dcc
This diff is collapsed.
Click to expand it.
packages/flutter/test/material/text_selection_test.dart
View file @
32547dcc
...
...
@@ -5,35 +5,10 @@
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter/widgets.dart'
;
import
'../widgets/text.dart'
show
findRenderEditable
,
globalize
,
textOffsetToPosition
;
class
MockClipboard
{
Object
_clipboardData
=
<
String
,
dynamic
>{
'text'
:
null
,
};
Future
<
dynamic
>
handleMethodCall
(
MethodCall
methodCall
)
async
{
switch
(
methodCall
.
method
)
{
case
'Clipboard.getData'
:
return
_clipboardData
;
case
'Clipboard.setData'
:
_clipboardData
=
methodCall
.
arguments
;
break
;
}
}
}
void
main
(
)
{
TestWidgetsFlutterBinding
.
ensureInitialized
();
final
MockClipboard
mockClipboard
=
MockClipboard
();
SystemChannels
.
platform
.
setMockMethodCallHandler
(
mockClipboard
.
handleMethodCall
);
setUp
(()
async
{
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
'clipboard data'
));
});
group
(
'canSelectAll'
,
()
{
Widget
createEditableText
({
Key
key
,
...
...
@@ -129,7 +104,7 @@ void main() {
expect
(
endpoints
.
length
,
1
);
final
Offset
handlePos
=
endpoints
[
0
].
point
+
const
Offset
(
0.0
,
1.0
);
await
tester
.
tapAt
(
handlePos
,
pointer:
7
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'CUT'
),
findsNothing
);
expect
(
find
.
text
(
'COPY'
),
findsNothing
);
expect
(
find
.
text
(
'PASTE'
),
findsOneWidget
);
...
...
@@ -260,7 +235,7 @@ void main() {
// Long press to show the menu.
final
Offset
textOffset
=
textOffsetToPosition
(
tester
,
1
);
await
tester
.
longPressAt
(
textOffset
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// The last two buttons are missing, and a more button is shown.
expect
(
find
.
text
(
'CUT'
),
findsOneWidget
);
...
...
@@ -326,7 +301,7 @@ void main() {
// Long press to show the menu.
final
Offset
textOffset
=
textOffsetToPosition
(
tester
,
1
);
await
tester
.
longPressAt
(
textOffset
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// The last button is missing, and a more button is shown.
expect
(
find
.
text
(
'CUT'
),
findsOneWidget
);
...
...
@@ -438,7 +413,7 @@ void main() {
// Long press to show the menu.
await
tester
.
longPressAt
(
textOffsetToPosition
(
tester
,
1
));
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
// The last button is missing, and a more button is shown.
expect
(
find
.
text
(
'CUT'
),
findsOneWidget
);
...
...
@@ -513,7 +488,7 @@ void main() {
expect
(
endpoints
.
length
,
1
);
final
Offset
handlePos
=
endpoints
[
0
].
point
+
const
Offset
(
0.0
,
1.0
);
await
tester
.
tapAt
(
handlePos
,
pointer:
7
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'CUT'
),
findsNothing
);
expect
(
find
.
text
(
'COPY'
),
findsNothing
);
expect
(
find
.
text
(
'PASTE'
),
findsOneWidget
);
...
...
@@ -581,58 +556,4 @@ void main() {
);
});
});
testWidgets
(
'Paste only appears when clipboard has contents'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Material
(
child:
Column
(
children:
<
Widget
>[
TextField
(
controller:
controller
,
),
],
),
),
),
);
// Make sure the clipboard is empty to start.
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
''
));
// Double tap to selet the first word.
const
int
index
=
4
;
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pumpAndSettle
();
// No Paste yet, because nothing has been copied.
expect
(
find
.
text
(
'PASTE'
),
findsNothing
);
expect
(
find
.
text
(
'COPY'
),
findsOneWidget
);
expect
(
find
.
text
(
'CUT'
),
findsOneWidget
);
expect
(
find
.
text
(
'SELECT ALL'
),
findsOneWidget
);
// Tap copy to add something to the clipboard and close the menu.
await
tester
.
tapAt
(
tester
.
getCenter
(
find
.
text
(
'COPY'
)));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'COPY'
),
findsNothing
);
expect
(
find
.
text
(
'CUT'
),
findsNothing
);
expect
(
find
.
text
(
'SELECT ALL'
),
findsNothing
);
// Double tap to show the menu again.
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
50
));
await
tester
.
tapAt
(
textOffsetToPosition
(
tester
,
index
));
await
tester
.
pumpAndSettle
();
// Paste now shows.
expect
(
find
.
text
(
'COPY'
),
findsOneWidget
);
expect
(
find
.
text
(
'CUT'
),
findsOneWidget
);
expect
(
find
.
text
(
'PASTE'
),
findsOneWidget
);
expect
(
find
.
text
(
'SELECT ALL'
),
findsOneWidget
);
},
skip:
isBrowser
);
}
packages/flutter/test/widgets/editable_text_cursor_test.dart
View file @
32547dcc
...
...
@@ -19,12 +19,6 @@ const TextStyle textStyle = TextStyle();
const
Color
cursorColor
=
Color
.
fromARGB
(
0xFF
,
0xFF
,
0x00
,
0x00
);
void
main
(
)
{
setUp
(()
async
{
// Fill the clipboard so that the PASTE option is available in the text
// selection menu.
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
'Clipboard data'
));
});
testWidgets
(
'cursor has expected width and radius'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
MediaQuery
(
data:
const
MediaQueryData
(
devicePixelRatio:
1.0
),
...
...
@@ -45,6 +39,7 @@ void main() {
expect
(
editableText
.
cursorRadius
.
x
,
2.0
);
});
testWidgets
(
'cursor layout has correct width'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
EditableTextState
>
editableTextKey
=
GlobalKey
<
EditableTextState
>();
...
...
@@ -137,7 +132,7 @@ void main() {
final
Finder
textFinder
=
find
.
byKey
(
editableTextKey
);
await
tester
.
longPress
(
textFinder
);
tester
.
state
<
EditableTextState
>(
textFinder
).
showToolbar
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
await
tester
.
tap
(
find
.
text
(
'PASTE'
));
await
tester
.
pump
();
...
...
packages/flutter/test/widgets/editable_text_test.dart
View file @
32547dcc
...
...
@@ -48,12 +48,9 @@ void main() {
final
MockClipboard
mockClipboard
=
MockClipboard
();
SystemChannels
.
platform
.
setMockMethodCallHandler
(
mockClipboard
.
handleMethodCall
);
setUp
(()
async
{
setUp
(()
{
debugResetSemanticsIdCounter
();
controller
=
TextEditingController
();
// Fill the clipboard so that the PASTE option is available in the text
// selection menu.
await
Clipboard
.
setData
(
const
ClipboardData
(
text:
'Clipboard data'
));
});
tearDown
(()
{
...
...
@@ -964,7 +961,7 @@ void main() {
// Can't show the toolbar when there's no focus.
expect
(
state
.
showToolbar
(),
false
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'PASTE'
),
findsNothing
);
// Can show the toolbar when focused even though there's no text.
...
...
@@ -974,7 +971,7 @@ void main() {
);
await
tester
.
pump
();
expect
(
state
.
showToolbar
(),
true
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'PASTE'
),
findsOneWidget
);
// Hide the menu again.
...
...
@@ -986,7 +983,7 @@ void main() {
controller
.
text
=
'blah'
;
await
tester
.
pump
();
expect
(
state
.
showToolbar
(),
true
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'PASTE'
),
findsOneWidget
);
},
skip:
isBrowser
);
...
...
@@ -1026,7 +1023,7 @@ void main() {
// Should be able to show the toolbar.
expect
(
state
.
showToolbar
(),
true
);
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
text
(
'PASTE'
),
findsOneWidget
);
});
...
...
@@ -1195,7 +1192,7 @@ void main() {
final
Finder
textFinder
=
find
.
byType
(
EditableText
);
await
tester
.
longPress
(
textFinder
);
tester
.
state
<
EditableTextState
>(
textFinder
).
showToolbar
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
await
tester
.
tap
(
find
.
text
(
'PASTE'
));
await
tester
.
pump
();
...
...
@@ -2415,13 +2412,12 @@ void main() {
controls
=
MockTextSelectionControls
();
when
(
controls
.
buildHandle
(
any
,
any
,
any
)).
thenReturn
(
Container
());
when
(
controls
.
buildToolbar
(
any
,
any
,
any
,
any
,
any
,
any
,
any
))
when
(
controls
.
buildToolbar
(
any
,
any
,
any
,
any
,
any
,
any
))
.
thenReturn
(
Container
());
});
testWidgets
(
'are exposed'
,
(
WidgetTester
tester
)
async
{
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
addTearDown
(
semantics
.
dispose
);
when
(
controls
.
canCopy
(
any
)).
thenReturn
(
false
);
when
(
controls
.
canCut
(
any
)).
thenReturn
(
false
);
...
...
@@ -2461,7 +2457,6 @@ void main() {
when
(
controls
.
canCopy
(
any
)).
thenReturn
(
false
);
when
(
controls
.
canPaste
(
any
)).
thenReturn
(
true
);
await
_buildApp
(
controls
,
tester
);
await
tester
.
pumpAndSettle
();
expect
(
semantics
,
includesNodeWith
(
...
...
@@ -2509,6 +2504,8 @@ void main() {
],
),
);
semantics
.
dispose
();
});
testWidgets
(
'can copy/cut/paste with a11y'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -2567,7 +2564,7 @@ void main() {
);
owner
.
performAction
(
expectedNodeId
,
SemanticsAction
.
copy
);
verify
(
controls
.
handleCopy
(
any
,
any
)).
called
(
1
);
verify
(
controls
.
handleCopy
(
any
)).
called
(
1
);
owner
.
performAction
(
expectedNodeId
,
SemanticsAction
.
cut
);
verify
(
controls
.
handleCut
(
any
)).
called
(
1
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment