artist + album search
This commit is contained in:
parent
d90e323d82
commit
c6b0bc4581
4 changed files with 72 additions and 12 deletions
|
@ -2,12 +2,18 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../../domain/entities/album.dart';
|
||||
import '../../domain/entities/artist.dart';
|
||||
import '../../domain/entities/song.dart';
|
||||
import '../state/audio_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
import '../state/search_page_store.dart';
|
||||
import '../theming.dart';
|
||||
import '../widgets/album_art_list_tile.dart';
|
||||
import '../widgets/song_bottom_sheet.dart';
|
||||
import '../widgets/song_list_tile.dart';
|
||||
import 'album_details_page.dart';
|
||||
import 'artist_details_page.dart';
|
||||
|
||||
class SearchPage extends StatefulWidget {
|
||||
const SearchPage({Key? key}) : super(key: key);
|
||||
|
@ -23,6 +29,7 @@ class _SearchPageState extends State<SearchPage> {
|
|||
|
||||
final searchStore = GetIt.I<SearchPageStore>();
|
||||
final audioStore = GetIt.I<AudioStore>();
|
||||
final navStore = GetIt.I<NavigationStore>();
|
||||
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
|
@ -40,11 +47,12 @@ class _SearchPageState extends State<SearchPage> {
|
|||
hintStyle: TEXT_HEADER.copyWith(color: Colors.white),
|
||||
fillColor: Colors.white10,
|
||||
filled: true,
|
||||
enabledBorder: const OutlineInputBorder(borderSide: BorderSide.none, gapPadding: 0.0),
|
||||
focusedBorder: const OutlineInputBorder(borderSide: BorderSide.none, gapPadding: 0.0),
|
||||
enabledBorder:
|
||||
const OutlineInputBorder(borderSide: BorderSide.none, gapPadding: 0.0),
|
||||
focusedBorder:
|
||||
const OutlineInputBorder(borderSide: BorderSide.none, gapPadding: 0.0),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
|
||||
),
|
||||
|
||||
onChanged: (text) {
|
||||
searchStore.search(text);
|
||||
},
|
||||
|
@ -64,6 +72,36 @@ class _SearchPageState extends State<SearchPage> {
|
|||
onTap: () => audioStore.playSong(0, [song]),
|
||||
onTapMore: () => SongBottomSheet()(song, context),
|
||||
);
|
||||
} else if (results[index] is Album) {
|
||||
final album = results[index] as Album;
|
||||
return AlbumArtListTile(
|
||||
title: album.title,
|
||||
subtitle: album.artist,
|
||||
albumArtPath: album.albumArtPath,
|
||||
onTap: () {
|
||||
navStore.pushOnLibrary(
|
||||
MaterialPageRoute<Widget>(
|
||||
builder: (BuildContext context) => AlbumDetailsPage(
|
||||
album: album,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else if (results[index] is Artist) {
|
||||
final artist = results[index] as Artist;
|
||||
return ListTile(
|
||||
title: Text(artist.name),
|
||||
onTap: () {
|
||||
navStore.pushOnLibrary(
|
||||
MaterialPageRoute<Widget>(
|
||||
builder: (BuildContext context) => ArtistDetailsPage(
|
||||
artist: artist,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
|
|
|
@ -303,10 +303,22 @@ class MusicDataDao extends DatabaseAccessor<MoorDatabase>
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List> search(String searchText) {
|
||||
print('Search: $searchText');
|
||||
Future<List> search(String searchText, {int limit = 0}) async {
|
||||
List<dynamic> result = [];
|
||||
|
||||
return (select(songs)..where((tbl) => tbl.title.like(searchText))).get().then(
|
||||
(moorSongList) => moorSongList.map((moorSong) => SongModel.fromMoor(moorSong)).toList());
|
||||
result += await (select(artists)..where((tbl) => tbl.name.like(searchText))).get().then(
|
||||
(moorList) => moorList.map((moorArtist) => ArtistModel.fromMoor(moorArtist)).toList(),
|
||||
);
|
||||
|
||||
result += await (select(albums)..where((tbl) => tbl.title.like(searchText))).get().then(
|
||||
(moorList) => moorList.map((moorAlbum) => AlbumModel.fromMoor(moorAlbum)).toList(),
|
||||
);
|
||||
|
||||
result += await (select(songs)..where((tbl) => tbl.title.like(searchText))).get().then(
|
||||
(moorList) => moorList.map((moorSong) => SongModel.fromMoor(moorSong)).toList(),
|
||||
);
|
||||
|
||||
if (limit <= 0) return result;
|
||||
return result.take(limit).toList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,5 +44,5 @@ abstract class MusicDataSource {
|
|||
Future<void> setAlbumOfDay(AlbumOfDay albumOfDay);
|
||||
Future<AlbumOfDay?> getAlbumOfDay();
|
||||
|
||||
Future<List> search(String searchText);
|
||||
Future<List> search(String searchText, {int limit});
|
||||
}
|
||||
|
|
|
@ -230,15 +230,19 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
|||
Future<List> search(String searchText) async {
|
||||
if (searchText == '') return [];
|
||||
|
||||
final searchTextLower = searchText.toLowerCase();
|
||||
|
||||
// TODO: need to clean the string? sql injection?
|
||||
final dbResult = await _musicDataSource.search(_fuzzy(searchText));
|
||||
print(dbResult.length);
|
||||
final dbResult = await _musicDataSource.search(_fuzzy(searchTextLower), limit: 200);
|
||||
|
||||
final List<List> ratedResults = [];
|
||||
for (final x in dbResult) {
|
||||
if (x is SongModel) {
|
||||
// print('${x.title}: ${x.title.similarityTo(searchText)}');
|
||||
ratedResults.add([x.title.similarityTo(searchText), x]);
|
||||
ratedResults.add([_similarity(x.title.toLowerCase(), searchTextLower), x]);
|
||||
} else if (x is AlbumModel) {
|
||||
ratedResults.add([_similarity(x.title.toLowerCase(), searchTextLower), x]);
|
||||
} else if (x is ArtistModel) {
|
||||
ratedResults.add([_similarity(x.name.toLowerCase(), searchTextLower), x]);
|
||||
}
|
||||
}
|
||||
ratedResults.sort((List a, List b) => -(a[0] as double).compareTo(b[0] as double));
|
||||
|
@ -247,6 +251,12 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
|||
return results.toList();
|
||||
}
|
||||
|
||||
double _similarity(String value, String searchText) {
|
||||
return value.startsWith(searchText)
|
||||
? value.similarityTo(searchText) + 1
|
||||
: value.similarityTo(searchText);
|
||||
}
|
||||
|
||||
String _fuzzy(String text) {
|
||||
String fuzzyText = '%$text%';
|
||||
// for (final c in text.toLowerCase().replaceAll(' ', '').split('')) {
|
||||
|
|
Loading…
Add table
Reference in a new issue