feat: support drag torrent file (#42)

This commit is contained in:
monkeyWie authored and GitHub committed 2022-11-07 14:12:12 +08:00
1 parent 77e59f7376
commit e9442edd94
9 files changed
+122 -79

No files matched your search

+9 -2
View File
@@ -6,6 +6,10 @@ Locale toLocale(String key) {
return Locale(arr[0], arr[1]);
}
String getLocaleKey(Locale locale) {
return '${locale.languageCode}_${locale.countryCode}';
}
final messages = _Messages();
const fallbackLocale = Locale('en', 'US');
@@ -21,7 +25,8 @@ class _Messages extends Translations {
'create.title': '创建任务',
'create.downloadLink': '下载链接',
'create.downloadLinkValid': '请输入下载链接',
'create.downloadLinkHit': '请输入下载链接,支持 HTTP/HTTPS/MAGNET',
'create.downloadLinkHit': '请输入下载链接,支持 HTTP/HTTPS/MAGNET@append',
'create.downloadLinkHitDesktop': ',也可以直接拖拽种子文件到此处',
'create.download': '下载',
'create.error.noStoragePermission': '需要开启存储权限',
'create.selectDir': '选择目录',
@@ -51,7 +56,9 @@ class _Messages extends Translations {
'create.downloadLink': 'Download Link',
'create.downloadLinkValid': 'Please enter the download link',
'create.downloadLinkHit':
'Please enter the download link, HTTP/HTTPS/MAGNET supported',
'Please enter the download link, HTTP/HTTPS/MAGNET supported@append',
'create.downloadLinkHitDesktop':
', or drag the torrent file here directly',
'create.download': 'Download',
'create.error.noStoragePermission': 'Storage permission required',
'create.selectDir': 'Select Directory',
+1 -1
View File
@@ -26,7 +26,7 @@ void main() async {
darkTheme: GopeedTheme.dark,
themeMode: Setting.instance.themeMode,
translations: messages,
locale: Setting.instance.locale,
locale: toLocale(Setting.instance.locale),
fallbackLocale: fallbackLocale,
getPages: Routes.routes,
));
@@ -1,5 +1,3 @@
import 'package:get/get.dart';
class CreateController extends GetxController {
var currentIndex = 0.obs;
}
class CreateController extends GetxController {}
+63 -52
View File
@@ -1,3 +1,4 @@
import 'package:desktop_drop/desktop_drop.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../api/api.dart';
@@ -32,65 +33,75 @@ class CreateView extends GetView<CreateController> {
actions: [Container()],
title: Text('create.title'.tr),
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Form(
key: _resolveFormKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
children: [
TextFormField(
autofocus: true,
controller: _urlController,
minLines: 1,
maxLines: 15,
decoration: InputDecoration(
hintText: 'create.downloadLinkHit'.tr,
labelText: 'create.downloadLink'.tr,
icon: const Icon(Icons.link)),
validator: (v) {
return v!.trim().isNotEmpty
? null
: 'create.downloadLinkValid'.tr;
}),
// 登录按钮
Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: ConstrainedBox(
constraints: const BoxConstraints.tightFor(
width: 150,
height: 40,
),
child: RoundedLoadingButton(
color: Get.theme.colorScheme.secondary,
onPressed: () async {
if (_resolveFormKey.currentState!.validate()) {
_confirmController.start();
try {
final res = await resolve(Request(
url: _urlController.text,
));
await _showResolveDialog(res);
} catch (e) {
Get.snackbar('error'.tr, e.toString());
} finally {
_confirmController.reset();
body: DropTarget(
onDragDone: (details) {
_urlController.text = details.files[0].path;
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Form(
key: _resolveFormKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
children: [
TextFormField(
autofocus: true,
controller: _urlController,
minLines: 1,
maxLines: 15,
decoration: InputDecoration(
hintText: _hitText(),
labelText: 'create.downloadLink'.tr,
icon: const Icon(Icons.link)),
validator: (v) {
return v!.trim().isNotEmpty
? null
: 'create.downloadLinkValid'.tr;
}),
Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: ConstrainedBox(
constraints: const BoxConstraints.tightFor(
width: 150,
height: 40,
),
child: RoundedLoadingButton(
color: Get.theme.colorScheme.secondary,
onPressed: () async {
if (_resolveFormKey.currentState!.validate()) {
_confirmController.start();
try {
final res = await resolve(Request(
url: _urlController.text,
));
await _showResolveDialog(res);
} catch (e) {
Get.snackbar('error'.tr, e.toString());
} finally {
_confirmController.reset();
}
}
}
},
controller: _confirmController,
child: Text('confirm'.tr),
),
)),
),
],
},
controller: _confirmController,
child: Text('confirm'.tr),
),
)),
),
],
),
),
),
),
);
}
String _hitText() {
return 'create.downloadLinkHit'.trParams({
'append': Util.isDesktop() ? 'create.downloadLinkHitDesktop'.tr : '',
});
}
Future<void> _showResolveDialog(Resource res) async {
final createFormKey = GlobalKey<FormState>();
final pathController =
+28 -17
View File
@@ -16,8 +16,15 @@ class SettingView extends GetView<SettingController> {
Widget build(BuildContext context) {
Timer? timer;
debounceSave() {
var completer = Completer<void>();
timer?.cancel();
timer = Timer(const Duration(milliseconds: 500), Setting.instance.save);
timer = Timer(const Duration(milliseconds: 500), () {
Setting.instance
.save()
.then(completer.complete)
.onError(completer.completeError);
});
return completer.future;
}
return Scaffold(
@@ -39,12 +46,12 @@ class SettingView extends GetView<SettingController> {
() => DropdownButton<ThemeMode>(
value: controller.setting.value.themeMode,
isDense: true,
onChanged: (value) {
onChanged: (value) async {
controller.setting.value.themeMode = value!;
controller.clearTapStatus();
Get.changeThemeMode(value);
debounceSave();
await debounceSave();
},
items: ThemeMode.values
.map((e) => DropdownMenuItem<ThemeMode>(
@@ -57,14 +64,14 @@ class SettingView extends GetView<SettingController> {
() => controller.setting.value.downloadDir, () {
final downloadDirController = TextEditingController(
text: controller.setting.value.downloadDir);
downloadDirController.addListener(() {
downloadDirController.addListener(() async {
if (downloadDirController.text !=
controller.setting.value.downloadDir) {
controller.setting.value.downloadDir =
downloadDirController.text;
controller.clearTapStatus();
debounceSave();
await debounceSave();
}
});
return DirectorySelector(
@@ -77,14 +84,14 @@ class SettingView extends GetView<SettingController> {
() {
final connectionsController = TextEditingController(
text: controller.setting.value.connections.toString());
connectionsController.addListener(() {
connectionsController.addListener(() async {
if (connectionsController.text.isNotEmpty &&
connectionsController.text !=
controller.setting.value.connections.toString()) {
controller.setting.value.connections =
int.parse(connectionsController.text);
debounceSave();
await debounceSave();
}
});
@@ -100,20 +107,20 @@ class SettingView extends GetView<SettingController> {
_ConfigItem(
'setting.locale'.tr,
() => _getLocaleName(controller.setting.value.locale),
() => DropdownButton<Locale>(
() => DropdownButton<String>(
value: controller.setting.value.locale,
isDense: true,
onChanged: (value) {
onChanged: (value) async {
controller.setting.value.locale = value!;
controller.clearTapStatus();
Get.updateLocale(value);
Get.updateLocale(toLocale(value));
debounceSave();
await debounceSave();
},
items: _getLocales()
.map((e) => DropdownMenuItem<Locale>(
value: toLocale(e
.substring(_settingLocaleKey.length)),
.map((e) => DropdownMenuItem<String>(
value:
e.substring(_settingLocaleKey.length),
child: Text(e.tr),
))
.toList(),
@@ -164,14 +171,18 @@ class SettingView extends GetView<SettingController> {
final _settingLocaleKey = 'setting.locale.';
List<String> _getLocales() {
return messages.keys[fallbackLocale.toString()]!.entries
return messages.keys[getLocaleKey(fallbackLocale)]!.entries
.where((e) => e.key.startsWith(_settingLocaleKey))
.map((e) => e.key)
.toList();
}
String _getLocaleName(Locale locale) {
return '$_settingLocaleKey${locale.toString()}'.tr;
String _getLocaleName(String locale) {
final localeKey = '$_settingLocaleKey${locale.toString()}';
if (messages.keys[locale]?.containsKey(localeKey) ?? false) {
return localeKey.tr;
}
return '$_settingLocaleKey$locale'.tr;
}
}
+6 -4
View File
@@ -14,14 +14,16 @@ class Setting {
int port = 0;
int connections = 0;
String downloadDir = "";
ThemeMode themeMode = ThemeMode.system;
Locale locale = ui.window.locale;
late ThemeMode themeMode;
late String locale;
// singleton pattern
static Setting? _instance;
static Setting get instance {
_instance ??= Setting._internal();
_instance!.themeMode = ThemeMode.system;
_instance!.locale = getLocaleKey(ui.window.locale);
return _instance!;
}
@@ -39,7 +41,7 @@ class Setting {
}
final locale = config.extra?['locale'];
if (locale != null) {
this.locale = toLocale(locale);
this.locale = locale;
}
if (Util.isWeb()) {
@@ -67,7 +69,7 @@ class Setting {
downloadDir: downloadDir,
extra: {
'themeMode': themeMode.name,
'locale': locale.toString(),
'locale': locale,
},
);
await putConfig(config);
+6
View File
@@ -1,4 +1,6 @@
PODS:
- desktop_drop (0.0.1):
- FlutterMacOS
- file_selector_macos (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
@@ -12,6 +14,7 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- macos_secure_bookmarks (from `Flutter/ephemeral/.symlinks/plugins/macos_secure_bookmarks/macos`)
@@ -20,6 +23,8 @@ DEPENDENCIES:
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
EXTERNAL SOURCES:
desktop_drop:
:path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos
file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
FlutterMacOS:
@@ -34,6 +39,7 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
file_selector_macos: f1b08a781e66103e3ba279fd5d4024a2478b3af6
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
macos_secure_bookmarks: cff041c4b377fa00941bb901aaec4d27fac5edf2
+7
View File
@@ -183,6 +183,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.4"
desktop_drop:
dependency: "direct main"
description:
name: desktop_drop
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.3"
dio:
dependency: "direct main"
description:
+1
View File
@@ -49,6 +49,7 @@ dependencies:
permission_handler: ^10.1.0
external_path: ^1.0.3
logger: ^1.1.0
desktop_drop: ^0.3.3
dev_dependencies:
flutter_test: