Merge branch 'feat/retours' into 'main'
Feat/retours See merge request jscampucci/libu-notube!3
This commit is contained in:
commit
9bbf38dce1
|
|
@ -47,3 +47,4 @@ app.*.map.json
|
||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
samples/
|
samples/
|
||||||
|
apps_logs.txt
|
||||||
|
|
@ -10,10 +10,12 @@ const colorMainBlue = Color(0xFF1f74ad);
|
||||||
enum Format {
|
enum Format {
|
||||||
mp3(
|
mp3(
|
||||||
format: 'MP3',
|
format: 'MP3',
|
||||||
|
ytCmd: 'bestaudio[ext=m4a]/bestaudio[ext=webm]',
|
||||||
ffmpegCmd: '-f mp3 -loglevel quiet -ab 192k -vn',
|
ffmpegCmd: '-f mp3 -loglevel quiet -ab 192k -vn',
|
||||||
extension: 'mp3'),
|
extension: 'mp3'),
|
||||||
mp3HD(
|
mp3HD(
|
||||||
format: 'MP3 HD',
|
format: 'MP3 HD',
|
||||||
|
ytCmd: 'bestaudio[ext=m4a]/bestaudio[ext=webm]',
|
||||||
ffmpegCmd: '-f mp3 -loglevel quiet -ab 320k -vn',
|
ffmpegCmd: '-f mp3 -loglevel quiet -ab 320k -vn',
|
||||||
extension: 'mp3'),
|
extension: 'mp3'),
|
||||||
mp4(format: 'MP4'),
|
mp4(format: 'MP4'),
|
||||||
|
|
@ -35,7 +37,11 @@ enum Format {
|
||||||
ffmpegCmd:
|
ffmpegCmd:
|
||||||
'-vcodec libx264 -preset slower -b 512k -bt 512k -threads 0 -s 640x360 -aspect 16:9 -acodec libmp3lame -ar 44100 -ab 32 -progress pipe:1',
|
'-vcodec libx264 -preset slower -b 512k -bt 512k -threads 0 -s 640x360 -aspect 16:9 -acodec libmp3lame -ar 44100 -ab 32 -progress pipe:1',
|
||||||
extension: 'flv'),
|
extension: 'flv'),
|
||||||
m4a(format: 'M4A'),
|
m4a(
|
||||||
|
format: 'M4A',
|
||||||
|
ytCmd: 'bestaudio[ext=m4a]',
|
||||||
|
extension: 'm4a',
|
||||||
|
),
|
||||||
;
|
;
|
||||||
|
|
||||||
final String ytCmd;
|
final String ytCmd;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class _SubmitButtonState extends State<SubmitButton> {
|
||||||
|
|
||||||
void addVideosListener(BuildContext context, DlFormState state) {
|
void addVideosListener(BuildContext context, DlFormState state) {
|
||||||
if (state.isParsed) {
|
if (state.isParsed) {
|
||||||
|
context.read<VideosCubit>().setGlobalStatus('loaded');
|
||||||
for (Video video in state.videos) {
|
for (Video video in state.videos) {
|
||||||
debugPrint('Adding video: $video');
|
debugPrint('Adding video: $video');
|
||||||
context.read<VideosCubit>().addVideo(video);
|
context.read<VideosCubit>().addVideo(video);
|
||||||
|
|
@ -45,6 +46,7 @@ class _SubmitButtonState extends State<SubmitButton> {
|
||||||
},
|
},
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
context.read<VideosCubit>().setGlobalStatus('loading');
|
||||||
context.read<DlFormCubit>().parseUrl();
|
context.read<DlFormCubit>().parseUrl();
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
import 'package:notube/screens/settings.dart';
|
import 'package:notube/screens/settings.dart';
|
||||||
import 'package:notube/wrapper.dart';
|
import 'package:notube/wrapper.dart';
|
||||||
import 'package:notube/constants.dart';
|
import 'package:notube/constants.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
import 'package:upgrader/upgrader.dart';
|
import 'package:upgrader/upgrader.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:notube/videoList/cubit/videos_cubit.dart';
|
import 'package:notube/videoList/cubit/videos_cubit.dart';
|
||||||
|
import 'package:notube/services/file_logger.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
@ -25,6 +31,12 @@ void main() async {
|
||||||
await windowManager.focus();
|
await windowManager.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await FileLogger().init();
|
||||||
|
|
||||||
|
FlutterError.onError = (FlutterErrorDetails details) {
|
||||||
|
FileLogger().e('FlutterError', details.exception, details.stack);
|
||||||
|
};
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
EasyLocalization(
|
EasyLocalization(
|
||||||
supportedLocales: [Locale('en', 'US'), Locale('fr', 'FR')],
|
supportedLocales: [Locale('en', 'US'), Locale('fr', 'FR')],
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,41 @@ class Home extends StatelessWidget {
|
||||||
child: BlocConsumer<VideosCubit, VideosState>(
|
child: BlocConsumer<VideosCubit, VideosState>(
|
||||||
listener: (context, state) {},
|
listener: (context, state) {},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return ListView.builder(
|
var returnWidget = <Widget>[];
|
||||||
itemCount: state.videoList.length,
|
switch (state.status) {
|
||||||
|
case 'loading':
|
||||||
|
returnWidget.add(Center(
|
||||||
|
child: CircularProgressIndicator()));
|
||||||
|
case 'error':
|
||||||
|
returnWidget.add(Center(
|
||||||
|
child: Text('home_dl_error').tr(),
|
||||||
|
));
|
||||||
|
default:
|
||||||
|
returnWidget.add(ListView.builder(
|
||||||
|
itemCount: state.videoList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var currentVideo =
|
||||||
|
state.videoList[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: SizedBox(
|
||||||
|
width: 72,
|
||||||
|
height: 48,
|
||||||
|
child: Image.network(
|
||||||
|
currentVideo.thumbnail,
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
title: Text(currentVideo.title),
|
||||||
|
subtitle: Text(
|
||||||
|
'${currentVideo.status} - ${currentVideo.format.format}'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
returnWidget.add(ListView.builder(
|
||||||
|
itemCount: state.archiveList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
var currentVideo = state.videoList[index];
|
var currentVideo =
|
||||||
|
state.archiveList[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: SizedBox(
|
leading: SizedBox(
|
||||||
width: 72,
|
width: 72,
|
||||||
|
|
@ -64,6 +95,9 @@ class Home extends StatelessWidget {
|
||||||
'${currentVideo.status} - ${currentVideo.format.format}'),
|
'${currentVideo.status} - ${currentVideo.format.format}'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
));
|
||||||
|
return Stack(
|
||||||
|
children: returnWidget,
|
||||||
);
|
);
|
||||||
})),
|
})),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:get/get_navigation/src/nav2/get_router_delegate.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
import 'package:notube/constants.dart';
|
import 'package:notube/constants.dart';
|
||||||
import 'package:notube/models/video.dart';
|
import 'package:notube/models/video.dart';
|
||||||
|
import 'package:notube/services/file_logger.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:process_run/shell.dart';
|
import 'package:process_run/shell.dart';
|
||||||
|
|
||||||
|
|
@ -91,12 +94,29 @@ class DLServices {
|
||||||
var command = '${url.trim()} -q --flat-playlist -J';
|
var command = '${url.trim()} -q --flat-playlist -J';
|
||||||
|
|
||||||
var shellLinesController = ShellLinesController();
|
var shellLinesController = ShellLinesController();
|
||||||
var shell = Shell(stdout: shellLinesController.sink, verbose: false);
|
var shellErrorController = ShellLinesController();
|
||||||
|
|
||||||
|
shellErrorController.stream.listen((event) {
|
||||||
|
debugPrint('Analyse error: $event');
|
||||||
|
FileLogger().e('Analyse error: $event');
|
||||||
|
});
|
||||||
|
|
||||||
|
var shell = Shell(
|
||||||
|
stdout: shellLinesController.sink,
|
||||||
|
stderr: shellErrorController.sink,
|
||||||
|
verbose: false);
|
||||||
|
|
||||||
await shell.run('''
|
await shell.run('''
|
||||||
$ytDlpPath $command
|
$ytDlpPath $command
|
||||||
''').then((result) {
|
''').then((result) {
|
||||||
debugPrint('Analyse result: $result');
|
debugPrint('Analyse error: $result');
|
||||||
|
|
||||||
|
FileLogger().d('Analyse result: ${result.toString()}');
|
||||||
|
}).catchError((
|
||||||
|
error,
|
||||||
|
stackTrace,
|
||||||
|
) {
|
||||||
|
FileLogger().e('Analyse error: $error');
|
||||||
});
|
});
|
||||||
|
|
||||||
return shellLinesController.stream;
|
return shellLinesController.stream;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class FileLogger {
|
||||||
|
static final FileLogger _instance = FileLogger._internal();
|
||||||
|
late Logger _logger;
|
||||||
|
late File _logFile;
|
||||||
|
|
||||||
|
factory FileLogger() {
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileLogger._internal();
|
||||||
|
|
||||||
|
Future<void> init() async {
|
||||||
|
_logFile = File('apps_logs.txt');
|
||||||
|
|
||||||
|
_logger = Logger(
|
||||||
|
printer: PrettyPrinter(),
|
||||||
|
output: FileOutput(file: _logFile),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void d(String message) {
|
||||||
|
_logger.d(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i(String message) {
|
||||||
|
_logger.i(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void w(String message) {
|
||||||
|
_logger.w(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void e(String message, [dynamic error, StackTrace? stackTrace]) {
|
||||||
|
_logger.e(message, error: error, stackTrace: stackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> getLogContent() async {
|
||||||
|
return await _logFile.readAsString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,5 +7,6 @@
|
||||||
"download_folder": "Download folder",
|
"download_folder": "Download folder",
|
||||||
"en_US": "English",
|
"en_US": "English",
|
||||||
"fr_FR": "French",
|
"fr_FR": "French",
|
||||||
"Ok": "OK"
|
"Ok": "OK",
|
||||||
|
"home_dl_error": "Error while downloading the video"
|
||||||
}
|
}
|
||||||
|
|
@ -7,5 +7,6 @@
|
||||||
"download_folder": "Dossier de téléchargement",
|
"download_folder": "Dossier de téléchargement",
|
||||||
"en_US": "Anglais",
|
"en_US": "Anglais",
|
||||||
"fr_FR": "Français",
|
"fr_FR": "Français",
|
||||||
"Ok": "OK"
|
"Ok": "OK",
|
||||||
|
"home_dl_error": "Erreur lors du téléchargement de la vidéo"
|
||||||
}
|
}
|
||||||
|
|
@ -19,41 +19,54 @@ class VideosCubit extends Cubit<VideosState> {
|
||||||
late DLServices dlService;
|
late DLServices dlService;
|
||||||
late ConverterService converterService;
|
late ConverterService converterService;
|
||||||
|
|
||||||
final List<Video> _videoList = [];
|
|
||||||
List<Video> get videoList => _videoList;
|
|
||||||
Iterable<Video> downloadingVid = [];
|
Iterable<Video> downloadingVid = [];
|
||||||
|
|
||||||
int runningTasks = 0;
|
int runningTasks = 0;
|
||||||
int maxConcurrentTasks = 3;
|
int maxConcurrentTasks = 3;
|
||||||
|
|
||||||
void addVideo(Video video) {
|
void addVideo(Video video) {
|
||||||
_videoList.add(video);
|
var nVideoList = state.videoList.toList();
|
||||||
emit(VideosState(videoList: _videoList));
|
nVideoList.add(video);
|
||||||
|
emit(VideosState(videoList: nVideoList));
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeStatus(Video video, String status) {
|
Future<void> changeStatus(Video video, String status) async {
|
||||||
int index = _videoList.indexWhere((v) => v.id == video.id);
|
var completer = Completer<void>();
|
||||||
|
var tmpVideoList = state.videoList.toList();
|
||||||
|
int index = tmpVideoList.indexWhere((v) => v.id == video.id);
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
_videoList[index] = video.copyWith(status: status);
|
tmpVideoList[index] = video.copyWith(status: status);
|
||||||
emit(VideosState(videoList: _videoList));
|
emit(VideosState(videoList: tmpVideoList));
|
||||||
|
completer.complete();
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Video not found in the list');
|
debugPrint('Video not found in the list');
|
||||||
|
completer.completeError('Video not found in the list');
|
||||||
}
|
}
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGlobalStatus(String status) {
|
||||||
|
emit(VideosState(status: status));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearVideos() {
|
void clearVideos() {
|
||||||
_videoList.clear();
|
emit(VideosState(videoList: []));
|
||||||
emit(VideosState(videoList: _videoList));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeVideo(Video video) {
|
void removeVideo(Video video) {
|
||||||
_videoList.remove(video);
|
var nVideoList = state.videoList.where((v) => v.id != video.id).toList();
|
||||||
emit(VideosState(videoList: _videoList));
|
emit(VideosState(videoList: nVideoList));
|
||||||
|
}
|
||||||
|
|
||||||
|
void archiveVideo(Video video) {
|
||||||
|
debugPrint('Archiving video: ${video.title} ${video.format.format}');
|
||||||
|
var nVideoList = state.videoList.where((v) => v.id != video.id).toList();
|
||||||
|
emit(VideosState(videoList: nVideoList, archiveList: [video]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> startConverter() async {
|
Future<void> startConverter() async {
|
||||||
var videosToConvert = _videoList.where((video) =>
|
var videosToConvert = state.videoList.where((video) =>
|
||||||
video.status == 'downloaded' &&
|
video.status == 'downloaded' &&
|
||||||
convertedFormats.contains(video.format));
|
convertedFormats.contains(video.format));
|
||||||
for (Video video in videosToConvert) {
|
for (Video video in videosToConvert) {
|
||||||
|
|
@ -64,20 +77,37 @@ class VideosCubit extends Cubit<VideosState> {
|
||||||
|
|
||||||
Future<void> startDownloader() async {
|
Future<void> startDownloader() async {
|
||||||
dlService = await DLServices.init();
|
dlService = await DLServices.init();
|
||||||
downloadingVid =
|
|
||||||
_videoList.where((video) => video.status == 'pending').take(3);
|
|
||||||
|
|
||||||
debugPrint('Videos to download: ${downloadingVid.length}');
|
downloadingVid =
|
||||||
|
state.videoList.where((video) => video.status == 'pending').take(3);
|
||||||
|
|
||||||
while (downloadingVid.isNotEmpty && runningTasks < maxConcurrentTasks) {
|
while (downloadingVid.isNotEmpty && runningTasks < maxConcurrentTasks) {
|
||||||
|
debugPrint('Videos to download: ${downloadingVid.length}');
|
||||||
runningTasks++;
|
runningTasks++;
|
||||||
debugPrint('Concurrent workers: $runningTasks');
|
debugPrint('Concurrent workers: $runningTasks');
|
||||||
|
|
||||||
await downloadVideo(downloadingVid.first);
|
await downloadVideo(downloadingVid.first);
|
||||||
downloadingVid =
|
downloadingVid =
|
||||||
_videoList.where((video) => video.status != 'downloaded');
|
state.videoList.where((video) => video.status == 'pending').take(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
await startConverter();
|
await startConverter();
|
||||||
|
|
||||||
|
await moveVideos();
|
||||||
|
|
||||||
|
final Directory directory = Directory('temp');
|
||||||
|
final List<FileSystemEntity> files = directory.listSync();
|
||||||
|
for (FileSystemEntity file in files) {
|
||||||
|
final String dirFilename = p.basenameWithoutExtension(file.path);
|
||||||
|
if (dirFilename.contains('_tmp')) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('All videos downloaded');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future moveVideos() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
Directory defaultDownloadDirectory = await getDownloadDirectory();
|
Directory defaultDownloadDirectory = await getDownloadDirectory();
|
||||||
prefs.get('downloadFolder') ??
|
prefs.get('downloadFolder') ??
|
||||||
|
|
@ -86,7 +116,8 @@ class VideosCubit extends Cubit<VideosState> {
|
||||||
final downloadDirectory = Directory(
|
final downloadDirectory = Directory(
|
||||||
prefs.getString('downloadFolder') ?? defaultDownloadDirectory.path);
|
prefs.getString('downloadFolder') ?? defaultDownloadDirectory.path);
|
||||||
|
|
||||||
for (Video video in _videoList) {
|
for (Video video in state.videoList.where((video) =>
|
||||||
|
video.status == 'downloaded' || video.status == 'converted')) {
|
||||||
var cleanTitle = video.title.replaceAll(RegExp(r'[^\w\s]+'), '');
|
var cleanTitle = video.title.replaceAll(RegExp(r'[^\w\s]+'), '');
|
||||||
final tmpFile =
|
final tmpFile =
|
||||||
File('temp/${video.filename}_done.${video.format.extension}');
|
File('temp/${video.filename}_done.${video.format.extension}');
|
||||||
|
|
@ -97,7 +128,7 @@ class VideosCubit extends Cubit<VideosState> {
|
||||||
.catchError((e) => debugPrint('Error creating directory: $e'));
|
.catchError((e) => debugPrint('Error creating directory: $e'));
|
||||||
debugPrint('Playlist title: $playlistTitle');
|
debugPrint('Playlist title: $playlistTitle');
|
||||||
if (playlistTitle.isNotEmpty && playlistTitle != '') {
|
if (playlistTitle.isNotEmpty && playlistTitle != '') {
|
||||||
cleanTitle = playlistTitle + '/' + cleanTitle;
|
cleanTitle = '$playlistTitle/$cleanTitle';
|
||||||
}
|
}
|
||||||
|
|
||||||
final newFile = File(
|
final newFile = File(
|
||||||
|
|
@ -113,33 +144,10 @@ class VideosCubit extends Cubit<VideosState> {
|
||||||
await Future.delayed(Duration(seconds: 1));
|
await Future.delayed(Duration(seconds: 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changeStatus(video, 'done');
|
await changeStatus(video, 'done');
|
||||||
|
archiveVideo(video.copyWith(status: 'done'));
|
||||||
debugPrint('File moved to ${newFile.path}');
|
debugPrint('File moved to ${newFile.path}');
|
||||||
}
|
}
|
||||||
|
|
||||||
final Directory directory = Directory('temp');
|
|
||||||
final List<FileSystemEntity> files = directory.listSync();
|
|
||||||
for (FileSystemEntity file in files) {
|
|
||||||
final String dirFilename = p.basenameWithoutExtension(file.path);
|
|
||||||
if (dirFilename.contains('_tmp')) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debugPrint('All videos downloaded');
|
|
||||||
/*
|
|
||||||
for (Video video in videosLeft) {
|
|
||||||
final shellStream = await dlService.downloadFile(video.url, video.format);
|
|
||||||
shellStream.listen((line) {
|
|
||||||
if (line.contains('[download]')) {
|
|
||||||
debugPrint('___Download___');
|
|
||||||
debugPrint('%=${line.split('[download]')[1].split(' of')[0].trim()}');
|
|
||||||
debugPrint('______');
|
|
||||||
}
|
|
||||||
debugPrint(line);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future convertVideo(Video video) async {
|
Future convertVideo(Video video) async {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
part of 'videos_cubit.dart';
|
part of 'videos_cubit.dart';
|
||||||
|
|
||||||
final class VideosState {
|
final class VideosState {
|
||||||
|
final String status;
|
||||||
final List<Video> videoList;
|
final List<Video> videoList;
|
||||||
|
final List<Video> archiveList;
|
||||||
|
|
||||||
VideosState({this.videoList = const []});
|
VideosState(
|
||||||
|
{this.status = 'initial',
|
||||||
|
this.videoList = const [],
|
||||||
|
this.archiveList = const []});
|
||||||
|
|
||||||
List<Object> get props => [videoList];
|
List<Object> get props => [videoList, status, archiveList];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
logger:
|
logger:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: logger
|
name: logger
|
||||||
sha256: af05cc8714f356fd1f3888fb6741cbe9fbe25cdb6eedbab80e1a6db21047d4a4
|
sha256: af05cc8714f356fd1f3888fb6741cbe9fbe25cdb6eedbab80e1a6db21047d4a4
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ dependencies:
|
||||||
filesystem_picker: ^4.1.0
|
filesystem_picker: ^4.1.0
|
||||||
file_picker: ^8.0.6
|
file_picker: ^8.0.6
|
||||||
rename: ^3.0.2
|
rename: ^3.0.2
|
||||||
|
logger: ^2.3.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue