Add localizely logo.

Tap logo in homepage to taggle dark mode.
Update open sorce libraries.
This commit is contained in:
stonegate 2020-07-16 17:35:01 +08:00
parent c5f2e4bdc1
commit 1d7d772323
19 changed files with 83 additions and 577 deletions

View File

@ -24,7 +24,7 @@ The podcasts search engine is powered by [ListenNotes](https://listennotes.com).
* Auto syncing in background * Auto syncing in background
* Listen and subscribe history record * Listen and subscribe history record
* Dark mode / Accent color * Dark mode / Accent color
* Download for offline playing * Download for offline play
* Auto download new episodes / Auto delete outdated downloads * Auto download new episodes / Auto delete outdated downloads
More to come... More to come...

BIN
assets/localizely_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -227,13 +227,13 @@ class MessageLookup extends MessageLookupByLibrary {
"settingsDefaultGridPodcast" : MessageLookupByLibrary.simpleMessage("Podcast page"), "settingsDefaultGridPodcast" : MessageLookupByLibrary.simpleMessage("Podcast page"),
"settingsDefaultGridRecent" : MessageLookupByLibrary.simpleMessage("Recent tab"), "settingsDefaultGridRecent" : MessageLookupByLibrary.simpleMessage("Recent tab"),
"settingsDiscovery" : MessageLookupByLibrary.simpleMessage("Discovery Features Again"), "settingsDiscovery" : MessageLookupByLibrary.simpleMessage("Discovery Features Again"),
"settingsEnableSyncing" : MessageLookupByLibrary.simpleMessage("Enable Syncing"), "settingsEnableSyncing" : MessageLookupByLibrary.simpleMessage("Enable syncing"),
"settingsEnableSyncingDes" : MessageLookupByLibrary.simpleMessage("Refresh all podcasts in the background to get leatest episodes"), "settingsEnableSyncingDes" : MessageLookupByLibrary.simpleMessage("Refresh all podcasts in the background to get leatest episodes"),
"settingsExportDes" : MessageLookupByLibrary.simpleMessage("Export and import app settings"), "settingsExportDes" : MessageLookupByLibrary.simpleMessage("Export and import app settings"),
"settingsFeedback" : MessageLookupByLibrary.simpleMessage("Feedback"), "settingsFeedback" : MessageLookupByLibrary.simpleMessage("Feedback"),
"settingsFeedbackDes" : MessageLookupByLibrary.simpleMessage("Bugs and features request"), "settingsFeedbackDes" : MessageLookupByLibrary.simpleMessage("Bugs and features request"),
"settingsHistory" : MessageLookupByLibrary.simpleMessage("History"), "settingsHistory" : MessageLookupByLibrary.simpleMessage("History"),
"settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("Listen date"), "settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("Listen data"),
"settingsInfo" : MessageLookupByLibrary.simpleMessage("Info"), "settingsInfo" : MessageLookupByLibrary.simpleMessage("Info"),
"settingsInterface" : MessageLookupByLibrary.simpleMessage("Interface"), "settingsInterface" : MessageLookupByLibrary.simpleMessage("Interface"),
"settingsLanguages" : MessageLookupByLibrary.simpleMessage("Languages"), "settingsLanguages" : MessageLookupByLibrary.simpleMessage("Languages"),
@ -248,7 +248,7 @@ class MessageLookup extends MessageLookupByLibrary {
"settingsNetworkCellular" : MessageLookupByLibrary.simpleMessage("Ask before using cellular data"), "settingsNetworkCellular" : MessageLookupByLibrary.simpleMessage("Ask before using cellular data"),
"settingsNetworkCellularAuto" : MessageLookupByLibrary.simpleMessage("Auto download using cellular data"), "settingsNetworkCellularAuto" : MessageLookupByLibrary.simpleMessage("Auto download using cellular data"),
"settingsNetworkCellularAutoDes" : MessageLookupByLibrary.simpleMessage("You can set podcast auto download in group manage page"), "settingsNetworkCellularAutoDes" : MessageLookupByLibrary.simpleMessage("You can set podcast auto download in group manage page"),
"settingsNetworkCellularDes" : MessageLookupByLibrary.simpleMessage("Ask to confirm when using cellulae data to download episodes"), "settingsNetworkCellularDes" : MessageLookupByLibrary.simpleMessage("Ask to confirm when using cellular data to download episodes"),
"settingsPlayDes" : MessageLookupByLibrary.simpleMessage("Playlist and player"), "settingsPlayDes" : MessageLookupByLibrary.simpleMessage("Playlist and player"),
"settingsPopupMenu" : MessageLookupByLibrary.simpleMessage("Episodes popup menu"), "settingsPopupMenu" : MessageLookupByLibrary.simpleMessage("Episodes popup menu"),
"settingsPopupMenuDes" : MessageLookupByLibrary.simpleMessage("Change the popup menu of episode"), "settingsPopupMenuDes" : MessageLookupByLibrary.simpleMessage("Change the popup menu of episode"),
@ -283,6 +283,7 @@ class MessageLookup extends MessageLookupByLibrary {
"toastFileError" : MessageLookupByLibrary.simpleMessage("File error, subscribe failed"), "toastFileError" : MessageLookupByLibrary.simpleMessage("File error, subscribe failed"),
"toastFileNotValid" : MessageLookupByLibrary.simpleMessage("File not valid"), "toastFileNotValid" : MessageLookupByLibrary.simpleMessage("File not valid"),
"toastHomeGroupNotSupport" : MessageLookupByLibrary.simpleMessage("Home group is not supported"), "toastHomeGroupNotSupport" : MessageLookupByLibrary.simpleMessage("Home group is not supported"),
"toastImportSettingsSuccess" : MessageLookupByLibrary.simpleMessage("Import settings successfully"),
"toastOneGroup" : MessageLookupByLibrary.simpleMessage("At least select one group"), "toastOneGroup" : MessageLookupByLibrary.simpleMessage("At least select one group"),
"toastPodcastRecovering" : MessageLookupByLibrary.simpleMessage("Recovering, wait for a moment"), "toastPodcastRecovering" : MessageLookupByLibrary.simpleMessage("Recovering, wait for a moment"),
"toastReadFile" : MessageLookupByLibrary.simpleMessage("Read file successfully"), "toastReadFile" : MessageLookupByLibrary.simpleMessage("Read file successfully"),

View File

@ -233,7 +233,7 @@ class MessageLookup extends MessageLookupByLibrary {
"settingsFeedback" : MessageLookupByLibrary.simpleMessage("反馈"), "settingsFeedback" : MessageLookupByLibrary.simpleMessage("反馈"),
"settingsFeedbackDes" : MessageLookupByLibrary.simpleMessage("意见与建议"), "settingsFeedbackDes" : MessageLookupByLibrary.simpleMessage("意见与建议"),
"settingsHistory" : MessageLookupByLibrary.simpleMessage("历史记录"), "settingsHistory" : MessageLookupByLibrary.simpleMessage("历史记录"),
"settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("播放日期"), "settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("收听记录"),
"settingsInfo" : MessageLookupByLibrary.simpleMessage("信息"), "settingsInfo" : MessageLookupByLibrary.simpleMessage("信息"),
"settingsInterface" : MessageLookupByLibrary.simpleMessage("界面"), "settingsInterface" : MessageLookupByLibrary.simpleMessage("界面"),
"settingsLanguages" : MessageLookupByLibrary.simpleMessage("语言"), "settingsLanguages" : MessageLookupByLibrary.simpleMessage("语言"),
@ -283,6 +283,7 @@ class MessageLookup extends MessageLookupByLibrary {
"toastFileError" : MessageLookupByLibrary.simpleMessage("文件错误,导入失败"), "toastFileError" : MessageLookupByLibrary.simpleMessage("文件错误,导入失败"),
"toastFileNotValid" : MessageLookupByLibrary.simpleMessage("文件错误"), "toastFileNotValid" : MessageLookupByLibrary.simpleMessage("文件错误"),
"toastHomeGroupNotSupport" : MessageLookupByLibrary.simpleMessage("Home 分组不支持此功能"), "toastHomeGroupNotSupport" : MessageLookupByLibrary.simpleMessage("Home 分组不支持此功能"),
"toastImportSettingsSuccess" : MessageLookupByLibrary.simpleMessage("导入设置成功"),
"toastOneGroup" : MessageLookupByLibrary.simpleMessage("请至少选择一个分组"), "toastOneGroup" : MessageLookupByLibrary.simpleMessage("请至少选择一个分组"),
"toastPodcastRecovering" : MessageLookupByLibrary.simpleMessage("恢复中,请稍后"), "toastPodcastRecovering" : MessageLookupByLibrary.simpleMessage("恢复中,请稍后"),
"toastReadFile" : MessageLookupByLibrary.simpleMessage("读取文件成功"), "toastReadFile" : MessageLookupByLibrary.simpleMessage("读取文件成功"),

View File

@ -1559,10 +1559,10 @@ class S {
); );
} }
/// `Enable Syncing` /// `Enable syncing`
String get settingsEnableSyncing { String get settingsEnableSyncing {
return Intl.message( return Intl.message(
'Enable Syncing', 'Enable syncing',
name: 'settingsEnableSyncing', name: 'settingsEnableSyncing',
desc: '', desc: '',
args: [], args: [],
@ -1619,10 +1619,10 @@ class S {
); );
} }
/// `Listen date` /// `Listen data`
String get settingsHistoryDes { String get settingsHistoryDes {
return Intl.message( return Intl.message(
'Listen date', 'Listen data',
name: 'settingsHistoryDes', name: 'settingsHistoryDes',
desc: '', desc: '',
args: [], args: [],
@ -1769,10 +1769,10 @@ class S {
); );
} }
/// `Ask to confirm when using cellulae data to download episodes` /// `Ask to confirm when using cellular data to download episodes`
String get settingsNetworkCellularDes { String get settingsNetworkCellularDes {
return Intl.message( return Intl.message(
'Ask to confirm when using cellulae data to download episodes', 'Ask to confirm when using cellular data to download episodes',
name: 'settingsNetworkCellularDes', name: 'settingsNetworkCellularDes',
desc: '', desc: '',
args: [], args: [],
@ -2129,6 +2129,16 @@ class S {
); );
} }
/// `Import settings successfully`
String get toastImportSettingsSuccess {
return Intl.message(
'Import settings successfully',
name: 'toastImportSettingsSuccess',
desc: '',
args: [],
);
}
/// `At least select one group` /// `At least select one group`
String get toastOneGroup { String get toastOneGroup {
return Intl.message( return Intl.message(

View File

@ -6,7 +6,7 @@ import 'package:line_icons/line_icons.dart';
import '../util/context_extension.dart'; import '../util/context_extension.dart';
const String version = '0.4.0'; const String version = '0.4.5';
class AboutApp extends StatelessWidget { class AboutApp extends StatelessWidget {
_launchUrl(String url) async { _launchUrl(String url) async {

View File

@ -20,11 +20,12 @@ import '../util/context_extension.dart';
import '../util/custompaint.dart'; import '../util/custompaint.dart';
import '../state/download_state.dart'; import '../state/download_state.dart';
import '../state/podcast_group.dart'; import '../state/podcast_group.dart';
import '../state/setting_state.dart';
import 'playlist.dart'; import 'playlist.dart';
import 'import_ompl.dart'; import 'import_ompl.dart';
import 'audioplayer.dart'; import 'audioplayer.dart';
import 'addpodcast.dart'; import 'addpodcast.dart';
import 'popupmenu.dart'; import 'home_menu.dart';
import 'home_groups.dart'; import 'home_groups.dart';
import 'download_list.dart'; import 'download_list.dart';
@ -89,6 +90,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
Widget build(BuildContext context) { Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width; double width = MediaQuery.of(context).size.width;
double height = (width - 20) / 3 + 140; double height = (width - 20) / 3 + 140;
var settings = Provider.of<SettingState>(context, listen: false);
final s = context.s; final s = context.s;
return AnnotatedRegion<SystemUiOverlayStyle>( return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle( value: SystemUiOverlayStyle(
@ -195,14 +197,25 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
}, },
), ),
), ),
Image( GestureDetector(
image: Theme.of(context) onTap: () => {
.brightness == Theme.of(context).brightness ==
Brightness.light Brightness.light
? AssetImage('assets/text.png') ? settings.setTheme =
: AssetImage( ThemeMode.dark
'assets/text_light.png'), : settings.setTheme =
height: 30, ThemeMode.light
},
child: Image(
image: Theme.of(context)
.brightness ==
Brightness.light
? AssetImage(
'assets/text.png')
: AssetImage(
'assets/text_light.png'),
height: 30,
),
), ),
DescribedFeatureOverlay( DescribedFeatureOverlay(
featureId: menuFeature, featureId: menuFeature,

View File

@ -1,69 +0,0 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
import '../util/context_extension.dart';
class ClipPreview extends StatefulWidget {
final String filePath;
ClipPreview({this.filePath, Key key}) : super(key: key);
@override
_ClipPreviewState createState() => _ClipPreviewState();
}
class _ClipPreviewState extends State<ClipPreview> {
VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.file(File(widget.filePath))
..initialize().then((_) {
setState(() {});
});
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Brightness.light,
systemNavigationBarColor: Colors.black,
systemNavigationBarIconBrightness: Brightness.dark,
),
child: Scaffold(
appBar: AppBar(backgroundColor: Colors.black),
backgroundColor: Colors.black,
body: Center(
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
backgroundColor: context.accentColor,
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
}
}

View File

@ -1,469 +0,0 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:line_icons/line_icons.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:tsacdop/home/preview.dart';
import 'package:wc_flutter_share/wc_flutter_share.dart';
import 'package:tuple/tuple.dart';
import '../state/audio_state.dart';
import '../util/context_extension.dart';
import '../util/custom_slider.dart';
import '../util/pageroute.dart';
final List<BoxShadow> _customShadow = [
BoxShadow(blurRadius: 26, offset: Offset(-6, -6), color: Colors.white),
BoxShadow(
blurRadius: 8,
offset: Offset(2, 2),
color: Colors.grey[600].withOpacity(0.4))
];
final List<BoxShadow> _customShadowNight = [
BoxShadow(
blurRadius: 6,
offset: Offset(-1, -1),
color: Colors.grey[100].withOpacity(0.3)),
BoxShadow(blurRadius: 8, offset: Offset(2, 2), color: Colors.black)
];
String _stringForSeconds(int seconds) {
if (seconds == null) return null;
return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
}
class ShareClip extends StatefulWidget {
ShareClip({Key key}) : super(key: key);
@override
_ShareClipState createState() => _ShareClipState();
}
class _ShareClipState extends State<ShareClip> {
int _durationSelected;
int _startPosition;
bool _startConfirm;
List<int> _durationToSelect = [30, 60, 90, 120];
Widget _animatedWidget;
Widget _toastWidget;
@override
void initState() {
super.initState();
_durationSelected = 60;
_startPosition = 0;
_startConfirm = false;
_animatedWidget = Center();
_toastWidget = Center();
}
_formatSeconds(int s) {
switch (s) {
case 30:
return "30sec";
break;
case 60:
return "1min";
break;
case 90:
return "90sec";
break;
case 120:
return "2min";
break;
default:
return '';
break;
}
}
_setShareButton(ShareStatus status, String filePath) {
switch (status) {
case ShareStatus.generate:
_animatedWidget = Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
)),
Padding(
padding: EdgeInsets.symmetric(horizontal: 2),
),
Text('Clipping'),
],
);
_toastWidget = Text('May take one minute',
style: TextStyle(color: const Color(0xff67727d)));
break;
case ShareStatus.download:
_animatedWidget = Text('Loading');
break;
case ShareStatus.complete:
_animatedWidget = Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.share),
Padding(
padding: EdgeInsets.symmetric(horizontal: 2),
),
Text('Share'),
],
);
_toastWidget = Row(
children: [
Text('Preview'),
IconButton(
icon: Icon(LineIcons.play_solid),
onPressed: () {
if (filePath != '')
Navigator.push(
context,
SlideLeftRoute(
page: ClipPreview(
filePath: filePath,
)),
);
}),
],
);
break;
case ShareStatus.undefined:
_animatedWidget = Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(LineIcons.cut_solid),
Padding(
padding: EdgeInsets.symmetric(horizontal: 2),
),
Text('Clip')
],
);
_toastWidget = Center();
break;
case ShareStatus.error:
_animatedWidget = Text('Retry');
_toastWidget = Text('Something wrong happened');
break;
}
}
@override
Widget build(BuildContext context) {
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
return Container(
height: 300,
width: double.infinity,
color: context.primaryColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 20.0),
height: 60.0,
// color: context.primaryColorDark,
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 20.0),
height: 20.0,
// color: context.primaryColorDark,
alignment: Alignment.centerLeft,
child: Text(
'Share Clip',
style: TextStyle(
color: Theme.of(context).accentColor,
fontWeight: FontWeight.bold,
fontSize: 16),
),
),
Spacer(),
Selector<AudioPlayerNotifier, Tuple2<ShareStatus, String>>(
selector: (_, audio) =>
Tuple2(audio.shareStatus, audio.shareFile ?? ''),
builder: (_, data, __) {
_setShareButton(data.item1, data.item2);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedSwitcher(
transitionBuilder: (child, animation) =>
ScaleTransition(scale: animation, child: child),
duration: Duration(milliseconds: 500),
child: _toastWidget),
Container(
margin: EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.center,
height: 40,
width: 120,
decoration: BoxDecoration(
color: context.primaryColor,
borderRadius:
BorderRadius.all(Radius.circular(20)),
border: Border.all(
color: Theme.of(context).brightness ==
Brightness.dark
? Colors.black12
: Colors.white10,
width: 1),
boxShadow: Theme.of(context).brightness ==
Brightness.dark
? _customShadowNight
: _customShadow),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.all(Radius.circular(15)),
onTap: () async {
if (data.item1 == ShareStatus.undefined ||
data.item1 ==
ShareStatus.error) if (_startConfirm)
audio.shareClip(
_startPosition, _durationSelected);
else
Fluttertoast.showToast(
msg: 'Please confirm start position',
gravity: ToastGravity.BOTTOM,
);
else if (data.item1 == ShareStatus.complete) {
File file = File(data.item2);
final Uint8List bytes =
await file.readAsBytes();
await WcFlutterShare.share(
sharePopupTitle: 'share Clip',
fileName: data.item2.split('/').last,
mimeType: 'video/mp4',
bytesOfFile: bytes.buffer.asUint8List());
audio.setShareStatue = ShareStatus.undefined;
}
},
child: SizedBox(
height: 40,
width: 100,
child: Center(
child: AnimatedSwitcher(
transitionBuilder: (child, animation) =>
ScaleTransition(
scale: animation, child: child),
duration: Duration(milliseconds: 700),
child: _animatedWidget)),
),
),
),
),
],
);
},
),
],
),
),
Consumer<AudioPlayerNotifier>(builder: (_, data, __) {
return Container(
padding: EdgeInsets.only(top: 5, left: 10, right: 10),
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor:
Theme.of(context).brightness == Brightness.dark
? Colors.black38
: Colors.grey[400],
inactiveTrackColor: Theme.of(context).primaryColorDark,
trackHeight: 20.0,
trackShape: MyRectangularTrackShape(),
thumbColor: Theme.of(context).accentColor,
thumbShape: MyRoundSliderThumpShape(
enabledThumbRadius: 10.0,
disabledThumbRadius: 10.0,
thumbCenterColor: context.accentColor),
overlayColor: Theme.of(context).accentColor.withAlpha(32),
overlayShape: RoundSliderOverlayShape(overlayRadius: 4.0),
),
child: Slider(
value: data.seekSliderValue,
onChanged: (double val) {
audio.sliderSeek(val);
}),
),
);
}),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 150,
width: 200,
child: Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Center(
child: Selector<AudioPlayerNotifier, int>(
selector: (_, audio) => audio.backgroundAudioPosition,
builder: (_, position, __) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Text.rich(
TextSpan(
text: 'Start at \n',
style:
TextStyle(color: context.accentColor),
children: [
TextSpan(
text: !_startConfirm
? _stringForSeconds(
position ~/ 1000)
: _stringForSeconds(
_startPosition),
style: context.textTheme.headline5
.copyWith(
color: _startConfirm
? context.accentColor
: null)),
]),
textAlign: TextAlign.center,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
padding: EdgeInsets.symmetric(
horizontal: 10.0),
onPressed: () => audio.forwardAudio(-30),
iconSize: 25.0,
icon: Icon(Icons.replay_30),
color: Colors.grey[500]),
InkWell(
onTap: () => setState(() {
if (!_startConfirm)
_startPosition = position ~/ 1000;
_startConfirm = !_startConfirm;
}),
child: Container(
margin: EdgeInsets.all(10.0),
decoration: BoxDecoration(
boxShadow: !_startConfirm
? (context.brightness ==
Brightness.dark)
? _customShadowNight
: _customShadow
: null,
color: _startConfirm
? Theme.of(context).accentColor
: Theme.of(context).primaryColor,
shape: BoxShape.circle),
alignment: Alignment.center,
width: 40,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
LineIcons.thumbtack_solid,
color: _startConfirm
? Colors.white
: null,
)),
),
),
IconButton(
padding: EdgeInsets.symmetric(
horizontal: 10.0),
onPressed: () => audio.forwardAudio(10),
iconSize: 25.0,
icon: Icon(Icons.forward_10),
color: Colors.grey[500]),
],
),
],
);
},
),
),
),
),
Container(
height: 100,
width: 2,
color: context.primaryColorDark,
),
SizedBox(
height: 150,
width: 200,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Center(
child: Wrap(
direction: Axis.horizontal,
children: _durationToSelect
.map<Widget>((e) => InkWell(
onTap: () =>
setState(() => _durationSelected = e),
child: Container(
margin: EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(15)),
boxShadow: e != _durationSelected
? (context.brightness ==
Brightness.dark)
? _customShadowNight
: _customShadow
: null,
color: (e == _durationSelected)
? Theme.of(context).accentColor
: Theme.of(context).primaryColor,
),
alignment: Alignment.center,
width: 70,
height: 30,
child: Text(_formatSeconds(e),
style: TextStyle(
fontWeight: FontWeight.bold,
color: (e == _durationSelected)
? Colors.white
: null)),
),
))
.toList(),
),
)),
),
],
),
),
Container(
height: 20,
padding: EdgeInsets.symmetric(horizontal: 20),
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('experimental'),
Icon(
LineIcons.info_circle_solid,
size: 20.0,
color: context.accentColor,
),
],
),
),
),
],
),
);
}
}

