mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
Stop player on close support
PlaylistCard image placeholder Player album placeholder PlayerDI provider for global avilability of MPVPlayer
This commit is contained in:
parent
f367d8f5c3
commit
6ea222c5b0
13
.vscode/launch.json
vendored
Normal file
13
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Flutter",
|
||||||
|
"type": "dart",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "lib/main.dart"
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
"compounds": []
|
||||||
|
}
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,3 +1 @@
|
|||||||
{
|
{}
|
||||||
"typescript.tsdk": "node_modules/typescript/lib"
|
|
||||||
}
|
|
12
.vscode/tasks.json
vendored
12
.vscode/tasks.json
vendored
@ -1,12 +1,4 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": []
|
||||||
{
|
|
||||||
"type": "npm",
|
|
||||||
"script": "start",
|
|
||||||
"problemMatcher": [],
|
|
||||||
"label": "npm: start",
|
|
||||||
"detail": "qode ./dist/index.js"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
import 'package:spotify/spotify.dart' hide Image;
|
import 'package:spotify/spotify.dart' hide Image;
|
||||||
import 'package:spotube/components/CategoryCard.dart';
|
import 'package:spotube/components/CategoryCard.dart';
|
||||||
import 'package:spotube/components/Login.dart';
|
import 'package:spotube/components/Login.dart';
|
||||||
|
import 'package:spotube/components/PageWindowTitleBar.dart';
|
||||||
import 'package:spotube/components/Player.dart' as player;
|
import 'package:spotube/components/Player.dart' as player;
|
||||||
import 'package:spotube/components/Settings.dart';
|
import 'package:spotube/components/Settings.dart';
|
||||||
import 'package:spotube/components/UserLibrary.dart';
|
import 'package:spotube/components/UserLibrary.dart';
|
||||||
@ -135,12 +136,10 @@ class _HomeState extends State<Home> {
|
|||||||
Theme.of(context).navigationRailTheme.backgroundColor,
|
Theme.of(context).navigationRailTheme.backgroundColor,
|
||||||
child: MoveWindow(),
|
child: MoveWindow(),
|
||||||
),
|
),
|
||||||
Expanded(child: MoveWindow())
|
Expanded(child: MoveWindow()),
|
||||||
|
const TitleBarActionButtons(),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
MinimizeWindowButton(animate: true),
|
|
||||||
MaximizeWindowButton(animate: true),
|
|
||||||
CloseWindowButton(animate: true),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,52 @@
|
|||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mpv_dart/mpv_dart.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:spotube/provider/PlayerDI.dart';
|
||||||
|
|
||||||
|
class TitleBarActionButtons extends StatelessWidget {
|
||||||
|
const TitleBarActionButtons({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
MPVPlayer player = context.watch<PlayerDI>().player;
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
appWindow.minimize();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
foregroundColor:
|
||||||
|
MaterialStateProperty.all(Theme.of(context).iconTheme.color),
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.minimize_rounded)),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
appWindow.maximizeOrRestore();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
foregroundColor:
|
||||||
|
MaterialStateProperty.all(Theme.of(context).iconTheme.color),
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.crop_square_rounded)),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
player.stop();
|
||||||
|
appWindow.close();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
foregroundColor:
|
||||||
|
MaterialStateProperty.all(Theme.of(context).iconTheme.color),
|
||||||
|
overlayColor: MaterialStateProperty.all(Colors.redAccent),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.close_rounded,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PageWindowTitleBar extends StatelessWidget {
|
class PageWindowTitleBar extends StatelessWidget {
|
||||||
final Widget? leading;
|
final Widget? leading;
|
||||||
@ -13,9 +60,7 @@ class PageWindowTitleBar extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (leading != null) leading!,
|
if (leading != null) leading!,
|
||||||
Expanded(child: MoveWindow(child: Center(child: center))),
|
Expanded(child: MoveWindow(child: Center(child: center))),
|
||||||
MinimizeWindowButton(animate: true),
|
const TitleBarActionButtons()
|
||||||
MaximizeWindowButton(animate: true),
|
|
||||||
CloseWindowButton(animate: true),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:mpv_dart/mpv_dart.dart';
|
import 'package:mpv_dart/mpv_dart.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/provider/PlayerDI.dart';
|
||||||
import 'package:spotube/provider/SpotifyDI.dart';
|
import 'package:spotube/provider/SpotifyDI.dart';
|
||||||
|
|
||||||
class Player extends StatefulWidget {
|
class Player extends StatefulWidget {
|
||||||
@ -18,8 +19,6 @@ class Player extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlayerState extends State<Player> {
|
class _PlayerState extends State<Player> {
|
||||||
late MPVPlayer player;
|
|
||||||
|
|
||||||
bool _isPlaying = false;
|
bool _isPlaying = false;
|
||||||
bool _shuffled = false;
|
bool _shuffled = false;
|
||||||
double _duration = 0;
|
double _duration = 0;
|
||||||
@ -29,80 +28,69 @@ class _PlayerState extends State<Player> {
|
|||||||
double _volume = 0;
|
double _volume = 0;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
player = MPVPlayer(
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) async {
|
||||||
// verbose: true,
|
|
||||||
// debug: true,
|
|
||||||
audioOnly: true,
|
|
||||||
mpvArgs: [
|
|
||||||
"--ytdl-raw-options-set=format=140,http-chunk-size=300000",
|
|
||||||
"--script-opts=ytdl_hook-ytdl_path=yt-dlp",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
(() async {
|
|
||||||
try {
|
try {
|
||||||
|
MPVPlayer player = context.read<PlayerDI>().player;
|
||||||
await player.start();
|
await player.start();
|
||||||
double volume = await player.getProperty<double>("volume");
|
double volume = await player.getProperty<double>("volume");
|
||||||
setState(() {
|
setState(() {
|
||||||
_volume = volume / 100;
|
_volume = volume / 100;
|
||||||
});
|
});
|
||||||
|
player.on(MPVEvents.paused, null, (ev, context) {
|
||||||
|
setState(() {
|
||||||
|
_isPlaying = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
player.on(MPVEvents.resumed, null, (ev, context) {
|
||||||
|
setState(() {
|
||||||
|
_isPlaying = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
player.on(MPVEvents.status, null, (ev, _) async {
|
||||||
|
Map data = ev.eventData as Map;
|
||||||
|
Playback playback = context.read<Playback>();
|
||||||
|
if (data["property"] == "media-title" && data["value"] != null) {
|
||||||
|
var containsYtdl = (data["value"] as String).contains("ytsearch:");
|
||||||
|
if (containsYtdl) {
|
||||||
|
var props = (data["value"] as String).split("-");
|
||||||
|
var mediaTitle = props.last.trim();
|
||||||
|
var mediaArtists = props.first.split("ytsearch:").last.trim();
|
||||||
|
setState(() {
|
||||||
|
_isPlaying = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
var matchedTracks = playback.currentPlaylist?.tracks.where(
|
||||||
|
(track) {
|
||||||
|
return track.name?.replaceAll("-", " ") == mediaTitle &&
|
||||||
|
artistsToString(track.artists ?? []) == mediaArtists;
|
||||||
|
},
|
||||||
|
) ??
|
||||||
|
[];
|
||||||
|
if (matchedTracks.isNotEmpty) {
|
||||||
|
playback.setCurrentTrack = matchedTracks.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data["property"] == "duration" && data["value"] != null) {
|
||||||
|
setState(() {
|
||||||
|
_duration = data["value"];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print("[PLAYER]: $e");
|
print("[PLAYER]: $e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
|
||||||
|
|
||||||
player.on(MPVEvents.paused, null, (ev, context) {
|
|
||||||
setState(() {
|
|
||||||
_isPlaying = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
player.on(MPVEvents.resumed, null, (ev, context) {
|
|
||||||
setState(() {
|
|
||||||
_isPlaying = true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
|
||||||
player.on(MPVEvents.status, null, (ev, _) async {
|
|
||||||
Map data = ev.eventData as Map;
|
|
||||||
Playback playback = context.read<Playback>();
|
|
||||||
if (data["property"] == "media-title" && data["value"] != null) {
|
|
||||||
var containsYtdl = (data["value"] as String).contains("ytsearch:");
|
|
||||||
if (containsYtdl) {
|
|
||||||
var props = (data["value"] as String).split("-");
|
|
||||||
var mediaTitle = props.last.trim();
|
|
||||||
var mediaArtists = props.first.split("ytsearch:").last.trim();
|
|
||||||
setState(() {
|
|
||||||
_isPlaying = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
var matchedTracks = playback.currentPlaylist?.tracks.where(
|
|
||||||
(track) {
|
|
||||||
return track.name?.replaceAll("-", " ") == mediaTitle &&
|
|
||||||
artistsToString(track.artists ?? []) == mediaArtists;
|
|
||||||
},
|
|
||||||
) ??
|
|
||||||
[];
|
|
||||||
if (matchedTracks.isNotEmpty) {
|
|
||||||
playback.setCurrentTrack = matchedTracks.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data["property"] == "duration" && data["value"] != null) {
|
|
||||||
setState(() {
|
|
||||||
_duration = data["value"];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
MPVPlayer player = context.read<PlayerDI>().player;
|
||||||
player.removeAllByEvent(MPVEvents.paused);
|
player.removeAllByEvent(MPVEvents.paused);
|
||||||
player.removeAllByEvent(MPVEvents.resumed);
|
player.removeAllByEvent(MPVEvents.resumed);
|
||||||
player.removeAllByEvent(MPVEvents.status);
|
player.removeAllByEvent(MPVEvents.status);
|
||||||
@ -115,7 +103,7 @@ class _PlayerState extends State<Player> {
|
|||||||
}).join("\n");
|
}).join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future playPlaylist(CurrentPlaylist playlist) async {
|
Future playPlaylist(MPVPlayer player, CurrentPlaylist playlist) async {
|
||||||
try {
|
try {
|
||||||
if (player.isRunning() && playlist.id != _currentPlaylistId) {
|
if (player.isRunning() && playlist.id != _currentPlaylistId) {
|
||||||
var playlistPath = "/tmp/playlist-${playlist.id}.txt";
|
var playlistPath = "/tmp/playlist-${playlist.id}.txt";
|
||||||
@ -146,12 +134,14 @@ class _PlayerState extends State<Player> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
MPVPlayer player = context.watch<PlayerDI>().player;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
color: Theme.of(context).backgroundColor,
|
color: Theme.of(context).backgroundColor,
|
||||||
child: Consumer<Playback>(
|
child: Consumer<Playback>(
|
||||||
builder: (context, playback, widget) {
|
builder: (context, playback, widget) {
|
||||||
if (playback.currentPlaylist != null) {
|
if (playback.currentPlaylist != null) {
|
||||||
playPlaylist(playback.currentPlaylist!);
|
playPlaylist(player, playback.currentPlaylist!);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? albumArt = playback.currentTrack?.album?.images?.last.url;
|
String? albumArt = playback.currentTrack?.album?.images?.last.url;
|
||||||
@ -166,6 +156,13 @@ class _PlayerState extends State<Player> {
|
|||||||
imageUrl: albumArt,
|
imageUrl: albumArt,
|
||||||
maxHeightDiskCache: 50,
|
maxHeightDiskCache: 50,
|
||||||
maxWidthDiskCache: 50,
|
maxWidthDiskCache: 50,
|
||||||
|
placeholder: (context, url) {
|
||||||
|
return Container(
|
||||||
|
height: 50,
|
||||||
|
width: 50,
|
||||||
|
color: Colors.green[400],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
// title of the currently playing track
|
// title of the currently playing track
|
||||||
Flexible(
|
Flexible(
|
||||||
|
@ -47,7 +47,13 @@ class _PlaylistCardState extends State<PlaylistCard> {
|
|||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: CachedNetworkImage(
|
child: CachedNetworkImage(
|
||||||
imageUrl: widget.playlist.images![0].url!),
|
imageUrl: widget.playlist.images![0].url!,
|
||||||
|
progressIndicatorBuilder: (context, url, progress) {
|
||||||
|
return CircularProgressIndicator.adaptive(
|
||||||
|
value: progress.progress,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Positioned.directional(
|
Positioned.directional(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
|
@ -23,18 +23,34 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
return (TableRow(
|
return (TableRow(
|
||||||
children: [
|
children: [
|
||||||
TableCell(
|
TableCell(
|
||||||
child: Text(
|
child: Padding(
|
||||||
(track.key + 1).toString(),
|
padding: const EdgeInsets.all(8.0),
|
||||||
textAlign: TextAlign.center,
|
child: Text(
|
||||||
|
(track.key + 1).toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
)),
|
)),
|
||||||
TableCell(
|
TableCell(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
if (thumbnailUrl != null)
|
if (thumbnailUrl != null)
|
||||||
CachedNetworkImage(
|
Padding(
|
||||||
imageUrl: thumbnailUrl,
|
padding: const EdgeInsets.all(8.0),
|
||||||
maxHeightDiskCache: 40,
|
child: ClipRRect(
|
||||||
maxWidthDiskCache: 40,
|
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||||
|
child: CachedNetworkImage(
|
||||||
|
placeholder: (context, url) {
|
||||||
|
return Container(
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
color: Colors.green[300],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
imageUrl: thumbnailUrl,
|
||||||
|
maxHeightDiskCache: 40,
|
||||||
|
maxWidthDiskCache: 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Flexible(
|
Flexible(
|
||||||
@ -62,16 +78,22 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
TableCell(
|
TableCell(
|
||||||
child: Text(
|
child: Padding(
|
||||||
track.value.album?.name ?? "",
|
padding: const EdgeInsets.all(8.0),
|
||||||
overflow: TextOverflow.ellipsis,
|
child: Text(
|
||||||
|
track.value.album?.name ?? "",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TableCell(
|
TableCell(
|
||||||
child: Text(
|
child: Padding(
|
||||||
duration,
|
padding: const EdgeInsets.all(8.0),
|
||||||
textAlign: TextAlign.center,
|
child: Text(
|
||||||
overflow: TextOverflow.ellipsis,
|
duration,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -148,7 +170,10 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
snapshot.hasError
|
snapshot.hasError
|
||||||
? const Center(child: Text("Error occurred"))
|
? const Center(child: Text("Error occurred"))
|
||||||
: !snapshot.hasData
|
: !snapshot.hasData
|
||||||
? const CircularProgressIndicator.adaptive()
|
? const Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator.adaptive()),
|
||||||
|
)
|
||||||
: Expanded(
|
: Expanded(
|
||||||
child: Scrollbar(
|
child: Scrollbar(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
@ -159,7 +184,7 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
0: FixedColumnWidth(40),
|
0: FixedColumnWidth(40),
|
||||||
1: FlexColumnWidth(),
|
1: FlexColumnWidth(),
|
||||||
2: FlexColumnWidth(),
|
2: FlexColumnWidth(),
|
||||||
3: FixedColumnWidth(40),
|
3: FixedColumnWidth(45),
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
TableRow(
|
TableRow(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mpv_dart/mpv_dart.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
@ -7,6 +8,7 @@ import 'package:spotube/components/Home.dart';
|
|||||||
import 'package:spotube/models/LocalStorageKeys.dart';
|
import 'package:spotube/models/LocalStorageKeys.dart';
|
||||||
import 'package:spotube/provider/Auth.dart';
|
import 'package:spotube/provider/Auth.dart';
|
||||||
import 'package:spotube/provider/Playback.dart';
|
import 'package:spotube/provider/Playback.dart';
|
||||||
|
import 'package:spotube/provider/PlayerDI.dart';
|
||||||
import 'package:spotube/provider/SpotifyDI.dart';
|
import 'package:spotube/provider/SpotifyDI.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@ -59,6 +61,15 @@ class MyApp extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
ChangeNotifierProvider<Playback>(create: (context) => Playback()),
|
ChangeNotifierProvider<Playback>(create: (context) => Playback()),
|
||||||
|
ChangeNotifierProvider<PlayerDI>(
|
||||||
|
create: (context) => PlayerDI(MPVPlayer(
|
||||||
|
audioOnly: true,
|
||||||
|
mpvArgs: [
|
||||||
|
"--ytdl-raw-options-set=format=140,http-chunk-size=300000",
|
||||||
|
"--script-opts=ytdl_hook-ytdl_path=yt-dlp",
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
@ -70,6 +81,7 @@ class MyApp extends StatelessWidget {
|
|||||||
buttonColor: Colors.green,
|
buttonColor: Colors.green,
|
||||||
),
|
),
|
||||||
shadowColor: Colors.grey[300],
|
shadowColor: Colors.grey[300],
|
||||||
|
backgroundColor: Colors.white,
|
||||||
textTheme: TextTheme(
|
textTheme: TextTheme(
|
||||||
bodyText1: TextStyle(color: Colors.grey[850]),
|
bodyText1: TextStyle(color: Colors.grey[850]),
|
||||||
headline1: TextStyle(color: Colors.grey[850]),
|
headline1: TextStyle(color: Colors.grey[850]),
|
||||||
@ -112,7 +124,7 @@ class MyApp extends StatelessWidget {
|
|||||||
backgroundColor: Colors.blueGrey[900],
|
backgroundColor: Colors.blueGrey[900],
|
||||||
scaffoldBackgroundColor: Colors.blueGrey[900],
|
scaffoldBackgroundColor: Colors.blueGrey[900],
|
||||||
dialogBackgroundColor: Colors.blueGrey[800],
|
dialogBackgroundColor: Colors.blueGrey[800],
|
||||||
shadowColor: Colors.black12,
|
shadowColor: Colors.black26,
|
||||||
buttonTheme: const ButtonThemeData(
|
buttonTheme: const ButtonThemeData(
|
||||||
buttonColor: Colors.green,
|
buttonColor: Colors.green,
|
||||||
),
|
),
|
||||||
|
15
lib/provider/PlayerDI.dart
Normal file
15
lib/provider/PlayerDI.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:mpv_dart/mpv_dart.dart';
|
||||||
|
|
||||||
|
class PlayerDI extends ChangeNotifier {
|
||||||
|
MPVPlayer _player;
|
||||||
|
|
||||||
|
PlayerDI(this._player);
|
||||||
|
|
||||||
|
get player => _player;
|
||||||
|
|
||||||
|
setPlayer(MPVPlayer player) {
|
||||||
|
_player = player;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user