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