mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-09 10:00:27 +00:00
feat: implement task patching functionality (#1267)
This commit is contained in:
22 files changed
+1281
-132
No files matched your search
@@ -59,6 +59,14 @@ final allTrackerSubscribeUrlCdns = {
|
||||
v: githubMirrorUrls(v, MirrorType.githubSource)
|
||||
};
|
||||
|
||||
/// Represents a task that is pending URL update via listen mode.
|
||||
class PendingUpdateTask {
|
||||
final String id;
|
||||
final String name;
|
||||
|
||||
PendingUpdateTask({required this.id, required this.name});
|
||||
}
|
||||
|
||||
class AppController extends GetxController with WindowListener, TrayListener {
|
||||
static StartConfig? _defaultStartConfig;
|
||||
|
||||
@@ -72,6 +80,10 @@ class AppController extends GetxController with WindowListener, TrayListener {
|
||||
final runningPort = 0.obs;
|
||||
final downloaderConfig = DownloaderConfig().obs;
|
||||
|
||||
/// The task that is pending URL update via listen mode.
|
||||
/// Stored here in AppController to persist across page navigations.
|
||||
final pendingUpdateTask = Rxn<PendingUpdateTask>();
|
||||
|
||||
late AppLinks _appLinks;
|
||||
StreamSubscription<Uri>? _linkSubscription;
|
||||
|
||||
@@ -320,7 +332,7 @@ class AppController extends GetxController with WindowListener, TrayListener {
|
||||
final silent = jsonMeta['silent'] as bool? ?? false;
|
||||
final params = await ctx.readText();
|
||||
final createTaskParams = CreateTask.fromJson(_decodeParams(params));
|
||||
if (!silent) {
|
||||
if (!silent || pendingUpdateTask.value != null) {
|
||||
await windowManager.show();
|
||||
_handleToCreate0(createTaskParams);
|
||||
} else {
|
||||
|
||||
@@ -836,6 +836,26 @@ class CreateView extends GetView<CreateController> {
|
||||
: _urlController.text.trim();
|
||||
|
||||
final urls = Util.textToLines(submitUrl);
|
||||
|
||||
// Check if there is a pending update task (only for single URL)
|
||||
if (urls.length == 1) {
|
||||
final appController = Get.find<AppController>();
|
||||
final pendingTask = appController.pendingUpdateTask.value;
|
||||
if (pendingTask != null) {
|
||||
final shouldUpdate = await _showPendingUpdateDialog(
|
||||
pendingTask.id, pendingTask.name);
|
||||
if (shouldUpdate == true) {
|
||||
// Update the pending task instead of creating a new one
|
||||
await _updatePendingTask(pendingTask.id, urls.first);
|
||||
return;
|
||||
} else if (shouldUpdate == null) {
|
||||
// User cancelled, don't create task either
|
||||
return;
|
||||
}
|
||||
// shouldUpdate == false, continue to create new task
|
||||
}
|
||||
}
|
||||
|
||||
// Add url to the history
|
||||
if (!isWebFileChosen) {
|
||||
for (final url in urls) {
|
||||
@@ -890,6 +910,72 @@ class CreateView extends GetView<CreateController> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows a dialog to ask if user wants to update pending task or create new
|
||||
/// Returns true to update, false to create new, null if cancelled
|
||||
Future<bool?> _showPendingUpdateDialog(String taskId, String taskName) async {
|
||||
return showDialog<bool>(
|
||||
context: Get.context!,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('pendingUpdateFound'.tr),
|
||||
content: Text('pendingUpdateConfirm'.trParams({'name': taskName})),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(null),
|
||||
child: Text('cancel'.tr),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: Text('pendingUpdateNo'.tr),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: Text('pendingUpdateYes'.tr),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates the pending task with new URL and headers
|
||||
Future<void> _updatePendingTask(String taskId, String newUrl) async {
|
||||
try {
|
||||
// Build headers from current form
|
||||
final headers = <String, String>{};
|
||||
for (final c in _httpHeaderControllers) {
|
||||
final key = c.name.text.trim();
|
||||
final value = c.value.text.trim();
|
||||
if (key.isNotEmpty) {
|
||||
headers[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Build ReqExtraHttp
|
||||
final reqExtra = ReqExtraHttp(header: headers);
|
||||
|
||||
// Create patch request
|
||||
final patchData = ResolveTask(
|
||||
req: Request(
|
||||
url: newUrl,
|
||||
extra: reqExtra.toJson(),
|
||||
proxy: parseProxy(),
|
||||
skipVerifyCert: _skipVerifyCertController.value,
|
||||
),
|
||||
);
|
||||
|
||||
await patchTask(taskId, patchData);
|
||||
await continueTask(taskId);
|
||||
|
||||
// Clear pending update state
|
||||
final appController = Get.find<AppController>();
|
||||
appController.pendingUpdateTask.value = null;
|
||||
|
||||
Get.rootDelegate.offNamed(Routes.TASK);
|
||||
} catch (e) {
|
||||
showErrorMessage(e);
|
||||
}
|
||||
}
|
||||
|
||||
RequestProxy? parseProxy() {
|
||||
if (controller.proxyConfig.value?.mode == RequestProxyMode.custom) {
|
||||
return RequestProxy()
|
||||
|
||||
Reference in new issue
Block a user