From cea6fd9797e63756d777af2a7768f89d15248bee Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Mon, 25 Apr 2022 22:15:01 +0600 Subject: [PATCH] optimized search for both youtube track & synched subtitle flutter_distributor .deb build support --- distribute_options.yaml | 16 ++++++++- lib/components/Home/Home.dart | 1 - lib/components/{ => Lyrics}/Lyrics.dart | 0 lib/components/Lyrics/SyncedLyrics.dart | 42 +++++++++++++++++++---- lib/helpers/contains-text-in-bracket.dart | 6 ++++ lib/helpers/search-youtube.dart | 32 +++++++++++++++-- lib/helpers/timed-lyrics.dart | 9 +++-- linux/packaging/deb/make_config.yaml | 27 +++++++++++++++ 8 files changed, 120 insertions(+), 13 deletions(-) rename lib/components/{ => Lyrics}/Lyrics.dart (100%) create mode 100644 lib/helpers/contains-text-in-bracket.dart create mode 100644 linux/packaging/deb/make_config.yaml diff --git a/distribute_options.yaml b/distribute_options.yaml index c8919523..153677e9 100644 --- a/distribute_options.yaml +++ b/distribute_options.yaml @@ -24,4 +24,18 @@ releases: target: appimage build_args: dart-define: - APP_ENV: dev \ No newline at end of file + APP_ENV: dev + - name: release-dev-windows-exe + package: + platform: windows + target: exe + build_args: + dart-define: + APP_ENV: dev + - name: release-dev-macos-dmg + package: + platform: macos + target: dmg + build_args: + dart-define: + APP_ENV: dev diff --git a/lib/components/Home/Home.dart b/lib/components/Home/Home.dart index c99d3c38..2b0de63f 100644 --- a/lib/components/Home/Home.dart +++ b/lib/components/Home/Home.dart @@ -12,7 +12,6 @@ import 'package:spotube/components/Category/CategoryCard.dart'; import 'package:spotube/components/Home/Sidebar.dart'; import 'package:spotube/components/Home/SpotubeNavigationBar.dart'; import 'package:spotube/components/Lyrics/SyncedLyrics.dart'; -import 'package:spotube/components/Lyrics.dart'; import 'package:spotube/components/Search/Search.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Player/Player.dart'; diff --git a/lib/components/Lyrics.dart b/lib/components/Lyrics/Lyrics.dart similarity index 100% rename from lib/components/Lyrics.dart rename to lib/components/Lyrics/Lyrics.dart diff --git a/lib/components/Lyrics/SyncedLyrics.dart b/lib/components/Lyrics/SyncedLyrics.dart index 057c73e0..7724a7db 100644 --- a/lib/components/Lyrics/SyncedLyrics.dart +++ b/lib/components/Lyrics/SyncedLyrics.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; -import 'package:spotube/components/Lyrics.dart'; +import 'package:spotube/components/Lyrics/Lyrics.dart'; import 'package:spotube/components/Shared/SpotubeMarqueeText.dart'; import 'package:spotube/helpers/artist-to-string.dart'; import 'package:spotube/helpers/timed-lyrics.dart'; @@ -26,9 +26,10 @@ class SyncedLyrics extends HookConsumerWidget { if (playback.currentTrack == null || playback.currentTrack is! SpotubeTrack) return null; try { + if (failed.value) failed.value = false; final lyrics = await getTimedLyrics(playback.currentTrack as SpotubeTrack); - if (failed.value) failed.value = false; + if (lyrics == null) failed.value = true; return lyrics; } catch (e) { if (e == "Subtitle lookup failed") { @@ -52,13 +53,42 @@ class SyncedLyrics extends HookConsumerWidget { final textTheme = Theme.of(context).textTheme; useEffect(() { - controller.scrollToIndex( - 0, - preferPosition: AutoScrollPosition.middle, - ); + controller.scrollToIndex(0); return null; }, [playback.currentTrack]); + useEffect(() { + if (lyricsSnapshot.data != null && lyricsSnapshot.data!.rating <= 2) { + Future.delayed(const Duration(seconds: 5), () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + actions: [ + TextButton( + child: const Text("No"), + onPressed: () { + Navigator.pop(context); + }, + ), + TextButton( + child: const Text("Yes"), + onPressed: () { + failed.value = true; + Navigator.pop(context); + }, + ), + ], + content: const Text( + "The found lyrics might not be properly synced. Do you want to default to static (genius.com) lyrics?"), + ); + }, + ); + }); + } + return null; + }, [lyricsSnapshot.data]); + // when synced lyrics not found, fallback to GeniusLyrics if (failed.value) return const Lyrics(); diff --git a/lib/helpers/contains-text-in-bracket.dart b/lib/helpers/contains-text-in-bracket.dart new file mode 100644 index 00000000..fe177ec6 --- /dev/null +++ b/lib/helpers/contains-text-in-bracket.dart @@ -0,0 +1,6 @@ +bool containsTextInBracket(String matcher, String text) { + return RegExp(r"(?<=\().+?(?=\))") + .allMatches(matcher) + .map((e) => e.group(0)) + .every((match) => match?.contains(text) ?? false); +} diff --git a/lib/helpers/search-youtube.dart b/lib/helpers/search-youtube.dart index c5cbb336..bf2a602c 100644 --- a/lib/helpers/search-youtube.dart +++ b/lib/helpers/search-youtube.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'package:spotify/spotify.dart'; +import 'package:spotube/helpers/contains-text-in-bracket.dart'; import 'package:spotube/helpers/getLyrics.dart'; import 'package:spotube/models/Logger.dart'; import 'package:spotube/models/SpotubeTrack.dart'; @@ -36,15 +37,40 @@ Future toSpotubeTrack( // the find should be lazy thus everything case insensitive final ytTitle = video.title.toLowerCase(); final bool hasTitle = ytTitle.contains(title); + final bool hasYtTitle = title.contains(ytTitle); final bool hasAllArtists = track.artists?.every( (artist) => ytTitle.contains(artist.name!.toLowerCase()), ) ?? false; - final bool authorIsArtist = track.artists - ?.any((artist) => artist.name?.toLowerCase() == video.author) ?? + final bool authorIsArtist = track.artists?.any((artist) { + return artist.name?.toLowerCase() == video.author.toLowerCase(); + }) ?? false; + + final bool hasNoLive = !containsTextInBracket(ytTitle, "live"); + final bool hasOfficialVideo = [ + "(official video)", + "[official video]", + "(official music video)", + "[official music video]" + ].any((v) => ytTitle.contains(v)); + + final bool hasOfficialAudio = [ + "[official audio]", + "(official audio)", + ].any((v) => ytTitle.contains(v)); + int rate = 0; - for (final el in [hasTitle, hasAllArtists, authorIsArtist]) { + for (final el in [ + hasTitle, + hasYtTitle, + hasAllArtists, + authorIsArtist, + hasNoLive, + !video.isLive, + hasOfficialAudio, + hasOfficialVideo, + ]) { if (el) rate++; } return { diff --git a/lib/helpers/timed-lyrics.dart b/lib/helpers/timed-lyrics.dart index f90dd772..67c7e029 100644 --- a/lib/helpers/timed-lyrics.dart +++ b/lib/helpers/timed-lyrics.dart @@ -2,6 +2,7 @@ import 'package:html/dom.dart'; import 'package:http/http.dart' as http; import 'package:html/parser.dart'; import 'package:collection/collection.dart'; +import 'package:spotube/helpers/contains-text-in-bracket.dart'; import 'package:spotube/helpers/getLyrics.dart'; import 'package:spotube/models/Logger.dart'; import 'package:spotube/models/SpotubeTrack.dart'; @@ -12,10 +13,12 @@ class SubtitleSimple { Uri uri; String name; List lyrics; + int rating; SubtitleSimple({ required this.uri, required this.name, required this.lyrics, + required this.rating, }); } @@ -60,9 +63,10 @@ Future getTimedLyrics(SpotubeTrack track) async { .every((artist) => title.contains(artist.toLowerCase())) ?? false; final hasTrackName = title.contains(track.name!.toLowerCase()); + final isNotLive = !containsTextInBracket(title, "live"); final exactYtMatch = title == track.ytTrack.title.toLowerCase(); - if (exactYtMatch) points = 8; - for (final criteria in [hasTrackName, hasAllArtists]) { + if (exactYtMatch) points = 7; + for (final criteria in [hasTrackName, hasAllArtists, isNotLive]) { if (criteria) points++; } return {"result": result, "points": points}; @@ -111,6 +115,7 @@ Future getTimedLyrics(SpotubeTrack track) async { name: topResult.text.trim(), uri: subtitleUri, lyrics: lrcList, + rating: rateSortedResults.first["points"] as int, ); return subtitle; diff --git a/linux/packaging/deb/make_config.yaml b/linux/packaging/deb/make_config.yaml new file mode 100644 index 00000000..ca254215 --- /dev/null +++ b/linux/packaging/deb/make_config.yaml @@ -0,0 +1,27 @@ +display_name: Spotube +package_name: spotube + +maintainer: + name: Kingkor Roy Tirtho + email: krtirtho@gmail.com + +priority: optional +section: x11 +installed_size: 24400 + +dependencies: + - libkeybinder-3.0-0 (>= 0.3.2) + +essential: false +icon: assets/spotube-logo.png + +keywords: + - Music + - Spotify + - Media + - Streaming + - YouTube + +generic_name: Music Streaming Application +categories: + - Music