View File

@ -355,7 +355,7 @@
"@settingsDefaultGridRecent": {}, "@settingsDefaultGridRecent": {},
"settingsDiscovery": "Discovery Features Again", "settingsDiscovery": "Discovery Features Again",
"@settingsDiscovery": {}, "@settingsDiscovery": {},
"settingsEnableSyncing": "Enable Syncing", "settingsEnableSyncing": "Enable syncing",
"@settingsEnableSyncing": {}, "@settingsEnableSyncing": {},
"settingsEnableSyncingDes": "Refresh all podcasts in the background to get leatest episodes", "settingsEnableSyncingDes": "Refresh all podcasts in the background to get leatest episodes",
"@settingsEnableSyncingDes": {}, "@settingsEnableSyncingDes": {},
@ -367,7 +367,7 @@
"@settingsFeedbackDes": {}, "@settingsFeedbackDes": {},
"settingsHistory": "History", "settingsHistory": "History",
"@settingsHistory": {}, "@settingsHistory": {},
"settingsHistoryDes": "Listen date", "settingsHistoryDes": "Listen data",
"@settingsHistoryDes": {}, "@settingsHistoryDes": {},
"settingsInfo": "Info", "settingsInfo": "Info",
"@settingsInfo": {}, "@settingsInfo": {},
@ -397,7 +397,7 @@
"@settingsNetworkCellularAuto": {}, "@settingsNetworkCellularAuto": {},
"settingsNetworkCellularAutoDes": "You can set podcast auto download in group manage page", "settingsNetworkCellularAutoDes": "You can set podcast auto download in group manage page",
"@settingsNetworkCellularAutoDes": {}, "@settingsNetworkCellularAutoDes": {},
"settingsNetworkCellularDes": "Ask to confirm when using cellulae data to download episodes", "settingsNetworkCellularDes": "Ask to confirm when using cellular data to download episodes",
"@settingsNetworkCellularDes": {}, "@settingsNetworkCellularDes": {},
"settingsPlayDes": "Playlist and player", "settingsPlayDes": "Playlist and player",
"@settingsPlayDes": {}, "@settingsPlayDes": {},
@ -481,6 +481,8 @@
"@toastFileNotValid": {}, "@toastFileNotValid": {},
"toastHomeGroupNotSupport": "Home group is not supported", "toastHomeGroupNotSupport": "Home group is not supported",
"@toastHomeGroupNotSupport": {}, "@toastHomeGroupNotSupport": {},
"toastImportSettingsSuccess": "Import settings successfully",
"@toastImportSettingsSuccess": {},
"toastOneGroup": "At least select one group", "toastOneGroup": "At least select one group",
"@toastOneGroup": {}, "@toastOneGroup": {},
"toastPodcastRecovering": "Recovering, wait for a moment", "toastPodcastRecovering": "Recovering, wait for a moment",

