import 'dart:async'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:terepi_seged/models/measured_record.dart'; import 'package:terepi_seged/pages/measured_data/presentation/views/seismogram_viewer_dialog.dart'; import 'package:terepi_seged/services/measured_data_service.dart'; import 'package:terepi_seged/services/project_service.dart'; class MeasuredDataController extends GetxController { static MeasuredDataController get to => Get.find(); final records = [].obs; final isLoading = true.obs; final searchText = ''.obs; final lineFilter = Rxn(); StreamSubscription>? _sub; @override void onInit() { super.onInit(); _subscribe(); ever(ProjectService.to.activeProject, (_) => _subscribe()); } void _subscribe() { _sub?.cancel(); lineFilter.value = null; final projectId = ProjectService.to.activeProject.value?.uuid; if (projectId == null) { records.clear(); isLoading.value = false; return; } isLoading.value = true; _sub = MeasuredDataService.to.watchRecords(projectId).listen( (data) { records.value = data; isLoading.value = false; }, onError: (e) { isLoading.value = false; Get.snackbar('Hiba', 'Nem sikerült betölteni a mérési adatokat: $e', snackPosition: SnackPosition.BOTTOM); }, ); } // ── Keresés/szűrés — a már memóriában lévő, élő listán, nem újabb // lekérdezéssel (a teljes projekt-adat úgyis a stream-ben van). ── List get filteredRecords { var list = records.toList(); if (lineFilter.value != null) { list = list.where((r) => r.sourceLineNumber == lineFilter.value).toList(); } final q = searchText.value.trim(); if (q.isNotEmpty) { list = list.where((r) { return (r.ffid?.toString().contains(q) ?? false) || (r.sourcePointNumber?.toString().contains(q) ?? false) || (r.sourceLineNumber?.toString().contains(q) ?? false); }).toList(); } return list; } List get availableLines { final set = records.map((r) => r.sourceLineNumber).whereType().toSet(); final list = set.toList()..sort(); return list; } void onSearchChanged(String v) => searchText.value = v; void setLineFilter(double? v) => lineFilter.value = v; // ── Kép megtekintése ───────────────────────────────────────────── Future showSeismicImage(MeasuredRecord record) async { if (!record.hasImage) { Get.snackbar('Nincs kép', 'Ehhez a felvételhez nincs rögzített kép.', snackPosition: SnackPosition.BOTTOM); return; } Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); try { final Uint8List? bytes = await MeasuredDataService.to.loadImage(record); Get.back(); // töltő-dialógus bezárása if (bytes == null) { Get.snackbar('Hiba', 'A kép nem tölthető be.', snackPosition: SnackPosition.BOTTOM); return; } Get.to(() => SeismogramViewerDialog(record: record, image: bytes), transition: Transition.downToUp); } catch (e) { Get.back(); Get.snackbar('Hiba', 'Kép letöltése sikertelen: $e', snackPosition: SnackPosition.BOTTOM); } } @override void onClose() { _sub?.cancel(); super.onClose(); } }