feat: more easter eggs + version checking
This commit is contained in:
@@ -26,6 +26,13 @@ class UnauthorizedException extends ApiException {
|
||||
: super(401, message ?? 'Unauthorized');
|
||||
}
|
||||
|
||||
/// This app is older than the backoffice accepts; it has to be updated
|
||||
/// before it can sync again. The token stays valid.
|
||||
class UpdateRequiredException extends ApiException {
|
||||
const UpdateRequiredException({super.code, String? message})
|
||||
: super(426, message ?? 'App update required');
|
||||
}
|
||||
|
||||
class RateLimitedException extends ApiException {
|
||||
final Duration retryAfter;
|
||||
|
||||
@@ -43,15 +50,26 @@ class KoolTapApiClient {
|
||||
final http.Client _client;
|
||||
final String baseUrl;
|
||||
|
||||
KoolTapApiClient({http.Client? client, this.baseUrl = kRemoteServerUrl})
|
||||
: _client = client ?? http.Client();
|
||||
/// Sent with every request so the backoffice can refuse an app that is too
|
||||
/// old (`426 app_update_required`).
|
||||
final String? appVersion;
|
||||
|
||||
KoolTapApiClient({
|
||||
http.Client? client,
|
||||
this.baseUrl = kRemoteServerUrl,
|
||||
this.appVersion,
|
||||
}) : _client = client ?? http.Client();
|
||||
|
||||
Map<String, String> get _versionHeader => {
|
||||
'X-App-Version': ?appVersion,
|
||||
};
|
||||
|
||||
static const _timeout = Duration(seconds: 15);
|
||||
static const _defaultRetryAfter = Duration(seconds: 60);
|
||||
|
||||
Future<List<Venue>> getVenues() async {
|
||||
final response = await _client
|
||||
.get(Uri.parse('$baseUrl/venues/'))
|
||||
.get(Uri.parse('$baseUrl/venues/'), headers: _versionHeader)
|
||||
.timeout(_timeout);
|
||||
|
||||
final data = _decode(response) as List<dynamic>;
|
||||
@@ -117,6 +135,7 @@ class KoolTapApiClient {
|
||||
'POST',
|
||||
Uri.parse('$baseUrl/devices/$deviceId/images'),
|
||||
)
|
||||
..headers.addAll(_versionHeader)
|
||||
..headers['Authorization'] = 'Bearer $token'
|
||||
..files.add(
|
||||
http.MultipartFile.fromBytes('file', bytes, filename: filename),
|
||||
@@ -133,7 +152,7 @@ class KoolTapApiClient {
|
||||
/// A product picture (public: pictures never change at their address).
|
||||
Future<List<int>> downloadImage(String imageId) async {
|
||||
final response = await _client
|
||||
.get(Uri.parse('$baseUrl/images/$imageId'))
|
||||
.get(Uri.parse('$baseUrl/images/$imageId'), headers: _versionHeader)
|
||||
.timeout(_timeout * 2);
|
||||
if (response.statusCode != 200) {
|
||||
throw ApiException(response.statusCode, 'Image $imageId not available');
|
||||
@@ -151,6 +170,7 @@ class KoolTapApiClient {
|
||||
Uri.parse('$baseUrl$path'),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
..._versionHeader,
|
||||
if (token != null) 'Authorization': 'Bearer $token',
|
||||
},
|
||||
body: jsonEncode(body),
|
||||
@@ -170,6 +190,11 @@ class KoolTapApiClient {
|
||||
throw UnauthorizedException(code: error.code, message: error.message);
|
||||
}
|
||||
|
||||
if (status == 426) {
|
||||
final error = _error(response);
|
||||
throw UpdateRequiredException(code: error.code, message: error.message);
|
||||
}
|
||||
|
||||
if (status == 429) {
|
||||
final seconds = int.tryParse(response.headers['retry-after'] ?? '');
|
||||
throw RateLimitedException(
|
||||
|
||||
@@ -273,6 +273,13 @@ class RemoteSyncService {
|
||||
stopPeriodicSync();
|
||||
_emit(RemoteSyncEventType.unauthorized);
|
||||
return;
|
||||
} on UpdateRequiredException catch (e) {
|
||||
// Retrying can't help until the app is updated. The token and every
|
||||
// outbox stay, so nothing is lost; a manual sync or restart tries again
|
||||
debugPrint('RemoteSyncService: app update required');
|
||||
stopPeriodicSync();
|
||||
_emit(RemoteSyncEventType.updateRequired, message: e.message);
|
||||
return;
|
||||
} on RateLimitedException catch (e) {
|
||||
nextDelay = await _recordFailure(e, retryAfter: e.retryAfter);
|
||||
} catch (e, stack) {
|
||||
@@ -328,6 +335,8 @@ class RemoteSyncService {
|
||||
);
|
||||
} on UnauthorizedException {
|
||||
rethrow;
|
||||
} on UpdateRequiredException {
|
||||
rethrow;
|
||||
} catch (e) {
|
||||
debugPrint('RemoteSyncService: picture upload failed: $e');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user