fix(apps): consolidate FormzInput validators and fix login screen

- Move FormzInput validators to core/form_inputs/form_inputs.dart
- Fix login_screen.dart syntax error (missing 'class' keyword)
- Remove unused _isLoading field
- Fix unnecessary const keywords
- Update login_cubit and register_cubit imports
- Remove duplicate FormzInput definitions from register_cubit
- Add Toast and Banner UI feedback system
- Remove legacy login/register screens (login_code, login_email, login_password, register_step2)
- Remove unused warning_banner widget
- Update tests for new error messages and DI setup
This commit is contained in:
qzl
2026-02-25 18:00:02 +08:00
parent d3bdb3ab4f
commit e20b1905cb
25 changed files with 542 additions and 608 deletions
+27 -21
View File
@@ -6,36 +6,42 @@ import '../storage/token_storage.dart';
class ApiClient {
final Dio _dio;
final TokenStorage _tokenStorage;
final Future<bool> Function(String)? _refreshToken;
final ApiInterceptor _interceptor;
ApiClient({
factory ApiClient({
required String baseUrl,
required TokenStorage tokenStorage,
Dio? dio,
Future<bool> Function(String)? refreshToken,
}) : _tokenStorage = tokenStorage,
_refreshToken = refreshToken,
_dio = dio ?? Dio(BaseOptions(baseUrl: baseUrl)) {
_dio.interceptors.add(
ApiInterceptor(
tokenStorage: _tokenStorage,
dio: _dio,
onTokenRefresh: _handleTokenRefresh,
),
}) {
final effectiveDio = dio ?? Dio(BaseOptions(baseUrl: baseUrl));
final interceptor = ApiInterceptor(
tokenStorage: tokenStorage,
dio: effectiveDio,
);
effectiveDio.interceptors.add(interceptor);
return ApiClient._(
dio: effectiveDio,
tokenStorage: tokenStorage,
interceptor: interceptor,
);
}
ApiClient._({
required Dio dio,
required TokenStorage tokenStorage,
required ApiInterceptor interceptor,
}) : _dio = dio,
_tokenStorage = tokenStorage,
_interceptor = interceptor;
Dio get dio => _dio;
Future<bool> _handleTokenRefresh() async {
final refreshToken = await _tokenStorage.getRefreshToken();
if (refreshToken == null || _refreshToken == null) return false;
try {
final success = await _refreshToken!(refreshToken);
return success;
} catch (_) {
return false;
}
void setRefreshCallback(Future<bool> Function(String) refresh) {
_interceptor.onTokenRefresh = () async {
final token = await _tokenStorage.getRefreshToken();
if (token == null) return false;
return refresh(token);
};
}
Future<Response<T>> get<T>(String path, {Options? options}) async {