новости
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:moonwell_launcher/features/launcher/data/launcher_log_service.da
|
||||
import 'package:moonwell_launcher/features/launcher/domain/entities/client_manifest.dart';
|
||||
import 'package:moonwell_launcher/features/launcher/domain/entities/client_manifest_file.dart';
|
||||
import 'package:moonwell_launcher/features/launcher/domain/entities/launcher_exception.dart';
|
||||
import 'package:moonwell_launcher/features/launcher/domain/entities/launcher_news_item.dart';
|
||||
import 'package:moonwell_launcher/features/launcher/domain/entities/launcher_session.dart';
|
||||
|
||||
@lazySingleton
|
||||
@@ -83,6 +84,44 @@ class LauncherApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<LauncherNewsItem>> fetchNews(String accessToken) async {
|
||||
final newsUri = _resolveUri('api/launcher/news');
|
||||
|
||||
try {
|
||||
final response = await _dio.getUri(
|
||||
newsUri,
|
||||
options: _authorizedOptions(accessToken),
|
||||
);
|
||||
final payload = _coerceMap(response.data);
|
||||
final rawItems = payload['data'];
|
||||
if (rawItems is! List) {
|
||||
throw const LauncherApiException('Unexpected launcher news payload.');
|
||||
}
|
||||
|
||||
return rawItems
|
||||
.whereType<Map>()
|
||||
.map(
|
||||
(item) => LauncherNewsItem.fromJson(
|
||||
item.map((key, value) => MapEntry(key.toString(), value)),
|
||||
),
|
||||
)
|
||||
.toList(growable: false);
|
||||
} on DioException catch (error, stackTrace) {
|
||||
await _launcherLogService.error(
|
||||
'Launcher news request failed.',
|
||||
details: <String, Object?>{
|
||||
'endpoint': newsUri.toString(),
|
||||
'statusCode': error.response?.statusCode,
|
||||
'dioType': error.type.name,
|
||||
'responseBody': _summarizePayload(error.response?.data),
|
||||
},
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
throw LauncherApiException(_extractErrorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> downloadFile({
|
||||
required String installationDir,
|
||||
required String accessToken,
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
final class LauncherNewsItem {
|
||||
final int id;
|
||||
final String title;
|
||||
final String body;
|
||||
final String? imageUrl;
|
||||
final DateTime? createdAt;
|
||||
|
||||
const LauncherNewsItem({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.body,
|
||||
required this.imageUrl,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory LauncherNewsItem.fromJson(Map<String, dynamic> json) {
|
||||
return LauncherNewsItem(
|
||||
id: (json['id'] as num? ?? 0).toInt(),
|
||||
title: (json['title'] as String? ?? '').trim(),
|
||||
body: (json['body'] as String? ?? '').trim(),
|
||||
imageUrl: _parseImageUrl(json['image_url'] as String?),
|
||||
createdAt: _parseDateTime(json['created_at'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
static String? _parseImageUrl(String? rawValue) {
|
||||
if (rawValue == null || rawValue.trim().isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return rawValue.trim();
|
||||
}
|
||||
|
||||
static DateTime? _parseDateTime(String? rawValue) {
|
||||
if (rawValue == null || rawValue.trim().isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DateTime.tryParse(rawValue);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user