Initial commit
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../providers/emby_headers_provider.dart';
|
||||
import '../../providers/shell_backdrop_provider.dart';
|
||||
|
||||
|
||||
class ShellBackdropLayer extends ConsumerWidget {
|
||||
final bool active;
|
||||
|
||||
const ShellBackdropLayer({super.key, this.active = false});
|
||||
|
||||
|
||||
static const double _blurSigma = 32;
|
||||
|
||||
|
||||
static const Duration _crossfade = Duration(milliseconds: 350);
|
||||
|
||||
|
||||
static const LinearGradient _immersiveDarkFallback = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
stops: [0.0, 0.4, 1.0],
|
||||
colors: [Color(0xFF1A1A1A), Color(0xFF0F0F0F), Color(0xFF000000)],
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final backdrop = active ? ref.watch(shellBackdropProvider) : null;
|
||||
final imageHeaders = ref.watch(embyImageHeadersProvider).value;
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
|
||||
final Widget child;
|
||||
if (backdrop != null) {
|
||||
child = _BackdropImage(
|
||||
key: ValueKey<String>(backdrop.primaryImageUrl),
|
||||
state: backdrop,
|
||||
imageHeaders: imageHeaders,
|
||||
);
|
||||
} else if (active) {
|
||||
child = const DecoratedBox(
|
||||
key: ValueKey<String>('__immersive_dark_fallback__'),
|
||||
decoration: BoxDecoration(gradient: _immersiveDarkFallback),
|
||||
);
|
||||
} else {
|
||||
child = ColoredBox(
|
||||
key: ValueKey<String>('__surface__${scheme.brightness.name}'),
|
||||
color: scheme.surface,
|
||||
);
|
||||
}
|
||||
|
||||
return AnimatedSwitcher(
|
||||
duration: _crossfade,
|
||||
switchInCurve: Curves.easeOut,
|
||||
switchOutCurve: Curves.easeOut,
|
||||
layoutBuilder: (currentChild, previousChildren) {
|
||||
final seen = <Key?>{if (currentChild != null) currentChild.key};
|
||||
final filtered = previousChildren.where((child) {
|
||||
if (seen.contains(child.key)) return false;
|
||||
seen.add(child.key);
|
||||
return true;
|
||||
}).toList();
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [...filtered, if (currentChild != null) currentChild],
|
||||
);
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _BackdropImage extends StatelessWidget {
|
||||
final ShellBackdropState state;
|
||||
final Map<String, String>? imageHeaders;
|
||||
|
||||
const _BackdropImage({
|
||||
super.key,
|
||||
required this.state,
|
||||
required this.imageHeaders,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final fallbackUrl = state.fallbackImageUrls.isNotEmpty
|
||||
? state.fallbackImageUrls.first
|
||||
: state.primaryImageUrl;
|
||||
final surface = Theme.of(context).colorScheme.surface;
|
||||
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
ImageFiltered(
|
||||
imageFilter: ImageFilter.blur(
|
||||
sigmaX: ShellBackdropLayer._blurSigma,
|
||||
sigmaY: ShellBackdropLayer._blurSigma,
|
||||
tileMode: TileMode.clamp,
|
||||
),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: state.primaryImageUrl,
|
||||
httpHeaders: imageHeaders,
|
||||
fit: BoxFit.cover,
|
||||
memCacheWidth: 800,
|
||||
fadeInDuration: const Duration(milliseconds: 200),
|
||||
placeholder: (_, _) => ColoredBox(color: surface),
|
||||
errorWidget: (_, _, _) => CachedNetworkImage(
|
||||
imageUrl: fallbackUrl,
|
||||
httpHeaders: imageHeaders,
|
||||
fit: BoxFit.cover,
|
||||
memCacheWidth: 800,
|
||||
placeholder: (_, _) => ColoredBox(color: surface),
|
||||
errorWidget: (_, _, _) => ColoredBox(color: surface),
|
||||
),
|
||||
),
|
||||
),
|
||||
const DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
stops: [0.0, 0.4, 1.0],
|
||||
colors: [Color(0x33000000), Color(0x59000000), Color(0xB3000000)],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user