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

migration of material files to nullsafety (#66633)

parent 549de844
This diff is collapsed.
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -41,43 +39,43 @@ class BottomSheetThemeData with Diagnosticable {
/// Default value for [BottomSheet.backgroundColor].
///
/// If null, [BottomSheet] defaults to [Material]'s default.
final Color backgroundColor;
final Color? backgroundColor;
/// Default value for [BottomSheet.elevation].
///
/// {@macro flutter.material.material.elevation}
///
/// If null, [BottomSheet] defaults to 0.0.
final double elevation;
final double? elevation;
/// Value for [BottomSheet.backgroundColor] when the Bottom sheet is presented
/// as a modal bottom sheet.
final Color modalBackgroundColor;
final Color? modalBackgroundColor;
/// Value for [BottomSheet.elevation] when the Bottom sheet is presented as a
/// modal bottom sheet.
final double modalElevation;
final double? modalElevation;
/// Default value for [BottomSheet.shape].
///
/// If null, no overriding shape is specified for [BottomSheet], so the
/// [BottomSheet] is rectangular.
final ShapeBorder shape;
final ShapeBorder? shape;
/// Default value for [BottomSheet.clipBehavior].
///
/// If null, [BottomSheet] uses [Clip.none].
final Clip clipBehavior;
final Clip? clipBehavior;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
BottomSheetThemeData copyWith({
Color backgroundColor,
double elevation,
Color modalBackgroundColor,
double modalElevation,
ShapeBorder shape,
Clip clipBehavior,
Color? backgroundColor,
double? elevation,
Color? modalBackgroundColor,
double? modalElevation,
ShapeBorder? shape,
Clip? clipBehavior,
}) {
return BottomSheetThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
......@@ -94,7 +92,7 @@ class BottomSheetThemeData with Diagnosticable {
/// If both arguments are null then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static BottomSheetThemeData lerp(BottomSheetThemeData a, BottomSheetThemeData b, double t) {
static BottomSheetThemeData? lerp(BottomSheetThemeData? a, BottomSheetThemeData? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show Color;
import 'package:flutter/painting.dart';
......@@ -27,34 +25,34 @@ class MaterialColor extends ColorSwatch<int> {
const MaterialColor(int primary, Map<int, Color> swatch) : super(primary, swatch);
/// The lightest shade.
Color get shade50 => this[50];
Color get shade50 => this[50]!;
/// The second lightest shade.
Color get shade100 => this[100];
Color get shade100 => this[100]!;
/// The third lightest shade.
Color get shade200 => this[200];
Color get shade200 => this[200]!;
/// The fourth lightest shade.
Color get shade300 => this[300];
Color get shade300 => this[300]!;
/// The fifth lightest shade.
Color get shade400 => this[400];
Color get shade400 => this[400]!;
/// The default shade.
Color get shade500 => this[500];
Color get shade500 => this[500]!;
/// The fourth darkest shade.
Color get shade600 => this[600];
Color get shade600 => this[600]!;
/// The third darkest shade.
Color get shade700 => this[700];
Color get shade700 => this[700]!;
/// The second darkest shade.
Color get shade800 => this[800];
Color get shade800 => this[800]!;
/// The darkest shade.
Color get shade900 => this[900];
Color get shade900 => this[900]!;
}
/// Defines a single accent color as well a swatch of four shades of the
......@@ -75,19 +73,19 @@ class MaterialAccentColor extends ColorSwatch<int> {
const MaterialAccentColor(int primary, Map<int, Color> swatch) : super(primary, swatch);
/// The lightest shade.
Color get shade50 => this[50];
Color get shade50 => this[50]!;
/// The second lightest shade.
Color get shade100 => this[100];
Color get shade100 => this[100]!;
/// The default shade.
Color get shade200 => this[200];
Color get shade200 => this[200]!;
/// The second darkest shade.
Color get shade400 => this[400];
Color get shade400 => this[400]!;
/// The darkest shade.
Color get shade700 => this[700];
Color get shade700 => this[700]!;
}
/// [Color] and [ColorSwatch] constants which represent Material design's
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/painting.dart';
/// The minimum dimension of any interactive region according to Material
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/animation.dart';
// The easing curves of the Material Library
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
......@@ -48,63 +46,63 @@ class FloatingActionButtonThemeData with Diagnosticable {
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
/// foreground.
final Color foregroundColor;
final Color? foregroundColor;
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
/// background.
final Color backgroundColor;
final Color? backgroundColor;
/// The color to use for filling the button when the button has input focus.
final Color focusColor;
final Color? focusColor;
/// The color to use for filling the button when the button has a pointer
/// hovering over it.
final Color hoverColor;
final Color? hoverColor;
/// The splash color for this [FloatingActionButton]'s [InkWell].
final Color splashColor;
final Color? splashColor;
/// The z-coordinate to be used for the unselected, enabled
/// [FloatingActionButton]'s elevation foreground.
final double elevation;
final double? elevation;
/// The z-coordinate at which to place this button relative to its parent when
/// the button has the input focus.
///
/// This controls the size of the shadow below the floating action button.
final double focusElevation;
final double? focusElevation;
/// The z-coordinate at which to place this button relative to its parent when
/// the button is enabled and has a pointer hovering over it.
///
/// This controls the size of the shadow below the floating action button.
final double hoverElevation;
final double? hoverElevation;
/// The z-coordinate to be used for the disabled [FloatingActionButton]'s
/// elevation foreground.
final double disabledElevation;
final double? disabledElevation;
/// The z-coordinate to be used for the selected, enabled
/// [FloatingActionButton]'s elevation foreground.
final double highlightElevation;
final double? highlightElevation;
/// The shape to be used for the floating action button's [Material].
final ShapeBorder shape;
final ShapeBorder? shape;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
FloatingActionButtonThemeData copyWith({
Color foregroundColor,
Color backgroundColor,
Color focusColor,
Color hoverColor,
Color splashColor,
double elevation,
double focusElevation,
double hoverElevation,
double disabledElevation,
double highlightElevation,
ShapeBorder shape,
Color? foregroundColor,
Color? backgroundColor,
Color? focusColor,
Color? hoverColor,
Color? splashColor,
double? elevation,
double? focusElevation,
double? hoverElevation,
double? disabledElevation,
double? highlightElevation,
ShapeBorder? shape,
}) {
return FloatingActionButtonThemeData(
foregroundColor: foregroundColor ?? this.foregroundColor,
......@@ -126,7 +124,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
/// If both arguments are null then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static FloatingActionButtonThemeData lerp(FloatingActionButtonThemeData a, FloatingActionButtonThemeData b, double t) {
static FloatingActionButtonThemeData? lerp(FloatingActionButtonThemeData? a, FloatingActionButtonThemeData? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
/// The Flutter logo, in widget form. This widget respects the [IconTheme].
......@@ -22,7 +20,7 @@ class FlutterLogo extends StatelessWidget {
/// The [textColor], [style], [duration], and [curve] arguments must not be
/// null.
const FlutterLogo({
Key key,
Key? key,
this.size,
this.textColor = const Color(0xFF757575),
this.style = FlutterLogoStyle.markOnly,
......@@ -41,7 +39,7 @@ class FlutterLogo extends StatelessWidget {
/// Defaults to the current [IconTheme] size, if any. If there is no
/// [IconTheme], or it does not specify an explicit size, then it defaults to
/// 24.0.
final double size;
final double? size;
/// The color used to paint the "Flutter" text on the logo, if [style] is
/// [FlutterLogoStyle.horizontal] or [FlutterLogoStyle.stacked].
......@@ -64,7 +62,7 @@ class FlutterLogo extends StatelessWidget {
@override
Widget build(BuildContext context) {
final IconThemeData iconTheme = IconTheme.of(context);
final double iconSize = size ?? iconTheme.size;
final double? iconSize = size ?? iconTheme.size;
return AnimatedContainer(
width: iconSize,
height: iconSize,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
/// A tile in a material design grid list.
......@@ -23,22 +21,22 @@ class GridTile extends StatelessWidget {
///
/// Must have a child. Does not typically have both a header and a footer.
const GridTile({
Key key,
Key? key,
this.header,
this.footer,
@required this.child,
required this.child,
}) : assert(child != null),
super(key: key);
/// The widget to show over the top of this grid tile.
///
/// Typically a [GridTileBar].
final Widget header;
final Widget? header;
/// The widget to show over the bottom of this grid tile.
///
/// Typically a [GridTileBar].
final Widget footer;
final Widget? footer;
/// The widget that fills the tile.
///
......@@ -60,14 +58,14 @@ class GridTile extends StatelessWidget {
top: 0.0,
left: 0.0,
right: 0.0,
child: header,
child: header!,
),
if (footer != null)
Positioned(
left: 0.0,
bottom: 0.0,
right: 0.0,
child: footer,
child: footer!,
),
],
);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
/// Identifiers for the supported material design icons.
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show Color;
import 'package:flutter/foundation.dart';
......@@ -76,7 +74,7 @@ enum MaterialState {
/// Signature for the function that returns a value of type `T` based on a given
/// set of states.
typedef MaterialPropertyResolver<T> = T Function(Set<MaterialState> states);
typedef MaterialPropertyResolver<T> = T? Function(Set<MaterialState> states);
/// Defines a [Color] that is also a [MaterialStateProperty].
///
......@@ -139,7 +137,7 @@ abstract class MaterialStateColor extends Color implements MaterialStateProperty
/// Returns a [Color] that's to be used when a Material component is in the
/// specified state.
@override
Color resolve(Set<MaterialState> states);
Color? resolve(Set<MaterialState> states);
}
/// A [MaterialStateColor] created from a [MaterialPropertyResolver<Color>]
......@@ -150,7 +148,7 @@ abstract class MaterialStateColor extends Color implements MaterialStateProperty
///
/// Used by [MaterialStateColor.resolveWith].
class _MaterialStateColor extends MaterialStateColor {
_MaterialStateColor(this._resolve) : super(_resolve(_defaultStates).value);
_MaterialStateColor(this._resolve) : super(_resolve(_defaultStates)!.value);
final MaterialPropertyResolver<Color> _resolve;
......@@ -158,7 +156,7 @@ class _MaterialStateColor extends MaterialStateColor {
static const Set<MaterialState> _defaultStates = <MaterialState>{};
@override
Color resolve(Set<MaterialState> states) => _resolve(states);
Color? resolve(Set<MaterialState> states) => _resolve(states);
}
/// Defines a [MouseCursor] whose value depends on a set of [MaterialState]s which
......@@ -224,7 +222,7 @@ abstract class MaterialStateMouseCursor extends MouseCursor implements MaterialS
@protected
@override
MouseCursorSession createSession(int device) {
return resolve(<MaterialState>{}).createSession(device);
return resolve(<MaterialState>{})!.createSession(device);
}
/// Returns a [MouseCursor] that's to be used when a Material component is in
......@@ -232,7 +230,7 @@ abstract class MaterialStateMouseCursor extends MouseCursor implements MaterialS
///
/// This method should never return null.
@override
MouseCursor resolve(Set<MaterialState> states);
MouseCursor? resolve(Set<MaterialState> states);
/// A mouse cursor for clickable material widgets, which resolves differently
/// when the widget is disabled.
......@@ -263,9 +261,9 @@ abstract class MaterialStateMouseCursor extends MouseCursor implements MaterialS
class _EnabledAndDisabledMouseCursor extends MaterialStateMouseCursor {
const _EnabledAndDisabledMouseCursor({
this.enabledCursor,
this.disabledCursor,
this.name,
required this.enabledCursor,
required this.disabledCursor,
required this.name,
});
final MouseCursor enabledCursor;
......@@ -349,7 +347,7 @@ abstract class MaterialStateProperty<T> {
/// Widgets like [TextButton] and [ElevatedButton] apply this method to their
/// current [MaterialState]s to compute colors and other visual parameters
/// at build time.
T resolve(Set<MaterialState> states);
T? resolve(Set<MaterialState> states);
/// Resolves the value for the given set of states if `value` is a
/// [MaterialStateProperty], otherwise returns the value itself.
......@@ -357,9 +355,9 @@ abstract class MaterialStateProperty<T> {
/// This is useful for widgets that have parameters which can optionally be a
/// [MaterialStateProperty]. For example, [InkWell.mouseCursor] can be a
/// [MouseCursor] or a [MaterialStateProperty<MouseCursor>].
static T resolveAs<T>(T value, Set<MaterialState> states) {
static T? resolveAs<T>(T? value, Set<MaterialState> states) {
if (value is MaterialStateProperty<T>) {
final MaterialStateProperty<T> property = value;
final MaterialStateProperty<T> property = value as MaterialStateProperty<T>;
return property.resolve(states);
}
return value;
......@@ -371,7 +369,7 @@ abstract class MaterialStateProperty<T> {
/// Convenience method for creating a [MaterialStateProperty] that resolves
/// to a single value for all states.
static MaterialStateProperty<T> all<T>(T value) => _MaterialStatePropertyAll<T>(value);
static MaterialStateProperty<T> all<T>(T? value) => _MaterialStatePropertyAll<T>(value);
}
class _MaterialStatePropertyWith<T> implements MaterialStateProperty<T> {
......@@ -380,16 +378,16 @@ class _MaterialStatePropertyWith<T> implements MaterialStateProperty<T> {
final MaterialPropertyResolver<T> _resolve;
@override
T resolve(Set<MaterialState> states) => _resolve(states);
T? resolve(Set<MaterialState> states) => _resolve(states);
}
class _MaterialStatePropertyAll<T> implements MaterialStateProperty<T> {
_MaterialStatePropertyAll(this.value);
final T value;
final T? value;
@override
T resolve(Set<MaterialState> states) => value;
T? resolve(Set<MaterialState> states) => value;
@override
String toString() => 'MaterialStateProperty.all($value)';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
......@@ -32,15 +30,15 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// The [activeColor], and [inactiveColor] arguments must not be
/// null. The [value] can only be null if tristate is true.
RenderToggleable({
@required bool value,
required bool? value,
bool tristate = false,
@required Color activeColor,
@required Color inactiveColor,
Color hoverColor,
Color focusColor,
ValueChanged<bool> onChanged,
BoxConstraints additionalConstraints,
@required TickerProvider vsync,
required Color activeColor,
required Color inactiveColor,
Color? hoverColor,
Color? focusColor,
ValueChanged<bool?>? onChanged,
required BoxConstraints additionalConstraints,
required TickerProvider vsync,
bool hasFocus = false,
bool hovering = false,
}) : assert(tristate != null),
......@@ -110,7 +108,7 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// animation reaches either 0.0 or 1.0.
@protected
AnimationController get positionController => _positionController;
AnimationController _positionController;
late AnimationController _positionController;
/// The visual value of the control.
///
......@@ -121,7 +119,7 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// to active (or vice versa), [value] is the target value and this animation
/// gradually updates from 0.0 to 1.0 (or vice versa).
CurvedAnimation get position => _position;
CurvedAnimation _position;
late CurvedAnimation _position;
/// Used by subclasses to control the radial reaction animation.
///
......@@ -132,8 +130,8 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// reaction.
@protected
AnimationController get reactionController => _reactionController;
AnimationController _reactionController;
Animation<double> _reaction;
late AnimationController _reactionController;
late Animation<double> _reaction;
/// Used by subclasses to control the radial reaction's opacity animation for
/// [hasFocus] changes.
......@@ -146,8 +144,8 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// reaction.
@protected
AnimationController get reactionFocusFadeController => _reactionFocusFadeController;
AnimationController _reactionFocusFadeController;
Animation<double> _reactionFocusFade;
late AnimationController _reactionFocusFadeController;
late Animation<double> _reactionFocusFade;
/// Used by subclasses to control the radial reaction's opacity animation for
/// [hovering] changes.
......@@ -160,8 +158,8 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// reaction.
@protected
AnimationController get reactionHoverFadeController => _reactionHoverFadeController;
AnimationController _reactionHoverFadeController;
Animation<double> _reactionHoverFade;
late AnimationController _reactionHoverFadeController;
late Animation<double> _reactionHoverFade;
/// True if this toggleable has the input focus.
bool get hasFocus => _hasFocus;
......@@ -216,9 +214,9 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// When the value changes, this object starts the [positionController] and
/// [position] animations to animate the visual appearance of the control to
/// the new value.
bool get value => _value;
bool _value;
set value(bool value) {
bool? get value => _value;
bool? _value;
set value(bool? value) {
assert(tristate || value != null);
if (value == _value)
return;
......@@ -323,9 +321,9 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// that is displayed when the toggleable is toggled by a tap.
///
/// Defaults to the [activeColor] at alpha [kRadialReactionAlpha].
Color get reactionColor => _reactionColor;
Color _reactionColor;
set reactionColor(Color value) {
Color? get reactionColor => _reactionColor;
Color? _reactionColor;
set reactionColor(Color? value) {
assert(value != null);
if (value == _reactionColor)
return;
......@@ -342,9 +340,9 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// callback is non-null. If the callback is null, then the control is
/// disabled, and non-interactive. A disabled checkbox, for example, is
/// displayed using a grey color and its value cannot be changed.
ValueChanged<bool> get onChanged => _onChanged;
ValueChanged<bool> _onChanged;
set onChanged(ValueChanged<bool> value) {
ValueChanged<bool?>? get onChanged => _onChanged;
ValueChanged<bool?>? _onChanged;
set onChanged(ValueChanged<bool?>? value) {
if (value == _onChanged)
return;
final bool wasInteractive = isInteractive;
......@@ -363,8 +361,8 @@ abstract class RenderToggleable extends RenderConstrainedBox {
/// grey color and its value cannot be changed.
bool get isInteractive => onChanged != null;
TapGestureRecognizer _tap;
Offset _downPosition;
late TapGestureRecognizer _tap;
Offset? _downPosition;
@override
void attach(PipelineOwner owner) {
......@@ -410,13 +408,13 @@ abstract class RenderToggleable extends RenderConstrainedBox {
return;
switch (value) {
case false:
onChanged(true);
onChanged!(true);
break;
case true:
onChanged(tristate ? null : false);
onChanged!(tristate ? null : false);
break;
default: // case null:
onChanged(false);
case null:
onChanged!(false);
break;
}
sendSemanticsEvent(const TapSemanticEvent());
......@@ -457,8 +455,8 @@ abstract class RenderToggleable extends RenderConstrainedBox {
Color.lerp(activeColor.withAlpha(kRadialReactionAlpha), hoverColor, _reactionHoverFade.value),
focusColor,
_reactionFocusFade.value,
);
final Offset center = Offset.lerp(_downPosition ?? origin, origin, _reaction.value);
)!;
final Offset center = Offset.lerp(_downPosition ?? origin, origin, _reaction.value)!;
final double reactionRadius = hasFocus || hovering
? kRadialReactionRadius
: _kRadialReactionRadiusTween.evaluate(_reaction);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
......@@ -117,12 +115,12 @@ class Typography with Diagnosticable {
/// The default values for [englishLike], [dense], and [tall] are
/// [englishLike2014], [dense2014], and [tall2014].
factory Typography.material2014({
TargetPlatform platform = TargetPlatform.android,
TextTheme black,
TextTheme white,
TextTheme englishLike,
TextTheme dense,
TextTheme tall,
TargetPlatform? platform = TargetPlatform.android,
TextTheme? black,
TextTheme? white,
TextTheme? englishLike,
TextTheme? dense,
TextTheme? tall,
}) {
assert(platform != null || (black != null && white != null));
return Typography._withPlatform(
......@@ -145,12 +143,12 @@ class Typography with Diagnosticable {
/// The default values for [englishLike], [dense], and [tall] are
/// [englishLike2018], [dense2018], and [tall2018].
factory Typography.material2018({
TargetPlatform platform = TargetPlatform.android,
TextTheme black,
TextTheme white,
TextTheme englishLike,
TextTheme dense,
TextTheme tall,
TargetPlatform? platform = TargetPlatform.android,
TextTheme? black,
TextTheme? white,
TextTheme? englishLike,
TextTheme? dense,
TextTheme? tall,
}) {
assert(platform != null || (black != null && white != null));
return Typography._withPlatform(
......@@ -163,9 +161,9 @@ class Typography with Diagnosticable {
}
factory Typography._withPlatform(
TargetPlatform platform,
TextTheme black,
TextTheme white,
TargetPlatform? platform,
TextTheme? black,
TextTheme? white,
TextTheme englishLike,
TextTheme dense,
TextTheme tall,
......@@ -193,8 +191,10 @@ class Typography with Diagnosticable {
black ??= blackHelsinki;
white ??= whiteHelsinki;
break;
case null:
break;
}
return Typography._(black, white, englishLike, dense, tall);
return Typography._(black!, white!, englishLike, dense, tall);
}
const Typography._(this.black, this.white, this.englishLike, this.dense, this.tall)
......@@ -269,17 +269,16 @@ class Typography with Diagnosticable {
case ScriptCategory.tall:
return tall;
}
return null;
}
/// Creates a copy of this [Typography] with the given fields
/// replaced by the non-null parameter values.
Typography copyWith({
TextTheme black,
TextTheme white,
TextTheme englishLike,
TextTheme dense,
TextTheme tall,
TextTheme? black,
TextTheme? white,
TextTheme? englishLike,
TextTheme? dense,
TextTheme? tall,
}) {
return Typography._(
black ?? this.black,
......
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