2020-06-23 19:23:12 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:freezer/api/deezer.dart';
|
|
|
|
import 'package:freezer/api/definitions.dart';
|
|
|
|
import 'package:freezer/api/player.dart';
|
2020-10-19 19:28:45 +00:00
|
|
|
import 'package:freezer/main.dart';
|
|
|
|
import 'package:freezer/ui/elements.dart';
|
2020-06-23 19:23:12 +00:00
|
|
|
import 'package:freezer/ui/error.dart';
|
|
|
|
import 'package:freezer/ui/menu.dart';
|
2020-09-18 17:36:41 +00:00
|
|
|
import 'package:freezer/translations.i18n.dart';
|
2020-06-23 19:23:12 +00:00
|
|
|
import 'tiles.dart';
|
|
|
|
import 'details_screens.dart';
|
|
|
|
import '../settings.dart';
|
|
|
|
|
|
|
|
class HomeScreen extends StatelessWidget {
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2020-07-16 20:25:30 +00:00
|
|
|
return SingleChildScrollView(
|
|
|
|
child: Column(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: <Widget>[
|
2020-10-19 19:28:45 +00:00
|
|
|
SafeArea(child: Container()),
|
2020-07-16 20:25:30 +00:00
|
|
|
Flexible(child: HomePageScreen(),)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
2020-06-23 19:23:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class FreezerTitle extends StatelessWidget {
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2020-07-18 21:45:48 +00:00
|
|
|
return Padding(
|
|
|
|
padding: EdgeInsets.fromLTRB(0, 24, 0, 8),
|
|
|
|
child: Row(
|
|
|
|
mainAxisSize: MainAxisSize.max,
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
|
|
|
Row(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: <Widget>[
|
|
|
|
Image.asset('assets/icon.png', width: 64, height: 64),
|
|
|
|
Text(
|
|
|
|
'freezer',
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 56,
|
|
|
|
fontWeight: FontWeight.w900
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
)
|
|
|
|
],
|
2020-06-23 19:23:12 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HomePageScreen extends StatefulWidget {
|
|
|
|
|
|
|
|
final HomePage homePage;
|
|
|
|
final DeezerChannel channel;
|
|
|
|
HomePageScreen({this.homePage, this.channel, Key key}): super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
_HomePageScreenState createState() => _HomePageScreenState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _HomePageScreenState extends State<HomePageScreen> {
|
|
|
|
|
|
|
|
HomePage _homePage;
|
|
|
|
bool _cancel = false;
|
|
|
|
bool _error = false;
|
|
|
|
|
|
|
|
void _loadChannel() async {
|
|
|
|
HomePage _hp;
|
|
|
|
//Fetch channel from api
|
|
|
|
try {
|
|
|
|
_hp = await deezerAPI.getChannel(widget.channel.target);
|
|
|
|
} catch (e) {}
|
|
|
|
if (_hp == null) {
|
|
|
|
//On error
|
|
|
|
setState(() => _error = true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setState(() => _homePage = _hp);
|
|
|
|
}
|
|
|
|
void _loadHomePage() async {
|
|
|
|
//Load local
|
|
|
|
try {
|
|
|
|
HomePage _hp = await HomePage().load();
|
|
|
|
setState(() => _homePage = _hp);
|
|
|
|
} catch (e) {}
|
|
|
|
//On background load from API
|
|
|
|
try {
|
2020-08-16 20:17:22 +00:00
|
|
|
if (settings.offlineMode) await deezerAPI.authorize();
|
2020-06-23 19:23:12 +00:00
|
|
|
HomePage _hp = await deezerAPI.homePage();
|
|
|
|
if (_hp != null) {
|
|
|
|
if (_cancel) return;
|
|
|
|
if (_hp.sections.length == 0) return;
|
|
|
|
setState(() => _homePage = _hp);
|
|
|
|
//Save to cache
|
|
|
|
await _homePage.save();
|
|
|
|
}
|
|
|
|
} catch (e) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _load() {
|
|
|
|
if (widget.channel != null) {
|
|
|
|
_loadChannel();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (widget.channel == null && widget.homePage == null) {
|
|
|
|
_loadHomePage();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (widget.homePage.sections == null || widget.homePage.sections.length == 0) {
|
|
|
|
_loadHomePage();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//Already have data
|
|
|
|
setState(() => _homePage = widget.homePage);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
2020-09-01 14:41:15 +00:00
|
|
|
_load();
|
2020-06-23 19:23:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
_cancel = true;
|
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
if (_homePage == null)
|
2020-08-16 20:17:22 +00:00
|
|
|
return Center(child: Padding(
|
|
|
|
padding: EdgeInsets.all(8.0),
|
|
|
|
child: CircularProgressIndicator(),
|
|
|
|
));
|
2020-06-23 19:23:12 +00:00
|
|
|
if (_error)
|
|
|
|
return ErrorScreen();
|
2020-07-16 20:25:30 +00:00
|
|
|
return ListView.builder(
|
|
|
|
shrinkWrap: true,
|
|
|
|
physics: NeverScrollableScrollPhysics(),
|
|
|
|
itemCount: _homePage.sections.length,
|
|
|
|
itemBuilder: (context, i) {
|
|
|
|
HomePageSection section = _homePage.sections[i];
|
|
|
|
return Column(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
Padding(
|
|
|
|
child: Text(
|
|
|
|
section.title,
|
|
|
|
textAlign: TextAlign.left,
|
|
|
|
maxLines: 2,
|
|
|
|
overflow: TextOverflow.ellipsis,
|
2020-07-18 21:45:48 +00:00
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 20.0,
|
2020-10-19 19:28:45 +00:00
|
|
|
fontWeight: FontWeight.w900
|
2020-07-18 21:45:48 +00:00
|
|
|
),
|
2020-06-24 13:19:14 +00:00
|
|
|
),
|
2020-10-19 19:28:45 +00:00
|
|
|
padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0)
|
2020-07-16 20:25:30 +00:00
|
|
|
),
|
|
|
|
|
|
|
|
SingleChildScrollView(
|
|
|
|
scrollDirection: Axis.horizontal,
|
|
|
|
child: Row(
|
2020-08-16 20:17:22 +00:00
|
|
|
children: List.generate(section.items.length + 1, (i) {
|
|
|
|
//Has more items
|
|
|
|
if (i == section.items.length) {
|
|
|
|
if (section.hasMore??false) {
|
|
|
|
return FlatButton(
|
|
|
|
child: Text(
|
2020-09-18 17:36:41 +00:00
|
|
|
'Show more'.i18n,
|
2020-08-16 20:17:22 +00:00
|
|
|
textAlign: TextAlign.center,
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 20.0
|
|
|
|
),
|
|
|
|
),
|
|
|
|
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
|
|
|
|
builder: (context) => Scaffold(
|
2020-10-19 19:28:45 +00:00
|
|
|
appBar: FreezerAppBar(section.title),
|
2020-08-16 20:17:22 +00:00
|
|
|
body: SingleChildScrollView(
|
|
|
|
child: HomePageScreen(
|
|
|
|
channel: DeezerChannel(target: section.pagePath)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Container(height: 0, width: 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Show item
|
2020-07-16 20:25:30 +00:00
|
|
|
HomePageItem item = section.items[i];
|
|
|
|
return HomePageItemWidget(item);
|
|
|
|
}),
|
2020-06-24 13:19:14 +00:00
|
|
|
),
|
2020-07-16 20:25:30 +00:00
|
|
|
),
|
2020-10-19 19:28:45 +00:00
|
|
|
Container(height: 8.0),
|
2020-07-16 20:25:30 +00:00
|
|
|
],
|
|
|
|
);
|
|
|
|
},
|
2020-06-23 19:23:12 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2020-06-24 13:19:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class HomePageItemWidget extends StatelessWidget {
|
|
|
|
|
|
|
|
HomePageItem item;
|
|
|
|
HomePageItemWidget(this.item);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2020-07-16 20:25:30 +00:00
|
|
|
|
2020-06-24 13:19:14 +00:00
|
|
|
switch (item.type) {
|
|
|
|
case HomePageItemType.SMARTTRACKLIST:
|
|
|
|
return SmartTrackListTile(
|
|
|
|
item.value,
|
|
|
|
onTap: () {
|
|
|
|
playerHelper.playFromSmartTrackList(item.value);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
case HomePageItemType.ALBUM:
|
|
|
|
return AlbumCard(
|
|
|
|
item.value,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
|
|
builder: (context) => AlbumDetails(item.value)
|
|
|
|
));
|
|
|
|
},
|
|
|
|
onHold: () {
|
|
|
|
MenuSheet m = MenuSheet(context);
|
|
|
|
m.defaultAlbumMenu(item.value);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
case HomePageItemType.ARTIST:
|
|
|
|
return ArtistTile(
|
|
|
|
item.value,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
|
|
builder: (context) => ArtistDetails(item.value)
|
|
|
|
));
|
|
|
|
},
|
|
|
|
onHold: () {
|
|
|
|
MenuSheet m = MenuSheet(context);
|
|
|
|
m.defaultArtistMenu(item.value);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
case HomePageItemType.PLAYLIST:
|
|
|
|
return PlaylistCardTile(
|
|
|
|
item.value,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
|
|
builder: (context) => PlaylistDetails(item.value)
|
|
|
|
));
|
|
|
|
},
|
|
|
|
onHold: () {
|
|
|
|
MenuSheet m = MenuSheet(context);
|
|
|
|
m.defaultPlaylistMenu(item.value);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
case HomePageItemType.CHANNEL:
|
|
|
|
return ChannelTile(
|
|
|
|
item.value,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
|
|
builder: (context) => Scaffold(
|
2020-10-20 19:55:14 +00:00
|
|
|
appBar: FreezerAppBar(item.value.title.toString()),
|
2020-08-16 20:17:22 +00:00
|
|
|
body: SingleChildScrollView(
|
|
|
|
child: HomePageScreen(channel: item.value,)
|
|
|
|
),
|
2020-06-24 13:19:14 +00:00
|
|
|
)
|
|
|
|
));
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Container(height: 0, width: 0);
|
|
|
|
}
|
|
|
|
}
|