Display tracks covers

This commit is contained in:
2022-03-23 21:15:29 +01:00
parent f087e987a4
commit 1d721dd682
6 changed files with 302 additions and 3 deletions

View File

@ -11,11 +11,15 @@ class MusicEntry {
required this.artist,
required this.title,
});
String get coverCacheKey => "cover-$id";
}
typedef MusicsList = List<MusicEntry>;
class API {
/// Get the list of music
static Future<List<MusicEntry>> getList() async {
static Future<MusicsList> getList() async {
final response = await Dio().get(config.apiURL + "/list",
options: Options(headers: {"Token": config.apiToken}));
@ -30,3 +34,7 @@ class API {
.cast<MusicEntry>();
}
}
extension MusicEntryAPIExt on MusicEntry {
String get coverURL => "${config.apiURL}/cover/$id";
}

View File

@ -2,6 +2,7 @@
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/material.dart';
import 'package:music_web_player/ui/music_player.dart';
import 'package:music_web_player/api.dart';
import 'package:music_web_player/config.dart';
@ -88,7 +89,6 @@ class _AppHomeState extends State<AppHome> {
return const Center(child: Text("Musics list is empty!"));
}
// TODO : go on
return Text(musics![0].artist);
return MusicPlayer(musicsList: musics!);
}
}

35
lib/ui/cover_image.dart Normal file
View File

@ -0,0 +1,35 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
import 'package:flutter/material.dart';
import 'package:music_web_player/api.dart';
import 'package:music_web_player/config.dart';
class CoverImage extends StatelessWidget {
final MusicEntry music;
final double? width;
final double? height;
final BoxFit? fit;
const CoverImage({
Key? key,
required this.music,
this.width,
this.height,
this.fit,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return CachedNetworkImage(
width: width,
height: height,
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
imageUrl: music.coverURL,
cacheKey: music.coverCacheKey,
httpHeaders: {"Token": config.apiToken},
useOldImageOnUrlChange: false,
placeholder: (c, s) => const Center(child: CircularProgressIndicator()),
fit: fit,
);
}
}

55
lib/ui/music_player.dart Normal file
View File

@ -0,0 +1,55 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:music_web_player/api.dart';
import 'package:music_web_player/ui/cover_image.dart';
class MusicPlayer extends StatefulWidget {
final MusicsList musicsList;
const MusicPlayer({Key? key, required this.musicsList}) : super(key: key);
@override
State<MusicPlayer> createState() => _MusicPlayerState();
}
class _MusicPlayerState extends State<MusicPlayer> {
final rng = Random();
final List<MusicEntry> stack = [];
int currMusicPos = 0;
MusicEntry get currMusic {
if (currMusicPos < 0) currMusicPos = 0;
// Automatically choose next music if required
if (currMusicPos >= stack.length) {
var nextId = rng.nextInt(widget.musicsList.length);
stack.add(widget.musicsList[nextId]);
}
return stack[currMusicPos];
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
// Background image
CoverImage(
music: currMusic,
width: constraints.maxWidth,
height: constraints.maxHeight,
fit: BoxFit.cover,
),
_buildFront(),
],
),
);
}
Widget _buildFront() {
return Text(currMusic.artist + " - " + currMusic.title);
}
}