veilidchat/lib/theme/views/styled_widgets/styled_slide_tile.dart
2025-05-25 23:40:52 -04:00

145 lines
5.5 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import '../../theme.dart';
class SlideTileAction {
const SlideTileAction({
required this.actionScale,
required this.onPressed,
this.key,
this.icon,
this.label,
});
final Key? key;
final ScaleKind actionScale;
final String? label;
final IconData? icon;
final SlidableActionCallback? onPressed;
}
class StyledSlideTile extends StatelessWidget {
const StyledSlideTile(
{required this.disabled,
required this.selected,
required this.tileScale,
required this.title,
this.subtitle = '',
this.endActions = const [],
this.startActions = const [],
this.onTap,
this.onDoubleTap,
this.leading,
this.trailing,
super.key});
final bool disabled;
final bool selected;
final ScaleKind tileScale;
final List<SlideTileAction> endActions;
final List<SlideTileAction> startActions;
final GestureTapCallback? onTap;
final GestureTapCallback? onDoubleTap;
final Widget? leading;
final Widget? trailing;
final String title;
final String subtitle;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty<bool>('disabled', disabled))
..add(DiagnosticsProperty<bool>('selected', selected))
..add(DiagnosticsProperty<ScaleKind>('tileScale', tileScale))
..add(IterableProperty<SlideTileAction>('endActions', endActions))
..add(IterableProperty<SlideTileAction>('startActions', startActions))
..add(ObjectFlagProperty<GestureTapCallback?>.has('onTap', onTap))
..add(DiagnosticsProperty<Widget?>('leading', leading))
..add(StringProperty('title', title))
..add(StringProperty('subtitle', subtitle))
..add(ObjectFlagProperty<GestureTapCallback?>.has(
'onDoubleTap', onDoubleTap))
..add(DiagnosticsProperty<Widget?>('trailing', trailing));
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scaleTheme = theme.extension<ScaleTheme>()!;
final scaleTileTheme = scaleTheme.tileTheme(
disabled: disabled, selected: selected, scaleKind: tileScale);
return Container(
clipBehavior: Clip.antiAlias,
decoration: ShapeDecoration(
color: scaleTileTheme.backgroundColor,
shape: scaleTileTheme.shapeBorder),
child: Slidable(
// Specify a key if the Slidable is dismissible.
key: key,
endActionPane: endActions.isEmpty
? null
: ActionPane(
motion: const DrawerMotion(),
children: endActions.map((a) {
final scaleActionTheme = scaleTheme.tileTheme(
disabled: disabled,
selected: true,
scaleKind: a.actionScale);
return SlidableAction(
onPressed: disabled ? null : a.onPressed,
backgroundColor: scaleActionTheme.backgroundColor,
foregroundColor: scaleActionTheme.textColor,
icon: subtitle.isEmpty ? a.icon : null,
label: a.label,
padding: const EdgeInsets.all(2).scaled(context),
);
}).toList()),
startActionPane: startActions.isEmpty
? null
: ActionPane(
motion: const DrawerMotion(),
children: startActions.map((a) {
final scaleActionTheme = scaleTheme.tileTheme(
disabled: disabled,
selected: true,
scaleKind: a.actionScale);
return SlidableAction(
onPressed: disabled ? null : a.onPressed,
backgroundColor: scaleActionTheme.backgroundColor,
foregroundColor: scaleActionTheme.textColor,
icon: subtitle.isEmpty ? a.icon : null,
label: a.label,
padding: const EdgeInsets.all(2).scaled(context),
);
}).toList()),
child: Padding(
padding: scaleTheme.config.useVisualIndicators
? EdgeInsets.zero
: const EdgeInsets.fromLTRB(0, 2, 0, 2).scaled(context),
child: GestureDetector(
onDoubleTap: onDoubleTap,
child: ListTile(
onTap: onTap,
dense: true,
title: Text(
title,
overflow: TextOverflow.fade,
softWrap: false,
),
subtitle: subtitle.isNotEmpty ? Text(subtitle) : null,
contentPadding: const EdgeInsets.fromLTRB(8, 4, 8, 4)
.scaled(context),
iconColor: scaleTileTheme.textColor,
textColor: scaleTileTheme.textColor,
leading:
leading != null ? FittedBox(child: leading) : null,
trailing: trailing != null
? FittedBox(child: trailing)
: null)))));
}
}