Add profile fetch cancel

This commit is contained in:
problematicconsumer
2024-01-04 21:35:04 +03:30
parent 5fcd3e819f
commit 6096c1c1ea
3 changed files with 48 additions and 10 deletions

View File

@@ -76,6 +76,15 @@ class AddProfileModal extends HookConsumerWidget {
const LinearProgressIndicator(
backgroundColor: Colors.transparent,
),
const Gap(8),
TextButton(
onPressed: () {
ref.invalidate(addProfileProvider);
},
child: Text(
MaterialLocalizations.of(context).cancelButtonLabel,
),
),
],
),
),

View File

@@ -1,5 +1,6 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:drift/drift.dart';
import 'package:fpdart/fpdart.dart';
import 'package:hiddify/core/database/app_database.dart';
@@ -32,6 +33,7 @@ abstract interface class ProfileRepository {
TaskEither<ProfileFailure, Unit> addByUrl(
String url, {
bool markAsActive = false,
CancelToken? cancelToken,
});
TaskEither<ProfileFailure, Unit> addByContent(
@@ -40,7 +42,10 @@ abstract interface class ProfileRepository {
bool markAsActive = false,
});
TaskEither<ProfileFailure, Unit> add(RemoteProfileEntity baseProfile);
TaskEither<ProfileFailure, Unit> add(
RemoteProfileEntity baseProfile, {
CancelToken? cancelToken,
});
TaskEither<ProfileFailure, String> generateConfig(String id);
@@ -48,6 +53,7 @@ abstract interface class ProfileRepository {
TaskEither<ProfileFailure, Unit> updateSubscription(
RemoteProfileEntity baseProfile, {
bool patchBaseProfile = false,
CancelToken? cancelToken,
});
TaskEither<ProfileFailure, Unit> patch(ProfileEntity profile);
@@ -127,6 +133,7 @@ class ProfileRepositoryImpl
TaskEither<ProfileFailure, Unit> addByUrl(
String url, {
bool markAsActive = false,
CancelToken? cancelToken,
}) {
return exceptionHandler(
() async {
@@ -138,11 +145,14 @@ class ProfileRepositoryImpl
final baseProfile = markAsActive
? existingProfile.copyWith(active: true)
: existingProfile;
return updateSubscription(baseProfile).run();
return updateSubscription(
baseProfile,
cancelToken: cancelToken,
).run();
}
final profileId = const Uuid().v4();
return fetch(url, profileId)
return fetch(url, profileId, cancelToken: cancelToken)
.flatMap(
(profile) => TaskEither(
() async {
@@ -221,10 +231,13 @@ class ProfileRepositoryImpl
}
@override
TaskEither<ProfileFailure, Unit> add(RemoteProfileEntity baseProfile) {
TaskEither<ProfileFailure, Unit> add(
RemoteProfileEntity baseProfile, {
CancelToken? cancelToken,
}) {
return exceptionHandler(
() async {
return fetch(baseProfile.url, baseProfile.id)
return fetch(baseProfile.url, baseProfile.id, cancelToken: cancelToken)
.flatMap(
(remoteProfile) => TaskEither(() async {
await profileDataSource.insert(
@@ -266,13 +279,14 @@ class ProfileRepositoryImpl
TaskEither<ProfileFailure, Unit> updateSubscription(
RemoteProfileEntity baseProfile, {
bool patchBaseProfile = false,
CancelToken? cancelToken,
}) {
return exceptionHandler(
() async {
loggy.debug(
"updating profile [${baseProfile.name} (${baseProfile.id})]",
);
return fetch(baseProfile.url, baseProfile.id)
return fetch(baseProfile.url, baseProfile.id, cancelToken: cancelToken)
.flatMap(
(remoteProfile) => TaskEither(
() async {
@@ -359,15 +373,20 @@ class ProfileRepositoryImpl
@visibleForTesting
TaskEither<ProfileFailure, RemoteProfileEntity> fetch(
String url,
String fileName,
) {
String fileName, {
CancelToken? cancelToken,
}) {
return TaskEither(
() async {
final file = profilePathResolver.file(fileName);
final tempFile = profilePathResolver.tempFile(fileName);
try {
final response = await httpClient.download(url.trim(), tempFile.path);
final response = await httpClient.download(
url.trim(),
tempFile.path,
cancelToken: cancelToken,
);
final headers =
await _populateHeaders(response.headers.map, tempFile.path);
return await validateConfig(file.path, tempFile.path, false)

View File

@@ -1,3 +1,4 @@
import 'package:dio/dio.dart';
import 'package:fpdart/fpdart.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/core/model/failures.dart';
@@ -20,6 +21,10 @@ class AddProfile extends _$AddProfile with AppLogger {
@override
AsyncValue<Unit?> build() {
ref.disposeDelay(const Duration(minutes: 1));
ref.onDispose(() {
loggy.debug("disposing");
_cancelToken?.cancel();
});
ref.listenSelf(
(previous, next) {
final t = ref.read(translationsProvider);
@@ -43,6 +48,7 @@ class AddProfile extends _$AddProfile with AppLogger {
ProfileRepository get _profilesRepo =>
ref.read(profileRepositoryProvider).requireValue;
CancelToken? _cancelToken;
Future<void> add(String rawInput) async {
if (state.isLoading) return;
@@ -55,7 +61,11 @@ class AddProfile extends _$AddProfile with AppLogger {
final TaskEither<ProfileFailure, Unit> task;
if (LinkParser.parse(rawInput) case (final link)?) {
loggy.debug("adding profile, url: [${link.url}]");
task = _profilesRepo.addByUrl(link.url, markAsActive: markAsActive);
task = _profilesRepo.addByUrl(
link.url,
markAsActive: markAsActive,
cancelToken: _cancelToken = CancelToken(),
);
} else if (LinkParser.protocol(rawInput) case (final parsed)?) {
loggy.debug("adding profile, content");
task = _profilesRepo.addByContent(