[param] base param + lang + folder
This commit is contained in:
parent
981a692a52
commit
0eca6ae549
|
|
@ -48,7 +48,7 @@ enum Format {
|
|||
'"18/22/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best"',
|
||||
this.format = 'MP4',
|
||||
this.ffmpegCmd = '',
|
||||
this.extension = '',
|
||||
this.extension = 'mp4',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
|||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:notube/constants.dart';
|
||||
import 'package:notube/models/video.dart';
|
||||
import 'package:notube/services/download.dart';
|
||||
|
|
@ -29,6 +28,9 @@ class DlFormCubit extends Cubit<DlFormState> {
|
|||
|
||||
void parseUrl() async {
|
||||
dlService = await DLServices.init();
|
||||
if (state.url.isEmpty) {
|
||||
return;
|
||||
}
|
||||
var shellStream = await dlService.analyseUrl(state.url);
|
||||
|
||||
shellStream.listen((line) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class DropdownFormat extends StatelessWidget {
|
|||
onChanged: (String? value) {
|
||||
var format =
|
||||
Format.values.firstWhere((element) => element.format == value);
|
||||
context.read<DlFormCubit>().setFormat(format!);
|
||||
context.read<DlFormCubit>().setFormat(format);
|
||||
},
|
||||
underline: Container(),
|
||||
items: Format.values.map<DropdownMenuItem<String>>((Format format) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:notube/constants.dart';
|
||||
import 'package:notube/models/video.dart';
|
||||
import 'package:notube/videoList/cubit/videos_cubit.dart';
|
||||
|
|
@ -35,23 +37,27 @@ class _SubmitButtonState extends State<SubmitButton> {
|
|||
constraints: BoxConstraints.tightFor(width: 200),
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onHover: (PointerHoverEvent event) {
|
||||
setState(() => isHovering = true);
|
||||
},
|
||||
onExit: (PointerExitEvent event) {
|
||||
setState(() => isHovering = false);
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<DlFormCubit>().parseUrl();
|
||||
},
|
||||
child: InkWell(
|
||||
onHover: (hovering) {
|
||||
debugPrint('Hovering: $hovering');
|
||||
setState(() => isHovering = hovering);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: isHovering ? colorDarkRed : colorMainRed,
|
||||
),
|
||||
child: const Text('Ok', textAlign: TextAlign.center).tr(),
|
||||
),
|
||||
))),
|
||||
onTap: () {
|
||||
context.read<DlFormCubit>().parseUrl();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: isHovering ? colorDarkRed : colorMainRed,
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(3),
|
||||
bottomRight: Radius.circular(3),
|
||||
)),
|
||||
child: const Text('Ok', textAlign: TextAlign.center).tr(),
|
||||
),
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,25 +11,34 @@ class UrlTextField extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Flexible(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: 'search_url'.tr(),
|
||||
filled: true,
|
||||
fillColor: colorBackgroundBlack,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: colorBackgroundBlack,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(3),
|
||||
bottomLeft: Radius.circular(3),
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter some text';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (newUrl) {
|
||||
context.read<DlFormCubit>().setUrl(newUrl);
|
||||
},
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: 'search_url'.tr(),
|
||||
filled: true,
|
||||
fillColor: Colors.transparent,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter some text';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (newUrl) {
|
||||
context.read<DlFormCubit>().setUrl(newUrl);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:notube/screens/settings.dart';
|
||||
import 'package:notube/wrapper.dart';
|
||||
import 'package:notube/constants.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:upgrader/upgrader.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
|
@ -63,9 +65,13 @@ class _NoTubeAppState extends State<NoTubeApp> {
|
|||
localizationsDelegates: context.localizationDelegates,
|
||||
supportedLocales: context.supportedLocales,
|
||||
locale: context.locale,
|
||||
home: BlocProvider(
|
||||
create: (context) => VideosCubit(),
|
||||
child: UpgradeAlert(upgrader: upgrader, child: const Wrapper())),
|
||||
initialRoute: '/',
|
||||
routes: {
|
||||
'/': (context) => BlocProvider(
|
||||
create: (context) => VideosCubit(),
|
||||
child: UpgradeAlert(upgrader: upgrader, child: const Wrapper())),
|
||||
'/settings': (context) => Settings(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,16 @@ class Home extends StatelessWidget {
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('home').tr(),
|
||||
actions: [
|
||||
SizedBox(
|
||||
width: 50,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.settings),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/settings');
|
||||
},
|
||||
))
|
||||
],
|
||||
),
|
||||
body: LayoutBuilder(builder:
|
||||
(BuildContext context, BoxConstraints viewportConstraints) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:downloadsfolder/downloadsfolder.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:filesystem_picker/filesystem_picker.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class Settings extends StatefulWidget {
|
||||
Settings({super.key});
|
||||
|
||||
@override
|
||||
State<Settings> createState() => _SettingsState();
|
||||
}
|
||||
|
||||
class _SettingsState extends State<Settings> {
|
||||
late Directory downloadFolder;
|
||||
late SharedPreferences prefs;
|
||||
|
||||
Future<String> _init() async {
|
||||
prefs = await SharedPreferences.getInstance();
|
||||
Directory defaultDownloadDirectory = await getDownloadDirectory();
|
||||
downloadFolder = Directory(
|
||||
prefs.getString('downloadFolder') ?? defaultDownloadDirectory.path);
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('settings').tr(),
|
||||
),
|
||||
body: FutureBuilder<String>(
|
||||
future: _init(),
|
||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return CircularProgressIndicator();
|
||||
} else if (snapshot.hasError) {
|
||||
return Center(child: Text('Error: ${snapshot.error}'));
|
||||
} else if (snapshot.hasData) {
|
||||
return LayoutBuilder(builder:
|
||||
(BuildContext context, BoxConstraints viewportConstraints) {
|
||||
return viewportConstraints.maxHeight < double.infinity
|
||||
? Center(
|
||||
child: Container(
|
||||
constraints: viewportConstraints,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
Text('settings').tr(),
|
||||
SizedBox(height: 10),
|
||||
Flexible(
|
||||
child: ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text('download_folder').tr(),
|
||||
subtitle: Text(downloadFolder.path),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.folder),
|
||||
onPressed: () async {
|
||||
String? selectedDirectory =
|
||||
await FilePicker.platform
|
||||
.getDirectoryPath();
|
||||
|
||||
if (selectedDirectory != null) {
|
||||
prefs.setString('downloadFolder',
|
||||
selectedDirectory);
|
||||
setState(() {
|
||||
downloadFolder =
|
||||
Directory(selectedDirectory);
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: Text('language').tr(),
|
||||
subtitle:
|
||||
Text(context.locale.toString()).tr(),
|
||||
trailing: DropdownButton(
|
||||
items: context.supportedLocales
|
||||
.map((locale) {
|
||||
return DropdownMenuItem(
|
||||
value: locale.toString(),
|
||||
child: Text(locale.toString()).tr(),
|
||||
);
|
||||
}).toList(),
|
||||
value: context.locale.toString(),
|
||||
onChanged: (String? value) => {
|
||||
if (value != null)
|
||||
{
|
||||
context.setLocale(Locale(
|
||||
value.split("_")[0],
|
||||
value.split("_")[1])),
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: CircularProgressIndicator();
|
||||
});
|
||||
} else {
|
||||
return Center(child: Text('No data'));
|
||||
}
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,5 +2,10 @@
|
|||
"test": "EN_test",
|
||||
"home": "EN_home",
|
||||
"home_intro": "EN_home_intro",
|
||||
"search_url": "EN_search_url"
|
||||
"search_url": "EN_search_url",
|
||||
"settings": "EN_Settings",
|
||||
"download_folder": "Download folder",
|
||||
"en_US": "English",
|
||||
"fr_FR": "French",
|
||||
"Ok": "OK"
|
||||
}
|
||||
|
|
@ -2,5 +2,10 @@
|
|||
"test": "Test",
|
||||
"home": "Accueil",
|
||||
"home_intro": "Saisissez l'url d'une video et laissez la magie opérer!",
|
||||
"search_url": "Url"
|
||||
"search_url": "Url",
|
||||
"settings": "Paramètres",
|
||||
"download_folder": "Dossier de téléchargement",
|
||||
"en_US": "Anglais",
|
||||
"fr_FR": "Français",
|
||||
"Ok": "OK"
|
||||
}
|
||||
|
|
@ -92,8 +92,18 @@ class VideosCubit extends Cubit<VideosState> {
|
|||
File('temp/${video.filename}_done.${video.format.extension}');
|
||||
|
||||
final newFile = File(
|
||||
'${downloadDirectory.path}/${cleanTitle}.${video.format.extension}');
|
||||
await tmpFile.rename(newFile.path);
|
||||
'${downloadDirectory.path}/$cleanTitle.${video.format.extension}');
|
||||
|
||||
var isMoved = false;
|
||||
while (!isMoved) {
|
||||
try {
|
||||
await tmpFile.rename(newFile.path);
|
||||
isMoved = true;
|
||||
} on FileSystemException catch (e) {
|
||||
debugPrint('Error moving file: $e');
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
}
|
||||
changeStatus(video, 'done');
|
||||
debugPrint('File moved to ${newFile.path}');
|
||||
}
|
||||
|
|
|
|||
32
pubspec.lock
32
pubspec.lock
|
|
@ -57,6 +57,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.4+1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -169,6 +177,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
file_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: "824f5b9f389bfc4dddac3dea76cd70c51092d9dff0b2ece7ef4f53db8547d258"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.6"
|
||||
filesystem_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: filesystem_picker
|
||||
sha256: cc2bfe7e5a4ce21afd5b1b03824c0e6e5386a981ed6cce7bda062b1af805cf62
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -203,6 +227,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.20"
|
||||
flutter_redux:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ dependencies:
|
|||
bloc: ^8.1.4
|
||||
shared_preferences: ^2.2.3
|
||||
downloadsfolder: ^1.1.0
|
||||
filesystem_picker: ^4.1.0
|
||||
file_picker: ^8.0.6
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue