diff --git a/lib/class/settingstate.dart b/lib/class/settingstate.dart index c99d7dc..74cd578 100644 --- a/lib/class/settingstate.dart +++ b/lib/class/settingstate.dart @@ -25,6 +25,29 @@ void callbackDispatcher() { }); } +ThemeData lightTheme = ThemeData( + accentColorBrightness: Brightness.dark, + primaryColor: Colors.grey[100], + // accentColor: _accentSetColor, + primaryColorLight: Colors.white, + primaryColorDark: Colors.grey[300], + dialogBackgroundColor: Colors.white, + backgroundColor: Colors.grey[100], + appBarTheme: AppBarTheme( + color: Colors.grey[100], + elevation: 0, + ), + textTheme: TextTheme( + bodyText2: TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal), + ), + tabBarTheme: TabBarTheme( + labelColor: Colors.black, + unselectedLabelColor: Colors.grey[400], + ), +); + + + class SettingState extends ChangeNotifier { KeyValueStorage themeStorage = KeyValueStorage(themesKey); KeyValueStorage accentStorage = KeyValueStorage(accentsKey); diff --git a/lib/home/appbar/addpodcast.dart b/lib/home/appbar/addpodcast.dart index e77b84c..40c996e 100644 --- a/lib/home/appbar/addpodcast.dart +++ b/lib/home/appbar/addpodcast.dart @@ -12,80 +12,14 @@ import 'package:fluttertoast/fluttertoast.dart'; import '../../class/searchpodcast.dart'; import '../../class/subscribe_podcast.dart'; -import '../../home/appbar/popupmenu.dart'; import '../../util/context_extension.dart'; import '../../webfeed/webfeed.dart'; import '../../.env.dart'; -import '../nested_home.dart'; -class MyHomePage extends StatefulWidget { - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - final _MyHomePageDelegate _delegate = _MyHomePageDelegate(); - final GlobalKey _scaffoldKey = GlobalKey(); - - var _androidAppRetain = MethodChannel("android_app_retain"); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarIconBrightness: Theme.of(context).accentColorBrightness, - systemNavigationBarIconBrightness: - Theme.of(context).accentColorBrightness, - systemNavigationBarColor: Theme.of(context).primaryColor, - // statusBarColor: Theme.of(context).primaryColor, - ), - child: Scaffold( - key: _scaffoldKey, - appBar: AppBar( - //elevation: 1.0, - centerTitle: true, - leading: IconButton( - tooltip: 'Add', - icon: const Icon(Icons.add_circle_outline), - onPressed: () async { - await showSearch( - context: context, - delegate: _delegate, - ); - }, - ), - title: Image( - image: Theme.of(context).brightness == Brightness.light - ? AssetImage('assets/text.png') - : AssetImage('assets/text_light.png'), - height: 30, - ), - actions: [ - PopupMenu(), - ], - ), - body: WillPopScope( - onWillPop: () async { - if (Platform.isAndroid) { - _androidAppRetain.invokeMethod('sendToBackground'); - return false; - } else { - return true; - } - }, - child: Home(), - ), - ), - ); - } -} - -class _MyHomePageDelegate extends SearchDelegate { +class MyHomePageDelegate extends SearchDelegate { + final String searchFieldLabel; + MyHomePageDelegate({this.searchFieldLabel}) + : super(searchFieldLabel: searchFieldLabel); static Future getList(String searchText) async { String apiKey = environment['apiKey']; String url = @@ -329,89 +263,6 @@ class _SearchResultState extends State subscribeWorker.setSubscribeItem(item); } - // savePodcast(String rss) async { - // if (mounted) setState(() => _adding = true); - - // importOmpl.importState = ImportState.import; - // try { - // BaseOptions options = new BaseOptions( - // connectTimeout: 30000, - // receiveTimeout: 30000, - // ); - // Response response = await Dio(options).get(rss); - // var dbHelper = DBHelper(); - // String _realUrl = response.realUri.toString(); - - // bool _checkUrl = await dbHelper.checkPodcast(_realUrl); - - // if (_checkUrl) { - // if (mounted) setState(() => _issubscribe = true); - - // var _p = RssFeed.parse(response.data); - - // print(_p.title); - - // var dir = await getApplicationDocumentsDirectory(); - - // Response> imageResponse = await Dio().get>( - // _p.itunes.image.href, - // options: Options(responseType: ResponseType.bytes)); - - // img.Image image = img.decodeImage(imageResponse.data); - // img.Image thumbnail = img.copyResize(image, width: 300); - - // String _uuid = Uuid().v4(); - // File("${dir.path}/$_uuid.png") - // ..writeAsBytesSync(img.encodePng(thumbnail)); - - // String _imagePath = "${dir.path}/$_uuid.png"; - // String _primaryColor = await getColor(File("${dir.path}/$_uuid.png")); - // String _author = _p.itunes.author ?? _p.author ?? ''; - // String _provider = _p.generator ?? ''; - // String _link = _p.link ?? ''; - // PodcastLocal podcastLocal = PodcastLocal( - // _p.title, - // _p.itunes.image.href, - // _realUrl, - // _primaryColor, - // _author, - // _uuid, - // _imagePath, - // _provider, - // _link, - // description: _p.description); - // await groupList.subscribe(podcastLocal); - - // if (_provider.contains('fireside')) { - // FiresideData data = FiresideData(_uuid, _link); - // await data.fatchData(); - // } - - // importOmpl.importState = ImportState.parse; - - // await dbHelper.savePodcastRss(_p, _uuid); - // groupList.updatePodcast(podcastLocal.id); - // importOmpl.importState = ImportState.complete; - // } else { - // importOmpl.importState = ImportState.error; - // Fluttertoast.showToast( - // msg: 'Podcast subscribed already', - // gravity: ToastGravity.TOP, - // ); - // await Future.delayed(Duration(seconds: 10)); - // importOmpl.importState = ImportState.stop; - // } - // } catch (e) { - // importOmpl.importState = ImportState.error; - // Fluttertoast.showToast( - // msg: 'Network error, Subscribe failed', - // gravity: ToastGravity.TOP, - // ); - // await Future.delayed(Duration(seconds: 5)); - // importOmpl.importState = ImportState.stop; - // } - // } - return Container( decoration: BoxDecoration( border: Border( diff --git a/lib/home/nested_home.dart b/lib/home/home.dart similarity index 84% rename from lib/home/nested_home.dart rename to lib/home/home.dart index efea0c0..d6de2e2 100644 --- a/lib/home/nested_home.dart +++ b/lib/home/home.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart' hide NestedScrollView; +import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:tsacdop/class/download_state.dart'; import 'package:tsacdop/class/podcast_group.dart'; @@ -21,6 +22,8 @@ import '../util/custompaint.dart'; import '../home/appbar/importompl.dart'; import '../home/audioplayer.dart'; +import 'appbar/addpodcast.dart'; +import 'appbar/popupmenu.dart'; import 'home_groups.dart'; import 'download_list.dart'; @@ -30,6 +33,10 @@ class Home extends StatefulWidget { } class _HomeState extends State with SingleTickerProviderStateMixin { + final MyHomePageDelegate _delegate = + MyHomePageDelegate(searchFieldLabel: 'Search podcast'); + + final GlobalKey _scaffoldKey = GlobalKey(); TabController _controller; Decoration _getIndicator(BuildContext context) { return UnderlineTabIndicator( @@ -41,6 +48,8 @@ class _HomeState extends State with SingleTickerProviderStateMixin { )); } + var _androidAppRetain = MethodChannel("android_app_retain"); + @override void initState() { super.initState(); @@ -58,83 +67,134 @@ class _HomeState extends State with SingleTickerProviderStateMixin { Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; double height = (width - 20) / 3 + 140; - return SafeArea( - child: Stack( - children: [ - Column( - children: [ - Import(), - Expanded( - child: NestedScrollView( - innerScrollPositionKeyBuilder: () { - return Key('tab' + _controller.index.toString()); - }, - pinnedHeaderSliverHeightBuilder: () => 50, - headerSliverBuilder: - (BuildContext context, bool innerBoxScrolled) { - return [ - SliverList( - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return SizedBox( - height: height, - width: width, - child: ScrollPodcasts(), - ); + return AnnotatedRegion( + value: SystemUiOverlayStyle( + systemNavigationBarIconBrightness: + Theme.of(context).accentColorBrightness, + statusBarIconBrightness: Theme.of(context).accentColorBrightness, + systemNavigationBarColor: Theme.of(context).primaryColor, + ), + child: Scaffold( + key: _scaffoldKey, + body: WillPopScope( + onWillPop: () async { + if (Platform.isAndroid) { + _androidAppRetain.invokeMethod('sendToBackground'); + return false; + } else { + return true; + } + }, + child: SafeArea( + child: Stack( + children: [ + Column( + children: [ + Import(), + Expanded( + child: NestedScrollView( + innerScrollPositionKeyBuilder: () { + return Key('tab' + _controller.index.toString()); }, - childCount: 1, - ), - ), - SliverPersistentHeader( - delegate: _SliverAppBarDelegate( - TabBar( - indicator: _getIndicator(context), - isScrollable: true, - indicatorSize: TabBarIndicatorSize.tab, + pinnedHeaderSliverHeightBuilder: () => 50, + headerSliverBuilder: + (BuildContext context, bool innerBoxScrolled) { + return [ + SliverToBoxAdapter( + child: SizedBox( + height: 50.0, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + IconButton( + tooltip: 'Add', + icon: const Icon( + Icons.add_circle_outline), + onPressed: () async { + await showSearch( + context: context, + delegate: _delegate, + ); + }, + ), + Image( + image: Theme.of(context).brightness == + Brightness.light + ? AssetImage('assets/text.png') + : AssetImage( + 'assets/text_light.png'), + height: 30, + ), + PopupMenu(), + ], + ), + ), + ), + SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return SizedBox( + height: height, + width: width, + child: ScrollPodcasts(), + ); + }, + childCount: 1, + ), + ), + SliverPersistentHeader( + delegate: _SliverAppBarDelegate( + TabBar( + indicator: _getIndicator(context), + isScrollable: true, + indicatorSize: TabBarIndicatorSize.tab, + controller: _controller, + tabs: [ + Tab( + child: Text('Recent Update'), + ), + Tab( + child: Text('Favorite'), + ), + Tab( + child: Text('Download'), + ) + ], + ), + ), + pinned: true, + ), + ]; + }, + body: TabBarView( controller: _controller, - tabs: [ - Tab( - child: Text('Recent Update'), - ), - Tab( - child: Text('Favorite'), - ), - Tab( - child: Text('Download'), - ) + children: [ + NestedScrollViewInnerScrollPositionKeyWidget( + Key('tab0'), _RecentUpdate()), + NestedScrollViewInnerScrollPositionKeyWidget( + Key('tab1'), _MyFavorite()), + NestedScrollViewInnerScrollPositionKeyWidget( + Key('tab2'), _MyDownload()), ], ), ), - pinned: true, ), - ]; - }, - body: TabBarView( - controller: _controller, - children: [ - NestedScrollViewInnerScrollPositionKeyWidget( - Key('tab0'), _RecentUpdate()), - NestedScrollViewInnerScrollPositionKeyWidget( - Key('tab1'), _MyFavorite()), - NestedScrollViewInnerScrollPositionKeyWidget( - Key('tab2'), _MyDownload()), + Selector( + selector: (_, audio) => audio.playerRunning, + builder: (_, data, __) { + return Padding( + padding: EdgeInsets.only(bottom: data ? 60.0 : 0), + ); + }), ], ), - ), + Container(child: PlayerWidget()), + ], ), - Selector( - selector: (_, audio) => audio.playerRunning, - builder: (_, data, __) { - return Padding( - padding: EdgeInsets.only(bottom: data ? 60.0 : 0), - ); - }), - ], + ), ), - Container(child: PlayerWidget()), - ], - ), - ); + )); } } @@ -573,7 +633,7 @@ class _RecentUpdateState extends State<_RecentUpdate> ), ]), ) - : Center(child: CircularProgressIndicator()); + : Center(); }, ); } diff --git a/lib/home/home_groups.dart b/lib/home/home_groups.dart index e22b909..ea2a65f 100644 --- a/lib/home/home_groups.dart +++ b/lib/home/home_groups.dart @@ -40,6 +40,14 @@ class _ScrollPodcastsState extends State { _groupIndex = 0; } + Widget _circleContainer(BuildContext context) => Container( + margin: EdgeInsets.symmetric(horizontal: 10), + height: 50, + width: 50, + decoration: + BoxDecoration(shape: BoxShape.circle, color: context.primaryColor), + ); + @override Widget build(BuildContext context) { double _width = MediaQuery.of(context).size.width; @@ -137,16 +145,49 @@ class _ScrollPodcastsState extends State { ), ), Container( - height: 70, - color: - Theme.of(context).scaffoldBackgroundColor, - ), + height: 70, + color: + Theme.of(context).scaffoldBackgroundColor, + child: Row( + children: [ + _circleContainer(context), + _circleContainer(context), + _circleContainer(context) + ], + )), ], )), Container( height: (_width - 20) / 3 + 40, color: Theme.of(context).primaryColor, margin: EdgeInsets.symmetric(horizontal: 15), + child: Center( + child: _groupIndex == 0 + ? Text.rich(TextSpan( + style: context.textTheme.headline6 + .copyWith(height: 2), + children: [ + TextSpan( + text: 'Welcome to Tsacdop\n', + style: context.textTheme.headline6 + .copyWith( + color: context.accentColor)), + TextSpan( + text: 'Get started\n', + style: context.textTheme.headline6 + .copyWith( + color: context.accentColor)), + TextSpan(text: 'Tap '), + WidgetSpan( + child: + Icon(Icons.add_circle_outline)), + TextSpan(text: ' to subscribe podcasts') + ], + )) + : Text('No podcast in this group', + style: TextStyle( + color: context.textTheme.bodyText2.color + .withOpacity(0.5)))), ), ], ), diff --git a/lib/intro_slider/app_intro.dart b/lib/intro_slider/app_intro.dart index 5332b23..e951a6a 100644 --- a/lib/intro_slider/app_intro.dart +++ b/lib/intro_slider/app_intro.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:tsacdop/class/settingstate.dart'; -import 'package:tsacdop/home/appbar/addpodcast.dart'; +import 'package:tsacdop/home/home.dart'; import 'package:tsacdop/util/pageroute.dart'; import 'fourthpage.dart'; import 'secondpage.dart'; @@ -209,7 +209,7 @@ class _SlideIntroState extends State { onTap: () { if (widget.goto == Goto.home) { Navigator.push(context, - SlideLeftRoute(page: MyHomePage())); + SlideLeftRoute(page: Home())); Provider.of(context, listen: false) .saveShowIntro(); diff --git a/lib/main.dart b/lib/main.dart index 8cc4dd5..e275ae0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,12 +4,12 @@ import 'package:flutter/services.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'class/podcast_group.dart'; -import 'home/appbar/addpodcast.dart'; import 'class/audiostate.dart'; import 'class/settingstate.dart'; import 'class/download_state.dart'; import 'class/refresh_podcast.dart'; import 'class/subscribe_podcast.dart'; +import 'home/home.dart'; import 'intro_slider/app_intro.dart'; final SettingState themeSetting = SettingState(); @@ -20,14 +20,16 @@ Future main() async { runApp( MultiProvider( providers: [ - ChangeNotifierProvider(create: (_) => themeSetting), + ChangeNotifierProvider( + create: (_) => themeSetting, + ), ChangeNotifierProvider(create: (_) => AudioPlayerNotifier()), ChangeNotifierProvider(create: (_) => GroupList()), ChangeNotifierProvider(create: (_) => SubscribeWorker()), ChangeNotifierProvider(create: (_) => RefreshWorker()), ChangeNotifierProvider( create: (_) => DownloadState(), - ), + ) ], child: MyApp(), ), @@ -50,26 +52,8 @@ class MyApp extends StatelessWidget { themeMode: setting.theme, debugShowCheckedModeBanner: false, title: 'Tsacdop', - theme: ThemeData( - accentColorBrightness: Brightness.dark, - primaryColor: Colors.grey[100], + theme: lightTheme.copyWith( accentColor: setting.accentSetColor, - primaryColorLight: Colors.white, - primaryColorDark: Colors.grey[300], - dialogBackgroundColor: Colors.white, - backgroundColor: Colors.grey[100], - appBarTheme: AppBarTheme( - color: Colors.grey[100], - elevation: 0, - ), - textTheme: TextTheme( - bodyText2: - TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal), - ), - tabBarTheme: TabBarTheme( - labelColor: Colors.black, - unselectedLabelColor: Colors.grey[400], - ), ), darkTheme: ThemeData.dark().copyWith( accentColor: setting.accentSetColor, @@ -80,7 +64,7 @@ class MyApp extends StatelessWidget { .copyWith(color: setting.realDark ? Colors.black87 : null), appBarTheme: AppBarTheme(elevation: 0), ), - home: setting.showIntro ? SlideIntro(goto: Goto.home) : MyHomePage(), + home: setting.showIntro ? SlideIntro(goto: Goto.home) : Home(), ); }, );