Drops dead code across services, models, utils and widgets, including the connection auth service, which had no implementer, and the Live TV DVR provisioning models, which had no caller. Tests that only covered deleted behaviour are removed or trimmed. No behaviour change.
126 lines
3.4 KiB
Dart
126 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:plezy/widgets/app_icon.dart';
|
|
import 'package:material_symbols_icons/symbols.dart';
|
|
import '../../../i18n/strings.g.dart';
|
|
import '../../../theme/mono_tokens.dart';
|
|
import '../../../utils/track_label_builder.dart';
|
|
import '../../../widgets/focusable_list_tile.dart';
|
|
|
|
class TrackSelectionHelper {
|
|
static Widget buildOffTile<T>({
|
|
required BuildContext context,
|
|
required bool isSelected,
|
|
required VoidCallback onTap,
|
|
Key? key,
|
|
FocusNode? focusNode,
|
|
VoidCallback? onLongPress,
|
|
VoidCallback? onSecondaryTap,
|
|
Widget? badge,
|
|
}) {
|
|
return _buildSelectableTile(
|
|
context: context,
|
|
key: key,
|
|
label: t.common.off,
|
|
isSelected: isSelected,
|
|
onTap: onTap,
|
|
focusNode: focusNode,
|
|
onLongPress: onLongPress,
|
|
onSecondaryTap: onSecondaryTap,
|
|
badge: badge,
|
|
);
|
|
}
|
|
|
|
static Widget buildTrackTile<T>({
|
|
required BuildContext context,
|
|
required TrackLabel label,
|
|
required bool isSelected,
|
|
required VoidCallback onTap,
|
|
Key? key,
|
|
FocusNode? focusNode,
|
|
VoidCallback? onLongPress,
|
|
VoidCallback? onSecondaryTap,
|
|
Widget? badge,
|
|
}) {
|
|
return _buildSelectableTile(
|
|
context: context,
|
|
key: key,
|
|
label: label.primary,
|
|
secondaryLabel: label.secondary,
|
|
isSelected: isSelected,
|
|
onTap: onTap,
|
|
focusNode: focusNode,
|
|
onLongPress: onLongPress,
|
|
onSecondaryTap: onSecondaryTap,
|
|
badge: badge,
|
|
);
|
|
}
|
|
|
|
/// Build a numbered badge for primary/secondary subtitle indicators.
|
|
static Widget buildTrackBadge(BuildContext context, int number) {
|
|
final colorScheme = Theme.of(context).colorScheme;
|
|
return Container(
|
|
width: 18,
|
|
height: 18,
|
|
decoration: BoxDecoration(color: colorScheme.primary, borderRadius: BorderRadius.circular(4)),
|
|
alignment: .center,
|
|
child: Text(
|
|
number.toString(),
|
|
style: TextStyle(color: colorScheme.onPrimary, fontSize: 11, fontWeight: .bold),
|
|
),
|
|
);
|
|
}
|
|
|
|
static Widget _buildSelectableTile({
|
|
required BuildContext context,
|
|
required String label,
|
|
required bool isSelected,
|
|
required VoidCallback onTap,
|
|
String? secondaryLabel,
|
|
Key? key,
|
|
FocusNode? focusNode,
|
|
VoidCallback? onLongPress,
|
|
VoidCallback? onSecondaryTap,
|
|
Widget? badge,
|
|
}) {
|
|
final primaryColor = Theme.of(context).colorScheme.primary;
|
|
Widget? trailing;
|
|
if (badge != null) {
|
|
trailing = badge;
|
|
} else if (isSelected) {
|
|
trailing = AppIcon(Symbols.check_rounded, fill: 1, color: primaryColor);
|
|
}
|
|
|
|
Widget tile = FocusableListTile(
|
|
key: key,
|
|
focusNode: focusNode,
|
|
selected: isSelected,
|
|
title: Text(
|
|
label,
|
|
style: TextStyle(color: isSelected ? primaryColor : null),
|
|
maxLines: 1,
|
|
overflow: .ellipsis,
|
|
),
|
|
subtitle: secondaryLabel == null
|
|
? null
|
|
: Text(
|
|
secondaryLabel,
|
|
style: TextStyle(
|
|
color: isSelected ? primaryColor.withValues(alpha: 0.7) : tokens(context).textMuted,
|
|
fontSize: 12,
|
|
),
|
|
maxLines: 1,
|
|
overflow: .ellipsis,
|
|
),
|
|
trailing: trailing,
|
|
onTap: onTap,
|
|
onLongPress: onLongPress,
|
|
);
|
|
|
|
if (onSecondaryTap != null) {
|
|
tile = GestureDetector(onSecondaryTap: onSecondaryTap, child: tile);
|
|
}
|
|
|
|
return tile;
|
|
}
|
|
}
|