import 'package:dio/dio.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; class ApiClient { late final Dio dio; final FlutterSecureStorage _storage = const FlutterSecureStorage(); VoidCallback? onForceLogout; ApiClient() { dio = Dio(BaseOptions( connectTimeout: const Duration(seconds: 15), receiveTimeout: const Duration(seconds: 30), )); dio.interceptors.add(InterceptorsWrapper( onRequest: (options, handler) async { final token = await _storage.read(key: 'access_token'); if (token != null) { options.headers['Authorization'] = 'Bearer $token'; } handler.next(options); }, onError: (error, handler) async { if (error.response?.statusCode == 401) { final refreshed = await _tryRefreshToken(); if (refreshed) { final opts = error.requestOptions; final token = await _storage.read(key: 'access_token'); opts.headers['Authorization'] = 'Bearer $token'; try { final response = await dio.fetch(opts); return handler.resolve(response); } catch (e) { return handler.next(error); } } else { onForceLogout?.call(); } } handler.next(error); }, )); } Future setBaseUrl(String serverUrl) async { final url = serverUrl.endsWith('/') ? serverUrl.substring(0, serverUrl.length - 1) : serverUrl; dio.options.baseUrl = '$url/wp-json/twilio-mobile/v1'; await _storage.write(key: 'server_url', value: url); } Future restoreBaseUrl() async { final url = await _storage.read(key: 'server_url'); if (url != null) { dio.options.baseUrl = '$url/wp-json/twilio-mobile/v1'; } } Future _tryRefreshToken() async { try { final refreshToken = await _storage.read(key: 'refresh_token'); if (refreshToken == null) return false; final response = await dio.post( '/auth/refresh', data: {'refresh_token': refreshToken}, options: Options(headers: {'Authorization': ''}), ); if (response.statusCode == 200 && response.data['success'] == true) { await _storage.write( key: 'access_token', value: response.data['access_token']); if (response.data['refresh_token'] != null) { await _storage.write( key: 'refresh_token', value: response.data['refresh_token']); } return true; } } catch (_) {} return false; } } typedef VoidCallback = void Function();