mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
feat(player): animated gradient background
This commit is contained in:
parent
80959aa0ca
commit
49b5d0e694
@ -70,6 +70,18 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
minimumSize: const Size(28, 28),
|
minimumSize: const Size(28, 28),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final accentColor = palette?.lightVibrantColor ??
|
||||||
|
palette?.darkVibrantColor ??
|
||||||
|
dominantColor;
|
||||||
|
|
||||||
|
final resumePauseStyle = IconButton.styleFrom(
|
||||||
|
backgroundColor: accentColor?.color ?? theme.colorScheme.primary,
|
||||||
|
foregroundColor:
|
||||||
|
accentColor?.titleTextColor ?? theme.colorScheme.onPrimary,
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
iconSize: 24,
|
||||||
|
);
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -199,14 +211,7 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
: Icon(
|
: Icon(
|
||||||
playing ? SpotubeIcons.pause : SpotubeIcons.play,
|
playing ? SpotubeIcons.pause : SpotubeIcons.play,
|
||||||
),
|
),
|
||||||
style: IconButton.styleFrom(
|
style: resumePauseStyle,
|
||||||
backgroundColor:
|
|
||||||
dominantColor?.color ?? theme.colorScheme.primary,
|
|
||||||
foregroundColor: dominantColor?.titleTextColor ??
|
|
||||||
theme.colorScheme.onPrimary,
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
iconSize: 24,
|
|
||||||
),
|
|
||||||
onPressed: Actions.handler<PlayPauseIntent>(
|
onPressed: Actions.handler<PlayPauseIntent>(
|
||||||
context,
|
context,
|
||||||
PlayPauseIntent(ref),
|
PlayPauseIntent(ref),
|
||||||
|
127
lib/components/shared/animated_gradient.dart
Normal file
127
lib/components/shared/animated_gradient.dart
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
|
class AnimateGradient extends HookWidget {
|
||||||
|
const AnimateGradient({
|
||||||
|
Key? key,
|
||||||
|
required this.primaryColors,
|
||||||
|
required this.secondaryColors,
|
||||||
|
this.child,
|
||||||
|
this.primaryBegin,
|
||||||
|
this.primaryEnd,
|
||||||
|
this.secondaryBegin,
|
||||||
|
this.secondaryEnd,
|
||||||
|
AnimationController? controller,
|
||||||
|
this.duration = const Duration(seconds: 4),
|
||||||
|
this.animateAlignments = true,
|
||||||
|
this.reverse = true,
|
||||||
|
}) : assert(primaryColors.length >= 2),
|
||||||
|
assert(primaryColors.length == secondaryColors.length),
|
||||||
|
_controller = controller,
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
/// [controller]: pass this to have a fine control over the [Animation]
|
||||||
|
final AnimationController? _controller;
|
||||||
|
|
||||||
|
/// [duration]: Time to switch between [Gradient].
|
||||||
|
/// By default its value is [Duration(seconds:4)]
|
||||||
|
final Duration duration;
|
||||||
|
|
||||||
|
/// [primaryColors]: These will be the starting colors of the [Animation].
|
||||||
|
final List<Color> primaryColors;
|
||||||
|
|
||||||
|
/// [secondaryColors]: These Colors are those in which the [primaryColors] will transition into.
|
||||||
|
final List<Color> secondaryColors;
|
||||||
|
|
||||||
|
/// [primaryBegin]: This is begin [Alignment] for [primaryColors].
|
||||||
|
/// By default its value is [Alignment.topLeft]
|
||||||
|
final Alignment? primaryBegin;
|
||||||
|
|
||||||
|
/// [primaryBegin]: This is end [Alignment] for [primaryColors].
|
||||||
|
/// By default its value is [Alignment.topRight]
|
||||||
|
final Alignment? primaryEnd;
|
||||||
|
|
||||||
|
/// [secondaryBegin]: This is begin [Alignment] for [secondaryColors].
|
||||||
|
/// By default its value is [Alignment.bottomLeft]
|
||||||
|
final Alignment? secondaryBegin;
|
||||||
|
|
||||||
|
/// [secondaryEnd]: This is end [Alignment] for [secondaryColors].
|
||||||
|
/// By default its value is [Alignment.bottomRight]
|
||||||
|
final Alignment? secondaryEnd;
|
||||||
|
|
||||||
|
/// [animateAlignments]: set to false if you don't want to animate the alignments.
|
||||||
|
/// This can provide you way cooler animations
|
||||||
|
final bool animateAlignments;
|
||||||
|
|
||||||
|
/// [reverse]: set it to false if you don't want to reverse the animation.
|
||||||
|
/// using that it will go into one direction only
|
||||||
|
final bool reverse;
|
||||||
|
|
||||||
|
final Widget? child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// ignore: no_leading_underscores_for_local_identifiers
|
||||||
|
final __controller = useAnimationController(
|
||||||
|
duration: duration,
|
||||||
|
)..repeat(reverse: reverse);
|
||||||
|
|
||||||
|
final controller = _controller ?? __controller;
|
||||||
|
|
||||||
|
final animation = useMemoized(
|
||||||
|
() => CurvedAnimation(
|
||||||
|
parent: controller,
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
),
|
||||||
|
[controller]);
|
||||||
|
|
||||||
|
final colorTween = useMemoized(
|
||||||
|
() => primaryColors.map((color) {
|
||||||
|
return ColorTween(
|
||||||
|
begin: color,
|
||||||
|
end: color,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
[primaryColors]);
|
||||||
|
final colors = useMemoized(
|
||||||
|
() => colorTween.map((color) {
|
||||||
|
return color.evaluate(animation)!;
|
||||||
|
}).toList(),
|
||||||
|
[colorTween, animation]);
|
||||||
|
|
||||||
|
final begin = useMemoized(
|
||||||
|
() => AlignmentTween(
|
||||||
|
begin: primaryBegin ?? Alignment.topLeft,
|
||||||
|
end: primaryEnd ?? Alignment.topRight,
|
||||||
|
),
|
||||||
|
[primaryBegin, primaryEnd]);
|
||||||
|
|
||||||
|
final end = useMemoized(
|
||||||
|
() => AlignmentTween(
|
||||||
|
begin: secondaryBegin ?? Alignment.bottomLeft,
|
||||||
|
end: secondaryEnd ?? Alignment.bottomRight,
|
||||||
|
),
|
||||||
|
[secondaryBegin, secondaryEnd]);
|
||||||
|
|
||||||
|
return AnimatedBuilder(
|
||||||
|
animation: animation,
|
||||||
|
child: child,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: animateAlignments
|
||||||
|
? begin.evaluate(animation)
|
||||||
|
: (primaryBegin as Alignment),
|
||||||
|
end: animateAlignments
|
||||||
|
? end.evaluate(animation)
|
||||||
|
: primaryEnd as Alignment,
|
||||||
|
colors: colors,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -12,11 +12,13 @@ class UniversalImage extends HookWidget {
|
|||||||
final double? width;
|
final double? width;
|
||||||
final double scale;
|
final double scale;
|
||||||
final String? placeholder;
|
final String? placeholder;
|
||||||
|
final BoxFit? fit;
|
||||||
const UniversalImage({
|
const UniversalImage({
|
||||||
required this.path,
|
required this.path,
|
||||||
this.height,
|
this.height,
|
||||||
this.width,
|
this.width,
|
||||||
this.placeholder,
|
this.placeholder,
|
||||||
|
this.fit,
|
||||||
this.scale = 1,
|
this.scale = 1,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -57,6 +59,7 @@ class UniversalImage extends HookWidget {
|
|||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
placeholder: AssetImage(placeholder ?? Assets.placeholder.path),
|
placeholder: AssetImage(placeholder ?? Assets.placeholder.path),
|
||||||
|
fit: fit,
|
||||||
);
|
);
|
||||||
} else if (Uri.tryParse(path) != null && !path.startsWith("assets")) {
|
} else if (Uri.tryParse(path) != null && !path.startsWith("assets")) {
|
||||||
return Image.file(
|
return Image.file(
|
||||||
@ -66,6 +69,7 @@ class UniversalImage extends HookWidget {
|
|||||||
cacheHeight: height?.toInt(),
|
cacheHeight: height?.toInt(),
|
||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
fit: fit,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return Image.asset(
|
return Image.asset(
|
||||||
placeholder ?? Assets.placeholder.path,
|
placeholder ?? Assets.placeholder.path,
|
||||||
@ -85,6 +89,7 @@ class UniversalImage extends HookWidget {
|
|||||||
cacheHeight: height?.toInt(),
|
cacheHeight: height?.toInt(),
|
||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
fit: fit,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return Image.asset(
|
return Image.asset(
|
||||||
placeholder ?? Assets.placeholder.path,
|
placeholder ?? Assets.placeholder.path,
|
||||||
@ -105,6 +110,7 @@ class UniversalImage extends HookWidget {
|
|||||||
cacheHeight: height?.toInt(),
|
cacheHeight: height?.toInt(),
|
||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
fit: fit,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return Image.asset(
|
return Image.asset(
|
||||||
placeholder ?? Assets.placeholder.path,
|
placeholder ?? Assets.placeholder.path,
|
||||||
|
@ -113,17 +113,6 @@ void main(List<String> rawArgs) async {
|
|||||||
enableApplicationParameters: false,
|
enableApplicationParameters: false,
|
||||||
),
|
),
|
||||||
FileHandler(await getLogsPath(), printLogs: false),
|
FileHandler(await getLogsPath(), printLogs: false),
|
||||||
SnackbarHandler(
|
|
||||||
const Duration(seconds: 5),
|
|
||||||
action: SnackBarAction(
|
|
||||||
label: "Dismiss",
|
|
||||||
onPressed: () {
|
|
||||||
ScaffoldMessenger.of(
|
|
||||||
Catcher.navigatorKey!.currentContext!,
|
|
||||||
).hideCurrentSnackBar();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
releaseConfig: CatcherOptions(SilentReportMode(), [
|
releaseConfig: CatcherOptions(SilentReportMode(), [
|
||||||
|
@ -9,6 +9,7 @@ import 'package:spotube/collections/assets.gen.dart';
|
|||||||
import 'package:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
import 'package:spotube/components/player/player_actions.dart';
|
import 'package:spotube/components/player/player_actions.dart';
|
||||||
import 'package:spotube/components/player/player_controls.dart';
|
import 'package:spotube/components/player/player_controls.dart';
|
||||||
|
import 'package:spotube/components/shared/animated_gradient.dart';
|
||||||
import 'package:spotube/components/shared/page_window_title_bar.dart';
|
import 'package:spotube/components/shared/page_window_title_bar.dart';
|
||||||
import 'package:spotube/components/shared/image/universal_image.dart';
|
import 'package:spotube/components/shared/image/universal_image.dart';
|
||||||
import 'package:spotube/hooks/use_breakpoints.dart';
|
import 'package:spotube/hooks/use_breakpoints.dart';
|
||||||
@ -75,123 +76,136 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
leading: const BackButton(),
|
leading: const BackButton(),
|
||||||
),
|
),
|
||||||
extendBodyBehindAppBar: true,
|
extendBodyBehindAppBar: true,
|
||||||
body: Container(
|
body: AnimateGradient(
|
||||||
decoration: BoxDecoration(
|
animateAlignments: true,
|
||||||
color: palette.dominantColor?.color,
|
primaryBegin: Alignment.topLeft,
|
||||||
gradient: LinearGradient(
|
primaryEnd: Alignment.bottomLeft,
|
||||||
colors: [
|
secondaryBegin: Alignment.bottomRight,
|
||||||
palette.dominantColor?.color ?? theme.colorScheme.primary,
|
secondaryEnd: Alignment.topRight,
|
||||||
palette.mutedColor?.color ?? theme.colorScheme.secondary,
|
duration: const Duration(seconds: 25),
|
||||||
],
|
primaryColors: [
|
||||||
transform: const GradientRotation(0.5),
|
palette.dominantColor?.color ?? theme.colorScheme.primary,
|
||||||
),
|
palette.mutedColor?.color ?? theme.colorScheme.secondary,
|
||||||
),
|
],
|
||||||
alignment: Alignment.center,
|
secondaryColors: [
|
||||||
child: ConstrainedBox(
|
(palette.darkVibrantColor ?? palette.lightVibrantColor)?.color ??
|
||||||
constraints: const BoxConstraints(maxWidth: 580),
|
theme.colorScheme.primaryContainer,
|
||||||
child: SafeArea(
|
(palette.darkMutedColor ?? palette.lightMutedColor)?.color ??
|
||||||
child: Padding(
|
theme.colorScheme.secondaryContainer,
|
||||||
padding: const EdgeInsets.all(8.0),
|
],
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
alignment: Alignment.center,
|
||||||
DecoratedBox(
|
width: double.infinity,
|
||||||
decoration: BoxDecoration(
|
child: ConstrainedBox(
|
||||||
borderRadius: BorderRadius.circular(20),
|
constraints: const BoxConstraints(maxWidth: 580),
|
||||||
boxShadow: const [
|
child: SafeArea(
|
||||||
BoxShadow(
|
child: Padding(
|
||||||
color: Colors.black26,
|
padding: const EdgeInsets.all(8.0),
|
||||||
spreadRadius: 2,
|
child: Column(
|
||||||
blurRadius: 10,
|
children: [
|
||||||
offset: Offset(0, 0),
|
Container(
|
||||||
|
constraints:
|
||||||
|
const BoxConstraints(maxHeight: 300, maxWidth: 300),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black26,
|
||||||
|
spreadRadius: 2,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: Offset(0, 0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
child: UniversalImage(
|
||||||
|
path: albumArt,
|
||||||
|
placeholder: Assets.albumPlaceholder.path,
|
||||||
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
child: UniversalImage(
|
|
||||||
path: albumArt,
|
|
||||||
placeholder: Assets.albumPlaceholder.path,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 10),
|
||||||
const SizedBox(height: 10),
|
Container(
|
||||||
Container(
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
alignment: Alignment.centerLeft,
|
||||||
alignment: Alignment.centerLeft,
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
AutoSizeText(
|
||||||
AutoSizeText(
|
currentTrack?.name ?? "Not playing",
|
||||||
currentTrack?.name ?? "Not playing",
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize: 20,
|
||||||
fontSize: 20,
|
color: titleTextColor,
|
||||||
color: titleTextColor,
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
if (isLocalTrack)
|
||||||
textAlign: TextAlign.start,
|
Text(
|
||||||
),
|
TypeConversionUtils.artists_X_String<Artist>(
|
||||||
if (isLocalTrack)
|
currentTrack?.artists ?? [],
|
||||||
Text(
|
),
|
||||||
TypeConversionUtils.artists_X_String<Artist>(
|
style: theme.textTheme.bodyMedium!.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: bodyTextColor,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
TypeConversionUtils.artists_X_ClickableArtists(
|
||||||
currentTrack?.artists ?? [],
|
currentTrack?.artists ?? [],
|
||||||
|
textStyle: theme.textTheme.bodyMedium!.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: bodyTextColor,
|
||||||
|
),
|
||||||
|
onRouteChange: (route) {
|
||||||
|
GoRouter.of(context).pop();
|
||||||
|
GoRouter.of(context).push(route);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
style: theme.textTheme.bodyMedium!.copyWith(
|
],
|
||||||
fontWeight: FontWeight.bold,
|
),
|
||||||
color: bodyTextColor,
|
),
|
||||||
),
|
const SizedBox(height: 40),
|
||||||
)
|
PlayerControls(palette: palette),
|
||||||
else
|
const Spacer(),
|
||||||
TypeConversionUtils.artists_X_ClickableArtists(
|
PlayerActions(
|
||||||
currentTrack?.artists ?? [],
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
textStyle: theme.textTheme.bodyMedium!.copyWith(
|
floatingQueue: false,
|
||||||
fontWeight: FontWeight.bold,
|
extraActions: [
|
||||||
color: bodyTextColor,
|
if (auth != null)
|
||||||
),
|
IconButton(
|
||||||
onRouteChange: (route) {
|
tooltip: "Open Lyrics",
|
||||||
GoRouter.of(context).pop();
|
icon: const Icon(SpotubeIcons.music),
|
||||||
GoRouter.of(context).push(route);
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isDismissible: true,
|
||||||
|
enableDrag: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.black38,
|
||||||
|
barrierColor: Colors.black12,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(20),
|
||||||
|
topRight: Radius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight:
|
||||||
|
MediaQuery.of(context).size.height *
|
||||||
|
0.8,
|
||||||
|
),
|
||||||
|
builder: (context) =>
|
||||||
|
const LyricsPage(isModal: true),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(height: 40),
|
),
|
||||||
PlayerControls(palette: palette),
|
|
||||||
const Spacer(),
|
|
||||||
PlayerActions(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
floatingQueue: false,
|
|
||||||
extraActions: [
|
|
||||||
if (auth != null)
|
|
||||||
IconButton(
|
|
||||||
tooltip: "Open Lyrics",
|
|
||||||
icon: const Icon(SpotubeIcons.music),
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isDismissible: true,
|
|
||||||
enableDrag: true,
|
|
||||||
isScrollControlled: true,
|
|
||||||
backgroundColor: Colors.black38,
|
|
||||||
barrierColor: Colors.black12,
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(20),
|
|
||||||
topRight: Radius.circular(20),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
maxHeight:
|
|
||||||
MediaQuery.of(context).size.height * 0.8,
|
|
||||||
),
|
|
||||||
builder: (context) =>
|
|
||||||
const LyricsPage(isModal: true),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
17
pubspec.lock
17
pubspec.lock
@ -17,23 +17,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.4.0"
|
version: "5.4.0"
|
||||||
animate_gradient:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
path: "."
|
|
||||||
ref: "2e02ab5d1cb60fc172a5f15f6e91bd34a050af23"
|
|
||||||
resolved-ref: "2e02ab5d1cb60fc172a5f15f6e91bd34a050af23"
|
|
||||||
url: "https://github.com/Vikaskumar75/Animated-Gradient"
|
|
||||||
source: git
|
|
||||||
version: "0.0.2"
|
|
||||||
animated_gradient:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: animated_gradient
|
|
||||||
sha256: "9c0c52a093817ae42550e3affec6973a7bae7186d1d5d58749ca9689da3ba245"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.2"
|
|
||||||
app_package_maker:
|
app_package_maker:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -9,11 +9,6 @@ environment:
|
|||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
animate_gradient:
|
|
||||||
git:
|
|
||||||
url: https://github.com/Vikaskumar75/Animated-Gradient
|
|
||||||
ref: 2e02ab5d1cb60fc172a5f15f6e91bd34a050af23
|
|
||||||
animated_gradient: ^0.0.2
|
|
||||||
args: ^2.3.2
|
args: ^2.3.2
|
||||||
async: ^2.9.0
|
async: ^2.9.0
|
||||||
audio_service: ^0.18.9
|
audio_service: ^0.18.9
|
||||||
|
Loading…
Reference in New Issue
Block a user