Compare commits

...

5 Commits

Author SHA1 Message Date
a6b40e81a7 🐛 Bug fixes on looking up ips 2024-09-11 20:37:42 +08:00
1913a7e909 🐛 Bug fixes on cross source track fetching 2024-09-11 20:18:03 +08:00
d860936010 🚀 Launch 1.0.0+17 2024-09-10 23:45:50 +08:00
873ad1cf8c 🐛 Fix cross source swap siblings issue 2024-09-10 23:06:15 +08:00
e0c9edad78 💄 Downgrade kugou source 2024-09-08 22:24:10 +08:00
7 changed files with 62 additions and 22 deletions

View File

@ -5,6 +5,7 @@ import 'package:rhythm_box/providers/database.dart';
import 'package:rhythm_box/providers/error_notifier.dart'; import 'package:rhythm_box/providers/error_notifier.dart';
import 'package:rhythm_box/providers/user_preferences.dart'; import 'package:rhythm_box/providers/user_preferences.dart';
import 'package:rhythm_box/services/database/database.dart'; import 'package:rhythm_box/services/database/database.dart';
import 'package:rhythm_box/services/server/active_sourced_track.dart';
import 'package:rhythm_box/services/sourced_track/sources/kugou.dart'; import 'package:rhythm_box/services/sourced_track/sources/kugou.dart';
import 'package:rhythm_box/services/sourced_track/sources/netease.dart'; import 'package:rhythm_box/services/sourced_track/sources/netease.dart';
import 'package:rhythm_box/services/utils.dart'; import 'package:rhythm_box/services/utils.dart';
@ -81,14 +82,31 @@ abstract class SourcedTrack extends Track {
}; };
} }
static Type getTrackBySourceInfo(SourceInfo info) { static Future<SourcedTrack?> reRoutineFetchFromTrack(
Track track, SourceMatchTableData cachedSource) {
final preferences = Get.find<UserPreferencesProvider>().state.value;
final ytOrPiped = preferences.audioSource == AudioSource.piped
? PipedSourcedTrack.fetchFromTrack
: YoutubeSourcedTrack.fetchFromTrack;
final sourceInfoTrackMap = { final sourceInfoTrackMap = {
YoutubeSourceInfo: YoutubeSourcedTrack, SourceType.youtube: ytOrPiped,
PipedSourceInfo: PipedSourcedTrack, SourceType.youtubeMusic: ytOrPiped,
NeteaseSourceInfo: NeteaseSourcedTrack, SourceType.netease: NeteaseSourcedTrack.fetchFromTrack,
KugouSourceInfo: KugouSourcedTrack, SourceType.kugou: KugouSourcedTrack.fetchFromTrack,
}; };
return sourceInfoTrackMap[info.runtimeType]!; return sourceInfoTrackMap[cachedSource.sourceType]!(track: track);
}
Future<SourcedTrack?> reRoutineSwapSiblings(SourceInfo info) {
final sourceInfoTrackMap = {
YoutubeSourceInfo: YoutubeSourcedTrack.fetchFromTrack,
PipedSourceInfo: PipedSourcedTrack.fetchFromTrack,
NeteaseSourceInfo: NeteaseSourcedTrack.fetchFromTrack,
KugouSourceInfo: KugouSourcedTrack.fetchFromTrack,
};
return sourceInfoTrackMap[info.runtimeType]!(
track: Get.find<ActiveSourcedTrackProvider>().state.value!,
);
} }
static String getSearchTerm(Track track) { static String getSearchTerm(Track track) {
@ -170,7 +188,7 @@ abstract class SourcedTrack extends Track {
return switch (audioSource) { return switch (audioSource) {
AudioSource.netease => AudioSource.netease =>
await fetchFromTrack(track: track, fallbackTo: AudioSource.kugou), await fetchFromTrack(track: track, fallbackTo: AudioSource.youtube),
AudioSource.kugou => AudioSource.kugou =>
await fetchFromTrack(track: track, fallbackTo: AudioSource.youtube), await fetchFromTrack(track: track, fallbackTo: AudioSource.youtube),
_ => _ =>

View File

@ -51,7 +51,7 @@ class KugouSourcedTrack extends SourcedTrack {
return client; return client;
} }
static Future<KugouSourcedTrack> fetchFromTrack({ static Future<SourcedTrack> fetchFromTrack({
required Track track, required Track track,
}) async { }) async {
final DatabaseProvider db = Get.find(); final DatabaseProvider db = Get.find();
@ -77,6 +77,7 @@ class KugouSourcedTrack extends SourcedTrack {
sourceId: siblings.first.info.id, sourceId: siblings.first.info.id,
sourceType: const Value(SourceType.kugou), sourceType: const Value(SourceType.kugou),
), ),
mode: InsertMode.insertOrReplace,
); );
return KugouSourcedTrack( return KugouSourcedTrack(
@ -85,6 +86,11 @@ class KugouSourcedTrack extends SourcedTrack {
sourceInfo: siblings.first.info, sourceInfo: siblings.first.info,
track: track, track: track,
); );
} else if (cachedSource.sourceType != SourceType.kugou) {
final out =
await SourcedTrack.reRoutineFetchFromTrack(track, cachedSource);
if (out == null) throw TrackNotFoundError(track);
return out;
} }
return KugouSourcedTrack( return KugouSourcedTrack(
@ -171,8 +177,7 @@ class KugouSourcedTrack extends SourcedTrack {
@override @override
Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async { Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling is! KugouSourceInfo) { if (sibling is! KugouSourceInfo) {
return (SourcedTrack.getTrackBySourceInfo(sibling) as SourcedTrack) return reRoutineSwapSiblings(sibling);
.swapWithSibling(sibling);
} }
if (sibling.id == sourceInfo.id) { if (sibling.id == sourceInfo.id) {

View File

@ -73,7 +73,7 @@ class NeteaseSourcedTrack extends SourcedTrack {
return _lookedUpRealIp!; return _lookedUpRealIp!;
} }
static Future<NeteaseSourcedTrack> fetchFromTrack({ static Future<SourcedTrack> fetchFromTrack({
required Track track, required Track track,
}) async { }) async {
final DatabaseProvider db = Get.find(); final DatabaseProvider db = Get.find();
@ -105,6 +105,7 @@ class NeteaseSourcedTrack extends SourcedTrack {
sourceId: siblings.first.info.id, sourceId: siblings.first.info.id,
sourceType: const Value(SourceType.netease), sourceType: const Value(SourceType.netease),
), ),
mode: InsertMode.insertOrReplace,
); );
return NeteaseSourcedTrack( return NeteaseSourcedTrack(
@ -113,10 +114,16 @@ class NeteaseSourcedTrack extends SourcedTrack {
sourceInfo: siblings.first.info, sourceInfo: siblings.first.info,
track: track, track: track,
); );
} else if (cachedSource.sourceType != SourceType.netease) {
final out =
await SourcedTrack.reRoutineFetchFromTrack(track, cachedSource);
if (out == null) throw TrackNotFoundError(track);
return out;
} }
final client = getClient(); final client = getClient();
final resp = await client.get('/song/detail?ids=${cachedSource.sourceId}'); final resp = await client.get('/song/detail?ids=${cachedSource.sourceId}');
if (resp.body?['songs'] == null) throw TrackNotFoundError(track);
final item = (resp.body['songs'] as List<dynamic>).firstOrNull; final item = (resp.body['songs'] as List<dynamic>).firstOrNull;
if (item == null) throw TrackNotFoundError(track); if (item == null) throw TrackNotFoundError(track);
@ -168,7 +175,7 @@ class NeteaseSourcedTrack extends SourcedTrack {
final client = getClient(); final client = getClient();
final resp = await client.get( final resp = await client.get(
'/search?keywords=${Uri.encodeComponent(query)}&realIP=${NeteaseSourcedTrack.lookupRealIp()}', '/search?keywords=${Uri.encodeComponent(query)}&realIP=${await NeteaseSourcedTrack.lookupRealIp()}',
); );
if (resp.body?['code'] == 405) throw TrackNotFoundError(track); if (resp.body?['code'] == 405) throw TrackNotFoundError(track);
final results = resp.body['result']['songs']; final results = resp.body['result']['songs'];
@ -202,8 +209,7 @@ class NeteaseSourcedTrack extends SourcedTrack {
@override @override
Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async { Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling is! NeteaseSourceInfo) { if (sibling is! NeteaseSourceInfo) {
return (SourcedTrack.getTrackBySourceInfo(sibling) as SourcedTrack) return reRoutineSwapSiblings(sibling);
.swapWithSibling(sibling);
} }
if (sibling.id == sourceInfo.id) { if (sibling.id == sourceInfo.id) {

View File

@ -57,6 +57,14 @@ class PipedSourcedTrack extends SourcedTrack {
final preferences = Get.find<UserPreferencesProvider>().state.value; final preferences = Get.find<UserPreferencesProvider>().state.value;
if (cachedSource?.sourceType != SourceType.youtube &&
cachedSource?.sourceType != SourceType.youtubeMusic) {
final out =
await SourcedTrack.reRoutineFetchFromTrack(track, cachedSource!);
if (out == null) throw TrackNotFoundError(track);
return out;
}
if (cachedSource == null) { if (cachedSource == null) {
final siblings = await fetchSiblings(track: track); final siblings = await fetchSiblings(track: track);
if (siblings.isEmpty) { if (siblings.isEmpty) {
@ -73,6 +81,7 @@ class PipedSourcedTrack extends SourcedTrack {
: SourceType.youtubeMusic, : SourceType.youtubeMusic,
), ),
), ),
mode: InsertMode.insertOrReplace,
); );
return PipedSourcedTrack( return PipedSourcedTrack(
@ -256,8 +265,7 @@ class PipedSourcedTrack extends SourcedTrack {
@override @override
Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async { Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling is! PipedSourceInfo) { if (sibling is! PipedSourceInfo) {
return (SourcedTrack.getTrackBySourceInfo(sibling) as SourcedTrack) return reRoutineSwapSiblings(sibling);
.swapWithSibling(sibling);
} }
if (sibling.id == sourceInfo.id) { if (sibling.id == sourceInfo.id) {

View File

@ -43,7 +43,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
required super.track, required super.track,
}); });
static Future<YoutubeSourcedTrack> fetchFromTrack({ static Future<SourcedTrack> fetchFromTrack({
required Track track, required Track track,
}) async { }) async {
final DatabaseProvider db = Get.find(); final DatabaseProvider db = Get.find();
@ -78,6 +78,11 @@ class YoutubeSourcedTrack extends SourcedTrack {
sourceInfo: siblings.first.info, sourceInfo: siblings.first.info,
track: track, track: track,
); );
} else if (cachedSource.sourceType != SourceType.youtube) {
final out =
await SourcedTrack.reRoutineFetchFromTrack(track, cachedSource);
if (out == null) throw TrackNotFoundError(track);
return out;
} }
final item = await youtubeClient.videos.get(cachedSource.sourceId); final item = await youtubeClient.videos.get(cachedSource.sourceId);
@ -271,8 +276,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
@override @override
Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async { Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling is! YoutubeSourceInfo) { if (sibling is! YoutubeSourceInfo) {
return (SourcedTrack.getTrackBySourceInfo(sibling) as SourcedTrack) return reRoutineSwapSiblings(sibling);
.swapWithSibling(sibling);
} }
if (sibling.id == sourceInfo.id) { if (sibling.id == sourceInfo.id) {

View File

@ -120,7 +120,7 @@ class _SiblingTracksState extends State<SiblingTracks> {
} else if (preferences.audioSource == AudioSource.netease) { } else if (preferences.audioSource == AudioSource.netease) {
final client = NeteaseSourcedTrack.getClient(); final client = NeteaseSourcedTrack.getClient();
final resp = await client.get( final resp = await client.get(
'/search?keywords=${Uri.encodeComponent(searchTerm)}&realIP=${NeteaseSourcedTrack.lookupRealIp()}'); '/search?keywords=${Uri.encodeComponent(searchTerm)}&realIP=${await NeteaseSourcedTrack.lookupRealIp()}');
final searchResults = resp.body['result']['songs'] final searchResults = resp.body['result']['songs']
.map(NeteaseSourcedTrack.toSourceInfo) .map(NeteaseSourcedTrack.toSourceInfo)
.toList(); .toList();

View File

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+15 version: 1.0.0+18
environment: environment:
sdk: ^3.5.0 sdk: ^3.5.0
@ -180,4 +180,3 @@ flutter_native_splash:
color: "#fef8f5" color: "#fef8f5"
color_dark: "#18120d" color_dark: "#18120d"
image: assets/icon-w-shadow.png image: assets/icon-w-shadow.png