feat: add endless playback support #285

This commit is contained in:
Kingkor Roy Tirtho 2024-01-31 18:00:54 +06:00
parent 4defeefe7e
commit 9dfd49ca04
13 changed files with 956 additions and 253 deletions

View File

@ -31,4 +31,6 @@ linter:
analyzer: analyzer:
enable-experiment: enable-experiment:
- records - records
- patterns - patterns
errors:
invalid_annotation_target: ignore

View File

@ -106,14 +106,22 @@ class TrackOptions extends HookConsumerWidget {
) ?? ) ??
[]; [];
final radios = pages.expand((e) => e.items ?? <PlaylistSimple>[]).toList(); final radios = pages
.expand((e) => e.items?.toList() ?? <PlaylistSimple>[])
.toList()
.cast<PlaylistSimple>();
final artists = track.artists!.map((e) => e.name); final artists = track.artists!.map((e) => e.name);
final radio = radios.firstWhere( final radio = radios.firstWhere(
(e) => (e) {
e.name == "${track.name} Radio" && final validPlaylists =
artists.where((a) => e.name!.contains(a!)).length >= 2, artists.where((a) => e.description!.contains(a!));
return e.name == "${track.name} Radio" &&
(validPlaylists.length >= 2 ||
validPlaylists.length == artists.length) &&
e.owner?.displayName == "Spotify";
},
orElse: () => radios.first, orElse: () => radios.first,
); );
@ -129,9 +137,12 @@ class TrackOptions extends HookConsumerWidget {
); );
} }
if (replaceQueue) { if (replaceQueue || playlist.tracks.isEmpty) {
await playback.stop(); await playback.stop();
await playback.load([track], autoPlay: true); await playback.load([track], autoPlay: true);
// we don't have to add those tracks as useEndlessPlayback will do it for us
return;
} else { } else {
await playback.addTrack(track); await playback.addTrack(track);
} }

View File

@ -0,0 +1,102 @@
import 'package:catcher_2/catcher_2.dart';
import 'package:fl_query_hooks/fl_query_hooks.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/spotify_provider.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/queries/search.dart';
void useEndlessPlayback(WidgetRef ref) {
final auth = ref.watch(AuthenticationNotifier.provider);
final playback = ref.watch(ProxyPlaylistNotifier.notifier);
final playlist = ref.watch(ProxyPlaylistNotifier.provider);
final spotify = ref.watch(spotifyProvider);
final endlessPlayback =
ref.watch(userPreferencesProvider.select((s) => s.endlessPlayback));
final queryClient = useQueryClient();
useEffect(
() {
if (!endlessPlayback || auth == null) return null;
void listener(int index) async {
try {
final playlist = ref.read(ProxyPlaylistNotifier.provider);
if (index != playlist.tracks.length - 1) return;
final track = playlist.tracks.last;
final pages = await queryClient.fetchInfiniteQueryJob<List<Page>,
dynamic, int, SearchParams>(
job: SearchQueries.queryJob(SearchType.playlist.name),
args: (
spotify: spotify,
searchType: SearchType.playlist,
query: "${track.name} Radio"
),
) ??
[];
final radios = pages
.expand((e) => e.items?.toList() ?? <PlaylistSimple>[])
.toList()
.cast<PlaylistSimple>();
final artists = track.artists!.map((e) => e.name);
final radio = radios.firstWhere(
(e) {
final validPlaylists =
artists.where((a) => e.description!.contains(a!));
return e.name == "${track.name} Radio" &&
(validPlaylists.length >= 2 ||
validPlaylists.length == artists.length) &&
e.owner?.displayName != "Spotify";
},
orElse: () => radios.first,
);
final tracks =
await spotify.playlists.getTracksByPlaylistId(radio.id!).all();
await playback.addTracks(
tracks.toList()
..removeWhere((e) {
final playlist = ref.read(ProxyPlaylistNotifier.provider);
final isDuplicate = playlist.tracks.any((t) => t.id == e.id);
return e.id == track.id || isDuplicate;
}),
);
} catch (e, stack) {
Catcher2.reportCheckedError(e, stack);
}
}
// Sometimes user can change settings for which the currentIndexChanged
// might not be called. So we need to check if the current track is the
// last track and if it is then we need to call the listener manually.
if (playlist.active == playlist.tracks.length - 1 &&
audioPlayer.isPlaying) {
listener(playlist.active!);
}
final subscription =
audioPlayer.currentIndexChangedStream.listen(listener);
return subscription.cancel;
},
[
spotify,
playback,
queryClient,
playlist.tracks,
endlessPlayback,
auth,
],
);
}

View File

@ -289,5 +289,6 @@
"no_lyrics_available": "Sorry, unable find lyrics for this track", "no_lyrics_available": "Sorry, unable find lyrics for this track",
"start_a_radio": "Start a Radio", "start_a_radio": "Start a Radio",
"how_to_start_radio": "How do you want to start the radio?", "how_to_start_radio": "How do you want to start the radio?",
"replace_queue_question": "Do you want to replace the current queue or append to it?" "replace_queue_question": "Do you want to replace the current queue or append to it?",
"endless_playback": "Endless Playback"
} }

View File

