|
|
@ -1,6 +1,7 @@ |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:meta/meta.dart'; |
|
|
|
import 'package:meta/meta.dart'; |
|
|
|
import 'package:neon/src/utils/hex_color.dart'; |
|
|
|
import 'package:neon/src/utils/hex_color.dart'; |
|
|
|
|
|
|
|
import 'package:neon/src/widgets/dialog.dart'; |
|
|
|
import 'package:nextcloud/nextcloud.dart'; |
|
|
|
import 'package:nextcloud/nextcloud.dart'; |
|
|
|
|
|
|
|
|
|
|
|
@internal |
|
|
|
@internal |
|
|
@ -48,11 +49,7 @@ class AppTheme { |
|
|
|
snackBarTheme: _snackBarTheme, |
|
|
|
snackBarTheme: _snackBarTheme, |
|
|
|
dividerTheme: _dividerTheme, |
|
|
|
dividerTheme: _dividerTheme, |
|
|
|
extensions: [ |
|
|
|
extensions: [ |
|
|
|
const NeonTheme( |
|
|
|
const NeonTheme(), |
|
|
|
tabletLayout: BoxConstraints( |
|
|
|
|
|
|
|
maxWidth: 640, |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
...?appThemes, |
|
|
|
...?appThemes, |
|
|
|
], |
|
|
|
], |
|
|
|
); |
|
|
|
); |
|
|
@ -71,21 +68,27 @@ class AppTheme { |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Defines the configuration of the overall visual [Theme] for a NeonApp |
|
|
|
|
|
|
|
/// or a widget subtree within the app. |
|
|
|
@internal |
|
|
|
@internal |
|
|
|
@immutable |
|
|
|
@immutable |
|
|
|
class NeonTheme extends ThemeExtension<NeonTheme> { |
|
|
|
class NeonTheme extends ThemeExtension<NeonTheme> { |
|
|
|
|
|
|
|
/// Create a [NeonTheme] that's used to configure a [Theme]. |
|
|
|
const NeonTheme({ |
|
|
|
const NeonTheme({ |
|
|
|
required this.tabletLayout, |
|
|
|
this.dialogTheme = const NeonDialogTheme(), |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
final BoxConstraints? tabletLayout; |
|
|
|
/// A theme for customizing the visual properties of [NeonDialog]s. |
|
|
|
|
|
|
|
/// |
|
|
|
|
|
|
|
/// This is the value returned from [NeonDialogTheme.of]. |
|
|
|
|
|
|
|
final NeonDialogTheme dialogTheme; |
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
@override |
|
|
|
NeonTheme copyWith({ |
|
|
|
NeonTheme copyWith({ |
|
|
|
final BoxConstraints? tabletLayout, |
|
|
|
final NeonDialogTheme? dialogTheme, |
|
|
|
}) => |
|
|
|
}) => |
|
|
|
NeonTheme( |
|
|
|
NeonTheme( |
|
|
|
tabletLayout: tabletLayout ?? this.tabletLayout, |
|
|
|
dialogTheme: dialogTheme ?? this.dialogTheme, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
@override |
|
|
@ -94,7 +97,68 @@ class NeonTheme extends ThemeExtension<NeonTheme> { |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
return NeonTheme( |
|
|
|
return NeonTheme( |
|
|
|
tabletLayout: BoxConstraints.lerp(tabletLayout, other.tabletLayout, t), |
|
|
|
dialogTheme: NeonDialogTheme.lerp(dialogTheme, other.dialogTheme, t), |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Defines a theme for [NeonDialog] widgets. |
|
|
|
|
|
|
|
/// |
|
|
|
|
|
|
|
/// Descendant widgets obtain the current [NeonDialogTheme] object using |
|
|
|
|
|
|
|
/// `NeonDialogTheme.of(context)`. Instances of [NeonDialogTheme] can be customized with |
|
|
|
|
|
|
|
/// [NeonDialogTheme.copyWith]. |
|
|
|
|
|
|
|
@immutable |
|
|
|
|
|
|
|
class NeonDialogTheme { |
|
|
|
|
|
|
|
/// Creates a dialog theme that can be used for [NeonTheme.dialogTheme]. |
|
|
|
|
|
|
|
const NeonDialogTheme({ |
|
|
|
|
|
|
|
this.constraints = const BoxConstraints( |
|
|
|
|
|
|
|
minWidth: 280, |
|
|
|
|
|
|
|
maxWidth: 560, |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Used to configure the [BoxConstraints] for the [NeonDialog] widget. |
|
|
|
|
|
|
|
/// |
|
|
|
|
|
|
|
/// This value should also be used on [Dialog.fullscreen] and other similar pages. |
|
|
|
|
|
|
|
/// By default it follows the default [m3 dialog specification](https://m3.material.io/components/dialogs/specs). |
|
|
|
|
|
|
|
final BoxConstraints constraints; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Creates a copy of this object but with the given fields replaced with the |
|
|
|
|
|
|
|
/// new values. |
|
|
|
|
|
|
|
NeonDialogTheme copyWith({ |
|
|
|
|
|
|
|
final BoxConstraints? constraints, |
|
|
|
|
|
|
|
}) => |
|
|
|
|
|
|
|
NeonDialogTheme( |
|
|
|
|
|
|
|
constraints: constraints ?? this.constraints, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The data from the closest [NeonDialogTheme] instance given the build context. |
|
|
|
|
|
|
|
static NeonDialogTheme of(final BuildContext context) => Theme.of(context).extension<NeonTheme>()!.dialogTheme; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Linearly interpolate between two neon dialog themes. |
|
|
|
|
|
|
|
/// |
|
|
|
|
|
|
|
/// {@macro dart.ui.shadow.lerp} |
|
|
|
|
|
|
|
// ignore: prefer_constructors_over_static_methods |
|
|
|
|
|
|
|
static NeonDialogTheme lerp(final NeonDialogTheme a, final NeonDialogTheme b, final double t) { |
|
|
|
|
|
|
|
if (identical(a, b)) { |
|
|
|
|
|
|
|
return a; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return NeonDialogTheme( |
|
|
|
|
|
|
|
constraints: BoxConstraints.lerp(a.constraints, b.constraints, t)!, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
|
|
int get hashCode => constraints.hashCode; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
|
|
bool operator ==(final Object other) { |
|
|
|
|
|
|
|
if (identical(this, other)) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (other.runtimeType != runtimeType) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return other is NeonDialogTheme && other.constraints == constraints; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|