Untitled
unknown
plain_text
9 months ago
8.0 kB
8
Indexable
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:family_tree/app/modules/family_tree/controllers/tree_controller.dart';
import 'package:family_tree/app/modules/family_tree/model/family_model.dart';
import 'package:family_tree/app/modules/profile/controllers/profile_controller.dart';
import 'package:family_tree/app/modules/session/controllers/session_controller.dart';
import 'package:family_tree/constant/shared_preference_key.dart';
import 'package:family_tree/constant/url.dart';
import 'package:family_tree/library/dio_client.dart';
import 'package:family_tree/mgwidgets/loading_widget.dart';
class FamilyTreeController extends GetxController with GetTickerProviderStateMixin {
// Dependencies
final sessionController = Get.put(SessionController());
final dio = DioClient(withLog: false);
// UI Controllers
late TabController tabController;
// Observable State
final isOpenFindPerson = false.obs;
final family = <FamilyModel>[].obs;
final index = 0.obs;
final loading = false.obs;
final listTreeController = <TreeController>[].obs;
// Internal State
final scrollKey = GlobalKey();
int activeTreeId = 0;
int treeId = 0;
bool isRefresh = false;
// Find a tree by its ID
FamilyModel? getTreeById(int treeId) {
for (var data in family) {
if (data.tree.treeId == treeId) {
return data;
}
}
return null;
}
@override
void onInit() async {
// Initialize tab controller with zero length initially
tabController = TabController(
vsync: this,
length: 0,
);
// Check if we need to focus on a specific tree
if (Get.arguments != null && Get.arguments.containsKey('tree_id')) {
activeTreeId = Get.arguments['tree_id'];
}
// Fetch data to populate the trees
await fetchDataTree(refreshTab: true);
super.onInit();
}
// Pull-to-refresh handler
Future<void> onRefresh() async {
Get.put(LoadingWidget()).show();
await fetchDataTree();
Get.put(LoadingWidget()).close();
}
// Fake refresh for testing purposes
Future<void> onRefreshFake() async {
Get.put(LoadingWidget()).show();
Get.put(LoadingWidget()).close();
}
// Fetch tree data from API
Future<void> fetchDataTree({
bool refreshTab = true,
bool toLastFamily = false,
}) async {
try {
// If we're refreshing tabs, reset the tab controller
if (refreshTab == true) {
tabController = TabController(length: 0, vsync: this);
}
loading(true);
// Get authentication token
final prefs = await SharedPreferences.getInstance();
var token = prefs.getString(SharedPreferenceKey.token);
dio.baseOptions.headers['Authorization'] = 'Bearer $token';
// Clear existing data
family.clear();
// Fetch tree data from API
var response = await dio.requestGet(getTreePath, {});
var result = response!.data;
var json = List<Map<String, dynamic>>.from(result['data']);
// Process each family tree
List<TreeController> listTreeControllerTemp = [];
for (var a in json) {
// Create family model
FamilyModel temp = FamilyModel.fromJson(a);
family.add(temp);
// Create and configure a tree controller for this family
TreeController tempTreeController = Get.put(
TreeController(),
tag: temp.treeId.toString(),
);
// Initialize controller collections
List<ScrollController> listScrollFamily = [];
List<List<GlobalKey>> listKeyFamily = [];
List<GlobalKey> listKeyGeneration = [];
List<List<bool>> listChildBlink = [];
List<List<bool>> listSpouseBlink = [];
// Process each generation in the family
for (var j in temp.generations) {
List<GlobalKey> listKeyFamilyGeneration = [];
List<bool> childBlink = [];
List<bool> spouseBlink = [];
// Set up keys and blink states for each child
for (int k = 0; k < j.children.length; k++) {
listKeyFamilyGeneration.add(GlobalKey());
childBlink.add(false);
spouseBlink.add(false);
}
// Add collections to their respective controllers
listChildBlink.add(childBlink);
listSpouseBlink.add(spouseBlink);
listScrollFamily.add(ScrollController());
listKeyFamily.add(listKeyFamilyGeneration);
listKeyGeneration.add(GlobalKey());
}
// Assign collections to the tree controller
tempTreeController.listChildBlink.value = listChildBlink;
tempTreeController.listSpouseBlink.value = listSpouseBlink;
tempTreeController.listFamilyKeyGeneration.value = listKeyGeneration;
tempTreeController.listFamilyScrollGeneration.value = listScrollFamily;
tempTreeController.listFamilyKeyChild.value = listKeyFamily;
// Refresh controller state
tempTreeController.listFamilyScrollGeneration.refresh();
tempTreeController.listFamilyKeyChild.refresh();
// Add to the main list of tree controllers
listTreeControllerTemp.add(tempTreeController);
}
// Update the main list of tree controllers
listTreeController.value = listTreeControllerTemp;
listTreeController.refresh();
// Update tab controller if needed
if (refreshTab == true) {
tabController = TabController(
vsync: this,
length: family.length,
);
}
// Set up tab selection listener
tabController.addListener(() {
index.value = tabController.index;
});
// Set active tab based on tree ID if specified
for (var i = 0; i < family.length; i++) {
if (family[i].treeId == treeId) {
tabController.index = i;
index.value = i;
treeId = 0;
}
}
// Ensure tab index is set
tabController.index = index.value;
// Update UI state
loading(false);
family.refresh();
return;
} catch (e) {
// Handle errors silently
print("Error fetching tree data: $e");
}
return null;
}
// Remove tree data (for cleanup)
Future<void> removeTree({
bool refreshTab = true,
bool toLastFamily = false,
}) async {
try {
family.clear();
family.refresh();
print(family.length);
} catch (e) {
// Handle errors silently
}
return null;
}
// API call to unmerge photos for two persons
Future<void> postUnmergePhoto({
required int personId1,
required int personId2,
}) async {
// Prepare request parameters
var param = {
'person_id1': personId1,
'person_id2': personId2,
};
// Show loading indicator
Get.put(LoadingWidget()).show();
try {
// Get authentication token
final prefs = await SharedPreferences.getInstance();
var token = prefs.getString(SharedPreferenceKey.token);
// Make API request
var response = await dio.requestPost(
unmergePhoto,
param,
options: Options(
headers: {
'authorization': 'Bearer $token',
},
),
);
// Handle response
if (response == null) {
Get.back();
return null;
}
// Refresh data after successful unmerge
await fetchDataTree(refreshTab: false);
await Get.put(ProfileController()).loadData();
} catch (e) {
print("Error unmerging photos: $e");
} finally {
// Close loading indicator
Get.put(LoadingWidget()).close();
}
}
// Set active tree by ID
void setActiveTreeId(int treeId) {
int activeIndex = family.indexWhere((e) => e.treeId == treeId);
if (activeIndex >= 0) {
tabController.animateTo(activeIndex);
}
}
}
Editor is loading...
Leave a Comment