- Flutter app with chat and terminal screens - WebSocket integration for real-time chat - xterm integration for screen sessions - Markdown rendering with code blocks - JWT authentication Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
83 lines
2.2 KiB
Dart
83 lines
2.2 KiB
Dart
import 'package:dio/dio.dart';
|
|
import '../config/api_config.dart';
|
|
import '../models/session.dart';
|
|
import '../models/message.dart';
|
|
|
|
class ApiService {
|
|
late final Dio _dio;
|
|
String? _token;
|
|
|
|
ApiService() {
|
|
_dio = Dio(BaseOptions(
|
|
baseUrl: ApiConfig.baseUrl,
|
|
connectTimeout: ApiConfig.connectionTimeout,
|
|
receiveTimeout: ApiConfig.receiveTimeout,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
));
|
|
|
|
_dio.interceptors.add(InterceptorsWrapper(
|
|
onRequest: (options, handler) {
|
|
if (_token != null) {
|
|
options.headers['Authorization'] = 'Bearer $_token';
|
|
}
|
|
return handler.next(options);
|
|
},
|
|
onError: (error, handler) {
|
|
if (error.response?.statusCode == 401) {
|
|
// Token expired, trigger re-login
|
|
}
|
|
return handler.next(error);
|
|
},
|
|
));
|
|
}
|
|
|
|
void setToken(String? token) {
|
|
_token = token;
|
|
}
|
|
|
|
Future<Map<String, dynamic>> login(String username, String password) async {
|
|
final response = await _dio.post(
|
|
ApiConfig.login,
|
|
data: {
|
|
'username': username,
|
|
'password': password,
|
|
},
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
Future<List<ScreenSession>> getSessions() async {
|
|
final response = await _dio.get(ApiConfig.sessions);
|
|
return (response.data as List)
|
|
.map((json) => ScreenSession.fromJson(json))
|
|
.toList();
|
|
}
|
|
|
|
Future<List<Conversation>> getHistory({int limit = 20}) async {
|
|
final response = await _dio.get(
|
|
ApiConfig.history,
|
|
queryParameters: {'limit': limit},
|
|
);
|
|
return (response.data as List)
|
|
.map((json) => Conversation.fromJson(json))
|
|
.toList();
|
|
}
|
|
|
|
Future<List<Message>> getConversationMessages(String conversationId) async {
|
|
final response = await _dio.get('${ApiConfig.history}/$conversationId');
|
|
return (response.data as List)
|
|
.map((json) => Message.fromJson(json))
|
|
.toList();
|
|
}
|
|
|
|
Future<Map<String, dynamic>> uploadFile(String filePath) async {
|
|
final formData = FormData.fromMap({
|
|
'file': await MultipartFile.fromFile(filePath),
|
|
});
|
|
final response = await _dio.post(ApiConfig.upload, data: formData);
|
|
return response.data;
|
|
}
|
|
}
|