diff --git a/.vscode/launch.json b/.vscode/launch.json index a480b7c..3d5d2ff 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,8 +8,7 @@ "name": "vaani", "request": "launch", "program": "lib/main.dart", - "type": "dart", - "console": "terminal" + "type": "dart" }, { "name": "vaani (profile mode)", diff --git a/lib/api/api_provider.dart b/lib/api/api_provider.dart index d6e9305..c706e9e 100644 --- a/lib/api/api_provider.dart +++ b/lib/api/api_provider.dart @@ -3,26 +3,26 @@ import 'dart:convert'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:http/http.dart'; +// import 'package:http_cache_client/http_cache_client.dart'; // import 'package:http_cache_core/http_cache_core.dart'; -// import 'package:http_cache_isar_store/http_cache_isar_store.dart'; +// import 'package:http_cache_hive_store/http_cache_hive_store.dart'; import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/db/cache/cache_key.dart'; import 'package:vaani/db/cache_manager.dart'; -import 'package:vaani/shared/utils/error_response.dart'; import 'package:vaani/features/settings/api_settings_provider.dart'; import 'package:vaani/features/settings/models/authenticated_user.dart'; import 'package:vaani/shared/extensions/obfuscation.dart'; +import 'package:vaani/shared/utils/error_response.dart'; part 'api_provider.g.dart'; -// TODO: workaround for https://github.com/rrousselGit/riverpod/issues/3718 -typedef ResponseErrorHandler = void Function( - Response response, [ - Object? error, -]); +// // TODO: workaround for https://github.com/rrousselGit/riverpod/issues/3718 +// typedef ResponseErrorHandler = void Function( +// T response, [ +// Object? error, +// ]); final _logger = Logger('api_provider'); @@ -39,15 +39,17 @@ Uri makeBaseUrl(String address) { // Global options // final options = CacheOptions( // // A default store is required for the client. -// store: IsarCacheStore("", name: "http_cache"), +// store: HiveCacheStore(appDocumentsDir.path, hiveBoxName: "http_cache"), // // All subsequent fields are optional to get a standard behaviour. // // Default. // policy: CachePolicy.request, +// // 对于给定的状态代码,返回之前缓存的错误响应。 // // Returns a previous cached response on error for given status codes. // // Defaults to `[]`. // hitCacheOnErrorCodes: const [500], +// // 允许在网络错误(例如脱机使用)时返回缓存响应。 // // Allows to return a cached response on network errors (e.g. offline usage). // // Defaults to `false`. // hitCacheOnNetworkFailure: true, @@ -72,9 +74,8 @@ AudiobookshelfApi audiobookshelfApi(Ref ref, Uri? baseUrl) { // try to get the base url from app settings final apiSettings = ref.watch(apiSettingsProvider); baseUrl ??= apiSettings.activeServer?.serverUrl; - return AudiobookshelfApi( + return DioAudiobookshelfApi( baseUrl: makeBaseUrl(baseUrl.toString()), - // client: ); } @@ -88,9 +89,10 @@ AudiobookshelfApi authenticatedApi(Ref ref) { _logger.severe('No active user can not provide authenticated api'); throw StateError('No active user'); } - return AudiobookshelfApi( + return DioAudiobookshelfApi( baseUrl: makeBaseUrl(user.server.serverUrl.toString()), token: user.authToken, + // client: CacheClient(Client(), options: options), ); } @@ -102,7 +104,7 @@ FutureOr isServerAlive(Ref ref, String address) async { } try { - return await AudiobookshelfApi(baseUrl: makeBaseUrl(address)) + return await DioAudiobookshelfApi(baseUrl: makeBaseUrl(address)) .server .ping() ?? false; diff --git a/lib/api/api_provider.g.dart b/lib/api/api_provider.g.dart index c3fa666..487ccad 100644 --- a/lib/api/api_provider.g.dart +++ b/lib/api/api_provider.g.dart @@ -6,7 +6,7 @@ part of 'api_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$audiobookshelfApiHash() => r'f23a06c404e11867a7f796877eaca99b8ff25458'; +String _$audiobookshelfApiHash() => r'd7fbddf9ce2b463468c8d4db5a1bc4a53b7b7278'; /// Copied from Dart SDK class _SystemHash { @@ -170,7 +170,7 @@ class _AudiobookshelfApiProviderElement Uri? get baseUrl => (origin as AudiobookshelfApiProvider).baseUrl; } -String _$authenticatedApiHash() => r'284be2c39823c20fb70035a136c430862c28fa27'; +String _$authenticatedApiHash() => r'13bba42fa712f173d3b72761ae9d544854df26d0'; /// get the api instance for the authenticated user /// @@ -191,7 +191,7 @@ final authenticatedApiProvider = Provider.internal( @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element typedef AuthenticatedApiRef = ProviderRef; -String _$isServerAliveHash() => r'bb3a53cae1eb64b8760a56864feed47b7a3f1c29'; +String _$isServerAliveHash() => r'3afd608ced03a23fa7300d4a59368d170406ecc8'; /// ping the server to check if it is reachable /// @@ -355,7 +355,7 @@ class ServerStatusFamily extends Family> { /// Copied from [serverStatus]. ServerStatusProvider call( Uri baseUrl, [ - void Function(Response, [Object?])? responseErrorHandler, + void Function(ApiResponse, [Object?])? responseErrorHandler, ]) { return ServerStatusProvider( baseUrl, @@ -398,7 +398,7 @@ class ServerStatusProvider /// Copied from [serverStatus]. ServerStatusProvider( Uri baseUrl, [ - void Function(Response, [Object?])? responseErrorHandler, + void Function(ApiResponse, [Object?])? responseErrorHandler, ]) : this._internal( (ref) => serverStatus( ref as ServerStatusRef, @@ -430,7 +430,7 @@ class ServerStatusProvider }) : super.internal(); final Uri baseUrl; - final void Function(Response, [Object?])? responseErrorHandler; + final void Function(ApiResponse, [Object?])? responseErrorHandler; @override Override overrideWith( @@ -480,7 +480,7 @@ mixin ServerStatusRef on AutoDisposeFutureProviderRef { Uri get baseUrl; /// The parameter `responseErrorHandler` of this provider. - void Function(Response, [Object?])? get responseErrorHandler; + void Function(ApiResponse, [Object?])? get responseErrorHandler; } class _ServerStatusProviderElement @@ -491,7 +491,7 @@ class _ServerStatusProviderElement @override Uri get baseUrl => (origin as ServerStatusProvider).baseUrl; @override - void Function(Response, [Object?])? get responseErrorHandler => + void Function(ApiResponse, [Object?])? get responseErrorHandler => (origin as ServerStatusProvider).responseErrorHandler; } diff --git a/lib/features/playback_reporting/core/playback_reporter.dart b/lib/features/playback_reporting/core/playback_reporter.dart index 68cc3b2..dc5b944 100644 --- a/lib/features/playback_reporting/core/playback_reporter.dart +++ b/lib/features/playback_reporting/core/playback_reporter.dart @@ -1,10 +1,10 @@ import 'dart:async'; -import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/features/player/core/abs_audio_player.dart'; import 'package:vaani/shared/extensions/obfuscation.dart'; +import 'package:vaani/shared/utils/error_response.dart'; final _logger = Logger('PlaybackReporter'); @@ -265,7 +265,7 @@ class PlaybackReporter { _logger.fine('cancelled timer'); } - void _responseErrorHandler(http.Response response, [error]) { + void _responseErrorHandler(ApiResponse response, [error]) { if (response.statusCode != 200) { _logger.severe('Error with api: ${response.obfuscate()}, $error'); throw PlaybackSyncError( diff --git a/lib/features/playback_reporting/core/playback_reporter_session.dart b/lib/features/playback_reporting/core/playback_reporter_session.dart index d157fcc..54405ba 100644 --- a/lib/features/playback_reporting/core/playback_reporter_session.dart +++ b/lib/features/playback_reporting/core/playback_reporter_session.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/features/player/core/abs_audio_player.dart'; @@ -211,7 +210,7 @@ class PlaybackReporter { _logger.fine('cancelled timer'); } - void _responseErrorHandler(http.Response response, [error]) { + void _responseErrorHandler(ApiResponse response, [error]) { if (response.statusCode != 200) { _logger.severe('Error with api: ${response.obfuscate()}, $error'); throw PlaybackSyncError( diff --git a/lib/shared/extensions/obfuscation.dart b/lib/shared/extensions/obfuscation.dart index 82603d0..252ab52 100644 --- a/lib/shared/extensions/obfuscation.dart +++ b/lib/shared/extensions/obfuscation.dart @@ -1,5 +1,4 @@ import 'package:flutter/foundation.dart'; -import 'package:http/http.dart' as http; import 'package:shelfsdk/audiobookshelf_api.dart' as shelfsdk; import 'package:vaani/features/settings/models/api_settings.dart'; import 'package:vaani/features/settings/models/audiobookshelf_server.dart'; @@ -98,32 +97,80 @@ extension ObfuscateApiSettings on ApiSettings { } } -extension ObfuscateRequest on http.BaseRequest { - http.BaseRequest obfuscate() { +// extension ObfuscateRequest on http.BaseRequest { +// http.BaseRequest obfuscate() { +// if (!kReleaseMode) { +// return this; +// } +// return http.Request( +// method, +// url.obfuscate(), +// ); +// } +// } + +// extension ObfuscateResponse on http.Response { +// http.Response obfuscate() { +// if (!kReleaseMode) { +// return this; +// } +// return http.Response( +// obfuscateBody(), +// statusCode, +// headers: headers, +// request: request?.obfuscate(), +// ); +// } + +// String obfuscateBody() { +// if (!kReleaseMode) { +// return body; +// } +// // replace any email addresses with emailObfuscated +// // replace any phone numbers with phoneObfuscated +// // replace any urls with urlObfuscated +// // replace any tokens with tokenObfuscated +// // token regex is `"token": "..."` +// return body +// .replaceAll( +// RegExp(r'(\b\w+@\w+\.\w+\b)|' +// r'(\b\d{3}-\d{3}-\d{4}\b)|' +// r'(\bhttps?://\S+\b)'), +// 'obfuscated', +// ) +// .replaceAll( +// RegExp(r'"?token"?:?\s*"[^"]+"'), +// '"token": "tokenObfuscated"', +// ); +// } +// } + +extension ObfuscateRequest on shelfsdk.ApiRequest { + shelfsdk.ApiRequest obfuscate() { if (!kReleaseMode) { return this; } - return http.Request( - method, - url.obfuscate(), + return shelfsdk.ApiRequest( + method: method, + url: url, ); } } -extension ObfuscateResponse on http.Response { - http.Response obfuscate() { +extension ObfuscateResponse on shelfsdk.ApiResponse { + shelfsdk.ApiResponse obfuscate() { if (!kReleaseMode) { return this; } - return http.Response( - obfuscateBody(), + return shelfsdk.BaseResponse( statusCode, + obfuscateBody(), headers: headers, - request: request?.obfuscate(), + request: request.obfuscate(), ); } - String obfuscateBody() { + dynamic obfuscateBody() { if (!kReleaseMode) { return body; } diff --git a/lib/shared/utils/error_response.dart b/lib/shared/utils/error_response.dart index 13352be..929f4d0 100644 --- a/lib/shared/utils/error_response.dart +++ b/lib/shared/utils/error_response.dart @@ -1,26 +1,26 @@ -import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; +import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/shared/extensions/obfuscation.dart'; final _logger = Logger('ErrorResponse'); class ErrorResponseHandler { String? name; - http.Response _response; + ApiResponse _response; bool logRawResponse; ErrorResponseHandler({ this.name, - http.Response? response, + dynamic response, this.logRawResponse = false, - }) : _response = response ?? http.Response('', 418); + }) : _response = response ?? BaseResponse(418, ''); - void storeError(http.Response response, [Object? error]) { + void storeError(ApiResponse response, [Object? error]) { if (logRawResponse) { - _logger.fine('for $name got response: ${response.obfuscate()}'); + _logger.severe('for $name got response: ${response.obfuscate()}'); } _response = response; } - http.Response get response => _response; + ApiResponse get response => _response; } diff --git a/pubspec.yaml b/pubspec.yaml index a45d50d..1c8f42f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -116,7 +116,7 @@ dependencies: tray_manager: ^0.5.2 icons_plus: ^5.0.0 # http_cache_client: ^1.0.4 - # http_cache_isar_store: ^3.0.0-dev.1 + # http_cache_hive_store: ^5.0.1 dev_dependencies: build_runner: ^2.4.9 diff --git a/shelfsdk b/shelfsdk index e1848a4..c4d69ad 160000 --- a/shelfsdk +++ b/shelfsdk @@ -1 +1 @@ -Subproject commit e1848a42c27257146015a33e9427f197f522fe03 +Subproject commit c4d69ada95a8ad2db367bb3c5efd181668ceca6d