Compare commits
3 Commits
master
...
kplayer2au
Author | SHA1 | Date |
---|---|---|
poka | 9b821402df | |
poka | 11c90c6d7f | |
poka | ed996df71e |
Before Width: | Height: | Size: 50 KiB |
|
@ -1,122 +1,122 @@
|
||||||
{
|
{
|
||||||
"images": [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-20x20@2x.png",
|
"size" : "20x20",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
"size": "20x20"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-20x20@3x.png",
|
"size" : "20x20",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "3x",
|
"filename" : "Icon-App-20x20@3x.png",
|
||||||
"size": "20x20"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-29x29@1x.png",
|
"size" : "29x29",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "1x",
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
"size": "29x29"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-29x29@2x.png",
|
"size" : "29x29",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
"size": "29x29"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-29x29@3x.png",
|
"size" : "29x29",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "3x",
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
"size": "29x29"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-40x40@2x.png",
|
"size" : "40x40",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
"size": "40x40"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-40x40@3x.png",
|
"size" : "40x40",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "3x",
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
"size": "40x40"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-60x60@2x.png",
|
"size" : "60x60",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
"size": "60x60"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-60x60@3x.png",
|
"size" : "60x60",
|
||||||
"idiom": "iphone",
|
"idiom" : "iphone",
|
||||||
"scale": "3x",
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
"size": "60x60"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-20x20@1x.png",
|
"size" : "20x20",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "1x",
|
"filename" : "Icon-App-20x20@1x.png",
|
||||||
"size": "20x20"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-20x20@2x.png",
|
"size" : "20x20",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
"size": "20x20"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-29x29@1x.png",
|
"size" : "29x29",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "1x",
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
"size": "29x29"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-29x29@2x.png",
|
"size" : "29x29",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
"size": "29x29"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-40x40@1x.png",
|
"size" : "40x40",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "1x",
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
"size": "40x40"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-40x40@2x.png",
|
"size" : "40x40",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
"size": "40x40"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-76x76@1x.png",
|
"size" : "76x76",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "1x",
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
"size": "76x76"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-76x76@2x.png",
|
"size" : "76x76",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
"size": "76x76"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-83.5x83.5@2x.png",
|
"size" : "83.5x83.5",
|
||||||
"idiom": "ipad",
|
"idiom" : "ipad",
|
||||||
"scale": "2x",
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
"size": "83.5x83.5"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "Icon-App-1024x1024@1x.png",
|
"size" : "1024x1024",
|
||||||
"idiom": "ios-marketing",
|
"idiom" : "ios-marketing",
|
||||||
"scale": "1x",
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
"size": "1024x1024"
|
"scale" : "1x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info": {
|
"info" : {
|
||||||
"author": "icons_launcher",
|
"version" : 1,
|
||||||
"version": 1
|
"author" : "xcode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:logger/logger.dart';
|
|
||||||
|
|
||||||
TextStyle globalTextStyle = TextStyle(color: Colors.grey[350]);
|
TextStyle globalTextStyle = TextStyle(color: Colors.grey[350]);
|
||||||
const proxyHeader =
|
const proxyHeader =
|
||||||
kDebugMode || !kIsWeb ? 'https://' : 'http://127.0.0.1:8080/';
|
kDebugMode || !kIsWeb ? 'https://' : 'http://127.0.0.1:8080/';
|
||||||
|
|
||||||
// Logger
|
|
||||||
final log = Logger();
|
|
||||||
|
|
||||||
// context
|
|
||||||
late BuildContext homeContext;
|
|
||||||
late BuildContext playerContext;
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:fipy/providers/download.dart';
|
|
||||||
import 'package:fipy/providers/home.dart';
|
import 'package:fipy/providers/home.dart';
|
||||||
import 'package:fipy/providers/player.dart';
|
import 'package:fipy/providers/player.dart';
|
||||||
import 'package:fipy/screens/home.dart';
|
import 'package:fipy/screens/home.dart';
|
||||||
|
@ -24,8 +23,7 @@ class FipyApp extends StatelessWidget {
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
title: 'Fipy',
|
title: 'Fipy',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.blue)
|
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.blue).copyWith(background: Colors.grey[900])),
|
||||||
.copyWith(background: Colors.grey[900])),
|
|
||||||
home: const HomeScreen(title: 'Fipy'),
|
home: const HomeScreen(title: 'Fipy'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
// ignore_for_file: use_build_context_synchronously
|
|
||||||
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:fipy/globals.dart';
|
|
||||||
import 'package:fipy/models/track.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
|
||||||
|
|
||||||
class DownloadProvider with ChangeNotifier {
|
|
||||||
Future downloadMusic(BuildContext context, Track track) async {
|
|
||||||
var yt = YoutubeExplode();
|
|
||||||
var manifest = await yt.videos.streamsClient.getManifest(track.id);
|
|
||||||
var streamManifest = StreamManifest(manifest.streams);
|
|
||||||
var streamInfo = streamManifest.audioOnly.withHighestBitrate();
|
|
||||||
var stream = yt.videos.streamsClient.get(streamInfo);
|
|
||||||
final fileName = '${track.title} - ${track.artiste}'
|
|
||||||
.replaceAll('\\', '')
|
|
||||||
.replaceAll('/', '')
|
|
||||||
.replaceAll(':', '')
|
|
||||||
.replaceAll('*', '')
|
|
||||||
.replaceAll('?', '')
|
|
||||||
.replaceAll('"', '')
|
|
||||||
.replaceAll('<', '')
|
|
||||||
.replaceAll('>', '')
|
|
||||||
.replaceAll('|', '');
|
|
||||||
|
|
||||||
if (!kIsWeb) {
|
|
||||||
final filePath = Platform.isAndroid
|
|
||||||
? Directory('/storage/emulated/0/Download')
|
|
||||||
: await getDownloadsDirectory();
|
|
||||||
|
|
||||||
var file = File('${filePath!.path}/$fileName.webm');
|
|
||||||
var fileStream = file.openWrite();
|
|
||||||
|
|
||||||
await stream.pipe(fileStream);
|
|
||||||
|
|
||||||
await fileStream.flush();
|
|
||||||
await fileStream.close();
|
|
||||||
yt.close();
|
|
||||||
// convertToMp3(file.path);
|
|
||||||
|
|
||||||
track.file = file;
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(playerContext).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content:
|
|
||||||
SizedBox(height: 90, child: Text('Son téléchargé: ${file.path}')),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
log.d(file.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reload() {
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,12 @@
|
||||||
|
// ignore_for_file: avoid_print
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:fipy/globals.dart';
|
import 'package:fipy/globals.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:universal_io/io.dart';
|
||||||
import 'package:fipy/models/track.dart';
|
import 'package:fipy/models/track.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
import 'package:fipy/providers/player.dart';
|
import 'package:fipy/providers/player.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -31,13 +36,12 @@ class HomeProvider with ChangeNotifier {
|
||||||
"Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
|
"Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
|
||||||
'Content-Type': 'text/plain'
|
'Content-Type': 'text/plain'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
Map body = jsonDecode(res.body);
|
Map body = jsonDecode(res.body);
|
||||||
if (body['next'] != null) {
|
if (body['next'] != null) {
|
||||||
cursor = body['next'];
|
cursor = body['next'];
|
||||||
} else {
|
} else {
|
||||||
log.d('Page N°$pageNbr');
|
print('Page N°$pageNbr');
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,12 +70,12 @@ class HomeProvider with ChangeNotifier {
|
||||||
return trackList;
|
return trackList;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future playTrack(Track track) async {
|
Future playTrack(BuildContext context, Track track) async {
|
||||||
var yt = YoutubeExplode();
|
final yt = YoutubeExplode();
|
||||||
PlayerProvider playerProvider =
|
PlayerProvider playerProvider =
|
||||||
Provider.of<PlayerProvider>(homeContext, listen: false);
|
Provider.of<PlayerProvider>(context, listen: false);
|
||||||
HomeProvider homeProvider =
|
HomeProvider homeProvider =
|
||||||
Provider.of<HomeProvider>(homeContext, listen: false);
|
Provider.of<HomeProvider>(context, listen: false);
|
||||||
|
|
||||||
// track = trackList[track.number - 1];
|
// track = trackList[track.number - 1];
|
||||||
currentTrack = track;
|
currentTrack = track;
|
||||||
|
@ -94,11 +98,11 @@ class HomeProvider with ChangeNotifier {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final source = UrlSource(
|
final source = UrlSource(
|
||||||
"https://${invidiousUrl[3]}/latest_version?id=${track.id}&itag=140&local=true&listen=1");
|
"https://${invidiousUrl[1]}/latest_version?id=${track.id}&itag=140&local=true&listen=1");
|
||||||
log.d(source.url);
|
print(source.url);
|
||||||
await player.play(source);
|
await player.play(source);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.d('Play error: $e');
|
print('Play error: $e');
|
||||||
}
|
}
|
||||||
Future.delayed(const Duration(milliseconds: 50));
|
Future.delayed(const Duration(milliseconds: 50));
|
||||||
|
|
||||||
|
@ -113,10 +117,10 @@ class HomeProvider with ChangeNotifier {
|
||||||
});
|
});
|
||||||
|
|
||||||
player.onPlayerComplete.listen((event) {
|
player.onPlayerComplete.listen((event) {
|
||||||
var nextTrack =
|
final nextTrack =
|
||||||
trackList.firstWhere((element) => element.number == track.number + 1);
|
trackList.firstWhere((element) => element.number == track.number + 1);
|
||||||
currentTrack = nextTrack;
|
currentTrack = nextTrack;
|
||||||
playTrack(nextTrack);
|
playTrack(context, nextTrack);
|
||||||
});
|
});
|
||||||
|
|
||||||
playerProvider.reload();
|
playerProvider.reload();
|
||||||
|
@ -124,31 +128,44 @@ class HomeProvider with ChangeNotifier {
|
||||||
yt.close();
|
yt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future nextTrack() async {
|
Future downloadMusic(BuildContext context, Track track) async {
|
||||||
if (currentTrack != null && currentTrack!.number < trackList.last.number) {
|
final yt = YoutubeExplode();
|
||||||
currentTrack = trackList
|
final manifest = await yt.videos.streamsClient.getManifest(track.id);
|
||||||
.firstWhere((element) => element.number == currentTrack!.number + 1);
|
final streamManifest = StreamManifest(manifest.streams);
|
||||||
await playTrack(currentTrack!);
|
final streamInfo = streamManifest.audioOnly.withHighestBitrate();
|
||||||
|
final stream = yt.videos.streamsClient.get(streamInfo);
|
||||||
|
final fileName = '${track.title} - ${track.artiste}'
|
||||||
|
.replaceAll('\\', '')
|
||||||
|
.replaceAll('/', '')
|
||||||
|
.replaceAll(':', '')
|
||||||
|
.replaceAll('*', '')
|
||||||
|
.replaceAll('?', '')
|
||||||
|
.replaceAll('"', '')
|
||||||
|
.replaceAll('<', '')
|
||||||
|
.replaceAll('>', '')
|
||||||
|
.replaceAll('|', '');
|
||||||
|
|
||||||
|
if (!kIsWeb) {
|
||||||
|
final filePath = Platform.isAndroid
|
||||||
|
? Directory('/storage/emulated/0/Download')
|
||||||
|
: await getDownloadsDirectory();
|
||||||
|
|
||||||
|
final file = File('${filePath!.path}/$fileName.webm');
|
||||||
|
final fileStream = file.openWrite();
|
||||||
|
|
||||||
|
await stream.pipe(fileStream);
|
||||||
|
|
||||||
|
await fileStream.flush();
|
||||||
|
await fileStream.close();
|
||||||
|
yt.close();
|
||||||
|
// convertToMp3(file.path);
|
||||||
|
|
||||||
|
track.file = file;
|
||||||
|
|
||||||
|
print(file.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future backTrack() async {
|
|
||||||
if (currentTrack != null && currentTrack!.number > 1) {
|
|
||||||
currentTrack = trackList
|
|
||||||
.firstWhere((element) => element.number == currentTrack!.number - 1);
|
|
||||||
await playTrack(currentTrack!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resumePlay() {
|
|
||||||
if (currentTrack == null) {
|
|
||||||
currentTrack = trackList.first;
|
|
||||||
playTrack(currentTrack!);
|
|
||||||
} else {
|
|
||||||
player.state.name == 'playing' ? player.pause() : player.resume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> get radioList {
|
List<DropdownMenuItem<String>> get radioList {
|
||||||
List<DropdownMenuItem<String>> menuItems = [
|
List<DropdownMenuItem<String>> menuItems = [
|
||||||
const DropdownMenuItem(value: "fip", child: Text("FIP")),
|
const DropdownMenuItem(value: "fip", child: Text("FIP")),
|
||||||
|
@ -160,7 +177,8 @@ class HomeProvider with ChangeNotifier {
|
||||||
const DropdownMenuItem(value: "fip_reggae", child: Text("Reggae")),
|
const DropdownMenuItem(value: "fip_reggae", child: Text("Reggae")),
|
||||||
const DropdownMenuItem(value: "fip_world", child: Text("World")),
|
const DropdownMenuItem(value: "fip_world", child: Text("World")),
|
||||||
const DropdownMenuItem(
|
const DropdownMenuItem(
|
||||||
value: "fip_nouveautes", child: Text("Nouveautés")),
|
value: "fip_nouveautes",
|
||||||
|
child: Text("Nouveautés")),
|
||||||
];
|
];
|
||||||
return menuItems;
|
return menuItems;
|
||||||
}
|
}
|
||||||
|
@ -180,3 +198,34 @@ class HomeProvider with ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DownloadProvider with ChangeNotifier {
|
||||||
|
void reload() {
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future convertToMp3(String audioFile) async {
|
||||||
|
// audioFile = 'E:\\Téléchargements/test.webm';
|
||||||
|
// final command = FfmpegCommand(
|
||||||
|
// inputs: [FfmpegInput.asset(audioFile)],
|
||||||
|
// args: [
|
||||||
|
// // CliArg(name: 'i', value: audioFile),
|
||||||
|
// const CliArg(name: 'ab', value: '320'),
|
||||||
|
// const CliArg(name: 'ar', value: '44100'),
|
||||||
|
// ],
|
||||||
|
// filterGraph: const FilterGraph(
|
||||||
|
// chains: [
|
||||||
|
// FilterChain(
|
||||||
|
// inputs: [],
|
||||||
|
// filters: [],
|
||||||
|
// outputs: [],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// outputFilepath: "E:\\Téléchargements/test.mp3",
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Execute command
|
||||||
|
// await Ffmpeg().run(command);
|
||||||
|
// }
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
// ignore_for_file: prefer_const_literals_to_create_immutables, avoid_print
|
// ignore_for_file: prefer_const_literals_to_create_immutables, avoid_print
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:fipy/globals.dart';
|
|
||||||
import 'package:fipy/models/track.dart';
|
import 'package:fipy/models/track.dart';
|
||||||
import 'package:fipy/providers/home.dart';
|
import 'package:fipy/providers/home.dart';
|
||||||
import 'package:fipy/providers/player.dart';
|
import 'package:fipy/providers/player.dart';
|
||||||
import 'package:fipy/widgets/download_track.dart';
|
|
||||||
import 'package:fipy/widgets/player/player.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:miniplayer/miniplayer.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
|
// import 'dart:math';
|
||||||
|
// import 'package:flutter/rendering.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
const HomeScreen({Key? key, required this.title}) : super(key: key);
|
const HomeScreen({Key? key, required this.title}) : super(key: key);
|
||||||
|
@ -23,169 +24,386 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
homeContext = context;
|
|
||||||
HomeProvider hp = Provider.of<HomeProvider>(context, listen: false);
|
HomeProvider hp = Provider.of<HomeProvider>(context, listen: false);
|
||||||
|
final MiniplayerController controller = MiniplayerController();
|
||||||
|
|
||||||
return RawKeyboardListener(
|
return RawKeyboardListener(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
onKey: (RawKeyEvent event) {
|
onKey: (RawKeyEvent event) {
|
||||||
// log.d(event.data.logicalKey.keyId);
|
if (event.runtimeType == RawKeyDownEvent &&
|
||||||
if (event.runtimeType == RawKeyDownEvent) //Enter Key ID from keyboard
|
event.data.logicalKey.keyId == 32) //Enter Key ID from keyboard
|
||||||
{
|
{
|
||||||
switch (event.data.logicalKey.keyId) {
|
hp.player.state.name == 'playing'
|
||||||
case 32:
|
? hp.player.pause()
|
||||||
case 112:
|
: hp.player.resume();
|
||||||
case 4294969861:
|
|
||||||
hp.resumePlay();
|
|
||||||
break;
|
|
||||||
case 110:
|
|
||||||
case 94489280688:
|
|
||||||
hp.nextTrack();
|
|
||||||
break;
|
|
||||||
case 98:
|
|
||||||
case 94489280689:
|
|
||||||
hp.backTrack();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: Colors.black,
|
body: RawScrollbar(
|
||||||
body: SingleChildScrollView(
|
thumbColor: Colors.grey[600],
|
||||||
child: Column(
|
radius: const Radius.circular(20),
|
||||||
children: <Widget>[
|
thickness: 12,
|
||||||
Container(
|
// thumbVisibility: true,
|
||||||
color: Colors.grey[900],
|
mainAxisMargin: 70,
|
||||||
height: 50,
|
child: SingleChildScrollView(
|
||||||
child: Row(
|
// controller: AdjustableScrollController(40),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
children: [
|
children: <Widget>[
|
||||||
DropdownButton(
|
Container(
|
||||||
dropdownColor: Colors.grey[900],
|
color: Colors.grey[900],
|
||||||
value: radio,
|
height: 50,
|
||||||
style: TextStyle(
|
child: Row(
|
||||||
fontSize: 15, color: Colors.grey[300]),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
underline: const SizedBox(),
|
children: [
|
||||||
iconSize: 22,
|
DropdownButton(
|
||||||
onChanged: (String? newRadio) {
|
dropdownColor: Colors.grey[900],
|
||||||
setState(() {
|
value: radio,
|
||||||
radio = newRadio!;
|
style: TextStyle(
|
||||||
});
|
fontSize: 15, color: Colors.grey[300]),
|
||||||
},
|
underline: const SizedBox(),
|
||||||
items: hp.radioList),
|
iconSize: 22,
|
||||||
const SizedBox(width: 50),
|
onChanged: (String? newRadio) {
|
||||||
DropdownButton(
|
setState(() {
|
||||||
dropdownColor: Colors.grey[900],
|
radio = newRadio!;
|
||||||
value: hp.userPageNbr.toString(),
|
});
|
||||||
style: TextStyle(
|
},
|
||||||
fontSize: 15, color: Colors.grey[300]),
|
items: hp.radioList),
|
||||||
underline: const SizedBox(),
|
const SizedBox(width: 50),
|
||||||
iconSize: 22,
|
DropdownButton(
|
||||||
onChanged: (String? newPageNumber) {
|
dropdownColor: Colors.grey[900],
|
||||||
setState(() {
|
value: hp.userPageNbr.toString(),
|
||||||
hp.userPageNbr = int.parse(newPageNumber!);
|
style: TextStyle(
|
||||||
});
|
fontSize: 15, color: Colors.grey[300]),
|
||||||
},
|
underline: const SizedBox(),
|
||||||
items: hp.pageList),
|
iconSize: 22,
|
||||||
]),
|
onChanged: (String? newPageNumber) {
|
||||||
),
|
setState(() {
|
||||||
FutureBuilder<List<Track>>(
|
hp.userPageNbr =
|
||||||
future: hp.getTracks(radio),
|
int.parse(newPageNumber!);
|
||||||
builder: (
|
});
|
||||||
BuildContext context,
|
},
|
||||||
AsyncSnapshot<List<Track>> snapshot,
|
items: hp.pageList),
|
||||||
) {
|
|
||||||
print(snapshot.connectionState);
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return Stack(children: [
|
|
||||||
Container(
|
|
||||||
height: 10000,
|
|
||||||
width: 10000,
|
|
||||||
color: const Color(0xFF121212)),
|
|
||||||
Center(
|
|
||||||
child: Column(children: [
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
SizedBox(
|
|
||||||
height: 30,
|
|
||||||
width: 30,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
color: Colors.amber[100],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]);
|
FutureBuilder<List<Track>>(
|
||||||
} else if (snapshot.connectionState ==
|
future: hp.getTracks(radio),
|
||||||
ConnectionState.done) {
|
builder: (
|
||||||
if (snapshot.hasError) {
|
BuildContext context,
|
||||||
return Stack(children: [
|
AsyncSnapshot<List<Track>> snapshot,
|
||||||
Container(
|
) {
|
||||||
height: 10000,
|
print(snapshot.connectionState);
|
||||||
width: 10000,
|
if (snapshot.connectionState ==
|
||||||
color: const Color(0xFF121212)),
|
ConnectionState.waiting) {
|
||||||
Center(
|
return Stack(children: [
|
||||||
child: Column(children: [
|
Container(
|
||||||
const SizedBox(height: 20),
|
height: 10000,
|
||||||
Text(
|
width: 10000,
|
||||||
'Error: ${snapshot.error}',
|
color: const Color(0xFF121212)),
|
||||||
style: TextStyle(color: Colors.grey[500]),
|
Center(
|
||||||
),
|
child: Column(children: [
|
||||||
]),
|
const SizedBox(height: 20),
|
||||||
),
|
SizedBox(
|
||||||
]);
|
height: 30,
|
||||||
} else if (snapshot.hasData) {
|
width: 30,
|
||||||
return Table(
|
child: CircularProgressIndicator(
|
||||||
columnWidths: {
|
color: Colors.amber[100],
|
||||||
0: const FlexColumnWidth(4),
|
),
|
||||||
1: const FlexColumnWidth(2),
|
),
|
||||||
2: const FlexColumnWidth(1),
|
]),
|
||||||
},
|
|
||||||
defaultVerticalAlignment:
|
|
||||||
TableCellVerticalAlignment.middle,
|
|
||||||
children: snapshot.data!
|
|
||||||
.map((item) => _buildTableRow(item))
|
|
||||||
.toList()
|
|
||||||
..insert(
|
|
||||||
0,
|
|
||||||
_buildTableRow(Track(
|
|
||||||
number: -1,
|
|
||||||
title: 'TITRE',
|
|
||||||
artiste: 'ARTISTE',
|
|
||||||
album: 'ALBUM',
|
|
||||||
id: 'URL')),
|
|
||||||
),
|
),
|
||||||
);
|
]);
|
||||||
} else {
|
} else if (snapshot.connectionState ==
|
||||||
return const Text('Empty data');
|
ConnectionState.done) {
|
||||||
}
|
if (snapshot.hasError) {
|
||||||
} else {
|
return Stack(children: [
|
||||||
return Text('State: ${snapshot.connectionState}');
|
Container(
|
||||||
}
|
height: 10000,
|
||||||
},
|
width: 10000,
|
||||||
|
color: const Color(0xFF121212)),
|
||||||
|
Center(
|
||||||
|
child: Column(children: [
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
'Error: ${snapshot.error}',
|
||||||
|
style: TextStyle(color: Colors.grey[500]),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
} else if (snapshot.hasData) {
|
||||||
|
return Table(
|
||||||
|
columnWidths: {
|
||||||
|
0: const FlexColumnWidth(4),
|
||||||
|
1: const FlexColumnWidth(2),
|
||||||
|
2: const FlexColumnWidth(1),
|
||||||
|
},
|
||||||
|
defaultVerticalAlignment:
|
||||||
|
TableCellVerticalAlignment.middle,
|
||||||
|
children: snapshot.data!
|
||||||
|
.map(
|
||||||
|
(item) => _buildTableRow(item, context))
|
||||||
|
.toList()
|
||||||
|
..insert(
|
||||||
|
0,
|
||||||
|
_buildTableRow(
|
||||||
|
Track(
|
||||||
|
number: -1,
|
||||||
|
title: 'TITRE',
|
||||||
|
artiste: 'ARTISTE',
|
||||||
|
album: 'ALBUM',
|
||||||
|
id: 'URL'),
|
||||||
|
context),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const Text('Empty data');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Text('State: ${snapshot.connectionState}');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 70)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 70)
|
)),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Player()
|
Consumer<PlayerProvider>(builder: (context, playerProvider, _) {
|
||||||
|
TextEditingController trackTitle = TextEditingController();
|
||||||
|
TextEditingController trackArtiste = TextEditingController();
|
||||||
|
trackTitle.text = hp.currentTrack?.title ?? '';
|
||||||
|
trackArtiste.text = hp.currentTrack?.artiste ?? '';
|
||||||
|
return Miniplayer(
|
||||||
|
controller: controller,
|
||||||
|
backgroundColor: Colors.grey[900]!,
|
||||||
|
minHeight: 70,
|
||||||
|
maxHeight: 70,
|
||||||
|
builder: (height, percentage) {
|
||||||
|
return Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
hp.currentTrack?.imageUrl != '' &&
|
||||||
|
hp.currentTrack?.imageUrl != null
|
||||||
|
? Image.network(
|
||||||
|
hp.currentTrack!.imageUrl!,
|
||||||
|
width: 70,
|
||||||
|
)
|
||||||
|
: const SizedBox(width: 70),
|
||||||
|
Expanded(
|
||||||
|
child: Column(children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
child: TextField(
|
||||||
|
enabled: false,
|
||||||
|
maxLines: 1,
|
||||||
|
controller: trackTitle,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
enabledBorder: InputBorder.none,
|
||||||
|
disabledBorder: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.only(left: 15),
|
||||||
|
),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey[300],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
child: TextField(
|
||||||
|
enabled: false,
|
||||||
|
maxLines: 1,
|
||||||
|
controller: trackArtiste,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
enabledBorder: InputBorder.none,
|
||||||
|
disabledBorder: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.only(left: 15),
|
||||||
|
),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.grey[500],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
Column(children: [
|
||||||
|
const Spacer(),
|
||||||
|
Row(children: [
|
||||||
|
const SizedBox(width: 70),
|
||||||
|
Column(children: [
|
||||||
|
IconButton(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
icon: Icon(Icons.skip_previous,
|
||||||
|
color: Colors.grey[500], size: 32),
|
||||||
|
onPressed: () {
|
||||||
|
if (hp.currentTrack != null &&
|
||||||
|
hp.currentTrack!.number > 1) {
|
||||||
|
hp.currentTrack = hp.trackList.firstWhere(
|
||||||
|
(element) =>
|
||||||
|
element.number ==
|
||||||
|
hp.currentTrack!.number - 1);
|
||||||
|
hp.playTrack(context, hp.currentTrack!);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
const SizedBox(width: 1),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
hp.player.state.name == 'playing'
|
||||||
|
? hp.player.pause()
|
||||||
|
: hp.player.resume();
|
||||||
|
|
||||||
|
// playerProvider.reload();
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
foregroundColor: Colors.grey[900],
|
||||||
|
backgroundColor: Colors.grey[300],
|
||||||
|
shape: const CircleBorder(),
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
hp.player.state.name == 'playing'
|
||||||
|
? Icons.pause
|
||||||
|
: Icons.play_arrow,
|
||||||
|
color: Colors.grey[900],
|
||||||
|
size: 30),
|
||||||
|
),
|
||||||
|
Column(children: [
|
||||||
|
IconButton(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
icon: Icon(Icons.skip_next,
|
||||||
|
color: Colors.grey[500], size: 32),
|
||||||
|
onPressed: () {
|
||||||
|
if (hp.currentTrack != null &&
|
||||||
|
hp.currentTrack!.number <
|
||||||
|
hp.trackList.last.number) {
|
||||||
|
hp.currentTrack = hp.trackList.firstWhere(
|
||||||
|
(element) =>
|
||||||
|
element.number ==
|
||||||
|
hp.currentTrack!.number + 1);
|
||||||
|
hp.playTrack(context, hp.currentTrack!);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
// const SizedBox(height: 7),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
const Spacer(),
|
||||||
|
Row(children: [
|
||||||
|
const SizedBox(width: 70),
|
||||||
|
Text(
|
||||||
|
timeFormat(hp.currentTrack?.position ??
|
||||||
|
const Duration(seconds: 0)),
|
||||||
|
style:
|
||||||
|
TextStyle(color: Colors.grey[500], fontSize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 3),
|
||||||
|
SliderTheme(
|
||||||
|
data: const SliderThemeData(
|
||||||
|
thumbShape:
|
||||||
|
RoundSliderThumbShape(enabledThumbRadius: 2),
|
||||||
|
overlayShape:
|
||||||
|
RoundSliderThumbShape(enabledThumbRadius: 5),
|
||||||
|
trackHeight: 2,
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 300,
|
||||||
|
child: Slider(
|
||||||
|
value: double.parse(hp
|
||||||
|
.currentTrack?.position?.inSeconds
|
||||||
|
.toString() ??
|
||||||
|
'0'),
|
||||||
|
max: double.parse(hp
|
||||||
|
.currentTrack?.duration?.inSeconds
|
||||||
|
.toString() ??
|
||||||
|
'2000'),
|
||||||
|
onChanged: (double value) {
|
||||||
|
if (hp.currentTrack?.position != null) {
|
||||||
|
hp.player.seek(
|
||||||
|
Duration(seconds: value.toInt()),
|
||||||
|
);
|
||||||
|
playerProvider.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activeColor: Colors.grey[400],
|
||||||
|
inactiveColor: Colors.grey[700],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 3),
|
||||||
|
Text(
|
||||||
|
timeFormat(hp.currentTrack?.duration ??
|
||||||
|
const Duration(seconds: 0)),
|
||||||
|
style:
|
||||||
|
TextStyle(color: Colors.grey[500], fontSize: 12),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
const Spacer(),
|
||||||
|
]),
|
||||||
|
const Spacer(),
|
||||||
|
SliderTheme(
|
||||||
|
data: const SliderThemeData(
|
||||||
|
thumbShape:
|
||||||
|
RoundSliderThumbShape(enabledThumbRadius: 7),
|
||||||
|
overlayShape:
|
||||||
|
RoundSliderThumbShape(enabledThumbRadius: 8),
|
||||||
|
trackHeight: 2.5,
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 130,
|
||||||
|
child: Slider(
|
||||||
|
value: hp.currentVolume,
|
||||||
|
max: 1,
|
||||||
|
onChanged: (double value) async {
|
||||||
|
hp.currentVolume = value;
|
||||||
|
await hp.player.setVolume(value);
|
||||||
|
playerProvider.reload();
|
||||||
|
},
|
||||||
|
activeColor: Colors.grey[400],
|
||||||
|
inactiveColor: Colors.grey[700],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TableRow _buildTableRow(Track track) {
|
Widget trackLine(Track track) {
|
||||||
final hp = Provider.of<HomeProvider>(homeContext, listen: false);
|
return SizedBox(
|
||||||
|
height: 30,
|
||||||
|
child: Row(
|
||||||
|
children: [Text('${track.title} - ${track.artiste}')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TableRow _buildTableRow(Track track, BuildContext context) {
|
||||||
|
DownloadProvider downloadProvider =
|
||||||
|
Provider.of<DownloadProvider>(context, listen: false);
|
||||||
|
HomeProvider hp = Provider.of<HomeProvider>(context, listen: false);
|
||||||
|
int isDownloading = -1;
|
||||||
|
|
||||||
final textStyle = TextStyle(
|
final textStyle = TextStyle(
|
||||||
fontWeight: track.number == -1 ? FontWeight.w200 : FontWeight.normal,
|
fontWeight: track.number == -1 ? FontWeight.w200 : FontWeight.normal,
|
||||||
color: Colors.grey[500],
|
color: Colors.grey[500],
|
||||||
fontSize: track.number == -1 ? 15 : 14);
|
fontSize: track.number == -1 ? 15 : 14);
|
||||||
const rowPadding = EdgeInsets.all(10);
|
const rowPadding = EdgeInsets.all(10);
|
||||||
|
final yt = YoutubeExplode();
|
||||||
|
|
||||||
return TableRow(
|
return TableRow(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
|
@ -198,7 +416,16 @@ TableRow _buildTableRow(Track track) {
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (track.number != -1) {
|
if (track.number != -1) {
|
||||||
hp.playTrack(track);
|
// FutureBuilder<void>(
|
||||||
|
// future: hp.playTrack(context, track),
|
||||||
|
// builder: (
|
||||||
|
// BuildContext context,
|
||||||
|
// AsyncSnapshot<void> snapshot,
|
||||||
|
// ) {
|
||||||
|
// return const SizedBox();
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
hp.playTrack(context, track);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
|
@ -243,9 +470,69 @@ TableRow _buildTableRow(Track track) {
|
||||||
),
|
),
|
||||||
TableCell(
|
TableCell(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: rowPadding,
|
padding: rowPadding,
|
||||||
child: DownloadTrack(track: track),
|
child: InkWell(
|
||||||
),
|
onTap: () async {
|
||||||
|
isDownloading = track.number;
|
||||||
|
downloadProvider.reload();
|
||||||
|
if (track.id == null) {
|
||||||
|
final secondMatch =
|
||||||
|
track.artiste == '' ? track.album : track.artiste;
|
||||||
|
final resultUrl = await yt.search
|
||||||
|
.search('${track.title} ${secondMatch!}');
|
||||||
|
track.id = resultUrl.first.id.value;
|
||||||
|
}
|
||||||
|
if (track.id != null) {
|
||||||
|
hp.downloadMusic(context, track);
|
||||||
|
}
|
||||||
|
isDownloading = -1;
|
||||||
|
yt.close();
|
||||||
|
downloadProvider.reload();
|
||||||
|
},
|
||||||
|
child: track.number == -1
|
||||||
|
? Text('TÉLÉCHARGER', style: textStyle)
|
||||||
|
: Consumer<DownloadProvider>(builder: (context, _, __) {
|
||||||
|
return Row(children: [
|
||||||
|
const SizedBox(width: 37),
|
||||||
|
isDownloading == track.number
|
||||||
|
? SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
color: Colors.grey[500],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(Icons.download, color: Colors.grey[500]),
|
||||||
|
]);
|
||||||
|
}))),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String timeFormat(Duration d) {
|
||||||
|
String dd = d.toString().split('.').first;
|
||||||
|
String minutes = dd.toString().split(':')[1];
|
||||||
|
String seconds = dd.toString().split(':')[2];
|
||||||
|
return '$minutes:$seconds';
|
||||||
|
}
|
||||||
|
|
||||||
|
// class AdjustableScrollController extends ScrollController {
|
||||||
|
// AdjustableScrollController([int extraScrollSpeed = 40]) {
|
||||||
|
// // super.initialScrollOffset = 50;
|
||||||
|
// super.addListener(() {
|
||||||
|
// ScrollDirection scrollDirection = super.position.userScrollDirection;
|
||||||
|
// if (scrollDirection != ScrollDirection.idle) {
|
||||||
|
// double scrollEnd = super.offset +
|
||||||
|
// (scrollDirection == ScrollDirection.reverse
|
||||||
|
// ? extraScrollSpeed
|
||||||
|
// : -extraScrollSpeed);
|
||||||
|
// scrollEnd = min(super.position.maxScrollExtent,
|
||||||
|
// max(super.position.minScrollExtent, scrollEnd));
|
||||||
|
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// if (super.hasClients) jumpTo(scrollEnd);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
import 'package:fipy/models/track.dart';
|
|
||||||
import 'package:fipy/providers/download.dart';
|
|
||||||
import 'package:fipy/providers/home.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
|
||||||
|
|
||||||
class DownloadTrack extends StatelessWidget {
|
|
||||||
const DownloadTrack({Key? key, this.track}) : super(key: key);
|
|
||||||
|
|
||||||
final Track? track;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final hp = Provider.of<HomeProvider>(context, listen: true);
|
|
||||||
final dl = Provider.of<DownloadProvider>(context, listen: false);
|
|
||||||
int isDownloading = -2;
|
|
||||||
final yt = YoutubeExplode();
|
|
||||||
|
|
||||||
final track = this.track ??
|
|
||||||
hp.currentTrack ??
|
|
||||||
Track(number: -3, title: 'title', artiste: 'artiste');
|
|
||||||
|
|
||||||
return InkWell(
|
|
||||||
onTap: track.number == -3
|
|
||||||
? null
|
|
||||||
: () async {
|
|
||||||
isDownloading = track.number;
|
|
||||||
dl.reload();
|
|
||||||
if (track.id == null) {
|
|
||||||
final secondMatch =
|
|
||||||
track.artiste == '' ? track.album : track.artiste;
|
|
||||||
final resultUrl =
|
|
||||||
await yt.search.search('${track.title} ${secondMatch!}');
|
|
||||||
track.id = resultUrl.first.id.value;
|
|
||||||
}
|
|
||||||
if (track.id != null) {
|
|
||||||
// ignore: use_build_context_synchronously
|
|
||||||
await dl.downloadMusic(context, track);
|
|
||||||
}
|
|
||||||
isDownloading = -2;
|
|
||||||
yt.close();
|
|
||||||
dl.reload();
|
|
||||||
},
|
|
||||||
child: Consumer<DownloadProvider>(builder: (context, _, __) {
|
|
||||||
return Row(children: [
|
|
||||||
const SizedBox(width: 37),
|
|
||||||
isDownloading == track.number
|
|
||||||
? SizedBox(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: Colors.grey[500],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Icon(Icons.download, color: Colors.grey[500]),
|
|
||||||
]);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
import 'package:fipy/globals.dart';
|
|
||||||
import 'package:fipy/providers/home.dart';
|
|
||||||
import 'package:fipy/widgets/download_track.dart';
|
|
||||||
import 'package:fipy/widgets/player/player_controls.dart';
|
|
||||||
import 'package:fipy/widgets/player/player_title.dart';
|
|
||||||
import 'package:fipy/widgets/player/player_volume.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:miniplayer/miniplayer.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class Player extends StatelessWidget {
|
|
||||||
const Player({
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
playerContext = context;
|
|
||||||
final controller = MiniplayerController();
|
|
||||||
final hp = Provider.of<HomeProvider>(context, listen: false);
|
|
||||||
|
|
||||||
return Miniplayer(
|
|
||||||
controller: controller,
|
|
||||||
backgroundColor: Colors.grey[900]!,
|
|
||||||
minHeight: 70,
|
|
||||||
maxHeight: 70,
|
|
||||||
builder: (height, percentage) {
|
|
||||||
return Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
hp.currentTrack?.imageUrl != '' && hp.currentTrack?.imageUrl != null
|
|
||||||
? Image.network(
|
|
||||||
hp.currentTrack!.imageUrl!,
|
|
||||||
width: 70,
|
|
||||||
)
|
|
||||||
: const SizedBox(width: 70),
|
|
||||||
const PlayerTitle(),
|
|
||||||
const SizedBox(width: 90),
|
|
||||||
const PlayerControls(),
|
|
||||||
const Spacer(),
|
|
||||||
const DownloadTrack(),
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
const PlayerVolume(),
|
|
||||||
const SizedBox(width: 20)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
import 'package:fipy/providers/home.dart';
|
|
||||||
import 'package:fipy/providers/player.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class PlayerControls extends StatelessWidget {
|
|
||||||
const PlayerControls({
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final hp = Provider.of<HomeProvider>(context, listen: true);
|
|
||||||
final playerProvider = Provider.of<PlayerProvider>(context, listen: true);
|
|
||||||
return Column(children: [
|
|
||||||
const Spacer(),
|
|
||||||
Row(children: [
|
|
||||||
const SizedBox(width: 70),
|
|
||||||
Column(children: [
|
|
||||||
IconButton(
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
icon:
|
|
||||||
Icon(Icons.skip_previous, color: Colors.grey[500], size: 32),
|
|
||||||
onPressed: () {
|
|
||||||
hp.backTrack();
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
const SizedBox(width: 1),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
hp.resumePlay();
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
foregroundColor: Colors.grey[900],
|
|
||||||
backgroundColor: Colors.grey[300],
|
|
||||||
shape: const CircleBorder(),
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
),
|
|
||||||
child: Icon(
|
|
||||||
hp.player.state.name == 'playing'
|
|
||||||
? Icons.pause
|
|
||||||
: Icons.play_arrow,
|
|
||||||
color: Colors.grey[900],
|
|
||||||
size: 30),
|
|
||||||
),
|
|
||||||
Column(children: [
|
|
||||||
IconButton(
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
icon: Icon(Icons.skip_next, color: Colors.grey[500], size: 32),
|
|
||||||
onPressed: () {
|
|
||||||
hp.nextTrack();
|
|
||||||
}),
|
|
||||||
// const SizedBox(height: 7),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
const Spacer(),
|
|
||||||
Row(children: [
|
|
||||||
const SizedBox(width: 70),
|
|
||||||
Text(
|
|
||||||
timeFormat(hp.currentTrack?.position ?? const Duration(seconds: 0)),
|
|
||||||
style: TextStyle(color: Colors.grey[500], fontSize: 12),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 3),
|
|
||||||
(hp.currentTrack?.duration?.inSeconds ?? -1) <= 0
|
|
||||||
? Column(
|
|
||||||
children: [
|
|
||||||
const SizedBox(width: 300),
|
|
||||||
hp.currentTrack?.title == null
|
|
||||||
? Text(
|
|
||||||
'Choisissez un titre',
|
|
||||||
style: TextStyle(color: Colors.grey[500]),
|
|
||||||
)
|
|
||||||
: const SizedBox(
|
|
||||||
height: 15,
|
|
||||||
width: 15,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: Colors.orange,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: SliderTheme(
|
|
||||||
data: const SliderThemeData(
|
|
||||||
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 2),
|
|
||||||
overlayShape: RoundSliderThumbShape(enabledThumbRadius: 5),
|
|
||||||
trackHeight: 2,
|
|
||||||
),
|
|
||||||
child: SizedBox(
|
|
||||||
width: 300,
|
|
||||||
child: Slider(
|
|
||||||
value: double.parse(
|
|
||||||
hp.currentTrack?.position?.inSeconds.toString() ?? '0'),
|
|
||||||
max: double.parse(
|
|
||||||
hp.currentTrack?.duration?.inSeconds.toString() ??
|
|
||||||
'2000'),
|
|
||||||
onChanged: (double value) {
|
|
||||||
if (hp.currentTrack?.position != null) {
|
|
||||||
hp.player.seek(
|
|
||||||
Duration(seconds: value.toInt()),
|
|
||||||
);
|
|
||||||
playerProvider.reload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activeColor: Colors.grey[400],
|
|
||||||
inactiveColor: Colors.grey[700],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 3),
|
|
||||||
Text(
|
|
||||||
timeFormat(hp.currentTrack?.duration ?? const Duration(seconds: 0)),
|
|
||||||
style: TextStyle(color: Colors.grey[500], fontSize: 12),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
const Spacer(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String timeFormat(Duration d) {
|
|
||||||
String dd = d.toString().split('.').first;
|
|
||||||
String minutes = dd.toString().split(':')[1];
|
|
||||||
String seconds = dd.toString().split(':')[2];
|
|
||||||
return '$minutes:$seconds';
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
import 'package:fipy/providers/home.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class PlayerTitle extends StatelessWidget {
|
|
||||||
const PlayerTitle({
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final hp = Provider.of<HomeProvider>(context, listen: true);
|
|
||||||
final trackTitle = TextEditingController();
|
|
||||||
final trackArtiste = TextEditingController();
|
|
||||||
trackTitle.text = hp.currentTrack?.title ?? '';
|
|
||||||
trackArtiste.text = hp.currentTrack?.artiste ?? '';
|
|
||||||
|
|
||||||
return Expanded(
|
|
||||||
child: Column(children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 20,
|
|
||||||
child: TextField(
|
|
||||||
enabled: false,
|
|
||||||
maxLines: 1,
|
|
||||||
controller: trackTitle,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
focusedBorder: InputBorder.none,
|
|
||||||
enabledBorder: InputBorder.none,
|
|
||||||
disabledBorder: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.only(left: 15),
|
|
||||||
),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.grey[300],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 20,
|
|
||||||
child: TextField(
|
|
||||||
enabled: false,
|
|
||||||
maxLines: 1,
|
|
||||||
controller: trackArtiste,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
focusedBorder: InputBorder.none,
|
|
||||||
enabledBorder: InputBorder.none,
|
|
||||||
disabledBorder: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.only(left: 15),
|
|
||||||
),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.grey[500],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
import 'package:fipy/providers/home.dart';
|
|
||||||
import 'package:fipy/providers/player.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class PlayerVolume extends StatelessWidget {
|
|
||||||
const PlayerVolume({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final hp = Provider.of<HomeProvider>(context, listen: false);
|
|
||||||
final playerProvider = Provider.of<PlayerProvider>(context, listen: true);
|
|
||||||
|
|
||||||
return SliderTheme(
|
|
||||||
data: const SliderThemeData(
|
|
||||||
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 7),
|
|
||||||
overlayShape: RoundSliderThumbShape(enabledThumbRadius: 8),
|
|
||||||
trackHeight: 2.5,
|
|
||||||
),
|
|
||||||
child: SizedBox(
|
|
||||||
width: 130,
|
|
||||||
child: Slider(
|
|
||||||
value: hp.currentVolume,
|
|
||||||
max: 1,
|
|
||||||
onChanged: (double value) async {
|
|
||||||
hp.currentVolume = value;
|
|
||||||
await hp.player.setVolume(value);
|
|
||||||
playerProvider.reload();
|
|
||||||
},
|
|
||||||
activeColor: Colors.grey[400],
|
|
||||||
inactiveColor: Colors.grey[700],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
import FlutterMacOS
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import audioplayers_darwin
|
|
||||||
import path_provider_foundation
|
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|
||||||
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
|
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
// This is a generated file; do not edit or check into version control.
|
|
||||||
FLUTTER_ROOT=C:\Users\poka\dev\flutter
|
|
||||||
FLUTTER_APPLICATION_PATH=C:\Users\poka\dev\fipy
|
|
||||||
COCOAPODS_PARALLEL_CODE_SIGN=true
|
|
||||||
FLUTTER_BUILD_DIR=build
|
|
||||||
FLUTTER_BUILD_NAME=0.0.2
|
|
||||||
FLUTTER_BUILD_NUMBER=2
|
|
||||||
DART_OBFUSCATION=false
|
|
||||||
TRACK_WIDGET_CREATION=true
|
|
||||||
TREE_SHAKE_ICONS=false
|
|
||||||
PACKAGE_CONFIG=.dart_tool/package_config.json
|
|
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# This is a generated file; do not edit or check into version control.
|
|
||||||
export "FLUTTER_ROOT=C:\Users\poka\dev\flutter"
|
|
||||||
export "FLUTTER_APPLICATION_PATH=C:\Users\poka\dev\fipy"
|
|
||||||
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
|
||||||
export "FLUTTER_BUILD_DIR=build"
|
|
||||||
export "FLUTTER_BUILD_NAME=0.0.2"
|
|
||||||
export "FLUTTER_BUILD_NUMBER=2"
|
|
||||||
export "DART_OBFUSCATION=false"
|
|
||||||
export "TRACK_WIDGET_CREATION=true"
|
|
||||||
export "TREE_SHAKE_ICONS=false"
|
|
||||||
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
|
|
@ -1,68 +0,0 @@
|
||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"filename": "app_icon_16.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "1x",
|
|
||||||
"size": "16x16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_32.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "2x",
|
|
||||||
"size": "16x16"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_32.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "1x",
|
|
||||||
"size": "32x32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_64.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "2x",
|
|
||||||
"size": "32x32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_128.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "1x",
|
|
||||||
"size": "128x128"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_256.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "2x",
|
|
||||||
"size": "128x128"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_256.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "1x",
|
|
||||||
"size": "256x256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_512.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "2x",
|
|
||||||
"size": "256x256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_512.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "1x",
|
|
||||||
"size": "512x512"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "app_icon_1024.png",
|
|
||||||
"idiom": "mac",
|
|
||||||
"scale": "2x",
|
|
||||||
"size": "512x512"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"author": "icons_launcher",
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 396 B |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 871 B |
Before Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 2.1 KiB |
|
@ -36,9 +36,13 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\dart_vlc_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\libvlc.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\libvlccore.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\audioplayers_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\audioplayers_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
Source: "C:\Users\poka\dev\fipy\build\windows\runner\Release\plugins\*"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
|
|
|
@ -264,14 +264,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
logger:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: logger
|
|
||||||
sha256: db2ff852ed77090ba9f62d3611e4208a3d11dfa35991a81ae724c113fcb3e3f7
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.0"
|
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
37
pubspec.yaml
|
@ -2,7 +2,7 @@ name: fipy
|
||||||
description: Advanced FIP radio track explorer
|
description: Advanced FIP radio track explorer
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
version: 0.0.3+2
|
version: 0.0.2+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.16.2 <3.0.0"
|
sdk: ">=2.16.2 <3.0.0"
|
||||||
|
@ -27,39 +27,20 @@ dependencies:
|
||||||
universal_io: ^2.0.4
|
universal_io: ^2.0.4
|
||||||
# ffmpeg_cli: ^0.1.0
|
# ffmpeg_cli: ^0.1.0
|
||||||
audioplayers: ^4.0.1
|
audioplayers: ^4.0.1
|
||||||
logger: ^1.3.0
|
|
||||||
# git:
|
|
||||||
# url: https://github.com/bluefireteam/audioplayers/tree/main/packages/audioplayers_linux
|
|
||||||
# ref: main
|
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
icons_launcher: ^2.0.6
|
icons_launcher: ^2.1.0
|
||||||
|
|
||||||
icons_launcher:
|
flutter_icons:
|
||||||
image_path: 'assets/logo_green_dark.jpg'
|
android: true
|
||||||
platforms:
|
ios: true
|
||||||
android:
|
# macos: true
|
||||||
enable: true
|
windows: true
|
||||||
ios:
|
web: true
|
||||||
enable: true
|
image_path: "assets/logo_green_dark.jpg"
|
||||||
windows:
|
|
||||||
enable: true
|
|
||||||
linux:
|
|
||||||
enable: true
|
|
||||||
macos:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
# flutter_icons:
|
|
||||||
# android: true
|
|
||||||
# ios: true
|
|
||||||
# # macos: true
|
|
||||||
# windows: true
|
|
||||||
# web: true
|
|
||||||
# image_path: "assets/logo_green_dark.jpg"
|
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[Desktop Entry]
|
|
||||||
Name=Flutter Linux App
|
|
||||||
Comment=Flutter Linux launcher icon
|
|
||||||
Exec=app_icon
|
|
||||||
Icon=app_icon.png
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
Categories=Entertainment;
|
|
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 33 KiB |