Display tracks covers
This commit is contained in:
parent
f087e987a4
commit
1d721dd682
10
lib/api.dart
10
lib/api.dart
@ -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";
|
||||
}
|
||||
|
@ -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
35
lib/ui/cover_image.dart
Normal 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
55
lib/ui/music_player.dart
Normal 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);
|
||||
}
|
||||
}
|
197
pubspec.lock
197
pubspec.lock
@ -15,6 +15,27 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
cached_network_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
cached_network_image_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
cached_network_image_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -43,6 +64,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -64,6 +92,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
fluentui_system_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -76,6 +118,20 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_blurhash:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_blurhash
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.4"
|
||||
flutter_cache_manager:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -88,6 +144,13 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.13.4"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -123,6 +186,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
octo_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: octo_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -130,6 +200,90 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.9"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.12"
|
||||
path_provider_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: rxdart
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.27.3"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -142,6 +296,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
sqflite:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -163,6 +331,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -184,6 +359,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -191,5 +373,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0+1"
|
||||
sdks:
|
||||
dart: ">=2.16.1 <3.0.0"
|
||||
flutter: ">=2.8.0"
|
||||
|
@ -41,6 +41,10 @@ dependencies:
|
||||
# Fluent icons
|
||||
fluentui_system_icons: ^1.1.162
|
||||
|
||||
# Image processing
|
||||
cached_network_image: ^3.2.0
|
||||
cached_network_image_platform_interface: ^1.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
Loading…
Reference in New Issue
Block a user