11import 'package:flutter/material.dart' ;
22import 'package:shared_preferences/shared_preferences.dart' ;
3- import 'package:vpn_client/design/dimensions.dart' ;
43import 'apps_list_item.dart' ;
4+ import 'package:vpn_client/l10n/app_localizations.dart' ;
55import 'dart:convert' ;
6+ import 'package:vpn_client/core/constants/storage_keys.dart' ; // Importar as constantes
67
78class AppsList extends StatefulWidget {
89 final Function (List <Map <String , dynamic >>)? onAppsLoaded;
@@ -17,32 +18,28 @@ class AppsList extends StatefulWidget {
1718class AppsListState extends State <AppsList > {
1819 List <Map <String , dynamic >> _apps = [];
1920 bool _isLoading = true ;
21+ bool _dataLoaded = false ; // Flag para controlar o carregamento inicial
2022
2123 @override
2224 void initState () {
2325 super .initState ();
2426 if (widget.apps != null && widget.apps! .isNotEmpty) {
2527 _apps = widget.apps! ;
2628 _isLoading = false ;
27- if (widget.onAppsLoaded != null ) {
28- widget.onAppsLoaded !(_apps);
29- }
30- } else {
31- _loadApps ();
29+ _dataLoaded =
30+ true ; // Marcar como carregado se dados iniciais foram fornecidos
31+ // widget.onAppsLoaded é chamado em didUpdateWidget ou após _loadApps
3232 }
3333 }
3434
3535 late String textallapps;
36- bool _initialized = false ;
37-
3836 @override
3937 void didChangeDependencies () {
4038 super .didChangeDependencies ();
41- if (! _initialized ) {
42- final statusText = CustomString (context);
43- textallapps = statusText.allapp ;
39+ if (! _dataLoaded ) {
40+ // Carregar apenas se os dados não foram carregados via widget.apps ou anteriormente
41+ textallapps = AppLocalizations . of (context) ! .all_apps ;
4442 _loadApps ();
45- _initialized = true ;
4643 }
4744 }
4845
@@ -53,22 +50,41 @@ class AppsListState extends State<AppsList> {
5350 setState (() {
5451 _apps = widget.apps! ;
5552 _isLoading = false ;
53+ _dataLoaded = true ;
5654 });
5755 _saveSelectedApps ();
5856 }
5957 }
6058
6159 Future <void > _loadApps () async {
6260 setState (() {
63- _isLoading = true ;
61+ // Evitar mostrar loading se já estiver carregando ou já carregou
62+ if (! _dataLoaded) _isLoading = true ;
6463 });
6564
65+ // Simulação de carregamento
66+ // Em um app real, aqui viria a lógica de buscar dados de uma API ou DB
67+ await Future .delayed (const Duration (milliseconds: 100 )); // Simular delay
68+
69+ // Definir textallapps aqui se ainda não foi definido em didChangeDependencies
70+ // Isso é um fallback, idealmente textallapps já está disponível.
71+ // Adicionando verificação de 'mounted' para o BuildContext
72+ if (! mounted) return ;
73+ final localizations = AppLocalizations .of (context);
74+ textallapps = localizations? .all_apps ?? "All Applications" ;
75+
6676 try {
77+ // Se os dados já foram carregados (ex: por uma busca anterior que atualizou widget.apps), não recarregar do zero
78+ if (_dataLoaded && _apps.isNotEmpty) {
79+ setState (() => _isLoading = false );
80+ return ;
81+ }
82+
6783 List <Map <String , dynamic >> appsList = [
6884 {
6985 'icon' : null ,
7086 'image' : null ,
71- 'text' : textallapps,
87+ 'text' : textallapps, // Usar a string localizada
7288 'isSwitch' : true ,
7389 'isActive' : false ,
7490 },
@@ -106,7 +122,7 @@ class AppsListState extends State<AppsList> {
106122 ]);
107123
108124 final prefs = await SharedPreferences .getInstance ();
109- final String ? savedApps = prefs.getString ('selected_apps' );
125+ final String ? savedApps = prefs.getString (StorageKeys .selectedApps );
110126 if (savedApps != null ) {
111127 final List <dynamic > savedAppsList = jsonDecode (savedApps);
112128 for (var savedApp in savedAppsList) {
@@ -122,6 +138,7 @@ class AppsListState extends State<AppsList> {
122138 setState (() {
123139 _apps = appsList;
124140 _isLoading = false ;
141+ _dataLoaded = true ; // Marcar que os dados foram carregados
125142 });
126143
127144 if (widget.onAppsLoaded != null ) {
@@ -130,6 +147,7 @@ class AppsListState extends State<AppsList> {
130147 } catch (e) {
131148 setState (() {
132149 _isLoading = false ;
150+ _dataLoaded = true ; // Marcar como tentado carregar para evitar loop
133151 });
134152 debugPrint ('Error loading apps: $e ' );
135153 }
@@ -141,7 +159,7 @@ class AppsListState extends State<AppsList> {
141159 _apps
142160 .map ((app) => {'text' : app['text' ], 'isActive' : app['isActive' ]})
143161 .toList ();
144- await prefs.setString ('selected_apps' , jsonEncode (selectedApps));
162+ await prefs.setString (StorageKeys .selectedApps , jsonEncode (selectedApps));
145163 }
146164
147165 List <Map <String , dynamic >> get apps => _apps;
@@ -150,14 +168,19 @@ class AppsListState extends State<AppsList> {
150168 setState (() {
151169 if (index == 0 && _apps[index]['isSwitch' ]) {
152170 _apps[0 ]['isActive' ] = ! _apps[0 ]['isActive' ];
171+ // Se "Todos os aplicativos" for ativado, desabilitar os outros itens da lista (visual)
172+ // A lógica de 'isEnabled' no AppListItem já cuida disso visualmente.
173+ // Aqui, garantimos que os outros não estejam 'isActive' se "Todos" estiver ativo.
153174 if (_apps[0 ]['isActive' ]) {
154175 for (int i = 1 ; i < _apps.length; i++ ) {
155- _apps[i]['isEnabled' ] = false ;
176+ _apps[i]['isActive' ] =
177+ false ; // Desmarcar outros se "Todos" for selecionado
156178 }
157179 }
158180 } else {
159181 _apps[index]['isActive' ] = ! _apps[index]['isActive' ];
160- if (_apps[index]['isActive' ]) {
182+ // Se um app individual for ativado, "Todos os aplicativos" deve ser desativado
183+ if (_apps[index]['isActive' ] && index != 0 ) {
161184 _apps[0 ]['isActive' ] = false ;
162185 }
163186 }
@@ -170,6 +193,18 @@ class AppsListState extends State<AppsList> {
170193
171194 @override
172195 Widget build (BuildContext context) {
196+ // Garante que textallapps seja inicializado se didChangeDependencies não for chamado a tempo
197+ // ou se o widget for reconstruído antes.
198+ textallapps = AppLocalizations .of (context)? .all_apps ?? "All Applications" ;
199+
200+ // Atualiza o texto do primeiro item se ele ainda não estiver com o texto localizado
201+ // Isso pode acontecer se _loadApps for chamado antes de textallapps ser definido por didChangeDependencies
202+ if (_apps.isNotEmpty &&
203+ _apps[0 ]['text' ] != textallapps &&
204+ _apps[0 ]['isSwitch' ] == true ) {
205+ _apps[0 ]['text' ] = textallapps;
206+ }
207+
173208 return Container (
174209 width: MediaQuery .of (context).size.width,
175210 height: MediaQuery .of (context).size.height,
@@ -191,7 +226,9 @@ class AppsListState extends State<AppsList> {
191226 text: _apps[index]['text' ],
192227 isSwitch: _apps[index]['isSwitch' ],
193228 isActive: _apps[index]['isActive' ],
194- isEnabled: index == 0 || ! _apps[0 ]['isActive' ],
229+ isEnabled:
230+ index == 0 ||
231+ ! _apps[0 ]['isActive' ], // Item é habilitado se for o switch "Todos" ou se "Todos" não estiver ativo
195232 onTap: () => _onItemTapped (index),
196233 );
197234 }),
0 commit comments