mobile-music/lib/screens/search_screen.dart
2026-07-29 16:22:00 -04:00

119 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../state/providers.dart';
import '../theme/tokens.dart';
import 'browser_screen.dart';
/// Search — `search3` across artists / albums / songs.
class SearchScreen extends ConsumerStatefulWidget {
const SearchScreen({super.key});
@override
ConsumerState<SearchScreen> createState() => _SearchScreenState();
}
class _SearchScreenState extends ConsumerState<SearchScreen> {
final _controller = TextEditingController();
String _query = '';
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final accent = Theme.of(context).colorScheme.primary;
return Scaffold(
appBar: AppBar(
title: TextField(
controller: _controller,
autofocus: true,
textInputAction: TextInputAction.search,
style: const TextStyle(color: TimbreColors.foreground),
cursorColor: accent,
decoration: const InputDecoration(
hintText: 'Search artists, albums, songs…',
hintStyle: TextStyle(color: TimbreColors.dimmed),
border: InputBorder.none,
),
onSubmitted: (v) => setState(() => _query = v),
),
),
body: SafeArea(
child: _query.trim().isEmpty
? const Center(
child: Text('Type and press search.',
style: TextStyle(color: TimbreColors.dimmed)),
)
: _Results(query: _query),
),
);
}
}
class _Results extends ConsumerWidget {
const _Results({required this.query});
final String query;
@override
Widget build(BuildContext context, WidgetRef ref) {
final results = ref.watch(searchProvider(query));
return results.when(
loading: () => const Center(
child: SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(strokeWidth: 2),
),
),
error: (e, _) => Center(
child: Text('$e', style: const TextStyle(color: TimbreColors.dimmed)),
),
data: (r) {
if (r.artists.isEmpty && r.albums.isEmpty && r.songs.isEmpty) {
return const Center(
child: Text('No results.',
style: TextStyle(color: TimbreColors.dimmed)),
);
}
return ListView(
children: [
for (final a in r.artists)
BrowseRow(
title: a.name ?? 'Unknown artist',
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_) => ArtistScreen(id: a.id)),
),
),
for (final a in r.albums)
BrowseRow(
title: a.name ?? 'Unknown album',
trailing: a.artist,
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_) => AlbumScreen(id: a.id)),
),
),
for (var i = 0; i < r.songs.length; i++)
BrowseRow(
title: r.songs[i].title ?? 'Untitled',
trailing: r.songs[i].artist,
onTap: () => ref
.read(playbackProvider.notifier)
.playSongs(r.songs, startIndex: i),
onPlayNext: () => ref
.read(playbackProvider.notifier)
.playNext(r.songs[i]),
onAddToQueue: () => ref
.read(playbackProvider.notifier)
.addToQueue(r.songs[i]),
),
],
);
},
);
}
}