Open playlist page default.

This commit is contained in:
Stonegate 2021-01-07 00:28:53 +08:00
parent 747aa47772
commit 4fe335ff69
8 changed files with 537 additions and 393 deletions

View File

@ -60,6 +60,8 @@ const String downloadPositionKey = 'downloadPositionKey';
const String deleteAfterPlayedKey = 'removeAfterPlayedKey';
const String playlistsAllKey = 'playlistsAllKey';
const String playerStateKey = 'playerStateKey';
const String openPlaylistDefaultKey = 'openPlaylistDefaultKey';
const String openAllPodcastDefaultKey = 'openAllPodcastDefaultKey';
class KeyValueStorage {
final String key;

View File

@ -5,6 +5,8 @@ import 'package:flutter/services.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/playlists/playlist_home.dart';
import 'package:tuple/tuple.dart';
import 'generated/l10n.dart';
import 'home/home.dart';
@ -52,15 +54,17 @@ Future main() async {
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<SettingState>(
builder: (_, setting, child) {
return Selector<SettingState, Tuple3<ThemeMode, ThemeData, ThemeData>>(
selector: (_, setting) =>
Tuple3(setting.theme, setting.lightTheme, setting.darkTheme),
builder: (_, data, child) {
return FeatureDiscovery(
child: MaterialApp(
themeMode: setting.theme,
themeMode: data.item1,
debugShowCheckedModeBanner: false,
title: 'Tsacdop',
theme: setting.lightTheme,
darkTheme: setting.darkTheme,
theme: data.item2,
darkTheme: data.item3,
localizationsDelegates: [
S.delegate,
GlobalMaterialLocalizations.delegate,
@ -68,11 +72,15 @@ class MyApp extends StatelessWidget {
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
home: setting.showIntro ? SlideIntro(goto: Goto.home) : child,
home: context.read<SettingState>().showIntro
? SlideIntro(goto: Goto.home)
: context.read<SettingState>().openPlaylistDefault
? PlaylistHome()
: Home(),
),
);
},
child: FeatureDiscovery(child: Home()),
//child: FeatureDiscovery(child: Home()),
);
}
}

View File

@ -5,10 +5,13 @@ import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:line_icons/line_icons.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/util/pageroute.dart';
import 'package:tuple/tuple.dart';
import '../home/home.dart';
import '../local_storage/sqflite_localpodcast.dart';
import '../state/audio_state.dart';
import '../state/setting_state.dart';
import '../type/episodebrief.dart';
import '../type/play_histroy.dart';
import '../type/playlist.dart';
@ -30,7 +33,9 @@ class _PlaylistHomeState extends State<PlaylistHome> {
@override
void initState() {
Future.microtask(() => context.read<AudioPlayerNotifier>().initPlaylist());
super.initState();
//context.read<AudioPlayerNotifier>().initPlaylist();
_selected = 'PlayNext';
_body = _Queue();
}
@ -64,184 +69,195 @@ class _PlaylistHomeState extends State<PlaylistHome> {
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
),
child: Scaffold(
appBar: AppBar(
leading: CustomBackButton(),
centerTitle: true,
title: Selector<AudioPlayerNotifier, EpisodeBrief>(
selector: (_, audio) => audio.episode,
builder: (_, data, __) {
return Text(data?.title ?? '', maxLines: 1);
},
child: WillPopScope(
onWillPop: () {
if (context.read<SettingState>().openPlaylistDefault) {
Navigator.push(context, SlideRightRoute(page: Home()));
return Future.value(false);
} else {
return Future.value(true);
}
},
child: Scaffold(
appBar: AppBar(
leading: CustomBackButton(),
centerTitle: true,
title: Selector<AudioPlayerNotifier, EpisodeBrief>(
selector: (_, audio) => audio.episode,
builder: (_, data, __) {
return Text(data?.title ?? '', maxLines: 1);
},
),
backgroundColor: context.scaffoldBackgroundColor,
),
backgroundColor: context.scaffoldBackgroundColor,
),
body: Column(
children: [
SizedBox(
height: 100,
child: Selector<AudioPlayerNotifier,
Tuple4<Playlist, bool, bool, EpisodeBrief>>(
selector: (_, audio) => Tuple4(audio.playlist,
audio.playerRunning, audio.playing, audio.episode),
builder: (_, data, __) {
final running = data.item2;
final playing = data.item3;
final audio = context.read<AudioPlayerNotifier>();
return Row(
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.fast_rewind),
onPressed: () {
body: Column(
children: [
SizedBox(
height: 100,
child: Selector<AudioPlayerNotifier,
Tuple4<Playlist, bool, bool, EpisodeBrief>>(
selector: (_, audio) => Tuple4(audio.playlist,
audio.playerRunning, audio.playing, audio.episode),
builder: (_, data, __) {
final running = data.item2;
final playing = data.item3;
final audio = context.read<AudioPlayerNotifier>();
return Row(
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.fast_rewind),
onPressed: () {
if (running) {
audio.rewind();
}
}),
SizedBox(width: 30),
IconButton(
padding: EdgeInsets.zero,
icon: Icon(
playing
? LineIcons.pause_solid
: LineIcons.play_solid,
size: 40),
onPressed: () {
if (running) {
playing
? audio.pauseAduio()
: audio.resumeAudio();
} else {
context
.read<AudioPlayerNotifier>()
.playFromLastPosition();
}
}),
SizedBox(width: 30),
IconButton(
icon: Icon(Icons.fast_forward),
onPressed: () {
if (running) {
audio.fastForward();
}
})
],
),
if (data.item2)
Selector<AudioPlayerNotifier,
Tuple3<bool, double, String>>(
selector: (_, audio) => Tuple3(
audio.buffering,
(audio.backgroundAudioDuration -
audio.backgroundAudioPosition) /
1000,
audio.remoteErrorMessage),
builder: (_, data, __) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: data.item3 != null
? Text(data.item3,
style: const TextStyle(
color: Color(0xFFFF0000)))
: data.item1
? Text(
s.buffering,
style: TextStyle(
color:
context.accentColor),
)
: Text(
s.timeLeft((data.item2)
.toInt()
.toTime ??
''),
maxLines: 2,
),
);
},
)
],
)),
data.item4 != null
? ClipRRect(
borderRadius: BorderRadius.circular(10),
child: InkWell(
onTap: () {
if (running) {
audio.rewind();
}
}),
SizedBox(width: 30),
IconButton(
padding: EdgeInsets.zero,
icon: Icon(
playing
? LineIcons.pause_solid
: LineIcons.play_solid,
size: 40),
onPressed: () {
if (running) {
playing
? audio.pauseAduio()
: audio.resumeAudio();
} else {
context
.read<AudioPlayerNotifier>()
.playFromLastPosition();
.playNext();
}
}),
SizedBox(width: 30),
IconButton(
icon: Icon(Icons.fast_forward),
onPressed: () {
if (running) {
audio.fastForward();
}
})
],
),
if (data.item2)
Selector<AudioPlayerNotifier,
Tuple3<bool, double, String>>(
selector: (_, audio) => Tuple3(
audio.buffering,
(audio.backgroundAudioDuration -
audio.backgroundAudioPosition) /
1000,
audio.remoteErrorMessage),
builder: (_, data, __) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: data.item3 != null
? Text(data.item3,
style: const TextStyle(
color: Color(0xFFFF0000)))
: data.item1
? Text(
s.buffering,
style: TextStyle(
color: context.accentColor),
)
: Text(
s.timeLeft((data.item2)
.toInt()
.toTime ??
''),
maxLines: 2,
),
);
},
)
],
)),
data.item4 != null
? ClipRRect(
borderRadius: BorderRadius.circular(10),
child: InkWell(
onTap: () {
if (running) {
context
.read<AudioPlayerNotifier>()
.playNext();
}
},
child: SizedBox(
width: 80,
height: 80,
child:
Image(image: data.item4.avatarImage)),
),
)
: Container(
decoration: BoxDecoration(
color: context.accentColor.withAlpha(70),
borderRadius: BorderRadius.circular(10)),
width: 80,
height: 80),
SizedBox(
width: 20,
),
],
);
},
},
child: SizedBox(
width: 80,
height: 80,
child: Image(
image: data.item4.avatarImage)),
),
)
: Container(
decoration: BoxDecoration(
color: context.accentColor.withAlpha(70),
borderRadius: BorderRadius.circular(10)),
width: 80,
height: 80),
SizedBox(
width: 20,
),
],
);
},
),
),
),
SizedBox(
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_tabWidget(
icon: Icon(Icons.queue_music_rounded),
label: s.playNext,
color: Colors.blue,
isSelected: _selected == 'PlayNext',
onTap: () => setState(() {
_body = _Queue();
_selected = 'PlayNext';
})),
_tabWidget(
icon: Icon(Icons.history),
label: s.settingsHistory,
color: Colors.green,
isSelected: _selected == 'History',
onTap: () => setState(() {
_body = _History();
_selected = 'History';
})),
_tabWidget(
icon: Icon(Icons.playlist_play),
label: s.playlists,
color: Colors.purple,
isSelected: _selected == 'Playlists',
onTap: () => setState(() {
_body = _Playlists();
_selected = 'Playlists';
})),
],
SizedBox(
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_tabWidget(
icon: Icon(Icons.queue_music_rounded),
label: s.playNext,
color: Colors.blue,
isSelected: _selected == 'PlayNext',
onTap: () => setState(() {
_body = _Queue();
_selected = 'PlayNext';
})),
_tabWidget(
icon: Icon(Icons.history),
label: s.settingsHistory,
color: Colors.green,
isSelected: _selected == 'History',
onTap: () => setState(() {
_body = _History();
_selected = 'History';
})),
_tabWidget(
icon: Icon(Icons.playlist_play),
label: s.playlists,
color: Colors.purple,
isSelected: _selected == 'Playlists',
onTap: () => setState(() {
_body = _Playlists();
_selected = 'Playlists';
})),
],
),
),
),
Divider(height: 1),
Expanded(
child: AnimatedSwitcher(
duration: Duration(milliseconds: 300), child: _body))
],
)),
Divider(height: 1),
Expanded(
child: AnimatedSwitcher(
duration: Duration(milliseconds: 300), child: _body))
],
)),
),
);
}
}
@ -260,61 +276,67 @@ class __QueueState extends State<_Queue> {
selector: (_, audio) =>
Tuple3(audio.playlist, audio.playerRunning, audio.episode),
builder: (_, data, __) {
var episodes = data.item1.episodes.toSet().toList();
var episodes = data.item1?.episodes?.toSet()?.toList();
var queue = data.item1;
var running = data.item2;
return queue.name == 'Queue'
? ReorderableListView(
onReorder: (oldIndex, newIndex) {
context
.read<AudioPlayerNotifier>()
.reorderPlaylist(oldIndex, newIndex);
setState(() {});
},
scrollDirection: Axis.vertical,
children: data.item2
? episodes.map<Widget>((episode) {
if (episode.enclosureUrl !=
episodes.first.enclosureUrl) {
return DismissibleContainer(
episode: episode,
onRemove: (value) => setState(() {}),
key: ValueKey(episode.enclosureUrl),
);
} else {
return EpisodeCard(episode,
key: ValueKey('playing'),
isPlaying: true,
canReorder: true,
tileColor: context.primaryColorDark);
}
}).toList()
: episodes
.map<Widget>((episode) => DismissibleContainer(
episode: episode,
onRemove: (value) => setState(() {}),
key: ValueKey(episode.enclosureUrl),
))
.toList())
: ListView.builder(
itemCount: queue.episodeList.length,
itemBuilder: (context, index) {
final episode = queue.episodes[index];
final isPlaying =
data.item3 != null && data.item3 == episode;
return EpisodeCard(
episode,
isPlaying: isPlaying && running,
tileColor: isPlaying ? context.primaryColorDark : null,
onTap: () async {
if (!isPlaying) {
await context
.read<AudioPlayerNotifier>()
.loadEpisodeFromPlaylist(episode);
}
return queue == null
? Center()
: queue?.name == 'Queue'
? ReorderableListView(
onReorder: (oldIndex, newIndex) {
context
.read<AudioPlayerNotifier>()
.reorderPlaylist(oldIndex, newIndex);
setState(() {});
},
);
});
scrollDirection: Axis.vertical,
children: data.item2
? episodes.map<Widget>((episode) {
if (episode.enclosureUrl !=
episodes.first.enclosureUrl) {
return DismissibleContainer(
episode: episode,
onRemove: (value) => setState(() {}),
key: ValueKey(episode.enclosureUrl),
);
} else {
return EpisodeCard(episode,
key: ValueKey('playing'),
isPlaying: true,
canReorder: true,
tileColor: context.primaryColorDark);
}
}).toList()
: episodes
.map<Widget>((episode) => DismissibleContainer(
episode: episode,
onRemove: (value) => setState(() {}),
key: ValueKey(episode.enclosureUrl),
))
.toList())
: ListView.builder(
itemCount: queue?.length,
itemBuilder: (context, index) {
final episode =
queue != null ? queue.episodes[index] : null;
final isPlaying =
data.item3 != null && data.item3 == episode;
return episode == null
? Center()
: EpisodeCard(
episode,
isPlaying: isPlaying && running,
tileColor:
isPlaying ? context.primaryColorDark : null,
onTap: () async {
if (!isPlaying) {
await context
.read<AudioPlayerNotifier>()
.loadEpisodeFromPlaylist(episode);
}
},
);
});
});
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/state/setting_state.dart';
import '../local_storage/key_value_storage.dart';
import '../service/search_api.dart';
@ -310,9 +311,61 @@ class _LayoutSettingState extends State<LayoutSetting> {
),
),
Divider(height: 1),
Padding(
padding: EdgeInsets.all(10.0),
SizedBox(height: 20),
Container(
height: 30.0,
padding: EdgeInsets.symmetric(horizontal: 70),
alignment: Alignment.centerLeft,
child: Text('Default page',
style: context.textTheme.bodyText1
.copyWith(color: context.accentColor)),
),
Selector<SettingState, bool>(
selector: (_, setting) => setting.openPlaylistDefault,
builder: (_, data, __) {
return ListTile(
contentPadding: EdgeInsets.fromLTRB(70, 10, 10, 10),
onTap: () => context
.read<SettingState>()
.openPlaylistDefault = !data,
title: Text('Open playlist page by default'),
subtitle: Text(
'Open playlist page instead of homepage by default'),
trailing: Transform.scale(
scale: 0.9,
child: Switch(
value: data,
onChanged: (boo) => context
.read<SettingState>()
.openPlaylistDefault = boo),
),
);
},
),
Selector<SettingState, bool>(
selector: (_, setting) => setting.openAllPodcastDefalt,
builder: (_, data, __) {
return ListTile(
contentPadding: EdgeInsets.fromLTRB(70, 10, 10, 10),
onTap: () => context
.read<SettingState>()
.openAllPodcastDefault = !data,
title: Text('Open all podcasts page by default'),
subtitle: Text(
'Open all podcasts page instead of group page by default'),
trailing: Transform.scale(
scale: 0.9,
child: Switch(
value: data,
onChanged: (boo) => context
.read<SettingState>()
.openAllPodcastDefault = boo),
),
);
},
),
Divider(height: 1),
SizedBox(height: 20),
Container(
height: 30.0,
padding: EdgeInsets.symmetric(horizontal: 70),

View File

@ -84,7 +84,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
EpisodeBrief _episode;
/// Playlists include queue and playlists created by user.
List<Playlist> _playlists;
List<Playlist> _playlists = [];
/// Playing playlist.
Playlist _playlist;
@ -261,53 +261,55 @@ class AudioPlayerNotifier extends ChangeNotifier {
}
Future<void> initPlaylist() async {
var playlistEntities = await _playlistsStorgae.getPlaylists();
_playlists = [
for (var entity in playlistEntities) Playlist.fromEntity(entity)
];
await _playlists.first.getPlaylist();
await _getAutoPlay();
if (_playlists.isEmpty) {
var playlistEntities = await _playlistsStorgae.getPlaylists();
_playlists = [
for (var entity in playlistEntities) Playlist.fromEntity(entity)
];
await _playlists.first.getPlaylist();
await _getAutoPlay();
var state = await _playerStateStorage.getPlayerState();
var idList = [for (var p in _playlists) p.id];
if (idList.contains(state[1])) {
_playlist = _playlists.firstWhere(
(p) => p.id == state[0],
);
await _playlist.getPlaylist();
if (state[1] != '') {
var episode = await _dbHelper.getRssItemWithUrl(state[1]);
if ((!_playlist.isQueue && _playlist.contains(episode)) ||
(_playlist.isQueue &&
_queue.isNotEmpty &&
_queue.episodes.first == episode)) {
_episode = episode;
_lastPosition = int.parse(state[2] ?? '0');
var state = await _playerStateStorage.getPlayerState();
var idList = [for (var p in _playlists) p.id];
if (idList.contains(state[1])) {
_playlist = _playlists.firstWhere(
(p) => p.id == state[0],
);
await _playlist.getPlaylist();
if (state[1] != '') {
var episode = await _dbHelper.getRssItemWithUrl(state[1]);
if ((!_playlist.isQueue && _playlist.contains(episode)) ||
(_playlist.isQueue &&
_queue.isNotEmpty &&
_queue.episodes.first == episode)) {
_episode = episode;
_lastPosition = int.parse(state[2] ?? '0');
} else {
_episode = _playlist.isNotEmpty ? _playlist.episodes.first : null;
_lastPosition = 0;
}
} else {
_episode = _playlist.isNotEmpty ? _playlist.episodes.first : null;
_lastPosition = 0;
}
} else {
_episode = _playlist.isNotEmpty ? _playlist.episodes.first : null;
_playlist = _playlists.first;
_episode = _playlist.isNotEmpty ? _playlist.episodes?.first : null;
_lastPosition = 0;
}
} else {
_playlist = _playlists.first;
_episode = _playlist.isNotEmpty ? _playlist.episodes?.first : null;
_lastPosition = 0;
}
notifyListeners();
notifyListeners();
/// Save plays history if app is closed accidentally.
/// if (_lastPostion > 0 && _queue.episodes.isNotEmpty) {
/// final episode = _queue.episodes.first;
/// final duration = episode.duration * 1000;
/// final seekValue = duration != 0 ? _lastPostion / duration : 1.0;
/// final history = PlayHistory(
/// episode.title, episode.enclosureUrl, _lastPostion ~/ 1000, seekValue);
/// await _dbHelper.saveHistory(history);
/// }
await KeyValueStorage(lastWorkKey).saveInt(0);
/// Save plays history if app is closed accidentally.
/// if (_lastPostion > 0 && _queue.episodes.isNotEmpty) {
/// final episode = _queue.episodes.first;
/// final duration = episode.duration * 1000;
/// final seekValue = duration != 0 ? _lastPostion / duration : 1.0;
/// final history = PlayHistory(
/// episode.title, episode.enclosureUrl, _lastPostion ~/ 1000, seekValue);
/// await _dbHelper.saveHistory(history);
/// }
await KeyValueStorage(lastWorkKey).saveInt(0);
}
}
Future<void> playFromLastPosition() async {

View File

@ -74,37 +74,40 @@ final showNotesFontStyles = <TextStyle>[
];
class SettingState extends ChangeNotifier {
var themeStorage = KeyValueStorage(themesKey);
var accentStorage = KeyValueStorage(accentsKey);
var autoupdateStorage = KeyValueStorage(autoUpdateKey);
var intervalStorage = KeyValueStorage(updateIntervalKey);
var downloadUsingDataStorage = KeyValueStorage(downloadUsingDataKey);
var introStorage = KeyValueStorage(introKey);
var realDarkStorage = KeyValueStorage(realDarkKey);
var autoPlayStorage = KeyValueStorage(autoPlayKey);
var defaultSleepTimerStorage = KeyValueStorage(defaultSleepTimerKey);
var autoSleepTimerStorage = KeyValueStorage(autoSleepTimerKey);
var autoSleepTimerModeStorage = KeyValueStorage(autoSleepTimerModeKey);
var autoSleepTimerStartStorage = KeyValueStorage(autoSleepTimerStartKey);
var autoSleepTimerEndStorage = KeyValueStorage(autoSleepTimerEndKey);
var tapToOpenPopupMenuStorage = KeyValueStorage(tapToOpenPopupMenuKey);
var cacheStorage = KeyValueStorage(cacheMaxKey);
var podcastLayoutStorage = KeyValueStorage(podcastLayoutKey);
var favLayoutStorage = KeyValueStorage(favLayoutKey);
var downloadLayoutStorage = KeyValueStorage(downloadLayoutKey);
var recentLayoutStorage = KeyValueStorage(recentLayoutKey);
var autoDeleteStorage = KeyValueStorage(autoDeleteKey);
var autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey);
var fastForwardSecondsStorage = KeyValueStorage(fastForwardSecondsKey);
var rewindSecondsStorage = KeyValueStorage(rewindSecondsKey);
var localeStorage = KeyValueStorage(localeKey);
var showNotesFontStorage = KeyValueStorage(showNotesFontKey);
final _themeStorage = KeyValueStorage(themesKey);
final _accentStorage = KeyValueStorage(accentsKey);
final _autoupdateStorage = KeyValueStorage(autoUpdateKey);
final _intervalStorage = KeyValueStorage(updateIntervalKey);
final _downloadUsingDataStorage = KeyValueStorage(downloadUsingDataKey);
final _introStorage = KeyValueStorage(introKey);
final _realDarkStorage = KeyValueStorage(realDarkKey);
final _autoPlayStorage = KeyValueStorage(autoPlayKey);
final _defaultSleepTimerStorage = KeyValueStorage(defaultSleepTimerKey);
final _autoSleepTimerStorage = KeyValueStorage(autoSleepTimerKey);
final _autoSleepTimerModeStorage = KeyValueStorage(autoSleepTimerModeKey);
final _autoSleepTimerStartStorage = KeyValueStorage(autoSleepTimerStartKey);
final _autoSleepTimerEndStorage = KeyValueStorage(autoSleepTimerEndKey);
final _cacheStorage = KeyValueStorage(cacheMaxKey);
final _podcastLayoutStorage = KeyValueStorage(podcastLayoutKey);
final _favLayoutStorage = KeyValueStorage(favLayoutKey);
final _downloadLayoutStorage = KeyValueStorage(downloadLayoutKey);
final _recentLayoutStorage = KeyValueStorage(recentLayoutKey);
final _autoDeleteStorage = KeyValueStorage(autoDeleteKey);
final _autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey);
final _fastForwardSecondsStorage = KeyValueStorage(fastForwardSecondsKey);
final _rewindSecondsStorage = KeyValueStorage(rewindSecondsKey);
final _localeStorage = KeyValueStorage(localeKey);
final _showNotesFontStorage = KeyValueStorage(showNotesFontKey);
final _openPlaylistDefaultStorage = KeyValueStorage(openPlaylistDefaultKey);
final _openAllPodcastDefaultStorage =
KeyValueStorage(openAllPodcastDefaultKey);
Future initData() async {
await _getTheme();
await _getAccentSetColor();
await _getShowIntro();
await _getRealDark();
await _getOpenPlaylistDefault();
}
@override
@ -116,6 +119,7 @@ class SettingState extends ChangeNotifier {
_getSleepTimerData();
_getPlayerSeconds();
_getShowNotesFonts();
_getOpenAllPodcastDefault();
_getUpdateInterval().then((value) async {
if (_initUpdateTag == 0) {
setWorkManager(24);
@ -247,6 +251,24 @@ class SettingState extends ChangeNotifier {
notifyListeners();
}
/// Open playlist page default
bool _openPlaylistDefault;
bool get openPlaylistDefault => _openPlaylistDefault;
set openPlaylistDefault(bool boo) {
_openPlaylistDefault = boo;
_setOpenPlaylistDefault();
notifyListeners();
}
/// Open all podcasts page default
bool _openAllPodcastDefault;
bool get openAllPodcastDefalt => _openAllPodcastDefault;
set openAllPodcastDefault(boo) {
_openAllPodcastDefault = boo;
_setOpenAllPodcastDefault();
notifyListeners();
}
int _defaultSleepTimer;
int get defaultSleepTimer => _defaultSleepTimer;
set setDefaultSleepTimer(int i) {
@ -322,12 +344,12 @@ class SettingState extends ChangeNotifier {
}
Future _getTheme() async {
var mode = await themeStorage.getInt();
var mode = await _themeStorage.getInt();
_theme = ThemeMode.values[mode];
}
Future _getAccentSetColor() async {
var colorString = await accentStorage.getString();
var colorString = await _accentStorage.getString();
if (colorString.isNotEmpty) {
var color = int.parse('FF${colorString.toUpperCase()}', radix: 16);
_accentSetColor = Color(color).withOpacity(1.0);
@ -339,53 +361,63 @@ class SettingState extends ChangeNotifier {
Future _getAutoUpdate() async {
_autoUpdate =
await autoupdateStorage.getBool(defaultValue: true, reverse: true);
await _autoupdateStorage.getBool(defaultValue: true, reverse: true);
}
Future _getUpdateInterval() async {
_initUpdateTag = await intervalStorage.getInt();
_initUpdateTag = await _intervalStorage.getInt();
_updateInterval = _initUpdateTag;
}
Future _getDownloadUsingData() async {
_downloadUsingData = await downloadUsingDataStorage.getBool(
_downloadUsingData = await _downloadUsingDataStorage.getBool(
defaultValue: true, reverse: true);
}
Future _saveDownloadUsingData() async {
await downloadUsingDataStorage.saveBool(_downloadUsingData, reverse: true);
await _downloadUsingDataStorage.saveBool(_downloadUsingData, reverse: true);
}
Future _getShowIntro() async {
_initialShowIntor = await introStorage.getInt();
_initialShowIntor = await _introStorage.getInt();
_showIntro = _initialShowIntor == 0;
}
Future _getRealDark() async {
_realDark = await realDarkStorage.getBool(defaultValue: false);
_realDark = await _realDarkStorage.getBool(defaultValue: false);
}
Future _getOpenPlaylistDefault() async {
_openPlaylistDefault =
await _openPlaylistDefaultStorage.getBool(defaultValue: false);
}
Future _getOpenAllPodcastDefault() async {
_openAllPodcastDefault =
await _openAllPodcastDefaultStorage.getBool(defaultValue: false);
}
Future _getSleepTimerData() async {
_defaultSleepTimer =
await defaultSleepTimerStorage.getInt(defaultValue: 30);
_autoSleepTimer = await autoSleepTimerStorage.getBool(defaultValue: false);
await _defaultSleepTimerStorage.getInt(defaultValue: 30);
_autoSleepTimer = await _autoSleepTimerStorage.getBool(defaultValue: false);
_autoSleepTimerStart =
await autoSleepTimerStartStorage.getInt(defaultValue: 1380);
await _autoSleepTimerStartStorage.getInt(defaultValue: 1380);
_autoSleepTimerEnd =
await autoSleepTimerEndStorage.getInt(defaultValue: 360);
await _autoSleepTimerEndStorage.getInt(defaultValue: 360);
_autoPlay =
await autoPlayStorage.getBool(defaultValue: true, reverse: true);
_autoSleepTimerMode = await autoSleepTimerModeStorage.getInt();
await _autoPlayStorage.getBool(defaultValue: true, reverse: true);
_autoSleepTimerMode = await _autoSleepTimerModeStorage.getInt();
}
Future _getPlayerSeconds() async {
_rewindSeconds = await rewindSecondsStorage.getInt(defaultValue: 10);
_rewindSeconds = await _rewindSecondsStorage.getInt(defaultValue: 10);
_fastForwardSeconds =
await fastForwardSecondsStorage.getInt(defaultValue: 30);
await _fastForwardSecondsStorage.getInt(defaultValue: 30);
}
Future _getLocale() async {
var localeString = await localeStorage.getStringList();
var localeString = await _localeStorage.getStringList();
if (localeString.isEmpty) {
await findSystemLocale();
var systemLanCode;
@ -405,111 +437,119 @@ class SettingState extends ChangeNotifier {
}
Future<void> _getShowNotesFonts() async {
_showNotesFontIndex = await showNotesFontStorage.getInt(defaultValue: 1);
_showNotesFontIndex = await _showNotesFontStorage.getInt(defaultValue: 1);
}
Future<void> _saveAccentSetColor() async {
await accentStorage
await _accentStorage
.saveString(_accentSetColor.toString().substring(10, 16));
}
Future<void> _setRealDark() async {
await realDarkStorage.saveBool(_realDark);
await _realDarkStorage.saveBool(_realDark);
}
Future<void> _setOpenPlaylistDefault() async {
await _openPlaylistDefaultStorage.saveBool(_openPlaylistDefault);
}
Future<void> _setOpenAllPodcastDefault() async {
await _openAllPodcastDefaultStorage.saveBool(_openAllPodcastDefault);
}
Future<void> saveShowIntro(int i) async {
await introStorage.saveInt(i);
await _introStorage.saveInt(i);
}
Future<void> _saveUpdateInterval() async {
await intervalStorage.saveInt(_updateInterval);
await _intervalStorage.saveInt(_updateInterval);
}
Future<void> _saveTheme() async {
await themeStorage.saveInt(_theme.index);
await _themeStorage.saveInt(_theme.index);
}
Future<void> _saveAutoUpdate() async {
await autoupdateStorage.saveBool(_autoUpdate, reverse: true);
await _autoupdateStorage.saveBool(_autoUpdate, reverse: true);
}
Future<void> _saveAutoPlay() async {
await autoPlayStorage.saveBool(_autoPlay, reverse: true);
await _autoPlayStorage.saveBool(_autoPlay, reverse: true);
}
Future<void> _setDefaultSleepTimer() async {
await defaultSleepTimerStorage.saveInt(_defaultSleepTimer);
await _defaultSleepTimerStorage.saveInt(_defaultSleepTimer);
}
Future<void> _saveAutoSleepTimer() async {
await autoSleepTimerStorage.saveBool(_autoSleepTimer);
await _autoSleepTimerStorage.saveBool(_autoSleepTimer);
}
Future<void> _saveAutoSleepTimerMode() async {
await autoSleepTimerModeStorage.saveInt(_autoSleepTimerMode);
await _autoSleepTimerModeStorage.saveInt(_autoSleepTimerMode);
}
Future<void> _saveAutoSleepTimerStart() async {
await autoSleepTimerStartStorage.saveInt(_autoSleepTimerStart);
await _autoSleepTimerStartStorage.saveInt(_autoSleepTimerStart);
}
Future<void> _saveAutoSleepTimerEnd() async {
await autoSleepTimerEndStorage.saveInt(_autoSleepTimerEnd);
await _autoSleepTimerEndStorage.saveInt(_autoSleepTimerEnd);
}
Future<void> _saveFastForwardSeconds() async {
await fastForwardSecondsStorage.saveInt(_fastForwardSeconds);
await _fastForwardSecondsStorage.saveInt(_fastForwardSeconds);
}
Future<void> _saveRewindSeconds() async {
await rewindSecondsStorage.saveInt(_rewindSeconds);
await _rewindSecondsStorage.saveInt(_rewindSeconds);
}
Future<void> _saveShowNotesFonts() async {
await showNotesFontStorage.saveInt(_showNotesFontIndex);
await _showNotesFontStorage.saveInt(_showNotesFontIndex);
}
Future<SettingsBackup> backup() async {
var theme = await themeStorage.getInt();
var accentColor = await accentStorage.getString();
var realDark = await realDarkStorage.getBool(defaultValue: false);
var theme = await _themeStorage.getInt();
var accentColor = await _accentStorage.getString();
var realDark = await _realDarkStorage.getBool(defaultValue: false);
var autoPlay =
await autoPlayStorage.getBool(defaultValue: true, reverse: true);
await _autoPlayStorage.getBool(defaultValue: true, reverse: true);
var autoUpdate =
await autoupdateStorage.getBool(defaultValue: true, reverse: true);
var updateInterval = await intervalStorage.getInt();
var downloadUsingData = await downloadUsingDataStorage.getBool(
await _autoupdateStorage.getBool(defaultValue: true, reverse: true);
var updateInterval = await _intervalStorage.getInt();
var downloadUsingData = await _downloadUsingDataStorage.getBool(
defaultValue: true, reverse: true);
var cacheMax = await cacheStorage.getInt(defaultValue: 500 * 1024 * 1024);
var podcastLayout = await podcastLayoutStorage.getInt();
var recentLayout = await recentLayoutStorage.getInt();
var favLayout = await favLayoutStorage.getInt();
var downloadLayout = await downloadLayoutStorage.getInt();
var cacheMax = await _cacheStorage.getInt(defaultValue: 500 * 1024 * 1024);
var podcastLayout = await _podcastLayoutStorage.getInt();
var recentLayout = await _recentLayoutStorage.getInt();
var favLayout = await _favLayoutStorage.getInt();
var downloadLayout = await _downloadLayoutStorage.getInt();
var autoDownloadNetwork =
await autoDownloadStorage.getBool(defaultValue: false);
await _autoDownloadStorage.getBool(defaultValue: false);
var episodePopupMenu = await KeyValueStorage(episodePopupMenuKey).getMenu();
var autoDelete = await autoDeleteStorage.getInt();
var autoDelete = await _autoDeleteStorage.getInt();
var autoSleepTimer =
await autoSleepTimerStorage.getBool(defaultValue: false);
var autoSleepTimerStart = await autoSleepTimerStartStorage.getInt();
var autoSleepTimerEnd = await autoSleepTimerEndStorage.getInt();
var autoSleepTimerMode = await autoSleepTimerModeStorage.getInt();
var defaultSleepTime = await defaultSleepTimerStorage.getInt();
await _autoSleepTimerStorage.getBool(defaultValue: false);
var autoSleepTimerStart = await _autoSleepTimerStartStorage.getInt();
var autoSleepTimerEnd = await _autoSleepTimerEndStorage.getInt();
var autoSleepTimerMode = await _autoSleepTimerModeStorage.getInt();
var defaultSleepTime = await _defaultSleepTimerStorage.getInt();
var tapToOpenPopupMenu = await KeyValueStorage(tapToOpenPopupMenuKey)
.getBool(defaultValue: false);
var fastForwardSeconds =
await fastForwardSecondsStorage.getInt(defaultValue: 30);
var rewindSeconds = await rewindSecondsStorage.getInt(defaultValue: 10);
await _fastForwardSecondsStorage.getInt(defaultValue: 30);
var rewindSeconds = await _rewindSecondsStorage.getInt(defaultValue: 10);
var playerHeight =
await KeyValueStorage(playerHeightKey).getInt(defaultValue: 0);
var localeList = await localeStorage.getStringList();
var localeList = await _localeStorage.getStringList();
var backupLocale =
localeList.isEmpty ? '' : '${'${localeList.first}-'}${localeList[1]}';
var hideListened =
await KeyValueStorage(hideListenedKey).getBool(defaultValue: false);
var notificationLayout =
await KeyValueStorage(notificationLayoutKey).getInt(defaultValue: 0);
var showNotesFont = await showNotesFontStorage.getInt(defaultValue: 1);
var showNotesFont = await _showNotesFontStorage.getInt(defaultValue: 1);
var speedList = await KeyValueStorage(speedListKey).getStringList();
var hidePodcastDiscovery = await KeyValueStorage(hidePodcastDiscoveryKey)
.getBool(defaultValue: false);
@ -555,37 +595,37 @@ class SettingState extends ChangeNotifier {
}
Future<void> restore(SettingsBackup backup) async {
await themeStorage.saveInt(backup.theme);
await accentStorage.saveString(backup.accentColor);
await realDarkStorage.saveBool(backup.realDark);
await autoPlayStorage.saveBool(backup.autoPlay, reverse: true);
await autoupdateStorage.saveBool(backup.autoUpdate, reverse: true);
await intervalStorage.saveInt(backup.updateInterval);
await downloadUsingDataStorage.saveBool(backup.downloadUsingData,
await _themeStorage.saveInt(backup.theme);
await _accentStorage.saveString(backup.accentColor);
await _realDarkStorage.saveBool(backup.realDark);
await _autoPlayStorage.saveBool(backup.autoPlay, reverse: true);
await _autoupdateStorage.saveBool(backup.autoUpdate, reverse: true);
await _intervalStorage.saveInt(backup.updateInterval);
await _downloadUsingDataStorage.saveBool(backup.downloadUsingData,
reverse: true);
await cacheStorage.saveInt(backup.cacheMax);
await podcastLayoutStorage.saveInt(backup.podcastLayout);
await recentLayoutStorage.saveInt(backup.recentLayout);
await favLayoutStorage.saveInt(backup.favLayout);
await downloadLayoutStorage.saveInt(backup.downloadLayout);
await autoDownloadStorage.saveBool(backup.autoDownloadNetwork);
await _cacheStorage.saveInt(backup.cacheMax);
await _podcastLayoutStorage.saveInt(backup.podcastLayout);
await _recentLayoutStorage.saveInt(backup.recentLayout);
await _favLayoutStorage.saveInt(backup.favLayout);
await _downloadLayoutStorage.saveInt(backup.downloadLayout);
await _autoDownloadStorage.saveBool(backup.autoDownloadNetwork);
await KeyValueStorage(episodePopupMenuKey)
.saveStringList(backup.episodePopupMenu);
await autoDeleteStorage.saveInt(backup.autoDelete);
await autoSleepTimerStorage.saveBool(backup.autoSleepTimer);
await autoSleepTimerStartStorage.saveInt(backup.autoSleepTimerStart);
await autoSleepTimerEndStorage.saveInt(backup.autoSleepTimerEnd);
await autoSleepTimerModeStorage.saveInt(backup.autoSleepTimerMode);
await defaultSleepTimerStorage.saveInt(backup.defaultSleepTime);
await fastForwardSecondsStorage.saveInt(backup.fastForwardSeconds);
await rewindSecondsStorage.saveInt(backup.rewindSeconds);
await _autoDeleteStorage.saveInt(backup.autoDelete);
await _autoSleepTimerStorage.saveBool(backup.autoSleepTimer);
await _autoSleepTimerStartStorage.saveInt(backup.autoSleepTimerStart);
await _autoSleepTimerEndStorage.saveInt(backup.autoSleepTimerEnd);
await _autoSleepTimerModeStorage.saveInt(backup.autoSleepTimerMode);
await _defaultSleepTimerStorage.saveInt(backup.defaultSleepTime);
await _fastForwardSecondsStorage.saveInt(backup.fastForwardSeconds);
await _rewindSecondsStorage.saveInt(backup.rewindSeconds);
await KeyValueStorage(playerHeightKey).saveInt(backup.playerHeight);
await KeyValueStorage(tapToOpenPopupMenuKey)
.saveBool(backup.tapToOpenPopupMenu);
await KeyValueStorage(hideListenedKey).saveBool(backup.hideListened);
await KeyValueStorage(notificationLayoutKey)
.saveInt(backup.notificationLayout);
await showNotesFontStorage.saveInt(backup.showNotesFont);
await _showNotesFontStorage.saveInt(backup.showNotesFont);
await KeyValueStorage(speedListKey).saveStringList(backup.speedList);
await KeyValueStorage(markListenedAfterSkipKey)
.saveBool(backup.markListenedAfterSkip);
@ -593,7 +633,7 @@ class SettingState extends ChangeNotifier {
.saveBool(backup.deleteAfterPlayed);
if (backup.locale == '') {
await localeStorage.saveStringList([]);
await _localeStorage.saveStringList([]);
await S.load(Locale(Intl.systemLocale));
} else {
var localeList = backup.locale.split('-');
@ -603,7 +643,7 @@ class SettingState extends ChangeNotifier {
} else {
backupLocale = Locale(localeList.first, localeList[1]);
}
await localeStorage.saveStringList(
await _localeStorage.saveStringList(
[backupLocale.languageCode, backupLocale.countryCode]);
await S.load(backupLocale);
}

View File

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
//Slide Transition
class SlideLeftRoute extends PageRouteBuilder {
@override
Duration get transitionDuration => Duration(milliseconds: 300);
final Widget page;
SlideLeftRoute({this.page})
: super(
@ -17,23 +19,38 @@ class SlideLeftRoute extends PageRouteBuilder {
secondaryAnimation,
child,
) {
var begin = Offset(1.0, 0.0);
var end = Offset.zero;
var curve = Curves.easeOutQuart;
var tween =
Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
var tweenSequence = TweenSequence(<TweenSequenceItem<Offset>>[
TweenSequenceItem<Offset>(
tween: tween,
weight: 90.0,
),
TweenSequenceItem<Offset>(
tween: ConstantTween<Offset>(Offset.zero),
weight: 10.0,
),
]);
return SlideTransition(
position: animation.drive(tweenSequence),
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: child,
);
});
}
//Slide Transition
class SlideRightRoute extends PageRouteBuilder {
final Widget page;
SlideRightRoute({this.page})
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) =>
page,
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1, 0),
end: Offset.zero,
).animate(animation),
child: child,
);
});

View File

@ -200,7 +200,7 @@ class EpisodeCard extends StatelessWidget {
this.isPlaying,
this.canReorder = false,
Key key})
: super(key: key);
: assert(episode != null), super(key: key);
@override
Widget build(BuildContext context) {