mirror of
https://github.com/lifegpc/eh_downloader_flutter.git
synced 2026-06-25 13:16:48 +08:00
Update server settings page
This commit is contained in:
30
lib/components/labeled_checkbox.dart
Normal file
30
lib/components/labeled_checkbox.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LabeledCheckbox extends StatelessWidget {
|
||||
const LabeledCheckbox({
|
||||
Key? key,
|
||||
required this.label,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
final Text label;
|
||||
final bool value;
|
||||
final ValueChanged<bool?>? onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: () => onChanged?.call(!value),
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
Expanded(child: label),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -107,5 +107,18 @@
|
||||
"enterNewCookies": "Enter new cookies here",
|
||||
"maxTaskCount": "Maximum number of parallel tasks",
|
||||
"invalidNumber": "Invalid number.",
|
||||
"numberOutOfRange": "The number is out of range."
|
||||
"numberOutOfRange": "The number is out of range.",
|
||||
"maxRetryCount": "Maximum retry count",
|
||||
"maxDownloadImgCount": "Maximum number of parallel downloads of images",
|
||||
"listeningPort": "Listening port",
|
||||
"listeningHostname": "Listening host",
|
||||
"meiliHost": "Meilisearch server host",
|
||||
"meiliUpdateApiKey": "Meilisearch API key for updating gallery metadata",
|
||||
"meiliSearchApiKey": "Meilisearch API key for searching",
|
||||
"ffmpegPath": "The path to the ffmpeg binary",
|
||||
"thumbnailMethod": "The method used to generate thumbnail",
|
||||
"thumbnailMethod0": "ffmpeg binary",
|
||||
"thumbnailMethod1": "ffmpeg API",
|
||||
"thumbnailDir": "The folder used to store thumbnails",
|
||||
"imgVerifySecret": "The secret of image verify"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,18 @@
|
||||
"enterNewCookies": "在此输入新的 Cookies",
|
||||
"maxTaskCount": "最大并行任务数",
|
||||
"invalidNumber": "非法的数字。",
|
||||
"numberOutOfRange": "数字超出了范围。"
|
||||
"numberOutOfRange": "数字超出了范围。",
|
||||
"maxRetryCount": "最大重试次数",
|
||||
"maxDownloadImgCount": "最大图片并行下载数",
|
||||
"listeningPort": "监听端口",
|
||||
"listeningHostname": "监听主机",
|
||||
"meiliHost": "Meilisearch 服务器主机",
|
||||
"meiliUpdateApiKey": "用于更新画廊元数据的 Meilisearch API 密钥",
|
||||
"meiliSearchApiKey": "用于搜索的 Meilisearch API 密钥",
|
||||
"ffmpegPath": "FFMPEG 二进制的位置",
|
||||
"thumbnailMethod": "生成缩略图的方式",
|
||||
"thumbnailMethod0": "FFMPEG 二进制",
|
||||
"thumbnailMethod1": "FFMPEG API",
|
||||
"thumbnailDir": "存放缩略图的文件夹",
|
||||
"imgVerifySecret": "用于验证图片 verify 的密钥"
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'api/config.dart';
|
||||
import 'components/labeled_checkbox.dart';
|
||||
import 'components/number_field.dart';
|
||||
import 'globals.dart';
|
||||
import 'platform/ua.dart';
|
||||
@@ -202,7 +203,7 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
return _buildWithHorizontalPadding(
|
||||
context,
|
||||
Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
_buildWithVecticalPadding(CheckboxMenuButton(
|
||||
_buildWithVecticalPadding(LabeledCheckbox(
|
||||
value: _now.ex ?? _config!.ex,
|
||||
onChanged: (b) {
|
||||
if (b != null) {
|
||||
@@ -212,8 +213,8 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(i18n.useEx))),
|
||||
_buildWithVecticalPadding(CheckboxMenuButton(
|
||||
label: Text(i18n.useEx))),
|
||||
_buildWithVecticalPadding(LabeledCheckbox(
|
||||
value: _now.mpv ?? _config!.mpv,
|
||||
onChanged: (b) {
|
||||
if (b != null) {
|
||||
@@ -223,8 +224,8 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(i18n.mpv))),
|
||||
_buildWithVecticalPadding(CheckboxMenuButton(
|
||||
label: Text(i18n.mpv))),
|
||||
_buildWithVecticalPadding(LabeledCheckbox(
|
||||
value: _now.downloadOriginalImg ?? _config!.downloadOriginalImg,
|
||||
onChanged: (b) {
|
||||
if (b != null) {
|
||||
@@ -234,8 +235,8 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(i18n.downloadOriginalImg))),
|
||||
_buildWithVecticalPadding(CheckboxMenuButton(
|
||||
label: Text(i18n.downloadOriginalImg))),
|
||||
_buildWithVecticalPadding(LabeledCheckbox(
|
||||
value: _now.exportZipJpnTitle ?? _config!.exportZipJpnTitle,
|
||||
onChanged: (b) {
|
||||
if (b != null) {
|
||||
@@ -245,8 +246,8 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(i18n.exportZipJpnTitle))),
|
||||
_buildWithVecticalPadding(CheckboxMenuButton(
|
||||
label: Text(i18n.exportZipJpnTitle))),
|
||||
_buildWithVecticalPadding(LabeledCheckbox(
|
||||
value:
|
||||
_now.removePreviousGallery ?? _config!.removePreviousGallery,
|
||||
onChanged: (b) {
|
||||
@@ -257,7 +258,7 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(i18n.removePreviousGallery))),
|
||||
label: Text(i18n.removePreviousGallery))),
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -347,6 +348,169 @@ class _ServerSettingsPage extends State<ServerSettingsPage>
|
||||
}
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(NumberFormField(
|
||||
min: 1,
|
||||
initialValue: _now.maxRetryCount ?? _config!.maxRetryCount,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.maxRetryCount,
|
||||
),
|
||||
onChanged: (s) {
|
||||
if (s != null) {
|
||||
setState(() {
|
||||
_now.maxRetryCount = s;
|
||||
_changed = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(NumberFormField(
|
||||
min: 1,
|
||||
initialValue:
|
||||
_now.maxDownloadImgCount ?? _config!.maxDownloadImgCount,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.maxDownloadImgCount,
|
||||
),
|
||||
onChanged: (s) {
|
||||
if (s != null) {
|
||||
setState(() {
|
||||
_now.maxDownloadImgCount = s;
|
||||
_changed = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(NumberFormField(
|
||||
min: 0,
|
||||
max: 65535,
|
||||
initialValue: _now.port ?? _config!.port,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.listeningPort,
|
||||
),
|
||||
onChanged: (s) {
|
||||
if (s != null) {
|
||||
setState(() {
|
||||
_now.port = s;
|
||||
_changed = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.hostname ?? _config!.hostname,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.listeningHostname,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.hostname = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.meiliHost ?? _config!.meiliHost,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.meiliHost,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.meiliHost = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.meiliSearchApiKey ?? _config!.meiliSearchApiKey,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.meiliSearchApiKey,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.meiliSearchApiKey = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.meiliUpdateApiKey ?? _config!.meiliUpdateApiKey,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.meiliUpdateApiKey,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.meiliUpdateApiKey = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.ffmpegPath ?? _config!.ffmpegPath,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.ffmpegPath,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.ffmpegPath = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(DropdownButtonFormField<ThumbnailMethod>(
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: ThumbnailMethod.ffmpegBinary,
|
||||
child: Text(i18n.thumbnailMethod0)),
|
||||
DropdownMenuItem(
|
||||
value: ThumbnailMethod.ffmpegApi,
|
||||
child: Text(i18n.thumbnailMethod1)),
|
||||
],
|
||||
onChanged: (v) {
|
||||
if (v != null) {
|
||||
setState(() {
|
||||
_now.thumbnailMethod = v;
|
||||
_changed = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
value: _now.thumbnailMethod ?? _config!.thumbnailMethod,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.thumbnailMethod,
|
||||
))),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.thumbnailDir ?? _config!.thumbnailDir,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.thumbnailDir,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.thumbnailDir = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
_buildWithVecticalPadding(TextFormField(
|
||||
initialValue: _now.imgVerifySecret ?? _config!.imgVerifySecret,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: i18n.imgVerifySecret,
|
||||
),
|
||||
onChanged: (s) {
|
||||
setState(() {
|
||||
_now.imgVerifySecret = s;
|
||||
_changed = true;
|
||||
});
|
||||
},
|
||||
)),
|
||||
]));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user