mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
refactor(audio-metadata): migrate from dart audio tagging library to rust based in-house solution
* fix(home): android bottom-bar abnormal empty top space for unknown reason * chore: bump deps and use pub.dev version of spotify package
This commit is contained in:
parent
2ab1fba3d6
commit
d841b06882
@ -111,6 +111,10 @@ class Home extends HookConsumerWidget {
|
|||||||
}, [backgroundColor]);
|
}, [backgroundColor]);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
bottomNavigationBar: SpotubeNavigationBar(
|
||||||
|
selectedIndex: _selectedIndex.value,
|
||||||
|
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||||
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
if (_selectedIndex.value != 3)
|
if (_selectedIndex.value != 3)
|
||||||
@ -178,10 +182,6 @@ class Home extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
// player itself
|
// player itself
|
||||||
Player(),
|
Player(),
|
||||||
SpotubeNavigationBar(
|
|
||||||
selectedIndex: _selectedIndex.value,
|
|
||||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:badges/badges.dart';
|
import 'package:badges/badges.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/components/Home/Sidebar.dart';
|
import 'package:spotube/components/Home/Sidebar.dart';
|
||||||
import 'package:spotube/hooks/useBreakpoints.dart';
|
import 'package:spotube/hooks/useBreakpoints.dart';
|
||||||
@ -24,7 +23,7 @@ class SpotubeNavigationBar extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
final breakpoint = useBreakpoints();
|
final breakpoint = useBreakpoints();
|
||||||
|
|
||||||
if (breakpoint.isMoreThan(Breakpoints.sm)) return Container();
|
if (breakpoint.isMoreThan(Breakpoints.sm)) return const SizedBox();
|
||||||
return NavigationBar(
|
return NavigationBar(
|
||||||
destinations: [
|
destinations: [
|
||||||
...sidebarTileList.map(
|
...sidebarTileList.map(
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dart_tags/dart_tags.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:metadata_god/bridge_generated.dart';
|
||||||
|
import 'package:metadata_god/metadata_god.dart';
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
import 'package:mp3_info/mp3_info.dart';
|
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
@ -18,14 +16,12 @@ import 'package:spotube/provider/Playback.dart';
|
|||||||
import 'package:spotube/provider/UserPreferences.dart';
|
import 'package:spotube/provider/UserPreferences.dart';
|
||||||
import 'package:spotube/utils/primitive_utils.dart';
|
import 'package:spotube/utils/primitive_utils.dart';
|
||||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||||
import 'package:id3/id3.dart';
|
|
||||||
|
|
||||||
final tagProcessor = TagProcessor();
|
|
||||||
|
|
||||||
const supportedAudioTypes = [
|
const supportedAudioTypes = [
|
||||||
"audio/webm",
|
"audio/webm",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"audio/mpeg",
|
"audio/mpeg",
|
||||||
|
"audio/mp4",
|
||||||
"audio/opus",
|
"audio/opus",
|
||||||
"audio/wav",
|
"audio/wav",
|
||||||
"audio/aac",
|
"audio/aac",
|
||||||
@ -56,69 +52,38 @@ final localTracksProvider = FutureProvider<List<Track>>((ref) async {
|
|||||||
}).map(
|
}).map(
|
||||||
(f) async {
|
(f) async {
|
||||||
try {
|
try {
|
||||||
final bytes = f.readAsBytes();
|
final metadata = await MetadataGod.getMetadata(f);
|
||||||
final mp3Instance = MP3Instance(await bytes);
|
|
||||||
|
|
||||||
bool isParsed = false;
|
final imageFile = File(join(
|
||||||
try {
|
(await getTemporaryDirectory()).path,
|
||||||
isParsed = mp3Instance.parseTagsSync();
|
"spotube",
|
||||||
} catch (e, stack) {
|
basenameWithoutExtension(f.path) +
|
||||||
getLogger(MP3Instance).e("[parseTagsSync]", e, stack);
|
imgMimeToExt[metadata?.picture?.mimeType ?? "image/jpeg"]!,
|
||||||
}
|
));
|
||||||
|
if (!await imageFile.exists() && metadata?.picture != null) {
|
||||||
final imageFile = isParsed
|
|
||||||
? File(join(
|
|
||||||
(await getTemporaryDirectory()).path,
|
|
||||||
"spotube",
|
|
||||||
basenameWithoutExtension(f.path) +
|
|
||||||
imgMimeToExt[mp3Instance.metaTags["APIC"]?["mime"] ??
|
|
||||||
"image/jpeg"]!,
|
|
||||||
))
|
|
||||||
: null;
|
|
||||||
if (imageFile != null &&
|
|
||||||
!await imageFile.exists() &&
|
|
||||||
mp3Instance.metaTags["APIC"]?["base64"] != null) {
|
|
||||||
await imageFile.create(recursive: true);
|
await imageFile.create(recursive: true);
|
||||||
await imageFile.writeAsBytes(
|
await imageFile.writeAsBytes(
|
||||||
base64Decode(
|
metadata?.picture?.data ?? [],
|
||||||
mp3Instance.metaTags["APIC"]["base64"],
|
|
||||||
),
|
|
||||||
mode: FileMode.writeOnly,
|
mode: FileMode.writeOnly,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Duration duration;
|
|
||||||
try {
|
|
||||||
duration = MP3Processor.fromBytes(await bytes).duration;
|
|
||||||
} catch (e, stack) {
|
|
||||||
getLogger(MP3Processor).e("[Parsing Mp3]", e, stack);
|
|
||||||
duration = Duration.zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
final metadata = await tagProcessor.getTagsFromByteArray(bytes);
|
return {"metadata": metadata, "file": f, "art": imageFile.path};
|
||||||
return {
|
|
||||||
"metadata": metadata,
|
|
||||||
"file": f,
|
|
||||||
"art": imageFile?.path,
|
|
||||||
"duration": duration,
|
|
||||||
};
|
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
getLogger(FutureProvider).e("[Fetching metadata]", e, stack);
|
getLogger(FutureProvider).e("[Fetching metadata]", e, stack);
|
||||||
return {
|
return {};
|
||||||
"metadata": <Tag>[],
|
|
||||||
"file": f,
|
|
||||||
"duration": Duration.zero,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
));
|
))
|
||||||
|
.where((e) => e.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
|
||||||
final tracks = filesWithMetadata
|
final tracks = filesWithMetadata
|
||||||
.map(
|
.map(
|
||||||
(fileWithMetadata) => TypeConversionUtils.localTrack_X_Track(
|
(fileWithMetadata) => TypeConversionUtils.localTrack_X_Track(
|
||||||
fileWithMetadata["metadata"] as List<Tag>,
|
fileWithMetadata["metadata"] as Metadata,
|
||||||
fileWithMetadata["file"] as File,
|
fileWithMetadata["file"] as File,
|
||||||
fileWithMetadata["duration"] as Duration,
|
|
||||||
fileWithMetadata["art"] as String?,
|
fileWithMetadata["art"] as String?,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -36,7 +36,7 @@ class DownloadTrackButton extends HookConsumerWidget {
|
|||||||
useEffect(() {
|
useEffect(() {
|
||||||
(() async {
|
(() async {
|
||||||
outputFile.value =
|
outputFile.value =
|
||||||
File(path.join(preferences.downloadLocation, "$fileName.mp3"));
|
File(path.join(preferences.downloadLocation, "$fileName.m4a"));
|
||||||
}());
|
}());
|
||||||
return null;
|
return null;
|
||||||
}, [fileName, track, preferences.downloadLocation]);
|
}, [fileName, track, preferences.downloadLocation]);
|
||||||
|
@ -12,6 +12,7 @@ extension VideoFromCacheTrackExtension on Video {
|
|||||||
cacheTrack.uploadDate != null
|
cacheTrack.uploadDate != null
|
||||||
? DateTime.tryParse(cacheTrack.uploadDate!)
|
? DateTime.tryParse(cacheTrack.uploadDate!)
|
||||||
: null,
|
: null,
|
||||||
|
cacheTrack.uploadDate,
|
||||||
cacheTrack.publishDate != null
|
cacheTrack.publishDate != null
|
||||||
? DateTime.tryParse(cacheTrack.publishDate!)
|
? DateTime.tryParse(cacheTrack.publishDate!)
|
||||||
: null,
|
: null,
|
||||||
@ -69,6 +70,7 @@ extension VideoToJson on Video {
|
|||||||
map["author"],
|
map["author"],
|
||||||
ChannelId(map["channelId"]),
|
ChannelId(map["channelId"]),
|
||||||
DateTime.tryParse(map["uploadDate"]),
|
DateTime.tryParse(map["uploadDate"]),
|
||||||
|
map["uploadDate"],
|
||||||
DateTime.tryParse(map["publishDate"]),
|
DateTime.tryParse(map["publishDate"]),
|
||||||
map["description"],
|
map["description"],
|
||||||
parseDuration(map["duration"]),
|
parseDuration(map["duration"]),
|
||||||
|
@ -1,157 +0,0 @@
|
|||||||
import 'package:dart_tags/dart_tags.dart';
|
|
||||||
|
|
||||||
class Id3Tags {
|
|
||||||
Id3Tags({
|
|
||||||
this.tsse,
|
|
||||||
this.title,
|
|
||||||
this.album,
|
|
||||||
this.tpe2,
|
|
||||||
this.comment,
|
|
||||||
this.tcop,
|
|
||||||
this.tdrc,
|
|
||||||
this.genre,
|
|
||||||
this.picture,
|
|
||||||
});
|
|
||||||
|
|
||||||
String? tsse;
|
|
||||||
String? title;
|
|
||||||
String? album;
|
|
||||||
String? tpe2;
|
|
||||||
Comment? comment;
|
|
||||||
String? tcop;
|
|
||||||
String? tdrc;
|
|
||||||
String? genre;
|
|
||||||
AttachedPicture? picture;
|
|
||||||
|
|
||||||
factory Id3Tags.fromJson(Map<String, dynamic> json) => Id3Tags(
|
|
||||||
tsse: json["TSSE"],
|
|
||||||
title: json["title"],
|
|
||||||
album: json["album"],
|
|
||||||
tpe2: json["TPE2"],
|
|
||||||
comment: json["comment"]?["eng:"] is Comment
|
|
||||||
? json["comment"]["eng:"]
|
|
||||||
: CommentJson.fromJson(Map.from(
|
|
||||||
json["comment"]?["eng:"] ?? {},
|
|
||||||
)),
|
|
||||||
tcop: json["TCOP"],
|
|
||||||
tdrc: json["TDRC"],
|
|
||||||
genre: json["genre"],
|
|
||||||
picture: json["picture"]?["Cover (front)"] is AttachedPicture
|
|
||||||
? json["picture"]["Cover (front)"]
|
|
||||||
: AttachedPictureJson.fromJson(Map.from(
|
|
||||||
json["picture"]?["Cover (front)"] ?? {},
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
|
|
||||||
factory Id3Tags.fromId3v1Tags(Id3v1Tags v1tags) => Id3Tags(
|
|
||||||
album: v1tags.album,
|
|
||||||
comment: Comment("", "", v1tags.comment ?? ""),
|
|
||||||
genre: v1tags.genre,
|
|
||||||
title: v1tags.title,
|
|
||||||
tcop: v1tags.year,
|
|
||||||
tdrc: v1tags.year,
|
|
||||||
tpe2: v1tags.artist,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
"TSSE": tsse,
|
|
||||||
"title": title,
|
|
||||||
"album": album,
|
|
||||||
"TPE2": tpe2,
|
|
||||||
"comment": comment,
|
|
||||||
"TCOP": tcop,
|
|
||||||
"TDRC": tdrc,
|
|
||||||
"genre": genre,
|
|
||||||
"picture": picture,
|
|
||||||
};
|
|
||||||
|
|
||||||
String? get artist => tpe2;
|
|
||||||
String? get year => tdrc;
|
|
||||||
|
|
||||||
Map<String, String> toAndroidJson(String artwork) {
|
|
||||||
return {
|
|
||||||
"title": title ?? "Unknown",
|
|
||||||
"artist": artist ?? "Unknown",
|
|
||||||
"album": album ?? "Unknown",
|
|
||||||
"genre": genre ?? "Unknown",
|
|
||||||
"artwork": artwork,
|
|
||||||
"year": year ?? "Unknown",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CommentJson on Comment {
|
|
||||||
static fromJson(Map<String, dynamic> json) => Comment(
|
|
||||||
json["lang"] ?? "",
|
|
||||||
json["description"] ?? "",
|
|
||||||
json["comment"] ?? "",
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
"comment": comment,
|
|
||||||
"description": description,
|
|
||||||
"key": key,
|
|
||||||
"lang": lang,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AttachedPictureJson on AttachedPicture {
|
|
||||||
static fromJson(Map<String, dynamic> json) => AttachedPicture(
|
|
||||||
json["mime"] ?? "",
|
|
||||||
json["imageTypeCode"] ?? 0,
|
|
||||||
json["description"] ?? "",
|
|
||||||
List<int>.from(json["imageData"] ?? []),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
"description": description,
|
|
||||||
"imageData": imageData,
|
|
||||||
"imageData64": imageData64,
|
|
||||||
"imageType": imageType,
|
|
||||||
"imageTypeCode": imageTypeCode,
|
|
||||||
"key": key,
|
|
||||||
"mime": mime,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class Id3v1Tags {
|
|
||||||
String? title;
|
|
||||||
String? artist;
|
|
||||||
String? album;
|
|
||||||
String? year;
|
|
||||||
String? comment;
|
|
||||||
String? track;
|
|
||||||
String? genre;
|
|
||||||
|
|
||||||
Id3v1Tags({
|
|
||||||
this.title,
|
|
||||||
this.artist,
|
|
||||||
this.album,
|
|
||||||
this.year,
|
|
||||||
this.comment,
|
|
||||||
this.track,
|
|
||||||
this.genre,
|
|
||||||
});
|
|
||||||
|
|
||||||
Id3v1Tags.fromJson(Map<String, dynamic> json) {
|
|
||||||
title = json['title'];
|
|
||||||
artist = json['artist'];
|
|
||||||
album = json['album'];
|
|
||||||
year = json['year'];
|
|
||||||
comment = json['comment'];
|
|
||||||
track = json['track'];
|
|
||||||
genre = json['genre'];
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return {
|
|
||||||
'title': title,
|
|
||||||
'artist': artist,
|
|
||||||
'album': album,
|
|
||||||
'year': year,
|
|
||||||
'comment': comment,
|
|
||||||
'track': track,
|
|
||||||
'genre': genre,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +1,19 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dart_tags/dart_tags.dart';
|
import 'package:flutter/widgets.dart' hide Image;
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:metadata_god/bridge_generated.dart';
|
||||||
|
import 'package:metadata_god/metadata_god.dart';
|
||||||
import 'package:queue/queue.dart';
|
import 'package:queue/queue.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart' hide Image;
|
||||||
import 'package:spotube/components/Library/UserLocalTracks.dart';
|
|
||||||
import 'package:spotube/models/Id3Tags.dart';
|
|
||||||
import 'package:spotube/models/Logger.dart';
|
import 'package:spotube/models/Logger.dart';
|
||||||
import 'package:spotube/models/SpotubeTrack.dart';
|
import 'package:spotube/models/SpotubeTrack.dart';
|
||||||
import 'package:spotube/provider/Playback.dart';
|
import 'package:spotube/provider/Playback.dart';
|
||||||
import 'package:spotube/provider/UserPreferences.dart';
|
import 'package:spotube/provider/UserPreferences.dart';
|
||||||
import 'package:spotube/provider/YouTube.dart';
|
import 'package:spotube/provider/YouTube.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
|
||||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart' hide Comment;
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart' hide Comment;
|
||||||
|
|
||||||
@ -63,7 +60,7 @@ class Downloader with ChangeNotifier {
|
|||||||
RegExp(r'[/\\?%*:|"<>]'),
|
RegExp(r'[/\\?%*:|"<>]'),
|
||||||
"",
|
"",
|
||||||
);
|
);
|
||||||
final filename = '$cleanTitle.mp3';
|
final filename = '$cleanTitle.m4a';
|
||||||
final file = File(path.join(downloadPath, filename));
|
final file = File(path.join(downloadPath, filename));
|
||||||
try {
|
try {
|
||||||
logger.v("[addToQueue] Download starting for ${file.path}");
|
logger.v("[addToQueue] Download starting for ${file.path}");
|
||||||
@ -97,9 +94,9 @@ class Downloader with ChangeNotifier {
|
|||||||
"[addToQueue] Download of ${file.path} is done successfully",
|
"[addToQueue] Download of ${file.path} is done successfully",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tagging isn't supported in Android currently
|
logger.v(
|
||||||
if (kIsAndroid) return;
|
"[addToQueue] Writing metadata to ${file.path}",
|
||||||
|
);
|
||||||
final imageUri = TypeConversionUtils.image_X_UrlString(
|
final imageUri = TypeConversionUtils.image_X_UrlString(
|
||||||
track.album?.images ?? [],
|
track.album?.images ?? [],
|
||||||
);
|
);
|
||||||
@ -108,43 +105,30 @@ class Downloader with ChangeNotifier {
|
|||||||
imageUri,
|
imageUri,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final picture = AttachedPicture.base64(
|
|
||||||
response.headers["Content-Type"] ?? "image/jpeg",
|
await MetadataGod.writeMetadata(
|
||||||
3,
|
file,
|
||||||
track.name!,
|
Metadata(
|
||||||
base64Encode(response.bodyBytes),
|
title: track.name,
|
||||||
);
|
artist: track.artists?.map((a) => a.name).join(", "),
|
||||||
// write id3 metadata
|
album: track.album?.name,
|
||||||
final tag = Id3Tags(
|
albumArtist: track.artists?.map((a) => a.name).join(", "),
|
||||||
album: track.album?.name,
|
year: track.album?.releaseDate != null
|
||||||
picture: picture,
|
? int.tryParse(track.album!.releaseDate!)
|
||||||
title: track.name,
|
: null,
|
||||||
genre: "Spotube",
|
trackNumber: track.trackNumber,
|
||||||
tcop: track.ytTrack.uploadDate?.year.toString(),
|
discNumber: track.discNumber,
|
||||||
tdrc: track.ytTrack.uploadDate?.year.toString(),
|
durationMs: track.durationMs?.toDouble(),
|
||||||
tpe2: TypeConversionUtils.artists_X_String<Artist>(
|
fileSize: file.lengthSync(),
|
||||||
track.artists ?? [],
|
trackTotal: track.album?.tracks?.length,
|
||||||
),
|
picture: response.headers['content-type'] != null
|
||||||
tsse: "",
|
? Image(
|
||||||
comment: Comment(
|
data: response.bodyBytes,
|
||||||
"eng",
|
mimeType: response.headers['content-type']!,
|
||||||
track.ytTrack.description,
|
)
|
||||||
track.ytTrack.title,
|
: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
logger.v("[addToQueue] Writing metadata to ${file.path}");
|
|
||||||
|
|
||||||
final taggedMp3 = await tagProcessor.putTagsToByteArray(
|
|
||||||
file.readAsBytes(),
|
|
||||||
[
|
|
||||||
Tag()
|
|
||||||
..type = "ID3"
|
|
||||||
..version = "2.4.0"
|
|
||||||
..tags = tag.toJson()
|
|
||||||
],
|
|
||||||
);
|
|
||||||
await file.writeAsBytes(taggedMp3);
|
|
||||||
logger.v(
|
logger.v(
|
||||||
"[addToQueue] Writing metadata to ${file.path} is successful",
|
"[addToQueue] Writing metadata to ${file.path} is successful",
|
||||||
);
|
);
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dart_tags/dart_tags.dart';
|
|
||||||
import 'package:flutter/widgets.dart' hide Image;
|
import 'package:flutter/widgets.dart' hide Image;
|
||||||
|
import 'package:metadata_god/bridge_generated.dart' hide Image;
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:spotube/components/Shared/LinkText.dart';
|
import 'package:spotube/components/Shared/LinkText.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
import 'package:spotube/models/Id3Tags.dart';
|
|
||||||
import 'package:spotube/models/SpotubeTrack.dart';
|
import 'package:spotube/models/SpotubeTrack.dart';
|
||||||
import 'package:spotube/utils/primitive_utils.dart';
|
import 'package:spotube/utils/primitive_utils.dart';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
|
|
||||||
abstract class TypeConversionUtils {
|
abstract class TypeConversionUtils {
|
||||||
@ -91,30 +89,23 @@ abstract class TypeConversionUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SpotubeTrack localTrack_X_Track(
|
static SpotubeTrack localTrack_X_Track(
|
||||||
List<Tag> metadatas,
|
Metadata metadata,
|
||||||
File file,
|
File file,
|
||||||
Duration duration,
|
|
||||||
String? art,
|
String? art,
|
||||||
) {
|
) {
|
||||||
final v2Tags =
|
|
||||||
metadatas.firstWhereOrNull((s) => s.version == "2.4.0")?.tags;
|
|
||||||
final v1Tags =
|
|
||||||
metadatas.firstWhereOrNull((s) => s.version != "2.4.0")?.tags;
|
|
||||||
final metadata = v2Tags != null
|
|
||||||
? Id3Tags.fromJson(v2Tags)
|
|
||||||
: Id3Tags.fromId3v1Tags(Id3v1Tags.fromJson(v1Tags ?? {}));
|
|
||||||
final track = SpotubeTrack(
|
final track = SpotubeTrack(
|
||||||
Video(
|
Video(
|
||||||
VideoId("dQw4w9WgXcQ"),
|
VideoId("dQw4w9WgXcQ"),
|
||||||
basenameWithoutExtension(file.path),
|
basenameWithoutExtension(file.path),
|
||||||
metadata.tpe2 ?? "",
|
metadata.artist ?? "",
|
||||||
ChannelId(
|
ChannelId(
|
||||||
"https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
|
"https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw",
|
||||||
),
|
),
|
||||||
DateTime.now(),
|
DateTime.now(),
|
||||||
|
"",
|
||||||
DateTime.now(),
|
DateTime.now(),
|
||||||
"",
|
"",
|
||||||
duration,
|
Duration(milliseconds: metadata.durationMs?.toInt() ?? 0),
|
||||||
ThumbnailSet(metadata.title ?? ""),
|
ThumbnailSet(metadata.title ?? ""),
|
||||||
[],
|
[],
|
||||||
const Engagement(0, 0, 0),
|
const Engagement(0, 0, 0),
|
||||||
@ -129,22 +120,23 @@ abstract class TypeConversionUtils {
|
|||||||
..genres = [if (metadata.genre != null) metadata.genre!]
|
..genres = [if (metadata.genre != null) metadata.genre!]
|
||||||
..artists = [
|
..artists = [
|
||||||
Artist()
|
Artist()
|
||||||
..name = metadata.tpe2 ?? "Spotube"
|
..name = metadata.albumArtist ?? "Spotube"
|
||||||
..id = metadata.tpe2 ?? "Spotube"
|
..id = metadata.albumArtist ?? "Spotube"
|
||||||
..type = "artist",
|
..type = "artist",
|
||||||
]
|
]
|
||||||
..id = metadata.album;
|
..id = metadata.album
|
||||||
|
..releaseDate = metadata.year?.toString();
|
||||||
track.artists = [
|
track.artists = [
|
||||||
Artist()
|
Artist()
|
||||||
..name = metadata.tpe2 ?? "Spotube"
|
..name = metadata.artist ?? "Spotube"
|
||||||
..id = metadata.tpe2 ?? "Spotube"
|
..id = metadata.artist ?? "Spotube"
|
||||||
];
|
];
|
||||||
|
|
||||||
track.id = metadata.title ?? basenameWithoutExtension(file.path);
|
track.id = metadata.title ?? basenameWithoutExtension(file.path);
|
||||||
track.name = metadata.title ?? basenameWithoutExtension(file.path);
|
track.name = metadata.title ?? basenameWithoutExtension(file.path);
|
||||||
track.type = "track";
|
track.type = "track";
|
||||||
track.uri = file.path;
|
track.uri = file.path;
|
||||||
track.durationMs = duration.inMilliseconds;
|
track.durationMs = metadata.durationMs?.toInt();
|
||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
||||||
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
|
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
|
||||||
|
#include <metadata_god/metadata_god_plugin.h>
|
||||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar =
|
g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin");
|
||||||
bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar);
|
bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) metadata_god_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "MetadataGodPlugin");
|
||||||
|
metadata_god_plugin_register_with_registrar(metadata_god_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
audioplayers_linux
|
audioplayers_linux
|
||||||
bitsdojo_window_linux
|
bitsdojo_window_linux
|
||||||
|
metadata_god
|
||||||
url_launcher_linux
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import audio_service
|
|||||||
import audio_session
|
import audio_session
|
||||||
import audioplayers_darwin
|
import audioplayers_darwin
|
||||||
import bitsdojo_window_macos
|
import bitsdojo_window_macos
|
||||||
|
import metadata_god
|
||||||
import package_info_plus_macos
|
import package_info_plus_macos
|
||||||
import path_provider_macos
|
import path_provider_macos
|
||||||
import shared_preferences_macos
|
import shared_preferences_macos
|
||||||
@ -20,6 +21,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||||
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
||||||
BitsdojoWindowPlugin.register(with: registry.registrar(forPlugin: "BitsdojoWindowPlugin"))
|
BitsdojoWindowPlugin.register(with: registry.registrar(forPlugin: "BitsdojoWindowPlugin"))
|
||||||
|
MetadataGodPlugin.register(with: registry.registrar(forPlugin: "MetadataGodPlugin"))
|
||||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
|
175
pubspec.lock
175
pubspec.lock
@ -78,48 +78,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.9"
|
version: "0.0.9"
|
||||||
app_package_parser:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: app_package_parser
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.7"
|
|
||||||
app_package_parser_apk:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: app_package_parser_apk
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.7"
|
|
||||||
app_package_parser_ipa:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: app_package_parser_ipa
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.7"
|
|
||||||
app_package_publisher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: app_package_publisher
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.9"
|
|
||||||
app_package_publisher_fir:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: app_package_publisher_fir
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.9"
|
|
||||||
app_package_publisher_pgyer:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: app_package_publisher_pgyer
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.9"
|
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -238,21 +196,21 @@ packages:
|
|||||||
name: bitsdojo_window
|
name: bitsdojo_window
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.4"
|
||||||
bitsdojo_window_linux:
|
bitsdojo_window_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: bitsdojo_window_linux
|
name: bitsdojo_window_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.3"
|
||||||
bitsdojo_window_macos:
|
bitsdojo_window_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: bitsdojo_window_macos
|
name: bitsdojo_window_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.3"
|
||||||
bitsdojo_window_platform_interface:
|
bitsdojo_window_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -266,7 +224,7 @@ packages:
|
|||||||
name: bitsdojo_window_windows
|
name: bitsdojo_window_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.4"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -386,20 +344,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.16.0"
|
||||||
colorize:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: colorize
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.0"
|
|
||||||
console_bars:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: console_bars
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.5"
|
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -435,27 +379,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.3"
|
version: "2.2.3"
|
||||||
dart_tags:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: dart_tags
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.4.0"
|
|
||||||
dbus:
|
dbus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dbus
|
name: dbus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.3"
|
version: "0.7.8"
|
||||||
dio:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: dio
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.0.6"
|
|
||||||
dots_indicator:
|
dots_indicator:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -483,7 +413,7 @@ packages:
|
|||||||
name: ffi
|
name: ffi
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "2.0.1"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -494,10 +424,12 @@ packages:
|
|||||||
file_picker:
|
file_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: file_picker
|
path: "."
|
||||||
url: "https://pub.dartlang.org"
|
ref: HEAD
|
||||||
source: hosted
|
resolved-ref: f9133f6d5dbf33191fc9b58655aebfd15445045a
|
||||||
version: "4.6.1"
|
url: "https://github.com/KRTirtho/flutter_file_picker.git"
|
||||||
|
source: git
|
||||||
|
version: "5.0.1"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -524,13 +456,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.9"
|
version: "0.0.9"
|
||||||
flutter_app_publisher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_app_publisher
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.9"
|
|
||||||
flutter_blurhash:
|
flutter_blurhash:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -551,7 +476,7 @@ packages:
|
|||||||
name: flutter_distributor
|
name: flutter_distributor
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.9"
|
version: "0.0.2"
|
||||||
flutter_hooks:
|
flutter_hooks:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -587,6 +512,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
flutter_rust_bridge:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_rust_bridge
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.42.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -603,7 +535,7 @@ packages:
|
|||||||
name: freezed_annotation
|
name: freezed_annotation
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "2.1.0"
|
||||||
frontend_server_client:
|
frontend_server_client:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -695,20 +627,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.1"
|
||||||
id3:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: id3
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
image:
|
image:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.2.0"
|
||||||
infinite_scroll_pagination:
|
infinite_scroll_pagination:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -793,6 +718,15 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.0"
|
||||||
|
metadata_god:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: HEAD
|
||||||
|
resolved-ref: "65e3b973213ab8c7495506d13b8e047ecd9fca88"
|
||||||
|
url: "https://github.com/KRTirtho/metadata_god.git"
|
||||||
|
source: git
|
||||||
|
version: "0.0.1"
|
||||||
mime:
|
mime:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -800,13 +734,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
mp3_info:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: mp3_info
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0"
|
|
||||||
msix:
|
msix:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -841,7 +768,7 @@ packages:
|
|||||||
name: package_info_plus
|
name: package_info_plus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.2"
|
version: "1.4.3+1"
|
||||||
package_info_plus_linux:
|
package_info_plus_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -876,7 +803,7 @@ packages:
|
|||||||
name: package_info_plus_windows
|
name: package_info_plus_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "2.0.0"
|
||||||
palette_generator:
|
palette_generator:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -884,13 +811,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.3"
|
version: "0.3.3"
|
||||||
parse_app_package:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: parse_app_package
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.7"
|
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -925,7 +845,7 @@ packages:
|
|||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.6"
|
version: "2.1.7"
|
||||||
path_provider_macos:
|
path_provider_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -946,7 +866,7 @@ packages:
|
|||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.1.3"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1186,12 +1106,10 @@ packages:
|
|||||||
spotify:
|
spotify:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
name: spotify
|
||||||
ref: HEAD
|
url: "https://pub.dartlang.org"
|
||||||
resolved-ref: ea313e2d21c38157cd8255d248bcd7897bf51360
|
source: hosted
|
||||||
url: "https://github.com/KRTirtho/spotify-dart.git"
|
version: "0.8.0"
|
||||||
source: git
|
|
||||||
version: "0.7.0"
|
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1332,13 +1250,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.1"
|
||||||
utf_convert:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: utf_convert
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.0+1"
|
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1375,12 +1286,12 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.6.1"
|
version: "3.0.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1394,7 +1305,7 @@ packages:
|
|||||||
name: xml
|
name: xml
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.4.1"
|
version: "6.1.0"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1408,7 +1319,7 @@ packages:
|
|||||||
name: youtube_explode_dart
|
name: youtube_explode_dart
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.0"
|
version: "1.12.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.17.1 <3.0.0"
|
dart: ">=2.17.1 <3.0.0"
|
||||||
flutter: ">=3.0.0"
|
flutter: ">=3.0.0"
|
||||||
|
23
pubspec.yaml
23
pubspec.yaml
@ -37,11 +37,10 @@ dependencies:
|
|||||||
html: ^0.15.0
|
html: ^0.15.0
|
||||||
http: ^0.13.4
|
http: ^0.13.4
|
||||||
shared_preferences: ^2.0.11
|
shared_preferences: ^2.0.11
|
||||||
spotify:
|
spotify: ^0.8.0
|
||||||
git: https://github.com/KRTirtho/spotify-dart.git
|
|
||||||
url_launcher: ^6.0.17
|
url_launcher: ^6.0.17
|
||||||
youtube_explode_dart: ^1.10.8
|
youtube_explode_dart: ^1.10.8
|
||||||
bitsdojo_window: ^0.1.2
|
bitsdojo_window: 0.1.4
|
||||||
path: ^1.8.0
|
path: ^1.8.0
|
||||||
path_provider: ^2.0.8
|
path_provider: ^2.0.8
|
||||||
collection: ^1.15.0
|
collection: ^1.15.0
|
||||||
@ -54,7 +53,7 @@ dependencies:
|
|||||||
permission_handler: ^9.2.0
|
permission_handler: ^9.2.0
|
||||||
marquee: ^2.2.1
|
marquee: ^2.2.1
|
||||||
scroll_to_index: ^2.1.1
|
scroll_to_index: ^2.1.1
|
||||||
package_info_plus: ^1.4.2
|
package_info_plus: ^1.4.3
|
||||||
version: ^2.0.0
|
version: ^2.0.0
|
||||||
audio_service: ^0.18.4
|
audio_service: ^0.18.4
|
||||||
hookified_infinite_scroll_pagination: ^0.1.0
|
hookified_infinite_scroll_pagination: ^0.1.0
|
||||||
@ -65,15 +64,23 @@ dependencies:
|
|||||||
audioplayers: ^1.0.1
|
audioplayers: ^1.0.1
|
||||||
introduction_screen: ^3.0.2
|
introduction_screen: ^3.0.2
|
||||||
audio_session: ^0.1.9
|
audio_session: ^0.1.9
|
||||||
file_picker: ^4.6.1
|
# This is temporary until the win32v3 update PR is merged and released
|
||||||
|
file_picker:
|
||||||
|
git:
|
||||||
|
url: https://github.com/KRTirtho/flutter_file_picker.git
|
||||||
popover: ^0.2.6+3
|
popover: ^0.2.6+3
|
||||||
queue: ^3.1.0+1
|
queue: ^3.1.0+1
|
||||||
auto_size_text: ^3.0.0
|
auto_size_text: ^3.0.0
|
||||||
badges: ^2.0.3
|
badges: ^2.0.3
|
||||||
mime: ^1.0.2
|
mime: ^1.0.2
|
||||||
dart_tags: ^0.4.0
|
metadata_god:
|
||||||
id3: ^1.0.2
|
git:
|
||||||
mp3_info: ^0.2.0
|
url: https://github.com/KRTirtho/metadata_god.git
|
||||||
|
|
||||||
|
# Temporary before [package_info_plus_windows] is updated to support
|
||||||
|
# win32v3
|
||||||
|
dependency_overrides:
|
||||||
|
win32: 3.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||||
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
|
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
|
||||||
|
#include <metadata_god/metadata_god_plugin_c_api.h>
|
||||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||||
#include <url_launcher_windows/url_launcher_windows.h>
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
@ -16,6 +17,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
||||||
BitsdojoWindowPluginRegisterWithRegistrar(
|
BitsdojoWindowPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
|
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
|
||||||
|
MetadataGodPluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("MetadataGodPluginCApi"));
|
||||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||||
UrlLauncherWindowsRegisterWithRegistrar(
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
audioplayers_windows
|
audioplayers_windows
|
||||||
bitsdojo_window_windows
|
bitsdojo_window_windows
|
||||||
|
metadata_god
|
||||||
permission_handler_windows
|
permission_handler_windows
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user