Compare commits

..

3 Commits

Author SHA1 Message Date
1fc43fce78 Can choose to play only filtered musics 2022-10-01 14:50:22 +02:00
da1ccb8e3a Update dependencies 2022-10-01 14:39:31 +02:00
6e9d945136 Display cover images in musics list 2022-10-01 14:33:04 +02:00
4 changed files with 137 additions and 75 deletions

View File

@@ -1,16 +1,19 @@
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:music_web_player/api.dart'; import 'package:music_web_player/api.dart';
import 'package:music_web_player/config.dart'; import 'package:music_web_player/config.dart';
class CoverImage extends StatelessWidget { class CoverImage extends StatefulWidget {
final MusicEntry music; final MusicEntry music;
final double? width; final double? width;
final double? height; final double? height;
final BoxFit? fit; final BoxFit? fit;
final Icon? icon; final Icon? icon;
final Color? backgroundColor; final Color? backgroundColor;
final Duration? delayLoading;
const CoverImage({ const CoverImage({
Key? key, Key? key,
@@ -20,31 +23,61 @@ class CoverImage extends StatelessWidget {
this.icon, this.icon,
this.fit, this.fit,
this.backgroundColor, this.backgroundColor,
this.delayLoading,
}) : super(key: key); }) : super(key: key);
@override
State<StatefulWidget> createState() => _CoverImageState();
}
class _CoverImageState extends State<CoverImage> {
var _canShowImage = true;
Timer? _timer;
@override
void initState() {
super.initState();
if (widget.delayLoading != null) {
_canShowImage = false;
Timer(widget.delayLoading!, () {
if (mounted) {
setState(() => _canShowImage = true);
}
});
}
}
@override
void dispose() {
super.dispose();
_timer?.cancel();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (!_canShowImage) return _loadingWidget(null);
return CachedNetworkImage( return CachedNetworkImage(
width: width, width: widget.width,
height: height, height: widget.height,
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet, imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
imageUrl: music.coverURL, imageUrl: widget.music.coverURL,
cacheKey: music.coverCacheKey, cacheKey: widget.music.coverCacheKey,
httpHeaders: {"Token": config.apiToken}, httpHeaders: {"Token": config.apiToken},
useOldImageOnUrlChange: false, useOldImageOnUrlChange: false,
progressIndicatorBuilder: (c, s, p) => _loadingWidget(p.progress), progressIndicatorBuilder: (c, s, p) => _loadingWidget(p.progress),
fit: fit, fit: widget.fit,
errorWidget: (c, s, e) => _loadingWidget(null), errorWidget: (c, s, e) => _loadingWidget(null),
); );
} }
Widget _loadingWidget(double? progress) => Container( Widget _loadingWidget(double? progress) => Container(
color: backgroundColor ?? Colors.black, color: widget.backgroundColor ?? Colors.black,
width: width, width: widget.width,
height: height, height: widget.height,
child: Center( child: Center(
child: progress == null child: progress == null
? icon ? widget.icon
: CircularProgressIndicator(value: progress), : CircularProgressIndicator(value: progress),
), ),
); );

View File

@@ -43,7 +43,9 @@ class _MusicPlayerState extends State<MusicPlayer> {
final List<MusicEntry> _stack = []; final List<MusicEntry> _stack = [];
int currMusicPos = 0; int currMusicPos = 0;
var _showPlaylist = false; var _showPlaylist = true;
var _playFilteredMusics = false;
final _filterController = fluent.TextEditingController(); final _filterController = fluent.TextEditingController();
MusicsList? _filteredList; MusicsList? _filteredList;
@@ -53,8 +55,11 @@ class _MusicPlayerState extends State<MusicPlayer> {
// Automatically choose next music if required // Automatically choose next music if required
if (currMusicPos >= _stack.length) { if (currMusicPos >= _stack.length) {
var nextId = rng.nextInt(widget.musicsList.length); var list = _playFilteredMusics
_stack.add(widget.musicsList[nextId]); ? _filteredList ?? widget.musicsList
: widget.musicsList;
var nextId = rng.nextInt(list.length);
_stack.add(list[nextId]);
} }
return _stack[currMusicPos]; return _stack[currMusicPos];
@@ -235,11 +240,7 @@ class _MusicPlayerState extends State<MusicPlayer> {
mainAxisAlignment: fluent.MainAxisAlignment.center, mainAxisAlignment: fluent.MainAxisAlignment.center,
crossAxisAlignment: fluent.CrossAxisAlignment.center, crossAxisAlignment: fluent.CrossAxisAlignment.center,
children: [ children: [
Material( RoundedImage(
borderRadius: const BorderRadius.all(
Radius.circular(18.0),
),
clipBehavior: Clip.hardEdge,
child: CoverImage( child: CoverImage(
width: 250, width: 250,
height: 250, height: 250,
@@ -343,6 +344,17 @@ class _MusicPlayerState extends State<MusicPlayer> {
itemBuilder: (c, i) { itemBuilder: (c, i) {
final music = (_filteredList ?? widget.musicsList)[i]; final music = (_filteredList ?? widget.musicsList)[i];
return ListTile( return ListTile(
leading: RoundedImage(
child: CoverImage(
delayLoading: const Duration(seconds: 2),
music: music,
width: 50,
height: 50,
fit: BoxFit.cover,
backgroundColor: Colors.transparent,
icon: const Icon(Icons.music_note),
),
),
title: Text(music.title), title: Text(music.title),
subtitle: Text(music.artist), subtitle: Text(music.artist),
selected: currMusic == music, selected: currMusic == music,
@@ -352,6 +364,13 @@ class _MusicPlayerState extends State<MusicPlayer> {
itemCount: (_filteredList ?? widget.musicsList).length, itemCount: (_filteredList ?? widget.musicsList).length,
), ),
), ),
ListTile(
leading: fluent.ToggleSwitch(
checked: _playFilteredMusics,
onChanged: (v) => setState(() => _playFilteredMusics = v),
),
title: const Text("Play only filtered musics"),
)
], ],
); );
} }
@@ -379,3 +398,20 @@ class DurationText extends StatelessWidget {
); );
} }
} }
class RoundedImage extends StatelessWidget {
final Widget child;
const RoundedImage({Key? key, required this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
borderRadius: const BorderRadius.all(
Radius.circular(18.0),
),
clipBehavior: Clip.hardEdge,
child: child,
);
}
}

View File

@@ -7,7 +7,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.8.2" version: "2.9.0"
audio_service_platform_interface: audio_service_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -35,35 +35,28 @@ packages:
name: cached_network_image name: cached_network_image
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.2.1" version: "3.2.2"
cached_network_image_platform_interface: cached_network_image_platform_interface:
dependency: "direct main" dependency: "direct main"
description: description:
name: cached_network_image_platform_interface name: cached_network_image_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "2.0.0"
cached_network_image_web: cached_network_image_web:
dependency: transitive dependency: transitive
description: description:
name: cached_network_image_web name: cached_network_image_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.0.2"
characters: characters:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
chewie_audio: chewie_audio:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -77,7 +70,7 @@ packages:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@@ -119,35 +112,35 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.1"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.1"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.2" version: "6.1.4"
fluent_ui: fluent_ui:
dependency: "direct main" dependency: "direct main"
description: description:
name: fluent_ui name: fluent_ui
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.12.0" version: "4.0.1"
fluentui_system_icons: fluentui_system_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: fluentui_system_icons name: fluentui_system_icons
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.170" version: "1.1.182"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@@ -173,7 +166,7 @@ packages:
name: flutter_lints name: flutter_lints
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "2.0.1"
flutter_localizations: flutter_localizations:
dependency: transitive dependency: transitive
description: flutter description: flutter
@@ -202,7 +195,7 @@ packages:
name: http name: http
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.13.4" version: "0.13.5"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@@ -230,28 +223,28 @@ packages:
name: lints name: lints
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "2.0.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.11" version: "0.12.12"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.4" version: "0.1.5"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0"
octo_image: octo_image:
dependency: transitive dependency: transitive
description: description:
@@ -265,28 +258,28 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.1" version: "1.8.2"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
name: path_provider name: path_provider
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.10" version: "2.0.11"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.14" version: "2.0.20"
path_provider_ios: path_provider_ios:
dependency: transitive dependency: transitive
description: description:
name: path_provider_ios name: path_provider_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.9" version: "2.0.11"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@@ -307,14 +300,14 @@ packages:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.5"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.3"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@@ -335,7 +328,7 @@ packages:
name: plugin_platform_interface name: plugin_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
process: process:
dependency: transitive dependency: transitive
description: description:
@@ -349,14 +342,14 @@ packages:
name: recase name: recase
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.1.0"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
name: rxdart name: rxdart
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.27.4" version: "0.27.5"
scroll_pos: scroll_pos:
dependency: transitive dependency: transitive
description: description:
@@ -375,21 +368,21 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.2" version: "1.9.0"
sqflite: sqflite:
dependency: transitive dependency: transitive
description: description:
name: sqflite name: sqflite
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2+1" version: "2.1.0"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.1+1" version: "2.3.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@@ -410,28 +403,28 @@ packages:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
synchronized: synchronized:
dependency: transitive dependency: transitive
description: description:
name: synchronized name: synchronized
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0+2" version: "3.0.0+3"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.9" version: "0.4.12"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -445,14 +438,14 @@ packages:
name: url_launcher name: url_launcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.2" version: "6.1.6"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.17" version: "6.0.19"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
@@ -480,14 +473,14 @@ packages:
name: url_launcher_platform_interface name: url_launcher_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" version: "2.1.1"
url_launcher_web: url_launcher_web:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.11" version: "2.0.13"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
@@ -515,49 +508,49 @@ packages:
name: video_player name: video_player
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.2" version: "2.4.7"
video_player_android: video_player_android:
dependency: transitive dependency: transitive
description: description:
name: video_player_android name: video_player_android
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.5" version: "2.3.9"
video_player_avfoundation: video_player_avfoundation:
dependency: transitive dependency: transitive
description: description:
name: video_player_avfoundation name: video_player_avfoundation
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.3.4" version: "2.3.6"
video_player_platform_interface: video_player_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: video_player_platform_interface name: video_player_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "5.1.2" version: "5.1.4"
video_player_web: video_player_web:
dependency: transitive dependency: transitive
description: description:
name: video_player_web name: video_player_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.10" version: "2.0.12"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.7.0" version: "3.0.0"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0+1" version: "0.2.0+2"
sdks: sdks:
dart: ">=2.17.0 <3.0.0" dart: ">=2.18.0 <3.0.0"
flutter: ">=3.0.0" flutter: ">=3.3.0"

View File

@@ -39,12 +39,12 @@ dependencies:
dio: ^4.0.4 dio: ^4.0.4
# Fluent ui # Fluent ui
fluent_ui: ^3.9.1 fluent_ui: ^4.0.1
fluentui_system_icons: ^1.1.162 fluentui_system_icons: ^1.1.162
# Image processing # Image processing
cached_network_image: ^3.2.1 cached_network_image: ^3.2.2
cached_network_image_platform_interface: ^1.0.0 cached_network_image_platform_interface: ^2.0.0
# Audio player # Audio player
video_player: ^2.3.0 video_player: ^2.3.0
@@ -65,7 +65,7 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^1.0.0 flutter_lints: ^2.0.1
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec