From 7a6821f28da0daa80f6da6aef0de1e586c3ca0a2 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Sat, 14 Jun 2025 08:41:38 +0600 Subject: [PATCH] feat: implement metadata plugins based on hetu --- lib/collections/routes.dart | 4 - lib/collections/routes.gr.dart | 400 +++++------- lib/main.dart | 2 +- lib/models/metadata/image.dart | 6 +- lib/models/metadata/metadata.freezed.dart | 180 +++--- lib/models/metadata/metadata.g.dart | 18 +- lib/models/metadata/user.dart | 7 +- lib/pages/settings/metadata_plugins.dart | 18 +- lib/pages/webview/webview.dart | 56 -- lib/provider/metadata_plugin/auth.dart | 56 +- .../metadata_plugin_provider.dart | 46 +- lib/provider/metadata_plugin/user.dart | 16 + lib/services/metadata/apis/localstorage.dart | 110 ++-- lib/services/metadata/apis/set_interval.dart | 80 --- lib/services/metadata/apis/totp.dart | 40 -- lib/services/metadata/apis/webview.dart | 171 ----- lib/services/metadata/endpoints/album.dart | 0 lib/services/metadata/endpoints/artist.dart | 0 lib/services/metadata/endpoints/auth.dart | 33 + lib/services/metadata/endpoints/browse.dart | 0 lib/services/metadata/endpoints/playlist.dart | 0 lib/services/metadata/endpoints/search.dart | 0 lib/services/metadata/endpoints/track.dart | 0 lib/services/metadata/endpoints/user.dart | 15 + lib/services/metadata/metadata.dart | 599 ++---------------- linux/flutter/generated_plugin_registrant.cc | 8 +- linux/flutter/generated_plugins.cmake | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 4 +- pubspec.lock | 73 ++- pubspec.yaml | 22 +- .../flutter/generated_plugin_registrant.cc | 6 +- windows/flutter/generated_plugins.cmake | 2 +- 32 files changed, 577 insertions(+), 1397 deletions(-) delete mode 100644 lib/pages/webview/webview.dart create mode 100644 lib/provider/metadata_plugin/user.dart delete mode 100644 lib/services/metadata/apis/set_interval.dart delete mode 100644 lib/services/metadata/apis/totp.dart delete mode 100644 lib/services/metadata/apis/webview.dart create mode 100644 lib/services/metadata/endpoints/album.dart create mode 100644 lib/services/metadata/endpoints/artist.dart create mode 100644 lib/services/metadata/endpoints/auth.dart create mode 100644 lib/services/metadata/endpoints/browse.dart create mode 100644 lib/services/metadata/endpoints/playlist.dart create mode 100644 lib/services/metadata/endpoints/search.dart create mode 100644 lib/services/metadata/endpoints/track.dart create mode 100644 lib/services/metadata/endpoints/user.dart diff --git a/lib/collections/routes.dart b/lib/collections/routes.dart index 3f2043a1..835260bc 100644 --- a/lib/collections/routes.dart +++ b/lib/collections/routes.dart @@ -235,9 +235,5 @@ class AppRouter extends RootStackRouter { page: LastFMLoginRoute.page, // parentNavigatorKey: rootNavigatorKey, ), - AutoRoute( - path: "/webview", - page: WebviewRoute.page, - ), ]; } diff --git a/lib/collections/routes.gr.dart b/lib/collections/routes.gr.dart index a049fd28..291254d7 100644 --- a/lib/collections/routes.gr.dart +++ b/lib/collections/routes.gr.dart @@ -8,12 +8,11 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i45; -import 'package:flutter/material.dart' as _i46; -import 'package:flutter_inappwebview/flutter_inappwebview.dart' as _i51; -import 'package:shadcn_flutter/shadcn_flutter.dart' as _i48; -import 'package:spotify/spotify.dart' as _i47; -import 'package:spotube/models/spotify/recommendation_seeds.dart' as _i49; +import 'package:auto_route/auto_route.dart' as _i44; +import 'package:flutter/material.dart' as _i45; +import 'package:shadcn_flutter/shadcn_flutter.dart' as _i47; +import 'package:spotify/spotify.dart' as _i46; +import 'package:spotube/models/spotify/recommendation_seeds.dart' as _i48; import 'package:spotube/pages/album/album.dart' as _i2; import 'package:spotube/pages/artist/artist.dart' as _i3; import 'package:spotube/pages/connect/connect.dart' as _i6; @@ -61,13 +60,11 @@ import 'package:spotube/pages/stats/playlists/playlists.dart' as _i34; import 'package:spotube/pages/stats/stats.dart' as _i33; import 'package:spotube/pages/stats/streams/streams.dart' as _i36; import 'package:spotube/pages/track/track.dart' as _i37; -import 'package:spotube/pages/webview/webview.dart' as _i44; -import 'package:spotube/services/metadata/apis/webview.dart' as _i50; /// generated route for /// [_i1.AboutSpotubePage] -class AboutSpotubeRoute extends _i45.PageRouteInfo { - const AboutSpotubeRoute({List<_i45.PageRouteInfo>? children}) +class AboutSpotubeRoute extends _i44.PageRouteInfo { + const AboutSpotubeRoute({List<_i44.PageRouteInfo>? children}) : super( AboutSpotubeRoute.name, initialChildren: children, @@ -75,7 +72,7 @@ class AboutSpotubeRoute extends _i45.PageRouteInfo { static const String name = 'AboutSpotubeRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i1.AboutSpotubePage(); @@ -85,12 +82,12 @@ class AboutSpotubeRoute extends _i45.PageRouteInfo { /// generated route for /// [_i2.AlbumPage] -class AlbumRoute extends _i45.PageRouteInfo { +class AlbumRoute extends _i44.PageRouteInfo { AlbumRoute({ - _i46.Key? key, + _i45.Key? key, required String id, - required _i47.AlbumSimple album, - List<_i45.PageRouteInfo>? children, + required _i46.AlbumSimple album, + List<_i44.PageRouteInfo>? children, }) : super( AlbumRoute.name, args: AlbumRouteArgs( @@ -104,7 +101,7 @@ class AlbumRoute extends _i45.PageRouteInfo { static const String name = 'AlbumRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -124,11 +121,11 @@ class AlbumRouteArgs { required this.album, }); - final _i46.Key? key; + final _i45.Key? key; final String id; - final _i47.AlbumSimple album; + final _i46.AlbumSimple album; @override String toString() { @@ -138,11 +135,11 @@ class AlbumRouteArgs { /// generated route for /// [_i3.ArtistPage] -class ArtistRoute extends _i45.PageRouteInfo { +class ArtistRoute extends _i44.PageRouteInfo { ArtistRoute({ required String artistId, - _i46.Key? key, - List<_i45.PageRouteInfo>? children, + _i45.Key? key, + List<_i44.PageRouteInfo>? children, }) : super( ArtistRoute.name, args: ArtistRouteArgs( @@ -155,7 +152,7 @@ class ArtistRoute extends _i45.PageRouteInfo { static const String name = 'ArtistRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -177,7 +174,7 @@ class ArtistRouteArgs { final String artistId; - final _i46.Key? key; + final _i45.Key? key; @override String toString() { @@ -187,8 +184,8 @@ class ArtistRouteArgs { /// generated route for /// [_i4.BlackListPage] -class BlackListRoute extends _i45.PageRouteInfo { - const BlackListRoute({List<_i45.PageRouteInfo>? children}) +class BlackListRoute extends _i44.PageRouteInfo { + const BlackListRoute({List<_i44.PageRouteInfo>? children}) : super( BlackListRoute.name, initialChildren: children, @@ -196,7 +193,7 @@ class BlackListRoute extends _i45.PageRouteInfo { static const String name = 'BlackListRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i4.BlackListPage(); @@ -206,8 +203,8 @@ class BlackListRoute extends _i45.PageRouteInfo { /// generated route for /// [_i5.ConnectControlPage] -class ConnectControlRoute extends _i45.PageRouteInfo { - const ConnectControlRoute({List<_i45.PageRouteInfo>? children}) +class ConnectControlRoute extends _i44.PageRouteInfo { + const ConnectControlRoute({List<_i44.PageRouteInfo>? children}) : super( ConnectControlRoute.name, initialChildren: children, @@ -215,7 +212,7 @@ class ConnectControlRoute extends _i45.PageRouteInfo { static const String name = 'ConnectControlRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i5.ConnectControlPage(); @@ -225,8 +222,8 @@ class ConnectControlRoute extends _i45.PageRouteInfo { /// generated route for /// [_i6.ConnectPage] -class ConnectRoute extends _i45.PageRouteInfo { - const ConnectRoute({List<_i45.PageRouteInfo>? children}) +class ConnectRoute extends _i44.PageRouteInfo { + const ConnectRoute({List<_i44.PageRouteInfo>? children}) : super( ConnectRoute.name, initialChildren: children, @@ -234,7 +231,7 @@ class ConnectRoute extends _i45.PageRouteInfo { static const String name = 'ConnectRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i6.ConnectPage(); @@ -244,8 +241,8 @@ class ConnectRoute extends _i45.PageRouteInfo { /// generated route for /// [_i7.GenrePage] -class GenreRoute extends _i45.PageRouteInfo { - const GenreRoute({List<_i45.PageRouteInfo>? children}) +class GenreRoute extends _i44.PageRouteInfo { + const GenreRoute({List<_i44.PageRouteInfo>? children}) : super( GenreRoute.name, initialChildren: children, @@ -253,7 +250,7 @@ class GenreRoute extends _i45.PageRouteInfo { static const String name = 'GenreRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i7.GenrePage(); @@ -263,12 +260,12 @@ class GenreRoute extends _i45.PageRouteInfo { /// generated route for /// [_i8.GenrePlaylistsPage] -class GenrePlaylistsRoute extends _i45.PageRouteInfo { +class GenrePlaylistsRoute extends _i44.PageRouteInfo { GenrePlaylistsRoute({ - _i46.Key? key, + _i45.Key? key, required String id, - required _i47.Category category, - List<_i45.PageRouteInfo>? children, + required _i46.Category category, + List<_i44.PageRouteInfo>? children, }) : super( GenrePlaylistsRoute.name, args: GenrePlaylistsRouteArgs( @@ -282,7 +279,7 @@ class GenrePlaylistsRoute extends _i45.PageRouteInfo { static const String name = 'GenrePlaylistsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -302,11 +299,11 @@ class GenrePlaylistsRouteArgs { required this.category, }); - final _i46.Key? key; + final _i45.Key? key; final String id; - final _i47.Category category; + final _i46.Category category; @override String toString() { @@ -316,8 +313,8 @@ class GenrePlaylistsRouteArgs { /// generated route for /// [_i9.GettingStartedPage] -class GettingStartedRoute extends _i45.PageRouteInfo { - const GettingStartedRoute({List<_i45.PageRouteInfo>? children}) +class GettingStartedRoute extends _i44.PageRouteInfo { + const GettingStartedRoute({List<_i44.PageRouteInfo>? children}) : super( GettingStartedRoute.name, initialChildren: children, @@ -325,7 +322,7 @@ class GettingStartedRoute extends _i45.PageRouteInfo { static const String name = 'GettingStartedRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i9.GettingStartedPage(); @@ -336,11 +333,11 @@ class GettingStartedRoute extends _i45.PageRouteInfo { /// generated route for /// [_i10.HomeFeedSectionPage] class HomeFeedSectionRoute - extends _i45.PageRouteInfo { + extends _i44.PageRouteInfo { HomeFeedSectionRoute({ - _i48.Key? key, + _i47.Key? key, required String sectionUri, - List<_i45.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( HomeFeedSectionRoute.name, args: HomeFeedSectionRouteArgs( @@ -353,7 +350,7 @@ class HomeFeedSectionRoute static const String name = 'HomeFeedSectionRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -374,7 +371,7 @@ class HomeFeedSectionRouteArgs { required this.sectionUri, }); - final _i48.Key? key; + final _i47.Key? key; final String sectionUri; @@ -386,8 +383,8 @@ class HomeFeedSectionRouteArgs { /// generated route for /// [_i11.HomePage] -class HomeRoute extends _i45.PageRouteInfo { - const HomeRoute({List<_i45.PageRouteInfo>? children}) +class HomeRoute extends _i44.PageRouteInfo { + const HomeRoute({List<_i44.PageRouteInfo>? children}) : super( HomeRoute.name, initialChildren: children, @@ -395,7 +392,7 @@ class HomeRoute extends _i45.PageRouteInfo { static const String name = 'HomeRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i11.HomePage(); @@ -405,8 +402,8 @@ class HomeRoute extends _i45.PageRouteInfo { /// generated route for /// [_i12.LastFMLoginPage] -class LastFMLoginRoute extends _i45.PageRouteInfo { - const LastFMLoginRoute({List<_i45.PageRouteInfo>? children}) +class LastFMLoginRoute extends _i44.PageRouteInfo { + const LastFMLoginRoute({List<_i44.PageRouteInfo>? children}) : super( LastFMLoginRoute.name, initialChildren: children, @@ -414,7 +411,7 @@ class LastFMLoginRoute extends _i45.PageRouteInfo { static const String name = 'LastFMLoginRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i12.LastFMLoginPage(); @@ -424,8 +421,8 @@ class LastFMLoginRoute extends _i45.PageRouteInfo { /// generated route for /// [_i13.LibraryPage] -class LibraryRoute extends _i45.PageRouteInfo { - const LibraryRoute({List<_i45.PageRouteInfo>? children}) +class LibraryRoute extends _i44.PageRouteInfo { + const LibraryRoute({List<_i44.PageRouteInfo>? children}) : super( LibraryRoute.name, initialChildren: children, @@ -433,7 +430,7 @@ class LibraryRoute extends _i45.PageRouteInfo { static const String name = 'LibraryRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i13.LibraryPage(); @@ -443,11 +440,11 @@ class LibraryRoute extends _i45.PageRouteInfo { /// generated route for /// [_i14.LikedPlaylistPage] -class LikedPlaylistRoute extends _i45.PageRouteInfo { +class LikedPlaylistRoute extends _i44.PageRouteInfo { LikedPlaylistRoute({ - _i46.Key? key, - required _i47.PlaylistSimple playlist, - List<_i45.PageRouteInfo>? children, + _i45.Key? key, + required _i46.PlaylistSimple playlist, + List<_i44.PageRouteInfo>? children, }) : super( LikedPlaylistRoute.name, args: LikedPlaylistRouteArgs( @@ -459,7 +456,7 @@ class LikedPlaylistRoute extends _i45.PageRouteInfo { static const String name = 'LikedPlaylistRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -477,9 +474,9 @@ class LikedPlaylistRouteArgs { required this.playlist, }); - final _i46.Key? key; + final _i45.Key? key; - final _i47.PlaylistSimple playlist; + final _i46.PlaylistSimple playlist; @override String toString() { @@ -489,13 +486,13 @@ class LikedPlaylistRouteArgs { /// generated route for /// [_i15.LocalLibraryPage] -class LocalLibraryRoute extends _i45.PageRouteInfo { +class LocalLibraryRoute extends _i44.PageRouteInfo { LocalLibraryRoute({ required String location, - _i46.Key? key, + _i45.Key? key, bool isDownloads = false, bool isCache = false, - List<_i45.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( LocalLibraryRoute.name, args: LocalLibraryRouteArgs( @@ -509,7 +506,7 @@ class LocalLibraryRoute extends _i45.PageRouteInfo { static const String name = 'LocalLibraryRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -533,7 +530,7 @@ class LocalLibraryRouteArgs { final String location; - final _i46.Key? key; + final _i45.Key? key; final bool isDownloads; @@ -547,8 +544,8 @@ class LocalLibraryRouteArgs { /// generated route for /// [_i16.LogsPage] -class LogsRoute extends _i45.PageRouteInfo { - const LogsRoute({List<_i45.PageRouteInfo>? children}) +class LogsRoute extends _i44.PageRouteInfo { + const LogsRoute({List<_i44.PageRouteInfo>? children}) : super( LogsRoute.name, initialChildren: children, @@ -556,7 +553,7 @@ class LogsRoute extends _i45.PageRouteInfo { static const String name = 'LogsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i16.LogsPage(); @@ -566,8 +563,8 @@ class LogsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i17.LyricsPage] -class LyricsRoute extends _i45.PageRouteInfo { - const LyricsRoute({List<_i45.PageRouteInfo>? children}) +class LyricsRoute extends _i44.PageRouteInfo { + const LyricsRoute({List<_i44.PageRouteInfo>? children}) : super( LyricsRoute.name, initialChildren: children, @@ -575,7 +572,7 @@ class LyricsRoute extends _i45.PageRouteInfo { static const String name = 'LyricsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i17.LyricsPage(); @@ -585,11 +582,11 @@ class LyricsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i18.MiniLyricsPage] -class MiniLyricsRoute extends _i45.PageRouteInfo { +class MiniLyricsRoute extends _i44.PageRouteInfo { MiniLyricsRoute({ - _i48.Key? key, - required _i48.Size prevSize, - List<_i45.PageRouteInfo>? children, + _i47.Key? key, + required _i47.Size prevSize, + List<_i44.PageRouteInfo>? children, }) : super( MiniLyricsRoute.name, args: MiniLyricsRouteArgs( @@ -601,7 +598,7 @@ class MiniLyricsRoute extends _i45.PageRouteInfo { static const String name = 'MiniLyricsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -619,9 +616,9 @@ class MiniLyricsRouteArgs { required this.prevSize, }); - final _i48.Key? key; + final _i47.Key? key; - final _i48.Size prevSize; + final _i47.Size prevSize; @override String toString() { @@ -631,8 +628,8 @@ class MiniLyricsRouteArgs { /// generated route for /// [_i19.PlayerLyricsPage] -class PlayerLyricsRoute extends _i45.PageRouteInfo { - const PlayerLyricsRoute({List<_i45.PageRouteInfo>? children}) +class PlayerLyricsRoute extends _i44.PageRouteInfo { + const PlayerLyricsRoute({List<_i44.PageRouteInfo>? children}) : super( PlayerLyricsRoute.name, initialChildren: children, @@ -640,7 +637,7 @@ class PlayerLyricsRoute extends _i45.PageRouteInfo { static const String name = 'PlayerLyricsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i19.PlayerLyricsPage(); @@ -650,8 +647,8 @@ class PlayerLyricsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i20.PlayerQueuePage] -class PlayerQueueRoute extends _i45.PageRouteInfo { - const PlayerQueueRoute({List<_i45.PageRouteInfo>? children}) +class PlayerQueueRoute extends _i44.PageRouteInfo { + const PlayerQueueRoute({List<_i44.PageRouteInfo>? children}) : super( PlayerQueueRoute.name, initialChildren: children, @@ -659,7 +656,7 @@ class PlayerQueueRoute extends _i45.PageRouteInfo { static const String name = 'PlayerQueueRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i20.PlayerQueuePage(); @@ -669,8 +666,8 @@ class PlayerQueueRoute extends _i45.PageRouteInfo { /// generated route for /// [_i21.PlayerTrackSourcesPage] -class PlayerTrackSourcesRoute extends _i45.PageRouteInfo { - const PlayerTrackSourcesRoute({List<_i45.PageRouteInfo>? children}) +class PlayerTrackSourcesRoute extends _i44.PageRouteInfo { + const PlayerTrackSourcesRoute({List<_i44.PageRouteInfo>? children}) : super( PlayerTrackSourcesRoute.name, initialChildren: children, @@ -678,7 +675,7 @@ class PlayerTrackSourcesRoute extends _i45.PageRouteInfo { static const String name = 'PlayerTrackSourcesRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i21.PlayerTrackSourcesPage(); @@ -689,11 +686,11 @@ class PlayerTrackSourcesRoute extends _i45.PageRouteInfo { /// generated route for /// [_i22.PlaylistGenerateResultPage] class PlaylistGenerateResultRoute - extends _i45.PageRouteInfo { + extends _i44.PageRouteInfo { PlaylistGenerateResultRoute({ - _i48.Key? key, - required _i49.GeneratePlaylistProviderInput state, - List<_i45.PageRouteInfo>? children, + _i47.Key? key, + required _i48.GeneratePlaylistProviderInput state, + List<_i44.PageRouteInfo>? children, }) : super( PlaylistGenerateResultRoute.name, args: PlaylistGenerateResultRouteArgs( @@ -705,7 +702,7 @@ class PlaylistGenerateResultRoute static const String name = 'PlaylistGenerateResultRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -723,9 +720,9 @@ class PlaylistGenerateResultRouteArgs { required this.state, }); - final _i48.Key? key; + final _i47.Key? key; - final _i49.GeneratePlaylistProviderInput state; + final _i48.GeneratePlaylistProviderInput state; @override String toString() { @@ -735,8 +732,8 @@ class PlaylistGenerateResultRouteArgs { /// generated route for /// [_i23.PlaylistGeneratorPage] -class PlaylistGeneratorRoute extends _i45.PageRouteInfo { - const PlaylistGeneratorRoute({List<_i45.PageRouteInfo>? children}) +class PlaylistGeneratorRoute extends _i44.PageRouteInfo { + const PlaylistGeneratorRoute({List<_i44.PageRouteInfo>? children}) : super( PlaylistGeneratorRoute.name, initialChildren: children, @@ -744,7 +741,7 @@ class PlaylistGeneratorRoute extends _i45.PageRouteInfo { static const String name = 'PlaylistGeneratorRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i23.PlaylistGeneratorPage(); @@ -754,12 +751,12 @@ class PlaylistGeneratorRoute extends _i45.PageRouteInfo { /// generated route for /// [_i24.PlaylistPage] -class PlaylistRoute extends _i45.PageRouteInfo { +class PlaylistRoute extends _i44.PageRouteInfo { PlaylistRoute({ - _i46.Key? key, + _i45.Key? key, required String id, - required _i47.PlaylistSimple playlist, - List<_i45.PageRouteInfo>? children, + required _i46.PlaylistSimple playlist, + List<_i44.PageRouteInfo>? children, }) : super( PlaylistRoute.name, args: PlaylistRouteArgs( @@ -773,7 +770,7 @@ class PlaylistRoute extends _i45.PageRouteInfo { static const String name = 'PlaylistRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final args = data.argsAs(); @@ -793,11 +790,11 @@ class PlaylistRouteArgs { required this.playlist, }); - final _i46.Key? key; + final _i45.Key? key; final String id; - final _i47.PlaylistSimple playlist; + final _i46.PlaylistSimple playlist; @override String toString() { @@ -807,8 +804,8 @@ class PlaylistRouteArgs { /// generated route for /// [_i25.ProfilePage] -class ProfileRoute extends _i45.PageRouteInfo { - const ProfileRoute({List<_i45.PageRouteInfo>? children}) +class ProfileRoute extends _i44.PageRouteInfo { + const ProfileRoute({List<_i44.PageRouteInfo>? children}) : super( ProfileRoute.name, initialChildren: children, @@ -816,7 +813,7 @@ class ProfileRoute extends _i45.PageRouteInfo { static const String name = 'ProfileRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i25.ProfilePage(); @@ -826,8 +823,8 @@ class ProfileRoute extends _i45.PageRouteInfo { /// generated route for /// [_i26.RootAppPage] -class RootAppRoute extends _i45.PageRouteInfo { - const RootAppRoute({List<_i45.PageRouteInfo>? children}) +class RootAppRoute extends _i44.PageRouteInfo { + const RootAppRoute({List<_i44.PageRouteInfo>? children}) : super( RootAppRoute.name, initialChildren: children, @@ -835,7 +832,7 @@ class RootAppRoute extends _i45.PageRouteInfo { static const String name = 'RootAppRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i26.RootAppPage(); @@ -845,8 +842,8 @@ class RootAppRoute extends _i45.PageRouteInfo { /// generated route for /// [_i27.SearchPage] -class SearchRoute extends _i45.PageRouteInfo { - const SearchRoute({List<_i45.PageRouteInfo>? children}) +class SearchRoute extends _i44.PageRouteInfo { + const SearchRoute({List<_i44.PageRouteInfo>? children}) : super( SearchRoute.name, initialChildren: children, @@ -854,7 +851,7 @@ class SearchRoute extends _i45.PageRouteInfo { static const String name = 'SearchRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i27.SearchPage(); @@ -864,8 +861,8 @@ class SearchRoute extends _i45.PageRouteInfo { /// generated route for /// [_i28.SettingsMetadataProviderPage] -class SettingsMetadataProviderRoute extends _i45.PageRouteInfo { - const SettingsMetadataProviderRoute({List<_i45.PageRouteInfo>? children}) +class SettingsMetadataProviderRoute extends _i44.PageRouteInfo { + const SettingsMetadataProviderRoute({List<_i44.PageRouteInfo>? children}) : super( SettingsMetadataProviderRoute.name, initialChildren: children, @@ -873,7 +870,7 @@ class SettingsMetadataProviderRoute extends _i45.PageRouteInfo { static const String name = 'SettingsMetadataProviderRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i28.SettingsMetadataProviderPage(); @@ -883,8 +880,8 @@ class SettingsMetadataProviderRoute extends _i45.PageRouteInfo { /// generated route for /// [_i29.SettingsPage] -class SettingsRoute extends _i45.PageRouteInfo { - const SettingsRoute({List<_i45.PageRouteInfo>? children}) +class SettingsRoute extends _i44.PageRouteInfo { + const SettingsRoute({List<_i44.PageRouteInfo>? children}) : super( SettingsRoute.name, initialChildren: children, @@ -892,7 +889,7 @@ class SettingsRoute extends _i45.PageRouteInfo { static const String name = 'SettingsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i29.SettingsPage(); @@ -902,8 +899,8 @@ class SettingsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i30.StatsAlbumsPage] -class StatsAlbumsRoute extends _i45.PageRouteInfo { - const StatsAlbumsRoute({List<_i45.PageRouteInfo>? children}) +class StatsAlbumsRoute extends _i44.PageRouteInfo { + const StatsAlbumsRoute({List<_i44.PageRouteInfo>? children}) : super( StatsAlbumsRoute.name, initialChildren: children, @@ -911,7 +908,7 @@ class StatsAlbumsRoute extends _i45.PageRouteInfo { static const String name = 'StatsAlbumsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i30.StatsAlbumsPage(); @@ -921,8 +918,8 @@ class StatsAlbumsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i31.StatsArtistsPage] -class StatsArtistsRoute extends _i45.PageRouteInfo { - const StatsArtistsRoute({List<_i45.PageRouteInfo>? children}) +class StatsArtistsRoute extends _i44.PageRouteInfo { + const StatsArtistsRoute({List<_i44.PageRouteInfo>? children}) : super( StatsArtistsRoute.name, initialChildren: children, @@ -930,7 +927,7 @@ class StatsArtistsRoute extends _i45.PageRouteInfo { static const String name = 'StatsArtistsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i31.StatsArtistsPage(); @@ -940,8 +937,8 @@ class StatsArtistsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i32.StatsMinutesPage] -class StatsMinutesRoute extends _i45.PageRouteInfo { - const StatsMinutesRoute({List<_i45.PageRouteInfo>? children}) +class StatsMinutesRoute extends _i44.PageRouteInfo { + const StatsMinutesRoute({List<_i44.PageRouteInfo>? children}) : super( StatsMinutesRoute.name, initialChildren: children, @@ -949,7 +946,7 @@ class StatsMinutesRoute extends _i45.PageRouteInfo { static const String name = 'StatsMinutesRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i32.StatsMinutesPage(); @@ -959,8 +956,8 @@ class StatsMinutesRoute extends _i45.PageRouteInfo { /// generated route for /// [_i33.StatsPage] -class StatsRoute extends _i45.PageRouteInfo { - const StatsRoute({List<_i45.PageRouteInfo>? children}) +class StatsRoute extends _i44.PageRouteInfo { + const StatsRoute({List<_i44.PageRouteInfo>? children}) : super( StatsRoute.name, initialChildren: children, @@ -968,7 +965,7 @@ class StatsRoute extends _i45.PageRouteInfo { static const String name = 'StatsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i33.StatsPage(); @@ -978,8 +975,8 @@ class StatsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i34.StatsPlaylistsPage] -class StatsPlaylistsRoute extends _i45.PageRouteInfo { - const StatsPlaylistsRoute({List<_i45.PageRouteInfo>? children}) +class StatsPlaylistsRoute extends _i44.PageRouteInfo { + const StatsPlaylistsRoute({List<_i44.PageRouteInfo>? children}) : super( StatsPlaylistsRoute.name, initialChildren: children, @@ -987,7 +984,7 @@ class StatsPlaylistsRoute extends _i45.PageRouteInfo { static const String name = 'StatsPlaylistsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i34.StatsPlaylistsPage(); @@ -997,8 +994,8 @@ class StatsPlaylistsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i35.StatsStreamFeesPage] -class StatsStreamFeesRoute extends _i45.PageRouteInfo { - const StatsStreamFeesRoute({List<_i45.PageRouteInfo>? children}) +class StatsStreamFeesRoute extends _i44.PageRouteInfo { + const StatsStreamFeesRoute({List<_i44.PageRouteInfo>? children}) : super( StatsStreamFeesRoute.name, initialChildren: children, @@ -1006,7 +1003,7 @@ class StatsStreamFeesRoute extends _i45.PageRouteInfo { static const String name = 'StatsStreamFeesRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i35.StatsStreamFeesPage(); @@ -1016,8 +1013,8 @@ class StatsStreamFeesRoute extends _i45.PageRouteInfo { /// generated route for /// [_i36.StatsStreamsPage] -class StatsStreamsRoute extends _i45.PageRouteInfo { - const StatsStreamsRoute({List<_i45.PageRouteInfo>? children}) +class StatsStreamsRoute extends _i44.PageRouteInfo { + const StatsStreamsRoute({List<_i44.PageRouteInfo>? children}) : super( StatsStreamsRoute.name, initialChildren: children, @@ -1025,7 +1022,7 @@ class StatsStreamsRoute extends _i45.PageRouteInfo { static const String name = 'StatsStreamsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i36.StatsStreamsPage(); @@ -1035,11 +1032,11 @@ class StatsStreamsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i37.TrackPage] -class TrackRoute extends _i45.PageRouteInfo { +class TrackRoute extends _i44.PageRouteInfo { TrackRoute({ - _i48.Key? key, + _i47.Key? key, required String trackId, - List<_i45.PageRouteInfo>? children, + List<_i44.PageRouteInfo>? children, }) : super( TrackRoute.name, args: TrackRouteArgs( @@ -1052,7 +1049,7 @@ class TrackRoute extends _i45.PageRouteInfo { static const String name = 'TrackRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { final pathParams = data.inheritedPathParams; @@ -1072,7 +1069,7 @@ class TrackRouteArgs { required this.trackId, }); - final _i48.Key? key; + final _i47.Key? key; final String trackId; @@ -1084,8 +1081,8 @@ class TrackRouteArgs { /// generated route for /// [_i38.UserAlbumsPage] -class UserAlbumsRoute extends _i45.PageRouteInfo { - const UserAlbumsRoute({List<_i45.PageRouteInfo>? children}) +class UserAlbumsRoute extends _i44.PageRouteInfo { + const UserAlbumsRoute({List<_i44.PageRouteInfo>? children}) : super( UserAlbumsRoute.name, initialChildren: children, @@ -1093,7 +1090,7 @@ class UserAlbumsRoute extends _i45.PageRouteInfo { static const String name = 'UserAlbumsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i38.UserAlbumsPage(); @@ -1103,8 +1100,8 @@ class UserAlbumsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i39.UserArtistsPage] -class UserArtistsRoute extends _i45.PageRouteInfo { - const UserArtistsRoute({List<_i45.PageRouteInfo>? children}) +class UserArtistsRoute extends _i44.PageRouteInfo { + const UserArtistsRoute({List<_i44.PageRouteInfo>? children}) : super( UserArtistsRoute.name, initialChildren: children, @@ -1112,7 +1109,7 @@ class UserArtistsRoute extends _i45.PageRouteInfo { static const String name = 'UserArtistsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i39.UserArtistsPage(); @@ -1122,8 +1119,8 @@ class UserArtistsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i40.UserDownloadsPage] -class UserDownloadsRoute extends _i45.PageRouteInfo { - const UserDownloadsRoute({List<_i45.PageRouteInfo>? children}) +class UserDownloadsRoute extends _i44.PageRouteInfo { + const UserDownloadsRoute({List<_i44.PageRouteInfo>? children}) : super( UserDownloadsRoute.name, initialChildren: children, @@ -1131,7 +1128,7 @@ class UserDownloadsRoute extends _i45.PageRouteInfo { static const String name = 'UserDownloadsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i40.UserDownloadsPage(); @@ -1141,8 +1138,8 @@ class UserDownloadsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i41.UserLocalLibraryPage] -class UserLocalLibraryRoute extends _i45.PageRouteInfo { - const UserLocalLibraryRoute({List<_i45.PageRouteInfo>? children}) +class UserLocalLibraryRoute extends _i44.PageRouteInfo { + const UserLocalLibraryRoute({List<_i44.PageRouteInfo>? children}) : super( UserLocalLibraryRoute.name, initialChildren: children, @@ -1150,7 +1147,7 @@ class UserLocalLibraryRoute extends _i45.PageRouteInfo { static const String name = 'UserLocalLibraryRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i41.UserLocalLibraryPage(); @@ -1160,8 +1157,8 @@ class UserLocalLibraryRoute extends _i45.PageRouteInfo { /// generated route for /// [_i42.UserPlaylistsPage] -class UserPlaylistsRoute extends _i45.PageRouteInfo { - const UserPlaylistsRoute({List<_i45.PageRouteInfo>? children}) +class UserPlaylistsRoute extends _i44.PageRouteInfo { + const UserPlaylistsRoute({List<_i44.PageRouteInfo>? children}) : super( UserPlaylistsRoute.name, initialChildren: children, @@ -1169,7 +1166,7 @@ class UserPlaylistsRoute extends _i45.PageRouteInfo { static const String name = 'UserPlaylistsRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i42.UserPlaylistsPage(); @@ -1179,8 +1176,8 @@ class UserPlaylistsRoute extends _i45.PageRouteInfo { /// generated route for /// [_i43.WebViewLoginPage] -class WebViewLoginRoute extends _i45.PageRouteInfo { - const WebViewLoginRoute({List<_i45.PageRouteInfo>? children}) +class WebViewLoginRoute extends _i44.PageRouteInfo { + const WebViewLoginRoute({List<_i44.PageRouteInfo>? children}) : super( WebViewLoginRoute.name, initialChildren: children, @@ -1188,75 +1185,10 @@ class WebViewLoginRoute extends _i45.PageRouteInfo { static const String name = 'WebViewLoginRoute'; - static _i45.PageInfo page = _i45.PageInfo( + static _i44.PageInfo page = _i44.PageInfo( name, builder: (data) { return const _i43.WebViewLoginPage(); }, ); } - -/// generated route for -/// [_i44.WebviewPage] -class WebviewRoute extends _i45.PageRouteInfo { - WebviewRoute({ - _i48.Key? key, - _i50.WebviewInitialSettings? initialSettings, - String? url, - void Function( - _i51.InAppWebViewController, - _i51.WebUri?, - )? onLoadStop, - List<_i45.PageRouteInfo>? children, - }) : super( - WebviewRoute.name, - args: WebviewRouteArgs( - key: key, - initialSettings: initialSettings, - url: url, - onLoadStop: onLoadStop, - ), - initialChildren: children, - ); - - static const String name = 'WebviewRoute'; - - static _i45.PageInfo page = _i45.PageInfo( - name, - builder: (data) { - final args = - data.argsAs(orElse: () => const WebviewRouteArgs()); - return _i44.WebviewPage( - key: args.key, - initialSettings: args.initialSettings, - url: args.url, - onLoadStop: args.onLoadStop, - ); - }, - ); -} - -class WebviewRouteArgs { - const WebviewRouteArgs({ - this.key, - this.initialSettings, - this.url, - this.onLoadStop, - }); - - final _i48.Key? key; - - final _i50.WebviewInitialSettings? initialSettings; - - final String? url; - - final void Function( - _i51.InAppWebViewController, - _i51.WebUri?, - )? onLoadStop; - - @override - String toString() { - return 'WebviewRouteArgs{key: $key, initialSettings: $initialSettings, url: $url, onLoadStop: $onLoadStop}'; - } -} diff --git a/lib/main.dart b/lib/main.dart index 3e9edbcd..6a619ad7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -147,7 +147,7 @@ class Spotube extends HookConsumerWidget { ref.listen(bonsoirProvider, (_, __) {}); ref.listen(connectClientsProvider, (_, __) {}); ref.listen(metadataPluginsProvider, (_, __) {}); - ref.listen(metadataPluginApiProvider, (_, __) {}); + ref.listen(metadataPluginProvider, (_, __) {}); ref.listen(serverProvider, (_, __) {}); ref.listen(trayManagerProvider, (_, __) {}); diff --git a/lib/models/metadata/image.dart b/lib/models/metadata/image.dart index aa20c385..1fc3bb30 100644 --- a/lib/models/metadata/image.dart +++ b/lib/models/metadata/image.dart @@ -3,9 +3,9 @@ part of 'metadata.dart'; @freezed class SpotubeImageObject with _$SpotubeImageObject { factory SpotubeImageObject({ - required final String url, - required final int width, - required final int height, + required String url, + int? width, + int? height, }) = _SpotubeImageObject; factory SpotubeImageObject.fromJson(Map json) => diff --git a/lib/models/metadata/metadata.freezed.dart b/lib/models/metadata/metadata.freezed.dart index f5544cb5..7f420732 100644 --- a/lib/models/metadata/metadata.freezed.dart +++ b/lib/models/metadata/metadata.freezed.dart @@ -775,8 +775,8 @@ SpotubeImageObject _$SpotubeImageObjectFromJson(Map json) { /// @nodoc mixin _$SpotubeImageObject { String get url => throw _privateConstructorUsedError; - int get width => throw _privateConstructorUsedError; - int get height => throw _privateConstructorUsedError; + int? get width => throw _privateConstructorUsedError; + int? get height => throw _privateConstructorUsedError; /// Serializes this SpotubeImageObject to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -794,7 +794,7 @@ abstract class $SpotubeImageObjectCopyWith<$Res> { SpotubeImageObject value, $Res Function(SpotubeImageObject) then) = _$SpotubeImageObjectCopyWithImpl<$Res, SpotubeImageObject>; @useResult - $Res call({String url, int width, int height}); + $Res call({String url, int? width, int? height}); } /// @nodoc @@ -813,22 +813,22 @@ class _$SpotubeImageObjectCopyWithImpl<$Res, $Val extends SpotubeImageObject> @override $Res call({ Object? url = null, - Object? width = null, - Object? height = null, + Object? width = freezed, + Object? height = freezed, }) { return _then(_value.copyWith( url: null == url ? _value.url : url // ignore: cast_nullable_to_non_nullable as String, - width: null == width + width: freezed == width ? _value.width : width // ignore: cast_nullable_to_non_nullable - as int, - height: null == height + as int?, + height: freezed == height ? _value.height : height // ignore: cast_nullable_to_non_nullable - as int, + as int?, ) as $Val); } } @@ -841,7 +841,7 @@ abstract class _$$SpotubeImageObjectImplCopyWith<$Res> __$$SpotubeImageObjectImplCopyWithImpl<$Res>; @override @useResult - $Res call({String url, int width, int height}); + $Res call({String url, int? width, int? height}); } /// @nodoc @@ -858,22 +858,22 @@ class __$$SpotubeImageObjectImplCopyWithImpl<$Res> @override $Res call({ Object? url = null, - Object? width = null, - Object? height = null, + Object? width = freezed, + Object? height = freezed, }) { return _then(_$SpotubeImageObjectImpl( url: null == url ? _value.url : url // ignore: cast_nullable_to_non_nullable as String, - width: null == width + width: freezed == width ? _value.width : width // ignore: cast_nullable_to_non_nullable - as int, - height: null == height + as int?, + height: freezed == height ? _value.height : height // ignore: cast_nullable_to_non_nullable - as int, + as int?, )); } } @@ -881,8 +881,7 @@ class __$$SpotubeImageObjectImplCopyWithImpl<$Res> /// @nodoc @JsonSerializable() class _$SpotubeImageObjectImpl implements _SpotubeImageObject { - _$SpotubeImageObjectImpl( - {required this.url, required this.width, required this.height}); + _$SpotubeImageObjectImpl({required this.url, this.width, this.height}); factory _$SpotubeImageObjectImpl.fromJson(Map json) => _$$SpotubeImageObjectImplFromJson(json); @@ -890,9 +889,9 @@ class _$SpotubeImageObjectImpl implements _SpotubeImageObject { @override final String url; @override - final int width; + final int? width; @override - final int height; + final int? height; @override String toString() { @@ -933,8 +932,8 @@ class _$SpotubeImageObjectImpl implements _SpotubeImageObject { abstract class _SpotubeImageObject implements SpotubeImageObject { factory _SpotubeImageObject( {required final String url, - required final int width, - required final int height}) = _$SpotubeImageObjectImpl; + final int? width, + final int? height}) = _$SpotubeImageObjectImpl; factory _SpotubeImageObject.fromJson(Map json) = _$SpotubeImageObjectImpl.fromJson; @@ -942,9 +941,9 @@ abstract class _SpotubeImageObject implements SpotubeImageObject { @override String get url; @override - int get width; + int? get width; @override - int get height; + int? get height; /// Create a copy of SpotubeImageObject /// with the given fields replaced by the non-null parameter values. @@ -2192,11 +2191,10 @@ SpotubeUserObject _$SpotubeUserObjectFromJson(Map json) { /// @nodoc mixin _$SpotubeUserObject { - String get uid => throw _privateConstructorUsedError; + String get id => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError; - List get avatars => throw _privateConstructorUsedError; - String get externalUrl => throw _privateConstructorUsedError; - String get displayName => throw _privateConstructorUsedError; + List get images => throw _privateConstructorUsedError; + String get externalUri => throw _privateConstructorUsedError; /// Serializes this SpotubeUserObject to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -2215,11 +2213,10 @@ abstract class $SpotubeUserObjectCopyWith<$Res> { _$SpotubeUserObjectCopyWithImpl<$Res, SpotubeUserObject>; @useResult $Res call( - {String uid, + {String id, String name, - List avatars, - String externalUrl, - String displayName}); + List images, + String externalUri}); } /// @nodoc @@ -2237,32 +2234,27 @@ class _$SpotubeUserObjectCopyWithImpl<$Res, $Val extends SpotubeUserObject> @pragma('vm:prefer-inline') @override $Res call({ - Object? uid = null, + Object? id = null, Object? name = null, - Object? avatars = null, - Object? externalUrl = null, - Object? displayName = null, + Object? images = null, + Object? externalUri = null, }) { return _then(_value.copyWith( - uid: null == uid - ? _value.uid - : uid // ignore: cast_nullable_to_non_nullable + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable as String, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable as String, - avatars: null == avatars - ? _value.avatars - : avatars // ignore: cast_nullable_to_non_nullable + images: null == images + ? _value.images + : images // ignore: cast_nullable_to_non_nullable as List, - externalUrl: null == externalUrl - ? _value.externalUrl - : externalUrl // ignore: cast_nullable_to_non_nullable - as String, - displayName: null == displayName - ? _value.displayName - : displayName // ignore: cast_nullable_to_non_nullable + externalUri: null == externalUri + ? _value.externalUri + : externalUri // ignore: cast_nullable_to_non_nullable as String, ) as $Val); } @@ -2277,11 +2269,10 @@ abstract class _$$SpotubeUserObjectImplCopyWith<$Res> @override @useResult $Res call( - {String uid, + {String id, String name, - List avatars, - String externalUrl, - String displayName}); + List images, + String externalUri}); } /// @nodoc @@ -2297,32 +2288,27 @@ class __$$SpotubeUserObjectImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? uid = null, + Object? id = null, Object? name = null, - Object? avatars = null, - Object? externalUrl = null, - Object? displayName = null, + Object? images = null, + Object? externalUri = null, }) { return _then(_$SpotubeUserObjectImpl( - uid: null == uid - ? _value.uid - : uid // ignore: cast_nullable_to_non_nullable + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable as String, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable as String, - avatars: null == avatars - ? _value._avatars - : avatars // ignore: cast_nullable_to_non_nullable + images: null == images + ? _value._images + : images // ignore: cast_nullable_to_non_nullable as List, - externalUrl: null == externalUrl - ? _value.externalUrl - : externalUrl // ignore: cast_nullable_to_non_nullable - as String, - displayName: null == displayName - ? _value.displayName - : displayName // ignore: cast_nullable_to_non_nullable + externalUri: null == externalUri + ? _value.externalUri + : externalUri // ignore: cast_nullable_to_non_nullable as String, )); } @@ -2332,37 +2318,34 @@ class __$$SpotubeUserObjectImplCopyWithImpl<$Res> @JsonSerializable() class _$SpotubeUserObjectImpl implements _SpotubeUserObject { _$SpotubeUserObjectImpl( - {required this.uid, + {required this.id, required this.name, - final List avatars = const [], - required this.externalUrl, - required this.displayName}) - : _avatars = avatars; + final List images = const [], + required this.externalUri}) + : _images = images; factory _$SpotubeUserObjectImpl.fromJson(Map json) => _$$SpotubeUserObjectImplFromJson(json); @override - final String uid; + final String id; @override final String name; - final List _avatars; + final List _images; @override @JsonKey() - List get avatars { - if (_avatars is EqualUnmodifiableListView) return _avatars; + List get images { + if (_images is EqualUnmodifiableListView) return _images; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_avatars); + return EqualUnmodifiableListView(_images); } @override - final String externalUrl; - @override - final String displayName; + final String externalUri; @override String toString() { - return 'SpotubeUserObject(uid: $uid, name: $name, avatars: $avatars, externalUrl: $externalUrl, displayName: $displayName)'; + return 'SpotubeUserObject(id: $id, name: $name, images: $images, externalUri: $externalUri)'; } @override @@ -2370,19 +2353,17 @@ class _$SpotubeUserObjectImpl implements _SpotubeUserObject { return identical(this, other) || (other.runtimeType == runtimeType && other is _$SpotubeUserObjectImpl && - (identical(other.uid, uid) || other.uid == uid) && + (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - const DeepCollectionEquality().equals(other._avatars, _avatars) && - (identical(other.externalUrl, externalUrl) || - other.externalUrl == externalUrl) && - (identical(other.displayName, displayName) || - other.displayName == displayName)); + const DeepCollectionEquality().equals(other._images, _images) && + (identical(other.externalUri, externalUri) || + other.externalUri == externalUri)); } @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => Object.hash(runtimeType, uid, name, - const DeepCollectionEquality().hash(_avatars), externalUrl, displayName); + int get hashCode => Object.hash(runtimeType, id, name, + const DeepCollectionEquality().hash(_images), externalUri); /// Create a copy of SpotubeUserObject /// with the given fields replaced by the non-null parameter values. @@ -2403,25 +2384,22 @@ class _$SpotubeUserObjectImpl implements _SpotubeUserObject { abstract class _SpotubeUserObject implements SpotubeUserObject { factory _SpotubeUserObject( - {required final String uid, + {required final String id, required final String name, - final List avatars, - required final String externalUrl, - required final String displayName}) = _$SpotubeUserObjectImpl; + final List images, + required final String externalUri}) = _$SpotubeUserObjectImpl; factory _SpotubeUserObject.fromJson(Map json) = _$SpotubeUserObjectImpl.fromJson; @override - String get uid; + String get id; @override String get name; @override - List get avatars; + List get images; @override - String get externalUrl; - @override - String get displayName; + String get externalUri; /// Create a copy of SpotubeUserObject /// with the given fields replaced by the non-null parameter values. diff --git a/lib/models/metadata/metadata.g.dart b/lib/models/metadata/metadata.g.dart index 7ae2cc75..216cf366 100644 --- a/lib/models/metadata/metadata.g.dart +++ b/lib/models/metadata/metadata.g.dart @@ -84,8 +84,8 @@ Map _$$SpotubeFeedObjectImplToJson( _$SpotubeImageObjectImpl _$$SpotubeImageObjectImplFromJson(Map json) => _$SpotubeImageObjectImpl( url: json['url'] as String, - width: (json['width'] as num).toInt(), - height: (json['height'] as num).toInt(), + width: (json['width'] as num?)?.toInt(), + height: (json['height'] as num?)?.toInt(), ); Map _$$SpotubeImageObjectImplToJson( @@ -203,25 +203,23 @@ Map _$$SpotubeTrackObjectImplToJson( _$SpotubeUserObjectImpl _$$SpotubeUserObjectImplFromJson(Map json) => _$SpotubeUserObjectImpl( - uid: json['uid'] as String, + id: json['id'] as String, name: json['name'] as String, - avatars: (json['avatars'] as List?) + images: (json['images'] as List?) ?.map((e) => SpotubeImageObject.fromJson( Map.from(e as Map))) .toList() ?? const [], - externalUrl: json['externalUrl'] as String, - displayName: json['displayName'] as String, + externalUri: json['externalUri'] as String, ); Map _$$SpotubeUserObjectImplToJson( _$SpotubeUserObjectImpl instance) => { - 'uid': instance.uid, + 'id': instance.id, 'name': instance.name, - 'avatars': instance.avatars.map((e) => e.toJson()).toList(), - 'externalUrl': instance.externalUrl, - 'displayName': instance.displayName, + 'images': instance.images.map((e) => e.toJson()).toList(), + 'externalUri': instance.externalUri, }; _$PluginConfigurationImpl _$$PluginConfigurationImplFromJson(Map json) => diff --git a/lib/models/metadata/user.dart b/lib/models/metadata/user.dart index 878f2da6..cd041f9c 100644 --- a/lib/models/metadata/user.dart +++ b/lib/models/metadata/user.dart @@ -3,11 +3,10 @@ part of 'metadata.dart'; @freezed class SpotubeUserObject with _$SpotubeUserObject { factory SpotubeUserObject({ - required final String uid, + required final String id, required final String name, - @Default([]) final List avatars, - required final String externalUrl, - required final String displayName, + @Default([]) final List images, + required final String externalUri, }) = _SpotubeUserObject; factory SpotubeUserObject.fromJson(Map json) => diff --git a/lib/pages/settings/metadata_plugins.dart b/lib/pages/settings/metadata_plugins.dart index 35ea5fdd..283cf715 100644 --- a/lib/pages/settings/metadata_plugins.dart +++ b/lib/pages/settings/metadata_plugins.dart @@ -7,6 +7,7 @@ import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/form/text_form_field.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; +import 'package:spotube/models/metadata/metadata.dart'; import 'package:spotube/provider/metadata_plugin/auth.dart'; import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart'; import 'package:file_picker/file_picker.dart'; @@ -21,10 +22,8 @@ class SettingsMetadataProviderPage extends HookConsumerWidget { final plugins = ref.watch(metadataPluginsProvider); final pluginsNotifier = ref.watch(metadataPluginsProvider.notifier); - final metadataApi = ref.watch(metadataPluginApiProvider); - final isAuthenticated = ref.watch(metadataAuthenticatedProvider); - - final artists = ref.watch(metadataUserArtistsProvider); + final metadataPlugin = ref.watch(metadataPluginProvider); + final isAuthenticated = ref.watch(metadataPluginAuthenticatedProvider); return Scaffold( headers: const [ @@ -111,9 +110,7 @@ class SettingsMetadataProviderPage extends HookConsumerWidget { final plugin = plugins.asData!.value.plugins[index]; final isDefault = plugins.asData!.value.defaultPlugin == index; final requiresAuth = isDefault && - metadataApi.hasValue && - metadataApi.asData?.value?.signatureFlags.requiresAuth == - true; + plugin.abilities.contains(PluginAbilities.authentication); return Card( child: Column( spacing: 8, @@ -153,8 +150,8 @@ class SettingsMetadataProviderPage extends HookConsumerWidget { if (isAuthenticated.asData?.value != true) Button.primary( onPressed: () async { - await metadataApi.asData?.value - ?.authenticate(); + await metadataPlugin.asData?.value?.auth + .authenticate(); }, leading: const Icon(SpotubeIcons.login), child: const Text("Login"), @@ -162,7 +159,8 @@ class SettingsMetadataProviderPage extends HookConsumerWidget { else Button.destructive( onPressed: () async { - await metadataApi.asData?.value?.logout(); + await metadataPlugin.asData?.value?.auth + .logout(); }, leading: const Icon(SpotubeIcons.logout), child: const Text("Logout"), diff --git a/lib/pages/webview/webview.dart b/lib/pages/webview/webview.dart deleted file mode 100644 index b4ce47b3..00000000 --- a/lib/pages/webview/webview.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter_inappwebview/flutter_inappwebview.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; -import 'package:spotube/components/button/back_button.dart'; -import 'package:spotube/components/titlebar/titlebar.dart'; -import 'package:spotube/services/metadata/apis/webview.dart'; - -@RoutePage() -class WebviewPage extends StatelessWidget { - final WebviewInitialSettings? initialSettings; - final String? url; - final void Function(InAppWebViewController controller, WebUri? url)? - onLoadStop; - - const WebviewPage({ - super.key, - this.initialSettings, - this.url, - this.onLoadStop, - }); - - @override - Widget build(BuildContext context) { - return SafeArea( - bottom: false, - child: Scaffold( - headers: const [ - TitleBar( - leading: [BackButton(color: Colors.white)], - backgroundColor: Colors.transparent, - ), - ], - floatingHeader: true, - child: InAppWebView( - initialSettings: InAppWebViewSettings( - userAgent: initialSettings?.userAgent ?? - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 safari/537.36", - incognito: initialSettings?.incognito ?? false, - clearCache: initialSettings?.clearCache ?? false, - clearSessionCache: initialSettings?.clearSessionCache ?? false, - ), - initialUrlRequest: URLRequest( - url: WebUri("https://accounts.spotify.com/"), - ), - onPermissionRequest: (controller, permissionRequest) async { - return PermissionResponse( - resources: permissionRequest.resources, - action: PermissionResponseAction.GRANT, - ); - }, - onLoadStop: onLoadStop, - ), - ), - ); - } -} diff --git a/lib/provider/metadata_plugin/auth.dart b/lib/provider/metadata_plugin/auth.dart index 0ccc9cd4..9aa696fc 100644 --- a/lib/provider/metadata_plugin/auth.dart +++ b/lib/provider/metadata_plugin/auth.dart @@ -1,49 +1,37 @@ -import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'dart:async'; + +import 'package:riverpod/riverpod.dart'; +import 'package:spotube/models/metadata/metadata.dart'; import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart'; -class MetadataAuthenticationNotifier extends AsyncNotifier { - MetadataAuthenticationNotifier(); +class MetadataPluginAuthenticatedNotifier extends AsyncNotifier { @override - build() async { - final metadataApi = await ref.watch(metadataPluginApiProvider.future); - - if (metadataApi?.signatureFlags.requiresAuth != true) { + FutureOr build() async { + final defaultPluginConfig = ref.watch(metadataPluginsProvider); + if (defaultPluginConfig.asData?.value.defaultPluginConfig?.abilities + .contains(PluginAbilities.authentication) != + true) { return false; } - final subscription = metadataApi?.authenticatedStream.listen((event) { - state = AsyncValue.data(event); + final defaultPlugin = await ref.watch(metadataPluginProvider.future); + if (defaultPlugin == null) { + return false; + } + + final sub = defaultPlugin.auth.authStateStream.listen((event) { + state = AsyncData(defaultPlugin.auth.isAuthenticated()); }); ref.onDispose(() { - subscription?.cancel(); + sub.cancel(); }); - return await metadataApi?.isAuthenticated() ?? false; - } - - Future login() async { - final metadataApi = await ref.read(metadataPluginApiProvider.future); - - if (metadataApi == null || !metadataApi.signatureFlags.requiresAuth) { - return; - } - - await metadataApi.authenticate(); - } - - Future logout() async { - final metadataApi = await ref.read(metadataPluginApiProvider.future); - - if (metadataApi == null || !metadataApi.signatureFlags.requiresAuth) { - return; - } - - await metadataApi.logout(); + return defaultPlugin.auth.isAuthenticated(); } } -final metadataAuthenticatedProvider = - AsyncNotifierProvider( - () => MetadataAuthenticationNotifier(), +final metadataPluginAuthenticatedProvider = + AsyncNotifierProvider( + MetadataPluginAuthenticatedNotifier.new, ); diff --git a/lib/provider/metadata_plugin/metadata_plugin_provider.dart b/lib/provider/metadata_plugin/metadata_plugin_provider.dart index 2852c537..81199699 100644 --- a/lib/provider/metadata_plugin/metadata_plugin_provider.dart +++ b/lib/provider/metadata_plugin/metadata_plugin_provider.dart @@ -10,7 +10,6 @@ import 'package:path_provider/path_provider.dart'; import 'package:spotube/models/database/database.dart'; import 'package:spotube/models/metadata/metadata.dart'; import 'package:spotube/provider/database/database.dart'; -import 'package:spotube/provider/metadata_plugin/auth.dart'; import 'package:spotube/services/dio/dio.dart'; import 'package:spotube/services/metadata/metadata.dart'; import 'package:spotube/utils/service_utils.dart'; @@ -315,20 +314,20 @@ class MetadataPluginNotifier extends AsyncNotifier { ); } - Future getPluginLibraryCode(PluginConfiguration plugin) async { + Future getPluginByteCode(PluginConfiguration plugin) async { final pluginDir = await _getPluginDir(); final pluginExtractionDirPath = join( pluginDir.path, ServiceUtils.sanitizeFilename(plugin.name), ); - final libraryFile = File(join(pluginExtractionDirPath, "dist", "index.js")); + final libraryFile = File(join(pluginExtractionDirPath, "plugin.out")); if (!libraryFile.existsSync()) { - throw Exception("No dist/index.js found"); + throw Exception("No plugin.out (Bytecode) file found"); } - return await libraryFile.readAsString(); + return await libraryFile.readAsBytes(); } } @@ -337,7 +336,7 @@ final metadataPluginsProvider = MetadataPluginNotifier.new, ); -final metadataPluginApiProvider = FutureProvider( +final metadataPluginProvider = FutureProvider( (ref) async { final defaultPlugin = await ref.watch( metadataPluginsProvider.selectAsync((data) => data.defaultPluginConfig), @@ -348,38 +347,9 @@ final metadataPluginApiProvider = FutureProvider( } final pluginsNotifier = ref.read(metadataPluginsProvider.notifier); - final libraryCode = - await pluginsNotifier.getPluginLibraryCode(defaultPlugin); + final pluginByteCode = + await pluginsNotifier.getPluginByteCode(defaultPlugin); - return MetadataApiSignature.init(libraryCode, defaultPlugin); + return await MetadataPlugin.create(defaultPlugin, pluginByteCode); }, ); - -final metadataProviderUserProvider = FutureProvider( - (ref) async { - final metadataApi = await ref.watch(metadataPluginApiProvider.future); - ref.watch(metadataAuthenticatedProvider); - - if (metadataApi == null) { - return null; - } - return metadataApi.getMe(); - }, -); - -final metadataUserArtistsProvider = - FutureProvider>((ref) async { - final metadataApi = await ref.watch(metadataPluginApiProvider.future); - ref.watch(metadataAuthenticatedProvider); - - final userId = await ref.watch( - metadataProviderUserProvider.selectAsync((data) => data?.uid), - ); - if (metadataApi == null || userId == null) { - return []; - } - - final res = await metadataApi.listUserSavedArtists(userId); - - return res.items as List; -}); diff --git a/lib/provider/metadata_plugin/user.dart b/lib/provider/metadata_plugin/user.dart new file mode 100644 index 00000000..7dd65766 --- /dev/null +++ b/lib/provider/metadata_plugin/user.dart @@ -0,0 +1,16 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:spotube/models/metadata/metadata.dart'; +import 'package:spotube/provider/metadata_plugin/auth.dart'; +import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart'; + +final metadataPluginUserProvider = FutureProvider( + (ref) async { + final metadataPlugin = await ref.watch(metadataPluginProvider.future); + ref.watch(metadataPluginAuthenticatedProvider); + + if (metadataPlugin == null) { + return null; + } + return metadataPlugin.user.me(); + }, +); diff --git a/lib/services/metadata/apis/localstorage.dart b/lib/services/metadata/apis/localstorage.dart index 3b76f169..4c511e77 100644 --- a/lib/services/metadata/apis/localstorage.dart +++ b/lib/services/metadata/apis/localstorage.dart @@ -1,60 +1,78 @@ -import 'package:flutter_js/flutter_js.dart'; +import 'package:hetu_spotube_plugin/hetu_spotube_plugin.dart'; import 'package:shared_preferences/shared_preferences.dart'; -class PluginLocalStorageApi { - final JavascriptRuntime runtime; - final SharedPreferences sharedPreferences; +class SharedPreferencesLocalStorage implements Localstorage { + final SharedPreferences _prefs; + final String pluginSlug; - final String pluginName; + SharedPreferencesLocalStorage(this._prefs, this.pluginSlug); - PluginLocalStorageApi({ - required this.runtime, - required this.sharedPreferences, - required this.pluginName, - }) { - runtime.onMessage("LocalStorage.getItem", (args) { - final key = args[0]["key"]; - final value = getItem(key); - runtime.evaluate( - """ - eventEmitter.emit('LocalStorage.getItem', ${value != null ? "'$value'" : "null"}); - """, - ); - }); - - runtime.onMessage("LocalStorage.setItem", (args) { - final map = args[0] as Map; - setItem(map["key"], map["value"]); - }); - - runtime.onMessage("LocalStorage.removeItem", (args) { - final map = args[0]; - removeItem(map["key"]); - }); - - runtime.onMessage("LocalStorage.clear", (args) { - clear(); - }); + String prefix(String key) { + return 'spotube_plugin.$pluginSlug.$key'; } - void setItem(String key, String value) async { - await sharedPreferences.setString("plugin.$pluginName.$key", value); + @override + Future clear() { + return _prefs.clear(); } - String? getItem(String key) { - return sharedPreferences.getString("plugin.$pluginName.$key"); + @override + Future containsKey(String key) async { + return _prefs.containsKey(prefix(key)); } - void removeItem(String key) async { - await sharedPreferences.remove("plugin.$pluginName.$key"); + @override + Future getBool(String key) async { + return _prefs.getBool(prefix(key)); } - void clear() async { - final keys = sharedPreferences.getKeys(); - for (String key in keys) { - if (key.startsWith("plugin.$pluginName.")) { - await sharedPreferences.remove(key); - } - } + @override + Future getDouble(String key) async { + return _prefs.getDouble(prefix(key)); + } + + @override + Future getInt(String key) async { + return _prefs.getInt(prefix(key)); + } + + @override + Future getString(String key) async { + return _prefs.getString(prefix(key)); + } + + @override + Future?> getStringList(String key) async { + return _prefs.getStringList(prefix(key)); + } + + @override + Future remove(String key) async { + await _prefs.remove(prefix(key)); + } + + @override + Future setBool(String key, bool value) async { + await _prefs.setBool(prefix(key), value); + } + + @override + Future setDouble(String key, double value) async { + await _prefs.setDouble(prefix(key), value); + } + + @override + Future setInt(String key, int value) async { + await _prefs.setInt(prefix(key), value); + } + + @override + Future setString(String key, String value) async { + await _prefs.setString(prefix(key), value); + } + + @override + Future setStringList(String key, List value) async { + await _prefs.setStringList(prefix(key), value); } } diff --git a/lib/services/metadata/apis/set_interval.dart b/lib/services/metadata/apis/set_interval.dart deleted file mode 100644 index f059dc75..00000000 --- a/lib/services/metadata/apis/set_interval.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'dart:async'; - -import 'package:flutter_js/flutter_js.dart'; - -class PluginSetIntervalApi { - final JavascriptRuntime runtime; - - final Map _timers = {}; - - PluginSetIntervalApi(this.runtime) { - runtime.evaluate( - """ - var __NATIVE_FLUTTER_JS__setIntervalCount = -1; - var __NATIVE_FLUTTER_JS__setIntervalCallbacks = {}; - function setInterval(fnInterval, interval) { - try { - __NATIVE_FLUTTER_JS__setIntervalCount += 1; - var intervalIndex = '' + __NATIVE_FLUTTER_JS__setIntervalCount; - __NATIVE_FLUTTER_JS__setIntervalCallbacks[intervalIndex] = fnInterval; - ; - sendMessage('PluginSetIntervalApi.setInterval', JSON.stringify({ intervalIndex, interval})); - return intervalIndex; - } catch (e) { - console.error('ERROR HERE',e.message); - } - }; - - function clearInterval(intervalIndex) { - try { - delete __NATIVE_FLUTTER_JS__setIntervalCallbacks[intervalIndex]; - sendMessage('PluginSetIntervalApi.clearInterval', JSON.stringify({ intervalIndex})); - } catch (e) { - console.error('ERROR HERE',e.message); - } - }; - 1 - """, - ); - - runtime.onMessage('PluginSetIntervalApi.setInterval', (dynamic args) { - try { - int duration = args['interval'] ?? 0; - String idx = args['intervalIndex']; - - _timers[idx] = - Timer.periodic(Duration(milliseconds: duration), (timer) { - runtime.evaluate(""" - __NATIVE_FLUTTER_JS__setIntervalCallbacks[$idx].call(); - delete __NATIVE_FLUTTER_JS__setIntervalCallbacks[$idx]; - """); - }); - } on Exception catch (e) { - print('Exception no setInterval: $e'); - } on Error catch (e) { - print('Erro no setInterval: $e'); - } - }); - - runtime.onMessage('PluginSetIntervalApi.clearInterval', (dynamic args) { - try { - String idx = args['intervalIndex']; - if (_timers.containsKey(idx)) { - _timers[idx]?.cancel(); - _timers.remove(idx); - } - } on Exception catch (e) { - print('Exception no clearInterval: $e'); - } on Error catch (e) { - print('Error no clearInterval: $e'); - } - }); - } - - void dispose() { - for (var timer in _timers.values) { - timer.cancel(); - } - _timers.clear(); - } -} diff --git a/lib/services/metadata/apis/totp.dart b/lib/services/metadata/apis/totp.dart deleted file mode 100644 index 7a0bdb90..00000000 --- a/lib/services/metadata/apis/totp.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter_js/javascript_runtime.dart'; -import 'package:otp_util/otp_util.dart'; -// ignore: implementation_imports -import 'package:otp_util/src/utils/generic_util.dart'; - -class PluginTotpGenerator { - final JavascriptRuntime runtime; - - PluginTotpGenerator(this.runtime) { - runtime.onMessage("TotpGenerator.generate", (args) { - final opts = args[0]; - if (opts is! Map) { - return; - } - - final totp = TOTP( - secret: opts["secret"] as String, - algorithm: OTPAlgorithm.values.firstWhere( - (e) => e.name == opts["algorithm"], - orElse: () => OTPAlgorithm.SHA1, - ), - digits: opts["digits"] as int? ?? 6, - interval: opts["interval"] as int? ?? 30, - ); - - final otp = totp.generateOTP( - input: Util.timeFormat( - time: DateTime.fromMillisecondsSinceEpoch(opts["period"]), - interval: 30, - ), - ); - - runtime.evaluate( - """ - eventEmitter.emit('TotpGenerator.generate', '$otp'); - """, - ); - }); - } -} diff --git a/lib/services/metadata/apis/webview.dart b/lib/services/metadata/apis/webview.dart deleted file mode 100644 index 5ad74060..00000000 --- a/lib/services/metadata/apis/webview.dart +++ /dev/null @@ -1,171 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:auto_route/auto_route.dart'; -import 'package:desktop_webview_window/desktop_webview_window.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_inappwebview/flutter_inappwebview.dart'; -import 'package:flutter_js/flutter_js.dart'; -import 'package:path/path.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart' hide join; -import 'package:spotube/collections/routes.dart'; -import 'package:spotube/collections/routes.gr.dart'; -import 'package:spotube/pages/mobile_login/no_webview_runtime_dialog.dart'; -import 'package:spotube/utils/platform.dart'; - -class WebviewInitialSettings { - final String? userAgent; - final bool? incognito; - final bool? clearCache; - final bool? clearSessionCache; - - WebviewInitialSettings({ - this.userAgent, - this.incognito, - this.clearCache, - this.clearSessionCache, - }); - - factory WebviewInitialSettings.fromJson(Map json) { - return WebviewInitialSettings( - userAgent: json["userAgent"], - incognito: json["incognito"], - clearCache: json["clearCache"], - clearSessionCache: json["clearSessionCache"], - ); - } -} - -class PluginWebViewApi { - JavascriptRuntime runtime; - - PluginWebViewApi({ - required this.runtime, - }) { - runtime.onMessage("WebView.show", (args) { - if (args[0] is! Map) { - return; - } - showWebView( - url: args[0]["url"] as String, - initialSettings: args[0]["initialSettings"] != null - ? WebviewInitialSettings.fromJson( - args[0]["initialSettings"], - ) - : null, - ); - }); - } - - Webview? webviewWindow; - - Future showWebView({ - required String url, - WebviewInitialSettings? initialSettings, - }) async { - if (rootNavigatorKey.currentContext == null) { - return; - } - final context = rootNavigatorKey.currentContext!; - final theme = Theme.of(context); - - if (kIsMobile || kIsMacOS) { - context.pushRoute(WebviewRoute( - initialSettings: initialSettings, - url: url, - onLoadStop: (controller, uri) async { - if (uri == null) return; - final cookies = await CookieManager().getAllCookies(); - - final jsonCookies = cookies.map((e) { - return { - "name": e.name, - "value": e.value, - "domain": e.domain, - "path": e.path, - }; - }); - - runtime.onMessage("WebView.close", (args) { - context.back(); - }); - - runtime.evaluate( - """ - eventEmitter.emit('WebView.onLoadFinish', {url: '${uri.toString()}', cookies: ${jsonEncode(jsonCookies)}}); - """, - ); - }, - )); - return; - } - - try { - final applicationSupportDir = await getApplicationSupportDirectory(); - final userDataFolder = Directory( - join(applicationSupportDir.path, "webview_window_Webview2"), - ); - - if (!await userDataFolder.exists()) { - await userDataFolder.create(); - } - - final webview = await WebviewWindow.create( - configuration: CreateConfiguration( - title: "Webview", - titleBarTopPadding: kIsMacOS ? 20 : 0, - windowHeight: 720, - windowWidth: 1280, - userDataFolderWindows: userDataFolder.path, - ), - ); - - webviewWindow = webview; - - runtime.onMessage("WebView.close", (args) { - webview.close(); - }); - - webview - ..setBrightness(theme.colorScheme.brightness) - ..launch(url) - ..setOnUrlRequestCallback((url) { - () async { - final cookies = await webview.getAllCookies(); - final jsonCookies = cookies.map((e) { - return { - "name": e.name, - "value": e.value, - "domain": e.domain, - "path": e.path, - }; - }).toList(); - - runtime.evaluate( - """ - eventEmitter.emit('WebView.onLoadFinish', {url: '$url', cookies: ${jsonEncode(jsonCookies)}}); - """, - ); - }(); - return false; - }); - } on PlatformException catch (_) { - if (!await WebviewWindow.isWebviewAvailable()) { - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - showDialog( - context: context, - builder: (context) { - return const NoWebviewRuntimeDialog(); - }, - ); - }); - } - } - } - - void dispose() { - webviewWindow?.close(); - webviewWindow = null; - } -} diff --git a/lib/services/metadata/endpoints/album.dart b/lib/services/metadata/endpoints/album.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/services/metadata/endpoints/artist.dart b/lib/services/metadata/endpoints/artist.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/services/metadata/endpoints/auth.dart b/lib/services/metadata/endpoints/auth.dart new file mode 100644 index 00000000..7c2077be --- /dev/null +++ b/lib/services/metadata/endpoints/auth.dart @@ -0,0 +1,33 @@ +import 'package:desktop_webview_window/desktop_webview_window.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:hetu_script/hetu_script.dart'; +import 'package:hetu_std/hetu_std.dart'; +import 'package:spotube/utils/platform.dart'; + +class MetadataAuthEndpoint { + final Hetu hetu; + + MetadataAuthEndpoint(this.hetu); + + Stream get authStateStream => + hetu.eval("metadataPlugin.auth.authStateStream"); + + Future authenticate() async { + await hetu.eval("metadataPlugin.auth.authenticate()"); + } + + bool isAuthenticated() { + return hetu.eval("metadataPlugin.auth.isAuthenticated()") as bool; + } + + Future logout() async { + await hetu.eval("metadataPlugin.auth.logout()"); + if (kIsMobile) { + WebStorageManager.instance().deleteAllData(); + CookieManager.instance().deleteAllCookies(); + } + if (kIsDesktop) { + await WebviewWindow.clearAll(); + } + } +} diff --git a/lib/services/metadata/endpoints/browse.dart b/lib/services/metadata/endpoints/browse.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/services/metadata/endpoints/playlist.dart b/lib/services/metadata/endpoints/playlist.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/services/metadata/endpoints/search.dart b/lib/services/metadata/endpoints/search.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/services/metadata/endpoints/track.dart b/lib/services/metadata/endpoints/track.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/services/metadata/endpoints/user.dart b/lib/services/metadata/endpoints/user.dart new file mode 100644 index 00000000..ec4cd963 --- /dev/null +++ b/lib/services/metadata/endpoints/user.dart @@ -0,0 +1,15 @@ +import 'package:hetu_script/hetu_script.dart'; +import 'package:spotube/models/metadata/metadata.dart'; + +class MetadataPluginUserEndpoint { + final Hetu hetu; + MetadataPluginUserEndpoint(this.hetu); + + Future me() async { + final raw = await hetu.eval("metadataPlugin.user.me()") as Map; + + return SpotubeUserObject.fromJson( + raw.cast(), + ); + } +} diff --git a/lib/services/metadata/metadata.dart b/lib/services/metadata/metadata.dart index b01e41be..8f219207 100644 --- a/lib/services/metadata/metadata.dart +++ b/lib/services/metadata/metadata.dart @@ -1,564 +1,81 @@ -import 'dart:async'; -import 'dart:convert'; +import 'dart:typed_data'; -import 'package:flutter_js/extensions/fetch.dart'; -import 'package:flutter_js/extensions/xhr.dart'; -import 'package:flutter_js/flutter_js.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:hetu_otp_util/hetu_otp_util.dart'; +import 'package:hetu_script/hetu_script.dart'; +import 'package:hetu_spotube_plugin/hetu_spotube_plugin.dart'; +import 'package:hetu_std/hetu_std.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:spotube/collections/routes.dart'; +import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/models/metadata/metadata.dart'; -import 'package:spotube/services/logger/logger.dart'; import 'package:spotube/services/metadata/apis/localstorage.dart'; -import 'package:spotube/services/metadata/apis/set_interval.dart'; -import 'package:spotube/services/metadata/apis/totp.dart'; -import 'package:spotube/services/metadata/apis/webview.dart'; +import 'package:spotube/services/metadata/endpoints/auth.dart'; +import 'package:spotube/services/metadata/endpoints/user.dart'; const defaultMetadataLimit = "20"; -class MetadataSignatureFlags { - final bool requiresAuth; - - const MetadataSignatureFlags({ - this.requiresAuth = false, - }); - - factory MetadataSignatureFlags.fromJson(Map json) { - return MetadataSignatureFlags( - requiresAuth: json["requiresAuth"] ?? false, - ); - } -} - -/// Signature for metadata and related methods that will return Spotube native -/// objects e.g. SpotubeTrack, SpotubePlaylist, etc. -class MetadataApiSignature { - final JavascriptRuntime runtime; - final PluginLocalStorageApi localStorageApi; - final PluginWebViewApi webViewApi; - final PluginTotpGenerator totpGenerator; - final PluginSetIntervalApi setIntervalApi; - late MetadataSignatureFlags _signatureFlags; - - final StreamController _authenticatedStreamController; - - Stream get authenticatedStream => _authenticatedStreamController.stream; - - MetadataSignatureFlags get signatureFlags => _signatureFlags; - - MetadataApiSignature._( - this.runtime, - this.localStorageApi, - this.webViewApi, - this.totpGenerator, - this.setIntervalApi, - ) : _authenticatedStreamController = StreamController.broadcast() { - runtime.onMessage("authenticatedStatus", (args) { - if (args[0] is Map && (args[0] as Map).containsKey("authenticated")) { - final authenticated = args[0]["authenticated"] as bool; - _authenticatedStreamController.add(authenticated); - } - }); - } - - static Future init( - String libraryCode, +class MetadataPlugin { + static Future create( PluginConfiguration config, + Uint8List byteCode, ) async { - final runtime = getJavascriptRuntime(xhr: true).enableXhr(); - runtime.enableHandlePromises(); - await runtime.enableFetch(); + final sharedPreferences = await SharedPreferences.getInstance(); + BuildContext? pageContext; - Timer.periodic( - const Duration(milliseconds: 100), - (timer) { - runtime.executePendingJob(); + final hetu = Hetu(); + hetu.init(); + + HetuStdLoader.loadBindings(hetu); + HetuSpotubePluginLoader.loadBindings( + hetu, + localStorageImpl: SharedPreferencesLocalStorage( + sharedPreferences, + config.slug, + ), + onNavigatorPush: (route) { + return rootNavigatorKey.currentContext?.router + .pushWidget(Builder(builder: (context) { + pageContext = context; + return Scaffold( + headers: const [ + TitleBar( + automaticallyImplyLeading: true, + ) + ], + child: route, + ); + })); + }, + onNavigatorPop: () { + pageContext?.maybePop(); }, ); - // Create all the PluginAPIs after library code is evaluated - final localStorageApi = PluginLocalStorageApi( - runtime: runtime, - sharedPreferences: await SharedPreferences.getInstance(), - pluginName: config.slug, - ); + await HetuStdLoader.loadBytecodeFlutter(hetu); + await HetuOtpUtilLoader.loadBytecodeFlutter(hetu); + await HetuSpotubePluginLoader.loadBytecodeFlutter(hetu); - final webViewApi = PluginWebViewApi(runtime: runtime); - final totpGenerator = PluginTotpGenerator(runtime); - final setIntervalApi = PluginSetIntervalApi(runtime); + hetu.loadBytecode(bytes: byteCode, moduleName: "plugin"); + hetu.eval(""" + import "module:plugin" as plugin - final metadataApi = MetadataApiSignature._( - runtime, - localStorageApi, - webViewApi, - totpGenerator, - setIntervalApi, - ); + var Plugin = plugin.${config.entryPoint} - final res = runtime.evaluate( - """ - ;$libraryCode; - const metadataApi = new MetadataApi(); - """, - ); - metadataApi._signatureFlags = await metadataApi._getSignatureFlags(); + var metadataPlugin = Plugin() + """); - if (res.isError) { - AppLogger.reportError( - "Error evaluating code: $libraryCode\n${res.rawResult}", - ); - } - - return metadataApi; + return MetadataPlugin._(hetu); } - void dispose() { - setIntervalApi.dispose(); - webViewApi.dispose(); - runtime.dispose(); - } + final Hetu hetu; - Future invoke(String method, [List? args]) async { - final completer = Completer(); - runtime.onMessage(method, (result) { - if (completer.isCompleted) return; - try { - if (result is Map && result.containsKey("error")) { - completer.completeError(result["error"]); - } else { - completer.complete(result is String ? jsonDecode(result) : result); - } - } catch (e, stack) { - AppLogger.reportError( - "[MetadataApiSignature][invoke] Error in $method: $e", - stack, - ); - } - }); - final code = """ - $method(...${args != null ? jsonEncode(args) : "[]"}) - .then((res) => { - try { - sendMessage("$method", res ? JSON.stringify(res) : "[]"); - } catch (e) { - console.error("Failed to send message in $method.then: ", `\${e.toString()}\n\${e.stack.toString()}`); - } - }).catch((e) => { - try { - console.error("Error in $method: ", `\${e.toString()}\n\${e.stack.toString()}`); - sendMessage("$method", JSON.stringify({error: `\${e.toString()}\n\${e.stack.toString()}`})); - } catch (e) { - console.error("Failed to send message in $method.catch: ", `\${e.toString()}\n\${e.stack.toString()}`); - } - }); - """; + late final MetadataAuthEndpoint auth; + late final MetadataPluginUserEndpoint user; - final res = await runtime.evaluateAsync(code); - - if (res.isError) { - AppLogger.reportError("Error evaluating code: $code\n${res.rawResult}"); - completer.completeError("Error evaluating code: $code\n${res.rawResult}"); - return completer.future; - } - - return completer.future; - } - - Future _getSignatureFlags() async { - final res = await invoke("metadataApi.getSignatureFlags"); - - return MetadataSignatureFlags.fromJson(res); - } - - // ----- Authentication ------ - - Future authenticate() async { - await invoke("metadataApi.authenticate"); - } - - Future isAuthenticated() async { - final res = await invoke("metadataApi.isAuthenticated"); - return res as bool; - } - - Future logout() async { - await invoke("metadataApi.logout"); - } - - // ----- Track ------ - Future getTrack(String id) async { - final result = await invoke("metadataApi.getTrack", [id]); - return SpotubeTrackObject.fromJson(result); - } - - Future> listTracks({ - List? ids, - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final result = await invoke( - "metadataApi.listTracks", - [ - ids, - limit, - cursor, - ], - ); - - return SpotubePaginationResponseObject.fromJson( - result, - SpotubeTrackObject.fromJson, - ); - } - - Future> listTracksByAlbum( - String albumId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listTracksByAlbum", - [albumId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeTrackObject.fromJson, - ); - } - - Future> - listTopTracksByArtist( - String artistId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listTopTracksByArtist", - [artistId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeTrackObject.fromJson, - ); - } - - Future> - listTracksByPlaylist( - String playlistId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listTracksByPlaylist", - [playlistId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeTrackObject.fromJson, - ); - } - - Future> - listUserSavedTracks( - String userId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listUserSavedTracks", - [userId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeTrackObject.fromJson, - ); - } - - // ----- Album ------ - Future getAlbum(String id) async { - final res = await invoke("metadataApi.getAlbum", [id]); - - return SpotubeAlbumObject.fromJson(res); - } - - Future> listAlbums({ - List? ids, - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listAlbums", - [ids, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeAlbumObject.fromJson, - ); - } - - Future> - listAlbumsByArtist( - String artistId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listAlbumsByArtist", - [artistId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeAlbumObject.fromJson, - ); - } - - Future> - listUserSavedAlbums( - String userId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listUserSavedAlbums", - [userId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeAlbumObject.fromJson, - ); - } - - // ----- Playlist ------ - Future getPlaylist(String id) async { - final res = await invoke("metadataApi.getPlaylist", [id]); - - return SpotubePlaylistObject.fromJson(res); - } - - Future> - listFeedPlaylists( - String feedId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listFeedPlaylists", - [feedId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubePlaylistObject.fromJson, - ); - } - - Future> - listUserSavedPlaylists( - String userId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listUserSavedPlaylists", - [userId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubePlaylistObject.fromJson, - ); - } - - Future createPlaylist( - String userId, - String name, { - String? description, - bool? public, - bool? collaborative, - String? imageBase64, - }) async { - final res = await invoke( - "metadataApi.createPlaylist", - [ - userId, - name, - description, - public, - collaborative, - imageBase64, - ], - ); - - return SpotubePlaylistObject.fromJson(res); - } - - Future updatePlaylist( - String playlistId, { - String? name, - String? description, - bool? public, - bool? collaborative, - String? imageBase64, - }) async { - await invoke( - "metadataApi.updatePlaylist", - [ - playlistId, - name, - description, - public, - collaborative, - imageBase64, - ], - ); - } - - Future deletePlaylist(String userId, String playlistId) async { - await unsavePlaylist(userId, playlistId); - } - - Future addTracksToPlaylist( - String playlistId, - List trackIds, { - int? position, - }) async { - await invoke( - "metadataApi.addTracksToPlaylist", - [ - playlistId, - trackIds, - position, - ], - ); - } - - Future removeTracksFromPlaylist( - String playlistId, - List trackIds, - ) async { - await invoke( - "metadataApi.removeTracksFromPlaylist", - [ - playlistId, - trackIds, - ], - ); - } - - // ----- Artist ------ - Future getArtist(String id) async { - final res = await invoke("metadataApi.getArtist", [id]); - - return SpotubeArtistObject.fromJson(res); - } - - Future> listArtists({ - List? ids, - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listArtists", - [ids, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeArtistObject.fromJson, - ); - } - - Future> - listUserSavedArtists( - String userId, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.listUserSavedArtists", - [userId, limit, cursor], - ); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeArtistObject.fromJson, - ); - } - - // ----- Search ------ - Future search( - String query, { - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke( - "metadataApi.search", - [query, limit, cursor], - ); - - return SpotubeSearchResponseObject.fromJson(res); - } - - // ----- Feed ------ - Future getFeed(String id) async { - final res = await invoke("metadataApi.getFeed", [id]); - - return SpotubeFeedObject.fromJson(res); - } - - Future> listFeeds({ - String limit = defaultMetadataLimit, - String? cursor, - }) async { - final res = await invoke("metadataApi.listFeeds", [limit, cursor]); - - return SpotubePaginationResponseObject.fromJson( - res, - SpotubeFeedObject.fromJson, - ); - } - - // ----- User ------ - Future getMe() async { - final res = await invoke("metadataApi.getMe"); - - return SpotubeUserObject.fromJson(res); - } - - Future followArtist(String userId, String artistId) async { - await invoke("metadataApi.followArtist", [userId, artistId]); - } - - Future unfollowArtist(String userId, String artistId) async { - await invoke("metadataApi.unfollowArtist", [userId, artistId]); - } - - Future savePlaylist(String userId, String playlistId) async { - await invoke("metadataApi.savePlaylist", [userId, playlistId]); - } - - Future unsavePlaylist(String userId, String playlistId) async { - await invoke("metadataApi.unsavePlaylist", [userId, playlistId]); - } - - Future saveAlbum(String userId, String albumId) async { - await invoke("metadataApi.saveAlbum", [userId, albumId]); - } - - Future unsaveAlbum(String userId, String albumId) async { - await invoke("metadataApi.unsaveAlbum", [userId, albumId]); - } - - Future saveTrack(String userId, String trackId) async { - await invoke("metadataApi.saveTrack", [userId, trackId]); - } - - Future unsaveTrack(String userId, String trackId) async { - await invoke("metadataApi.unsaveTrack", [userId, trackId]); + MetadataPlugin._(this.hetu) { + auth = MetadataAuthEndpoint(hetu); + user = MetadataPluginUserEndpoint(hetu); } } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 3976fd80..8a9a2e19 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,8 +8,8 @@ #include #include -#include #include +#include #include #include #include @@ -28,12 +28,12 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); - g_autoptr(FlPluginRegistrar) flutter_js_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterJsPlugin"); - flutter_js_plugin_register_with_registrar(flutter_js_registrar); g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_timezone_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterTimezonePlugin"); + flutter_timezone_plugin_register_with_registrar(flutter_timezone_registrar); g_autoptr(FlPluginRegistrar) gtk_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin"); gtk_plugin_register_with_registrar(gtk_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index c47d2627..783f370f 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,8 +5,8 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window file_selector_linux - flutter_js flutter_secure_storage_linux + flutter_timezone gtk local_notifier media_kit_libs_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index d44e5a13..bc163169 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -14,8 +14,8 @@ import desktop_webview_window import device_info_plus import file_selector_macos import flutter_inappwebview_macos -import flutter_js import flutter_secure_storage_macos +import flutter_timezone import local_notifier import media_kit_libs_macos_audio import open_file_mac @@ -40,8 +40,8 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) - FlutterJsPlugin.register(with: registry.registrar(forPlugin: "FlutterJsPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + FlutterTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterTimezonePlugin")) LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin")) MediaKitLibsMacosAudioPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosAudioPlugin")) OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin")) diff --git a/pubspec.lock b/pubspec.lock index dcb307a9..8c5211f7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -540,10 +540,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" url: "https://pub.dev" source: hosted - version: "5.7.0" + version: "5.8.0+1" dio_http2_adapter: dependency: "direct main" description: @@ -658,6 +658,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + fast_noise: + dependency: transitive + description: + name: fast_noise + sha256: "271031cebf1602fc064472970e658fa7ff2f3b55a979bb430337b715bd55690b" + url: "https://pub.dev" + source: hosted + version: "1.0.1" ffi: dependency: transitive description: @@ -909,14 +917,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" - flutter_js: - dependency: "direct main" - description: - name: flutter_js - sha256: "6b777cd4e468546f046a2f114d078a4596143269f6fa6bad5c29611d5b896369" - url: "https://pub.dev" - source: hosted - version: "0.8.2" flutter_launcher_icons: dependency: "direct dev" description: @@ -1048,6 +1048,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_timezone: + dependency: transitive + description: + name: flutter_timezone + sha256: "13b2109ad75651faced4831bf262e32559e44aa549426eab8a597610d385d934" + url: "https://pub.dev" + source: hosted + version: "4.1.1" flutter_undraw: dependency: "direct main" description: @@ -1122,6 +1130,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: f126a3e286b7f5b578bf436d5592968706c4c1de28a228b870ce375d9f743103 + url: "https://pub.dev" + source: hosted + version: "8.0.3" glob: dependency: transitive description: @@ -1170,6 +1186,41 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + hetu_otp_util: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "7790606751828758769596e809ba6cbb756f9b9a" + url: "https://github.com/hetu-community/hetu_otp_util.git" + source: git + version: "1.0.0" + hetu_script: + dependency: "direct main" + description: + name: hetu_script + sha256: a9a3f4f510ae10188d352b79e8fc45e27134cfa81ee1691004067395f45f17cb + url: "https://pub.dev" + source: hosted + version: "0.4.2+1" + hetu_spotube_plugin: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "1aa924281d2dbe09aab27d8c2de1cffc853b0d16" + url: "https://github.com/KRTirtho/hetu_spotube_plugin.git" + source: git + version: "0.0.1" + hetu_std: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: d3720be2a92022f7b95a3082d40322d8458c70da + url: "https://github.com/hetu-community/hetu_std.git" + source: git + version: "1.0.0" home_widget: dependency: "direct main" description: @@ -2783,5 +2834,5 @@ packages: source: git version: "1.0.0" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.7.2 <4.0.0" flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6c7c1d8b..4dd74570 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -142,8 +142,21 @@ dependencies: collection: any otp_util: ^1.0.2 dio_http2_adapter: ^2.6.0 - flutter_js: ^0.8.2 archive: ^4.0.7 + hetu_script: ^0.4.2+1 + hetu_std: + git: + url: https://github.com/hetu-community/hetu_std.git + ref: main + hetu_otp_util: + git: + url: https://github.com/hetu-community/hetu_otp_util.git + ref: main + hetu_spotube_plugin: + git: + url: https://github.com/KRTirtho/hetu_spotube_plugin.git + ref: main + get_it: ^8.0.3 dev_dependencies: build_runner: ^2.4.13 @@ -170,9 +183,10 @@ dependency_overrides: git: url: https://github.com/KRTirtho/Bonsoir.git path: packages/bonsoir_android - web: ^1.1.0 meta: 1.16.0 + web: ^1.1.0 flutter_svg: ^2.0.17 + intl: any collection: any flutter: @@ -195,6 +209,10 @@ flutter: - packages/flutter_undraw/assets/undraw/taken.svg - packages/flutter_undraw/assets/undraw/empty.svg - packages/flutter_undraw/assets/undraw/no_data.svg + # hetu script bytecode + - packages/hetu_std/assets/bytecode/std.out + - packages/hetu_otp_util/assets/bytecode/otp_util.out + - packages/hetu_spotube_plugin/assets/bytecode/spotube_plugin.out fonts: - family: RadixIcons fonts: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 9ad3a3a5..f053614f 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -37,10 +37,10 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FileSelectorWindows")); FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi")); - FlutterJsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FlutterJsPlugin")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + FlutterTimezonePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterTimezonePluginCApi")); LocalNotifierPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("LocalNotifierPlugin")); MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index a9b74bf4..fae5ffe9 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -9,8 +9,8 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_webview_window file_selector_windows flutter_inappwebview_windows - flutter_js flutter_secure_storage_windows + flutter_timezone local_notifier media_kit_libs_windows_audio permission_handler_windows