Unverified Commit 69788322 authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

migrate some cupertino files to nullsafety (#65880)

parent 10a66b19
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show Color, Brightness; import 'dart:ui' show Color, Brightness;
import '../../foundation.dart'; import '../../foundation.dart';
...@@ -683,15 +681,15 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -683,15 +681,15 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
/// ///
/// All the colors must not be null. /// All the colors must not be null.
const CupertinoDynamicColor({ const CupertinoDynamicColor({
String debugLabel, String? debugLabel,
@required Color color, required Color color,
@required Color darkColor, required Color darkColor,
@required Color highContrastColor, required Color highContrastColor,
@required Color darkHighContrastColor, required Color darkHighContrastColor,
@required Color elevatedColor, required Color elevatedColor,
@required Color darkElevatedColor, required Color darkElevatedColor,
@required Color highContrastElevatedColor, required Color highContrastElevatedColor,
@required Color darkHighContrastElevatedColor, required Color darkHighContrastElevatedColor,
}) : this._( }) : this._(
color, color,
color, color,
...@@ -713,11 +711,11 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -713,11 +711,11 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
/// ///
/// All the colors must not be null. /// All the colors must not be null.
const CupertinoDynamicColor.withBrightnessAndContrast({ const CupertinoDynamicColor.withBrightnessAndContrast({
String debugLabel, String? debugLabel,
@required Color color, required Color color,
@required Color darkColor, required Color darkColor,
@required Color highContrastColor, required Color highContrastColor,
@required Color darkHighContrastColor, required Color darkHighContrastColor,
}) : this( }) : this(
debugLabel: debugLabel, debugLabel: debugLabel,
color: color, color: color,
...@@ -736,9 +734,9 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -736,9 +734,9 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
/// ///
/// All the colors must not be null. /// All the colors must not be null.
const CupertinoDynamicColor.withBrightness({ const CupertinoDynamicColor.withBrightness({
String debugLabel, String? debugLabel,
@required Color color, required Color color,
@required Color darkColor, required Color darkColor,
}) : this( }) : this(
debugLabel: debugLabel, debugLabel: debugLabel,
color: color, color: color,
...@@ -786,9 +784,9 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -786,9 +784,9 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
@override @override
int get value => _effectiveColor.value; int get value => _effectiveColor.value;
final String _debugLabel; final String? _debugLabel;
final Element _debugResolveContext; final Element? _debugResolveContext;
/// The color to use when the [BuildContext] implies a combination of light mode, /// The color to use when the [BuildContext] implies a combination of light mode,
/// normal contrast, and base interface elevation. /// normal contrast, and base interface elevation.
...@@ -887,7 +885,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -887,7 +885,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
/// value will be used ([Brightness.light] platform brightness, normal contrast, /// value will be used ([Brightness.light] platform brightness, normal contrast,
/// [CupertinoUserInterfaceLevelData.base] elevation level), unless [nullOk] is /// [CupertinoUserInterfaceLevelData.base] elevation level), unless [nullOk] is
/// set to false, in which case an exception will be thrown. /// set to false, in which case an exception will be thrown.
static Color resolve(Color resolvable, BuildContext context, { bool nullOk = true }) { static Color? resolve(Color? resolvable, BuildContext context, { bool nullOk = true }) {
if (resolvable == null) if (resolvable == null)
return null; return null;
assert(context != null); assert(context != null);
...@@ -981,7 +979,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -981,7 +979,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
} }
} }
Element _debugContext; Element? _debugContext;
assert(() { assert(() {
_debugContext = context as Element; _debugContext = context as Element;
return true; return true;
...@@ -1058,7 +1056,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -1058,7 +1056,7 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
if (_debugLabel != null) if (_debugLabel != null)
properties.add(MessageProperty('debugLabel', _debugLabel)); properties.add(MessageProperty('debugLabel', _debugLabel!));
properties.add(createCupertinoColorProperty('color', color)); properties.add(createCupertinoColorProperty('color', color));
if (_isPlatformBrightnessDependent) if (_isPlatformBrightnessDependent)
properties.add(createCupertinoColorProperty('darkColor', darkColor)); properties.add(createCupertinoColorProperty('darkColor', darkColor));
...@@ -1085,11 +1083,11 @@ class CupertinoDynamicColor extends Color with Diagnosticable { ...@@ -1085,11 +1083,11 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
/// The [showName], [style], and [level] arguments must not be null. /// The [showName], [style], and [level] arguments must not be null.
DiagnosticsProperty<Color> createCupertinoColorProperty( DiagnosticsProperty<Color> createCupertinoColorProperty(
String name, String name,
Color value, { Color? value, {
bool showName = true, bool showName = true,
Object defaultValue = kNoDefaultValue, Object? defaultValue = kNoDefaultValue,
DiagnosticsTreeStyle style = DiagnosticsTreeStyle.singleLine, DiagnosticsTreeStyle style = DiagnosticsTreeStyle.singleLine,
DiagnosticLevel level = DiagnosticLevel.info, DiagnosticLevel level = DiagnosticLevel.info,
}) { }) {
if (value is CupertinoDynamicColor) { if (value is CupertinoDynamicColor) {
return DiagnosticsProperty<CupertinoDynamicColor>( return DiagnosticsProperty<CupertinoDynamicColor>(
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
...@@ -16,22 +14,22 @@ class CupertinoIconThemeData extends IconThemeData with Diagnosticable { ...@@ -16,22 +14,22 @@ class CupertinoIconThemeData extends IconThemeData with Diagnosticable {
/// The opacity applies to both explicit and default icon colors. The value /// The opacity applies to both explicit and default icon colors. The value
/// is clamped between 0.0 and 1.0. /// is clamped between 0.0 and 1.0.
const CupertinoIconThemeData({ const CupertinoIconThemeData({
Color color, Color? color,
double opacity, double? opacity,
double size double? size,
}) : super(color: color, opacity: opacity, size: size); }) : super(color: color, opacity: opacity, size: size);
/// Called by [IconTheme.of] to resolve [color] against the given [BuildContext]. /// Called by [IconTheme.of] to resolve [color] against the given [BuildContext].
@override @override
IconThemeData resolve(BuildContext context) { IconThemeData resolve(BuildContext context) {
final Color resolvedColor = CupertinoDynamicColor.resolve(color, context); final Color? resolvedColor = CupertinoDynamicColor.resolve(color, context);
return resolvedColor == color ? this : copyWith(color: resolvedColor); return resolvedColor == color ? this : copyWith(color: resolvedColor);
} }
/// Creates a copy of this icon theme but with the given fields replaced with /// Creates a copy of this icon theme but with the given fields replaced with
/// the new values. /// the new values.
@override @override
CupertinoIconThemeData copyWith({ Color color, double opacity, double size }) { CupertinoIconThemeData copyWith({ Color? color, double? opacity, double? size }) {
return CupertinoIconThemeData( return CupertinoIconThemeData(
color: color ?? this.color, color: color ?? this.color,
opacity: opacity ?? this.opacity, opacity: opacity ?? this.opacity,
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import '../widgets/framework.dart'; import '../widgets/framework.dart';
...@@ -41,9 +39,9 @@ class CupertinoUserInterfaceLevel extends InheritedWidget { ...@@ -41,9 +39,9 @@ class CupertinoUserInterfaceLevel extends InheritedWidget {
/// Creates a [CupertinoUserInterfaceLevel] to change descendant Cupertino widget's /// Creates a [CupertinoUserInterfaceLevel] to change descendant Cupertino widget's
/// visual level. /// visual level.
const CupertinoUserInterfaceLevel({ const CupertinoUserInterfaceLevel({
Key key, Key? key,
@required CupertinoUserInterfaceLevelData data, required CupertinoUserInterfaceLevelData data,
Widget child, required Widget child,
}) : assert(data != null), }) : assert(data != null),
_data = data, _data = data,
super(key: key, child: child); super(key: key, child: child);
...@@ -59,10 +57,10 @@ class CupertinoUserInterfaceLevel extends InheritedWidget { ...@@ -59,10 +57,10 @@ class CupertinoUserInterfaceLevel extends InheritedWidget {
/// You can use this function to query the user interface elevation level within /// You can use this function to query the user interface elevation level within
/// the given [BuildContext]. When that information changes, your widget will /// the given [BuildContext]. When that information changes, your widget will
/// be scheduled to be rebuilt, keeping your widget up-to-date. /// be scheduled to be rebuilt, keeping your widget up-to-date.
static CupertinoUserInterfaceLevelData of(BuildContext context, { bool nullOk = false }) { static CupertinoUserInterfaceLevelData? of(BuildContext context, { bool nullOk = false }) {
assert(context != null); assert(context != null);
assert(nullOk != null); assert(nullOk != null);
final CupertinoUserInterfaceLevel query = context.dependOnInheritedWidgetOfExactType<CupertinoUserInterfaceLevel>(); final CupertinoUserInterfaceLevel? query = context.dependOnInheritedWidgetOfExactType<CupertinoUserInterfaceLevel>();
if (query != null) if (query != null)
return query._data; return query._data;
if (nullOk) if (nullOk)
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show Brightness; import 'package:flutter/services.dart' show Brightness;
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -98,12 +96,12 @@ const TextStyle _kDefaultDateTimePickerTextStyle = TextStyle( ...@@ -98,12 +96,12 @@ const TextStyle _kDefaultDateTimePickerTextStyle = TextStyle(
color: CupertinoColors.label, color: CupertinoColors.label,
); );
TextStyle _resolveTextStyle(TextStyle style, BuildContext context, bool nullOk) { TextStyle? _resolveTextStyle(TextStyle? style, BuildContext context, bool nullOk) {
// This does not resolve the shadow color, foreground, background, etc. // This does not resolve the shadow color, foreground, background, etc.
return style?.copyWith( return style?.copyWith(
color: CupertinoDynamicColor.resolve(style?.color, context, nullOk: nullOk), color: CupertinoDynamicColor.resolve(style.color, context, nullOk: nullOk),
backgroundColor: CupertinoDynamicColor.resolve(style?.backgroundColor, context, nullOk: nullOk), backgroundColor: CupertinoDynamicColor.resolve(style.backgroundColor, context, nullOk: nullOk),
decorationColor: CupertinoDynamicColor.resolve(style?.decorationColor, context, nullOk: nullOk), decorationColor: CupertinoDynamicColor.resolve(style.decorationColor, context, nullOk: nullOk),
); );
} }
...@@ -126,15 +124,15 @@ class CupertinoTextThemeData with Diagnosticable { ...@@ -126,15 +124,15 @@ class CupertinoTextThemeData with Diagnosticable {
'This argument no longer does anything. You can remove it. ' 'This argument no longer does anything. You can remove it. '
'This feature was deprecated after v1.10.14.' 'This feature was deprecated after v1.10.14.'
) )
Brightness brightness, Brightness? brightness,
TextStyle textStyle, TextStyle? textStyle,
TextStyle actionTextStyle, TextStyle? actionTextStyle,
TextStyle tabLabelTextStyle, TextStyle? tabLabelTextStyle,
TextStyle navTitleTextStyle, TextStyle? navTitleTextStyle,
TextStyle navLargeTitleTextStyle, TextStyle? navLargeTitleTextStyle,
TextStyle navActionTextStyle, TextStyle? navActionTextStyle,
TextStyle pickerTextStyle, TextStyle? pickerTextStyle,
TextStyle dateTimePickerTextStyle, TextStyle? dateTimePickerTextStyle,
}) : this._raw( }) : this._raw(
const _TextThemeDefaultsBuilder(CupertinoColors.label, CupertinoColors.inactiveGray), const _TextThemeDefaultsBuilder(CupertinoColors.label, CupertinoColors.inactiveGray),
primaryColor, primaryColor,
...@@ -162,41 +160,41 @@ class CupertinoTextThemeData with Diagnosticable { ...@@ -162,41 +160,41 @@ class CupertinoTextThemeData with Diagnosticable {
) : assert((_navActionTextStyle != null && _actionTextStyle != null) || _primaryColor != null); ) : assert((_navActionTextStyle != null && _actionTextStyle != null) || _primaryColor != null);
final _TextThemeDefaultsBuilder _defaults; final _TextThemeDefaultsBuilder _defaults;
final Color _primaryColor; final Color? _primaryColor;
final TextStyle _textStyle; final TextStyle? _textStyle;
/// The [TextStyle] of general text content for Cupertino widgets. /// The [TextStyle] of general text content for Cupertino widgets.
TextStyle get textStyle => _textStyle ?? _defaults.textStyle; TextStyle get textStyle => _textStyle ?? _defaults.textStyle;
final TextStyle _actionTextStyle; final TextStyle? _actionTextStyle;
/// The [TextStyle] of interactive text content such as text in a button without background. /// The [TextStyle] of interactive text content such as text in a button without background.
TextStyle get actionTextStyle { TextStyle get actionTextStyle {
return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor); return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor);
} }
final TextStyle _tabLabelTextStyle; final TextStyle? _tabLabelTextStyle;
/// The [TextStyle] of unselected tabs. /// The [TextStyle] of unselected tabs.
TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle; TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle;
final TextStyle _navTitleTextStyle; final TextStyle? _navTitleTextStyle;
/// The [TextStyle] of titles in standard navigation bars. /// The [TextStyle] of titles in standard navigation bars.
TextStyle get navTitleTextStyle => _navTitleTextStyle ?? _defaults.navTitleTextStyle; TextStyle get navTitleTextStyle => _navTitleTextStyle ?? _defaults.navTitleTextStyle;
final TextStyle _navLargeTitleTextStyle; final TextStyle? _navLargeTitleTextStyle;
/// The [TextStyle] of large titles in sliver navigation bars. /// The [TextStyle] of large titles in sliver navigation bars.
TextStyle get navLargeTitleTextStyle => _navLargeTitleTextStyle ?? _defaults.navLargeTitleTextStyle; TextStyle get navLargeTitleTextStyle => _navLargeTitleTextStyle ?? _defaults.navLargeTitleTextStyle;
final TextStyle _navActionTextStyle; final TextStyle? _navActionTextStyle;
/// The [TextStyle] of interactive text content in navigation bars. /// The [TextStyle] of interactive text content in navigation bars.
TextStyle get navActionTextStyle { TextStyle get navActionTextStyle {
return _navActionTextStyle ?? _defaults.navActionTextStyle(primaryColor: _primaryColor); return _navActionTextStyle ?? _defaults.navActionTextStyle(primaryColor: _primaryColor);
} }
final TextStyle _pickerTextStyle; final TextStyle? _pickerTextStyle;
/// The [TextStyle] of pickers. /// The [TextStyle] of pickers.
TextStyle get pickerTextStyle => _pickerTextStyle ?? _defaults.pickerTextStyle; TextStyle get pickerTextStyle => _pickerTextStyle ?? _defaults.pickerTextStyle;
final TextStyle _dateTimePickerTextStyle; final TextStyle? _dateTimePickerTextStyle;
/// The [TextStyle] of date time pickers. /// The [TextStyle] of date time pickers.
TextStyle get dateTimePickerTextStyle => _dateTimePickerTextStyle ?? _defaults.dateTimePickerTextStyle; TextStyle get dateTimePickerTextStyle => _dateTimePickerTextStyle ?? _defaults.dateTimePickerTextStyle;
...@@ -209,7 +207,7 @@ class CupertinoTextThemeData with Diagnosticable { ...@@ -209,7 +207,7 @@ class CupertinoTextThemeData with Diagnosticable {
/// be used as-is. /// be used as-is.
CupertinoTextThemeData resolveFrom(BuildContext context, { bool nullOk = false }) { CupertinoTextThemeData resolveFrom(BuildContext context, { bool nullOk = false }) {
return CupertinoTextThemeData._raw( return CupertinoTextThemeData._raw(
_defaults?.resolveFrom(context, nullOk), _defaults.resolveFrom(context, nullOk),
CupertinoDynamicColor.resolve(_primaryColor, context, nullOk: nullOk), CupertinoDynamicColor.resolve(_primaryColor, context, nullOk: nullOk),
_resolveTextStyle(_textStyle, context, nullOk), _resolveTextStyle(_textStyle, context, nullOk),
_resolveTextStyle(_actionTextStyle, context, nullOk), _resolveTextStyle(_actionTextStyle, context, nullOk),
...@@ -225,20 +223,20 @@ class CupertinoTextThemeData with Diagnosticable { ...@@ -225,20 +223,20 @@ class CupertinoTextThemeData with Diagnosticable {
/// Returns a copy of the current [CupertinoTextThemeData] instance with /// Returns a copy of the current [CupertinoTextThemeData] instance with
/// specified overrides. /// specified overrides.
CupertinoTextThemeData copyWith({ CupertinoTextThemeData copyWith({
Color primaryColor, Color? primaryColor,
@Deprecated( @Deprecated(
'This argument no longer does anything. You can remove it. ' 'This argument no longer does anything. You can remove it. '
'This feature was deprecated after v1.10.14.' 'This feature was deprecated after v1.10.14.'
) )
Brightness brightness, Brightness? brightness,
TextStyle textStyle, TextStyle? textStyle,
TextStyle actionTextStyle, TextStyle? actionTextStyle,
TextStyle tabLabelTextStyle, TextStyle? tabLabelTextStyle,
TextStyle navTitleTextStyle, TextStyle? navTitleTextStyle,
TextStyle navLargeTitleTextStyle, TextStyle? navLargeTitleTextStyle,
TextStyle navActionTextStyle, TextStyle? navActionTextStyle,
TextStyle pickerTextStyle, TextStyle? pickerTextStyle,
TextStyle dateTimePickerTextStyle, TextStyle? dateTimePickerTextStyle,
}) { }) {
return CupertinoTextThemeData._raw( return CupertinoTextThemeData._raw(
_defaults, _defaults,
...@@ -282,9 +280,9 @@ class _TextThemeDefaultsBuilder { ...@@ -282,9 +280,9 @@ class _TextThemeDefaultsBuilder {
final Color inactiveGrayColor; final Color inactiveGrayColor;
static TextStyle _applyLabelColor(TextStyle original, Color color) { static TextStyle _applyLabelColor(TextStyle original, Color color) {
return original?.color == color return original.color == color
? original ? original
: original?.copyWith(color: color); : original.copyWith(color: color);
} }
TextStyle get textStyle => _applyLabelColor(_kDefaultTextStyle, labelColor); TextStyle get textStyle => _applyLabelColor(_kDefaultTextStyle, labelColor);
...@@ -294,12 +292,12 @@ class _TextThemeDefaultsBuilder { ...@@ -294,12 +292,12 @@ class _TextThemeDefaultsBuilder {
TextStyle get pickerTextStyle => _applyLabelColor(_kDefaultPickerTextStyle, labelColor); TextStyle get pickerTextStyle => _applyLabelColor(_kDefaultPickerTextStyle, labelColor);
TextStyle get dateTimePickerTextStyle => _applyLabelColor(_kDefaultDateTimePickerTextStyle, labelColor); TextStyle get dateTimePickerTextStyle => _applyLabelColor(_kDefaultDateTimePickerTextStyle, labelColor);
TextStyle actionTextStyle({ Color primaryColor }) => _kDefaultActionTextStyle.copyWith(color: primaryColor); TextStyle actionTextStyle({ Color? primaryColor }) => _kDefaultActionTextStyle.copyWith(color: primaryColor);
TextStyle navActionTextStyle({ Color primaryColor }) => actionTextStyle(primaryColor: primaryColor); TextStyle navActionTextStyle({ Color? primaryColor }) => actionTextStyle(primaryColor: primaryColor);
_TextThemeDefaultsBuilder resolveFrom(BuildContext context, bool nullOk) { _TextThemeDefaultsBuilder resolveFrom(BuildContext context, bool nullOk) {
final Color resolvedLabelColor = CupertinoDynamicColor.resolve(labelColor, context, nullOk: nullOk); final Color resolvedLabelColor = CupertinoDynamicColor.resolve(labelColor, context, nullOk: nullOk)!;
final Color resolvedInactiveGray = CupertinoDynamicColor.resolve(inactiveGrayColor, context, nullOk: nullOk); final Color resolvedInactiveGray = CupertinoDynamicColor.resolve(inactiveGrayColor, context, nullOk: nullOk)!;
return resolvedLabelColor == labelColor && resolvedInactiveGray == CupertinoColors.inactiveGray return resolvedLabelColor == labelColor && resolvedInactiveGray == CupertinoColors.inactiveGray
? this ? this
: _TextThemeDefaultsBuilder(resolvedLabelColor, resolvedInactiveGray); : _TextThemeDefaultsBuilder(resolvedLabelColor, resolvedInactiveGray);
......
...@@ -167,7 +167,7 @@ void main() { ...@@ -167,7 +167,7 @@ void main() {
}); });
test('can resolve null color', () { test('can resolve null color', () {
expect(CupertinoDynamicColor.resolve(null, null), isNull); expect(CupertinoDynamicColor.resolve(null, _NullElement.instance), isNull);
}); });
test('withVibrancy constructor creates colors that may depend on vibrancy', () { test('withVibrancy constructor creates colors that may depend on vibrancy', () {
...@@ -589,3 +589,20 @@ void main() { ...@@ -589,3 +589,20 @@ void main() {
}); });
}); });
} }
class _NullElement extends Element {
_NullElement() : super(_NullWidget());
static _NullElement instance = _NullElement();
@override
bool get debugDoingBuild => throw UnimplementedError();
@override
void performRebuild() { }
}
class _NullWidget extends Widget {
@override
Element createElement() => throw UnimplementedError();
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment