Skip to content

Commit

Permalink
chore: better search for track replace dialog
Browse files Browse the repository at this point in the history
after importing lastfm/yt history & when replacing history track
  • Loading branch information
MSOB7YY committed May 22, 2024
1 parent a8932c0 commit 6b4c591
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 67 deletions.
54 changes: 31 additions & 23 deletions lib/controller/search_sort_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,32 +198,38 @@ class SearchSortController {
}
},
isolateFunction: (itemsSendPort) async {
final params = {
'tracks': Indexer.inst.allTracksMappedByPath.values
.map((e) => {
'title': e.title,
'artist': e.originalArtist,
'album': e.album,
'albumArtist': e.albumArtist,
'genre': e.originalGenre,
'composer': e.composer,
'year': e.year,
'comment': e.comment,
'path': e.path,
})
.toList(),
'artistsSplitConfig': ArtistsSplitConfig.settings().toMap(),
'genresSplitConfig': GenresSplitConfig.settings().toMap(),
'filters': settings.trackSearchFilter.cast<TrackSearchFilter>(),
'cleanup': _shouldCleanup,
'sendPort': itemsSendPort,
};

await Isolate.spawn(_searchTracksIsolate, params);
final params = generateTrackSearchIsolateParams(itemsSendPort);
await Isolate.spawn(searchTracksIsolate, params);
},
);
}

Map<String, dynamic> generateTrackSearchIsolateParams(SendPort sendPort, {bool sendPrepared = false}) {
final params = {
'tracks': Indexer.inst.allTracksMappedByPath.values
.map((e) => {
'title': e.title,
'artist': e.originalArtist,
'album': e.album,
'albumArtist': e.albumArtist,
'genre': e.originalGenre,
'composer': e.composer,
'year': e.year,
'comment': e.comment,
'path': e.path,
})
.toList(),
'artistsSplitConfig': ArtistsSplitConfig.settings().toMap(),
'genresSplitConfig': GenresSplitConfig.settings().toMap(),
// ignore: invalid_use_of_protected_member
'filters': settings.trackSearchFilter.value,
'cleanup': _shouldCleanup,
'sendPrepared': sendPrepared,
'sendPort': sendPort,
};
return params;
}

Future<SendPort> _preparePlaylistPorts() async {
return await SearchPortsProvider.inst.preparePorts(
type: MediaType.playlist,
Expand Down Expand Up @@ -306,12 +312,13 @@ class SearchSortController {
});
}

static void _searchTracksIsolate(Map params) {
static void searchTracksIsolate(Map params) {
final tracks = params['tracks'] as List<Map>;
final artistsSplitConfig = ArtistsSplitConfig.fromMap(params['artistsSplitConfig']);
final genresSplitConfig = GenresSplitConfig.fromMap(params['genresSplitConfig']);
final tsf = params['filters'] as List<TrackSearchFilter>;
final cleanup = params['cleanup'] as bool;
final sendPrepared = params['sendPrepared'] as bool?;
final sendPort = params['sendPort'] as SendPort;

final receivePort = ReceivePort();
Expand Down Expand Up @@ -415,6 +422,7 @@ class SearchSortController {

sendPort.send((result, temp, text));
});
if (sendPrepared == true) sendPort.send(null);
}

void _searchMediaType({required MediaType type, required String text, bool temp = false}) async {
Expand Down
143 changes: 100 additions & 43 deletions lib/ui/dialogs/track_advanced_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'dart:io';
import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'package:namida/base/ports_provider.dart';
import 'package:namida/class/color_m.dart';
import 'package:namida/class/track.dart';
import 'package:namida/controller/current_color.dart';
Expand All @@ -11,8 +13,10 @@ import 'package:namida/controller/history_controller.dart';
import 'package:namida/controller/indexer_controller.dart';
import 'package:namida/controller/namida_channel.dart';
import 'package:namida/controller/navigator_controller.dart';
import 'package:namida/controller/search_sort_controller.dart';
import 'package:namida/controller/settings_controller.dart';
import 'package:namida/core/constants.dart';
import 'package:namida/core/dimensions.dart';
import 'package:namida/core/enums.dart';
import 'package:namida/core/extensions.dart';
import 'package:namida/core/icon_fonts/broken_icons.dart';
Expand Down Expand Up @@ -514,8 +518,10 @@ void showLibraryTracksChooseDialog({
String trackName = '',
Color? colorScheme,
}) async {
final allTracksList = List<Track>.from(allTracksInLibrary).obs;
final allTracksListBase = List<Track>.from(allTracksInLibrary);
final allTracksList = allTracksListBase.obs;
final selectedTrack = Rxn<Track>();
final isSearching = false.obs;
void onTrackTap(Track tr) {
if (selectedTrack.value == tr) {
selectedTrack.value = null;
Expand All @@ -525,14 +531,24 @@ void showLibraryTracksChooseDialog({
}

final searchController = TextEditingController();
final scrollController = ScrollController();
final focusNode = FocusNode();
final searchManager = _TracksSearchTemp(
(tracks) {
allTracksList.value = tracks;
isSearching.value = false;
},
);

await NamidaNavigator.inst.navigateDialog(
onDisposing: () {
allTracksList.close();
selectedTrack.close();
isSearching.close();
searchController.dispose();
scrollController.dispose();
focusNode.dispose();
searchManager.dispose();
},
colorScheme: colorScheme,
dialogBuilder: (theme) => CustomBlurryDialog(
Expand All @@ -552,7 +568,7 @@ void showLibraryTracksChooseDialog({
],
child: SizedBox(
width: Get.width,
height: Get.height * 0.6,
height: Get.height * 0.7,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expand All @@ -567,59 +583,75 @@ void showLibraryTracksChooseDialog({
textFieldController: searchController,
textFieldHintText: lang.SEARCH,
onTextFieldValueChanged: (value) {
final matched = allTracksInLibrary.where((element) {
final titleMatch = element.title.cleanUpForComparison.contains(value);
final artistMatch = element.originalArtist.cleanUpForComparison.contains(value);
final albumMatch = element.album.cleanUpForComparison.contains(value);
return titleMatch || artistMatch || albumMatch;
});
allTracksList.value = matched.toList();
if (value.isEmpty) {
allTracksList.value = allTracksListBase;
} else {
isSearching.value = true;
searchManager.search(value);
}
},
),
),
const SizedBox(width: 8.0),
NamidaIconButton(
icon: Broken.close_circle,
onPressed: () {
allTracksList
..clear()
..addAll(allTracksInLibrary);
searchController.clear();
},
Stack(
alignment: Alignment.center,
children: [
NamidaIconButton(
icon: Broken.close_circle,
onPressed: () {
allTracksList.value = allTracksListBase;
searchController.clear();
},
),
Obx(
() => isSearching.value
? const CircularProgressIndicator.adaptive(
strokeWidth: 2.0,
strokeCap: StrokeCap.round,
)
: const SizedBox(),
),
],
)
],
),
),
const SizedBox(height: 8.0),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
trackName,
style: Get.textTheme.displayMedium,
if (trackName != '')
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
trackName,
style: Get.textTheme.displayMedium,
),
),
),
const SizedBox(height: 8.0),
if (trackName != '') const SizedBox(height: 8.0),
Expanded(
child: Obx(
() => ListView.builder(
padding: EdgeInsets.zero,
itemCount: allTracksList.length,
itemBuilder: (context, i) {
final tr = allTracksList[i];
return Obx(
() => TrackTile(
trackOrTwd: tr,
index: i,
queueSource: QueueSource.playlist,
onTap: () => onTrackTap(tr),
onRightAreaTap: () => onTrackTap(tr),
trailingWidget: NamidaCheckMark(
size: 22.0,
active: selectedTrack.value == tr,
child: NamidaScrollbar(
controller: scrollController,
child: Obx(
() => ListView.builder(
controller: scrollController,
padding: EdgeInsets.zero,
itemCount: allTracksList.length,
itemExtent: Dimensions.inst.trackTileItemExtent,
itemBuilder: (context, i) {
final tr = allTracksList[i];
return Obx(
() => TrackTile(
trackOrTwd: tr,
index: i,
queueSource: QueueSource.playlist,
onTap: () => onTrackTap(tr),
onRightAreaTap: () => onTrackTap(tr),
trailingWidget: NamidaCheckMark(
size: 22.0,
active: selectedTrack.value == tr,
),
),
),
);
},
);
},
),
),
),
),
Expand All @@ -629,3 +661,28 @@ void showLibraryTracksChooseDialog({
),
);
}

class _TracksSearchTemp with PortsProvider<Map> {
final void Function(List<Track> tracks) _onResult;
_TracksSearchTemp(this._onResult);

void search(String text) async {
await initialize();
final p = {'text': text, 'temp': true};
await sendPort(p);
}

@override
void onResult(dynamic result) {
final r = result as (List<Track>, bool, String);
_onResult(r.$1);
}

@override
IsolateFunctionReturnBuild<Map> isolateFunction(SendPort port) {
final params = SearchSortController.inst.generateTrackSearchIsolateParams(port, sendPrepared: true);
return IsolateFunctionReturnBuild(SearchSortController.searchTracksIsolate, params);
}

Future<void> dispose() async => await disposePort();
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: namida
description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter
publish_to: "none"
version: 2.5.4-beta+240521239
version: 2.5.45-beta+240522000

environment:
sdk: ">=3.1.4 <4.0.0"
Expand Down

0 comments on commit 6b4c591

Please sign in to comment.