@ -15,6 +15,7 @@ import 'package:spotube/components/root/bottom_player.dart';
import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/root/sidebar.dart';
import 'package:spotube/components/root/spotube_navigation_bar.dart'; import 'package:spotube/components/root/spotube_navigation_bar.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/configurators/use_endless_playback.dart';
import 'package:spotube/hooks/configurators/use_update_checker.dart'; import 'package:spotube/hooks/configurators/use_update_checker.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
import 'package:spotube/utils/persisted_state_notifier.dart'; import 'package:spotube/utils/persisted_state_notifier.dart';
@ -134,6 +135,8 @@ class RootApp extends HookConsumerWidget {
// checks for latest version of the application // checks for latest version of the application
useUpdateChecker(ref); useUpdateChecker(ref);
useEndlessPlayback(ref);
final backgroundColor = Theme.of(context).scaffoldBackgroundColor; final backgroundColor = Theme.of(context).scaffoldBackgroundColor;
useEffect(() { useEffect(() {

View File

@ -221,6 +221,12 @@ class SettingsPlaybackSection extends HookConsumerWidget {
preferencesNotifier.setDownloadMusicCodec(value); preferencesNotifier.setDownloadMusicCodec(value);
}, },
), ),
SwitchListTile(
secondary: const Icon(SpotubeIcons.repeat),
title: Text(context.l10n.endless_playback),
value: preferences.endlessPlayback,
onChanged: preferencesNotifier.setEndlessPlayback,
),
], ],
); );
} }

View File

@ -123,6 +123,10 @@ class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
audioPlayer.setAudioNormalization(normalize); audioPlayer.setAudioNormalization(normalize);
} }
void setEndlessPlayback(bool endless) {
state = state.copyWith(endlessPlayback: endless);
}
Future<String> _getDefaultDownloadDirectory() async { Future<String> _getDefaultDownloadDirectory() async {
if (kIsAndroid) return "/storage/emulated/0/Download/Spotube"; if (kIsAndroid) return "/storage/emulated/0/Download/Spotube";

View File

@ -1,12 +1,13 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/settings/color_scheme_picker_dialog.dart'; import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
import 'package:spotube/services/sourced_track/enums.dart'; import 'package:spotube/services/sourced_track/enums.dart';
part 'user_preferences_state.g.dart'; part 'user_preferences_state.g.dart';
part 'user_preferences_state.freezed.dart';
@JsonEnum() @JsonEnum()
enum LayoutMode { enum LayoutMode {
@ -53,40 +54,48 @@ enum SearchMode {
} }
} }
@JsonSerializable() @freezed
final class UserPreferences { class UserPreferences with _$UserPreferences {
@JsonKey( const factory UserPreferences({
defaultValue: SourceQualities.high, @Default(SourceQualities.high) SourceQualities audioQuality,
unknownEnumValue: SourceQualities.high, @Default(true) bool albumColorSync,
) @Default(false) bool amoledDarkTheme,
final SourceQualities audioQuality; @Default(true) bool checkUpdate,
@Default(false) bool normalizeAudio,
@Default(true) bool showSystemTrayIcon,
@Default(false) bool skipNonMusic,
@Default(false) bool systemTitleBar,
@Default(CloseBehavior.minimizeToTray) CloseBehavior closeBehavior,
@Default(SpotubeColor(0xFF2196F3, name: "Blue"))
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue,
)
SpotubeColor accentColorScheme,
@Default(LayoutMode.adaptive) LayoutMode layoutMode,
@Default(Locale("system", "system"))
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue,
)
Locale locale,
@Default(Market.US) Market recommendationMarket,
@Default(SearchMode.youtube) SearchMode searchMode,
@Default("") String downloadLocation,
@Default("https://pipedapi.kavin.rocks") String pipedInstance,
@Default(ThemeMode.system) ThemeMode themeMode,
@Default(AudioSource.youtube) AudioSource audioSource,
@Default(SourceCodecs.weba) SourceCodecs streamMusicCodec,
@Default(SourceCodecs.m4a) SourceCodecs downloadMusicCodec,
@Default(true) bool discordPresence,
@Default(true) bool endlessPlayback,
}) = _UserPreferences;
factory UserPreferences.fromJson(Map<String, dynamic> json) =>
_$UserPreferencesFromJson(json);
@JsonKey(defaultValue: true) factory UserPreferences.withDefaults() => UserPreferences.fromJson({});
final bool albumColorSync;
@JsonKey(defaultValue: false)
final bool amoledDarkTheme;
@JsonKey(defaultValue: true)
final bool checkUpdate;
@JsonKey(defaultValue: false)
final bool normalizeAudio;
@JsonKey(defaultValue: true)
final bool showSystemTrayIcon;
@JsonKey(defaultValue: true)
final bool skipNonMusic;
@JsonKey(defaultValue: false)
final bool systemTitleBar;
@JsonKey(
defaultValue: CloseBehavior.minimizeToTray,
unknownEnumValue: CloseBehavior.minimizeToTray,
)
final CloseBehavior closeBehavior;
static SpotubeColor _accentColorSchemeFromJson(Map<String, dynamic> json) { static SpotubeColor _accentColorSchemeFromJson(Map<String, dynamic> json) {
return SpotubeColor.fromString(json["color"]); return SpotubeColor.fromString(json["color"]);
@ -105,23 +114,6 @@ final class UserPreferences {
return {"color": color.toString()}; return {"color": color.toString()};
} }
static SpotubeColor _defaultAccentColorScheme() =>
const SpotubeColor(0xFF2196F3, name: "Blue");
@JsonKey(
defaultValue: UserPreferences._defaultAccentColorScheme,
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue,
)
final SpotubeColor accentColorScheme;
@JsonKey(
defaultValue: LayoutMode.adaptive,
unknownEnumValue: LayoutMode.adaptive,
)
final LayoutMode layoutMode;
static Locale _localeFromJson(Map<String, dynamic> json) { static Locale _localeFromJson(Map<String, dynamic> json) {
return Locale(json["languageCode"], json["countryCode"]); return Locale(json["languageCode"], json["countryCode"]);
} }
@ -145,144 +137,4 @@ final class UserPreferences {
return json[key] as Map<String, dynamic>?; return json[key] as Map<String, dynamic>?;
} }
static Locale _defaultLocaleValue() => const Locale("system", "system");
@JsonKey(
defaultValue: UserPreferences._defaultLocaleValue,
toJson: UserPreferences._localeToJson,
fromJson: UserPreferences._localeFromJson,
readValue: UserPreferences._localeReadValue,
)
final Locale locale;
@JsonKey(
defaultValue: Market.US,
unknownEnumValue: Market.US,
)
final Market recommendationMarket;
@JsonKey(
defaultValue: SearchMode.youtube,
unknownEnumValue: SearchMode.youtube,
)
final SearchMode searchMode;
@JsonKey(defaultValue: "")
final String downloadLocation;
@JsonKey(defaultValue: "https://pipedapi.kavin.rocks")
final String pipedInstance;
@JsonKey(
defaultValue: ThemeMode.system,
unknownEnumValue: ThemeMode.system,
)
final ThemeMode themeMode;
@JsonKey(
defaultValue: AudioSource.youtube,
unknownEnumValue: AudioSource.youtube,
)
final AudioSource audioSource;
@JsonKey(
defaultValue: SourceCodecs.weba,
unknownEnumValue: SourceCodecs.weba,
)
final SourceCodecs streamMusicCodec;
@JsonKey(
defaultValue: SourceCodecs.m4a,
unknownEnumValue: SourceCodecs.m4a,
)
final SourceCodecs downloadMusicCodec;
@JsonKey(defaultValue: true)
final bool discordPresence;
UserPreferences({
required this.audioQuality,
required this.albumColorSync,
required this.amoledDarkTheme,
required this.checkUpdate,
required this.normalizeAudio,
required this.showSystemTrayIcon,
required this.skipNonMusic,
required this.systemTitleBar,
required this.closeBehavior,
required this.accentColorScheme,
required this.layoutMode,
required this.locale,
required this.recommendationMarket,
required this.searchMode,
required this.downloadLocation,
required this.pipedInstance,
required this.themeMode,
required this.audioSource,
required this.streamMusicCodec,
required this.downloadMusicCodec,
required this.discordPresence,
});
factory UserPreferences.withDefaults() {
return UserPreferences.fromJson({});
}
factory UserPreferences.fromJson(Map<String, dynamic> json) {
return _$UserPreferencesFromJson(json);
}
Map<String, dynamic> toJson() {
return _$UserPreferencesToJson(this);
}
UserPreferences copyWith({
ThemeMode? themeMode,
SpotubeColor? accentColorScheme,
bool? albumColorSync,
bool? checkUpdate,
SourceQualities? audioQuality,
String? downloadLocation,
LayoutMode? layoutMode,
CloseBehavior? closeBehavior,
bool? showSystemTrayIcon,
Locale? locale,
String? pipedInstance,
SearchMode? searchMode,
bool? skipNonMusic,
AudioSource? audioSource,
Market? recommendationMarket,
bool? saveTrackLyrics,
bool? amoledDarkTheme,
bool? normalizeAudio,
SourceCodecs? downloadMusicCodec,
SourceCodecs? streamMusicCodec,
bool? systemTitleBar,
bool? discordPresence,
}) {
return UserPreferences(
themeMode: themeMode ?? this.themeMode,
accentColorScheme: accentColorScheme ?? this.accentColorScheme,
albumColorSync: albumColorSync ?? this.albumColorSync,
checkUpdate: checkUpdate ?? this.checkUpdate,
audioQuality: audioQuality ?? this.audioQuality,
downloadLocation: downloadLocation ?? this.downloadLocation,
layoutMode: layoutMode ?? this.layoutMode,
closeBehavior: closeBehavior ?? this.closeBehavior,
showSystemTrayIcon: showSystemTrayIcon ?? this.showSystemTrayIcon,
locale: locale ?? this.locale,
pipedInstance: pipedInstance ?? this.pipedInstance,
searchMode: searchMode ?? this.searchMode,
skipNonMusic: skipNonMusic ?? this.skipNonMusic,
audioSource: audioSource ?? this.audioSource,
recommendationMarket: recommendationMarket ?? this.recommendationMarket,
amoledDarkTheme: amoledDarkTheme ?? this.amoledDarkTheme,
downloadMusicCodec: downloadMusicCodec ?? this.downloadMusicCodec,
normalizeAudio: normalizeAudio ?? this.normalizeAudio,
streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec,
systemTitleBar: systemTitleBar ?? this.systemTitleBar,
discordPresence: discordPresence ?? this.discordPresence,
);
}
} }

