Added class clearance fixes and improvements
Some checks failed
Release / meta (push) Successful in 18s
Release / android-build (push) Successful in 11m48s
Release / linux-build (push) Successful in 1m24s
Release / web-build (push) Successful in 6m15s
Release / release-dev (push) Has been cancelled
Release / release-master (push) Has been cancelled

This commit is contained in:
2026-01-22 23:17:15 +00:00
parent 559f79b805
commit d8312a3f1b
19 changed files with 865 additions and 63 deletions

View File

@@ -55,6 +55,40 @@ class ApiService {
return _processResponse(response);
}
Future<ApiBinaryResponse> getBytes(
String endpoint, {
Map<String, String>? headers,
}) async {
final response = await _client
.get(
Uri.parse('$baseUrl$endpoint'),
headers: _buildHeaders(headers),
)
.timeout(timeout);
if (response.statusCode >= 200 && response.statusCode < 300) {
final contentDisposition = response.headers['content-disposition'];
return ApiBinaryResponse(
bytes: response.bodyBytes,
statusCode: response.statusCode,
contentType: response.headers['content-type'],
filename: _extractFilename(contentDisposition),
);
}
if (response.statusCode == 401 && _onUnauthorized != null) {
await _onUnauthorized!();
}
final body = _decodeBody(response);
final message = _extractErrorMessage(body);
throw ApiException(
statusCode: response.statusCode,
message: message,
body: body,
);
}
Future<dynamic> post(
String endpoint,
dynamic data, {
@@ -176,6 +210,20 @@ class ApiService {
}
return body.toString();
}
String? _extractFilename(String? contentDisposition) {
if (contentDisposition == null || contentDisposition.isEmpty) return null;
final utf8Match =
RegExp(r"filename\\*=UTF-8''([^;]+)", caseSensitive: false)
.firstMatch(contentDisposition);
if (utf8Match != null) {
return Uri.decodeComponent(utf8Match.group(1) ?? '');
}
final match =
RegExp(r'filename="?([^\";]+)"?', caseSensitive: false)
.firstMatch(contentDisposition);
return match?.group(1);
}
}
class ApiException implements Exception {
@@ -192,3 +240,17 @@ class ApiException implements Exception {
@override
String toString() => 'API error $statusCode: $message';
}
class ApiBinaryResponse {
final List<int> bytes;
final int statusCode;
final String? contentType;
final String? filename;
ApiBinaryResponse({
required this.bytes,
required this.statusCode,
this.contentType,
this.filename,
});
}