Compare commits

..

3 Commits

Author SHA1 Message Date
d61899dd5e Add player buttons 2022-03-24 09:57:47 +01:00
d9497d50c6 Use fluent icons 2022-03-24 09:30:08 +01:00
6a79a90e56 Display music title & artist 2022-03-24 09:20:43 +01:00
7 changed files with 201 additions and 94 deletions

View File

@ -1,94 +1,8 @@
// ignore_for_file: avoid_print
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/material.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'; import 'package:music_web_player/config.dart';
import 'package:music_web_player/ui/player_app.dart';
void main() { void main() {
loadConfig(); loadConfig();
runApp(const PlayerApp()); runApp(const PlayerApp());
} }
class PlayerApp extends StatelessWidget {
const PlayerApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Music player',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.green,
brightness: Brightness.dark,
),
home: const AppHome(),
);
}
}
class AppHome extends StatefulWidget {
const AppHome({Key? key}) : super(key: key);
@override
State<AppHome> createState() => _AppHomeState();
}
class _AppHomeState extends State<AppHome> {
var error = false;
List<MusicEntry>? musics;
Future<void> load() async {
try {
setState(() => error = false);
musics = await API.getList();
setState(() {});
} catch (e, s) {
print("$e $s");
setState(() => error = true);
}
}
@override
void initState() {
super.initState();
load();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: buildBody(context));
}
Widget buildBody(BuildContext context) {
if (error) {
return Center(
child: IntrinsicHeight(
child: Column(
children: [
const Icon(FluentIcons.warning_24_regular, size: 50),
const SizedBox(height: 50),
const Text("Failed to load musics list!"),
const SizedBox(height: 50),
ElevatedButton(
onPressed: load,
child: Text("Try again".toUpperCase()),
),
],
),
));
}
if (musics == null) {
return const Center(child: CircularProgressIndicator());
}
if (musics!.isEmpty) {
return const Center(child: Text("Musics list is empty!"));
}
return MusicPlayer(musicsList: musics!);
}
}

View File

@ -10,6 +10,7 @@ class CoverImage extends StatelessWidget {
final double? height; final double? height;
final BoxFit? fit; final BoxFit? fit;
final Icon? icon; final Icon? icon;
final Color? backgroundColor;
const CoverImage({ const CoverImage({
Key? key, Key? key,
@ -18,6 +19,7 @@ class CoverImage extends StatelessWidget {
this.height, this.height,
this.icon, this.icon,
this.fit, this.fit,
this.backgroundColor,
}) : super(key: key); }) : super(key: key);
@override @override
@ -37,7 +39,7 @@ class CoverImage extends StatelessWidget {
} }
Widget _loadingWidget(double? progress) => Container( Widget _loadingWidget(double? progress) => Container(
color: Colors.black, color: backgroundColor ?? Colors.black,
width: width, width: width,
height: height, height: height,
child: Center( child: Center(

View File

@ -1,6 +1,8 @@
import 'dart:math'; import 'dart:math';
import 'dart:ui'; import 'dart:ui';
import 'package:fluent_ui/fluent_ui.dart' as fluent;
import 'package:fluentui_system_icons/fluentui_system_icons.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/ui/cover_image.dart'; import 'package:music_web_player/ui/cover_image.dart';
@ -59,13 +61,77 @@ class _MusicPlayerState extends State<MusicPlayer> {
), ),
)), )),
_buildFront(), _buildCenter(),
], ],
), ),
); );
} }
Widget _buildFront() { Widget _buildCenter() {
return Text(currMusic.artist + " - " + currMusic.title); return fluent.Center(
child: Container(
width: 250,
child: Column(
mainAxisAlignment: fluent.MainAxisAlignment.center,
crossAxisAlignment: fluent.CrossAxisAlignment.center,
children: [
Material(
borderRadius: const BorderRadius.all(
Radius.circular(18.0),
),
clipBehavior: Clip.hardEdge,
child: CoverImage(
width: 250,
height: 250,
music: currMusic,
fit: BoxFit.cover,
backgroundColor: Colors.black12,
icon: const Icon(FluentIcons.music_note_2_24_regular, size: 90),
),
),
const SizedBox(height: 40),
Text(currMusic.title, style: const TextStyle(fontSize: 22)),
const SizedBox(height: 20),
Text(currMusic.artist),
const fluent.SizedBox(height: 40),
fluent.Slider(
max: 100,
value: 10,
onChanged: (v) => {},
// Label is the text displayed above the slider when the user is interacting with it.
label: 'hey',
),
const fluent.SizedBox(height: 40),
fluent.Row(
children: [
IconButton(
icon: const PlayerIcon(fluent.FluentIcons.previous),
onPressed: () => {},
),
const Spacer(),
IconButton(
icon: const PlayerIcon(fluent.FluentIcons.play),
onPressed: () => {},
),
const Spacer(),
IconButton(
icon: const PlayerIcon(fluent.FluentIcons.next),
onPressed: () => {},
),
],
)
],
),
),
);
} }
} }
class PlayerIcon extends StatelessWidget {
final IconData icon;
const PlayerIcon(this.icon, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => Icon(icon, size: 35);
}

97
lib/ui/player_app.dart Normal file
View File

@ -0,0 +1,97 @@
// ignore_for_file: avoid_print
import 'package:fluent_ui/fluent_ui.dart' as fluent;
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/material.dart';
import 'package:music_web_player/api.dart';
import 'package:music_web_player/ui/music_player.dart';
class PlayerApp extends StatelessWidget {
const PlayerApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Music player',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.green,
brightness: Brightness.dark,
),
home: fluent.FluentTheme(
child: const AppHome(),
data: fluent.ThemeData(
iconTheme: const IconThemeData(color: Colors.white)),
),
);
}
}
class AppHome extends StatefulWidget {
const AppHome({Key? key}) : super(key: key);
@override
State<AppHome> createState() => _AppHomeState();
}
class _AppHomeState extends State<AppHome> {
var error = false;
List<MusicEntry>? musics;
Future<void> load() async {
try {
setState(() => error = false);
musics = await API.getList();
setState(() {});
} catch (e, s) {
print("$e $s");
setState(() => error = true);
}
}
@override
void initState() {
super.initState();
load();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: buildBody(context));
}
Widget buildBody(BuildContext context) {
if (error) {
return Center(
child: IntrinsicHeight(
child: Column(
children: [
const Icon(
FluentIcons.warning_24_regular,
size: 50,
color: Colors.white,
),
const SizedBox(height: 50),
const Text("Failed to load musics list!"),
const SizedBox(height: 50),
fluent.FilledButton(
onPressed: load,
child: Text("Try again".toUpperCase()),
),
],
),
));
}
if (musics == null) {
return const Center(child: fluent.ProgressRing());
}
if (musics!.isEmpty) {
return const Center(child: Text("Musics list is empty!"));
}
return MusicPlayer(musicsList: musics!);
}
}

View File

@ -106,6 +106,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.2" version: "6.1.2"
fluent_ui:
dependency: "direct main"
description:
name: fluent_ui
url: "https://pub.dartlang.org"
source: hosted
version: "3.9.1"
fluentui_system_icons: fluentui_system_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -158,6 +165,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@ -277,6 +291,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.2.4" version: "4.2.4"
recase:
dependency: transitive
description:
name: recase
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@ -284,6 +305,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.27.3" version: "0.27.3"
scroll_pos:
dependency: transitive
description:
name: scroll_pos
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter

View File

@ -38,7 +38,8 @@ dependencies:
# HTTP client # HTTP client
dio: ^4.0.4 dio: ^4.0.4
# Fluent icons # Fluent ui
fluent_ui: ^3.9.1
fluentui_system_icons: ^1.1.162 fluentui_system_icons: ^1.1.162
# Image processing # Image processing

View File

@ -7,8 +7,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:music_web_player/ui/player_app.dart';
import 'package:music_web_player/main.dart';
void main() { void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async { testWidgets('Counter increments smoke test', (WidgetTester tester) async {