0.6.12 - bug fixes
This commit is contained in:
parent
aa7f82b399
commit
972e84c136
|
@ -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)
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.",
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -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(),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(() {});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
104
pubspec.lock
104
pubspec.lock
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue