mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
refactor: use shadcn for TrackTile
This commit is contained in:
parent
e54a646073
commit
88906098dd
@ -1,4 +1,3 @@
|
||||
import 'package:flutter/material.dart' show ListTile;
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
@ -21,9 +20,6 @@ class TrackPresentation extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final headerTextStyle = context.theme.typography.small.copyWith(
|
||||
color: context.theme.colorScheme.mutedForeground,
|
||||
);
|
||||
final scrollController = useScrollController();
|
||||
final focusNode = useFocusNode();
|
||||
final scale = context.theme.scaling;
|
||||
@ -66,10 +62,11 @@ class TrackPresentation extends HookConsumerWidget {
|
||||
TrackPresentationModifiersSection(
|
||||
focusNode: focusNode,
|
||||
),
|
||||
ListTile(
|
||||
titleTextStyle: headerTextStyle,
|
||||
subtitleTextStyle: headerTextStyle,
|
||||
leadingAndTrailingTextStyle: headerTextStyle,
|
||||
Basic(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16,
|
||||
),
|
||||
leading: constrains.mdAndUp ? const Text(" #") : null,
|
||||
title: Row(
|
||||
children: [
|
||||
@ -85,7 +82,7 @@ class TrackPresentation extends HookConsumerWidget {
|
||||
Text(context.l10n.duration),
|
||||
],
|
||||
),
|
||||
),
|
||||
).small().muted(),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -32,7 +32,11 @@ Future<void> Function(Track track, int index) useTrackTilePlayCallback(
|
||||
ref.read(presentationStateProvider(options.collection).notifier);
|
||||
|
||||
if (state.selectedTracks.isNotEmpty) {
|
||||
if (state.selectedTracks.contains(track)) {
|
||||
notifier.deselectTrack(track);
|
||||
} else {
|
||||
notifier.selectTrack(track);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart' show ListTile, Material, MaterialType;
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
@ -14,7 +14,9 @@ import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/components/links/artist_link.dart';
|
||||
import 'package:spotube/components/links/link_text.dart';
|
||||
import 'package:spotube/components/track_tile/track_options.dart';
|
||||
import 'package:spotube/components/ui/button_tile.dart';
|
||||
import 'package:spotube/extensions/artist_simple.dart';
|
||||
import 'package:spotube/extensions/button_variance.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/duration.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
@ -89,13 +91,10 @@ class TrackTile extends HookConsumerWidget {
|
||||
},
|
||||
child: HoverBuilder(
|
||||
permanentState: isSelected || constrains.smAndDown ? true : null,
|
||||
builder: (context, isHovering) => Material(
|
||||
type: MaterialType.transparency,
|
||||
child: ListTile(
|
||||
selectedColor: theme.colorScheme.primary,
|
||||
selectedTileColor: theme.colorScheme.primary.withOpacity(0.1),
|
||||
builder: (context, isHovering) => ButtonTile(
|
||||
selected: isSelected,
|
||||
onTap: () async {
|
||||
onPressed: () async {
|
||||
if (isBlackListed) return;
|
||||
try {
|
||||
isLoading.value = true;
|
||||
await onTap?.call();
|
||||
@ -106,18 +105,12 @@ class TrackTile extends HookConsumerWidget {
|
||||
}
|
||||
},
|
||||
onLongPress: onLongPress,
|
||||
enabled: !isBlackListed,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
tileColor: isBlackListed ? theme.colorScheme.destructive : null,
|
||||
horizontalTitleGap: 12,
|
||||
leadingAndTrailingTextStyle: theme.typography.normal.copyWith(
|
||||
color: theme.colorScheme.foreground,
|
||||
),
|
||||
titleTextStyle: theme.typography.normal.copyWith(
|
||||
color: theme.colorScheme.foreground,
|
||||
),
|
||||
subtitleTextStyle: theme.typography.xSmall.copyWith(
|
||||
color: theme.colorScheme.mutedForeground,
|
||||
style: (isBlackListed
|
||||
? ButtonVariance.destructive
|
||||
: ButtonVariance.ghost)
|
||||
.copyWith(
|
||||
padding: (context, states) =>
|
||||
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
|
||||
),
|
||||
leading: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@ -140,8 +133,7 @@ class TrackTile extends HookConsumerWidget {
|
||||
: SizedBox(
|
||||
width: 50,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 6),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
child: Text(
|
||||
'${(index ?? 0) + 1}',
|
||||
maxLines: 1,
|
||||
@ -174,7 +166,7 @@ class TrackTile extends HookConsumerWidget {
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: theme.borderRadiusMd,
|
||||
color: isHovering
|
||||
? Colors.black.withOpacity(0.4)
|
||||
? Colors.black.withAlpha(102)
|
||||
: Colors.transparent,
|
||||
),
|
||||
),
|
||||
@ -200,8 +192,8 @@ class TrackTile extends HookConsumerWidget {
|
||||
const SizedBox(
|
||||
width: 26,
|
||||
height: 26,
|
||||
child: CircularProgressIndicator(
|
||||
size: 1.5),
|
||||
child:
|
||||
CircularProgressIndicator(size: 1.5),
|
||||
),
|
||||
(_, _, true, _, _) => Icon(
|
||||
SpotubeIcons.pause,
|
||||
@ -233,13 +225,31 @@ class TrackTile extends HookConsumerWidget {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
_ => LinkText(
|
||||
_ => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Button(
|
||||
style: ButtonVariance.link.copyWith(
|
||||
padding: (context, states) => EdgeInsets.zero,
|
||||
),
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
TrackPage.name,
|
||||
pathParameters: {
|
||||
"id": track.id!,
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
track.name!,
|
||||
"/track/${track.id}",
|
||||
push: true,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
),
|
||||
if (constrains.mdAndUp) ...[
|
||||
@ -310,7 +320,6 @@ class TrackTile extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ class ButtonTile extends StatelessWidget {
|
||||
final Widget? leading;
|
||||
final Widget? trailing;
|
||||
final bool enabled;
|
||||
final void Function()? onPressed;
|
||||
final VoidCallback? onPressed;
|
||||
final VoidCallback? onLongPress;
|
||||
final bool selected;
|
||||
final ButtonVariance style;
|
||||
final EdgeInsets? padding;
|
||||
@ -19,6 +20,7 @@ class ButtonTile extends StatelessWidget {
|
||||
this.trailing,
|
||||
this.enabled = true,
|
||||
this.onPressed,
|
||||
this.onLongPress,
|
||||
this.selected = false,
|
||||
this.padding,
|
||||
this.style = ButtonVariance.outline,
|
||||
@ -28,13 +30,17 @@ class ButtonTile extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData(:colorScheme, :typography) = Theme.of(context);
|
||||
|
||||
return Button(
|
||||
return GestureDetector(
|
||||
onLongPress: onLongPress,
|
||||
child: Button(
|
||||
enabled: enabled,
|
||||
onPressed: onPressed,
|
||||
style: style.copyWith(
|
||||
padding: padding != null ? (context, states, value) => padding! : null,
|
||||
padding:
|
||||
padding != null ? (context, states, value) => padding! : null,
|
||||
decoration: (context, states, value) {
|
||||
final decoration = style.decoration(context, states) as BoxDecoration;
|
||||
final decoration =
|
||||
style.decoration(context, states) as BoxDecoration;
|
||||
|
||||
if (selected) {
|
||||
return switch (style) {
|
||||
@ -97,6 +103,7 @@ class ButtonTile extends StatelessWidget {
|
||||
trailing: trailing,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
21
lib/extensions/button_variance.dart
Normal file
21
lib/extensions/button_variance.dart
Normal file
@ -0,0 +1,21 @@
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
|
||||
extension CopyWithButtonVarianceExtension on ButtonVariance {
|
||||
ButtonVariance copyWith({
|
||||
ButtonStateProperty<EdgeInsets>? padding,
|
||||
ButtonStateProperty<Decoration>? decoration,
|
||||
ButtonStateProperty<MouseCursor>? mouseCursor,
|
||||
ButtonStateProperty<IconThemeData>? iconTheme,
|
||||
ButtonStateProperty<EdgeInsets>? margin,
|
||||
ButtonStateProperty<TextStyle>? textStyle,
|
||||
}) {
|
||||
return ButtonVariance(
|
||||
padding: padding ?? this.padding,
|
||||
decoration: decoration ?? this.decoration,
|
||||
mouseCursor: mouseCursor ?? this.mouseCursor,
|
||||
iconTheme: iconTheme ?? this.iconTheme,
|
||||
margin: margin ?? this.margin,
|
||||
textStyle: textStyle ?? this.textStyle,
|
||||
);
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ class HomeGenresSection extends HookConsumerWidget {
|
||||
|
||||
useEffect(() {
|
||||
int times = 0;
|
||||
Timer.periodic(
|
||||
final timer = Timer.periodic(
|
||||
const Duration(seconds: 5),
|
||||
(timer) {
|
||||
if (times > 5 || interactedRef.value) {
|
||||
@ -57,7 +57,10 @@ class HomeGenresSection extends HookConsumerWidget {
|
||||
},
|
||||
);
|
||||
|
||||
return controller.dispose;
|
||||
return () {
|
||||
timer.cancel();
|
||||
controller.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return SliverList.list(
|
||||
|
Loading…
Reference in New Issue
Block a user