Missing scrolling, homepage reload, sections page
This commit is contained in:
parent
d4299f736f
commit
3e5641b3c2
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:cookie_jar/cookie_jar.dart';
|
import 'package:cookie_jar/cookie_jar.dart';
|
||||||
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
|
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
|
||||||
@ -29,6 +31,7 @@ class DeezerAPI {
|
|||||||
"Accept-Language": "${settings.deezerLanguage??"en"}-${settings.deezerCountry??'US'},${settings.deezerLanguage??"en"};q=0.9,en-US;q=0.8,en;q=0.7",
|
"Accept-Language": "${settings.deezerLanguage??"en"}-${settings.deezerCountry??'US'},${settings.deezerLanguage??"en"};q=0.9,en-US;q=0.8,en;q=0.7",
|
||||||
"Connection": "keep-alive"
|
"Connection": "keep-alive"
|
||||||
};
|
};
|
||||||
|
Future _authorizing;
|
||||||
|
|
||||||
CookieJar _cookieJar = new CookieJar();
|
CookieJar _cookieJar = new CookieJar();
|
||||||
|
|
||||||
@ -75,8 +78,16 @@ class DeezerAPI {
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Wrapper so it can be globally awaited
|
||||||
|
Future authorize() async {
|
||||||
|
if (_authorizing == null) {
|
||||||
|
this._authorizing = this._authorize();
|
||||||
|
}
|
||||||
|
return _authorizing;
|
||||||
|
}
|
||||||
|
|
||||||
//Authorize, bool = success
|
//Authorize, bool = success
|
||||||
Future<bool> authorize() async {
|
Future<bool> _authorize() async {
|
||||||
try {
|
try {
|
||||||
Map<dynamic, dynamic> data = await callApi('deezer.getUserData');
|
Map<dynamic, dynamic> data = await callApi('deezer.getUserData');
|
||||||
if (data['results']['USER']['USER_ID'] == 0) {
|
if (data['results']['USER']['USER_ID'] == 0) {
|
||||||
|
@ -553,14 +553,24 @@ class HomePageSection {
|
|||||||
String title;
|
String title;
|
||||||
HomePageSectionLayout layout;
|
HomePageSectionLayout layout;
|
||||||
|
|
||||||
|
//For loading more items
|
||||||
|
String pagePath;
|
||||||
|
bool hasMore;
|
||||||
|
|
||||||
@JsonKey(fromJson: _homePageItemFromJson, toJson: _homePageItemToJson)
|
@JsonKey(fromJson: _homePageItemFromJson, toJson: _homePageItemToJson)
|
||||||
List<HomePageItem> items;
|
List<HomePageItem> items;
|
||||||
|
|
||||||
HomePageSection({this.layout, this.items, this.title});
|
HomePageSection({this.layout, this.items, this.title, this.pagePath, this.hasMore});
|
||||||
|
|
||||||
//JSON
|
//JSON
|
||||||
factory HomePageSection.fromPrivateJson(Map<dynamic, dynamic> json) {
|
factory HomePageSection.fromPrivateJson(Map<dynamic, dynamic> json) {
|
||||||
HomePageSection hps = HomePageSection(title: json['title'], items: []);
|
HomePageSection hps = HomePageSection(
|
||||||
|
title: json['title'],
|
||||||
|
items: [],
|
||||||
|
pagePath: json['target'],
|
||||||
|
hasMore: json['hasMoreItems']??false
|
||||||
|
);
|
||||||
|
|
||||||
String layout = json['layout'];
|
String layout = json['layout'];
|
||||||
//No ads there
|
//No ads there
|
||||||
if (layout == 'ads') return null;
|
if (layout == 'ads') return null;
|
||||||
|
@ -273,6 +273,8 @@ HomePageSection _$HomePageSectionFromJson(Map<String, dynamic> json) {
|
|||||||
_$enumDecodeNullable(_$HomePageSectionLayoutEnumMap, json['layout']),
|
_$enumDecodeNullable(_$HomePageSectionLayoutEnumMap, json['layout']),
|
||||||
items: HomePageSection._homePageItemFromJson(json['items']),
|
items: HomePageSection._homePageItemFromJson(json['items']),
|
||||||
title: json['title'] as String,
|
title: json['title'] as String,
|
||||||
|
pagePath: json['pagePath'] as String,
|
||||||
|
hasMore: json['hasMore'] as bool,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,6 +282,8 @@ Map<String, dynamic> _$HomePageSectionToJson(HomePageSection instance) =>
|
|||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'title': instance.title,
|
'title': instance.title,
|
||||||
'layout': _$HomePageSectionLayoutEnumMap[instance.layout],
|
'layout': _$HomePageSectionLayoutEnumMap[instance.layout],
|
||||||
|
'pagePath': instance.pagePath,
|
||||||
|
'hasMore': instance.hasMore,
|
||||||
'items': HomePageSection._homePageItemToJson(instance.items),
|
'items': HomePageSection._homePageItemToJson(instance.items),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ class PlayerHelper {
|
|||||||
await AudioService.start(
|
await AudioService.start(
|
||||||
backgroundTaskEntrypoint: backgroundTaskEntrypoint,
|
backgroundTaskEntrypoint: backgroundTaskEntrypoint,
|
||||||
androidEnableQueue: true,
|
androidEnableQueue: true,
|
||||||
androidStopForegroundOnPause: false,
|
androidStopForegroundOnPause: true,
|
||||||
androidNotificationOngoing: false,
|
androidNotificationOngoing: false,
|
||||||
androidNotificationClickStartsActivity: true,
|
androidNotificationClickStartsActivity: true,
|
||||||
androidNotificationChannelDescription: 'Freezer',
|
androidNotificationChannelDescription: 'Freezer',
|
||||||
androidNotificationChannelName: 'Freezer',
|
androidNotificationChannelName: 'Freezer',
|
||||||
androidNotificationIcon: 'drawable/ic_logo'
|
androidNotificationIcon: 'drawable/ic_logo',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,6 +470,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future onClose() async {
|
Future onClose() async {
|
||||||
|
print('onClose');
|
||||||
await onStop();
|
await onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +479,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
|||||||
_player.stop();
|
_player.stop();
|
||||||
if (_eventSub != null) _eventSub.cancel();
|
if (_eventSub != null) _eventSub.cancel();
|
||||||
|
|
||||||
super.onStop();
|
await super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get queue save file path
|
//Get queue save file path
|
||||||
|
@ -43,10 +43,14 @@ class _FreezerAppState extends State<FreezerApp> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
//Make update theme global
|
//Make update theme global
|
||||||
updateTheme = _updateTheme;
|
updateTheme = _updateTheme;
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
void _updateTheme() {
|
void _updateTheme() {
|
||||||
setState(() {
|
setState(() {
|
||||||
settings.themeData;
|
settings.themeData;
|
||||||
|
@ -22,18 +22,6 @@ class HomeScreen extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
|
||||||
return ListView(
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 16.0),
|
|
||||||
child: FreezerTitle(),
|
|
||||||
),
|
|
||||||
HomePageScreen()
|
|
||||||
],
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +92,7 @@ class _HomePageScreenState extends State<HomePageScreen> {
|
|||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
//On background load from API
|
//On background load from API
|
||||||
try {
|
try {
|
||||||
if (settings.offlineMode) return;
|
if (settings.offlineMode) await deezerAPI.authorize();
|
||||||
HomePage _hp = await deezerAPI.homePage();
|
HomePage _hp = await deezerAPI.homePage();
|
||||||
if (_hp != null) {
|
if (_hp != null) {
|
||||||
if (_cancel) return;
|
if (_cancel) return;
|
||||||
@ -148,12 +136,14 @@ class _HomePageScreenState extends State<HomePageScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (_homePage == null)
|
if (_homePage == null)
|
||||||
return Center(child: CircularProgressIndicator(),);
|
return Center(child: Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
));
|
||||||
if (_error)
|
if (_error)
|
||||||
return ErrorScreen();
|
return ErrorScreen();
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
addAutomaticKeepAlives: true,
|
|
||||||
physics: NeverScrollableScrollPhysics(),
|
physics: NeverScrollableScrollPhysics(),
|
||||||
itemCount: _homePage.sections.length,
|
itemCount: _homePage.sections.length,
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
@ -179,7 +169,36 @@ class _HomePageScreenState extends State<HomePageScreen> {
|
|||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: List.generate(section.items.length, (i) {
|
children: List.generate(section.items.length + 1, (i) {
|
||||||
|
//Has more items
|
||||||
|
if (i == section.items.length) {
|
||||||
|
if (section.hasMore??false) {
|
||||||
|
return FlatButton(
|
||||||
|
child: Text(
|
||||||
|
'Show more',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20.0
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (context) => Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(section.title),
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: HomePageScreen(
|
||||||
|
channel: DeezerChannel(target: section.pagePath)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(height: 0, width: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Show item
|
||||||
HomePageItem item = section.items[i];
|
HomePageItem item = section.items[i];
|
||||||
return HomePageItemWidget(item);
|
return HomePageItemWidget(item);
|
||||||
}),
|
}),
|
||||||
@ -255,7 +274,9 @@ class HomePageItemWidget extends StatelessWidget {
|
|||||||
Navigator.of(context).push(MaterialPageRoute(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
builder: (context) => Scaffold(
|
builder: (context) => Scaffold(
|
||||||
appBar: AppBar(title: Text(item.value.title.toString()),),
|
appBar: AppBar(title: Text(item.value.title.toString()),),
|
||||||
body: HomePageScreen(channel: item.value,),
|
body: SingleChildScrollView(
|
||||||
|
child: HomePageScreen(channel: item.value,)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,7 @@ class _SearchScreenState extends State<SearchScreen> {
|
|||||||
|
|
||||||
String _query;
|
String _query;
|
||||||
bool _offline = false;
|
bool _offline = false;
|
||||||
|
TextEditingController _controller = new TextEditingController();
|
||||||
|
|
||||||
void _submit(BuildContext context, {String query}) {
|
void _submit(BuildContext context, {String query}) {
|
||||||
if (query != null) _query = query;
|
if (query != null) _query = query;
|
||||||
@ -52,17 +53,33 @@ class _SearchScreenState extends State<SearchScreen> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: Stack(
|
||||||
onChanged: (String s) => _query = s,
|
alignment: Alignment(1.0, 1.0),
|
||||||
decoration: InputDecoration(
|
children: [
|
||||||
labelText: 'Search'
|
TextField(
|
||||||
),
|
onChanged: (String s) => _query = s,
|
||||||
onSubmitted: (String s) => _submit(context, query: s),
|
decoration: InputDecoration(
|
||||||
),
|
labelText: 'Search'
|
||||||
|
),
|
||||||
|
controller: _controller,
|
||||||
|
onSubmitted: (String s) => _submit(context, query: s),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.clear),
|
||||||
|
onPressed: () {
|
||||||
|
_controller.clear();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.search),
|
Padding(
|
||||||
onPressed: () => _submit(context),
|
padding: EdgeInsets.fromLTRB(0, 8, 0, 0),
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(Icons.search),
|
||||||
|
onPressed: () => _submit(context),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user