View File

@ -0,0 +1,697 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'user_preferences_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
UserPreferences _$UserPreferencesFromJson(Map<String, dynamic> json) {
return _UserPreferences.fromJson(json);
}
/// @nodoc
mixin _$UserPreferences {
SourceQualities get audioQuality => throw _privateConstructorUsedError;
bool get albumColorSync => throw _privateConstructorUsedError;
bool get amoledDarkTheme => throw _privateConstructorUsedError;
bool get checkUpdate => throw _privateConstructorUsedError;
bool get normalizeAudio => throw _privateConstructorUsedError;
bool get showSystemTrayIcon => throw _privateConstructorUsedError;
bool get skipNonMusic => throw _privateConstructorUsedError;
bool get systemTitleBar => throw _privateConstructorUsedError;
CloseBehavior get closeBehavior => throw _privateConstructorUsedError;
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
SpotubeColor get accentColorScheme => throw _privateConstructorUsedError;
LayoutMode get layoutMode => throw _privateConstructorUsedError;
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
Locale get locale => throw _privateConstructorUsedError;
Market get recommendationMarket => throw _privateConstructorUsedError;
SearchMode get searchMode => throw _privateConstructorUsedError;
String get downloadLocation => throw _privateConstructorUsedError;
String get pipedInstance => throw _privateConstructorUsedError;
ThemeMode get themeMode => throw _privateConstructorUsedError;
AudioSource get audioSource => throw _privateConstructorUsedError;
SourceCodecs get streamMusicCodec => throw _privateConstructorUsedError;
SourceCodecs get downloadMusicCodec => throw _privateConstructorUsedError;
bool get discordPresence => throw _privateConstructorUsedError;
bool get endlessPlayback => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$UserPreferencesCopyWith<UserPreferences> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserPreferencesCopyWith<$Res> {
factory $UserPreferencesCopyWith(
UserPreferences value, $Res Function(UserPreferences) then) =
_$UserPreferencesCopyWithImpl<$Res, UserPreferences>;
@useResult
$Res call(
{SourceQualities audioQuality,
bool albumColorSync,
bool amoledDarkTheme,
bool checkUpdate,
bool normalizeAudio,
bool showSystemTrayIcon,
bool skipNonMusic,
bool systemTitleBar,
CloseBehavior closeBehavior,
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
SpotubeColor accentColorScheme,
LayoutMode layoutMode,
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
Locale locale,
Market recommendationMarket,
SearchMode searchMode,
String downloadLocation,
String pipedInstance,
ThemeMode themeMode,
AudioSource audioSource,
SourceCodecs streamMusicCodec,
SourceCodecs downloadMusicCodec,
bool discordPresence,
bool endlessPlayback});
}
/// @nodoc
class _$UserPreferencesCopyWithImpl<$Res, $Val extends UserPreferences>
implements $UserPreferencesCopyWith<$Res> {
_$UserPreferencesCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? audioQuality = null,
Object? albumColorSync = null,
Object? amoledDarkTheme = null,
Object? checkUpdate = null,
Object? normalizeAudio = null,
Object? showSystemTrayIcon = null,
Object? skipNonMusic = null,
Object? systemTitleBar = null,
Object? closeBehavior = null,
Object? accentColorScheme = null,
Object? layoutMode = null,
Object? locale = null,
Object? recommendationMarket = null,
Object? searchMode = null,
Object? downloadLocation = null,
Object? pipedInstance = null,
Object? themeMode = null,
Object? audioSource = null,
Object? streamMusicCodec = null,
Object? downloadMusicCodec = null,
Object? discordPresence = null,
Object? endlessPlayback = null,
}) {
return _then(_value.copyWith(
audioQuality: null == audioQuality
? _value.audioQuality
: audioQuality // ignore: cast_nullable_to_non_nullable
as SourceQualities,
albumColorSync: null == albumColorSync
? _value.albumColorSync
: albumColorSync // ignore: cast_nullable_to_non_nullable
as bool,
amoledDarkTheme: null == amoledDarkTheme
? _value.amoledDarkTheme
: amoledDarkTheme // ignore: cast_nullable_to_non_nullable
as bool,
checkUpdate: null == checkUpdate
? _value.checkUpdate
: checkUpdate // ignore: cast_nullable_to_non_nullable
as bool,
normalizeAudio: null == normalizeAudio
? _value.normalizeAudio
: normalizeAudio // ignore: cast_nullable_to_non_nullable
as bool,
showSystemTrayIcon: null == showSystemTrayIcon
? _value.showSystemTrayIcon
: showSystemTrayIcon // ignore: cast_nullable_to_non_nullable
as bool,
skipNonMusic: null == skipNonMusic
? _value.skipNonMusic
: skipNonMusic // ignore: cast_nullable_to_non_nullable
as bool,
systemTitleBar: null == systemTitleBar
? _value.systemTitleBar
: systemTitleBar // ignore: cast_nullable_to_non_nullable
as bool,
closeBehavior: null == closeBehavior
? _value.closeBehavior
: closeBehavior // ignore: cast_nullable_to_non_nullable
as CloseBehavior,
accentColorScheme: null == accentColorScheme
? _value.accentColorScheme
: accentColorScheme // ignore: cast_nullable_to_non_nullable
as SpotubeColor,
layoutMode: null == layoutMode
? _value.layoutMode
: layoutMode // ignore: cast_nullable_to_non_nullable
as LayoutMode,
locale: null == locale
? _value.locale
: locale // ignore: cast_nullable_to_non_nullable
as Locale,
recommendationMarket: null == recommendationMarket
? _value.recommendationMarket
: recommendationMarket // ignore: cast_nullable_to_non_nullable
as Market,
searchMode: null == searchMode
? _value.searchMode
: searchMode // ignore: cast_nullable_to_non_nullable
as SearchMode,
downloadLocation: null == downloadLocation
? _value.downloadLocation
: downloadLocation // ignore: cast_nullable_to_non_nullable
as String,
pipedInstance: null == pipedInstance
? _value.pipedInstance
: pipedInstance // ignore: cast_nullable_to_non_nullable
as String,
themeMode: null == themeMode
? _value.themeMode
: themeMode // ignore: cast_nullable_to_non_nullable
as ThemeMode,
audioSource: null == audioSource
? _value.audioSource
: audioSource // ignore: cast_nullable_to_non_nullable
as AudioSource,
streamMusicCodec: null == streamMusicCodec
? _value.streamMusicCodec
: streamMusicCodec // ignore: cast_nullable_to_non_nullable
as SourceCodecs,
downloadMusicCodec: null == downloadMusicCodec
? _value.downloadMusicCodec
: downloadMusicCodec // ignore: cast_nullable_to_non_nullable
as SourceCodecs,
discordPresence: null == discordPresence
? _value.discordPresence
: discordPresence // ignore: cast_nullable_to_non_nullable
as bool,
endlessPlayback: null == endlessPlayback
? _value.endlessPlayback
: endlessPlayback // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
}
/// @nodoc
abstract class _$$UserPreferencesImplCopyWith<$Res>
implements $UserPreferencesCopyWith<$Res> {
factory _$$UserPreferencesImplCopyWith(_$UserPreferencesImpl value,
$Res Function(_$UserPreferencesImpl) then) =
__$$UserPreferencesImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{SourceQualities audioQuality,
bool albumColorSync,
bool amoledDarkTheme,
bool checkUpdate,
bool normalizeAudio,
bool showSystemTrayIcon,
bool skipNonMusic,
bool systemTitleBar,
CloseBehavior closeBehavior,
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
SpotubeColor accentColorScheme,
LayoutMode layoutMode,
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
Locale locale,
Market recommendationMarket,
SearchMode searchMode,
String downloadLocation,
String pipedInstance,
ThemeMode themeMode,
AudioSource audioSource,
SourceCodecs streamMusicCodec,
SourceCodecs downloadMusicCodec,
bool discordPresence,
bool endlessPlayback});
}
/// @nodoc
class __$$UserPreferencesImplCopyWithImpl<$Res>
extends _$UserPreferencesCopyWithImpl<$Res, _$UserPreferencesImpl>
implements _$$UserPreferencesImplCopyWith<$Res> {
__$$UserPreferencesImplCopyWithImpl(
_$UserPreferencesImpl _value, $Res Function(_$UserPreferencesImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? audioQuality = null,
Object? albumColorSync = null,
Object? amoledDarkTheme = null,
Object? checkUpdate = null,
Object? normalizeAudio = null,
Object? showSystemTrayIcon = null,
Object? skipNonMusic = null,
Object? systemTitleBar = null,
Object? closeBehavior = null,
Object? accentColorScheme = null,
Object? layoutMode = null,
Object? locale = null,
Object? recommendationMarket = null,
Object? searchMode = null,
Object? downloadLocation = null,
Object? pipedInstance = null,
Object? themeMode = null,
Object? audioSource = null,
Object? streamMusicCodec = null,
Object? downloadMusicCodec = null,
Object? discordPresence = null,
Object? endlessPlayback = null,
}) {
return _then(_$UserPreferencesImpl(
audioQuality: null == audioQuality
? _value.audioQuality
: audioQuality // ignore: cast_nullable_to_non_nullable
as SourceQualities,
albumColorSync: null == albumColorSync
? _value.albumColorSync
: albumColorSync // ignore: cast_nullable_to_non_nullable
as bool,
amoledDarkTheme: null == amoledDarkTheme
? _value.amoledDarkTheme
: amoledDarkTheme // ignore: cast_nullable_to_non_nullable
as bool,
checkUpdate: null == checkUpdate
? _value.checkUpdate
: checkUpdate // ignore: cast_nullable_to_non_nullable
as bool,
normalizeAudio: null == normalizeAudio
? _value.normalizeAudio
: normalizeAudio // ignore: cast_nullable_to_non_nullable
as bool,
showSystemTrayIcon: null == showSystemTrayIcon
? _value.showSystemTrayIcon
: showSystemTrayIcon // ignore: cast_nullable_to_non_nullable
as bool,
skipNonMusic: null == skipNonMusic
? _value.skipNonMusic
: skipNonMusic // ignore: cast_nullable_to_non_nullable
as bool,
systemTitleBar: null == systemTitleBar
? _value.systemTitleBar
: systemTitleBar // ignore: cast_nullable_to_non_nullable
as bool,
closeBehavior: null == closeBehavior
? _value.closeBehavior
: closeBehavior // ignore: cast_nullable_to_non_nullable
as CloseBehavior,
accentColorScheme: null == accentColorScheme
? _value.accentColorScheme
: accentColorScheme // ignore: cast_nullable_to_non_nullable
as SpotubeColor,
layoutMode: null == layoutMode
? _value.layoutMode
: layoutMode // ignore: cast_nullable_to_non_nullable
as LayoutMode,
locale: null == locale
? _value.locale
: locale // ignore: cast_nullable_to_non_nullable
as Locale,
recommendationMarket: null == recommendationMarket
? _value.recommendationMarket
: recommendationMarket // ignore: cast_nullable_to_non_nullable
as Market,
searchMode: null == searchMode
? _value.searchMode
: searchMode // ignore: cast_nullable_to_non_nullable
as SearchMode,
downloadLocation: null == downloadLocation
? _value.downloadLocation
: downloadLocation // ignore: cast_nullable_to_non_nullable
as String,
pipedInstance: null == pipedInstance
? _value.pipedInstance
: pipedInstance // ignore: cast_nullable_to_non_nullable
as String,
themeMode: null == themeMode
? _value.themeMode
: themeMode // ignore: cast_nullable_to_non_nullable
as ThemeMode,
audioSource: null == audioSource
? _value.audioSource
: audioSource // ignore: cast_nullable_to_non_nullable
as AudioSource,
streamMusicCodec: null == streamMusicCodec
? _value.streamMusicCodec
: streamMusicCodec // ignore: cast_nullable_to_non_nullable
as SourceCodecs,
downloadMusicCodec: null == downloadMusicCodec
? _value.downloadMusicCodec
: downloadMusicCodec // ignore: cast_nullable_to_non_nullable
as SourceCodecs,
discordPresence: null == discordPresence
? _value.discordPresence
: discordPresence // ignore: cast_nullable_to_non_nullable
as bool,
endlessPlayback: null == endlessPlayback
? _value.endlessPlayback
: endlessPlayback // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// @nodoc
@JsonSerializable()
class _$UserPreferencesImpl implements _UserPreferences {
const _$UserPreferencesImpl(
{this.audioQuality = SourceQualities.high,
this.albumColorSync = true,
this.amoledDarkTheme = false,
this.checkUpdate = true,
this.normalizeAudio = false,
this.showSystemTrayIcon = true,
this.skipNonMusic = false,
this.systemTitleBar = false,
this.closeBehavior = CloseBehavior.minimizeToTray,
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
this.accentColorScheme = const SpotubeColor(0xFF2196F3, name: "Blue"),
this.layoutMode = LayoutMode.adaptive,
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
this.locale = const Locale("system", "system"),
this.recommendationMarket = Market.US,
this.searchMode = SearchMode.youtube,
this.downloadLocation = "",
this.pipedInstance = "https://pipedapi.kavin.rocks",
this.themeMode = ThemeMode.system,
this.audioSource = AudioSource.youtube,
this.streamMusicCodec = SourceCodecs.weba,
this.downloadMusicCodec = SourceCodecs.m4a,
this.discordPresence = true,
this.endlessPlayback = true});
factory _$UserPreferencesImpl.fromJson(Map<String, dynamic> json) =>
_$$UserPreferencesImplFromJson(json);
@override
@JsonKey()
final SourceQualities audioQuality;
@override
@JsonKey()
final bool albumColorSync;
@override
@JsonKey()
final bool amoledDarkTheme;
@override
@JsonKey()
final bool checkUpdate;
@override
@JsonKey()
final bool normalizeAudio;
@override
@JsonKey()
final bool showSystemTrayIcon;
@override
@JsonKey()
final bool skipNonMusic;
@override
@JsonKey()
final bool systemTitleBar;
@override
@JsonKey()
final CloseBehavior closeBehavior;
@override
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
final SpotubeColor accentColorScheme;
@override
@JsonKey()
final LayoutMode layoutMode;
@override
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
final Locale locale;
@override
@JsonKey()
final Market recommendationMarket;
@override
@JsonKey()
final SearchMode searchMode;
@override
@JsonKey()
final String downloadLocation;
@override
@JsonKey()
final String pipedInstance;
@override
@JsonKey()
final ThemeMode themeMode;
@override
@JsonKey()
final AudioSource audioSource;
@override
@JsonKey()
final SourceCodecs streamMusicCodec;
@override
@JsonKey()
final SourceCodecs downloadMusicCodec;
@override
@JsonKey()
final bool discordPresence;
@override
@JsonKey()
final bool endlessPlayback;
@override
String toString() {
return 'UserPreferences(audioQuality: $audioQuality, albumColorSync: $albumColorSync, amoledDarkTheme: $amoledDarkTheme, checkUpdate: $checkUpdate, normalizeAudio: $normalizeAudio, showSystemTrayIcon: $showSystemTrayIcon, skipNonMusic: $skipNonMusic, systemTitleBar: $systemTitleBar, closeBehavior: $closeBehavior, accentColorScheme: $accentColorScheme, layoutMode: $layoutMode, locale: $locale, recommendationMarket: $recommendationMarket, searchMode: $searchMode, downloadLocation: $downloadLocation, pipedInstance: $pipedInstance, themeMode: $themeMode, audioSource: $audioSource, streamMusicCodec: $streamMusicCodec, downloadMusicCodec: $downloadMusicCodec, discordPresence: $discordPresence, endlessPlayback: $endlessPlayback)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserPreferencesImpl &&
(identical(other.audioQuality, audioQuality) ||
other.audioQuality == audioQuality) &&
(identical(other.albumColorSync, albumColorSync) ||
other.albumColorSync == albumColorSync) &&
(identical(other.amoledDarkTheme, amoledDarkTheme) ||
other.amoledDarkTheme == amoledDarkTheme) &&
(identical(other.checkUpdate, checkUpdate) ||
other.checkUpdate == checkUpdate) &&
(identical(other.normalizeAudio, normalizeAudio) ||
other.normalizeAudio == normalizeAudio) &&
(identical(other.showSystemTrayIcon, showSystemTrayIcon) ||
other.showSystemTrayIcon == showSystemTrayIcon) &&
(identical(other.skipNonMusic, skipNonMusic) ||
other.skipNonMusic == skipNonMusic) &&
(identical(other.systemTitleBar, systemTitleBar) ||
other.systemTitleBar == systemTitleBar) &&
(identical(other.closeBehavior, closeBehavior) ||
other.closeBehavior == closeBehavior) &&
(identical(other.accentColorScheme, accentColorScheme) ||
other.accentColorScheme == accentColorScheme) &&
(identical(other.layoutMode, layoutMode) ||
other.layoutMode == layoutMode) &&
(identical(other.locale, locale) || other.locale == locale) &&
(identical(other.recommendationMarket, recommendationMarket) ||
other.recommendationMarket == recommendationMarket) &&
(identical(other.searchMode, searchMode) ||
other.searchMode == searchMode) &&
(identical(other.downloadLocation, downloadLocation) ||
other.downloadLocation == downloadLocation) &&
(identical(other.pipedInstance, pipedInstance) ||
other.pipedInstance == pipedInstance) &&
(identical(other.themeMode, themeMode) ||
other.themeMode == themeMode) &&
(identical(other.audioSource, audioSource) ||
other.audioSource == audioSource) &&
(identical(other.streamMusicCodec, streamMusicCodec) ||
other.streamMusicCodec == streamMusicCodec) &&
(identical(other.downloadMusicCodec, downloadMusicCodec) ||
other.downloadMusicCodec == downloadMusicCodec) &&
(identical(other.discordPresence, discordPresence) ||
other.discordPresence == discordPresence) &&
(identical(other.endlessPlayback, endlessPlayback) ||
other.endlessPlayback == endlessPlayback));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hashAll([
runtimeType,
audioQuality,
albumColorSync,
amoledDarkTheme,
checkUpdate,
normalizeAudio,
showSystemTrayIcon,
skipNonMusic,
systemTitleBar,
closeBehavior,
accentColorScheme,
layoutMode,
locale,
recommendationMarket,
searchMode,
downloadLocation,
pipedInstance,
themeMode,
audioSource,
streamMusicCodec,
downloadMusicCodec,
discordPresence,
endlessPlayback
]);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$UserPreferencesImplCopyWith<_$UserPreferencesImpl> get copyWith =>
__$$UserPreferencesImplCopyWithImpl<_$UserPreferencesImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$UserPreferencesImplToJson(
this,
);
}
}
abstract class _UserPreferences implements UserPreferences {
const factory _UserPreferences(
{final SourceQualities audioQuality,
final bool albumColorSync,
final bool amoledDarkTheme,
final bool checkUpdate,
final bool normalizeAudio,
final bool showSystemTrayIcon,
final bool skipNonMusic,
final bool systemTitleBar,
final CloseBehavior closeBehavior,
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
final SpotubeColor accentColorScheme,
final LayoutMode layoutMode,
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
final Locale locale,
final Market recommendationMarket,
final SearchMode searchMode,
final String downloadLocation,
final String pipedInstance,
final ThemeMode themeMode,
final AudioSource audioSource,
final SourceCodecs streamMusicCodec,
final SourceCodecs downloadMusicCodec,
final bool discordPresence,
final bool endlessPlayback}) = _$UserPreferencesImpl;
factory _UserPreferences.fromJson(Map<String, dynamic> json) =
_$UserPreferencesImpl.fromJson;
@override
SourceQualities get audioQuality;
@override
bool get albumColorSync;
@override
bool get amoledDarkTheme;
@override
bool get checkUpdate;
@override
bool get normalizeAudio;
@override
bool get showSystemTrayIcon;
@override
bool get skipNonMusic;
@override
bool get systemTitleBar;
@override
CloseBehavior get closeBehavior;
@override
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
readValue: UserPreferences._accentColorSchemeReadValue)
SpotubeColor get accentColorScheme;
@override
LayoutMode get layoutMode;
@override
@JsonKey(
fromJson: UserPreferences._localeFromJson,
toJson: UserPreferences._localeToJson,
readValue: UserPreferences._localeReadValue)
Locale get locale;
@override
Market get recommendationMarket;
@override
SearchMode get searchMode;
@override
String get downloadLocation;
@override
String get pipedInstance;
@override
ThemeMode get themeMode;
@override
AudioSource get audioSource;
@override
SourceCodecs get streamMusicCodec;
@override
SourceCodecs get downloadMusicCodec;
@override
bool get discordPresence;
@override
bool get endlessPlayback;
@override
@JsonKey(ignore: true)
_$$UserPreferencesImplCopyWith<_$UserPreferencesImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -6,67 +6,63 @@ part of 'user_preferences_state.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
UserPreferences _$UserPreferencesFromJson(Map<String, dynamic> json) => _$UserPreferencesImpl _$$UserPreferencesImplFromJson(
UserPreferences( Map<String, dynamic> json) =>
audioQuality: $enumDecodeNullable( _$UserPreferencesImpl(
_$SourceQualitiesEnumMap, json['audioQuality'], audioQuality:
unknownValue: SourceQualities.high) ?? $enumDecodeNullable(_$SourceQualitiesEnumMap, json['audioQuality']) ??
SourceQualities.high, SourceQualities.high,
albumColorSync: json['albumColorSync'] as bool? ?? true, albumColorSync: json['albumColorSync'] as bool? ?? true,
amoledDarkTheme: json['amoledDarkTheme'] as bool? ?? false, amoledDarkTheme: json['amoledDarkTheme'] as bool? ?? false,
checkUpdate: json['checkUpdate'] as bool? ?? true, checkUpdate: json['checkUpdate'] as bool? ?? true,
normalizeAudio: json['normalizeAudio'] as bool? ?? false, normalizeAudio: json['normalizeAudio'] as bool? ?? false,
showSystemTrayIcon: json['showSystemTrayIcon'] as bool? ?? true, showSystemTrayIcon: json['showSystemTrayIcon'] as bool? ?? true,
skipNonMusic: json['skipNonMusic'] as bool? ?? true, skipNonMusic: json['skipNonMusic'] as bool? ?? false,
systemTitleBar: json['systemTitleBar'] as bool? ?? false, systemTitleBar: json['systemTitleBar'] as bool? ?? false,
closeBehavior: $enumDecodeNullable( closeBehavior:
_$CloseBehaviorEnumMap, json['closeBehavior'], $enumDecodeNullable(_$CloseBehaviorEnumMap, json['closeBehavior']) ??
unknownValue: CloseBehavior.minimizeToTray) ?? CloseBehavior.minimizeToTray,
CloseBehavior.minimizeToTray,
accentColorScheme: UserPreferences._accentColorSchemeReadValue( accentColorScheme: UserPreferences._accentColorSchemeReadValue(
json, 'accentColorScheme') == json, 'accentColorScheme') ==
null null
? UserPreferences._defaultAccentColorScheme() ? const SpotubeColor(0xFF2196F3, name: "Blue")
: UserPreferences._accentColorSchemeFromJson( : UserPreferences._accentColorSchemeFromJson(
UserPreferences._accentColorSchemeReadValue( UserPreferences._accentColorSchemeReadValue(
json, 'accentColorScheme') as Map<String, dynamic>), json, 'accentColorScheme') as Map<String, dynamic>),
layoutMode: $enumDecodeNullable(_$LayoutModeEnumMap, json['layoutMode'], layoutMode:
unknownValue: LayoutMode.adaptive) ?? $enumDecodeNullable(_$LayoutModeEnumMap, json['layoutMode']) ??
LayoutMode.adaptive, LayoutMode.adaptive,
locale: UserPreferences._localeReadValue(json, 'locale') == null locale: UserPreferences._localeReadValue(json, 'locale') == null
? UserPreferences._defaultLocaleValue() ? const Locale("system", "system")
: UserPreferences._localeFromJson( : UserPreferences._localeFromJson(
UserPreferences._localeReadValue(json, 'locale') UserPreferences._localeReadValue(json, 'locale')
as Map<String, dynamic>), as Map<String, dynamic>),
recommendationMarket: $enumDecodeNullable( recommendationMarket:
_$MarketEnumMap, json['recommendationMarket'], $enumDecodeNullable(_$MarketEnumMap, json['recommendationMarket']) ??
unknownValue: Market.US) ?? Market.US,
Market.US, searchMode:
searchMode: $enumDecodeNullable(_$SearchModeEnumMap, json['searchMode'], $enumDecodeNullable(_$SearchModeEnumMap, json['searchMode']) ??
unknownValue: SearchMode.youtube) ?? SearchMode.youtube,
SearchMode.youtube, downloadLocation: json['downloadLocation'] as String? ?? "",
downloadLocation: json['downloadLocation'] as String? ?? '',
pipedInstance: pipedInstance:
json['pipedInstance'] as String? ?? 'https://pipedapi.kavin.rocks', json['pipedInstance'] as String? ?? "https://pipedapi.kavin.rocks",
themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode'], themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ??
unknownValue: ThemeMode.system) ??
ThemeMode.system, ThemeMode.system,
audioSource: $enumDecodeNullable( audioSource:
_$AudioSourceEnumMap, json['audioSource'], $enumDecodeNullable(_$AudioSourceEnumMap, json['audioSource']) ??
unknownValue: AudioSource.youtube) ?? AudioSource.youtube,
AudioSource.youtube,
streamMusicCodec: $enumDecodeNullable( streamMusicCodec: $enumDecodeNullable(
_$SourceCodecsEnumMap, json['streamMusicCodec'], _$SourceCodecsEnumMap, json['streamMusicCodec']) ??
unknownValue: SourceCodecs.weba) ??
SourceCodecs.weba, SourceCodecs.weba,
downloadMusicCodec: $enumDecodeNullable( downloadMusicCodec: $enumDecodeNullable(
_$SourceCodecsEnumMap, json['downloadMusicCodec'], _$SourceCodecsEnumMap, json['downloadMusicCodec']) ??
unknownValue: SourceCodecs.m4a) ??
SourceCodecs.m4a, SourceCodecs.m4a,
discordPresence: json['discordPresence'] as bool? ?? true, discordPresence: json['discordPresence'] as bool? ?? true,
endlessPlayback: json['endlessPlayback'] as bool? ?? true,
); );
Map<String, dynamic> _$UserPreferencesToJson(UserPreferences instance) => Map<String, dynamic> _$$UserPreferencesImplToJson(
_$UserPreferencesImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'audioQuality': _$SourceQualitiesEnumMap[instance.audioQuality]!, 'audioQuality': _$SourceQualitiesEnumMap[instance.audioQuality]!,
'albumColorSync': instance.albumColorSync, 'albumColorSync': instance.albumColorSync,
@ -90,6 +86,7 @@ Map<String, dynamic> _$UserPreferencesToJson(UserPreferences instance) =>
'streamMusicCodec': _$SourceCodecsEnumMap[instance.streamMusicCodec]!, 'streamMusicCodec': _$SourceCodecsEnumMap[instance.streamMusicCodec]!,
'downloadMusicCodec': _$SourceCodecsEnumMap[instance.downloadMusicCodec]!, 'downloadMusicCodec': _$SourceCodecsEnumMap[instance.downloadMusicCodec]!,
'discordPresence': instance.discordPresence, 'discordPresence': instance.discordPresence,
'endlessPlayback': instance.endlessPlayback,
}; };
const _$SourceQualitiesEnumMap = { const _$SourceQualitiesEnumMap = {

View File

@ -957,8 +957,16 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
freezed:
dependency: "direct dev"
description:
name: freezed
sha256: "6c5031daae12c7072b3a87eff98983076434b4889ef2a44384d0cae3f82372ba"
url: "https://pub.dev"
source: hosted
version: "2.4.6"
freezed_annotation: freezed_annotation:
dependency: transitive dependency: "direct main"
description: description:
name: freezed_annotation name: freezed_annotation
sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d

View File

@ -122,6 +122,7 @@ dependencies:
app_links: ^3.5.0 app_links: ^3.5.0
win32_registry: ^1.1.2 win32_registry: ^1.1.2
flutter_sharing_intent: ^1.1.0 flutter_sharing_intent: ^1.1.0
freezed_annotation: ^2.4.1
dev_dependencies: dev_dependencies:
build_runner: ^2.3.2 build_runner: ^2.3.2
@ -138,6 +139,7 @@ dev_dependencies:
json_serializable: ^6.6.2 json_serializable: ^6.6.2
pub_api_client: ^2.4.0 pub_api_client: ^2.4.0
pubspec_parse: ^1.2.2 pubspec_parse: ^1.2.2
freezed: ^2.4.6
dependency_overrides: dependency_overrides:
http: ^1.1.0 http: ^1.1.0

View File

@ -2,108 +2,126 @@
"ar": [ "ar": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"bn": [ "bn": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"ca": [ "ca": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"de": [ "de": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"es": [ "es": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"fa": [ "fa": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"fr": [ "fr": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"hi": [ "hi": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"it": [ "it": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"ja": [ "ja": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"ne": [ "ne": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"nl": [ "nl": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"pl": [ "pl": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"pt": [ "pt": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"ru": [ "ru": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"tr": [ "tr": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"uk": [ "uk": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
], ],
"zh": [ "zh": [
"start_a_radio", "start_a_radio",
"how_to_start_radio", "how_to_start_radio",
"replace_queue_question" "replace_queue_question",
"endless_playback"
] ]
} }