View File

@ -367,7 +367,7 @@
"@settingsFeedbackDes": {}, "@settingsFeedbackDes": {},
"settingsHistory": "历史记录", "settingsHistory": "历史记录",
"@settingsHistory": {}, "@settingsHistory": {},
"settingsHistoryDes": "播放日期", "settingsHistoryDes": "收听记录",
"@settingsHistoryDes": {}, "@settingsHistoryDes": {},
"settingsInfo": "信息", "settingsInfo": "信息",
"@settingsInfo": {}, "@settingsInfo": {},
@ -481,6 +481,8 @@
"@toastFileNotValid": {}, "@toastFileNotValid": {},
"toastHomeGroupNotSupport": "Home 分组不支持此功能", "toastHomeGroupNotSupport": "Home 分组不支持此功能",
"@toastHomeGroupNotSupport": {}, "@toastHomeGroupNotSupport": {},
"toastImportSettingsSuccess": "导入设置成功",
"@toastImportSettingsSuccess": {},
"toastOneGroup": "请至少选择一个分组", "toastOneGroup": "请至少选择一个分组",
"@toastOneGroup": {}, "@toastOneGroup": {},
"toastPodcastRecovering": "恢复中,请稍后", "toastPodcastRecovering": "恢复中,请稍后",

View File

