Merge pull request #58 from stonega/audio_service

Update to latest audio service
This commit is contained in:
stonegate 2021-10-06 18:50:52 +08:00 committed by GitHub
commit ee5a0660ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 569 additions and 602 deletions

View File

@ -42,6 +42,7 @@ android {
lintOptions {
disable 'InvalidPackage'
checkReleaseBuilds false
}
defaultConfig {

View File

@ -8,7 +8,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application android:name="io.flutter.app.FlutterApplication" android:label="Tsacdop" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:networkSecurityConfig="@xml/network_security_config">
<activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<activity android:name="com.ryanheise.audioservice.AudioServiceActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/LaunchTheme" />
<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/normal_background" />
<intent-filter>

View File

@ -6,7 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.2'
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

View File

@ -3,5 +3,5 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionSha256Sum=abc10bcedb58806e8654210f96031db541bcd2d6fc3161e81cb0572d6a15e821
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
#distributionSha256Sum=abc10bcedb58806e8654210f96031db541bcd2d6fc3161e81cb0572d6a15e821

View File

@ -457,18 +457,10 @@ class _PlaylistWidgetState extends State<PlaylistWidget> {
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(15.0)),
child: SizedBox(
height: 30.0,
width: 30.0,
child: Image(
image: episodes[index].avatarImage)
// Image.file(File(
// "${episodes[index].imagePath}"))
),
),
child: CircleAvatar(
radius: 15,
backgroundImage:
episodes[index].avatarImage),
),
Expanded(
child: Align(
@ -522,9 +514,9 @@ class _PlaylistWidgetState extends State<PlaylistWidget> {
borderRadius: BorderRadius.all(Radius.circular(15)),
onTap: () {
audio.playNext();
miniPlaylistKey.currentState.removeItem(
0, (context, animation) => Container());
miniPlaylistKey.currentState.insertItem(0);
// miniPlaylistKey.currentState.removeItem(
// 0, (context, animation) => Container());
// miniPlaylistKey.currentState.insertItem(0);
},
child: SizedBox(
height: 30,
@ -1336,13 +1328,7 @@ class _ControlPanelState extends State<ControlPanel>
AudioProcessingState
.buffering ||
data.audioState ==
AudioProcessingState
.connecting ||
data.audioState ==
AudioProcessingState.none ||
data.audioState ==
AudioProcessingState
.skippingToNext
AudioProcessingState.loading
? context.s.buffering
: '',
style: TextStyle(

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:line_icons/line_icons.dart';
import 'package:provider/provider.dart';
@ -197,16 +199,20 @@ class DiscoveryPageState extends State<DiscoveryPage> {
}
Future<List<OnlinePodcast>> _getTopPodcasts({int page}) async {
if(environment['apiKey'] == '') return [];
if (environment['apiKey'] == '') return [];
final searchEngine = ListenNotesSearch();
var searchResult = await searchEngine.fetchBestPodcast(
genre: '',
page: page,
);
final podcastTopList =
searchResult.podcasts.map((e) => e?.toOnlinePodcast).toList();
_podcastList.addAll(podcastTopList.cast());
return _podcastList;
try {
var searchResult = await searchEngine.fetchBestPodcast(
genre: '',
page: page,
);
final podcastTopList =
searchResult.podcasts.map((e) => e?.toOnlinePodcast).toList();
_podcastList.addAll(podcastTopList.cast());
return _podcastList;
} catch (e) {
return [];
}
}
Future<bool> _getHideDiscovery() async {
@ -404,7 +410,9 @@ class __TopPodcastListState extends State<_TopPodcastList> {
@override
void initState() {
_page = 1;
_searchFuture = _getTopPodcasts(genre: widget.genre, page: _page);
try {
_searchFuture = _getTopPodcasts(genre: widget.genre, page: _page);
} catch (e) {}
super.initState();
}

View File

@ -11,6 +11,7 @@ import 'package:flutter_html/flutter_html.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/util/cache_manager.dart';
import 'package:webfeed/webfeed.dart';
import '../.env.dart';
@ -251,6 +252,7 @@ class _RssResultState extends State<RssResult> {
CachedNetworkImage(
height: 120.0,
width: 120.0,
cacheManager: CustomCacheManager(),
fit: BoxFit.fitWidth,
alignment: Alignment.center,
imageUrl: _onlinePodcast.image,
@ -1356,6 +1358,7 @@ class PodcastAvatar extends StatelessWidget {
fit: BoxFit.fitWidth,
alignment: Alignment.center,
imageUrl: podcast.image,
cacheManager: CustomCacheManager(),
placeholderFadeInDuration: Duration.zero,
progressIndicatorBuilder: (context, url, downloadProgress) =>
Container(

View File

@ -75,8 +75,8 @@ class _PlaylistHomeState extends State<PlaylistHome> {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarIconBrightness:
Theme.of(context).accentColorBrightness,
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
Theme.of(context).colorScheme.brightness,
statusBarIconBrightness: Theme.of(context).colorScheme.brightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
),
child: WillPopScope(
@ -143,6 +143,9 @@ class _PlaylistHomeState extends State<PlaylistHome> {
playing
? audio.pauseAduio()
: audio.resumeAudio();
} else if (data.item1.isEmpty) {
Fluttertoast.showToast(
msg: 'Playlist is empty');
} else {
context
.read<AudioPlayerNotifier>()
@ -952,15 +955,14 @@ class __NewPlaylistState extends State<_NewPlaylist> {
}
Future<EpisodeBrief> _getEpisodeFromFile(String path) async {
var metadataRetriever = MetadataRetriever();
final fileLength = File(path).statSync().size;
final pubDate = DateTime.now().millisecondsSinceEpoch;
var primaryColor;
var imagePath;
await metadataRetriever.setFile(File(path));
if (metadataRetriever.albumArt != null) {
var metadata = await MetadataRetriever.fromFile(File(path));
if (metadata.albumArt != null) {
final dir = await getApplicationDocumentsDirectory();
final image = img.decodeImage(metadataRetriever.albumArt);
final image = img.decodeImage(metadata.albumArt);
final thumbnail = img.copyResize(image, width: 300);
var uuid = Uuid().v4();
File("${dir.path}/$uuid.png")..writeAsBytesSync(img.encodePng(thumbnail));
@ -968,7 +970,6 @@ class __NewPlaylistState extends State<_NewPlaylist> {
primaryColor = await _getColor(File(imagePath));
}
final fileName = path.split('/').last;
final metadata = await metadataRetriever.metadata;
return EpisodeBrief(
fileName,
'file://$path',

View File

@ -2,7 +2,6 @@ import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:file_picker/file_picker.dart';
import '../state/audio_state.dart';
import '../type/episodebrief.dart';

View File

@ -31,13 +31,15 @@ class Gpodder {
Future<void> _initDio() async {
final dir = await getApplicationDocumentsDirectory();
var cookieJar = PersistCookieJar(dir: "${dir.path}/.cookies/");
var cookieJar =
PersistCookieJar(storage: FileStorage("${dir.path}/.cookies/"));
_dio.interceptors.add(CookieManager(cookieJar));
}
Future<int> login({String username, String password}) async {
final dir = await getApplicationDocumentsDirectory();
var cookieJar = PersistCookieJar(dir: "${dir.path}/.cookies/");
var cookieJar =
PersistCookieJar(storage: FileStorage("${dir.path}/.cookies/"));
cookieJar.delete(Uri.parse(_baseUrl));
_dio.interceptors.add(CookieManager(cookieJar));
final basicAuth =
@ -81,7 +83,8 @@ class Gpodder {
Future<void> _initService() async {
final dir = await getApplicationDocumentsDirectory();
var cookieJar = PersistCookieJar(dir: "${dir.path}/.cookies/");
var cookieJar =
PersistCookieJar(storage: FileStorage("${dir.path}/.cookies/"));
cookieJar.delete(Uri.parse(_baseUrl));
await _storage.clearList();
await _addStorage.clearList();

View File

@ -441,7 +441,7 @@ class HistoryChart extends StatelessWidget {
titlesData: FlTitlesData(
show: true,
bottomTitles: SideTitles(
getTextStyles: (i) => TextStyle(
getTextStyles: (_, i) => TextStyle(
color: const Color(0xff67727d),
fontWeight: FontWeight.bold,
fontSize: 12,
@ -456,7 +456,7 @@ class HistoryChart extends StatelessWidget {
),
leftTitles: SideTitles(
showTitles: true,
getTextStyles: (s) => TextStyle(
getTextStyles: (_, s) => TextStyle(
color: const Color(0xff67727d),
fontWeight: FontWeight.bold,
fontSize: 12,

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@ import 'dart:ui';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
@ -18,43 +19,43 @@ import '../type/settings_backup.dart';
import 'download_state.dart';
void callbackDispatcher() {
Workmanager.executeTask((task, inputData) async {
var dbHelper = DBHelper();
var podcastList = await dbHelper.getPodcastLocalAll(updateOnly: true);
//lastWork is a indicator for if the app was opened since last backgroundwork
//if the app wes opend,then the old marked new episode would be marked not new.
var lastWorkStorage = KeyValueStorage(lastWorkKey);
var lastWork = await lastWorkStorage.getInt();
for (var podcastLocal in podcastList) {
await dbHelper.updatePodcastRss(podcastLocal, removeMark: lastWork);
developer.log('Refresh ${podcastLocal.title}');
}
await FlutterDownloader.initialize();
var downloader = AutoDownloader();
Workmanager.executeTask((task, inputData) async {
var dbHelper = DBHelper();
var podcastList = await dbHelper.getPodcastLocalAll(updateOnly: true);
//lastWork is a indicator for if the app was opened since last backgroundwork
//if the app wes opend,then the old marked new episode would be marked not new.
var lastWorkStorage = KeyValueStorage(lastWorkKey);
var lastWork = await lastWorkStorage.getInt();
for (var podcastLocal in podcastList) {
await dbHelper.updatePodcastRss(podcastLocal, removeMark: lastWork);
developer.log('Refresh ${podcastLocal.title}');
}
await FlutterDownloader.initialize();
var downloader = AutoDownloader();
var autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey);
var autoDownloadNetwork = await autoDownloadStorage.getInt();
var result = await Connectivity().checkConnectivity();
if (autoDownloadNetwork == 1) {
var episodes = await dbHelper.getNewEpisodes('all');
// For safety
if (episodes.length < 100 && episodes.length > 0) {
downloader.bindBackgroundIsolate();
await downloader.startTask(episodes);
}
} else if (result == ConnectivityResult.wifi) {
var episodes = await dbHelper.getNewEpisodes('all');
//For safety
if (episodes.length < 100 && episodes.length > 0) {
downloader.bindBackgroundIsolate();
await downloader.startTask(episodes);
}
var autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey);
var autoDownloadNetwork = await autoDownloadStorage.getInt();
var result = await Connectivity().checkConnectivity();
if (autoDownloadNetwork == 1) {
var episodes = await dbHelper.getNewEpisodes('all');
// For safety
if (episodes.length < 100 && episodes.length > 0) {
downloader.bindBackgroundIsolate();
await downloader.startTask(episodes);
}
await lastWorkStorage.saveInt(1);
var refreshstorage = KeyValueStorage(refreshdateKey);
await refreshstorage.saveInt(DateTime.now().millisecondsSinceEpoch);
return Future.value(true);
});
} else if (result == ConnectivityResult.wifi) {
var episodes = await dbHelper.getNewEpisodes('all');
//For safety
if (episodes.length < 100 && episodes.length > 0) {
downloader.bindBackgroundIsolate();
await downloader.startTask(episodes);
}
}
await lastWorkStorage.saveInt(1);
var refreshstorage = KeyValueStorage(refreshdateKey);
await refreshstorage.saveInt(DateTime.now().millisecondsSinceEpoch);
return Future.value(true);
});
}
final showNotesFontStyles = <TextStyle>[
@ -139,42 +140,51 @@ class SettingState extends ChangeNotifier {
ThemeMode get theme => _theme;
ThemeData get lightTheme => ThemeData(
accentColorBrightness: Brightness.dark,
primaryColor: Colors.grey[100],
primaryColorLight: Colors.white,
primaryColorDark: Colors.grey[300],
dialogBackgroundColor: Colors.white,
backgroundColor: Colors.grey[100],
appBarTheme: AppBarTheme(
color: Colors.grey[100],
elevation: 0,
),
textTheme: TextTheme(
bodyText2: TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal),
),
tabBarTheme: TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey[400],
),
accentColor: _accentSetColor,
cursorColor: _accentSetColor,
textSelectionHandleColor: _accentSetColor,
toggleableActiveColor: _accentSetColor,
buttonTheme: ButtonThemeData(
colorScheme: ColorScheme.fromSwatch()
.copyWith(brightness: Brightness.light, secondary: _accentSetColor),
primaryColor: Colors.grey[100],
primaryColorLight: Colors.white,
primaryColorDark: Colors.grey[300],
dialogBackgroundColor: Colors.white,
backgroundColor: Colors.grey[100],
appBarTheme: AppBarTheme(
color: Colors.grey[100],
elevation: 0,
titleTextStyle: TextStyle(color: Colors.black),
iconTheme: IconThemeData(color: Colors.black),
systemOverlayStyle: SystemUiOverlayStyle.dark),
textTheme: TextTheme(
bodyText2: TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal),
),
tabBarTheme: TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey[400],
),
textSelectionTheme: TextSelectionThemeData(
cursorColor: _accentSetColor,
selectionHandleColor: _accentSetColor,
),
toggleableActiveColor: _accentSetColor,
buttonTheme: ButtonThemeData(
height: 32,
hoverColor: _accentSetColor.withAlpha(70),
splashColor: _accentSetColor.withAlpha(70)));
splashColor: _accentSetColor.withAlpha(70),
),
);
ThemeData get darkTheme => ThemeData.dark().copyWith(
accentColor: _accentSetColor,
primaryColorDark: Colors.grey[800],
scaffoldBackgroundColor: _realDark ? Colors.black87 : Color(0XFF212121),
primaryColor: _realDark ? Colors.black : Color(0XFF1B1B1B),
popupMenuTheme: PopupMenuThemeData()
.copyWith(color: _realDark ? Colors.grey[900] : null),
appBarTheme: AppBarTheme(elevation: 0),
buttonTheme: ButtonThemeData(height: 32),
dialogBackgroundColor: _realDark ? Colors.grey[900] : null,
cursorColor: _accentSetColor);
colorScheme: ColorScheme.fromSwatch()
.copyWith(brightness: Brightness.dark, secondary: _accentSetColor),
primaryColorDark: Colors.grey[800],
scaffoldBackgroundColor: _realDark ? Colors.black87 : Color(0XFF212121),
primaryColor: _realDark ? Colors.black : Color(0XFF1B1B1B),
popupMenuTheme: PopupMenuThemeData()
.copyWith(color: _realDark ? Colors.grey[900] : null),
appBarTheme: AppBarTheme(
elevation: 0, systemOverlayStyle: SystemUiOverlayStyle.light),
buttonTheme: ButtonThemeData(height: 32),
dialogBackgroundColor: _realDark ? Colors.grey[900] : null,
);
set setTheme(ThemeMode mode) {
_theme = mode;
@ -558,8 +568,10 @@ class SettingState extends ChangeNotifier {
.getBool(defaultValue: false);
final deleteAfterPlayed = await KeyValueStorage(deleteAfterPlayedKey)
.getBool(defaultValue: false);
final openPlaylistDefault = await _openPlaylistDefaultStorage.getBool(defaultValue: false);
final openAllPodcastDefault = await _openAllPodcastDefaultStorage.getBool(defaultValue: false);
final openPlaylistDefault =
await _openPlaylistDefaultStorage.getBool(defaultValue: false);
final openAllPodcastDefault =
await _openAllPodcastDefaultStorage.getBool(defaultValue: false);
return SettingsBackup(
theme: theme,

View File

@ -56,7 +56,7 @@ class EpisodeBrief extends Equatable {
artist: feedTitle,
album: feedTitle,
duration: Duration.zero,
artUri: imagePath == '' ? episodeImage : 'file://$imagePath',
artUri: Uri.parse(imagePath == '' ? episodeImage : 'file://$imagePath'),
extras: {
'skipSecondsStart': skipSecondsStart,
'skipSecondsEnd': skipSecondsEnd

View File

@ -0,0 +1,50 @@
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
/// The DefaultCacheManager that can be easily used directly. The code of
/// this implementation can be used as inspiration for more complex cache
/// managers.
class CustomCacheManager extends CacheManager with ImageCacheManager {
static const key = 'libCachedImageData';
static final CustomCacheManager _instance = CustomCacheManager._();
factory CustomCacheManager() {
return _instance;
}
@override
Future<FileInfo> downloadFile(String url,
{String key, Map<String, String> authHeaders, bool force = false}) async {
var file;
try {
file = await super
.downloadFile(url, key: key, authHeaders: authHeaders, force: force);
} catch (e) {
rethrow;
}
return file;
}
@override
Stream<FileResponse> getImageFile(
String url, {
String key,
Map<String, String> headers,
bool withProgress = false,
int maxHeight,
int maxWidth,
}) async* {
try {
super.getImageFile(url,
key: key,
headers: headers,
withProgress: withProgress,
maxHeight: maxHeight,
maxWidth: maxWidth);
} catch (e) {
}
}
CustomCacheManager._() : super(Config(key));
}

View File

@ -9,7 +9,7 @@ import '../generated/l10n.dart';
extension ContextExtension on BuildContext {
Color get primaryColor => Theme.of(this).primaryColor;
Color get accentColor => Theme.of(this).accentColor;
Color get accentColor => Theme.of(this).colorScheme.secondary;
Color get scaffoldBackgroundColor => Theme.of(this).scaffoldBackgroundColor;
Color get primaryColorDark => Theme.of(this).primaryColorDark;
Color get textColor => Theme.of(this).textTheme.bodyText1.color;

View File

@ -12,71 +12,67 @@ dependencies:
flutter_localizations:
sdk: flutter
auto_animated: ^3.0.0
audio_session: ^0.0.9
cached_network_image: ^2.5.1
audio_session: ^0.1.0
cached_network_image: ^3.1.0
color_thief_flutter: ^1.0.2
confetti: ^0.5.5
cupertino_icons: ^1.0.2
connectivity: ^3.0.2
crypto: ^3.0.0
device_info: ^2.0.0
dio: ^3.0.10
dio_cookie_manager: ^1.0.0
connectivity: ^3.0.3
crypto: ^3.0.1
device_info: ^2.0.2
dio_cookie_manager: ^2.0.0
dio: ^4.0.0
extended_nested_scroll_view: ^3.0.0
effective_dart: ^1.3.1
equatable: ^1.2.5
feature_discovery: ^0.13.0+2
file_picker: ^2.1.4
flutter_html: ^0.11.1
feature_discovery: ^0.14.0
file_picker: ^3.0.1
flutter_html: 0.11.1
fluttertoast: ^4.0.1
flutter_isolate: ^1.0.0+14
flutter_linkify: ^4.0.2
flutter_file_dialog: ^1.0.0
flare_flutter: ^2.0.6
fl_chart: ^0.12.2
line_icons: ^1.3.2
flutter_media_metadata: ^0.0.3+2
marquee: ^1.7.0
google_fonts: ^2.0.0
image: ^3.0.1
flutter_isolate: ^2.0.0
flutter_linkify: ^4.1.0
flutter_file_dialog: ^2.1.1
flare_flutter: ^3.0.2
fl_chart: ^0.36.4
line_icons: ^2.0.1
flutter_media_metadata: ^0.1.1
marquee: ^2.0.0
google_fonts: ^2.1.0
image: ^3.0.2
intl: ^0.17.0
json_serializable: ^3.5.1
json_annotation: ^3.1.1
permission_handler: ^5.0.1
provider: ^4.3.2
rxdart: ^0.24.1
sqflite: ^1.3.2+1
state_notifier: ^0.6.0
tuple: ^1.0.3
url_launcher: ^5.7.10
json_serializable: ^4.1.0
json_annotation: ^4.0.1
permission_handler: ^6.1.1
provider: ^5.0.0
sqflite: ^2.0.0+3
state_notifier: ^0.7.0
tuple: ^2.0.0
url_launcher: ^6.0.3
uuid: ^3.0.4
workmanager: ^0.2.3
wc_flutter_share: ^0.2.2
wc_flutter_share: ^0.4.0
xml: ^5.2.0
audio_service: 0.18.0
just_audio:
git:
url: https://github.com/stonega/just_audio_origin.git
ref: update
path: just_audio
flutter_downloader:
git:
url: https://github.com/stonega/flutter_downloader.git
audio_service:
git:
url: https://github.com/stonega/audio_service.git
just_audio:
git:
url: https://github.com/stonega/just_audio.git
focused_menu:
git:
url: https://github.com/stonega/focused_menu.git
webfeed:
git:
url: https://github.com/stonega/webfeed.git
dependency_overrides:
equatable: ^2.0.0
path_provider: ^2.0.1
http_parser: ^4.0.0
cookie_jar: ^2.0.0
uuid: ^3.0.1
http: ^0.13.0
flutter_cache_manager: ^2.1.2
dependency_overrides:
meta: 1.3.0
shared_preferences: 2.0.0
convert: ^3.0.0
xml: ^5.0.2
linkify:
git:
url: https://github.com/stonega/linkify.git