102 lines
3.2 KiB
Dart
102 lines
3.2 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'package:signalr_core/signalr_core.dart';
|
|
import 'package:finlytic_app/core/network/api_client.dart';
|
|
import 'package:finlytic_app/features/news/models/news_article_model.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
|
|
class NewsRepository {
|
|
final ApiClient apiClient;
|
|
final String backendUrl;
|
|
final FlutterSecureStorage secureStorage = const FlutterSecureStorage();
|
|
|
|
HubConnection? _hubConnection;
|
|
final _liveNewsController = StreamController<NewsArticleModel>.broadcast();
|
|
|
|
Stream<NewsArticleModel> get liveNewsStream => _liveNewsController.stream;
|
|
|
|
NewsRepository({required this.apiClient, required this.backendUrl});
|
|
|
|
Future<List<NewsArticleModel>> fetchNews({
|
|
int page = 1,
|
|
int pageSize = 20,
|
|
String? symbol,
|
|
String? isin,
|
|
String? date,
|
|
}) async {
|
|
try {
|
|
final Map<String, dynamic> queryParams = {
|
|
'page': page,
|
|
'pageSize': pageSize,
|
|
};
|
|
|
|
if (symbol != null && symbol.isNotEmpty) queryParams['symbol'] = symbol;
|
|
if (isin != null && isin.isNotEmpty) queryParams['isin'] = isin;
|
|
if (date != null && date.isNotEmpty) queryParams['date'] = date;
|
|
|
|
final response = await apiClient.get('/api/v1/news', queryParameters: queryParams);
|
|
|
|
if (response.statusCode == 200) {
|
|
final List<dynamic> data = response.data;
|
|
return data.map((json) => NewsArticleModel.fromJson(json)).toList();
|
|
}
|
|
return [];
|
|
} catch (e) {
|
|
print('Error fetching news: $e');
|
|
throw Exception('Failed to load news');
|
|
}
|
|
}
|
|
|
|
Future<void> connectToLiveFeed() async {
|
|
if (_hubConnection != null && _hubConnection!.state == HubConnectionState.connected) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
final token = await secureStorage.read(key: 'auth_token');
|
|
final hubUrl = '$backendUrl/hubs/news${token != null ? '?access_token=$token' : ''}';
|
|
|
|
_hubConnection = HubConnectionBuilder()
|
|
.withUrl(hubUrl, HttpConnectionOptions(
|
|
logging: (level, message) => print(message),
|
|
))
|
|
.withAutomaticReconnect()
|
|
.build();
|
|
|
|
_hubConnection!.on('ReceiveNewArticle', (arguments) {
|
|
if (arguments != null && arguments.isNotEmpty) {
|
|
try {
|
|
// SignalR might send it as a Map or raw JSON depending on .NET format
|
|
final dynamic rawPayload = arguments[0];
|
|
final Map<String, dynamic> jsonData = rawPayload is String
|
|
? jsonDecode(rawPayload)
|
|
: Map<String, dynamic>.from(rawPayload);
|
|
|
|
final article = NewsArticleModel.fromJson(jsonData);
|
|
_liveNewsController.add(article);
|
|
} catch (e) {
|
|
print('Error parsing live article: $e');
|
|
}
|
|
}
|
|
});
|
|
|
|
await _hubConnection!.start();
|
|
print('Connected to News Live Feed');
|
|
} catch (e) {
|
|
print('Error connecting to News Live Feed: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> disconnectFromLiveFeed() async {
|
|
if (_hubConnection != null) {
|
|
await _hubConnection!.stop();
|
|
_hubConnection = null;
|
|
}
|
|
}
|
|
|
|
void dispose() {
|
|
_liveNewsController.close();
|
|
disconnectFromLiveFeed();
|
|
}
|
|
}
|