@ -64,7 +64,7 @@ class _DataBackupState extends State<DataBackup> {
now.day.toString() + now.day.toString() +
now.second.toString(); now.second.toString();
var file = File(join(tempdir.path, 'tsacdop_settings_$datePlus.json')); var file = File(join(tempdir.path, 'tsacdop_settings_$datePlus.json'));
await file.writeAsString(json.toString()); await file.writeAsString(jsonEncode(json));
return file; return file;
} }
@ -76,11 +76,15 @@ class _DataBackupState extends State<DataBackup> {
String json = file.readAsStringSync(); String json = file.readAsStringSync();
SettingsBackup backup = SettingsBackup.fromJson(jsonDecode(json)); SettingsBackup backup = SettingsBackup.fromJson(jsonDecode(json));
await settings.restore(backup); await settings.restore(backup);
Fluttertoast.showToast(
msg: s.toastImportSettingsSuccess,
gravity: ToastGravity.BOTTOM,
);
} catch (e) { } catch (e) {
print(e); print(e);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: s.toastFileError, msg: s.toastFileError,
gravity: ToastGravity.TOP, gravity: ToastGravity.BOTTOM,
); );
} }
} }
@ -95,7 +99,7 @@ class _DataBackupState extends State<DataBackup> {
print('File Path' + filePath); print('File Path' + filePath);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: s.toastReadFile, msg: s.toastReadFile,
gravity: ToastGravity.TOP, gravity: ToastGravity.BOTTOM,
); );
_importSetting(filePath, context); _importSetting(filePath, context);
} on PlatformException catch (e) { } on PlatformException catch (e) {
@ -262,7 +266,7 @@ class _DataBackupState extends State<DataBackup> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( Icon(
LineIcons.file_import_solid, LineIcons.paperclip_solid,
size: context.textTheme.headline6.fontSize, size: context.textTheme.headline6.fontSize,
color: Colors.red[700], color: Colors.red[700],
), ),

View File

@ -95,12 +95,21 @@ class _LanguagesSettingState extends State<LanguagesSetting> {
onTap: () => _launchUrl( onTap: () => _launchUrl(
'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop localization project'), 'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop localization project'),
contentPadding: const EdgeInsets.only(left: 75, right: 20), contentPadding: const EdgeInsets.only(left: 75, right: 20),
title: Align(
alignment: Alignment.centerLeft,
child: Image(
image: Theme.of(context).brightness ==
Brightness.light
? AssetImage('assets/localizely_logo.png')
: AssetImage('assets/localizely_logo_light.png'),
height: 20),
),
subtitle: Text( subtitle: Text(
"If you'd like to contribute to support more languages, please contact me."), "If you'd like to contribute to support more languages, please contact me."),
trailing: IconButton( // trailing: IconButton(
icon: Icon(LineIcons.heart), // icon: Icon(LineIcons.heart),
onPressed: () => _launchUrl( // onPressed: () => _launchUrl(
'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop localization project')), // 'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop localization project')),
), ),
], ],
))), ))),

View File

@ -70,5 +70,8 @@ List<Libries> plugins = [
Libries('flutter_isolate', mit, 'https://pub.dev/packages/flutter_isolate'), Libries('flutter_isolate', mit, 'https://pub.dev/packages/flutter_isolate'),
Libries('auto_animated', mit, 'https://pub.dev/packages/auto_animated'), Libries('auto_animated', mit, 'https://pub.dev/packages/auto_animated'),
Libries('wc_flutter_share', apacheLicense, Libries('wc_flutter_share', apacheLicense,
'https://pub.dev/packages/wc_flutter_share') 'https://pub.dev/packages/wc_flutter_share'),
Libries('flutter_time_picker_spinner', 'unknow',
'https://pub.dev/packages/flutter_time_picker_spinner'),
Libries('focused_menu', mit, 'https://pub.dev/packages/focused_menu')
]; ];

View File

@ -782,7 +782,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
if (_playing == null) { if (_playing == null) {
_playing = true; _playing = true;
int cacheMax = int cacheMax =
await cacheStorage.getInt(defaultValue: 500 * 1024 * 1024); await cacheStorage.getInt(defaultValue: 200 * 1024 * 1024);
// await AudioServiceBackground.setQueue(_queue); // await AudioServiceBackground.setQueue(_queue);
await _audioPlayer.setUrl(mediaItem.id, cacheMax); await _audioPlayer.setUrl(mediaItem.id, cacheMax);

View File

@ -94,8 +94,8 @@ class EpisodeGrid extends StatelessWidget {
Future<bool> _getTapToOpenPopupMenu() async { Future<bool> _getTapToOpenPopupMenu() async {
KeyValueStorage tapToOpenPopupMenuStorage = KeyValueStorage tapToOpenPopupMenuStorage =
KeyValueStorage(tapToOpenPopupMenuKey); KeyValueStorage(tapToOpenPopupMenuKey);
int boo = await tapToOpenPopupMenuStorage.getInt(defaultValue: 0); bool boo = await tapToOpenPopupMenuStorage.getBool(defaultValue: false);
return boo == 1; return boo;
} }
_markListened(EpisodeBrief episode) async { _markListened(EpisodeBrief episode) async {

View File

@ -1,7 +1,7 @@
name: tsacdop name: tsacdop
description: An easy-use podacasts player. description: An easy-use podacasts player.
version: 0.4.0+20 version: 0.4.5+21
environment: environment:
sdk: ">=2.6.0 <3.0.0" sdk: ">=2.6.0 <3.0.0"
@ -42,7 +42,6 @@ dependencies:
flare_flutter: ^2.0.5 flare_flutter: ^2.0.5
rxdart: ^0.24.0 rxdart: ^0.24.0
wc_flutter_share: ^0.2.1 wc_flutter_share: ^0.2.1
video_player: ^0.10.11
auto_animated: ^2.1.0 auto_animated: ^2.1.0
feature_discovery: ^0.10.0 feature_discovery: ^0.10.0
flutter_isolate: ^1.0.0+14 flutter_isolate: ^1.0.0+14