86 lines
2.9 KiB
Dart
86 lines
2.9 KiB
Dart
import 'package:flutter/foundation.dart';
|
||
import 'package:qpay/http/http.dart';
|
||
import 'package:qpay/browser.dart';
|
||
|
||
const appBuildNumber = 6;
|
||
|
||
/// Describes the result of the build-number check performed during splash.
|
||
enum SplashCheckStatus { checking, noUpdate, updateAvailable }
|
||
|
||
class SplashProvider extends ChangeNotifier {
|
||
final Http _http = Http();
|
||
|
||
SplashCheckStatus _status = SplashCheckStatus.checking;
|
||
Map<String, dynamic>? _updatePayload;
|
||
bool _isRefreshing = false;
|
||
|
||
SplashCheckStatus get status => _status;
|
||
Map<String, dynamic>? get updatePayload => _updatePayload;
|
||
bool get isRefreshing => _isRefreshing;
|
||
|
||
/// The store / download URL from the server payload, or `null` if
|
||
/// the server didn't include one.
|
||
String? get downloadUrl => _updatePayload?['downloadUrl']?.toString();
|
||
|
||
/// Calls the server endpoint to see whether a newer app build exists.
|
||
///
|
||
/// * 204 → no new build — proceed with normal app loading.
|
||
/// * 200 → a new build is available — the splash screen will show a
|
||
/// non-dismissible bottom sheet offering the user a hard refresh.
|
||
Future<void> checkVersion() async {
|
||
_status = SplashCheckStatus.checking;
|
||
notifyListeners();
|
||
|
||
try {
|
||
final buildNumber = appBuildNumber;
|
||
String url;
|
||
if (kIsWeb) {
|
||
url = '/public/app-version/check/web?currentBuildNumber=$buildNumber';
|
||
} else {
|
||
url = '/public/app-version/check/app?currentBuildNumber=$buildNumber';
|
||
}
|
||
|
||
final response = await _http.getRaw(url);
|
||
|
||
if (response.statusCode == 204) {
|
||
_status = SplashCheckStatus.noUpdate;
|
||
} else if (response.statusCode == 200) {
|
||
_status = SplashCheckStatus.updateAvailable;
|
||
_updatePayload = response.data is Map
|
||
? response.data as Map<String, dynamic>
|
||
: null;
|
||
} else {
|
||
// Unexpected status code – don't block the user.
|
||
_status = SplashCheckStatus.noUpdate;
|
||
}
|
||
} catch (_) {
|
||
// Network / server errors should not prevent the app from loading.
|
||
_status = SplashCheckStatus.noUpdate;
|
||
}
|
||
|
||
notifyListeners();
|
||
}
|
||
|
||
/// 1. Sends a POST request to clear the Cloudflare cache.
|
||
/// 2. Waits 5 seconds to give the CDN time to propagate.
|
||
/// 3. Performs a hard refresh by reloading the current URL, which
|
||
/// forces the browser to re-fetch all cached assets.
|
||
Future<void> clearCacheAndRefresh() async {
|
||
_isRefreshing = true;
|
||
notifyListeners();
|
||
|
||
try {
|
||
await _http.postRaw('/public/cache/cloudflare/clear');
|
||
} catch (_) {
|
||
// Proceed with refresh even if the cache-clear request fails.
|
||
}
|
||
|
||
// Allow Cloudflare a few seconds to flush its edge cache.
|
||
await Future<void>.delayed(const Duration(seconds: 5));
|
||
|
||
// Hard-refresh: navigate to the current location which triggers a
|
||
// full page reload on web (and restarts the app on other platforms).
|
||
Browser.location.href = Browser.location.href;
|
||
}
|
||
}
|