mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-08 09:30:27 +00:00
refactor(downloader): remove opts parameter from Resolve (#1595)
This commit is contained in:
45 files changed
+1589
-384
No files matched your search
@@ -10,6 +10,7 @@ import 'model/install_extension.dart';
|
||||
import 'model/login.dart';
|
||||
import 'model/resolve_result.dart';
|
||||
import 'model/resolve_task.dart';
|
||||
import 'model/patch_task.dart';
|
||||
import 'model/result.dart';
|
||||
import 'model/switch_extension.dart';
|
||||
import 'model/task.dart';
|
||||
@@ -91,7 +92,7 @@ Future<List<String>> createTaskBatch(CreateTaskBatch createTaskBatch) {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> patchTask(String id, ResolveTask patchTask) {
|
||||
Future<void> patchTask(String id, PatchTask patchTask) {
|
||||
return _parse<void>(() => _request('api/v1/tasks/$id', method: 'PATCH', data: patchTask), null);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'options.dart';
|
||||
import 'request.dart';
|
||||
|
||||
class PatchTask {
|
||||
final Request? req;
|
||||
final Options? opts;
|
||||
|
||||
PatchTask({this.req, this.opts});
|
||||
|
||||
factory PatchTask.fromJson(Map<String, dynamic> json) => PatchTask(
|
||||
req: json['req'] == null ? null : Request.fromJson(json['req'] as Map<String, dynamic>),
|
||||
opts: json['opts'] == null ? null : Options.fromJson(json['opts'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {'req': req?.toJson(), 'opts': opts?.toJson()};
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import 'options.dart';
|
||||
import 'request.dart';
|
||||
|
||||
part 'resolve_task.g.dart';
|
||||
@@ -8,9 +7,8 @@ part 'resolve_task.g.dart';
|
||||
@JsonSerializable()
|
||||
class ResolveTask {
|
||||
Request? req;
|
||||
Options? opts;
|
||||
|
||||
ResolveTask({this.req, this.opts});
|
||||
ResolveTask({this.req});
|
||||
|
||||
factory ResolveTask.fromJson(Map<String, dynamic> json) => _$ResolveTaskFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$ResolveTaskToJson(this);
|
||||
|
||||
@@ -7,11 +7,10 @@ part of 'resolve_task.dart';
|
||||
// **************************************************************************
|
||||
|
||||
ResolveTask _$ResolveTaskFromJson(Map<String, dynamic> json) => ResolveTask(
|
||||
req: json['req'] == null ? null : Request.fromJson(json['req'] as Map<String, dynamic>),
|
||||
opts: json['opts'] == null ? null : Options.fromJson(json['opts'] as Map<String, dynamic>),
|
||||
req: json['req'] == null
|
||||
? null
|
||||
: Request.fromJson(json['req'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ResolveTaskToJson(ResolveTask instance) => <String, dynamic>{
|
||||
'req': ?instance.req,
|
||||
'opts': ?instance.opts,
|
||||
};
|
||||
Map<String, dynamic> _$ResolveTaskToJson(ResolveTask instance) =>
|
||||
<String, dynamic>{'req': ?instance.req};
|
||||
@@ -8,6 +8,7 @@ import '../../api/model/extension.dart';
|
||||
import '../../api/model/install_extension.dart';
|
||||
import '../../api/model/resolve_result.dart';
|
||||
import '../../api/model/resolve_task.dart';
|
||||
import '../../api/model/patch_task.dart';
|
||||
import '../../api/model/switch_extension.dart';
|
||||
import '../../api/model/task.dart';
|
||||
import '../../api/model/update_check_extension_resp.dart';
|
||||
@@ -85,7 +86,7 @@ void _bindGopeed(CapabilityRegistry registry) {
|
||||
..bind(GopeedMethods.createTask, api.createTask)
|
||||
..bind(GopeedMethods.createTaskBatch, api.createTaskBatch)
|
||||
..bind(GopeedMethods.patchTask, (params) async {
|
||||
await api.patchTask(params['id'] as String, ResolveTask.fromJson(params['request'] as Map<String, dynamic>));
|
||||
await api.patchTask(params['id'] as String, PatchTask.fromJson(params['request'] as Map<String, dynamic>));
|
||||
return const RpcUnit();
|
||||
})
|
||||
..bind(
|
||||
|
||||
@@ -5,6 +5,7 @@ import '../../api/model/extension.dart';
|
||||
import '../../api/model/install_extension.dart';
|
||||
import '../../api/model/resolve_result.dart';
|
||||
import '../../api/model/resolve_task.dart';
|
||||
import '../../api/model/patch_task.dart';
|
||||
import '../../api/model/switch_extension.dart';
|
||||
import '../../api/model/task.dart';
|
||||
import '../../api/model/update_check_extension_resp.dart';
|
||||
@@ -49,7 +50,7 @@ class GopeedService {
|
||||
Future<List<String>> createTaskBatch(CreateTaskBatch request) =>
|
||||
_invoker.invoke(GopeedMethods.createTaskBatch, request);
|
||||
|
||||
Future<void> patchTask(String id, ResolveTask request) async {
|
||||
Future<void> patchTask(String id, PatchTask request) async {
|
||||
await _invoker.invoke(GopeedMethods.patchTask, {'id': id, 'request': request.toJson()});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../api/model/request.dart';
|
||||
import '../../../api/model/resolve_task.dart';
|
||||
import '../../../api/model/patch_task.dart';
|
||||
import '../../../api/model/task.dart' as api_model;
|
||||
import '../../../core/capabilities/app_capabilities.dart';
|
||||
import '../domain/task_record.dart';
|
||||
@@ -99,7 +99,7 @@ class TasksController extends AsyncNotifier<TasksState> {
|
||||
}
|
||||
|
||||
Future<void> updateRequest(String id, Request request) async {
|
||||
await ref.read(gopeedServiceProvider).patchTask(id, ResolveTask(req: request));
|
||||
await ref.read(gopeedServiceProvider).patchTask(id, PatchTask(req: request));
|
||||
await ref.read(gopeedServiceProvider).continueTask(id);
|
||||
await refresh(silent: true);
|
||||
}
|
||||
|
||||
@@ -927,8 +927,7 @@ class _CreateTaskWindowPageState extends ConsumerState<CreateTaskWindowPage> {
|
||||
}
|
||||
|
||||
final request = _buildRequest(urls.first, protocolUrl: _protocolUrlFor(urls.first));
|
||||
final options = _buildOptions();
|
||||
final result = await ref.read(gopeedServiceProvider).resolve(ResolveTask(req: request, opts: options));
|
||||
final result = await ref.read(gopeedServiceProvider).resolve(ResolveTask(req: request));
|
||||
if (!mounted) return;
|
||||
final created = await _showResolveDialog(request, result);
|
||||
if (!created) {
|
||||
|
||||
@@ -3,30 +3,49 @@ import 'dart:convert';
|
||||
import 'package:dio/dio.dart' as dio;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gopeed/api/api.dart' as api;
|
||||
import 'package:gopeed/api/model/create_task.dart';
|
||||
import 'package:gopeed/api/model/options.dart';
|
||||
import 'package:gopeed/api/model/patch_task.dart';
|
||||
import 'package:gopeed/api/model/request.dart';
|
||||
import 'package:gopeed/api/model/resolve_task.dart';
|
||||
import 'package:gopeed/core/network/gopeed/gopeed_transport.dart';
|
||||
|
||||
void main() {
|
||||
test('resolve sends the complete resolve task for magnet links', () async {
|
||||
test('resolve omits download options and creation submits them separately', () async {
|
||||
final transport = _RecordingTransport();
|
||||
api.setTransportForTesting(transport);
|
||||
final result = await api.resolve(
|
||||
ResolveTask(
|
||||
req: Request(url: 'magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567'),
|
||||
opts: Options(path: '/downloads', selectFiles: const []),
|
||||
),
|
||||
ResolveTask(req: Request(url: 'magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567')),
|
||||
);
|
||||
|
||||
expect(result.id, 'resolved-id');
|
||||
final requestBody = transport.data as Map<String, dynamic>;
|
||||
expect(requestBody.keys, containsAll(<String>['req', 'opts']));
|
||||
expect(requestBody.keys, equals(<String>['req']));
|
||||
expect(
|
||||
(requestBody['req'] as Map<String, dynamic>)['url'],
|
||||
'magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567',
|
||||
);
|
||||
expect((requestBody['opts'] as Map<String, dynamic>)['path'], '/downloads');
|
||||
expect(requestBody, isNot(contains('opts')));
|
||||
|
||||
final id = await api.createTask(
|
||||
CreateTask(
|
||||
rid: result.id,
|
||||
opts: Options(path: '/chosen-after-resolve', selectFiles: [1]),
|
||||
),
|
||||
);
|
||||
expect(id, 'created-id');
|
||||
final createBody = transport.data as Map<String, dynamic>;
|
||||
expect(createBody['rid'], 'resolved-id');
|
||||
expect((createBody['opts'] as Map<String, dynamic>)['path'], '/chosen-after-resolve');
|
||||
expect((createBody['opts'] as Map<String, dynamic>)['selectFiles'], [1]);
|
||||
});
|
||||
|
||||
test('patch preserves options in its independent request model', () async {
|
||||
final transport = _RecordingTransport();
|
||||
api.setTransportForTesting(transport);
|
||||
await api.patchTask('task-id', PatchTask(opts: Options(selectFiles: [1])));
|
||||
final requestBody = transport.data as Map<String, dynamic>;
|
||||
expect((requestBody['opts'] as Map<String, dynamic>)['selectFiles'], [1]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,6 +60,12 @@ class _RecordingTransport implements GopeedTransport {
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
this.data = jsonDecode(jsonEncode(data));
|
||||
if (path == 'api/v1/tasks') {
|
||||
return {'code': 0, 'data': 'created-id'};
|
||||
}
|
||||
if (method == 'PATCH') {
|
||||
return {'code': 0, 'data': null};
|
||||
}
|
||||
return {
|
||||
'code': 0,
|
||||
'data': {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gopeed/api/model/options.dart';
|
||||
import 'package:gopeed/api/model/patch_task.dart';
|
||||
import 'package:gopeed/api/model/request.dart';
|
||||
import 'package:gopeed/api/model/resolve_result.dart';
|
||||
import 'package:gopeed/api/model/resolve_task.dart';
|
||||
import 'package:gopeed/api/model/resource.dart';
|
||||
import 'package:gopeed/core/capabilities/app_capabilities.dart';
|
||||
import 'package:gopeed/core/capabilities/capability_rpc.dart';
|
||||
import 'package:gopeed/core/capabilities/gopeed_capability.dart';
|
||||
import 'package:gopeed/core/window/app_window_appearance.dart';
|
||||
|
||||
class _Payload {
|
||||
@@ -13,6 +21,33 @@ class _Payload {
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('serialized resolve and patch capabilities keep separate request contracts', () async {
|
||||
final codecs = createAppCapabilityCodecs();
|
||||
String? resolvedUrl;
|
||||
Map<String, dynamic>? patch;
|
||||
final registry = CapabilityRegistry(codecs)
|
||||
..bind(GopeedMethods.resolve, (request) {
|
||||
resolvedUrl = request.req?.url;
|
||||
return ResolveResult(id: 'resolved-id', res: Resource(files: []));
|
||||
})
|
||||
..bind(GopeedMethods.patchTask, (request) {
|
||||
patch = request;
|
||||
return const RpcUnit();
|
||||
});
|
||||
final request = ResolveTask(req: Request(url: 'magnet:?xt=urn:btih:hash'));
|
||||
final wireRequest = codecs.encode(request) as Map<String, dynamic>;
|
||||
expect(wireRequest.keys, ['req']);
|
||||
final result = codecs.decode<ResolveResult>(await registry.invoke(GopeedMethods.resolve.name, wireRequest));
|
||||
expect(result.id, 'resolved-id');
|
||||
expect(resolvedUrl, request.req?.url);
|
||||
|
||||
final service = GopeedService(LocalCapabilityInvoker(registry));
|
||||
await service.patchTask('task-id', PatchTask(opts: Options(selectFiles: [1])));
|
||||
expect(patch?['id'], 'task-id');
|
||||
final patchBody = patch?['request'] as Map<String, dynamic>;
|
||||
expect((patchBody['opts'] as Map<String, dynamic>)['selectFiles'], [1]);
|
||||
});
|
||||
|
||||
test('one method descriptor supports direct and serialized dispatch', () async {
|
||||
const method = RpcMethod<_Payload, _Payload>('test.increment');
|
||||
final codecs = RpcCodecRegistry()..register<_Payload>((json) => _Payload.fromJson(json! as Map<String, dynamic>));
|
||||
|
||||
Reference in new issue
Block a user