未验证 提交 81e010f7 编写于 作者: Y Yegor 提交者: GitHub

last flutter web sync: cc38319841 (#11732)

* last flutter web sync: cc38319841

* revert text.dart changes

* revert paragraph.dart

* link to issue
上级 e620012c
......@@ -13,6 +13,9 @@ enum BrowserEngine {
/// The engine that powers Safari.
webkit,
/// The engine that powers Firefox.
firefox,
/// We were unable to detect the current browser engine.
unknown,
}
......@@ -31,6 +34,10 @@ BrowserEngine _detectBrowserEngine() {
return BrowserEngine.blink;
} else if (vendor == 'Apple Computer, Inc.') {
return BrowserEngine.webkit;
} else if (vendor == '') {
// An empty string means firefox:
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/vendor
return BrowserEngine.firefox;
}
// Assume blink otherwise, but issue a warning.
......
......@@ -254,12 +254,20 @@ flt-semantics input[type=range] {
' -webkit-appearance: none;'
'}',
sheet.cssRules.length);
}
if (browserEngine == BrowserEngine.firefox) {
sheet.insertRule(
'input::-moz-selection {'
' background-color: transparent;'
'}',
sheet.cssRules.length);
} else {
// On iOS, the invisible semantic text field has a visible cursor and
// selection highlight. The following 2 CSS rules force everything to be
// transparent.
sheet.insertRule(
'flt-semantics ::selection {'
'input::selection {'
' background-color: transparent;'
'}',
sheet.cssRules.length);
......
......@@ -59,15 +59,20 @@ void _createPlatformView(
final Map<dynamic, dynamic> args = methodCall.arguments;
final int id = args['id'];
final String viewType = args['viewType'];
const MethodCodec codec = StandardMethodCodec();
// TODO(het): Use 'direction', 'width', and 'height'.
if (!platformViewRegistry._registeredFactories.containsKey(viewType)) {
// TODO(het): Do we have a way of nicely reporting errors during platform
// channel calls?
callback(null);
callback(codec.encodeErrorEnvelope(
code: 'Unregistered factory',
message: "No factory registered for viewtype '$viewType'",
));
return;
}
// TODO(het): Use creation parameters.
final html.Element element =
platformViewRegistry._registeredFactories[viewType](id);
platformViewRegistry._createdViews[id] = element;
callback(codec.encodeSuccessEnvelope(null));
}
......@@ -62,6 +62,7 @@ class TextField extends RoleManager {
switch (browserEngine) {
case BrowserEngine.blink:
case BrowserEngine.firefox:
case BrowserEngine.unknown:
_initializeForBlink();
break;
......
......@@ -293,7 +293,7 @@ class EngineParagraph implements ui.Paragraph {
@override
List<ui.LineMetrics> computeLineMetrics() {
// TODO(flutter_web): Implement this.
// TODO(flutter_web): https://github.com/flutter/flutter/issues/39537
return null;
}
}
......@@ -1059,7 +1059,7 @@ void _applyParagraphStyleToElement({
cssStyle.lineHeight = '${style._lineHeight}';
}
if (style._textDirection != null) {
cssStyle.direction = _textDirectionToCssValue(style._textDirection);
cssStyle.direction = _textDirectionToCss(style._textDirection);
}
if (style._fontSize != null) {
cssStyle.fontSize = '${style._fontSize.floor()}px';
......@@ -1083,7 +1083,7 @@ void _applyParagraphStyleToElement({
cssStyle.lineHeight = '${style._lineHeight}';
}
if (style._textDirection != previousStyle._textDirection) {
cssStyle.direction = _textDirectionToCssValue(style._textDirection);
cssStyle.direction = _textDirectionToCss(style._textDirection);
}
if (style._fontSize != previousStyle._fontSize) {
cssStyle.fontSize =
......@@ -1272,10 +1272,28 @@ String _decorationStyleToCssString(ui.TextDecorationStyle decorationStyle) {
/// ```css
/// direction: rtl;
/// ```
String _textDirectionToCssValue(ui.TextDirection textDirection) {
return textDirection == ui.TextDirection.ltr
? null // it's the default
: 'rtl';
String _textDirectionToCss(ui.TextDirection textDirection) {
if (textDirection == null) {
return null;
}
return textDirectionIndexToCss(textDirection.index);
}
String textDirectionIndexToCss(int textDirectionIndex) {
switch (textDirectionIndex) {
case 0:
return 'rtl';
case 1:
return null; // ltr is the default
}
assert(() {
throw AssertionError(
'Failed to convert text direction $textDirectionIndex to CSS',
);
}());
return null;
}
/// Converts [align] to its corresponding CSS value.
......
......@@ -14,30 +14,31 @@ void _emptyCallback(dynamic _) {}
///
/// They are assigned once during the creation of the dom element.
void _setStaticStyleAttributes(html.HtmlElement domElement) {
domElement.style
final html.CssStyleDeclaration elementStyle = domElement.style;
elementStyle
..whiteSpace = 'pre'
..alignContent = 'center'
..position = 'absolute'
..top = '0'
..left = '0'
..padding = '0'
..opacity = '1';
..opacity = '1'
..color = 'transparent'
..backgroundColor = 'transparent'
..background = 'transparent'
..outline = 'none'
..border = 'none'
..resize = 'none'
..textShadow = 'transparent'
..transformOrigin = '0 0 0';
/// This property makes the input's blinking cursor transparent.
elementStyle.setProperty('caret-color', 'transparent');
if (_debugVisibleTextEditing) {
domElement.style
elementStyle
..color = 'purple'
..backgroundColor = 'pink';
} else {
domElement.style
..color = 'transparent'
..backgroundColor = 'transparent'
..background = 'transparent'
..border = 'none'
..resize = 'none'
..cursor = 'none'
..textShadow = 'transparent'
..outline = 'none';
/// This property makes the cursor transparent in mobile browsers where
/// cursor = 'none' does not work.
domElement.style.setProperty('caret-color', 'transparent');
..outline = '1px solid purple';
}
}
......@@ -479,6 +480,7 @@ class PersistentTextEditingElement extends TextEditingElement {
}) : _onDomElementSwap = onDomElementSwap,
super(owner) {
// Make sure the dom element is of a type that we support for text editing.
// TODO(yjbanov): move into initializer list when https://github.com/dart-lang/sdk/issues/37881 is fixed.
assert(_getTypeFromElement(domElement) != null);
this.domElement = domElement;
}
......@@ -611,7 +613,7 @@ class HybridTextEditing {
}
break;
case 'TextInput.setEditingLocationSize':
case 'TextInput.setEditableSizeAndTransform':
_setLocation(call.arguments);
break;
......@@ -656,41 +658,41 @@ class HybridTextEditing {
assert(style.containsKey('fontSize'));
assert(style.containsKey('fontFamily'));
assert(style.containsKey('textAlignIndex'));
assert(style.containsKey('textDirectionIndex'));
final int textAlignIndex = style.remove('textAlignIndex');
final int textAlignIndex = style['textAlignIndex'];
final int textDirectionIndex = style['textDirectionIndex'];
/// Converts integer value coming as fontWeightValue from TextInput.setStyle
/// Converts integer value coming as fontWeightIndex from TextInput.setStyle
/// to its CSS equivalent value.
/// Converts index of TextAlign to enum value.
_editingStyle = _EditingStyle(
textDirection: style.containsKey('textDirection')
? style.remove('textDirection')
: ui.TextDirection.ltr,
fontSize: style.remove('fontSize'),
textDirection: ui.TextDirection.values[textDirectionIndex],
fontSize: style['fontSize'],
textAlign: ui.TextAlign.values[textAlignIndex],
fontFamily: style.remove('fontFamily'),
fontWeight: fontWeightIndexToCss(
fontWeightIndex: style.remove('fontWeightValue')),
fontFamily: style['fontFamily'],
fontWeight:
fontWeightIndexToCss(fontWeightIndex: style['fontWeightIndex']),
);
}
/// Location of the editable text on the page as a rectangle.
// TODO(flutter_web): investigate if transform matrix can be used instead of
// a rectangle.
_EditingLocationAndSize _editingLocationAndSize;
_EditingLocationAndSize get editingLocationAndSize => _editingLocationAndSize;
/// Size and transform of the editable text on the page.
_EditableSizeAndTransform _editingLocationAndSize;
_EditableSizeAndTransform get editingLocationAndSize =>
_editingLocationAndSize;
void _setLocation(Map<String, dynamic> editingLocationAndSize) {
assert(editingLocationAndSize.containsKey('top'));
assert(editingLocationAndSize.containsKey('left'));
assert(editingLocationAndSize.containsKey('width'));
assert(editingLocationAndSize.containsKey('height'));
_editingLocationAndSize = _EditingLocationAndSize(
top: editingLocationAndSize.remove('top'),
left: editingLocationAndSize.remove('left'),
width: editingLocationAndSize.remove('width'),
height: editingLocationAndSize.remove('height'));
assert(editingLocationAndSize.containsKey('transform'));
final List<double> transformList =
List<double>.from(editingLocationAndSize['transform']);
_editingLocationAndSize = _EditableSizeAndTransform(
width: editingLocationAndSize['width'],
height: editingLocationAndSize['height'],
transform: Float64List.fromList(transformList),
);
if (editingElement.domElement != null) {
_setDynamicStyleAttributes(editingElement.domElement);
......@@ -714,7 +716,7 @@ class HybridTextEditing {
/// element.
///
/// They are changed depending on the messages coming from method calls:
/// "TextInput.setStyle", "TextInput.setEditingLocationSize".
/// "TextInput.setStyle", "TextInput.setEditableSizeAndTransform".
void _setDynamicStyleAttributes(html.HtmlElement domElement) {
if (_editingLocationAndSize != null &&
!(browserEngine == BrowserEngine.webkit &&
......@@ -731,18 +733,14 @@ class HybridTextEditing {
/// Users can interact with the element and use the functionalities of the
/// right-click menu. Such as copy,paste, cut, select, translate...
void setStyle(html.HtmlElement domElement) {
final String transformCss =
float64ListToCssTransform(_editingLocationAndSize.transform);
domElement.style
..top = '${_editingLocationAndSize.top}px'
..left = '${_editingLocationAndSize.left}px'
..width = '${_editingLocationAndSize.width}px'
..height = '${_editingLocationAndSize.height}px';
if (_debugVisibleTextEditing) {
domElement.style.font = '24px sans-serif';
} else {
domElement.style
..textAlign = _editingStyle.align
..font = font();
}
..height = '${_editingLocationAndSize.height}px'
..textAlign = _editingStyle.align
..font = font()
..transform = transformCss;
}
html.InputElement createInputElement() {
......@@ -785,19 +783,18 @@ class _EditingStyle {
/// Information on the location and size of the editing element.
///
/// This information is received via "TextInput.setEditingLocationSize"
/// This information is received via "TextInput.setEditableSizeAndTransform"
/// message. Framework currently sends this information on paint.
// TODO(flutter_web): send the location during the scroll for more frequent
// updates from the framework.
class _EditingLocationAndSize {
_EditingLocationAndSize(
{@required this.top,
@required this.left,
@required this.width,
@required this.height});
final double top;
final double left;
class _EditableSizeAndTransform {
_EditableSizeAndTransform({
@required this.width,
@required this.height,
@required this.transform,
});
final double width;
final double height;
final Float64List transform;
}
......@@ -471,21 +471,22 @@ void main() {
'TextInput.setClient', <dynamic>[123, flutterSinglelineConfig]);
textEditing.handleTextInput(codec.encodeMethodCall(setClient));
const MethodCall setLocationSize =
MethodCall('TextInput.setEditingLocationSize', <String, dynamic>{
'top': 0,
'left': 0,
final MethodCall setSizeAndTransform =
MethodCall('TextInput.setEditableSizeAndTransform', <String, dynamic>{
'width': 150,
'height': 50,
'transform':
Matrix4.translationValues(10.0, 20.0, 30.0).storage.toList()
});
textEditing.handleTextInput(codec.encodeMethodCall(setLocationSize));
textEditing.handleTextInput(codec.encodeMethodCall(setSizeAndTransform));
const MethodCall setStyle =
MethodCall('TextInput.setStyle', <String, dynamic>{
'fontSize': 12,
'fontFamily': 'sans-serif',
'textAlignIndex': 4,
'fontWeightValue': 4,
'fontWeightIndex': 4,
'textDirectionIndex': 1,
});
textEditing.handleTextInput(codec.encodeMethodCall(setStyle));
......@@ -500,14 +501,17 @@ void main() {
const MethodCall show = MethodCall('TextInput.show');
textEditing.handleTextInput(codec.encodeMethodCall(show));
checkInputEditingState(
textEditing.editingElement.domElement, 'abcd', 2, 3);
final HtmlElement domElement = textEditing.editingElement.domElement;
checkInputEditingState(domElement, 'abcd', 2, 3);
// Check if the location and styling is correct.
expect(
textEditing.editingElement.domElement.getBoundingClientRect(),
Rectangle<double>.fromPoints(
const Point<double>(0.0, 0.0), const Point<double>(150.0, 50.0)));
domElement.getBoundingClientRect(),
Rectangle<double>.fromPoints(const Point<double>(10.0, 20.0),
const Point<double>(160.0, 70.0)));
expect(domElement.style.transform,
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 20, 30, 1)');
expect(textEditing.editingElement.domElement.style.font,
'500 12px sans-serif');
......
......@@ -16,6 +16,7 @@ void main() {
// Run the unit test without emulating Flutter tester environment.
ui.debugEmulateFlutterTesterEnvironment = false;
// TODO(yjbanov): https://github.com/flutter/flutter/issues/39159
document.title = '';
expect(document.title, '');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册