Update podcast setting menu, add skip seconds at end.
This commit is contained in:
parent
fb31758f50
commit
b271965009
|
@ -308,6 +308,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"share" : MessageLookupByLibrary.simpleMessage("Share"),
|
"share" : MessageLookupByLibrary.simpleMessage("Share"),
|
||||||
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("Show notes font"),
|
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("Show notes font"),
|
||||||
"size" : MessageLookupByLibrary.simpleMessage("Size"),
|
"size" : MessageLookupByLibrary.simpleMessage("Size"),
|
||||||
|
"skipSecondsAtEnd" : MessageLookupByLibrary.simpleMessage("Skip seconds at end"),
|
||||||
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Skip seconds at start"),
|
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Skip seconds at start"),
|
||||||
"skipSilence" : MessageLookupByLibrary.simpleMessage("Skip silence"),
|
"skipSilence" : MessageLookupByLibrary.simpleMessage("Skip silence"),
|
||||||
"skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"),
|
"skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"),
|
||||||
|
|
|
@ -308,6 +308,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"share" : MessageLookupByLibrary.simpleMessage("Compartir"),
|
"share" : MessageLookupByLibrary.simpleMessage("Compartir"),
|
||||||
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("Show notes font"),
|
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("Show notes font"),
|
||||||
"size" : MessageLookupByLibrary.simpleMessage("Tamaño"),
|
"size" : MessageLookupByLibrary.simpleMessage("Tamaño"),
|
||||||
|
"skipSecondsAtEnd" : MessageLookupByLibrary.simpleMessage("Skip seconds at end"),
|
||||||
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Saltar segundos al inicio"),
|
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Saltar segundos al inicio"),
|
||||||
"skipSilence" : MessageLookupByLibrary.simpleMessage("Saltar silencios"),
|
"skipSilence" : MessageLookupByLibrary.simpleMessage("Saltar silencios"),
|
||||||
"skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"),
|
"skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"),
|
||||||
|
|
|
@ -308,6 +308,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"share" : MessageLookupByLibrary.simpleMessage("Partager"),
|
"share" : MessageLookupByLibrary.simpleMessage("Partager"),
|
||||||
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("Show notes font"),
|
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("Show notes font"),
|
||||||
"size" : MessageLookupByLibrary.simpleMessage("Taille"),
|
"size" : MessageLookupByLibrary.simpleMessage("Taille"),
|
||||||
|
"skipSecondsAtEnd" : MessageLookupByLibrary.simpleMessage("Skip seconds at end"),
|
||||||
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Passer les premières secondes du début"),
|
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Passer les premières secondes du début"),
|
||||||
"skipSilence" : MessageLookupByLibrary.simpleMessage("Skip silence"),
|
"skipSilence" : MessageLookupByLibrary.simpleMessage("Skip silence"),
|
||||||
"skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"),
|
"skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"),
|
||||||
|
|
|
@ -308,6 +308,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"share" : MessageLookupByLibrary.simpleMessage("分享"),
|
"share" : MessageLookupByLibrary.simpleMessage("分享"),
|
||||||
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("节目简介字体"),
|
"showNotesFonts" : MessageLookupByLibrary.simpleMessage("节目简介字体"),
|
||||||
"size" : MessageLookupByLibrary.simpleMessage("大小"),
|
"size" : MessageLookupByLibrary.simpleMessage("大小"),
|
||||||
|
"skipSecondsAtEnd" : MessageLookupByLibrary.simpleMessage("结束跳过秒数"),
|
||||||
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("开头跳过秒数"),
|
"skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("开头跳过秒数"),
|
||||||
"skipSilence" : MessageLookupByLibrary.simpleMessage("跳过无声"),
|
"skipSilence" : MessageLookupByLibrary.simpleMessage("跳过无声"),
|
||||||
"skipToNext" : MessageLookupByLibrary.simpleMessage("下一首"),
|
"skipToNext" : MessageLookupByLibrary.simpleMessage("下一首"),
|
||||||
|
|
|
@ -2362,6 +2362,16 @@ class S {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Skip seconds at end`
|
||||||
|
String get skipSecondsAtEnd {
|
||||||
|
return Intl.message(
|
||||||
|
'Skip seconds at end',
|
||||||
|
name: 'skipSecondsAtEnd',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// `Skip seconds at start`
|
/// `Skip seconds at start`
|
||||||
String get skipSecondsAtStart {
|
String get skipSecondsAtStart {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
|
|
|
@ -535,6 +535,8 @@
|
||||||
"@showNotesFonts": {},
|
"@showNotesFonts": {},
|
||||||
"size": "Size",
|
"size": "Size",
|
||||||
"@size": {},
|
"@size": {},
|
||||||
|
"skipSecondsAtEnd": "Skip seconds at end",
|
||||||
|
"@skipSecondsAtEnd": {},
|
||||||
"skipSecondsAtStart": "Skip seconds at start",
|
"skipSecondsAtStart": "Skip seconds at start",
|
||||||
"@skipSecondsAtStart": {},
|
"@skipSecondsAtStart": {},
|
||||||
"skipSilence": "Skip silence",
|
"skipSilence": "Skip silence",
|
||||||
|
|
|
@ -535,6 +535,8 @@
|
||||||
"@showNotesFonts": {},
|
"@showNotesFonts": {},
|
||||||
"size": "Tamaño",
|
"size": "Tamaño",
|
||||||
"@size": {},
|
"@size": {},
|
||||||
|
"skipSecondsAtEnd": "Skip seconds at end",
|
||||||
|
"@skipSecondsAtEnd": {},
|
||||||
"skipSecondsAtStart": "Saltar segundos al inicio",
|
"skipSecondsAtStart": "Saltar segundos al inicio",
|
||||||
"@skipSecondsAtStart": {},
|
"@skipSecondsAtStart": {},
|
||||||
"skipSilence": "Saltar silencios",
|
"skipSilence": "Saltar silencios",
|
||||||
|
|
|
@ -535,6 +535,8 @@
|
||||||
"@showNotesFonts": {},
|
"@showNotesFonts": {},
|
||||||
"size": "Taille",
|
"size": "Taille",
|
||||||
"@size": {},
|
"@size": {},
|
||||||
|
"skipSecondsAtEnd": "Skip seconds at end",
|
||||||
|
"@skipSecondsAtEnd": {},
|
||||||
"skipSecondsAtStart": "Passer les premières secondes du début",
|
"skipSecondsAtStart": "Passer les premières secondes du début",
|
||||||
"@skipSecondsAtStart": {},
|
"@skipSecondsAtStart": {},
|
||||||
"skipSilence": "Skip silence",
|
"skipSilence": "Skip silence",
|
||||||
|
|
|
@ -535,6 +535,8 @@
|
||||||
"@showNotesFonts": {},
|
"@showNotesFonts": {},
|
||||||
"size": "大小",
|
"size": "大小",
|
||||||
"@size": {},
|
"@size": {},
|
||||||
|
"skipSecondsAtEnd": "结束跳过秒数",
|
||||||
|
"@skipSecondsAtEnd": {},
|
||||||
"skipSecondsAtStart": "开头跳过秒数",
|
"skipSecondsAtStart": "开头跳过秒数",
|
||||||
"@skipSecondsAtStart": {},
|
"@skipSecondsAtStart": {},
|
||||||
"skipSilence": "跳过无声",
|
"skipSilence": "跳过无声",
|
||||||
|
|
|
@ -27,7 +27,7 @@ class DBHelper {
|
||||||
var documentsDirectory = await getDatabasesPath();
|
var documentsDirectory = await getDatabasesPath();
|
||||||
var path = join(documentsDirectory, "podcasts.db");
|
var path = join(documentsDirectory, "podcasts.db");
|
||||||
var theDb = await openDatabase(path,
|
var theDb = await openDatabase(path,
|
||||||
version: 3, onCreate: _onCreate, onUpgrade: _onUpgrade);
|
version: 4, onCreate: _onCreate, onUpgrade: _onUpgrade);
|
||||||
return theDb;
|
return theDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +37,15 @@ class DBHelper {
|
||||||
imageUrl TEXT,rssUrl TEXT UNIQUE, primaryColor TEXT, author TEXT,
|
imageUrl TEXT,rssUrl TEXT UNIQUE, primaryColor TEXT, author TEXT,
|
||||||
description TEXT, add_date INTEGER, imagePath TEXT, provider TEXT, link TEXT,
|
description TEXT, add_date INTEGER, imagePath TEXT, provider TEXT, link TEXT,
|
||||||
background_image TEXT DEFAULT '', hosts TEXT DEFAULT '',update_count INTEGER DEFAULT 0,
|
background_image TEXT DEFAULT '', hosts TEXT DEFAULT '',update_count INTEGER DEFAULT 0,
|
||||||
episode_count INTEGER DEFAULT 0, skip_seconds INTEGER DEFAULT 0, auto_download INTEGER DEFAULT 0)""");
|
episode_count INTEGER DEFAULT 0, skip_seconds INTEGER DEFAULT 0,
|
||||||
|
auto_download INTEGER DEFAULT 0, skip_seconds_end INTEGER DEFAULT 0)""");
|
||||||
await db
|
await db
|
||||||
.execute("""CREATE TABLE Episodes(id INTEGER PRIMARY KEY,title TEXT,
|
.execute("""CREATE TABLE Episodes(id INTEGER PRIMARY KEY,title TEXT,
|
||||||
enclosure_url TEXT UNIQUE, enclosure_length INTEGER, pubDate TEXT,
|
enclosure_url TEXT UNIQUE, enclosure_length INTEGER, pubDate TEXT,
|
||||||
description TEXT, feed_id TEXT, feed_link TEXT, milliseconds INTEGER,
|
description TEXT, feed_id TEXT, feed_link TEXT, milliseconds INTEGER,
|
||||||
duration INTEGER DEFAULT 0, explicit INTEGER DEFAULT 0, liked INTEGER DEFAULT 0,
|
duration INTEGER DEFAULT 0, explicit INTEGER DEFAULT 0, liked INTEGER DEFAULT 0,
|
||||||
liked_date INTEGER DEFAULT 0, downloaded TEXT DEFAULT 'ND', download_date INTEGER DEFAULT 0, media_id TEXT,
|
liked_date INTEGER DEFAULT 0, downloaded TEXT DEFAULT 'ND',
|
||||||
is_new INTEGER DEFAULT 0)""");
|
download_date INTEGER DEFAULT 0, media_id TEXT, is_new INTEGER DEFAULT 0)""");
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""CREATE TABLE PlayHistory(id INTEGER PRIMARY KEY, title TEXT, enclosure_url TEXT,
|
"""CREATE TABLE PlayHistory(id INTEGER PRIMARY KEY, title TEXT, enclosure_url TEXT,
|
||||||
seconds REAL, seek_value REAL, add_date INTEGER, listen_time INTEGER DEFAULT 0)""");
|
seconds REAL, seek_value REAL, add_date INTEGER, listen_time INTEGER DEFAULT 0)""");
|
||||||
|
@ -59,9 +60,16 @@ class DBHelper {
|
||||||
"ALTER TABLE PodcastLocal ADD skip_seconds INTEGER DEFAULT 0 ");
|
"ALTER TABLE PodcastLocal ADD skip_seconds INTEGER DEFAULT 0 ");
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
||||||
} else if (oldVersion == 2) {
|
} else if (oldVersion == 2) {
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
"ALTER TABLE PodcastLocal ADD auto_download INTEGER DEFAULT 0");
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
||||||
|
} else if (oldVersion == 3) {
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE PodcastLocal ADD skip_seconds_end INTEGER DEFAULT 0 ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,19 +138,33 @@ class DBHelper {
|
||||||
return list.first['count'];
|
return list.first['count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> getSkipSeconds(String id) async {
|
Future<int> getSkipSecondsStart(String id) async {
|
||||||
var dbClient = await database;
|
var dbClient = await database;
|
||||||
List<Map> list = await dbClient
|
List<Map> list = await dbClient
|
||||||
.rawQuery('SELECT skip_seconds FROM PodcastLocal WHERE id = ?', [id]);
|
.rawQuery('SELECT skip_seconds FROM PodcastLocal WHERE id = ?', [id]);
|
||||||
return list.first['skip_seconds'];
|
return list.first['skip_seconds'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> saveSkipSeconds(String id, int seconds) async {
|
Future<int> saveSkipSecondsStart(String id, int seconds) async {
|
||||||
var dbClient = await database;
|
var dbClient = await database;
|
||||||
return await dbClient.rawUpdate(
|
return await dbClient.rawUpdate(
|
||||||
"UPDATE PodcastLocal SET skip_seconds = ? WHERE id = ?", [seconds, id]);
|
"UPDATE PodcastLocal SET skip_seconds = ? WHERE id = ?", [seconds, id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> getSkipSecondsEnd(String id) async {
|
||||||
|
var dbClient = await database;
|
||||||
|
List<Map> list = await dbClient.rawQuery(
|
||||||
|
'SELECT skip_seconds_end FROM PodcastLocal WHERE id = ?', [id]);
|
||||||
|
return list.first['skip_seconds_end'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> saveSkipSecondsEnd(String id, int seconds) async {
|
||||||
|
var dbClient = await database;
|
||||||
|
return await dbClient.rawUpdate(
|
||||||
|
"UPDATE PodcastLocal SET skip_seconds_end = ? WHERE id = ?",
|
||||||
|
[seconds, id]);
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> getAutoDownload(String id) async {
|
Future<bool> getAutoDownload(String id) async {
|
||||||
var dbClient = await database;
|
var dbClient = await database;
|
||||||
List<Map> list = await dbClient
|
List<Map> list = await dbClient
|
||||||
|
@ -1336,8 +1358,8 @@ class DBHelper {
|
||||||
EpisodeBrief episode;
|
EpisodeBrief episode;
|
||||||
List<Map> list = await dbClient.rawQuery(
|
List<Map> list = await dbClient.rawQuery(
|
||||||
"""SELECT E.title, E.enclosure_url, E.enclosure_length, E.milliseconds, P.imagePath,
|
"""SELECT E.title, E.enclosure_url, E.enclosure_length, E.milliseconds, P.imagePath,
|
||||||
P.title as feed_title, E.duration, E.explicit, P.skip_seconds,E.is_new,
|
P.title as feed_title, E.duration, E.explicit, P.skip_seconds, P.skip_seconds_end,
|
||||||
P.primaryColor, E.media_id FROM Episodes E INNER JOIN PodcastLocal P ON E.feed_id = P.id
|
E.is_new, P.primaryColor, E.media_id FROM Episodes E INNER JOIN PodcastLocal P ON E.feed_id = P.id
|
||||||
WHERE E.enclosure_url = ?""", [url]);
|
WHERE E.enclosure_url = ?""", [url]);
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1354,7 +1376,8 @@ class DBHelper {
|
||||||
list.first['imagePath'],
|
list.first['imagePath'],
|
||||||
list.first['is_new'],
|
list.first['is_new'],
|
||||||
mediaId: list.first['media_id'],
|
mediaId: list.first['media_id'],
|
||||||
skipSeconds: list.first['skip_seconds']);
|
skipSecondsStart: list.first['skip_seconds'],
|
||||||
|
skipSecondsEnd: list.first['skip_seconds_end']);
|
||||||
return episode;
|
return episode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1364,9 +1387,9 @@ class DBHelper {
|
||||||
EpisodeBrief episode;
|
EpisodeBrief episode;
|
||||||
List<Map> list = await dbClient.rawQuery(
|
List<Map> list = await dbClient.rawQuery(
|
||||||
"""SELECT E.title, E.enclosure_url, E.enclosure_length, E.milliseconds, P.imagePath,
|
"""SELECT E.title, E.enclosure_url, E.enclosure_length, E.milliseconds, P.imagePath,
|
||||||
P.title as feed_title, E.duration, E.explicit, P.skip_seconds,E.is_new,
|
P.title as feed_title, E.duration, E.explicit, P.skip_seconds, P.skip_seconds_end,
|
||||||
P.primaryColor, E.media_id FROM Episodes E INNER JOIN PodcastLocal P ON E.feed_id = P.id
|
E.is_new, P.primaryColor, E.media_id FROM Episodes E INNER JOIN
|
||||||
WHERE E.media_id = ?""", [id]);
|
PodcastLocal P ON E.feed_id = P.id WHERE E.media_id = ?""", [id]);
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1382,7 +1405,8 @@ class DBHelper {
|
||||||
list.first['imagePath'],
|
list.first['imagePath'],
|
||||||
list.first['is_new'],
|
list.first['is_new'],
|
||||||
mediaId: list.first['media_id'],
|
mediaId: list.first['media_id'],
|
||||||
skipSeconds: list.first['skip_seconds']);
|
skipSecondsStart: list.first['skip_seconds'],
|
||||||
|
skipSecondsEnd: list.first['skip_seconds_end']);
|
||||||
return episode;
|
return episode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,7 +354,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
case 2:
|
case 2:
|
||||||
generalSheet(
|
generalSheet(
|
||||||
context,
|
context,
|
||||||
title: s.settings,
|
title: widget.podcastLocal.title,
|
||||||
child: PodcastSetting(podcastLocal: widget.podcastLocal),
|
child: PodcastSetting(podcastLocal: widget.podcastLocal),
|
||||||
).then((value) => setState(() {}));
|
).then((value) => setState(() {}));
|
||||||
break;
|
break;
|
||||||
|
@ -674,7 +674,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var _color = widget.podcastLocal.primaryColor.colorizedark();
|
final color = widget.podcastLocal.primaryColor.colorizedark();
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
|
@ -745,7 +745,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
expandedHeight: 150 + context.paddingTop,
|
expandedHeight: 150 + context.paddingTop,
|
||||||
backgroundColor: _color,
|
backgroundColor: color,
|
||||||
floating: true,
|
floating: true,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
flexibleSpace: LayoutBuilder(
|
flexibleSpace: LayoutBuilder(
|
||||||
|
|
|
@ -82,14 +82,14 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
|
|
||||||
Future<int> _getSkipSecond(String id) async {
|
Future<int> _getSkipSecond(String id) async {
|
||||||
var dbHelper = DBHelper();
|
var dbHelper = DBHelper();
|
||||||
var seconds = await dbHelper.getSkipSeconds(id);
|
var seconds = await dbHelper.getSkipSecondsStart(id);
|
||||||
_skipSeconds = seconds;
|
_skipSeconds = seconds;
|
||||||
return seconds;
|
return seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
_saveSkipSeconds(String id, int seconds) async {
|
_saveSkipSeconds(String id, int seconds) async {
|
||||||
var dbHelper = DBHelper();
|
var dbHelper = DBHelper();
|
||||||
await dbHelper.saveSkipSeconds(id, seconds);
|
await dbHelper.saveSkipSecondsStart(id, seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
_setAutoDownload(String id, bool boo) async {
|
_setAutoDownload(String id, bool boo) async {
|
||||||
|
@ -463,8 +463,7 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlatButton(
|
FlatButton(
|
||||||
splashColor:
|
splashColor: Colors.red.withAlpha(70),
|
||||||
context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
groupList.removePodcast(
|
groupList.removePodcast(
|
||||||
widget.podcastLocal.id);
|
widget.podcastLocal.id);
|
||||||
|
|
|
@ -3,12 +3,14 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:image/image.dart' as img;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:provider/provider.dart';
|
||||||
import 'package:webfeed/webfeed.dart';
|
import 'package:webfeed/webfeed.dart';
|
||||||
|
|
||||||
import '../local_storage/sqflite_localpodcast.dart';
|
import '../local_storage/sqflite_localpodcast.dart';
|
||||||
|
import '../state/podcast_group.dart';
|
||||||
import '../type/play_histroy.dart';
|
import '../type/play_histroy.dart';
|
||||||
import '../type/podcastlocal.dart';
|
import '../type/podcastlocal.dart';
|
||||||
import '../util/custom_widget.dart';
|
import '../util/custom_widget.dart';
|
||||||
|
@ -28,73 +30,74 @@ class PodcastSetting extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PodcastSettingState extends State<PodcastSetting> {
|
class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
|
final _dbHelper = DBHelper();
|
||||||
MarkStatus _markStatus = MarkStatus.none;
|
MarkStatus _markStatus = MarkStatus.none;
|
||||||
RefreshCoverStatus _coverStatus = RefreshCoverStatus.none;
|
RefreshCoverStatus _coverStatus = RefreshCoverStatus.none;
|
||||||
int _seconds = 0;
|
int _secondsStart;
|
||||||
|
int _secondsEnd;
|
||||||
|
bool _markConfirm;
|
||||||
|
bool _removeConfirm;
|
||||||
|
bool _showStartTimePicker;
|
||||||
|
bool _showEndTimePicker;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_secondsStart = 0;
|
||||||
|
_secondsEnd = 0;
|
||||||
|
_markConfirm = false;
|
||||||
|
_removeConfirm = false;
|
||||||
|
_showStartTimePicker = false;
|
||||||
|
_showEndTimePicker = false;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _setAutoDownload(bool boo) async {
|
Future<void> _setAutoDownload(bool boo) async {
|
||||||
var permission = await _checkPermmison();
|
var permission = await _checkPermmison();
|
||||||
if (permission) {
|
if (permission) {
|
||||||
var dbHelper = DBHelper();
|
await _dbHelper.saveAutoDownload(widget.podcastLocal.id, boo: boo);
|
||||||
await dbHelper.saveAutoDownload(widget.podcastLocal.id, boo: boo);
|
|
||||||
}
|
}
|
||||||
if (mounted) setState(() {});
|
if (mounted) setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _saveSkipSeconds(int seconds) async {
|
Future<void> _saveSkipSecondsStart(int seconds) async {
|
||||||
var dbHelper = DBHelper();
|
await _dbHelper.saveSkipSecondsStart(widget.podcastLocal.id, seconds);
|
||||||
await dbHelper.saveSkipSeconds(widget.podcastLocal.id, seconds);
|
}
|
||||||
|
|
||||||
|
Future<void> _saveSkipSecondsEnd(int seconds) async {
|
||||||
|
await _dbHelper.saveSkipSecondsEnd(widget.podcastLocal.id, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _getAutoDownload(String id) async {
|
||||||
|
return await _dbHelper.getAutoDownload(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> _getSkipSecondStart(String id) async {
|
||||||
|
return await _dbHelper.getSkipSecondsStart(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> _getSkipSecondEnd(String id) async {
|
||||||
|
return await _dbHelper.getSkipSecondsEnd(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _markListened(String podcastId) async {
|
Future<void> _markListened(String podcastId) async {
|
||||||
setState(() {
|
setState(() {
|
||||||
_markStatus = MarkStatus.start;
|
_markStatus = MarkStatus.start;
|
||||||
});
|
});
|
||||||
var dbHelper = DBHelper();
|
var episodes = await _dbHelper.getRssItem(podcastId, -1, reverse: true);
|
||||||
var episodes = await dbHelper.getRssItem(podcastId, -1, reverse: true);
|
|
||||||
for (var episode in episodes) {
|
for (var episode in episodes) {
|
||||||
var marked = await dbHelper.checkMarked(episode);
|
final marked = await _dbHelper.checkMarked(episode);
|
||||||
if (!marked) {
|
if (!marked) {
|
||||||
final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1);
|
final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1);
|
||||||
await dbHelper.saveHistory(history);
|
await _dbHelper.saveHistory(history);
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_markStatus = MarkStatus.complete;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_markStatus = MarkStatus.complete;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _confirmMarkListened(BuildContext context) => generalDialog(
|
|
||||||
context,
|
|
||||||
title: Text(context.s.markConfirm),
|
|
||||||
content: Text(context.s.markConfirmContent),
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
context.s.cancel,
|
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () async {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
await _markListened(widget.podcastLocal.id);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
context.s.confirm,
|
|
||||||
style: TextStyle(color: context.accentColor),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<void> _refreshArtWork() async {
|
Future<void> _refreshArtWork() async {
|
||||||
setState(() => _coverStatus = RefreshCoverStatus.start);
|
setState(() => _coverStatus = RefreshCoverStatus.start);
|
||||||
var options = BaseOptions(
|
var options = BaseOptions(
|
||||||
|
@ -161,17 +164,6 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _getAutoDownload(String id) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
return await dbHelper.getAutoDownload(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int> _getSkipSecond(String id) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
var seconds = await dbHelper.getSkipSeconds(id);
|
|
||||||
return seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _getRefreshStatusIcon(RefreshCoverStatus status) {
|
Widget _getRefreshStatusIcon(RefreshCoverStatus status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case RefreshCoverStatus.none:
|
case RefreshCoverStatus.none:
|
||||||
|
@ -194,130 +186,265 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
|
final groupList = context.watch<GroupList>();
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FutureBuilder<bool>(
|
FutureBuilder<bool>(
|
||||||
future: _getAutoDownload(widget.podcastLocal.id),
|
future: _getAutoDownload(widget.podcastLocal.id),
|
||||||
initialData: false,
|
initialData: false,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () => _setAutoDownload(!snapshot.data),
|
onTap: () => _setAutoDownload(!snapshot.data),
|
||||||
leading: SizedBox(
|
leading: SizedBox(
|
||||||
height: 18,
|
height: 22,
|
||||||
width: 18,
|
width: 24,
|
||||||
child: CustomPaint(
|
child: CustomPaint(
|
||||||
painter: DownloadPainter(
|
painter: DownloadPainter(
|
||||||
color: context.brightness == Brightness.light
|
color: context.brightness == Brightness.light
|
||||||
? Colors.grey[600]
|
|
||||||
: Colors.white,
|
|
||||||
fraction: 0,
|
|
||||||
progressColor: context.accentColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(s.autoDownload),
|
|
||||||
trailing: Transform.scale(
|
|
||||||
scale: 0.9,
|
|
||||||
child: Switch(
|
|
||||||
value: snapshot.data, onChanged: _setAutoDownload),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
Divider(height: 1),
|
|
||||||
FutureBuilder<int>(
|
|
||||||
future: _getSkipSecond(widget.podcastLocal.id),
|
|
||||||
initialData: 0,
|
|
||||||
builder: (context, snapshot) => ListTile(
|
|
||||||
onTap: () {
|
|
||||||
generalDialog(
|
|
||||||
context,
|
|
||||||
title: Text(s.skipSecondsAtStart, maxLines: 2),
|
|
||||||
content: DurationPicker(
|
|
||||||
duration: Duration(seconds: snapshot.data),
|
|
||||||
onChange: (value) => _seconds = value.inSeconds,
|
|
||||||
),
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
_seconds = 0;
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
s.cancel,
|
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
_saveSkipSeconds(_seconds);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
s.confirm,
|
|
||||||
style: TextStyle(color: context.accentColor),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
).then((value) => setState(() {}));
|
|
||||||
},
|
|
||||||
leading: Icon(Icons.fast_forward),
|
|
||||||
title: Text(s.skipSecondsAtStart),
|
|
||||||
trailing: Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 10.0),
|
|
||||||
child: Text(snapshot.data.toTime),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Divider(height: 1),
|
|
||||||
ListTile(
|
|
||||||
onTap: () {
|
|
||||||
if (_markStatus != MarkStatus.start) {
|
|
||||||
_confirmMarkListened(context);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title: Text(s.menuMarkAllListened),
|
|
||||||
leading: SizedBox(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
child: CustomPaint(
|
|
||||||
painter: ListenedAllPainter(
|
|
||||||
context.brightness == Brightness.light
|
|
||||||
? Colors.grey[600]
|
? Colors.grey[600]
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
stroke: 2),
|
fraction: 0,
|
||||||
|
progressColor: context.accentColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
title: Text(s.autoDownload),
|
||||||
trailing: Padding(
|
trailing: Transform.scale(
|
||||||
padding: const EdgeInsets.only(right: 10.0),
|
scale: 0.9,
|
||||||
|
child:
|
||||||
|
Switch(value: snapshot.data, onChanged: _setAutoDownload),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
FutureBuilder<int>(
|
||||||
|
future: _getSkipSecondStart(widget.podcastLocal.id),
|
||||||
|
initialData: 0,
|
||||||
|
builder: (context, snapshot) => ListTile(
|
||||||
|
onTap: () {
|
||||||
|
_secondsStart = 0;
|
||||||
|
setState(() {
|
||||||
|
_removeConfirm = false;
|
||||||
|
_markConfirm = false;
|
||||||
|
_showEndTimePicker = false;
|
||||||
|
_showStartTimePicker = !_showStartTimePicker;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
leading: Icon(Icons.fast_forward),
|
||||||
|
title: Text(s.skipSecondsAtStart),
|
||||||
|
trailing: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 10.0),
|
||||||
|
child: Text(snapshot.data.toTime),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_showStartTimePicker)
|
||||||
|
_TimePicker(
|
||||||
|
onCancel: () {
|
||||||
|
_secondsStart = 0;
|
||||||
|
setState(() => _showStartTimePicker = false);
|
||||||
|
},
|
||||||
|
onConfirm: () async {
|
||||||
|
await _saveSkipSecondsStart(_secondsStart);
|
||||||
|
setState(() => _showStartTimePicker = false);
|
||||||
|
},
|
||||||
|
onChange: (value) => _secondsStart = value.inSeconds),
|
||||||
|
FutureBuilder<int>(
|
||||||
|
future: _getSkipSecondEnd(widget.podcastLocal.id),
|
||||||
|
initialData: 0,
|
||||||
|
builder: (context, snapshot) => ListTile(
|
||||||
|
onTap: () {
|
||||||
|
_secondsEnd = 0;
|
||||||
|
setState(() {
|
||||||
|
_removeConfirm = false;
|
||||||
|
_markConfirm = false;
|
||||||
|
_showStartTimePicker = false;
|
||||||
|
_showEndTimePicker = !_showEndTimePicker;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
leading: Icon(Icons.fast_rewind),
|
||||||
|
title: Text(s.skipSecondsAtEnd),
|
||||||
|
trailing: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 10.0),
|
||||||
|
child: Text(snapshot.data.toTime),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_showEndTimePicker)
|
||||||
|
_TimePicker(
|
||||||
|
onCancel: () {
|
||||||
|
_secondsEnd = 0;
|
||||||
|
setState(() => _showEndTimePicker = false);
|
||||||
|
},
|
||||||
|
onConfirm: () async {
|
||||||
|
await _saveSkipSecondsEnd(_secondsEnd);
|
||||||
|
setState(() => _showEndTimePicker = false);
|
||||||
|
},
|
||||||
|
onChange: (value) => _secondsEnd = value.inSeconds,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
onTap: () {
|
||||||
|
if (_coverStatus != RefreshCoverStatus.start) {
|
||||||
|
_refreshArtWork();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: Text(s.refreshArtwork),
|
||||||
|
leading: Icon(Icons.refresh),
|
||||||
|
trailing: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 15.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
width: 20,
|
width: 20,
|
||||||
child: _markStatus == MarkStatus.none
|
child: _getRefreshStatusIcon(_coverStatus)))),
|
||||||
? Center()
|
Divider(height: 1),
|
||||||
: _markStatus == MarkStatus.start
|
ListTile(
|
||||||
? CircularProgressIndicator(strokeWidth: 2)
|
onTap: () {
|
||||||
: Icon(Icons.done)),
|
setState(() {
|
||||||
)),
|
_removeConfirm = false;
|
||||||
Divider(height: 1),
|
_showStartTimePicker = false;
|
||||||
ListTile(
|
_showEndTimePicker = false;
|
||||||
onTap: () {
|
_markConfirm = !_markConfirm;
|
||||||
if (_coverStatus != RefreshCoverStatus.start) {
|
});
|
||||||
_refreshArtWork();
|
},
|
||||||
}
|
title: Text(s.menuMarkAllListened,
|
||||||
},
|
style: TextStyle(
|
||||||
title: Text(s.refreshArtwork),
|
color: context.accentColor, fontWeight: FontWeight.bold)),
|
||||||
leading: Icon(Icons.refresh),
|
leading: SizedBox(
|
||||||
trailing: Padding(
|
height: 22,
|
||||||
padding: const EdgeInsets.only(right: 15.0),
|
width: 24,
|
||||||
child: SizedBox(
|
child: CustomPaint(
|
||||||
height: 20,
|
painter: ListenedAllPainter(
|
||||||
width: 20,
|
context.brightness == Brightness.light
|
||||||
child: _getRefreshStatusIcon(_coverStatus)))),
|
? Colors.grey[600]
|
||||||
Divider(height: 1),
|
: Colors.white,
|
||||||
]);
|
stroke: 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 10.0),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: _markStatus == MarkStatus.none
|
||||||
|
? Center()
|
||||||
|
: _markStatus == MarkStatus.start
|
||||||
|
? CircularProgressIndicator(strokeWidth: 2)
|
||||||
|
: Icon(Icons.done)),
|
||||||
|
)),
|
||||||
|
if (_markConfirm)
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
color: context.primaryColorDark,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
onPressed: () => setState(() {
|
||||||
|
_markConfirm = false;
|
||||||
|
}),
|
||||||
|
child: Text(
|
||||||
|
s.cancel,
|
||||||
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
|
)),
|
||||||
|
FlatButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_markStatus != MarkStatus.start) {
|
||||||
|
_markListened(widget.podcastLocal.id);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_markConfirm = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Text(s.confirm,
|
||||||
|
style: TextStyle(color: context.accentColor))),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_markConfirm = false;
|
||||||
|
_showStartTimePicker = false;
|
||||||
|
_showEndTimePicker = false;
|
||||||
|
_removeConfirm = !_removeConfirm;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
title: Text(s.remove,
|
||||||
|
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold)),
|
||||||
|
leading: Icon(Icons.delete, color: Colors.red),
|
||||||
|
),
|
||||||
|
if (_removeConfirm)
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
color: context.primaryColorDark,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
onPressed: () => setState(() {
|
||||||
|
_removeConfirm = false;
|
||||||
|
}),
|
||||||
|
child:
|
||||||
|
Text(s.cancel, style: TextStyle(color: Colors.grey[600])),
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
splashColor: Colors.red.withAlpha(70),
|
||||||
|
onPressed: () {
|
||||||
|
groupList.removePodcast(widget.podcastLocal.id);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
Text(s.confirm, style: TextStyle(color: Colors.red))),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TimePicker extends StatelessWidget {
|
||||||
|
const _TimePicker({this.onConfirm, this.onCancel, this.onChange, Key key})
|
||||||
|
: super(key: key);
|
||||||
|
final VoidCallback onConfirm;
|
||||||
|
final VoidCallback onCancel;
|
||||||
|
final ValueChanged<Duration> onChange;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = context.s;
|
||||||
|
return Container(
|
||||||
|
color: context.primaryColorDark,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 10),
|
||||||
|
DurationPicker(
|
||||||
|
key: key,
|
||||||
|
onChange: onChange,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
onPressed: onCancel,
|
||||||
|
child: Text(
|
||||||
|
s.cancel,
|
||||||
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
splashColor: context.accentColor.withAlpha(70),
|
||||||
|
onPressed: onConfirm,
|
||||||
|
child: Text(
|
||||||
|
s.confirm,
|
||||||
|
style: TextStyle(color: context.accentColor),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -920,6 +920,13 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
||||||
Future<void> _playFromStart() async {
|
Future<void> _playFromStart() async {
|
||||||
_playing = true;
|
_playing = true;
|
||||||
_session.setActive(true);
|
_session.setActive(true);
|
||||||
|
if (mediaItem.extras['skipSecondsStart'] > 0 ||
|
||||||
|
mediaItem.extras['skipSecondsEnd'] > 0) {
|
||||||
|
//_audioPlayer.seek(Duration(seconds: mediaItem.extras['skip']));
|
||||||
|
_audioPlayer.setClip(
|
||||||
|
start: Duration(seconds: mediaItem.extras['skipSecondsStart']),
|
||||||
|
end: Duration(seconds: mediaItem.extras['skipSecondsEnd']));
|
||||||
|
}
|
||||||
if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting ||
|
if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting ||
|
||||||
_audioPlayer.playbackEvent.state != AudioPlaybackState.none) {
|
_audioPlayer.playbackEvent.state != AudioPlaybackState.none) {
|
||||||
try {
|
try {
|
||||||
|
@ -928,9 +935,6 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
||||||
_setState(processingState: AudioProcessingState.error);
|
_setState(processingState: AudioProcessingState.error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mediaItem.extras['skip'] > 0) {
|
|
||||||
_audioPlayer.seek(Duration(seconds: mediaItem.extras['skip']));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -21,7 +21,8 @@ class EpisodeBrief extends Equatable {
|
||||||
final String imagePath;
|
final String imagePath;
|
||||||
final String mediaId;
|
final String mediaId;
|
||||||
final int isNew;
|
final int isNew;
|
||||||
final int skipSeconds;
|
final int skipSecondsStart;
|
||||||
|
final int skipSecondsEnd;
|
||||||
final int downloadDate;
|
final int downloadDate;
|
||||||
EpisodeBrief(
|
EpisodeBrief(
|
||||||
this.title,
|
this.title,
|
||||||
|
@ -37,7 +38,8 @@ class EpisodeBrief extends Equatable {
|
||||||
{this.mediaId,
|
{this.mediaId,
|
||||||
this.liked,
|
this.liked,
|
||||||
this.downloaded,
|
this.downloaded,
|
||||||
this.skipSeconds,
|
this.skipSecondsStart,
|
||||||
|
this.skipSecondsEnd,
|
||||||
this.description = '',
|
this.description = '',
|
||||||
this.downloadDate = 0})
|
this.downloadDate = 0})
|
||||||
: assert(enclosureUrl != null);
|
: assert(enclosureUrl != null);
|
||||||
|
@ -50,7 +52,10 @@ class EpisodeBrief extends Equatable {
|
||||||
album: feedTitle,
|
album: feedTitle,
|
||||||
duration: Duration.zero,
|
duration: Duration.zero,
|
||||||
artUri: 'file://$imagePath',
|
artUri: 'file://$imagePath',
|
||||||
extras: {'skip': skipSeconds});
|
extras: {
|
||||||
|
'skipSecondsStart': skipSecondsStart,
|
||||||
|
'skipSecondsEnd': skipSecondsEnd
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageProvider get avatarImage {
|
ImageProvider get avatarImage {
|
||||||
|
@ -72,7 +77,8 @@ class EpisodeBrief extends Equatable {
|
||||||
primaryColor, duration, explicit, imagePath, isNew,
|
primaryColor, duration, explicit, imagePath, isNew,
|
||||||
mediaId: mediaId ?? this.mediaId,
|
mediaId: mediaId ?? this.mediaId,
|
||||||
downloaded: downloaded,
|
downloaded: downloaded,
|
||||||
skipSeconds: skipSeconds,
|
skipSecondsStart: skipSecondsStart,
|
||||||
|
skipSecondsEnd: skipSecondsEnd,
|
||||||
description: description,
|
description: description,
|
||||||
downloadDate: downloadDate);
|
downloadDate: downloadDate);
|
||||||
|
|
||||||
|
|
|
@ -635,24 +635,20 @@ class DurationPicker extends StatelessWidget {
|
||||||
@required this.onChange,
|
@required this.onChange,
|
||||||
this.snapToMins,
|
this.snapToMins,
|
||||||
this.width,
|
this.width,
|
||||||
this.height});
|
this.height,
|
||||||
|
Key key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: width ?? _kDurationPickerWidthPortrait / 1.5,
|
width: width ?? _kDurationPickerWidthPortrait / 1.5,
|
||||||
height: height ?? _kDurationPickerHeightPortrait / 1.5,
|
height: height ?? _kDurationPickerHeightPortrait / 1.5,
|
||||||
child: Column(
|
child: _Dial(
|
||||||
mainAxisSize: MainAxisSize.min,
|
duration: duration,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
onChanged: onChange,
|
||||||
children: <Widget>[
|
snapToMins: snapToMins,
|
||||||
Expanded(
|
),
|
||||||
child: _Dial(
|
);
|
||||||
duration: duration,
|
|
||||||
onChanged: onChange,
|
|
||||||
snapToMins: snapToMins,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,25 +41,37 @@ Future generalSheet(BuildContext context, {Widget child, String title}) async =>
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return Column(
|
return SafeArea(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: SingleChildScrollView(
|
||||||
children: [
|
physics: NeverScrollableScrollPhysics(),
|
||||||
Padding(
|
child: Column(
|
||||||
padding: EdgeInsets.only(top: 10.0, bottom: 2.0),
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Container(
|
children: [
|
||||||
height: 4,
|
Padding(
|
||||||
width: 25,
|
padding: EdgeInsets.only(top: 10.0, bottom: 2.0),
|
||||||
decoration: BoxDecoration(
|
child: Container(
|
||||||
borderRadius: BorderRadius.circular(2.0),
|
height: 4,
|
||||||
color: context.primaryColorDark),
|
width: 25,
|
||||||
),
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(2.0),
|
||||||
|
color: context.primaryColorDark),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 50, right: 50, top: 6.0, bottom: 15),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: context.textTheme.headline6,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.clip,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(height: 1),
|
||||||
|
child,
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: EdgeInsets.symmetric(vertical: 6.0),
|
|
||||||
child: Text(title, style: context.textTheme.headline6),
|
|
||||||
),
|
|
||||||
Divider(height: 1),
|
|
||||||
child,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue