mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-16 02:35:59 -07:00
chore: Improved performance for some widgets (#525)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
10bd34bb20
commit
07972ea5ee
16 changed files with 589 additions and 545 deletions
|
|
@ -5,13 +5,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:iconsax_plus/iconsax_plus.dart';
|
||||
|
||||
import 'package:fladder/models/item_base_model.dart';
|
||||
import 'package:fladder/screens/shared/flat_button.dart';
|
||||
import 'package:fladder/screens/shared/media/banner_play_button.dart';
|
||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||
import 'package:fladder/util/fladder_image.dart';
|
||||
import 'package:fladder/util/focus_provider.dart';
|
||||
import 'package:fladder/util/item_base_model/item_base_model_extensions.dart';
|
||||
import 'package:fladder/util/list_padding.dart';
|
||||
import 'package:fladder/util/themes_data.dart';
|
||||
import 'package:fladder/widgets/shared/ensure_visible.dart';
|
||||
import 'package:fladder/widgets/shared/item_actions.dart';
|
||||
import 'package:fladder/widgets/shared/modal_bottom_sheet.dart';
|
||||
|
||||
|
|
@ -64,148 +65,151 @@ class _CarouselBannerState extends ConsumerState<CarouselBanner> {
|
|||
itemExtent: itemExtent,
|
||||
children: [
|
||||
...widget.items.mapIndexed(
|
||||
(index, item) => LayoutBuilder(builder: (context, constraints) {
|
||||
final opacity = (constraints.maxWidth / maxExtent);
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
FladderImage(image: item.bannerImage),
|
||||
Opacity(
|
||||
opacity: opacity.clamp(0, 1),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.bottomLeft,
|
||||
end: Alignment.topCenter,
|
||||
colors: [
|
||||
ThemesData.of(context)
|
||||
.dark
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
.withValues(alpha: 0.85),
|
||||
Colors.transparent,
|
||||
],
|
||||
),
|
||||
(index, item) => LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final opacity = (constraints.maxWidth / maxExtent);
|
||||
return FocusButton(
|
||||
onTap: () => widget.items[index].navigateTo(context),
|
||||
onFocusChanged: (hover) {
|
||||
context.ensureVisible();
|
||||
},
|
||||
onLongPress: AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer
|
||||
? null
|
||||
: () {
|
||||
final poster = widget.items[index];
|
||||
showBottomSheetPill(
|
||||
context: context,
|
||||
item: poster,
|
||||
content: (scrollContext, scrollController) => ListView(
|
||||
shrinkWrap: true,
|
||||
controller: scrollController,
|
||||
children: poster
|
||||
.generateActions(context, ref)
|
||||
.listTileItems(scrollContext, useIcons: true),
|
||||
),
|
||||
);
|
||||
},
|
||||
onSecondaryTapDown: AdaptiveLayout.inputDeviceOf(context) == InputDevice.touch
|
||||
? null
|
||||
: (details) async {
|
||||
Offset localPosition = details.globalPosition;
|
||||
RelativeRect position = RelativeRect.fromLTRB(
|
||||
localPosition.dx, localPosition.dy, localPosition.dx, localPosition.dy);
|
||||
final poster = widget.items[index];
|
||||
|
||||
await showMenu(
|
||||
context: context,
|
||||
position: position,
|
||||
items: poster.generateActions(context, ref).popupMenuItems(useIcons: true),
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
FladderImage(image: item.bannerImage),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.bottomLeft,
|
||||
end: Alignment.topCenter,
|
||||
colors: [
|
||||
ThemesData.of(context)
|
||||
.dark
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
.withValues(alpha: opacity.clamp(0, 1)),
|
||||
Colors.transparent,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0).copyWith(right: constraints.maxWidth * 0.2),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.title,
|
||||
maxLines: 2,
|
||||
softWrap: item.title.length > 25,
|
||||
overflow: TextOverflow.fade,
|
||||
style:
|
||||
Theme.of(context).textTheme.headlineMedium?.copyWith(color: Colors.white),
|
||||
),
|
||||
if (item.label(context) != null || item.subText != null)
|
||||
Text(
|
||||
item.label(context) ?? item.subText ?? "",
|
||||
maxLines: 2,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(color: Colors.white),
|
||||
),
|
||||
].addInBetween(const SizedBox(height: 4)),
|
||||
),
|
||||
),
|
||||
),
|
||||
FlatButton(
|
||||
onTap: () => widget.items[index].navigateTo(context),
|
||||
onLongPress: AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer
|
||||
? null
|
||||
: () {
|
||||
final poster = widget.items[index];
|
||||
showBottomSheetPill(
|
||||
context: context,
|
||||
item: poster,
|
||||
content: (scrollContext, scrollController) => ListView(
|
||||
shrinkWrap: true,
|
||||
controller: scrollController,
|
||||
children: poster
|
||||
.generateActions(context, ref)
|
||||
.listTileItems(scrollContext, useIcons: true),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0).copyWith(right: constraints.maxWidth * 0.2),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.title,
|
||||
maxLines: 2,
|
||||
softWrap: item.title.length > 25,
|
||||
overflow: TextOverflow.fade,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headlineMedium
|
||||
?.copyWith(color: Colors.white),
|
||||
),
|
||||
);
|
||||
},
|
||||
onSecondaryTapDown: AdaptiveLayout.inputDeviceOf(context) == InputDevice.touch
|
||||
? null
|
||||
: (details) async {
|
||||
Offset localPosition = details.globalPosition;
|
||||
RelativeRect position = RelativeRect.fromLTRB(
|
||||
localPosition.dx, localPosition.dy, localPosition.dx, localPosition.dy);
|
||||
final poster = widget.items[index];
|
||||
|
||||
await showMenu(
|
||||
context: context,
|
||||
position: position,
|
||||
items: poster.generateActions(context, ref).popupMenuItems(useIcons: true),
|
||||
);
|
||||
},
|
||||
),
|
||||
ExcludeFocus(
|
||||
child: BannerPlayButton(item: widget.items[index]),
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.1),
|
||||
width: 1.0,
|
||||
if (item.label(context) != null || item.subText != null)
|
||||
Text(
|
||||
item.label(context) ?? item.subText ?? "",
|
||||
maxLines: 2,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.copyWith(color: Colors.white),
|
||||
),
|
||||
].addInBetween(const SizedBox(height: 4)),
|
||||
),
|
||||
borderRadius: border),
|
||||
),
|
||||
),
|
||||
),
|
||||
ExcludeFocus(
|
||||
child: BannerPlayButton(item: widget.items[index]),
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.white.withValues(alpha: 0.1),
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: border,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
if (AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer)
|
||||
AnimatedOpacity(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
opacity: showControls ? 1 : 0,
|
||||
child: IgnorePointer(
|
||||
ignoring: !showControls,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
IconButton.filledTonal(
|
||||
onPressed: () {
|
||||
final currentPos = carouselController.position;
|
||||
carouselController.animateTo(currentPos.pixels - itemExtent,
|
||||
curve: Curves.easeInOutCubic, duration: const Duration(milliseconds: 250));
|
||||
},
|
||||
icon: const Icon(IconsaxPlusLinear.arrow_left_1),
|
||||
),
|
||||
IconButton.filledTonal(
|
||||
onPressed: () {
|
||||
final currentPos = carouselController.position;
|
||||
carouselController.animateTo(currentPos.pixels + itemExtent,
|
||||
curve: Curves.easeInOutCubic, duration: const Duration(milliseconds: 250));
|
||||
},
|
||||
icon: const Icon(IconsaxPlusLinear.arrow_right_3),
|
||||
),
|
||||
],
|
||||
ExcludeFocus(
|
||||
child: AnimatedOpacity(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
opacity: showControls ? 1 : 0,
|
||||
child: IgnorePointer(
|
||||
ignoring: !showControls,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
IconButton.filledTonal(
|
||||
onPressed: () {
|
||||
final currentPos = carouselController.position;
|
||||
carouselController.animateTo(currentPos.pixels - itemExtent,
|
||||
curve: Curves.easeInOutCubic, duration: const Duration(milliseconds: 250));
|
||||
},
|
||||
icon: const Icon(IconsaxPlusLinear.arrow_left_1),
|
||||
),
|
||||
IconButton.filledTonal(
|
||||
onPressed: () {
|
||||
final currentPos = carouselController.position;
|
||||
carouselController.animateTo(currentPos.pixels + itemExtent,
|
||||
curve: Curves.easeInOutCubic, duration: const Duration(milliseconds: 250));
|
||||
},
|
||||
icon: const Icon(IconsaxPlusLinear.arrow_right_3),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue