didvan-app/lib/views/home/bookmarks/bookmark_state.dart

189 lines
6.1 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:didvan/config/auth_config.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/home_page_content/swot.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/auth/token_storage.dart';
import 'package:didvan/services/content/content_service.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:didvan/views/home/bookmarks/bookmark_service.dart';
import 'package:didvan/services/swot_service.dart';
class BookmarksState extends CoreProvier {
final List<OverviewData> bookmarks = [];
List<SwotItem> bookmarkedSwotItems = [];
String search = '';
String lastSearch = '';
int page = 1;
int lastPage = 1;
List<int> selectedTypes = [];
DateTime? startDate;
DateTime? endDate;
bool get isFiltered =>
selectedTypes.isNotEmpty || startDate != null || endDate != null;
bool _swotItemsLoading = false;
bool get searching => search.isNotEmpty;
bool get swotItemsLoading => _swotItemsLoading;
Future<void> loadInitialData() async {
appState = AppState.busy;
_swotItemsLoading = true;
bookmarks.clear();
bookmarkedSwotItems.clear();
notifyListeners();
await Future.wait([
_fetchGeneralBookmarks(page: 1),
_fetchSwotBookmarks(),
]);
if (appState != AppState.failed && !searching) {
appState = AppState.idle;
} else if (appState != AppState.failed &&
searching &&
bookmarks.isEmpty &&
bookmarkedSwotItems.isEmpty) {
appState = AppState.idle;
}
_swotItemsLoading = false;
notifyListeners();
}
Future<void> _fetchGeneralBookmarks({required int page}) async {
if (page == 1) bookmarks.clear();
this.page = page;
if (!searching) lastSearch = search;
// مسیر جدید: content های bookmarkشده از api2.didvan.com.
final userId = TokenStorage.userId;
if (userId != null && userId.isNotEmpty) {
final result = await ContentService.instance.getBookmarkedContents(
userId: userId,
page: page,
limit: 15,
search: search.isNotEmpty ? search : null,
);
if (result.isSuccess && result.data != null) {
lastPage = result.data!.totalPages;
bookmarks.addAll(result.data!.data.map((c) {
final ov = OverviewData.fromContentItem(c);
// در صفحه‌ی نشان‌شده‌ها فیلدِ «یادداشتِ من» از description خوانده
// می‌شود؛ آن را خالی می‌کنیم تا کاربر یادداشتِ خودش را بنویسد و
// summaryِ محتوا در آن نیاید.
ov.description = '';
return ov;
}));
return;
}
// اگر content جدید خطا داد (مثلا 403) و legacy هم در دسترس نیست،
// فقط swot bookmarks نمایش داده می‌شود؛ general را خالی می‌گذاریم.
if (!AuthConfig.useLegacyApi) {
// failure را fatal نمی‌کنیم تا swot bookmarks دیده شوند.
return;
}
}
// TODO(backend-migration): مسیر legacy (api.didvan.app/home/mark/v2).
// فعلا فقط در صورت useLegacyApi اجرا می‌شود.
if (!AuthConfig.useLegacyApi) return;
final service = RequestService(
RequestHelper.searchMarks(
page: page,
search: search.isNotEmpty ? search : null,
types: selectedTypes.isNotEmpty ? selectedTypes : null,
startDate: startDate?.toIso8601String().split('T').first,
endDate: endDate?.toIso8601String().split('T').first,
),
);
await service.httpGet();
if (service.isSuccess) {
lastPage = service.result['lastPage'];
final marks = service.result['contents'];
for (var i = 0; i < marks.length; i++) {
bookmarks.add(OverviewData.fromJson(marks[i]));
}
} else {
appState = AppState.failed;
}
}
Future<void> searchAndLoadData({required int page}) async {
appState = AppState.busy;
_swotItemsLoading = true;
bookmarks.clear();
notifyListeners();
await Future.wait([
_fetchGeneralBookmarks(page: page),
_fetchSwotBookmarks(),
]);
if (appState != AppState.failed) {
appState = AppState.idle;
}
_swotItemsLoading = false;
notifyListeners();
}
Future<void> _fetchSwotBookmarks() async {
try {
if (selectedTypes.isNotEmpty && !selectedTypes.contains(8)) {
bookmarkedSwotItems = [];
return;
}
// TODO(backend-migration): opportunity-threat.didvan.com/api/bookmarks
// توکن جدید Keycloak را نمی‌پذیرد (403). تا زمانی که آن سرور با
// احراز هویت جدید سازگار شود یا bookmark به api2 منتقل شود، این
// مسیر را در حالت غیر-legacy رد می‌کنیم.
if (!AuthConfig.useLegacyApi) {
bookmarkedSwotItems = [];
return;
}
final postIds = await BookmarkService.fetchBookmarks();
if (postIds.isNotEmpty) {
final allSwots = await SwotService.fetchSwotItems();
bookmarkedSwotItems = allSwots.where((swot) {
final isBookmarked = postIds.contains(swot.id);
if (search.isEmpty) return isBookmarked;
return isBookmarked &&
swot.title.toLowerCase().contains(search.toLowerCase());
}).toList();
} else {
bookmarkedSwotItems = [];
}
} catch (e) {
bookmarkedSwotItems = [];
}
}
void onMarkChanged(int id, bool value) {
bookmarks.removeWhere((element) => element.id == id);
notifyListeners();
}
void onSwotMarkChanged(int swotId) {
bookmarkedSwotItems.removeWhere((element) => element.id == swotId);
notifyListeners();
}
void resetFilters([bool notify = true]) {
selectedTypes.clear();
startDate = null;
endDate = null;
if (notify) {
loadInitialData();
}
}
// ignore: annotate_overrides
void update() {
notifyListeners();
}
}