import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import '../models/external_symbol_model.dart'; class ExternalSymbolsRepository { static final ExternalSymbolsRepository _instance = ExternalSymbolsRepository._internal(); factory ExternalSymbolsRepository() => _instance; ExternalSymbolsRepository._internal(); List _symbols = []; bool _isLoaded = false; List get allSymbols => _symbols; bool get isLoaded => _isLoaded; int get totalCount => _symbols.length; Future init() async { if (_isLoaded) return; try { String jsonStr = ''; // 1. Попытка чтения напрямую из файловой системы (для dev / test) for (final p in ['assets/data/oracle_external_symbols.json', '../assets/data/oracle_external_symbols.json']) { final f = File(p); if (f.existsSync()) { jsonStr = f.readAsStringSync(); break; } } // 2. В релизе загружаем через rootBundle if (jsonStr.isEmpty && !Platform.environment.containsKey('FLUTTER_TEST')) { try { jsonStr = await rootBundle.loadString('assets/data/oracle_external_symbols.json'); } catch (_) {} } if (jsonStr.isNotEmpty) { final decoded = json.decode(jsonStr) as Map; _symbols = decoded.values .map((v) => ExternalSymbol.fromMap(Map.from(v as Map))) .toList(); // Сортируем по алфавиту _symbols.sort((a, b) => a.term.toLowerCase().compareTo(b.term.toLowerCase())); _isLoaded = true; } } catch (e) { debugPrint('[ExternalSymbolsRepository] Ошибка загрузки: $e'); } } List search(String query, {bool onlyWithImages = false}) { final q = query.trim().toLowerCase(); return _symbols.where((s) { if (onlyWithImages && !s.hasIllustrations) return false; if (q.isEmpty) return true; if (s.term.toLowerCase().contains(q)) return true; if (s.normalized.contains(q)) return true; if (s.sources.any((src) => src.author.toLowerCase().contains(q) || src.excerpt.toLowerCase().contains(q))) { return true; } return false; }).toList(); } }