Compare commits
3 Commits
fce5cc326e
...
d61899dd5e
Author | SHA1 | Date | |
---|---|---|---|
d61899dd5e | |||
d9497d50c6 | |||
6a79a90e56 |
@ -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!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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(
|
||||||
|
@ -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
97
lib/ui/player_app.dart
Normal 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!);
|
||||||
|
}
|
||||||
|
}
|
28
pubspec.lock
28
pubspec.lock
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user