0.6.12 - bug fixes

This commit is contained in:
exttex 2021-07-02 18:28:59 +02:00
parent aa7f82b399
commit 972e84c136
18 changed files with 271 additions and 150 deletions

View File

@ -214,7 +214,13 @@ public class Deezer {
original = original.replaceAll("%title%", sanitize(publicTrack.getString("title"))); original = original.replaceAll("%title%", sanitize(publicTrack.getString("title")));
original = original.replaceAll("%album%", sanitize(publicTrack.getJSONObject("album").getString("title"))); original = original.replaceAll("%album%", sanitize(publicTrack.getJSONObject("album").getString("title")));
original = original.replaceAll("%artist%", sanitize(publicTrack.getJSONObject("artist").getString("name"))); original = original.replaceAll("%artist%", sanitize(publicTrack.getJSONObject("artist").getString("name")));
// Album might not be available
try {
original = original.replaceAll("%albumArtist%", sanitize(publicAlbum.getJSONObject("artist").getString("name"))); original = original.replaceAll("%albumArtist%", sanitize(publicAlbum.getJSONObject("artist").getString("name")));
} catch (Exception e) {
original = original.replaceAll("%albumArtist%", sanitize(publicTrack.getJSONObject("artist").getString("name")));
}
//Artists //Artists
String artists = ""; String artists = "";
String feats = ""; String feats = "";
@ -275,15 +281,16 @@ public class Deezer {
if (!artists.contains(artist)) if (!artists.contains(artist))
artists += settings.artistSeparator + artist; artists += settings.artistSeparator + artist;
} }
boolean albumAvailable = !publicAlbum.has("error");
if (settings.tags.artist) tag.addField(FieldKey.ARTIST, artists.substring(settings.artistSeparator.length())); if (settings.tags.artist) tag.addField(FieldKey.ARTIST, artists.substring(settings.artistSeparator.length()));
if (settings.tags.track) tag.setField(FieldKey.TRACK, String.format("%02d", publicTrack.getInt("track_position"))); if (settings.tags.track) tag.setField(FieldKey.TRACK, String.format("%02d", publicTrack.getInt("track_position")));
if (settings.tags.disc) tag.setField(FieldKey.DISC_NO, Integer.toString(publicTrack.getInt("disk_number"))); if (settings.tags.disc) tag.setField(FieldKey.DISC_NO, Integer.toString(publicTrack.getInt("disk_number")));
if (settings.tags.albumArtist) tag.setField(FieldKey.ALBUM_ARTIST, publicAlbum.getJSONObject("artist").getString("name")); if (settings.tags.albumArtist && albumAvailable) tag.setField(FieldKey.ALBUM_ARTIST, publicAlbum.getJSONObject("artist").getString("name"));
if (settings.tags.date) tag.setField(FieldKey.YEAR, publicTrack.getString("release_date").substring(0, 4)); if (settings.tags.date) tag.setField(FieldKey.YEAR, publicTrack.getString("release_date").substring(0, 4));
if (settings.tags.label) tag.setField(FieldKey.RECORD_LABEL, publicAlbum.getString("label")); if (settings.tags.label && albumAvailable) tag.setField(FieldKey.RECORD_LABEL, publicAlbum.getString("label"));
if (settings.tags.isrc) tag.setField(FieldKey.ISRC, publicTrack.getString("isrc")); if (settings.tags.isrc) tag.setField(FieldKey.ISRC, publicTrack.getString("isrc"));
if (settings.tags.upc) tag.setField(FieldKey.BARCODE, publicAlbum.getString("upc")); if (settings.tags.upc && albumAvailable) tag.setField(FieldKey.BARCODE, publicAlbum.getString("upc"));
if (settings.tags.trackTotal) tag.setField(FieldKey.TRACK_TOTAL, Integer.toString(publicAlbum.getInt("nb_tracks"))); if (settings.tags.trackTotal && albumAvailable) tag.setField(FieldKey.TRACK_TOTAL, Integer.toString(publicAlbum.getInt("nb_tracks")));
//BPM //BPM
if (publicTrack.has("bpm") && (int)publicTrack.getDouble("bpm") > 0) if (publicTrack.has("bpm") && (int)publicTrack.getDouble("bpm") > 0)
@ -301,6 +308,7 @@ public class Deezer {
//Genres //Genres
String genres = ""; String genres = "";
if (albumAvailable) {
for (int i=0; i<publicAlbum.getJSONObject("genres").getJSONArray("data").length(); i++) { for (int i=0; i<publicAlbum.getJSONObject("genres").getJSONArray("data").length(); i++) {
String genre = publicAlbum.getJSONObject("genres").getJSONArray("data").getJSONObject(0).getString("name"); String genre = publicAlbum.getJSONObject("genres").getJSONArray("data").getJSONObject(0).getString("name");
if (!genres.contains(genre)) { if (!genres.contains(genre)) {
@ -309,6 +317,7 @@ public class Deezer {
} }
if (genres.length() > 2 && settings.tags.genre) if (genres.length() > 2 && settings.tags.genre)
tag.setField(FieldKey.GENRE, genres.substring(2)); tag.setField(FieldKey.GENRE, genres.substring(2));
}
//Additional tags from private api //Additional tags from private api
if (settings.tags.contributors) if (settings.tags.contributors)

View File

@ -478,7 +478,7 @@ public class DownloadService extends Service {
File coverFile = new File(outFile.getPath().substring(0, outFile.getPath().lastIndexOf('.')) + ".jpg"); File coverFile = new File(outFile.getPath().substring(0, outFile.getPath().lastIndexOf('.')) + ".jpg");
try { try {
URL url = new URL("http://e-cdn-images.deezer.com/images/cover/" + albumJson.getString("md5_image") + "/" + Integer.toString(settings.albumArtResolution) + "x" + Integer.toString(settings.albumArtResolution) + "-000000-80-0-0.jpg"); URL url = new URL("http://e-cdn-images.deezer.com/images/cover/" + trackJson.getString("md5_image") + "/" + Integer.toString(settings.albumArtResolution) + "x" + Integer.toString(settings.albumArtResolution) + "-000000-80-0-0.jpg");
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//Set headers //Set headers
connection.setRequestMethod("GET"); connection.setRequestMethod("GET");

View File

@ -1,15 +1,11 @@
import 'dart:async';
import 'package:freezer/api/deezer.dart';
import 'package:freezer/api/definitions.dart'; import 'package:freezer/api/definitions.dart';
import 'package:freezer/ui/details_screens.dart';
import 'package:freezer/ui/library.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'dart:io'; import 'dart:io';
import 'dart:convert'; import 'dart:convert';
import 'dart:async';
part 'cache.g.dart'; part 'cache.g.dart';
@ -68,6 +64,12 @@ class Cache {
if (searchHistory == null) if (searchHistory == null)
searchHistory = []; searchHistory = [];
// Remove duplicate
int i = searchHistory.indexWhere((e) => e.data.id == item.id);
if (i != -1) {
searchHistory.removeAt(i);
}
if (item is Track) if (item is Track)
searchHistory.add(SearchHistoryItem(item, SearchHistoryItemType.TRACK)); searchHistory.add(SearchHistoryItem(item, SearchHistoryItemType.TRACK));
if (item is Album) if (item is Album)

View File

@ -32,7 +32,6 @@ class PlayerHelper {
QueueSource queueSource; QueueSource queueSource;
LoopMode repeatType = LoopMode.off; LoopMode repeatType = LoopMode.off;
Timer _timer; Timer _timer;
Scrobblenaut scrobblenaut;
int audioSession; int audioSession;
int _prevAudioSession; int _prevAudioSession;
bool equalizerOpen = false; bool equalizerOpen = false;
@ -53,6 +52,7 @@ class PlayerHelper {
//After audio_service is loaded, load queue, set quality //After audio_service is loaded, load queue, set quality
await settings.updateAudioServiceQuality(); await settings.updateAudioServiceQuality();
await AudioService.customAction('load'); await AudioService.customAction('load');
await authorizeLastFM();
break; break;
case 'onRestore': case 'onRestore':
//Load queueSource from isolate //Load queueSource from isolate
@ -126,15 +126,6 @@ class PlayerHelper {
if (settings.logListen) { if (settings.logListen) {
deezerAPI.logListen(AudioService.currentMediaItem.id); deezerAPI.logListen(AudioService.currentMediaItem.id);
} }
//LastFM
if (scrobblenaut != null) {
await scrobblenaut.track.scrobble(
track: AudioService.currentMediaItem.title,
artist: AudioService.currentMediaItem.artist,
album: AudioService.currentMediaItem.album,
);
}
} }
}); });
@ -163,15 +154,7 @@ class PlayerHelper {
Future authorizeLastFM() async { Future authorizeLastFM() async {
if (settings.lastFMUsername == null || settings.lastFMPassword == null) return; if (settings.lastFMUsername == null || settings.lastFMPassword == null) return;
try { await AudioService.customAction("authorizeLastFM", [settings.lastFMUsername, settings.lastFMPassword]);
LastFM lastFM = await LastFM.authenticateWithPasswordHash(
apiKey: 'b6ab5ae967bcd8b10b23f68f42493829',
apiSecret: '861b0dff9a8a574bec747f9dab8b82bf',
username: settings.lastFMUsername,
passwordHash: settings.lastFMPassword
);
scrobblenaut = Scrobblenaut(lastFM: lastFM);
} catch (e) {}
} }
Future toggleShuffle() async { Future toggleShuffle() async {
@ -390,6 +373,10 @@ class AudioPlayerTask extends BackgroundAudioTask {
LoopMode _loopMode = LoopMode.off; LoopMode _loopMode = LoopMode.off;
Completer _androidAutoCallback; Completer _androidAutoCallback;
Scrobblenaut _scrobblenaut;
bool _scrobblenautReady = false;
// Last logged track id
String _loggedTrackId;
MediaItem get mediaItem => _queue[_queueIndex]; MediaItem get mediaItem => _queue[_queueIndex];
@ -473,13 +460,23 @@ class AudioPlayerTask extends BackgroundAudioTask {
} }
@override @override
Future onPlay() { Future onPlay() async {
_player.play(); _player.play();
//Restore position on play //Restore position on play
if (_lastPosition != null) { if (_lastPosition != null) {
onSeekTo(_lastPosition); onSeekTo(_lastPosition);
_lastPosition = null; _lastPosition = null;
} }
//LastFM
if (_scrobblenautReady && mediaItem.id != _loggedTrackId) {
_loggedTrackId = mediaItem.id;
await _scrobblenaut.track.scrobble(
track: mediaItem.title,
artist: mediaItem.artist,
album: mediaItem.album,
);
}
} }
@override @override
@ -515,6 +512,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
@override @override
Future<void> onSkipToNext() async { Future<void> onSkipToNext() async {
_lastPosition = null;
if (_queueIndex == _queue.length-1) return; if (_queueIndex == _queue.length-1) return;
//Update buffering state //Update buffering state
_skipState = AudioProcessingState.skippingToNext; _skipState = AudioProcessingState.skippingToNext;
@ -618,6 +616,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
//Replace current queue //Replace current queue
@override @override
Future onUpdateQueue(List<MediaItem> q) async { Future onUpdateQueue(List<MediaItem> q) async {
_lastPosition = null;
//just_audio //just_audio
_shuffle = false; _shuffle = false;
_originalQueue = null; _originalQueue = null;
@ -793,6 +792,25 @@ class AudioPlayerTask extends BackgroundAudioTask {
_visualizerSubscription = null; _visualizerSubscription = null;
} }
break; break;
//Authorize lastfm
case 'authorizeLastFM':
String username = args[0];
String password = args[1];
try {
LastFM lastFM = await LastFM.authenticateWithPasswordHash(
apiKey: 'b6ab5ae967bcd8b10b23f68f42493829',
apiSecret: '861b0dff9a8a574bec747f9dab8b82bf',
username: username,
passwordHash: password
);
_scrobblenaut = Scrobblenaut(lastFM: lastFM);
_scrobblenautReady = true;
} catch (e) { print(e); }
break;
case 'disableLastFM':
_scrobblenaut = null;
_scrobblenautReady = false;
break;
} }
return true; return true;

View File

@ -378,6 +378,35 @@ const language_en_us = {
//0.6.11, offline text OCD lol //0.6.11, offline text OCD lol
"Track removed from offline!": "Track removed from offline!", "Track removed from offline!": "Track removed from offline!",
"Removed album from offline!": "Removed album from offline!", "Removed album from offline!": "Removed album from offline!",
"Playlist removed from offline!": "Playlist removed from offline!" "Playlist removed from offline!": "Playlist removed from offline!",
//0.6.11 - a11y by dangou
"Repeat": "Repeat",
"Repeat one": "Repeat one",
"Repeat off": "Repeat off",
"Love": "Love",
"Unlove": "Unlove",
"Dislike": "Dislike",
"Close": "Close",
"Sort playlist": "Sort playlist",
"Sort ascending": "Sort ascending",
"Sort descending": "Sort descending",
"Stop": "Stop",
"Start": "Start",
"Clear all": "Clear all",
"Play previous": "Play previous",
"Play": "Play",
"Pause": "Pause",
"Remove": "Remove",
"Seekbar": "Seekbar",
"Singles": "Singles",
"Featured": "Featured",
"Fans": "Fans",
"Duration": "Duration",
"Sort": "Sort",
//0.6.12
"Your ARL might be expired, try logging out and logging back in using new ARL or browser.": "Your ARL might be expired, try logging out and logging back in using new ARL or browser.",
} }
}; };

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:palette_generator/palette_generator.dart'; import 'package:palette_generator/palette_generator.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view.dart';
import 'package:freezer/translations.i18n.dart';
ImagesDatabase imagesDatabase = ImagesDatabase(); ImagesDatabase imagesDatabase = ImagesDatabase();
@ -115,12 +116,15 @@ class _ZoomableImageState extends State<ZoomableImage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
ctx = context; ctx = context;
return TextButton( return TextButton(
child: Semantics(
child: CachedImage( child: CachedImage(
url: widget.url, url: widget.url,
rounded: widget.rounded, rounded: widget.rounded,
width: widget.width, width: widget.width,
fullThumb: true, fullThumb: true,
), ),
label: "Album art".i18n,
),
onPressed: () { onPressed: () {
Navigator.of(context).push(PageRouteBuilder( Navigator.of(context).push(PageRouteBuilder(
opaque: false, // transparent background opaque: false, // transparent background

View File

@ -127,7 +127,7 @@ class _AlbumDetailsState extends State<AlbumDetails> {
children: <Widget>[ children: <Widget>[
Row( Row(
children: <Widget>[ children: <Widget>[
Icon(Icons.audiotrack, size: 32.0,), Icon(Icons.audiotrack, size: 32.0, semanticLabel: "Tracks".i18n,),
Container(width: 8.0, height: 42.0,), //Height to adjust card height Container(width: 8.0, height: 42.0,), //Height to adjust card height
Text( Text(
album.tracks.length.toString(), album.tracks.length.toString(),
@ -137,7 +137,7 @@ class _AlbumDetailsState extends State<AlbumDetails> {
), ),
Row( Row(
children: <Widget>[ children: <Widget>[
Icon(Icons.timelapse, size: 32.0,), Icon(Icons.timelapse, size: 32.0, semanticLabel: "Duration".i18n,),
Container(width: 8.0,), Container(width: 8.0,),
Text( Text(
album.durationString, album.durationString,
@ -147,7 +147,7 @@ class _AlbumDetailsState extends State<AlbumDetails> {
), ),
Row( Row(
children: <Widget>[ children: <Widget>[
Icon(Icons.people, size: 32.0,), Icon(Icons.people, size: 32.0, semanticLabel: "Fans".i18n),
Container(width: 8.0,), Container(width: 8.0,),
Text( Text(
album.fansString, album.fansString,
@ -361,6 +361,7 @@ class ArtistDetails extends StatelessWidget {
Icon( Icon(
Icons.people, Icons.people,
size: 32.0, size: 32.0,
semanticLabel: "Fans".i18n,
), ),
Container( Container(
width: 8, width: 8,
@ -377,7 +378,7 @@ class ArtistDetails extends StatelessWidget {
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Icon(Icons.album, size: 32.0), Icon(Icons.album, size: 32.0, semanticLabel: "Albums".i18n,),
Container( Container(
width: 8.0, width: 8.0,
), ),
@ -666,9 +667,9 @@ class _DiscographyScreenState extends State<DiscographyScreen> {
'Discography'.i18n, 'Discography'.i18n,
bottom: TabBar( bottom: TabBar(
tabs: [ tabs: [
Tab(icon: Icon(Icons.album)), Tab(icon: Icon(Icons.album, semanticLabel: "Albums".i18n,)),
Tab(icon: Icon(Icons.audiotrack)), Tab(icon: Icon(Icons.audiotrack, semanticLabel: "Singles".i18n)),
Tab(icon: Icon(Icons.recent_actors)) Tab(icon: Icon(Icons.recent_actors, semanticLabel: "Featured".i18n,))
], ],
), ),
height: 100.0, height: 100.0,
@ -894,6 +895,7 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
Icon( Icon(
Icons.audiotrack, Icons.audiotrack,
size: 32.0, size: 32.0,
semanticLabel: "Tracks".i18n,
), ),
Container(width: 8.0,), Container(width: 8.0,),
Text((playlist.trackCount??playlist.tracks.length).toString(), style: TextStyle(fontSize: 16),) Text((playlist.trackCount??playlist.tracks.length).toString(), style: TextStyle(fontSize: 16),)
@ -905,6 +907,7 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
Icon( Icon(
Icons.timelapse, Icons.timelapse,
size: 32.0, size: 32.0,
semanticLabel: "Duration".i18n,
), ),
Container(width: 8.0,), Container(width: 8.0,),
Text(playlist.durationString, style: TextStyle(fontSize: 16),) Text(playlist.durationString, style: TextStyle(fontSize: 16),)
@ -943,7 +946,8 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
if (playlist.user.name != deezerAPI.userName) if (playlist.user.name != deezerAPI.userName)
IconButton( IconButton(
icon: Icon(playlist.library ? Icons.favorite : Icons.favorite_outline, size: 32), icon: Icon(playlist.library ? Icons.favorite : Icons.favorite_outline, size: 32,
semanticLabel: playlist.library ? "Unlove".i18n : "Love".i18n,),
onPressed: () async { onPressed: () async {
//Add to library //Add to library
if (!playlist.library) { if (!playlist.library) {
@ -968,14 +972,14 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
}, },
), ),
IconButton( IconButton(
icon: Icon(Icons.file_download, size: 32.0,), icon: Icon(Icons.file_download, size: 32.0, semanticLabel: "Download".i18n,),
onPressed: () async { onPressed: () async {
if (await downloadManager.addOfflinePlaylist(playlist, private: false, context: context) != false) if (await downloadManager.addOfflinePlaylist(playlist, private: false, context: context) != false)
MenuSheet(context).showDownloadStartedToast(); MenuSheet(context).showDownloadStartedToast();
}, },
), ),
PopupMenuButton( PopupMenuButton(
child: Icon(Icons.sort, size: 32.0), child: Icon(Icons.sort, size: 32.0, semanticLabel: "Sort playlist".i18n,),
color: Theme.of(context).scaffoldBackgroundColor, color: Theme.of(context).scaffoldBackgroundColor,
onSelected: (SortType s) async { onSelected: (SortType s) async {
if (playlist.tracks.length < playlist.trackCount) { if (playlist.tracks.length < playlist.trackCount) {
@ -1013,7 +1017,8 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
], ],
), ),
IconButton( IconButton(
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down), icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down,
semanticLabel: _sort.reverse ? "Sort descending".i18n : "Sort ascending".i18n,),
onPressed: () => _reverse(), onPressed: () => _reverse(),
), ),
Container(width: 4.0) Container(width: 4.0)
@ -1230,7 +1235,7 @@ class _ShowScreenState extends State<ShowScreen> {
return ShowEpisodeTile( return ShowEpisodeTile(
e, e,
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.more_vert), icon: Icon(Icons.more_vert, semanticLabel: "Options".i18n,),
onPressed: () { onPressed: () {
MenuSheet m = MenuSheet(context); MenuSheet m = MenuSheet(context);
m.defaultShowEpisodeMenu(_show, e); m.defaultShowEpisodeMenu(_show, e);

View File

@ -74,7 +74,7 @@ class _DownloadsScreenState extends State<DownloadsScreen> {
'Downloads'.i18n, 'Downloads'.i18n,
actions: [ actions: [
IconButton( IconButton(
icon: Icon(Icons.delete_sweep), icon: Icon(Icons.delete_sweep, semanticLabel: "Clear all".i18n,),
onPressed: () async { onPressed: () async {
await downloadManager.removeDownloads(DownloadState.ERROR); await downloadManager.removeDownloads(DownloadState.ERROR);
await downloadManager.removeDownloads(DownloadState.DEEZER_ERROR); await downloadManager.removeDownloads(DownloadState.DEEZER_ERROR);
@ -84,7 +84,8 @@ class _DownloadsScreenState extends State<DownloadsScreen> {
), ),
IconButton( IconButton(
icon: icon:
Icon(downloadManager.running ? Icons.stop : Icons.play_arrow), Icon(downloadManager.running ? Icons.stop : Icons.play_arrow,
semanticLabel: downloadManager.running ? "Stop".i18n : "Start".i18n,),
onPressed: () { onPressed: () {
setState(() { setState(() {
if (downloadManager.running) if (downloadManager.running)

View File

@ -1,11 +1,36 @@
import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:freezer/translations.i18n.dart'; import 'package:freezer/translations.i18n.dart';
class ErrorScreen extends StatelessWidget { int counter = 0;
class ErrorScreen extends StatefulWidget {
final String message; final String message;
const ErrorScreen({this.message, Key key}) : super(key: key);
ErrorScreen({this.message}); @override
_ErrorScreenState createState() => _ErrorScreenState();
}
class _ErrorScreenState extends State<ErrorScreen> {
bool checkArl = false;
@override
void initState() {
Connectivity().checkConnectivity().then((connectivity) {
if (connectivity != ConnectivityResult.none && counter > 3) {
setState(() {
checkArl = true;
});
}
});
counter += 1;
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -19,7 +44,18 @@ class ErrorScreen extends StatelessWidget {
size: 64.0, size: 64.0,
), ),
Container(height: 4.0,), Container(height: 4.0,),
Text(message ?? 'Please check your connection and try again later...'.i18n) Text(widget.message ?? 'Please check your connection and try again later...'.i18n),
if (checkArl)
Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 32.0),
child: Text(
"Your ARL might be expired, try logging out and logging back in using new ARL or browser.".i18n,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12.0,
),
),
)
], ],
), ),
); );

View File

@ -98,7 +98,7 @@ class _SpotifyImporterV1State extends State<SpotifyImporterV1> {
), ),
), ),
IconButton( IconButton(
icon: Icon(Icons.search), icon: Icon(Icons.search, semanticLabel: "Search".i18n,),
onPressed: () => _load(), onPressed: () => _load(),
) )
], ],

View File

@ -33,7 +33,7 @@ class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget {
'Library'.i18n, 'Library'.i18n,
actions: <Widget>[ actions: <Widget>[
IconButton( IconButton(
icon: Icon(Icons.file_download), icon: Icon(Icons.file_download, semanticLabel: "Download".i18n,),
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute(builder: (context) => DownloadsScreen()) MaterialPageRoute(builder: (context) => DownloadsScreen())
@ -41,7 +41,7 @@ class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget {
}, },
), ),
IconButton( IconButton(
icon: Icon(Icons.settings), icon: Icon(Icons.settings, semanticLabel: "Settings".i18n,),
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SettingsScreen()) MaterialPageRoute(builder: (context) => SettingsScreen())
@ -420,13 +420,14 @@ class _LibraryTracksState extends State<LibraryTracks> {
'Tracks'.i18n, 'Tracks'.i18n,
actions: [ actions: [
IconButton( IconButton(
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down), icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down,
semanticLabel: _sort.reverse ? "Sort descending".i18n : "Sort ascending".i18n,),
onPressed: () async { onPressed: () async {
await _reverse(); await _reverse();
} }
), ),
PopupMenuButton( PopupMenuButton(
child: Icon(Icons.sort, size: 32.0), child: Icon(Icons.sort, size: 32.0, semanticLabel: "Sort".i18n,),
color: Theme.of(context).scaffoldBackgroundColor, color: Theme.of(context).scaffoldBackgroundColor,
onSelected: (SortType s) async { onSelected: (SortType s) async {
//Preload for sorting //Preload for sorting
@ -631,7 +632,8 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
'Albums'.i18n, 'Albums'.i18n,
actions: [ actions: [
IconButton( IconButton(
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down), icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down,
semanticLabel: _sort.reverse ? "Sort descending".i18n : "Sort ascending".i18n,),
onPressed: () => _reverse(), onPressed: () => _reverse(),
), ),
PopupMenuButton( PopupMenuButton(
@ -834,7 +836,8 @@ class _LibraryArtistsState extends State<LibraryArtists> {
'Artists'.i18n, 'Artists'.i18n,
actions: [ actions: [
IconButton( IconButton(
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down), icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down,
semanticLabel: _sort.reverse ? "Sort descending".i18n : "Sort ascending".i18n,),
onPressed: () => _reverse(), onPressed: () => _reverse(),
), ),
PopupMenuButton( PopupMenuButton(
@ -995,7 +998,8 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
'Playlists'.i18n, 'Playlists'.i18n,
actions: [ actions: [
IconButton( IconButton(
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down), icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down,
semanticLabel: _sort.reverse ? "Sort descending".i18n : "Sort ascending".i18n,),
onPressed: () => _reverse(), onPressed: () => _reverse(),
), ),
PopupMenuButton( PopupMenuButton(
@ -1178,7 +1182,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
'History'.i18n, 'History'.i18n,
actions: [ actions: [
IconButton( IconButton(
icon: Icon(Icons.delete_sweep), icon: Icon(Icons.delete_sweep, semanticLabel: "Clear all".i18n,),
onPressed: () { onPressed: () {
setState(() => cache.history = []); setState(() => cache.history = []);
cache.save(); cache.save();

View File

@ -67,11 +67,15 @@ class MenuSheet {
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[ children: <Widget>[
CachedImage( Semantics(
child: CachedImage(
url: track.albumArt.full, url: track.albumArt.full,
height: 128, height: 128,
width: 128, width: 128,
), ),
label: "Album art".i18n,
image: true,
),
Container( Container(
width: 240.0, width: 240.0,
child: Column( child: Column(

View File

@ -2,6 +2,7 @@ import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:freezer/settings.dart'; import 'package:freezer/settings.dart';
import 'package:freezer/translations.i18n.dart';
import '../api/player.dart'; import '../api/player.dart';
import 'cached_image.dart'; import 'cached_image.dart';
@ -122,13 +123,13 @@ class PrevNextButton extends StatelessWidget {
if (!prev) { if (!prev) {
if (playerHelper.queueIndex == (AudioService.queue??[]).length - 1) { if (playerHelper.queueIndex == (AudioService.queue??[]).length - 1) {
return IconButton( return IconButton(
icon: Icon(Icons.skip_next), icon: Icon(Icons.skip_next, semanticLabel: "Play next".i18n,),
iconSize: size, iconSize: size,
onPressed: null, onPressed: null,
); );
} }
return IconButton( return IconButton(
icon: Icon(Icons.skip_next), icon: Icon(Icons.skip_next, semanticLabel: "Play next".i18n,),
iconSize: size, iconSize: size,
onPressed: () => AudioService.skipToNext(), onPressed: () => AudioService.skipToNext(),
); );
@ -139,13 +140,13 @@ class PrevNextButton extends StatelessWidget {
return Container(height: 0, width: 0,); return Container(height: 0, width: 0,);
} }
return IconButton( return IconButton(
icon: Icon(Icons.skip_previous), icon: Icon(Icons.skip_previous, semanticLabel: "Play previous".i18n,),
iconSize: size, iconSize: size,
onPressed: null, onPressed: null,
); );
} }
return IconButton( return IconButton(
icon: Icon(Icons.skip_previous), icon: Icon(Icons.skip_previous, semanticLabel: "Play previous".i18n,),
iconSize: size, iconSize: size,
onPressed: () => AudioService.skipToPrevious(), onPressed: () => AudioService.skipToPrevious(),
); );
@ -203,6 +204,7 @@ class _PlayPauseButtonState extends State<PlayPauseButton> with SingleTickerProv
icon: AnimatedIcon( icon: AnimatedIcon(
icon: AnimatedIcons.play_pause, icon: AnimatedIcons.play_pause,
progress: _animation, progress: _animation,
semanticLabel: _playing ? "Pause".i18n : "Play".i18n,
), ),
iconSize: widget.size, iconSize: widget.size,
onPressed: _playing onPressed: _playing

View File

@ -263,7 +263,8 @@ class _PlayerScreenHorizontalState extends State<PlayerScreenHorizontal> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
IconButton( IconButton(
icon: Icon(Icons.subtitles, size: ScreenUtil().setWidth(32)), icon: Icon(Icons.subtitles, size: ScreenUtil().setWidth(32),
semanticLabel: "Lyrics".i18n,),
onPressed: () { onPressed: () {
Navigator.of(context).push(MaterialPageRoute( Navigator.of(context).push(MaterialPageRoute(
builder: (context) => LyricsScreen(trackId: AudioService.currentMediaItem.id) builder: (context) => LyricsScreen(trackId: AudioService.currentMediaItem.id)
@ -365,7 +366,8 @@ class _PlayerScreenVerticalState extends State<PlayerScreenVertical> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
IconButton( IconButton(
icon: Icon(Icons.subtitles, size: ScreenUtil().setWidth(46)), icon: Icon(Icons.subtitles, size: ScreenUtil().setWidth(46),
semanticLabel: "Lyrics".i18n,),
onPressed: () async { onPressed: () async {
//Fix bottom buttons //Fix bottom buttons
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
@ -381,7 +383,7 @@ class _PlayerScreenVerticalState extends State<PlayerScreenVertical> {
}, },
), ),
IconButton( IconButton(
icon: Icon(Icons.file_download), icon: Icon(Icons.file_download, semanticLabel: "Download".i18n,),
onPressed: () async { onPressed: () async {
Track t = Track.fromMediaItem(AudioService.currentMediaItem); Track t = Track.fromMediaItem(AudioService.currentMediaItem);
if (await downloadManager.addOfflineTrack(t, private: false, context: context, isSingleton: true) != false) if (await downloadManager.addOfflineTrack(t, private: false, context: context, isSingleton: true) != false)
@ -466,7 +468,8 @@ class PlayerMenuButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return IconButton( return IconButton(
icon: Icon(Icons.more_vert, size: ScreenUtil().setWidth(46)), icon: Icon(Icons.more_vert, size: ScreenUtil().setWidth(46),
semanticLabel: "Options".i18n,),
onPressed: () { onPressed: () {
Track t = Track.fromMediaItem(AudioService.currentMediaItem); Track t = Track.fromMediaItem(AudioService.currentMediaItem);
MenuSheet m = MenuSheet(context, navigateCallback: () { MenuSheet m = MenuSheet(context, navigateCallback: () {
@ -502,19 +505,22 @@ class _RepeatButtonState extends State<RepeatButton> {
case LoopMode.off: case LoopMode.off:
return Icon( return Icon(
Icons.repeat, Icons.repeat,
size: widget.iconSize size: widget.iconSize,
semanticLabel: "Repeat off".i18n,
); );
case LoopMode.all: case LoopMode.all:
return Icon( return Icon(
Icons.repeat, Icons.repeat,
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
size: widget.iconSize size: widget.iconSize,
semanticLabel: "Repeat".i18n,
); );
case LoopMode.one: case LoopMode.one:
return Icon( return Icon(
Icons.repeat_one, Icons.repeat_one,
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
size: widget.iconSize size: widget.iconSize,
semanticLabel: "Repeat one".i18n,
); );
} }
} }
@ -546,9 +552,9 @@ class _PlaybackControlsState extends State<PlaybackControls> {
Icon get libraryIcon { Icon get libraryIcon {
if (cache.checkTrackFavorite(Track.fromMediaItem(AudioService.currentMediaItem))) { if (cache.checkTrackFavorite(Track.fromMediaItem(AudioService.currentMediaItem))) {
return Icon(Icons.favorite, size: widget.iconSize * 0.64); return Icon(Icons.favorite, size: widget.iconSize * 0.64, semanticLabel: "Unlove".i18n,);
} }
return Icon(Icons.favorite_border, size: widget.iconSize * 0.64); return Icon(Icons.favorite_border, size: widget.iconSize * 0.64, semanticLabel: "Love".i18n,);
} }
@override @override
@ -560,7 +566,7 @@ class _PlaybackControlsState extends State<PlaybackControls> {
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
IconButton( IconButton(
icon: Icon(Icons.sentiment_very_dissatisfied, size: ScreenUtil().setWidth(46)), icon: Icon(Icons.sentiment_very_dissatisfied, size: ScreenUtil().setWidth(46), semanticLabel: "Dislike".i18n,),
onPressed: () async { onPressed: () async {
await deezerAPI.dislikeTrack(AudioService.currentMediaItem.id); await deezerAPI.dislikeTrack(AudioService.currentMediaItem.id);
if (playerHelper.queueIndex < (AudioService.queue??[]).length - 1) { if (playerHelper.queueIndex < (AudioService.queue??[]).length - 1) {
@ -678,7 +684,7 @@ class PlayerScreenTopRow extends StatelessWidget {
), ),
), ),
IconButton( IconButton(
icon: Icon(Icons.menu), icon: Icon(Icons.menu, semanticLabel: "Queue".i18n,),
iconSize: this.iconSize??ScreenUtil().setSp(52), iconSize: this.iconSize??ScreenUtil().setSp(52),
splashRadius: this.iconSize??ScreenUtil().setWidth(52), splashRadius: this.iconSize??ScreenUtil().setWidth(52),
onPressed: () async { onPressed: () async {
@ -823,6 +829,7 @@ class _QueueScreenState extends State<QueueScreen> {
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.shuffle, Icons.shuffle,
semanticLabel: "Shuffle".i18n,
), ),
onPressed: () async { onPressed: () async {
await playerHelper.toggleShuffle(); await playerHelper.toggleShuffle();
@ -848,7 +855,7 @@ class _QueueScreenState extends State<QueueScreen> {
}, },
key: Key(i.toString()), key: Key(i.toString()),
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.close), icon: Icon(Icons.close, semanticLabel: "Close".i18n,),
onPressed: () async { onPressed: () async {
await AudioService.removeQueueItem(t.toMediaItem()); await AudioService.removeQueueItem(t.toMediaItem());
setState(() {}); setState(() {});

View File

@ -111,7 +111,7 @@ class _SearchScreenState extends State<SearchScreen> {
Widget _removeHistoryItemWidget(int index) { Widget _removeHistoryItemWidget(int index) {
return IconButton( return IconButton(
icon: Icon(Icons.close), icon: Icon(Icons.close, semanticLabel: "Remove".i18n,),
onPressed: () async { onPressed: () async {
if (cache.searchHistory != null) if (cache.searchHistory != null)
cache.searchHistory.removeAt(index); cache.searchHistory.removeAt(index);
@ -188,7 +188,7 @@ class _SearchScreenState extends State<SearchScreen> {
width: 40.0, width: 40.0,
child: IconButton( child: IconButton(
splashRadius: 20.0, splashRadius: 20.0,
icon: Icon(Icons.clear), icon: Icon(Icons.clear, semanticLabel: "Clear".i18n,),
onPressed: () { onPressed: () {
setState(() { setState(() {
_suggestions = []; _suggestions = [];
@ -311,7 +311,7 @@ class _SearchScreenState extends State<SearchScreen> {
data, data,
onTap: () { onTap: () {
List<Track> queue = cache.searchHistory.where((h) => h.type == SearchHistoryItemType.TRACK).map<Track>((t) => t.data).toList(); List<Track> queue = cache.searchHistory.where((h) => h.type == SearchHistoryItemType.TRACK).map<Track>((t) => t.data).toList();
playerHelper.playFromTrackList(queue, queue.first.id, QueueSource( playerHelper.playFromTrackList(queue, data.id, QueueSource(
text: 'Search history'.i18n, text: 'Search history'.i18n,
source: 'searchhistory', source: 'searchhistory',
id: 'searchhistory' id: 'searchhistory'
@ -723,7 +723,7 @@ class SearchResultsScreen extends StatelessWidget {
return ShowEpisodeTile( return ShowEpisodeTile(
e, e,
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.more_vert), icon: Icon(Icons.more_vert, semanticLabel: "Options".i18n,),
onPressed: () { onPressed: () {
MenuSheet m = MenuSheet(context); MenuSheet m = MenuSheet(context);
m.defaultShowEpisodeMenu(e.show, e); m.defaultShowEpisodeMenu(e.show, e);
@ -907,7 +907,7 @@ class EpisodeListScreen extends StatelessWidget {
return ShowEpisodeTile( return ShowEpisodeTile(
e, e,
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.more_vert), icon: Icon(Icons.more_vert, semanticLabel: "Options".i18n,),
onPressed: () { onPressed: () {
MenuSheet m = MenuSheet(context); MenuSheet m = MenuSheet(context);
m.defaultShowEpisodeMenu(e.show, e); m.defaultShowEpisodeMenu(e.show, e);

View File

@ -1226,8 +1226,8 @@ class _GeneralSettingsState extends State<GeneralSettings> {
if (settings.lastFMPassword != null && settings.lastFMUsername != null) { if (settings.lastFMPassword != null && settings.lastFMUsername != null) {
settings.lastFMUsername = null; settings.lastFMUsername = null;
settings.lastFMPassword = null; settings.lastFMPassword = null;
playerHelper.scrobblenaut = null;
await settings.save(); await settings.save();
await AudioService.customAction("disableLastFM");
setState(() {}); setState(() {});
Fluttertoast.showToast(msg: 'Logged out!'.i18n); Fluttertoast.showToast(msg: 'Logged out!'.i18n);
return; return;
@ -1352,7 +1352,7 @@ class _LastFMLoginState extends State<LastFMLogin> {
settings.lastFMUsername = last.username; settings.lastFMUsername = last.username;
settings.lastFMPassword = last.passwordHash; settings.lastFMPassword = last.passwordHash;
await settings.save(); await settings.save();
playerHelper.scrobblenaut = Scrobblenaut(lastFM: last); await playerHelper.authorizeLastFM();
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
), ),
@ -1396,7 +1396,7 @@ class _DirectoryPickerState extends State<DirectoryPicker> {
'Pick-a-Path'.i18n, 'Pick-a-Path'.i18n,
actions: <Widget>[ actions: <Widget>[
IconButton( IconButton(
icon: Icon(Icons.sd_card), icon: Icon(Icons.sd_card, semanticLabel: 'Select storage'.i18n,),
onPressed: () { onPressed: () {
String path = ''; String path = '';
//Chose storage //Chose storage

View File

@ -21,14 +21,14 @@ packages:
name: args name: args
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.1"
async: async:
dependency: "direct main" dependency: "direct main"
description: description:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.5.0" version: "2.6.1"
audio_service: audio_service:
dependency: "direct main" dependency: "direct main"
description: description:
@ -63,14 +63,14 @@ packages:
name: build_config name: build_config
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.5" version: "0.4.6"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.7" version: "2.1.10"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
@ -84,28 +84,28 @@ packages:
name: build_runner name: build_runner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.11.1" version: "1.11.5"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.7" version: "6.1.10"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
name: built_collection name: built_collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.3.2" version: "5.1.0"
built_value: built_value:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "7.1.0" version: "8.1.0"
cached_network_image: cached_network_image:
dependency: "direct main" dependency: "direct main"
description: description:
@ -140,14 +140,14 @@ packages:
name: cli_util name: cli_util
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0" version: "0.3.1"
clipboard: clipboard:
dependency: "direct main" dependency: "direct main"
description: description:
name: clipboard name: clipboard
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.2+8" version: "0.1.3"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -161,7 +161,7 @@ packages:
name: code_builder name: code_builder
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.6.0" version: "3.7.0"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
@ -310,14 +310,14 @@ packages:
name: ffi name: ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.3" version: "1.1.2"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.0" version: "6.1.2"
filesize: filesize:
dependency: "direct main" dependency: "direct main"
description: description:
@ -331,7 +331,7 @@ packages:
name: fixnum name: fixnum
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.10.11" version: "1.0.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -371,7 +371,7 @@ packages:
name: flutter_isolate name: flutter_isolate
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0+14" version: "1.0.0+15"
flutter_local_notifications: flutter_local_notifications:
dependency: "direct main" dependency: "direct main"
description: description:
@ -442,7 +442,7 @@ packages:
name: glob name: glob
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "2.0.1"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
@ -505,7 +505,7 @@ packages:
name: infinite_listview name: infinite_listview
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1+1" version: "1.1.0"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -519,7 +519,7 @@ packages:
name: io name: io
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.4" version: "0.3.5"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -568,14 +568,14 @@ packages:
name: logging name: logging
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.11.4" version: "1.0.1"
marquee: marquee:
dependency: "direct main" dependency: "direct main"
description: description:
name: marquee name: marquee
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.1" version: "1.7.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -603,21 +603,7 @@ packages:
name: move_to_background name: move_to_background
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.0.2"
node_interop:
dependency: transitive
description:
name: node_interop
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
numberpicker: numberpicker:
dependency: "direct main" dependency: "direct main"
description: description:
@ -645,7 +631,7 @@ packages:
name: open_file name: open_file
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.3" version: "3.2.1"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@ -715,7 +701,7 @@ packages:
name: pedantic name: pedantic
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.2" version: "1.11.1"
permission_handler: permission_handler:
dependency: "direct main" dependency: "direct main"
description: description:
@ -764,28 +750,28 @@ packages:
name: pool name: pool
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.0" version: "1.5.0"
process: process:
dependency: transitive dependency: transitive
description: description:
name: process name: process
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.1.0" version: "4.2.1"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.4" version: "2.0.0"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.7" version: "0.1.8"
quick_actions: quick_actions:
dependency: "direct main" dependency: "direct main"
description: description:
@ -820,7 +806,7 @@ packages:
name: scrobblenaut name: scrobblenaut
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.5"
share: share:
dependency: "direct main" dependency: "direct main"
description: description:
@ -841,7 +827,7 @@ packages:
name: shelf_web_socket name: shelf_web_socket
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.4" version: "0.2.4+1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -853,14 +839,14 @@ packages:
name: source_gen name: source_gen
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.10+1" version: "0.9.10+3"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.8.1"
spotify: spotify:
dependency: "direct main" dependency: "direct main"
description: description:
@ -881,14 +867,14 @@ packages:
name: sqflite name: sqflite
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.2+3" version: "1.3.2+4"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3+1" version: "1.0.3+3"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -909,7 +895,7 @@ packages:
name: stream_transform name: stream_transform
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "2.0.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@ -937,7 +923,7 @@ packages:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.19" version: "0.3.0"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@ -959,6 +945,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.0" version: "0.4.0"
universal_io:
dependency: transitive
description:
name: universal_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
url_launcher: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1021,7 +1014,7 @@ packages:
name: version name: version
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.3.1"
wakelock: wakelock:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1049,7 +1042,7 @@ packages:
name: watcher name: watcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.7+15" version: "1.0.0"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
@ -1077,7 +1070,14 @@ packages:
name: yaml name: yaml
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.1" version: "3.1.0"
zone_local:
dependency: transitive
description:
name: zone_local
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
sdks: sdks:
dart: ">=2.12.0 <3.0.0" dart: ">=2.12.0 <3.0.0"
flutter: ">=1.22.2" flutter: ">=1.22.2"

View File

@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.6.11+1 version: 0.6.12+1
environment: environment:
sdk: ">=2.8.0 <3.0.0" sdk: ">=2.8.0 <3.0.0"