From 357fb4c519e94104cd8776812439064b1a261e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20L?= Date: Wed, 20 Nov 2024 21:27:21 -0300 Subject: [PATCH 01/24] feat: Top Navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Se agrega Top Navigation con un condicional para saber si es una screen principal o secundaria - Si isMainScreen = true se agrega la imagen del perfil y los (⁝) - Si isMainScreen = false se agrega la flecha atrás para hacer pop() - Se elimina el espacio debajo del statusBar de Android (no fué testeado en iOS) - Se eliminan sombreados de algunas Cards --- lib/core/utils/theme.dart | 11 ++- lib/main.dart | 16 ++++ .../asignaturas/asignaturas_screen.dart | 83 +++++++++++-------- .../card_asignatura.dart | 1 + lib/screens/home/home_screen.dart | 80 +++++++++--------- lib/screens/profile/profile_screen.dart | 2 +- lib/screens/tasklist/task_list_screen.dart | 7 ++ lib/screens/widgets_screens.dart | 15 ++++ lib/widgets/navigation/bottom_navbar.dart | 11 +-- lib/widgets/navigation/top_navigation.dart | 49 +++++++---- 10 files changed, 176 insertions(+), 99 deletions(-) create mode 100644 lib/screens/widgets_screens.dart diff --git a/lib/core/utils/theme.dart b/lib/core/utils/theme.dart index 9d0b5d6..bd2d569 100644 --- a/lib/core/utils/theme.dart +++ b/lib/core/utils/theme.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:miutem/core/utils/style_text.dart'; @@ -64,6 +65,10 @@ class AppTheme { /// Tema de la barra superior appBarTheme: AppBarTheme.of(context).copyWith( backgroundColor: white, + systemOverlayStyle: SystemUiOverlayStyle.dark.copyWith( + statusBarColor: white, + statusBarIconBrightness: Brightness.dark, + ), actionsIconTheme: const IconThemeData( color: Color(0xFF333333), ), @@ -168,6 +173,10 @@ class AppTheme { /// Tema de la barra superior appBarTheme: AppBarTheme.of(context).copyWith( backgroundColor: const Color(0xFF1D1B20), + systemOverlayStyle: SystemUiOverlayStyle.light.copyWith( + statusBarColor: Colors.black, + statusBarIconBrightness: Brightness.light, + ), actionsIconTheme: const IconThemeData( color: Color(0xFFFAFAFA), ), @@ -179,8 +188,6 @@ class AppTheme { toolbarTextStyle: GoogleFonts.roboto( color: const Color(0xFFFAFAFA), fontSize: 20, - - fontWeight: FontWeight.w600, ), foregroundColor: const Color(0xFFFAFAFA), diff --git a/lib/main.dart b/lib/main.dart index e3aebd4..11f2872 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:miutem/core/models/preferencia.dart'; import 'package:miutem/core/services/service_manager.dart'; import 'package:miutem/core/utils/http/functions.dart'; @@ -6,6 +7,20 @@ import 'package:miutem/core/utils/theme.dart'; import 'package:miutem/widgets/navigation/bottom_navbar.dart'; void main() async { + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + // Oculta la barra de estado + statusBarIconBrightness: Brightness.dark, + ), + ); + + // Esto hace que la app se construya debajo del status bar + SystemChrome.setEnabledSystemUIMode( + SystemUiMode.edgeToEdge, + overlays: [SystemUiOverlay.top], + ); + WidgetsFlutterBinding.ensureInitialized(); await initServices(); runApp(const MiUTEMApp()); @@ -28,6 +43,7 @@ class _MiUTEMAppState extends State { @override Widget build(BuildContext context) => MaterialApp( + title: 'Mi UTEM', debugShowCheckedModeBanner: false, theme: AppTheme.getTheme(context), diff --git a/lib/screens/asignaturas/asignaturas_screen.dart b/lib/screens/asignaturas/asignaturas_screen.dart index 5797a6e..c99271a 100644 --- a/lib/screens/asignaturas/asignaturas_screen.dart +++ b/lib/screens/asignaturas/asignaturas_screen.dart @@ -19,53 +19,64 @@ class AsignaturasScreen extends StatefulWidget { } class _AsignaturasScreenState extends State { - Estudiante? estudiante; List? asignaturas; @override void initState() { super.initState(); - getStudentOrLogin(context: context).then((estudiante) => setState(() => this.estudiante = estudiante)); - Get.find().getAsignaturas().then((asignaturas) => setState(() => this.asignaturas = asignaturas), onError: (err) { + getStudentOrLogin(context: context) + .then((estudiante) => setState(() => this.estudiante = estudiante)); + Get.find() + .getAsignaturas() + .then((asignaturas) => setState(() => this.asignaturas = asignaturas), + onError: (err) { logger.e('Error al cargar asignaturas', error: err); }); } @override - Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.all(16), - child: RefreshIndicator( - onRefresh: () async { - setState(() { - this.estudiante = null; - this.asignaturas = null; - }); + Widget build(BuildContext context) => Scaffold( + appBar: TopNavigation( + estudiante: estudiante, + isMainScreen: true, + title: 'Asignaturas', + actions: const [], + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: RefreshIndicator( + onRefresh: () async { + setState(() { + this.estudiante = null; + this.asignaturas = null; + }); - final estudiante = await Get.find().login(forceRefresh: true); - final asignaturas = await Get.find().getAsignaturas(forceRefresh: true); - setState(() { - this.estudiante = estudiante; - this.asignaturas = asignaturas; - }); - }, - child: SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - clipBehavior: Clip.none, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TopNavigation(estudiante: estudiante), - const SizedBox(height: 20), - Text("Asignaturas", style: StyleText.headline), - const SizedBox(height: 20), - const AccesoRapido(), - const SizedBox(height: 20), - AsignaturasEnCurso(asignaturas: asignaturas), - ], + final estudiante = + await Get.find().login(forceRefresh: true); + final asignaturas = await Get.find() + .getAsignaturas(forceRefresh: true); + setState(() { + this.estudiante = estudiante; + this.asignaturas = asignaturas; + }); + }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + clipBehavior: Clip.none, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Text("Asignaturas", style: StyleText.headline), + const SizedBox(height: 20), + const AccesoRapido(), + const SizedBox(height: 20), + AsignaturasEnCurso(asignaturas: asignaturas), + ], + ), + ), + ), ), - ), - ), - ); + ); } - diff --git a/lib/screens/asignaturas/widgets/asignaturas_inscritas/card_asignatura.dart b/lib/screens/asignaturas/widgets/asignaturas_inscritas/card_asignatura.dart index dbe0622..c15a0f6 100644 --- a/lib/screens/asignaturas/widgets/asignaturas_inscritas/card_asignatura.dart +++ b/lib/screens/asignaturas/widgets/asignaturas_inscritas/card_asignatura.dart @@ -11,6 +11,7 @@ class CardAsignatura extends StatelessWidget { Widget build(BuildContext context) => GestureDetector( onTap: onTap, child: Card( + elevation: 0, color: Theme.of(context).scaffoldBackgroundColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart index 1b6af64..8dc685f 100644 --- a/lib/screens/home/home_screen.dart +++ b/lib/screens/home/home_screen.dart @@ -37,45 +37,47 @@ class _HomeScreenState extends State { } @override - Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.all(16), - child: RefreshIndicator( - onRefresh: () async { - setState(() { - this.estudiante = null; - bloques = null; - }); - await HttpClient.clearCache(); - final estudiante = await Get.find().login(forceRefresh: true); - await _cargarHorario(forceRefresh: true); - setState(() => this.estudiante = estudiante); - }, - child: SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - clipBehavior: Clip.none, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TopNavigation(estudiante: estudiante), - const SizedBox(height: 20), - Saludo(estudiante: estudiante), - const SizedBox(height: 20), - const AccesoRapido(), - const SizedBox(height: 20), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text("Clases de Hoy", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), - Text(getToday(), style: const TextStyle(fontSize: 12, fontWeight: FontWeight.normal)), - ], - ), - const SizedBox(height: 10), - ListaClases(error: errorAlCargarHorario, bloques: bloques, onRefresh: () => _cargarHorario(forceRefresh: true)), - ], - ), - ], + Widget build(BuildContext context) => Scaffold( + appBar: TopNavigation(estudiante: estudiante, isMainScreen: true, title: 'Inicio', actions: const []), + body: Padding( + padding: const EdgeInsets.all(16), + child: RefreshIndicator( + onRefresh: () async { + setState(() { + this.estudiante = null; + bloques = null; + }); + await HttpClient.clearCache(); + final estudiante = await Get.find().login(forceRefresh: true); + await _cargarHorario(forceRefresh: true); + setState(() => this.estudiante = estudiante); + }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + clipBehavior: Clip.none, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Saludo(estudiante: estudiante), + const SizedBox(height: 20), + const AccesoRapido(), + const SizedBox(height: 20), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text("Clases de Hoy", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + Text(getToday(), style: const TextStyle(fontSize: 12, fontWeight: FontWeight.normal)), + ], + ), + const SizedBox(height: 10), + ListaClases(error: errorAlCargarHorario, bloques: bloques, onRefresh: () => _cargarHorario(forceRefresh: true)), + ], + ), + ], + ), ), ), ), diff --git a/lib/screens/profile/profile_screen.dart b/lib/screens/profile/profile_screen.dart index 81c2732..c81d3ef 100644 --- a/lib/screens/profile/profile_screen.dart +++ b/lib/screens/profile/profile_screen.dart @@ -24,7 +24,7 @@ class _ProfileScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - TopNavigation(estudiante: estudiante), + TopNavigation(title: "Perfil", estudiante: estudiante, isMainScreen: true, actions: [],), const SizedBox(height: 20), const SizedBox(height: 20), const SizedBox(height: 20), diff --git a/lib/screens/tasklist/task_list_screen.dart b/lib/screens/tasklist/task_list_screen.dart index afe4c9b..cb97085 100644 --- a/lib/screens/tasklist/task_list_screen.dart +++ b/lib/screens/tasklist/task_list_screen.dart @@ -5,6 +5,8 @@ import 'package:miutem/core/repositories/tasks_repository.dart'; import 'package:miutem/screens/tasklist/actions/add_task_action.dart'; import 'package:miutem/screens/tasklist/actions/refresh_tasks_action.dart'; import 'package:miutem/screens/tasklist/widgets/task_card.dart'; +import 'package:miutem/widgets/icons.dart'; +import 'package:miutem/widgets/navigation/top_navigation.dart'; import 'package:skeletonizer/skeletonizer.dart'; class TaskListScreen extends StatefulWidget { @@ -38,6 +40,11 @@ class _TaskListScreenState extends State { @override Widget build(BuildContext context) => Scaffold( + appBar: const TopNavigation( + title: 'Apuntes', + isMainScreen: true, + actions: [], + ), body: SafeArea(child: Column( children: [ Expanded( diff --git a/lib/screens/widgets_screens.dart b/lib/screens/widgets_screens.dart new file mode 100644 index 0000000..ef703eb --- /dev/null +++ b/lib/screens/widgets_screens.dart @@ -0,0 +1,15 @@ +/* Aquí se exportan las screens y widgets importantes para la navegación del sistema */ +// HOME +export 'home/home_screen.dart'; + +// ASIGNATURAS +export 'asignaturas/asignaturas_screen.dart'; + +// APUNTES +export 'tasklist/task_list_screen.dart'; + +// PERFIL +export 'profile/profile-idea.dart'; + +// NOTAS +export 'notas/notas_screen.dart'; diff --git a/lib/widgets/navigation/bottom_navbar.dart b/lib/widgets/navigation/bottom_navbar.dart index 79aea69..239d10f 100644 --- a/lib/widgets/navigation/bottom_navbar.dart +++ b/lib/widgets/navigation/bottom_navbar.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:miutem/core/models/navigation/navigation_item.dart'; -import 'package:miutem/screens/asignaturas/asignaturas_screen.dart'; -import 'package:miutem/screens/home/home_screen.dart'; -import 'package:miutem/screens/profile/profile-idea.dart'; import 'package:miutem/widgets/icons.dart'; +import 'package:miutem/screens/widgets_screens.dart'; class BottomNavBar extends StatefulWidget { const BottomNavBar({super.key}); @@ -18,7 +16,7 @@ class _BottomNavBarState extends State { final List screens = [ NavigationItem(destination: const HomeScreen(), label: "Inicio", icon: AppIcons.home), NavigationItem(destination: const AsignaturasScreen(), label: "Asignaturas", icon: AppIcons.subjects), - NavigationItem(destination: const HomeScreen(), label: "Apuntes", icon: AppIcons.notes), + NavigationItem(destination: const TaskListScreen(), label: "Apuntes", icon: AppIcons.notes), NavigationItem(destination: const ProfileScreen(), label: "Perfil", icon: AppIcons.profile), ]; @@ -33,7 +31,6 @@ class _BottomNavBarState extends State { label: e.label, )).toList(), ), - body: SafeArea(child: screens[idx].destination), + body: screens[idx].destination, ); -} - +} \ No newline at end of file diff --git a/lib/widgets/navigation/top_navigation.dart b/lib/widgets/navigation/top_navigation.dart index 656f268..9ba42c7 100644 --- a/lib/widgets/navigation/top_navigation.dart +++ b/lib/widgets/navigation/top_navigation.dart @@ -5,23 +5,44 @@ import 'package:miutem/core/models/user/estudiante.dart'; import 'package:miutem/core/utils/utils.dart'; import 'package:miutem/widgets/icons.dart'; import 'package:skeletonizer/skeletonizer.dart'; +import 'package:flutter/services.dart'; -class TopNavigation extends StatelessWidget { +class TopNavigation extends StatelessWidget implements PreferredSizeWidget { + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); final Estudiante? estudiante; - - const TopNavigation({super.key, required this.estudiante}); + final bool isMainScreen; + final String title; + const TopNavigation({super.key, this.estudiante, required this.isMainScreen, required this.title, required List actions}); @override - Widget build(BuildContext context) => Row( - children: [ - let(estudiante?.fotoUrl, (String fotoUrl) => CircleAvatar( - radius: 25, - foregroundImage: - MemoryImage(base64Decode(fotoUrl)), - )) ?? const Skeleton.keep(child: CircleAvatar(child: Icon(AppIcons.profile, fill: 1, size: 40))), - const Spacer(), - Skeleton.keep(child: IconButton(onPressed: (){}, icon: const Icon(AppIcons.more,weight: 900,))), - ], - ); + Widget build(BuildContext context) { + return AppBar( + backgroundColor: Theme.of(context).appBarTheme.backgroundColor, + systemOverlayStyle: SystemUiOverlayStyle( + statusBarColor: Theme.of(context).appBarTheme.backgroundColor, + statusBarIconBrightness: Theme.of(context).brightness == Brightness.dark ? Brightness.light : Brightness.dark, + ), + leading: Padding( + padding: const EdgeInsets.all(8.0), + child: isMainScreen + ? let(estudiante?.fotoUrl, (String fotoUrl) => CircleAvatar( + radius: 25, + foregroundImage: MemoryImage(base64Decode(fotoUrl)), + )) ?? const Skeleton.keep(child: CircleAvatar(child: Icon(AppIcons.profile, fill: 1, size: 40))) + : const BackButton(), + ), + title: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text(title), + ), + actions: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Skeleton.keep(child: IconButton(onPressed: (){}, icon: const Icon(AppIcons.more, weight: 900,))), + ), + ], + ); + } } From 4db7445492afac627bc876ac4e53dc4b45574c2b Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:49:46 -0300 Subject: [PATCH 02/24] patch: merge desde dev --- lib/main.dart | 1 - lib/screens/tasklist/task_list_screen.dart | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 11f2872..2a83580 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -43,7 +43,6 @@ class _MiUTEMAppState extends State { @override Widget build(BuildContext context) => MaterialApp( - title: 'Mi UTEM', debugShowCheckedModeBanner: false, theme: AppTheme.getTheme(context), diff --git a/lib/screens/tasklist/task_list_screen.dart b/lib/screens/tasklist/task_list_screen.dart index cb97085..31cbcbf 100644 --- a/lib/screens/tasklist/task_list_screen.dart +++ b/lib/screens/tasklist/task_list_screen.dart @@ -1,11 +1,10 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:miutem/core/models/tasklist.dart'; import 'package:miutem/core/repositories/tasks_repository.dart'; import 'package:miutem/screens/tasklist/actions/add_task_action.dart'; import 'package:miutem/screens/tasklist/actions/refresh_tasks_action.dart'; +import 'package:miutem/screens/tasklist/models/task_model.dart'; import 'package:miutem/screens/tasklist/widgets/task_card.dart'; -import 'package:miutem/widgets/icons.dart'; import 'package:miutem/widgets/navigation/top_navigation.dart'; import 'package:skeletonizer/skeletonizer.dart'; @@ -19,7 +18,7 @@ class TaskListScreen extends StatefulWidget { class _TaskListScreenState extends State { bool loading = false; - List _taskLists = []; + List _taskLists = []; @override void initState(){ From 2f4429c176062f56126fd3685f2cc5b1c41d80c2 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:13:24 -0400 Subject: [PATCH 03/24] feat: implement asignatura screen with horario and notas functionality --- ios/Podfile | 2 +- ios/Podfile.lock | 256 ++++++++-------- lib/core/utils/theme.dart | 226 -------------- .../{widgets => }/actions/acceso_rapido.dart | 0 .../asignaturas/asignaturas_screen.dart | 82 ------ .../actions/cargar_notas_asignatura.dart | 8 + .../detalle_asignatura/asignatura_screen.dart | 68 +++++ .../models/horario_bloque.dart | 15 + .../widgets/card_horario.dart | 117 ++++++++ .../detalle_asignatura/widgets/promedio.dart | 107 +++++++ .../widgets/seccion_horario.dart | 90 ++++++ .../asignaturas/lista_asignaturas_screen.dart | 81 +++++ .../asignaturas/widgets/acceso_rapido.dart | 2 +- .../lista_asignaturas.dart | 2 + .../auth/login/widgets/login_form.dart | 6 +- .../auth/login/widgets/login_form_fields.dart | 2 + .../widgets/components/bloque_ramo_card.dart | 2 +- lib/screens/notas/notas_screen.dart | 49 +++- lib/screens/profile/profile_screen.dart | 2 +- .../profile/widgets/profile_settings.dart | 13 +- lib/screens/widgets_screens.dart | 2 +- lib/styles/navigation/bottom_navbar.dart | 4 +- lib/styles/theme/theme.dart | 6 +- lib/widgets/navigation/top_navigation.dart | 48 --- .../flutter_secure_storage_linux | 2 +- .../.plugin_symlinks/package_info_plus | 2 +- .../ephemeral/.plugin_symlinks/share_plus | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 4 +- .../ephemeral/Flutter-Generated.xcconfig | 2 +- .../ephemeral/flutter_export_environment.sh | 2 +- macos/Podfile | 4 +- macos/Podfile.lock | 256 ++++++++-------- pubspec.lock | 276 +++++++++--------- pubspec.yaml | 8 +- 34 files changed, 965 insertions(+), 783 deletions(-) delete mode 100644 lib/core/utils/theme.dart rename lib/screens/asignaturas/{widgets => }/actions/acceso_rapido.dart (100%) delete mode 100644 lib/screens/asignaturas/asignaturas_screen.dart create mode 100644 lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart create mode 100644 lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart create mode 100644 lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart create mode 100644 lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart create mode 100644 lib/screens/asignaturas/detalle_asignatura/widgets/promedio.dart create mode 100644 lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart create mode 100644 lib/screens/asignaturas/lista_asignaturas_screen.dart delete mode 100644 lib/widgets/navigation/top_navigation.dart diff --git a/ios/Podfile b/ios/Podfile index 74c3caa..8295bd3 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -33,7 +33,7 @@ target 'Runner' do pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', - :tag => '11.4.0' + :tag => '11.15.0' flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1a36c73..8d26435 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -4,150 +4,156 @@ PODS: - IosAwnCore (~> 0.10.0) - awesome_notifications_core (0.0.1): - Flutter - - cloud_firestore (5.6.0): - - Firebase/Firestore (= 11.4.0) + - cloud_firestore (5.6.12): + - Firebase/Firestore (= 11.15.0) - firebase_core - Flutter - file_saver (0.0.1): - Flutter - - Firebase/Analytics (11.4.0): + - Firebase/Analytics (11.15.0): - Firebase/Core - - Firebase/Core (11.4.0): + - Firebase/Core (11.15.0): - Firebase/CoreOnly - - FirebaseAnalytics (~> 11.4.0) - - Firebase/CoreOnly (11.4.0): - - FirebaseCore (= 11.4.0) - - Firebase/Firestore (11.4.0): + - FirebaseAnalytics (~> 11.15.0) + - Firebase/CoreOnly (11.15.0): + - FirebaseCore (~> 11.15.0) + - Firebase/Firestore (11.15.0): - Firebase/CoreOnly - - FirebaseFirestore (~> 11.4.0) - - Firebase/RemoteConfig (11.4.0): + - FirebaseFirestore (~> 11.15.0) + - Firebase/RemoteConfig (11.15.0): - Firebase/CoreOnly - - FirebaseRemoteConfig (~> 11.4.0) - - firebase_analytics (11.3.6): - - Firebase/Analytics (= 11.4.0) + - FirebaseRemoteConfig (~> 11.15.0) + - firebase_analytics (11.6.0): + - Firebase/Analytics (= 11.15.0) - firebase_core - Flutter - - firebase_core (3.9.0): - - Firebase/CoreOnly (= 11.4.0) + - firebase_core (3.15.2): + - Firebase/CoreOnly (= 11.15.0) - Flutter - - firebase_remote_config (5.2.0): - - Firebase/RemoteConfig (= 11.4.0) + - firebase_remote_config (5.5.0): + - Firebase/RemoteConfig (= 11.15.0) - firebase_core - Flutter - - FirebaseABTesting (11.4.0): - - FirebaseCore (~> 11.0) - - FirebaseAnalytics (11.4.0): - - FirebaseAnalytics/AdIdSupport (= 11.4.0) - - FirebaseCore (~> 11.0) + - FirebaseABTesting (11.15.0): + - FirebaseCore (~> 11.15.0) + - FirebaseAnalytics (11.15.0): + - FirebaseAnalytics/Default (= 11.15.0) + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseAnalytics/AdIdSupport (11.4.0): - - FirebaseCore (~> 11.0) + - FirebaseAnalytics/Default (11.15.0): + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - - GoogleAppMeasurement (= 11.4.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/Default (= 11.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseCore (11.4.0): - - FirebaseCoreInternal (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Logger (~> 8.0) - - FirebaseCoreExtension (11.4.0): - - FirebaseCore (~> 11.0) - - FirebaseCoreInternal (11.4.2): - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FirebaseFirestore (11.4.0): - - FirebaseFirestoreBinary (= 11.4.0) - - FirebaseFirestoreAbseilBinary (1.2024011602.0) - - FirebaseFirestoreBinary (11.4.0): - - FirebaseCore (= 11.4.0) - - FirebaseCoreExtension (= 11.4.0) - - FirebaseFirestoreInternalBinary (= 11.4.0) - - FirebaseSharedSwift (= 11.4.0) - - FirebaseFirestoreGRPCBoringSSLBinary (1.65.1) - - FirebaseFirestoreGRPCCoreBinary (1.65.1): - - FirebaseFirestoreAbseilBinary (= 1.2024011602.0) - - FirebaseFirestoreGRPCBoringSSLBinary (= 1.65.1) - - FirebaseFirestoreGRPCCPPBinary (1.65.1): - - FirebaseFirestoreAbseilBinary (= 1.2024011602.0) - - FirebaseFirestoreGRPCCoreBinary (= 1.65.1) - - FirebaseFirestoreInternalBinary (11.4.0): - - FirebaseCore (= 11.4.0) - - FirebaseFirestoreAbseilBinary (= 1.2024011602.0) - - FirebaseFirestoreGRPCCPPBinary (= 1.65.1) + - FirebaseCore (11.15.0): + - FirebaseCoreInternal (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/Logger (~> 8.1) + - FirebaseCoreExtension (11.15.0): + - FirebaseCore (~> 11.15.0) + - FirebaseCoreInternal (11.15.0): + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - FirebaseFirestore (11.15.0): + - FirebaseFirestoreBinary (= 11.15.0) + - FirebaseFirestoreAbseilBinary (1.2024072200.0) + - FirebaseFirestoreBinary (11.15.0): + - FirebaseCore (= 11.15.0) + - FirebaseCoreExtension (= 11.15.0) + - FirebaseFirestoreInternalBinary (= 11.15.0) + - FirebaseSharedSwift (= 11.15.0) + - FirebaseFirestoreGRPCBoringSSLBinary (1.69.0) + - FirebaseFirestoreGRPCCoreBinary (1.69.0): + - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) + - FirebaseFirestoreGRPCBoringSSLBinary (= 1.69.0) + - FirebaseFirestoreGRPCCPPBinary (1.69.0): + - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) + - FirebaseFirestoreGRPCCoreBinary (= 1.69.0) + - FirebaseFirestoreInternalBinary (11.15.0): + - FirebaseCore (= 11.15.0) + - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) + - FirebaseFirestoreGRPCCPPBinary (= 1.69.0) - leveldb-library (~> 1.22) - nanopb (~> 3.30910.0) - - FirebaseInstallations (11.4.0): - - FirebaseCore (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) + - FirebaseInstallations (11.15.0): + - FirebaseCore (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseRemoteConfig (11.4.0): + - FirebaseRemoteConfig (11.15.0): - FirebaseABTesting (~> 11.0) - - FirebaseCore (~> 11.0) + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - FirebaseRemoteConfigInterop (~> 11.0) - FirebaseSharedSwift (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FirebaseRemoteConfigInterop (11.5.0) - - FirebaseSharedSwift (11.4.0) + - GoogleUtilities/Environment (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - FirebaseRemoteConfigInterop (11.15.0) + - FirebaseSharedSwift (11.15.0) - Flutter (1.0.0) - flutter_native_splash (2.4.3): - Flutter - flutter_secure_storage (6.0.0): - Flutter - - GoogleAppMeasurement (11.4.0): - - GoogleAppMeasurement/AdIdSupport (= 11.4.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAdsOnDeviceConversion (2.1.0): + - GoogleUtilities/Logger (~> 8.1) + - GoogleUtilities/Network (~> 8.1) - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/AdIdSupport (11.4.0): - - GoogleAppMeasurement/WithoutAdIdSupport (= 11.4.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/Core (11.15.0): + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/WithoutAdIdSupport (11.4.0): - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/Default (11.15.0): + - GoogleAdsOnDeviceConversion (= 2.1.0) + - GoogleAppMeasurement/Core (= 11.15.0) + - GoogleAppMeasurement/IdentitySupport (= 11.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleUtilities/AppDelegateSwizzler (8.0.2): + - GoogleAppMeasurement/IdentitySupport (11.15.0): + - GoogleAppMeasurement/Core (= 11.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - nanopb (~> 3.30910.0) + - GoogleUtilities/AppDelegateSwizzler (8.1.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - GoogleUtilities/Privacy - - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Environment (8.1.0): - GoogleUtilities/Privacy - - GoogleUtilities/Logger (8.0.2): + - GoogleUtilities/Logger (8.1.0): - GoogleUtilities/Environment - GoogleUtilities/Privacy - - GoogleUtilities/MethodSwizzler (8.0.2): + - GoogleUtilities/MethodSwizzler (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GoogleUtilities/Network (8.0.2): + - GoogleUtilities/Network (8.1.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Privacy - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (8.0.2)": + - "GoogleUtilities/NSData+zlib (8.1.0)": - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (8.0.2) - - GoogleUtilities/Reachability (8.0.2): + - GoogleUtilities/Privacy (8.1.0) + - GoogleUtilities/Reachability (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (8.0.2): + - GoogleUtilities/UserDefaults (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - IosAwnCore (0.10.0) @@ -185,7 +191,7 @@ DEPENDENCIES: - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`) - - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `11.4.0`) + - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `11.15.0`) - Flutter (from `Flutter`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) @@ -215,6 +221,7 @@ SPEC REPOS: - FirebaseRemoteConfig - FirebaseRemoteConfigInterop - FirebaseSharedSwift + - GoogleAdsOnDeviceConversion - GoogleAppMeasurement - GoogleUtilities - IosAwnCore @@ -239,7 +246,7 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_remote_config/ios" FirebaseFirestore: :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.4.0 + :tag: 11.15.0 Flutter: :path: Flutter flutter_native_splash: @@ -264,38 +271,39 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: FirebaseFirestore: :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.4.0 + :tag: 11.15.0 SPEC CHECKSUMS: awesome_notifications: dd5518ff1c80be03d4f1c40f04da9d9cc2a37af5 awesome_notifications_core: d02eed89738fa362d56cbd372850e9adcd2c6bef - cloud_firestore: 56bca083ecf07f16188ace1d5b57123bcb1b3465 + cloud_firestore: 97e42181866db3cba3fe3935895ab779b6acacd6 file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 - Firebase: cf1b19f21410b029b6786a54e9764a0cacad3c99 - firebase_analytics: 2815af29d49c1a994652abd37a5b001a88bc7b75 - firebase_core: b62a5080210edad3f2934314a8b2c6f5124e8e10 - firebase_remote_config: 015a36be218a38943c2273d63b33bc983b3d7bb6 - FirebaseABTesting: aef1719704fade00b200827e7973f352efc4caee - FirebaseAnalytics: 3feef9ae8733c567866342a1000691baaa7cad49 - FirebaseCore: e0510f1523bc0eb21653cac00792e1e2bd6f1771 - FirebaseCoreExtension: 4445e4cd877e0790c4af33bedca61eaef27b7513 - FirebaseCoreInternal: 35731192cab10797b88411be84940d2beb33a238 - FirebaseFirestore: 97f18b411aaca686a9e94ba742341228643b1a46 - FirebaseFirestoreAbseilBinary: fa2ebd2ed02cadef5382e4f7c93f1b265c812c85 - FirebaseFirestoreBinary: d0380b879b58d663b22467017d0e348d5b17b36b - FirebaseFirestoreGRPCBoringSSLBinary: d86ebbe2adc8d15d7ebf305fff7d6358385327f8 - FirebaseFirestoreGRPCCoreBinary: 472bd808e1886a5efb2fd03dd09b98d34641a335 - FirebaseFirestoreGRPCCPPBinary: db76d83d2b7517623f8426ed7f7a17bad2478084 - FirebaseFirestoreInternalBinary: 01c33a6d789b95dce32dbdfcaf30d60ddf8902d8 - FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 - FirebaseRemoteConfig: 7655681d02417bc9b287338edb9d721ff79e1a4a - FirebaseRemoteConfigInterop: 7a7aebb9342d53913a5c890efa88e289d9e5c1bc - FirebaseSharedSwift: 505dae2d05969dbf6d43749a642bb1bf230f0252 + Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e + firebase_analytics: bf93e20703c95030404d6ddbb1adf05bf5c3885b + firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c + firebase_remote_config: 395d35aa770405fd0121c97382671371ea00734a + FirebaseABTesting: 5e9d432834aebf27ab72100d37af44dfbe8d82f7 + FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae + FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e + FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435 + FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 + FirebaseFirestore: 736c2099af30aed7728d5789059fee1914b4d213 + FirebaseFirestoreAbseilBinary: 4cfa8823cedc1b774843e04fe578ad279b387f97 + FirebaseFirestoreBinary: 43abe19da1cb39a10171786e5a2e18fa9d57b6af + FirebaseFirestoreGRPCBoringSSLBinary: c3dfef3ff448ae2c1c85f9baf9fac5afc4db99fa + FirebaseFirestoreGRPCCoreBinary: 565534e160a0415d12185f7f171c52a567382fbd + FirebaseFirestoreGRPCCPPBinary: 6c0134e8d230ee58b9d51dec2a30a48efd6d5dc7 + FirebaseFirestoreInternalBinary: ea89c368772c8fa4c9550a464b36c25796f6182c + FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 + FirebaseRemoteConfig: b496646b82855e174a7f1e354c65e0e913085168 + FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa + FirebaseSharedSwift: e17c654ef1f1a616b0b33054e663ad1035c8fd40 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a + flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 - GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e - GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d + GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64 + GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 + GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 IosAwnCore: 653786a911089012092ce831f2945cd339855a89 leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 @@ -308,6 +316,6 @@ SPEC CHECKSUMS: url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 -PODFILE CHECKSUM: 8772d4b5866a97bb5a903186d29a2772b40e01c0 +PODFILE CHECKSUM: 314cb596080ef1b32fcb9923d3afff0f310a59c1 COCOAPODS: 1.16.2 diff --git a/lib/core/utils/theme.dart b/lib/core/utils/theme.dart deleted file mode 100644 index 82a0ff3..0000000 --- a/lib/core/utils/theme.dart +++ /dev/null @@ -1,226 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:miutem/core/utils/style_text.dart'; - -class AppTheme { - - static Color get white => const Color(0xFFFAFAFA); - static Color get black => const Color(0xFF333333); - - static Color get lightGrey => const Color(0xFFBBBBBB); - static Color get darkLightGrey => const Color(0xFF474747); - - static Color get lightBlueCard => const Color(0xFFB8E8FC); - static Color get darkBlueCard => const Color(0xFF005C82); - - static Color get lightPurpleCard => const Color(0xFFDFCCFB); - static Color get darkPurpleCard => const Color(0xFF692083); - - static Color get lightYellowCard => const Color(0xFFFCF7BB); - static Color get darkYellowCard => const Color(0xFF6D660A); - - static Color get lightSalmonCard => const Color(0xFFFFBDBD); - static Color get darkSalmonCard => const Color(0xFF8C3A3A); - - static Color get lightGreenCard => const Color(0xFFB3E6CC); - static Color get darkGreenCard => const Color(0xFF0A693C); - - /// themes horario - static const Color mediumGrey = Color(0xFFBDBDBD); - static const Color greyligth = Color(0xfff1f1f1); - static const Color grey = Color(0xff7f7f7f); - static const Color dividerColor = mediumGrey; - - static ColorScheme get colorScheme => ColorScheme.fromSeed( - seedColor: const Color(0xFF1D8E5C), - primary: const Color(0xFF1D8E5C), - secondary: const Color(0xFF06607A), - ); - - static ThemeData getTheme(BuildContext context) => ThemeData.light().copyWith( - /// Esquema de colores - colorScheme: colorScheme, - canvasColor: colorScheme.surface, - dividerColor: lightGrey, - - /// Tema de texto - textTheme: GoogleFonts.robotoTextTheme(Theme.of(context).textTheme).copyWith( - headlineMedium: GoogleFonts.inter(textStyle: const TextStyle( - fontSize: 30, - fontWeight: FontWeight.w900, - letterSpacing: 0.01, - )), - titleLarge: GoogleFonts.inter(), - titleMedium: GoogleFonts.inter(), - titleSmall: GoogleFonts.inter(), - ).apply( - bodyColor: const Color(0xFF333333), - displayColor: const Color(0xFF333333), - ), - - /// Fondo de la aplicación - scaffoldBackgroundColor: const Color(0xFFFAFAFA), - - /// Tema de la barra de navegación - navigationBarTheme: NavigationBarTheme.of(context).copyWith( - backgroundColor: const Color(0xFFFFFFFF), - elevation: 0, - ), - - /// Tema de la barra superior - appBarTheme: AppBarTheme.of(context).copyWith( - backgroundColor: white, - systemOverlayStyle: SystemUiOverlayStyle.dark.copyWith( - statusBarColor: white, - statusBarIconBrightness: Brightness.dark, - ), - actionsIconTheme: const IconThemeData( - color: Color(0xFF333333), - ), - titleTextStyle: GoogleFonts.inter( - color: const Color(0xFF333333), - fontSize: 20, - fontWeight: FontWeight.w600, - ), - toolbarTextStyle: GoogleFonts.roboto( - color: const Color(0xFF333333), - fontSize: 20, - fontWeight: FontWeight.w600, - ), - foregroundColor: const Color(0xFF333333), - elevation: 0, - ), - - /// Tema de la decoración de los inputs - inputDecorationTheme: InputDecorationTheme( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: lightGrey), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: lightGrey), - ), - disabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: lightGrey), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: colorScheme.primary), - ), - fillColor: white, - hintStyle: StyleText.body.copyWith( - color: AppTheme.lightGrey, - ), - labelStyle: StyleText.body, - contentPadding: const EdgeInsets.symmetric(horizontal: 12), - ), - ); - - static ThemeData getThemeDark(BuildContext context) => ThemeData.dark().copyWith( - /// Esquema de colores - colorScheme: colorScheme.copyWith( - primary: const Color(0xFF009951) - ), - canvasColor: colorScheme.inverseSurface, - dividerColor: darkLightGrey, - - /// Tema de texto - textTheme: GoogleFonts.robotoTextTheme(Theme.of(context).textTheme.copyWith( - headlineMedium: GoogleFonts.inter(textStyle: const TextStyle( - fontSize: 30, - fontWeight: FontWeight.w900, - letterSpacing: 0.01, - )), - titleLarge: GoogleFonts.inter(), - titleMedium: GoogleFonts.inter(), - titleSmall: GoogleFonts.inter(), - ).apply( - bodyColor: const Color(0xFFFAFAFA), - displayColor: const Color(0xFFFAFAFA), - )), - - /// Fondo de la aplicación - scaffoldBackgroundColor: const Color(0xFF1D1B20), - - /// Tema de la barra de navegación - navigationBarTheme: NavigationBarTheme.of(context).copyWith( - backgroundColor: const Color(0xFF1E1E1E), - indicatorColor: const Color(0xFF1D8E5C).withOpacity(.9), - labelTextStyle: WidgetStateProperty.resolveWith((states) { - if(states.contains(WidgetState.selected)) { - return const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - ); - } - - return const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w400, - ); - }), - iconTheme: WidgetStateProperty.resolveWith((states) { - if(states.contains(WidgetState.selected)) { - return const IconThemeData( - color: Color(0xFFFAFAFA), - ); - } - - return const IconThemeData( - color: Color(0xFFFAFAFA), - ); - }), - elevation: 0, - ), - - /// Tema de la barra superior - appBarTheme: AppBarTheme.of(context).copyWith( - backgroundColor: const Color(0xFF1D1B20), - systemOverlayStyle: SystemUiOverlayStyle.light.copyWith( - statusBarColor: Colors.black, - statusBarIconBrightness: Brightness.light, - ), - actionsIconTheme: const IconThemeData( - color: Color(0xFFFAFAFA), - ), - titleTextStyle: GoogleFonts.inter( - color: const Color(0xFFFAFAFA), - fontSize: 20, - fontWeight: FontWeight.w600, - ), - toolbarTextStyle: GoogleFonts.roboto( - color: const Color(0xFFFAFAFA), - fontSize: 20, - fontWeight: FontWeight.w600, - ), - foregroundColor: const Color(0xFFFAFAFA), - elevation: 0, - ), - - /// Tema de la decoración de los inputs - inputDecorationTheme: InputDecorationTheme( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: darkLightGrey), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: darkLightGrey), - ), - disabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: darkLightGrey), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide(color: colorScheme.primary), - ), - fillColor: const Color(0xFF1D1B20), - hintStyle: StyleText.body.copyWith(color: AppTheme.lightGrey), - contentPadding: const EdgeInsets.symmetric(horizontal: 12), - ), - ); -} \ No newline at end of file diff --git a/lib/screens/asignaturas/widgets/actions/acceso_rapido.dart b/lib/screens/asignaturas/actions/acceso_rapido.dart similarity index 100% rename from lib/screens/asignaturas/widgets/actions/acceso_rapido.dart rename to lib/screens/asignaturas/actions/acceso_rapido.dart diff --git a/lib/screens/asignaturas/asignaturas_screen.dart b/lib/screens/asignaturas/asignaturas_screen.dart deleted file mode 100644 index 7c901fd..0000000 --- a/lib/screens/asignaturas/asignaturas_screen.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:miutem/core/models/asignaturas/asignatura.dart'; -import 'package:miutem/core/models/user/estudiante.dart'; -import 'package:miutem/core/services/asignaturas_service.dart'; -import 'package:miutem/core/services/auth_service.dart'; -import 'package:miutem/core/utils/utils.dart'; -import 'package:miutem/screens/asignaturas/widgets/acceso_rapido.dart'; -import 'package:miutem/screens/asignaturas/widgets/asignaturas_en_curso.dart'; -import 'package:miutem/screens/auth/login/login_screen.dart'; -import 'package:miutem/styles/styles.dart'; - -class AsignaturasScreen extends StatefulWidget { - const AsignaturasScreen({super.key}); - - @override - State createState() => _AsignaturasScreenState(); -} - -class _AsignaturasScreenState extends State { - Estudiante? estudiante; - List? asignaturas; - - @override - void initState() { - super.initState(); - Get.find().login() - .then((estudiante) => setState(() => this.estudiante = estudiante), onError: (err) { - if(mounted) { - Navigator.popUntil(context, (route) => route.isFirst); - Navigator.pushReplacement(context, MaterialPageRoute(builder: (ctx) => const LoginScreen())); - } - }); - Get.find() - .getAsignaturas() - .then((asignaturas) => setState(() => this.asignaturas = asignaturas), - onError: (err) { - logger.e('Error al cargar asignaturas', error: err); - }); - } - - - @override - Widget build(BuildContext context) => Scaffold( - appBar: TopNavigation( - estudiante: estudiante, - isMainScreen: true, - title: 'Asignaturas', - actions: const [], - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: RefreshIndicator( - onRefresh: () async { - setState(() { - this.estudiante = null; - this.asignaturas = null; - }); - - final estudiante = await Get.find().login(forceRefresh: true); - final asignaturas = await Get.find().getAsignaturas(forceRefresh: true); - setState(() { - this.estudiante = estudiante; - this.asignaturas = asignaturas; - }); - }, - child: SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - clipBehavior: Clip.none, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 20), - Text("Asignaturas", style: Theme.of(context).textTheme.headlineMedium), - const SizedBox(height: 20), - const AccesoRapido(), - const SizedBox(height: 20), - AsignaturasEnCurso(asignaturas: asignaturas), - ], - ),),) - ); -} diff --git a/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart b/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart new file mode 100644 index 0000000..f591e6c --- /dev/null +++ b/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart @@ -0,0 +1,8 @@ +import 'package:get/get.dart'; +import 'package:miutem/core/models/asignaturas/asignatura.dart'; +import 'package:miutem/core/services/grades_service.dart'; + +Future cargarAsignaturaConNotas({required Asignatura asignatura, bool forceRefresh = false}) async { + final grades = await Get.find().getGrades(asignatura, forceRefresh: forceRefresh); + return asignatura.copyWith(grades: grades); +} \ No newline at end of file diff --git a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart new file mode 100644 index 0000000..46f248e --- /dev/null +++ b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/asignaturas/asignatura.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/widgets/promedio.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart'; +import 'package:miutem/screens/notas/notas_screen.dart'; +import 'package:miutem/styles/styles.dart'; + +class AsignaturaScreen extends StatefulWidget { + + final Asignatura asignatura; + + const AsignaturaScreen({ + super.key, + required this.asignatura, + }); + + @override + State createState() => _AsignaturaScreenState(); +} + +class _AsignaturaScreenState extends State { + + late Asignatura asignatura; + + @override + void initState() { + asignatura = widget.asignatura; + super.initState(); + cargarAsignaturaConNotas(asignatura: widget.asignatura).then((asignatura) => setState(() => this.asignatura = asignatura)).catchError((error) { + if(mounted) showErrorSnackbar(context, "Error al cargar las notas"); + }); + } + + @override + Widget build(BuildContext context) => Scaffold( + appBar: AppBar(title: Text(asignatura.nombre)), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 25), + child: RefreshIndicator( + onRefresh: () async { + try { + final asignatura = await cargarAsignaturaConNotas(asignatura: widget.asignatura); + if (context.mounted) setState(() => this.asignatura = asignatura); + } catch (error) { + if (context.mounted) showErrorSnackbar(context, "Error al recargar las notas"); + } + }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 12), + GestureDetector( + child: Promedio(grades: asignatura.grades), + onTap: () => Navigator.push(context, MaterialPageRoute(builder: (ctx) => NotasScreen(asignatura: asignatura))), + ), + const SizedBox(height: 12), + SeccionHorario(asignatura: asignatura), + const SizedBox(height: 12), + ], + ), + ), + ), + ), + ); +} diff --git a/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart b/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart new file mode 100644 index 0000000..70383b4 --- /dev/null +++ b/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart @@ -0,0 +1,15 @@ +class HorarioBloque { + final String dia; + final String horaInicio; + final String horaFin; + final String nombreAsignatura; + final String sala; + + HorarioBloque({ + required this.dia, + required this.horaInicio, + required this.horaFin, + required this.nombreAsignatura, + required this.sala, + }); +} diff --git a/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart b/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart new file mode 100644 index 0000000..a207bba --- /dev/null +++ b/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart'; + +class CardHorario extends StatelessWidget { + final HorarioBloque bloque; + + const CardHorario({ + super.key, + required this.bloque, + }); + + String formatTime(String time) { + final parts = time.split(':'); + final hours = parts[0].padLeft(2, '0'); + final minutes = parts[1].padLeft(2, '0'); + return '$hours:$minutes'; + } + + String _capitalizeDia(String dia) { + return dia[0].toUpperCase() + dia.substring(1).toLowerCase(); + } + + @override + Widget build(BuildContext context) => Card( + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide(color: Theme.of(context).dividerColor), + ), + margin: const EdgeInsets.only(bottom: 10), + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DecoratedBox( + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + bottomLeft: Radius.circular(16), + ), + border: Border( + right: BorderSide( + color: Theme.of(context).dividerColor, + ), + ), + ), + child: SizedBox( + width: 85, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + formatTime(bloque.horaInicio), + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 16, + ), + ), + Text( + formatTime(bloque.horaFin), + style: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 14, + ), + ), + ], + ), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + _capitalizeDia(bloque.dia), + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 16, + ), + overflow: TextOverflow.ellipsis, + ), + Text( + bloque.nombreAsignatura, + style: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 14, + ), + overflow: TextOverflow.ellipsis, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Icons.location_on, size: 16), + const SizedBox(width: 5), + Expanded( + child: Text( + bloque.sala, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + ); +} diff --git a/lib/screens/asignaturas/detalle_asignatura/widgets/promedio.dart b/lib/screens/asignaturas/detalle_asignatura/widgets/promedio.dart new file mode 100644 index 0000000..008d502 --- /dev/null +++ b/lib/screens/asignaturas/detalle_asignatura/widgets/promedio.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/evaluacion/grades.dart'; +import 'package:miutem/styles/styles.dart'; +import 'package:miutem/core/utils/utils.dart'; +import 'package:skeletonizer/skeletonizer.dart'; + +class Promedio extends StatelessWidget { + + final Grades? grades; + + const Promedio({ + super.key, + required this.grades, + }); + + @override + Widget build(BuildContext context) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Text("Promedio", style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 5), + SizedBox( + child: Skeletonizer( + enabled: grades == null, + child: Card( + margin: EdgeInsets.zero, + color: Theme.of(context).scaffoldBackgroundColor, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: AppTheme.lightGrey)), + child: Padding( + padding: const EdgeInsets.only(top: 20, bottom: 20, left: 40, right: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(formatoNota(grades?.notaFinal) ?? "--", style: TextStyle(fontSize: 32, fontWeight: FontWeight.w700, color: AppTheme.colorScheme.primary)), + const Spacer(), + DecoratedBox(decoration: BoxDecoration(color: AppTheme.lightGrey), child: const SizedBox(width: 1, height: 80)), + const Spacer(), // Spacer agregado + Flexible( + flex: 6, + fit: FlexFit.tight, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Skeleton.keep(child: Text("Presentación", style: Theme.of(context).textTheme.bodyMedium)), + const Spacer(), + Container( + width: 80, + height: 40, + decoration: BoxDecoration( + color: Colors.grey.withValues(alpha: 0.2), + border: Border.all(color: Theme.of(context).dividerColor), + borderRadius: BorderRadius.circular(4), + ), + child: Center( + child: Text( + formatoNota(grades?.notaPresentacion) ?? '--', + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + const SizedBox(height: 10), + Row( + children: [ + Skeleton.keep(child: Text("Examen", style: Theme.of(context).textTheme.bodyMedium)), + const Spacer(), + Container( + width: 80, + height: 40, + decoration: BoxDecoration( + color: Colors.grey.withValues(alpha: 0.2), + border: Border.all(color: Theme.of(context).dividerColor), + borderRadius: BorderRadius.circular(4), + ), + child: Center( + child: Text( + formatoNota(grades?.notaExamen) ?? "--", + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + const SizedBox(height: 12), + Text( + "El promedio se calcula con las notas de presentación y examen. Presiona sobre el promedio para ver más detalles.", + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.grey), + ), + ], + ); +} \ No newline at end of file diff --git a/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart b/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart new file mode 100644 index 0000000..540db49 --- /dev/null +++ b/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/asignaturas/asignatura.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart'; +import 'package:miutem/screens/horario/horario_screen.dart'; +import 'package:miutem/styles/styles.dart'; + +class SeccionHorario extends StatelessWidget { + final Asignatura asignatura; + + const SeccionHorario({ + super.key, + required this.asignatura, + }); + + List _parseHorario() { + final List bloques = []; + + if (asignatura.horario == null || asignatura.horario!.isEmpty) { + return bloques; + } + + // Parse horario string: "lunes | 13:00 - 13:45 / 13:45 - 14:30 || martes | 9:40 - 10:25 / 10:25 - 11:10 || jueves | 11:20 - 12:05 / 12:05 - 12:50" + final dias = asignatura.horario!.split(' || '); + final salas = asignatura.sala?.split(', ') ?? []; + + for (int i = 0; i < dias.length; i++) { + final partes = dias[i].split(' | '); + if (partes.length != 2) continue; + + final dia = partes[0].trim(); + final horariosDelDia = partes[1].trim(); + final bloquesDeTiempo = horariosDelDia.split(' / '); + + if (bloquesDeTiempo.length >= 2) { + final primerBloque = bloquesDeTiempo[0].split(' - '); + final ultimoBloque = bloquesDeTiempo.last.split(' - '); + + if (primerBloque.length == 2 && ultimoBloque.length == 2) { + final horaInicio = primerBloque[0].trim(); + final horaFin = ultimoBloque[1].trim(); + final sala = i < salas.length ? salas[i].trim() : 'Sin sala'; + + bloques.add(HorarioBloque( + dia: dia, + horaInicio: horaInicio, + horaFin: horaFin, + nombreAsignatura: asignatura.nombre, + sala: sala, + )); + } + } + } + + return bloques; + } + + @override + Widget build(BuildContext context) { + final bloques = _parseHorario(); + + if (bloques.isEmpty) { + return const SizedBox.shrink(); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Horario', + style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600), + ), + GestureDetector( + child: Text( + 'Ver más', + style: Theme.of(context).textTheme.bodySmall?.copyWith(fontWeight: FontWeight.w500), + ), + onTap: () => Navigator.push(context, MaterialPageRoute(builder: (ctx) => const HorarioScreen())), + ), + ], + ), + Space.xSmall, + ...bloques.map((bloque) => CardHorario(bloque: bloque)), + ], + ); + } +} diff --git a/lib/screens/asignaturas/lista_asignaturas_screen.dart b/lib/screens/asignaturas/lista_asignaturas_screen.dart new file mode 100644 index 0000000..e524ee1 --- /dev/null +++ b/lib/screens/asignaturas/lista_asignaturas_screen.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:miutem/core/models/asignaturas/asignatura.dart'; +import 'package:miutem/core/models/user/estudiante.dart'; +import 'package:miutem/core/services/asignaturas_service.dart'; +import 'package:miutem/core/services/auth_service.dart'; +import 'package:miutem/core/utils/utils.dart'; +import 'package:miutem/screens/asignaturas/widgets/acceso_rapido.dart'; +import 'package:miutem/screens/asignaturas/widgets/asignaturas_en_curso.dart'; +import 'package:miutem/screens/auth/login/login_screen.dart'; +import 'package:miutem/styles/styles.dart'; + +class AsignaturasScreen extends StatefulWidget { + const AsignaturasScreen({super.key}); + + @override + State createState() => _AsignaturasScreenState(); +} + +class _AsignaturasScreenState extends State { + Estudiante? estudiante; + List? asignaturas; + + @override + void initState() { + super.initState(); + Get.find() + .login() + .then((estudiante) => setState(() => this.estudiante = estudiante), + onError: (err) { + if (mounted) { + Navigator.popUntil(context, (route) => route.isFirst); + Navigator.pushReplacement( + context, MaterialPageRoute(builder: (ctx) => const LoginScreen())); + } + }); + Get.find() + .getAsignaturas() + .then((asignaturas) => setState(() => this.asignaturas = asignaturas), + onError: (err) { + logger.e('Error al cargar asignaturas', error: err); + }); + } + + @override + Widget build(BuildContext context) => Scaffold( + body: Padding( + padding: const EdgeInsets.all(16), + child: RefreshIndicator( + onRefresh: () async { + setState(() { + this.estudiante = null; + this.asignaturas = null; + }); + final estudiante = await Get.find().login(forceRefresh: true); + final asignaturas = await Get.find() + .getAsignaturas(forceRefresh: true); + setState(() { + this.estudiante = estudiante; + this.asignaturas = asignaturas; + }); + }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + clipBehavior: Clip.none, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Text("Asignaturas", style: Theme.of(context).textTheme.headlineMedium), + const SizedBox(height: 20), + const AccesoRapido(), + const SizedBox(height: 20), + AsignaturasEnCurso(asignaturas: asignaturas), + ], + ), + ), + ), + ), + ); +} diff --git a/lib/screens/asignaturas/widgets/acceso_rapido.dart b/lib/screens/asignaturas/widgets/acceso_rapido.dart index 5ed7004..0edd38d 100644 --- a/lib/screens/asignaturas/widgets/acceso_rapido.dart +++ b/lib/screens/asignaturas/widgets/acceso_rapido.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:miutem/styles/styles.dart'; -import 'package:miutem/screens/asignaturas/widgets/actions/acceso_rapido.dart'; +import 'package:miutem/screens/asignaturas/actions/acceso_rapido.dart'; class AccesoRapido extends StatelessWidget { const AccesoRapido({super.key}); diff --git a/lib/screens/asignaturas/widgets/asignaturas_inscritas/lista_asignaturas.dart b/lib/screens/asignaturas/widgets/asignaturas_inscritas/lista_asignaturas.dart index 497bfb1..9c93964 100644 --- a/lib/screens/asignaturas/widgets/asignaturas_inscritas/lista_asignaturas.dart +++ b/lib/screens/asignaturas/widgets/asignaturas_inscritas/lista_asignaturas.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:miutem/core/models/asignaturas/asignatura.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/asignatura_screen.dart'; import 'package:miutem/screens/asignaturas/widgets/asignaturas_inscritas/card_asignatura.dart'; import 'package:skeletonizer/skeletonizer.dart'; @@ -26,6 +27,7 @@ class ListaAsignaturas extends StatelessWidget { tipo: asignatura.tipoHora, nombre: asignatura.nombre, codigo: asignatura.codigo, + onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => AsignaturaScreen(asignatura: asignatura))), )).toList() ?? List.filled(6, defaultCard), ), ); diff --git a/lib/screens/auth/login/widgets/login_form.dart b/lib/screens/auth/login/widgets/login_form.dart index 29164b2..325bc36 100644 --- a/lib/screens/auth/login/widgets/login_form.dart +++ b/lib/screens/auth/login/widgets/login_form.dart @@ -1,3 +1,4 @@ +import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:flutter/material.dart'; import 'package:miutem/core/models/exceptions/custom_exception.dart'; import 'package:miutem/screens/auth/login/actions/login_action.dart'; @@ -50,7 +51,10 @@ class _LoginFormState extends State with WidgetsBindingObserver { children: [ Padding( padding: const EdgeInsets.all(15), - child: Image.asset(MediaQuery.of(context).platformBrightness == Brightness.light ? 'assets/images/miutem_oscuro.png' : 'assets/images/miutem_claro.png', height: 80, fit: BoxFit.fitWidth), + child: ValueListenableBuilder( + valueListenable: AdaptiveTheme.of(context).modeChangeNotifier, + builder: (ctx, mode, child) => Image.asset(mode == AdaptiveThemeMode.light ? 'assets/images/miutem_oscuro.png' : 'assets/images/miutem_claro.png', height: 80, fit: BoxFit.fitWidth), + ), ), const Padding( padding: EdgeInsets.only(bottom: 15), diff --git a/lib/screens/auth/login/widgets/login_form_fields.dart b/lib/screens/auth/login/widgets/login_form_fields.dart index e37e4e7..e2023fb 100644 --- a/lib/screens/auth/login/widgets/login_form_fields.dart +++ b/lib/screens/auth/login/widgets/login_form_fields.dart @@ -33,6 +33,8 @@ class LoginFormFields extends StatelessWidget { border: OutlineInputBorder(), prefixIcon: Icon(Icons.password), ), + autofillHints: const [AutofillHints.password], + textInputAction: TextInputAction.go, focusNode: passwordFocus, obscureText: true, obscuringCharacter: '•', diff --git a/lib/screens/horario/widgets/components/bloque_ramo_card.dart b/lib/screens/horario/widgets/components/bloque_ramo_card.dart index 8638e58..4237a11 100644 --- a/lib/screens/horario/widgets/components/bloque_ramo_card.dart +++ b/lib/screens/horario/widgets/components/bloque_ramo_card.dart @@ -6,7 +6,7 @@ import 'package:miutem/core/services/asignaturas_service.dart'; import 'package:miutem/core/services/carrera_service.dart'; import 'package:miutem/core/services/grades_service.dart'; import 'package:miutem/core/utils/utilities.dart'; -import 'package:miutem/screens/asignaturas/asignaturas_screen.dart'; +import 'package:miutem/screens/asignaturas/lista_asignaturas_screen.dart'; import 'package:miutem/screens/horario/widgets/modals/vista_previa_asignatura_modal.dart'; import 'package:miutem/screens/tasklist/task_list_screen.dart'; import 'package:miutem/styles/loading/loading_dialog.dart'; diff --git a/lib/screens/notas/notas_screen.dart b/lib/screens/notas/notas_screen.dart index 336c3d3..d0d7ebe 100644 --- a/lib/screens/notas/notas_screen.dart +++ b/lib/screens/notas/notas_screen.dart @@ -5,6 +5,7 @@ import 'package:miutem/core/models/evaluacion/evaluacion.dart'; import 'package:miutem/core/models/evaluacion/grades.dart'; import 'package:miutem/core/models/user/persona/persona.dart'; import 'package:miutem/core/services/controllers/notas_controller.dart'; +import 'package:miutem/core/utils/constants.dart'; import 'package:miutem/screens/notas/actions/cargar_asignaturas_con_notas.dart'; import 'package:miutem/screens/notas/widgets/notas.dart'; import 'package:miutem/screens/notas/widgets/promedio.dart'; @@ -13,7 +14,13 @@ import 'package:miutem/screens/notas/widgets/selector_asignatura.dart'; final emptyAsignatura = Asignatura(id: "id", nombre: "Calcular Notas", codigo: "--", tipoHora: "--", estado: "--", seccion: "--", docente: Persona(nombreCompleto: "--"), grades: Grades(notasParciales: [IEvaluacion()])); class NotasScreen extends StatefulWidget { - const NotasScreen({super.key}); + + final Asignatura? asignatura; + + const NotasScreen({ + super.key, + this.asignatura, + }); @override State createState() => _NotasScreenState(); @@ -29,6 +36,16 @@ class _NotasScreenState extends State { @override void initState() { super.initState(); + + if(widget.asignatura != null) { + if(!mounted) return; + setState(() { + asignatura = widget.asignatura; + notasController.updateWithGrades(asignatura?.grades); + }); + return; + } + cargarAsignaturasConNotas().then((asignaturas) { asignaturas = [ emptyAsignatura, @@ -55,20 +72,22 @@ class _NotasScreenState extends State { appBar: AppBar(title: const Text('Notas')), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 25), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SelectorAsignatura(asignatura: asignatura, asignaturas: asignaturas, onChanged: (Asignatura? asignatura) { - notasController.updateWithGrades(asignatura?.grades); - setState(() => this.asignatura = asignatura); - }), - const SizedBox(height: 12), - Promedio(notasController: notasController), - const SizedBox(height: 12), - Notas(notasController: notasController, canAddNotas: asignaturas != null), - const SizedBox(height: 12), - const Center(child: Text("* La función de calculadora sólo funciona para el cálculo del ramo seleccionado, no modificará ninguna nota ingresada al sistema.", style: TextStyle(color: Colors.grey, fontSize: 12))), - ], + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if(widget.asignatura == null) SelectorAsignatura(asignatura: asignatura, asignaturas: asignaturas, onChanged: (Asignatura? asignatura) { + notasController.updateWithGrades(asignatura?.grades); + setState(() => this.asignatura = asignatura); + }), + const SizedBox(height: 12), + Promedio(notasController: notasController), + const SizedBox(height: 12), + Notas(notasController: notasController, canAddNotas: asignaturas != null), + const SizedBox(height: 12), + const Center(child: Text("* La función de calculadora sólo funciona para el cálculo del ramo seleccionado, no modificará ninguna nota ingresada al sistema.", style: TextStyle(color: Colors.grey, fontSize: 12))), + ], + ), ), ), ); diff --git a/lib/screens/profile/profile_screen.dart b/lib/screens/profile/profile_screen.dart index 2f4013e..f1aea07 100644 --- a/lib/screens/profile/profile_screen.dart +++ b/lib/screens/profile/profile_screen.dart @@ -39,7 +39,7 @@ class _ProfileScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - if (estudiante != null) ProfileHeader(title: "Perfil", estudiante: estudiante, isMainScreen: true, actions: [],), + if (estudiante != null) ProfileHeader(estudiante: estudiante), Space.xSmall, const LogOutButton(), Space.small, diff --git a/lib/screens/profile/widgets/profile_settings.dart b/lib/screens/profile/widgets/profile_settings.dart index 574f416..43f034f 100644 --- a/lib/screens/profile/widgets/profile_settings.dart +++ b/lib/screens/profile/widgets/profile_settings.dart @@ -16,7 +16,14 @@ class ProfileSettings extends StatelessWidget { title: const Text('Habilitar Notificaciones'), subtitle: const Text('Recibir notificaciones de la aplicación'), value: UserConfig.to.notificationsEnabled.value, - onChanged: (value) => UserConfig.to.toggleNotifications(), + onChanged: (value) async { + await UserConfig.to.toggleNotifications(); + + if(value) { + // Se habilitan las notificaciones, si no hay permisos, se solicita + if(context.mounted) showTextSnackbar(context, title: 'Notificaciones', message: 'Se han habilitado las notificaciones de la aplicación'); + } + }, ), Space.small, Text('Pantalla', style: Theme.of(context).textTheme.bodyLarge), @@ -37,8 +44,8 @@ class ProfileSettings extends StatelessWidget { ListTile( title: const Text('Sugerencias'), subtitle: const Text('Déjanos tus opiniones sobre la App'), - onTap: () { - // Implementar lógica para sugerencias + onTap: () => { + }, ), ListTile( diff --git a/lib/screens/widgets_screens.dart b/lib/screens/widgets_screens.dart index e1300ca..6dfc0e6 100644 --- a/lib/screens/widgets_screens.dart +++ b/lib/screens/widgets_screens.dart @@ -3,7 +3,7 @@ export 'home/home_screen.dart'; // ASIGNATURAS -export 'asignaturas/asignaturas_screen.dart'; +export 'asignaturas/lista_asignaturas_screen.dart'; // APUNTES export 'tasklist/task_list_screen.dart'; diff --git a/lib/styles/navigation/bottom_navbar.dart b/lib/styles/navigation/bottom_navbar.dart index 42f937f..35c488a 100644 --- a/lib/styles/navigation/bottom_navbar.dart +++ b/lib/styles/navigation/bottom_navbar.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:miutem/core/models/navigation/navigation_item.dart'; -import 'package:miutem/screens/asignaturas/asignaturas_screen.dart'; +import 'package:miutem/screens/asignaturas/lista_asignaturas_screen.dart'; import 'package:miutem/screens/home/home_screen.dart'; import 'package:miutem/screens/profile/profile_screen.dart'; import 'package:miutem/screens/tasklist/task_list_screen.dart'; @@ -19,7 +19,7 @@ class _BottomNavBarState extends State { final List screens = [ NavigationItem(destination: const HomeScreen(), label: "Inicio", icon: AppIcons.home), NavigationItem(destination: const AsignaturasScreen(), label: "Asignaturas", icon: AppIcons.subjects), - NavigationItem(destination: const TaskListScreen(), label: "Apuntes", icon: AppIcons.notes), + // NavigationItem(destination: const TaskListScreen(), label: "Apuntes", icon: AppIcons.notes), NavigationItem(destination: const ProfileScreen(), label: "Perfil", icon: AppIcons.profile), ]; diff --git a/lib/styles/theme/theme.dart b/lib/styles/theme/theme.dart index 46d5a04..f6cad5b 100644 --- a/lib/styles/theme/theme.dart +++ b/lib/styles/theme/theme.dart @@ -88,7 +88,7 @@ class AppTheme { scaffoldBackgroundColor: scaffoldBackgroundColor, /// Tema de las tarjetas - cardTheme: CardTheme( + cardTheme: CardThemeData( color: scaffoldBackgroundColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Theme.of(context).dividerColor)), ), @@ -171,7 +171,7 @@ class AppTheme { scaffoldBackgroundColor: scaffoldBackgroundColorDark, /// Tema de las tarjetas - cardTheme: CardTheme( + cardTheme: CardThemeData( color: scaffoldBackgroundColorDark, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Theme.of(context).dividerColor)), ), @@ -238,7 +238,7 @@ class AppTheme { ), /// Tema del dialogo - dialogTheme: DialogTheme( + dialogTheme: DialogThemeData( backgroundColor: scaffoldBackgroundColorDark, titleTextStyle: GoogleFonts.inter( color: white, diff --git a/lib/widgets/navigation/top_navigation.dart b/lib/widgets/navigation/top_navigation.dart deleted file mode 100644 index 9ba42c7..0000000 --- a/lib/widgets/navigation/top_navigation.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:miutem/core/models/user/estudiante.dart'; -import 'package:miutem/core/utils/utils.dart'; -import 'package:miutem/widgets/icons.dart'; -import 'package:skeletonizer/skeletonizer.dart'; -import 'package:flutter/services.dart'; - -class TopNavigation extends StatelessWidget implements PreferredSizeWidget { - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); - - final Estudiante? estudiante; - final bool isMainScreen; - final String title; - const TopNavigation({super.key, this.estudiante, required this.isMainScreen, required this.title, required List actions}); - - @override - Widget build(BuildContext context) { - return AppBar( - backgroundColor: Theme.of(context).appBarTheme.backgroundColor, - systemOverlayStyle: SystemUiOverlayStyle( - statusBarColor: Theme.of(context).appBarTheme.backgroundColor, - statusBarIconBrightness: Theme.of(context).brightness == Brightness.dark ? Brightness.light : Brightness.dark, - ), - leading: Padding( - padding: const EdgeInsets.all(8.0), - child: isMainScreen - ? let(estudiante?.fotoUrl, (String fotoUrl) => CircleAvatar( - radius: 25, - foregroundImage: MemoryImage(base64Decode(fotoUrl)), - )) ?? const Skeleton.keep(child: CircleAvatar(child: Icon(AppIcons.profile, fill: 1, size: 40))) - : const BackButton(), - ), - title: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Text(title), - ), - actions: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Skeleton.keep(child: IconButton(onPressed: (){}, icon: const Icon(AppIcons.more, weight: 900,))), - ), - ], - ); - } -} diff --git a/linux/flutter/ephemeral/.plugin_symlinks/flutter_secure_storage_linux b/linux/flutter/ephemeral/.plugin_symlinks/flutter_secure_storage_linux index 5b68978..4928e70 120000 --- a/linux/flutter/ephemeral/.plugin_symlinks/flutter_secure_storage_linux +++ b/linux/flutter/ephemeral/.plugin_symlinks/flutter_secure_storage_linux @@ -1 +1 @@ -/Users/fran/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.1/ \ No newline at end of file +/Users/fran/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/ \ No newline at end of file diff --git a/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus b/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus index fdf5ebe..368c67c 120000 --- a/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus +++ b/linux/flutter/ephemeral/.plugin_symlinks/package_info_plus @@ -1 +1 @@ -/Users/fran/.pub-cache/hosted/pub.dev/package_info_plus-8.1.2/ \ No newline at end of file +/Users/fran/.pub-cache/hosted/pub.dev/package_info_plus-8.3.0/ \ No newline at end of file diff --git a/linux/flutter/ephemeral/.plugin_symlinks/share_plus b/linux/flutter/ephemeral/.plugin_symlinks/share_plus index a4d5b0a..0fdff83 120000 --- a/linux/flutter/ephemeral/.plugin_symlinks/share_plus +++ b/linux/flutter/ephemeral/.plugin_symlinks/share_plus @@ -1 +1 @@ -/Users/fran/.pub-cache/hosted/pub.dev/share_plus-10.1.3/ \ No newline at end of file +/Users/fran/.pub-cache/hosted/pub.dev/share_plus-10.1.4/ \ No newline at end of file diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 20890c8..d1b023f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -26,9 +26,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AwesomeNotificationsCorePlugin.register(with: registry.registrar(forPlugin: "AwesomeNotificationsCorePlugin")) FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin")) - FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) + FirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) - FLTFirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseRemoteConfigPlugin")) + FirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FirebaseRemoteConfigPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 7ca70c2..780dc4e 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -6,7 +6,7 @@ FLUTTER_TARGET=/Users/fran/Development/Apps/miutem/lib/main.dart FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=3.0.0 FLUTTER_BUILD_NUMBER=142 -DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl +DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzIuNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MDc3YjRhNGNlMQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzJmMmIxOGJiMA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My44LjE= DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index 175b6c8..d71e410 100755 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -7,7 +7,7 @@ export "FLUTTER_TARGET=/Users/fran/Development/Apps/miutem/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=3.0.0" export "FLUTTER_BUILD_NUMBER=142" -export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl" +export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzIuNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MDc3YjRhNGNlMQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzJmMmIxOGJiMA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My44LjE=" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" diff --git a/macos/Podfile b/macos/Podfile index f85f88f..3ffa125 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -1,4 +1,4 @@ -platform :macos, '11.5' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -32,7 +32,7 @@ target 'Runner' do pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', - :tag => '11.4.0' + :tag => '11.15.0' flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 60305c1..3879a61 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -3,150 +3,152 @@ PODS: - FlutterMacOS - awesome_notifications_core (0.0.1): - FlutterMacOS - - cloud_firestore (5.6.0): - - Firebase/CoreOnly (~> 11.4.0) - - Firebase/Firestore (~> 11.4.0) + - cloud_firestore (5.6.12): + - Firebase/CoreOnly (~> 11.15.0) + - Firebase/Firestore (~> 11.15.0) - firebase_core - FlutterMacOS - file_saver (0.0.1): - FlutterMacOS - - Firebase/Analytics (11.4.0): + - Firebase/Analytics (11.15.0): - Firebase/Core - - Firebase/Core (11.4.0): + - Firebase/Core (11.15.0): - Firebase/CoreOnly - - FirebaseAnalytics (~> 11.4.0) - - Firebase/CoreOnly (11.4.0): - - FirebaseCore (= 11.4.0) - - Firebase/Firestore (11.4.0): + - FirebaseAnalytics (~> 11.15.0) + - Firebase/CoreOnly (11.15.0): + - FirebaseCore (~> 11.15.0) + - Firebase/Firestore (11.15.0): - Firebase/CoreOnly - - FirebaseFirestore (~> 11.4.0) - - Firebase/RemoteConfig (11.4.0): + - FirebaseFirestore (~> 11.15.0) + - Firebase/RemoteConfig (11.15.0): - Firebase/CoreOnly - - FirebaseRemoteConfig (~> 11.4.0) - - firebase_analytics (11.3.6): - - Firebase/Analytics (= 11.4.0) + - FirebaseRemoteConfig (~> 11.15.0) + - firebase_analytics (11.6.0): + - Firebase/Analytics (= 11.15.0) - firebase_core - FlutterMacOS - - firebase_core (3.9.0): - - Firebase/CoreOnly (~> 11.4.0) + - firebase_core (3.15.2): + - Firebase/CoreOnly (~> 11.15.0) - FlutterMacOS - - firebase_remote_config (5.2.0): - - Firebase/CoreOnly (~> 11.4.0) - - Firebase/RemoteConfig (~> 11.4.0) + - firebase_remote_config (5.5.0): + - Firebase/CoreOnly (~> 11.15.0) + - Firebase/RemoteConfig (~> 11.15.0) - firebase_core - FlutterMacOS - - FirebaseABTesting (11.4.0): - - FirebaseCore (~> 11.0) - - FirebaseAnalytics (11.4.0): - - FirebaseAnalytics/AdIdSupport (= 11.4.0) - - FirebaseCore (~> 11.0) + - FirebaseABTesting (11.15.0): + - FirebaseCore (~> 11.15.0) + - FirebaseAnalytics (11.15.0): + - FirebaseAnalytics/Default (= 11.15.0) + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseAnalytics/AdIdSupport (11.4.0): - - FirebaseCore (~> 11.0) + - FirebaseAnalytics/Default (11.15.0): + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - - GoogleAppMeasurement (= 11.4.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/Default (= 11.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseCore (11.4.0): - - FirebaseCoreInternal (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Logger (~> 8.0) - - FirebaseCoreExtension (11.4.0): - - FirebaseCore (~> 11.0) - - FirebaseCoreInternal (11.5.0): - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FirebaseFirestore (11.4.0): - - FirebaseFirestoreBinary (= 11.4.0) - - FirebaseFirestoreAbseilBinary (1.2024011602.0) - - FirebaseFirestoreBinary (11.4.0): - - FirebaseCore (= 11.4.0) - - FirebaseCoreExtension (= 11.4.0) - - FirebaseFirestoreInternalBinary (= 11.4.0) - - FirebaseSharedSwift (= 11.4.0) - - FirebaseFirestoreGRPCBoringSSLBinary (1.65.1) - - FirebaseFirestoreGRPCCoreBinary (1.65.1): - - FirebaseFirestoreAbseilBinary (= 1.2024011602.0) - - FirebaseFirestoreGRPCBoringSSLBinary (= 1.65.1) - - FirebaseFirestoreGRPCCPPBinary (1.65.1): - - FirebaseFirestoreAbseilBinary (= 1.2024011602.0) - - FirebaseFirestoreGRPCCoreBinary (= 1.65.1) - - FirebaseFirestoreInternalBinary (11.4.0): - - FirebaseCore (= 11.4.0) - - FirebaseFirestoreAbseilBinary (= 1.2024011602.0) - - FirebaseFirestoreGRPCCPPBinary (= 1.65.1) + - FirebaseCore (11.15.0): + - FirebaseCoreInternal (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/Logger (~> 8.1) + - FirebaseCoreExtension (11.15.0): + - FirebaseCore (~> 11.15.0) + - FirebaseCoreInternal (11.15.0): + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - FirebaseFirestore (11.15.0): + - FirebaseFirestoreBinary (= 11.15.0) + - FirebaseFirestoreAbseilBinary (1.2024072200.0) + - FirebaseFirestoreBinary (11.15.0): + - FirebaseCore (= 11.15.0) + - FirebaseCoreExtension (= 11.15.0) + - FirebaseFirestoreInternalBinary (= 11.15.0) + - FirebaseSharedSwift (= 11.15.0) + - FirebaseFirestoreGRPCBoringSSLBinary (1.69.0) + - FirebaseFirestoreGRPCCoreBinary (1.69.0): + - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) + - FirebaseFirestoreGRPCBoringSSLBinary (= 1.69.0) + - FirebaseFirestoreGRPCCPPBinary (1.69.0): + - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) + - FirebaseFirestoreGRPCCoreBinary (= 1.69.0) + - FirebaseFirestoreInternalBinary (11.15.0): + - FirebaseCore (= 11.15.0) + - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) + - FirebaseFirestoreGRPCCPPBinary (= 1.69.0) - leveldb-library (~> 1.22) - nanopb (~> 3.30910.0) - - FirebaseInstallations (11.4.0): - - FirebaseCore (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) + - FirebaseInstallations (11.15.0): + - FirebaseCore (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseRemoteConfig (11.4.0): + - FirebaseRemoteConfig (11.15.0): - FirebaseABTesting (~> 11.0) - - FirebaseCore (~> 11.0) + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - FirebaseRemoteConfigInterop (~> 11.0) - FirebaseSharedSwift (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FirebaseRemoteConfigInterop (11.5.0) - - FirebaseSharedSwift (11.4.0) - - flutter_secure_storage_macos (6.1.1): + - GoogleUtilities/Environment (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - FirebaseRemoteConfigInterop (11.15.0) + - FirebaseSharedSwift (11.15.0) + - flutter_secure_storage_macos (6.1.3): - FlutterMacOS - FlutterMacOS (1.0.0) - - GoogleAppMeasurement (11.4.0): - - GoogleAppMeasurement/AdIdSupport (= 11.4.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/Core (11.15.0): + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/AdIdSupport (11.4.0): - - GoogleAppMeasurement/WithoutAdIdSupport (= 11.4.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/Default (11.15.0): + - GoogleAdsOnDeviceConversion (= 2.1.0) + - GoogleAppMeasurement/Core (= 11.15.0) + - GoogleAppMeasurement/IdentitySupport (= 11.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/WithoutAdIdSupport (11.4.0): - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/MethodSwizzler (~> 8.0) - - GoogleUtilities/Network (~> 8.0) - - "GoogleUtilities/NSData+zlib (~> 8.0)" + - GoogleAppMeasurement/IdentitySupport (11.15.0): + - GoogleAppMeasurement/Core (= 11.15.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/MethodSwizzler (~> 8.1) + - GoogleUtilities/Network (~> 8.1) + - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleUtilities/AppDelegateSwizzler (8.0.2): + - GoogleUtilities/AppDelegateSwizzler (8.1.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - GoogleUtilities/Privacy - - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Environment (8.1.0): - GoogleUtilities/Privacy - - GoogleUtilities/Logger (8.0.2): + - GoogleUtilities/Logger (8.1.0): - GoogleUtilities/Environment - GoogleUtilities/Privacy - - GoogleUtilities/MethodSwizzler (8.0.2): + - GoogleUtilities/MethodSwizzler (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GoogleUtilities/Network (8.0.2): + - GoogleUtilities/Network (8.1.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Privacy - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (8.0.2)": + - "GoogleUtilities/NSData+zlib (8.1.0)": - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (8.0.2) - - GoogleUtilities/Reachability (8.0.2): + - GoogleUtilities/Privacy (8.1.0) + - GoogleUtilities/Reachability (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (8.0.2): + - GoogleUtilities/UserDefaults (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy - leveldb-library (1.22.6) @@ -183,7 +185,7 @@ DEPENDENCIES: - firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`) - firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`) - firebase_remote_config (from `Flutter/ephemeral/.symlinks/plugins/firebase_remote_config/macos`) - - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `11.4.0`) + - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `11.15.0`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) @@ -235,7 +237,7 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/firebase_remote_config/macos FirebaseFirestore: :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.4.0 + :tag: 11.15.0 flutter_secure_storage_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos FlutterMacOS: @@ -258,37 +260,37 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: FirebaseFirestore: :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.4.0 + :tag: 11.15.0 SPEC CHECKSUMS: awesome_notifications: 428f5c15a700b117418aed09e29c21c5806fcf69 awesome_notifications_core: 43438f2e1b0e1dd9da81aaeb1b4af5ec0447af1a - cloud_firestore: 0d1c982890702bf99ab2881743c35fddb66e295d + cloud_firestore: 8f6806cab914d2e8b607a6d8abee6ce7fa0880fd file_saver: 44e6fbf666677faf097302460e214e977fdd977b - Firebase: cf1b19f21410b029b6786a54e9764a0cacad3c99 - firebase_analytics: a80b3d6645f2f12d626fde928b61dae12e5ea2ef - firebase_core: 1dfe1f4d02ad78be0277e320aa3d8384cf46231f - firebase_remote_config: 559bbd2f3fec93598e725d35da1f94a3140a15ad - FirebaseABTesting: aef1719704fade00b200827e7973f352efc4caee - FirebaseAnalytics: 3feef9ae8733c567866342a1000691baaa7cad49 - FirebaseCore: e0510f1523bc0eb21653cac00792e1e2bd6f1771 - FirebaseCoreExtension: 4445e4cd877e0790c4af33bedca61eaef27b7513 - FirebaseCoreInternal: f47dd28ae7782e6a4738aad3106071a8fe0af604 - FirebaseFirestore: 97f18b411aaca686a9e94ba742341228643b1a46 - FirebaseFirestoreAbseilBinary: fa2ebd2ed02cadef5382e4f7c93f1b265c812c85 - FirebaseFirestoreBinary: d0380b879b58d663b22467017d0e348d5b17b36b - FirebaseFirestoreGRPCBoringSSLBinary: d86ebbe2adc8d15d7ebf305fff7d6358385327f8 - FirebaseFirestoreGRPCCoreBinary: 472bd808e1886a5efb2fd03dd09b98d34641a335 - FirebaseFirestoreGRPCCPPBinary: db76d83d2b7517623f8426ed7f7a17bad2478084 - FirebaseFirestoreInternalBinary: 01c33a6d789b95dce32dbdfcaf30d60ddf8902d8 - FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 - FirebaseRemoteConfig: 7655681d02417bc9b287338edb9d721ff79e1a4a - FirebaseRemoteConfigInterop: 7a7aebb9342d53913a5c890efa88e289d9e5c1bc - FirebaseSharedSwift: 505dae2d05969dbf6d43749a642bb1bf230f0252 - flutter_secure_storage_macos: 59459653abe1adb92abbc8ea747d79f8d19866c9 + Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e + firebase_analytics: c6a3f80cf2e8681b4e6b3402162acf116c4d3a57 + firebase_core: 2af692f4818474ed52eda1ba6aeb448a6a3352af + firebase_remote_config: bb8bc7e5c54dfcf006175eb91f901e4216d2a522 + FirebaseABTesting: 5e9d432834aebf27ab72100d37af44dfbe8d82f7 + FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae + FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e + FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435 + FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 + FirebaseFirestore: 736c2099af30aed7728d5789059fee1914b4d213 + FirebaseFirestoreAbseilBinary: 4cfa8823cedc1b774843e04fe578ad279b387f97 + FirebaseFirestoreBinary: 43abe19da1cb39a10171786e5a2e18fa9d57b6af + FirebaseFirestoreGRPCBoringSSLBinary: c3dfef3ff448ae2c1c85f9baf9fac5afc4db99fa + FirebaseFirestoreGRPCCoreBinary: 565534e160a0415d12185f7f171c52a567382fbd + FirebaseFirestoreGRPCCPPBinary: 6c0134e8d230ee58b9d51dec2a30a48efd6d5dc7 + FirebaseFirestoreInternalBinary: ea89c368772c8fa4c9550a464b36c25796f6182c + FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 + FirebaseRemoteConfig: b496646b82855e174a7f1e354c65e0e913085168 + FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa + FirebaseSharedSwift: e17c654ef1f1a616b0b33054e663ad1035c8fd40 + flutter_secure_storage_macos: c2754d3483d20bb207bb9e5a14f1b8e771abcdb9 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e - GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d + GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 + GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b @@ -300,6 +302,6 @@ SPEC CHECKSUMS: url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 -PODFILE CHECKSUM: 7e95490b7d7a576b730e49f0b16ae56b13152a13 +PODFILE CHECKSUM: 12a580f9c9fdf6d524385f77d7258e098581c672 COCOAPODS: 1.16.2 diff --git a/pubspec.lock b/pubspec.lock index 4cc4fb8..7efc196 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: daa1d780fdecf8af925680c06c86563cdd445deea995d5c9176f1302a2b10bbe + sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11 url: "https://pub.dev" source: hosted - version: "1.3.48" + version: "1.3.59" adaptive_number: dependency: transitive description: @@ -53,42 +53,42 @@ packages: dependency: transitive description: name: archive - sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a" + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.7" args: dependency: transitive description: name: args - sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.0" async: dependency: transitive description: name: async - sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted - version: "2.12.0" + version: "2.13.0" awesome_notifications: dependency: "direct main" description: name: awesome_notifications - sha256: d051ffb694a53da216ff13d02c8ec645d75320048262f7e6b3c1d95a4f54c902 + sha256: "0d5fa4457f2ba4e536adc3ef6af709cdcecf4a05a1f3035981e9afa2f899b2a8" url: "https://pub.dev" source: hosted - version: "0.10.0" + version: "0.10.1" awesome_notifications_core: dependency: "direct main" description: name: awesome_notifications_core - sha256: b77e1b147067572908c9472255913a81aac56d35abdeaaada0d22121f6cd15d1 + sha256: f8a227159f70e30d0f4c1d8996cf7e3865fec7c9030df752dfa51d177dc08b38 url: "https://pub.dev" source: hosted - version: "0.10.0" + version: "0.10.1" boolean_selector: dependency: transitive description: @@ -113,6 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + chalkdart: + dependency: transitive + description: + name: chalkdart + sha256: "7ffc6bd39c81453fb9ba8dbce042a9c960219b75ea1c07196a7fa41c2fab9e86" + url: "https://pub.dev" + source: hosted + version: "3.0.5" characters: dependency: transitive description: @@ -157,26 +165,26 @@ packages: dependency: "direct main" description: name: cloud_firestore - sha256: ba89d4ae6ddaea0241f50a2dc1ffe36f32891f1a6bc78540f55d79c7f8ed536a + sha256: "2d33da4465bdb81b6685c41b535895065adcb16261beb398f5f3bbc623979e9c" url: "https://pub.dev" source: hosted - version: "5.6.0" + version: "5.6.12" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - sha256: "966cfd6beb2e943f3363a7bced4476533caa55d2338ffd876855c07e5296d1d7" + sha256: "413c4e01895cf9cb3de36fa5c219479e06cd4722876274ace5dfc9f13ab2e39b" url: "https://pub.dev" source: hosted - version: "6.6.0" + version: "6.6.12" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - sha256: "110ba7ff3322c239527e5be3c0d471a3e14fd0a870b2feff96d1e527a2eae2bb" + sha256: c1e30fc4a0fcedb08723fb4b1f12ee4e56d937cbf9deae1bda43cbb6367bb4cf url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.4.12" collection: dependency: "direct main" description: @@ -229,10 +237,10 @@ packages: dependency: "direct main" description: name: dart_jsonwebtoken - sha256: "866787dc17afaef46a9ea7dd33eefe60c6d82084b4a36d70e8e788d091cd04ef" + sha256: "00a0812d2aeaeb0d30bcbc4dd3cee57971dbc0ab2216adf4f0247f37793f15ef" url: "https://pub.dev" source: hosted - version: "2.14.2" + version: "2.17.0" dart_style: dependency: transitive description: @@ -293,18 +301,18 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" ffi: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" file: dependency: transitive description: @@ -325,74 +333,74 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: "366140abb55418ea23060b779893fa997c2d8e1974a4d1cc4d9590933b65c5fd" + sha256: "4f85b161772e1d54a66893ef131c0a44bd9e552efa78b33d5f4f60d2caa5c8a3" url: "https://pub.dev" source: hosted - version: "11.3.6" + version: "11.6.0" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "8e987cf977c0c8f4ad02d9950a9b25b1a9606899f37b66a322a43af05be0246b" + sha256: a44b6d1155ed5cae7641e3de7163111cfd9f6f6c954ca916dc6a3bdfa86bf845 url: "https://pub.dev" source: hosted - version: "4.2.8" + version: "4.4.3" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "0b64ef9060d394bba3d3b4777f49ee098efeeea7b0afb04663c956de6a3da170" + sha256: c7d1ed1f86ae64215757518af5576ff88341c8ce5741988c05cc3b2e07b0b273 url: "https://pub.dev" source: hosted - version: "0.5.10+5" + version: "0.5.10+16" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "15d761b95dfa2906dfcc31b7fc6fe293188533d1a3ffe78389ba9e69bd7fdbde" + sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5" url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.15.2" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: fbc008cf390d909b823763064b63afefe9f02d8afdb13eb3f485b871afee956b + sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37" url: "https://pub.dev" source: hosted - version: "2.19.0" + version: "2.24.1" firebase_remote_config: dependency: "direct main" description: name: firebase_remote_config - sha256: e377fd519e73baf5afae343da8c8a0a88b506cfbf2ea8ceb7614a8793d9a7083 + sha256: e1635b1e8713f4a823920ec3a56a14034b90ce455d47746ab0da994857f370cf url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.5.0" firebase_remote_config_platform_interface: dependency: transitive description: name: firebase_remote_config_platform_interface - sha256: "95755bcab41c7c9c28ac92aefc1eb4c79ffcc7565e94833cb1e7a2c9320ba53f" + sha256: ce836c5c62056edbe23ef501e6876691ee32476afd12fe95b76e57bba9d25485 url: "https://pub.dev" source: hosted - version: "1.4.47" + version: "2.0.0" firebase_remote_config_web: dependency: transitive description: name: firebase_remote_config_web - sha256: "09ff1f3db2120e798530354dd77c49e6596d88eadcfe366eb3a083c2dd5d7cb0" + sha256: "9dbd75024bfcd47c05046c95f9cf648a8fc862b096bcf8ea1e4b855d50ea19ad" url: "https://pub.dev" source: hosted - version: "1.7.5" + version: "1.8.9" fixnum: dependency: transitive description: @@ -442,34 +450,34 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: "1152ab0067ca5a2ebeb862fe0a762057202cceb22b7e62692dcbabf6483891bb" + sha256: "8321a6d11a8d13977fa780c89de8d257cce3d841eecfb7a4cadffcc4f12d82dc" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.6" flutter_secure_storage: dependency: "direct main" description: name: flutter_secure_storage - sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" + sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" url: "https://pub.dev" source: hosted - version: "9.2.2" + version: "9.2.4" flutter_secure_storage_linux: dependency: transitive description: name: flutter_secure_storage_linux - sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b" + sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.3" flutter_secure_storage_macos: dependency: transitive description: name: flutter_secure_storage_macos - sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" + sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" flutter_secure_storage_platform_interface: dependency: transitive description: @@ -508,10 +516,10 @@ packages: dependency: "direct main" description: name: get - sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e + sha256: c79eeb4339f1f3deffd9ec912f8a923834bec55f7b49c9e882b8fef2c139d425 url: "https://pub.dev" source: hosted - version: "4.6.6" + version: "4.7.2" get_storage: dependency: "direct main" description: @@ -524,10 +532,10 @@ packages: dependency: transitive description: name: glob - sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" google_fonts: dependency: "direct main" description: @@ -540,42 +548,42 @@ packages: dependency: "direct main" description: name: html - sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" url: "https://pub.dev" source: hosted - version: "0.15.5" + version: "0.15.6" http: dependency: transitive description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.4.0" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" image: dependency: transitive description: name: image - sha256: "8346ad4b5173924b5ddddab782fc7d8a6300178c8b1dc427775405a01701c4a6" + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" url: "https://pub.dev" source: hosted - version: "4.5.2" + version: "4.5.4" intl: dependency: transitive description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.20.2" js: dependency: transitive description: @@ -604,10 +612,10 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "10.0.9" leak_tracker_flutter_testing: dependency: transitive description: @@ -636,10 +644,10 @@ packages: dependency: "direct main" description: name: logger - sha256: be4b23575aac7ebf01f225a241eb7f6b5641eeaf43c6a8613510fc2f8cf187d1 + sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c" url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.6.1" logging: dependency: transitive description: @@ -668,10 +676,10 @@ packages: dependency: "direct main" description: name: material_symbols_icons - sha256: "64404f47f8e0a9d20478468e5decef867a688660bad7173adcd20418d7f892c9" + sha256: "7c50901b39d1ad645ee25d920aed008061e1fd541a897b4ebf2c01d966dbf16b" url: "https://pub.dev" source: hosted - version: "4.2801.0" + version: "4.2815.1" meta: dependency: transitive description: @@ -692,26 +700,26 @@ packages: dependency: transitive description: name: package_config - sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - sha256: "70c421fe9d9cc1a9a7f3b05ae56befd469fe4f8daa3b484823141a55442d858d" + sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" url: "https://pub.dev" source: hosted - version: "8.1.2" + version: "8.3.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b + sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.2.0" path: dependency: transitive description: @@ -748,10 +756,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" + sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 url: "https://pub.dev" source: hosted - version: "2.2.15" + version: "2.2.17" path_provider_foundation: dependency: transitive description: @@ -796,10 +804,10 @@ packages: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "6.1.0" platform: dependency: transitive description: @@ -828,18 +836,18 @@ packages: dependency: transitive description: name: posix - sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" url: "https://pub.dev" source: hosted - version: "6.0.1" + version: "6.0.3" pub_semver: dependency: transitive description: name: pub_semver - sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" pubspec_parse: dependency: transitive description: @@ -876,10 +884,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "6327c3f233729374d0abaafd61f6846115b2a481b4feddd8534211dc10659400" + sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da url: "https://pub.dev" source: hosted - version: "10.1.3" + version: "10.1.4" share_plus_platform_interface: dependency: transitive description: @@ -892,18 +900,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "3c7e73920c694a436afaf65ab60ce3453d91f84208d761fbd83fc21182134d93" + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.5.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d" + sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.10" shared_preferences_foundation: dependency: transitive description: @@ -932,10 +940,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" shared_preferences_windows: dependency: transitive description: @@ -948,10 +956,10 @@ packages: dependency: "direct main" description: name: skeletonizer - sha256: "3b202e4fa9c49b017d368fb0e570d4952bcd19972b67b2face071bdd68abbfae" + sha256: eebc03dc86b298e2d7f61e0ebce5713e9dbbc3e786f825909b4591756f196eb6 url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "2.1.0+1" sky_engine: dependency: transitive description: flutter @@ -985,34 +993,34 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb" + sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" sqflite_android: dependency: transitive description: name: sqflite_android - sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" + sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b" url: "https://pub.dev" source: hosted - version: "2.5.4+6" + version: "2.5.5" sqflite_darwin: dependency: transitive description: name: sqflite_darwin - sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474" + sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" sqflite_platform_interface: dependency: transitive description: @@ -1049,10 +1057,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 url: "https://pub.dev" source: hosted - version: "3.3.0+3" + version: "3.4.0" term_glyph: dependency: transitive description: @@ -1089,26 +1097,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" + sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" url: "https://pub.dev" source: hosted - version: "6.3.14" + version: "6.3.16" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" + sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.3" url_launcher_linux: dependency: transitive description: @@ -1137,18 +1145,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.1" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" uuid: dependency: transitive description: @@ -1169,74 +1177,74 @@ packages: dependency: "direct main" description: name: video_player - sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17" + sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" url: "https://pub.dev" source: hosted - version: "2.9.2" + version: "2.10.0" video_player_android: dependency: transitive description: name: video_player_android - sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898" + sha256: "9d5af2d233ba69df803dcf2f31e66d9a4c6206f2d96178df06b09b0ec3056b39" url: "https://pub.dev" source: hosted - version: "2.7.16" + version: "2.8.9" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: "33224c19775fd244be2d6e3dbd8e1826ab162877bd61123bf71890772119a2b7" + sha256: "9fedd55023249f3a02738c195c906b4e530956191febf0838e37d0dac912f953" url: "https://pub.dev" source: hosted - version: "2.6.5" + version: "2.8.0" video_player_platform_interface: dependency: transitive description: name: video_player_platform_interface - sha256: "229d7642ccd9f3dc4aba169609dd6b5f3f443bb4cc15b82f7785fcada5af9bbb" + sha256: cf2a1d29a284db648fd66cbd18aacc157f9862d77d2cc790f6f9678a46c1db5a url: "https://pub.dev" source: hosted - version: "6.2.3" + version: "6.4.0" video_player_web: dependency: transitive description: name: video_player_web - sha256: "881b375a934d8ebf868c7fb1423b2bfaa393a0a265fa3f733079a86536064a10" + sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.0" vm_service: dependency: transitive description: name: vm_service - sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 url: "https://pub.dev" source: hosted - version: "14.3.1" + version: "15.0.0" watcher: dependency: transitive description: name: watcher - sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" + sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" web: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" win32: dependency: transitive description: name: win32 - sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69" + sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" url: "https://pub.dev" source: hosted - version: "5.9.0" + version: "5.14.0" xdg_directories: dependency: transitive description: @@ -1278,5 +1286,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.8.0 <4.0.0" + flutter: ">=3.31.0-0.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 4af61e9..60e2196 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: flutter_native_splash: ^2.4.1 video_player: ^2.9.2 url_launcher: ^6.3.0 - skeletonizer: ^1.4.2 + skeletonizer: ^2.1.0+1 material_symbols_icons: ^4.2785.1 collection: ^1.18.0 extended_masked_text: ^3.0.1 @@ -35,9 +35,9 @@ dependencies: screenshot: ^3.0.0 share_plus: ^10.1.2 # Firebase - firebase_core: ^3.7.0 - firebase_remote_config: ^5.1.4 - firebase_analytics: ^11.3.4 + firebase_core: ^3.15.2 + firebase_remote_config: ^5.5.0 + firebase_analytics: ^11.6.0 # Apuntes sqflite: ^2.4.1 flutter_secure_storage: ^9.2.2 From 07682fc2f168c234aed71ecc16547d75655e2644 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:16:01 -0400 Subject: [PATCH 04/24] Update lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../asignaturas/detalle_asignatura/asignatura_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart index 46f248e..3aca639 100644 --- a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart +++ b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart @@ -28,7 +28,7 @@ class _AsignaturaScreenState extends State { asignatura = widget.asignatura; super.initState(); cargarAsignaturaConNotas(asignatura: widget.asignatura).then((asignatura) => setState(() => this.asignatura = asignatura)).catchError((error) { - if(mounted) showErrorSnackbar(context, "Error al cargar las notas"); + if (mounted) showErrorSnackbar(context, "Error al cargar las notas"); }); } From 915b9221ee2f236e81c1dbd5d9adb8b9d2dad141 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:16:11 -0400 Subject: [PATCH 05/24] Update lib/screens/notas/notas_screen.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/screens/notas/notas_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/notas/notas_screen.dart b/lib/screens/notas/notas_screen.dart index d0d7ebe..86951d4 100644 --- a/lib/screens/notas/notas_screen.dart +++ b/lib/screens/notas/notas_screen.dart @@ -37,7 +37,7 @@ class _NotasScreenState extends State { void initState() { super.initState(); - if(widget.asignatura != null) { + if (widget.asignatura != null) { if(!mounted) return; setState(() { asignatura = widget.asignatura; From 0d792112c9e08c4aabef68043f4a0ab145eab326 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:16:20 -0400 Subject: [PATCH 06/24] Update lib/screens/notas/notas_screen.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/screens/notas/notas_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/notas/notas_screen.dart b/lib/screens/notas/notas_screen.dart index 86951d4..9bd5362 100644 --- a/lib/screens/notas/notas_screen.dart +++ b/lib/screens/notas/notas_screen.dart @@ -38,7 +38,7 @@ class _NotasScreenState extends State { super.initState(); if (widget.asignatura != null) { - if(!mounted) return; + if (!mounted) return; setState(() { asignatura = widget.asignatura; notasController.updateWithGrades(asignatura?.grades); From 00e033c4c157473f1a9228221b468a2b7187d321 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:16:32 -0400 Subject: [PATCH 07/24] Update lib/screens/profile/widgets/profile_settings.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/screens/profile/widgets/profile_settings.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/profile/widgets/profile_settings.dart b/lib/screens/profile/widgets/profile_settings.dart index 43f034f..3dd2c59 100644 --- a/lib/screens/profile/widgets/profile_settings.dart +++ b/lib/screens/profile/widgets/profile_settings.dart @@ -19,9 +19,9 @@ class ProfileSettings extends StatelessWidget { onChanged: (value) async { await UserConfig.to.toggleNotifications(); - if(value) { + if (value) { // Se habilitan las notificaciones, si no hay permisos, se solicita - if(context.mounted) showTextSnackbar(context, title: 'Notificaciones', message: 'Se han habilitado las notificaciones de la aplicación'); + if (context.mounted) showTextSnackbar(context, title: 'Notificaciones', message: 'Se han habilitado las notificaciones de la aplicación'); } }, ), From 9a4353132bf8eecb33d4f722ccb35f5fa12e9602 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:16:44 -0400 Subject: [PATCH 08/24] Update lib/screens/notas/notas_screen.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/screens/notas/notas_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/notas/notas_screen.dart b/lib/screens/notas/notas_screen.dart index 9bd5362..246250f 100644 --- a/lib/screens/notas/notas_screen.dart +++ b/lib/screens/notas/notas_screen.dart @@ -76,7 +76,7 @@ class _NotasScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if(widget.asignatura == null) SelectorAsignatura(asignatura: asignatura, asignaturas: asignaturas, onChanged: (Asignatura? asignatura) { + if (widget.asignatura == null) SelectorAsignatura(asignatura: asignatura, asignaturas: asignaturas, onChanged: (Asignatura? asignatura) { notasController.updateWithGrades(asignatura?.grades); setState(() => this.asignatura = asignatura); }), From 394dfc2b8e7f51640d63385e1ececca6e20cd714 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:35:50 -0400 Subject: [PATCH 09/24] Update lib/screens/profile/widgets/profile_settings.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/screens/profile/widgets/profile_settings.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/screens/profile/widgets/profile_settings.dart b/lib/screens/profile/widgets/profile_settings.dart index 3dd2c59..2ac1cb9 100644 --- a/lib/screens/profile/widgets/profile_settings.dart +++ b/lib/screens/profile/widgets/profile_settings.dart @@ -44,9 +44,7 @@ class ProfileSettings extends StatelessWidget { ListTile( title: const Text('Sugerencias'), subtitle: const Text('Déjanos tus opiniones sobre la App'), - onTap: () => { - - }, + onTap: () {}, ), ListTile( title: const Text('Desarrolladores de la App'), From 78fed217264a9040085266cbd3238cd5485abd18 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:52:23 -0400 Subject: [PATCH 10/24] feat: add feature flag support to bottom navigation items and app --- .../models/navigation/navigation_item.dart | 3 +- lib/styles/navigation/bottom_navbar.dart | 100 ++++-- lib/widgets/feature_flag.dart | 326 ++++++++++++++++++ 3 files changed, 400 insertions(+), 29 deletions(-) create mode 100644 lib/widgets/feature_flag.dart diff --git a/lib/core/models/navigation/navigation_item.dart b/lib/core/models/navigation/navigation_item.dart index 03bd242..879ef68 100644 --- a/lib/core/models/navigation/navigation_item.dart +++ b/lib/core/models/navigation/navigation_item.dart @@ -4,7 +4,8 @@ class NavigationItem { final Widget destination; final String label; + final String featureFlag; final IconData icon; - NavigationItem({required this.destination, required this.label, required this.icon}); + NavigationItem({required this.destination, required this.label, required this.featureFlag, required this.icon}); } \ No newline at end of file diff --git a/lib/styles/navigation/bottom_navbar.dart b/lib/styles/navigation/bottom_navbar.dart index 35c488a..e371d81 100644 --- a/lib/styles/navigation/bottom_navbar.dart +++ b/lib/styles/navigation/bottom_navbar.dart @@ -5,6 +5,7 @@ import 'package:miutem/screens/home/home_screen.dart'; import 'package:miutem/screens/profile/profile_screen.dart'; import 'package:miutem/screens/tasklist/task_list_screen.dart'; import 'package:miutem/styles/theme/icons.dart'; +import 'package:miutem/widgets/feature_flag.dart'; class BottomNavBar extends StatefulWidget { const BottomNavBar({super.key}); @@ -16,35 +17,78 @@ class BottomNavBar extends StatefulWidget { class _BottomNavBarState extends State { int idx = 0; - final List screens = [ - NavigationItem(destination: const HomeScreen(), label: "Inicio", icon: AppIcons.home), - NavigationItem(destination: const AsignaturasScreen(), label: "Asignaturas", icon: AppIcons.subjects), - // NavigationItem(destination: const TaskListScreen(), label: "Apuntes", icon: AppIcons.notes), - NavigationItem(destination: const ProfileScreen(), label: "Perfil", icon: AppIcons.profile), + final List allScreens = [ + NavigationItem(destination: const HomeScreen(), label: "Inicio", featureFlag: "bottom_navigation.home", icon: AppIcons.home), + NavigationItem(destination: const AsignaturasScreen(), label: "Asignaturas", featureFlag: "bottom_navigation.asignaturas", icon: AppIcons.subjects), + NavigationItem(destination: const TaskListScreen(), label: "Apuntes", featureFlag: "bottom_navigation.apuntes", icon: AppIcons.notes), + NavigationItem(destination: const ProfileScreen(), label: "Perfil", featureFlag: "bottom_navigation.perfil", icon: AppIcons.profile), ]; + List get enabledScreens { + return allScreens.where((screen) => FeatureFlag.evaluateSync(screen.featureFlag)).toList(); + } + + @override + void initState() { + super.initState(); + // Ensure the initial index is valid for enabled screens + WidgetsBinding.instance.addPostFrameCallback((_) { + final enabled = enabledScreens; + if (enabled.isNotEmpty && idx >= enabled.length) { + setState(() { + idx = 0; // Reset to first available screen + }); + } + }); + } + + void _onDestinationSelected(int selectedIdx) { + final enabled = enabledScreens; + if (selectedIdx >= 0 && selectedIdx < enabled.length) { + setState(() { + idx = selectedIdx; + }); + } + } + @override - Widget build(BuildContext context) => Scaffold( - extendBody: true, - bottomNavigationBar: NavigationBar( - height: 65, - elevation: 0, - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - labelBehavior: NavigationDestinationLabelBehavior.alwaysShow, - onDestinationSelected: (idx) => setState(() => this.idx = idx), - selectedIndex: idx, - destinations: screens.map((e) => NavigationDestination( - selectedIcon: Icon(e.icon, fill: 1), - icon: Icon(e.icon, weight: 600), - label: e.label, - )).toList(), - ), - body: IndexedStack( - index: idx, - children: screens.map((e) => SafeArea( - minimum: const EdgeInsets.symmetric(vertical: 20), - child: e.destination, - )).toList(), - ), - ); + Widget build(BuildContext context) { + final enabled = enabledScreens; + + // If no screens are enabled, show a fallback (this shouldn't happen in practice) + if (enabled.isEmpty) { + return const Scaffold( + body: Center( + child: Text('No navigation items available'), + ), + ); + } + + // Ensure current index is valid + final currentIdx = idx >= enabled.length ? 0 : idx; + + return Scaffold( + extendBody: true, + bottomNavigationBar: NavigationBar( + height: 65, + elevation: 0, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + labelBehavior: NavigationDestinationLabelBehavior.alwaysShow, + onDestinationSelected: _onDestinationSelected, + selectedIndex: currentIdx, + destinations: enabled.map((e) => NavigationDestination( + selectedIcon: Icon(e.icon, fill: 1), + icon: Icon(e.icon, weight: 600), + label: e.label, + )).toList(), + ), + body: IndexedStack( + index: currentIdx, + children: enabled.map((e) => SafeArea( + minimum: const EdgeInsets.symmetric(vertical: 20), + child: e.destination, + )).toList(), + ), + ); + } } \ No newline at end of file diff --git a/lib/widgets/feature_flag.dart b/lib/widgets/feature_flag.dart new file mode 100644 index 0000000..3fbcfd7 --- /dev/null +++ b/lib/widgets/feature_flag.dart @@ -0,0 +1,326 @@ +import 'dart:convert'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:logger/logger.dart'; +import 'package:miutem/core/services/firebase/remote_config_service.dart'; + +/// A widget that conditionally renders its child based on a feature flag value from Firebase Remote Config. +/// +/// Usage: +/// ```dart +/// FeatureFlag('bottom_navigation.novedades', child: const Text('This text will be shown if the feature flag is true')) +/// ``` +class FeatureFlag extends StatelessWidget { + /// The feature flag key to evaluate (supports dot notation for nested flags) + final String flagKey; + + /// The child widget to render if the feature flag is enabled + final Widget child; + + /// The fallback widget to render if the feature flag is disabled (optional) + final Widget? fallback; + + /// Whether to show debug information in development mode + final bool showDebugInfo; + + const FeatureFlag( + this.flagKey, { + super.key, + required this.child, + this.fallback, + this.showDebugInfo = false, + }); + + /// Evaluates a feature flag and returns its boolean value + /// + /// Usage: + /// ```dart + /// const featureFlagValue = await FeatureFlag.evaluate('bottom_navigation.novedades'); + /// ``` + static Future evaluate(String flagKey) async { + try { + final remoteConfig = FirebaseRemoteConfig.instance; + + // Ensure remote config is initialized + if (Get.isRegistered()) { + // Remote config should already be initialized via the service + } else { + // Fallback initialization if service is not available + await remoteConfig.setConfigSettings(RemoteConfigSettings( + fetchTimeout: const Duration(minutes: 1), + minimumFetchInterval: const Duration(hours: 12), + )); + await remoteConfig.fetchAndActivate(); + } + + return _evaluateNestedFlag(remoteConfig, flagKey); + } catch (e) { + // Return false by default if there's an error + debugPrint('FeatureFlag: Error evaluating flag "$flagKey": $e'); + return false; + } + } + + /// Evaluates a feature flag synchronously (uses cached values) + /// + /// Usage: + /// ```dart + /// final isEnabled = FeatureFlag.evaluateSync('bottom_navigation.novedades'); + /// ``` + static bool evaluateSync(String flagKey) { + try { + final remoteConfig = FirebaseRemoteConfig.instance; + return _evaluateNestedFlag(remoteConfig, flagKey); + } catch (e) { + debugPrint('FeatureFlag: Error evaluating flag "$flagKey" synchronously: $e'); + return false; + } + } + + /// Internal method to evaluate nested feature flags from the JSON structure + static bool _evaluateNestedFlag(FirebaseRemoteConfig remoteConfig, String flagKey) { + try { + // Get the feature_flags JSON from Remote Config + final featureFlagsJson = remoteConfig.getString('feature_flags'); + + if (featureFlagsJson.isEmpty) { + Logger().w('FeatureFlag: No feature_flags parameter found in Remote Config'); + return false; + } + + // Parse the JSON + final Map featureFlags = jsonDecode(featureFlagsJson); + + // Navigate through the nested structure using dot notation + final keyParts = flagKey.split('.'); + dynamic currentLevel = featureFlags; + + for (final part in keyParts) { + if (currentLevel is Map && currentLevel.containsKey(part)) { + currentLevel = currentLevel[part]; + } else { + Logger().w('FeatureFlag: Feature flag "$flagKey" not found in remote config, defaulting to false'); + return false; + } + } + + // Return the boolean value, defaulting to false if it's not a boolean + if (currentLevel is bool) { + return currentLevel; + } else { + Logger().w('FeatureFlag: Value for "$flagKey" is not a boolean: $currentLevel, defaulting to false'); + return false; + } + } catch (e) { + Logger().e('FeatureFlag: Error parsing feature flags JSON for "$flagKey": $e, defaulting to false'); + return false; + } + } + + /// Gets the string value of a nested feature flag + static String getString(String flagKey, {String defaultValue = ''}) { + try { + final remoteConfig = FirebaseRemoteConfig.instance; + final featureFlagsJson = remoteConfig.getString('feature_flags'); + + if (featureFlagsJson.isEmpty) { + return defaultValue; + } + + final Map featureFlags = jsonDecode(featureFlagsJson); + final keyParts = flagKey.split('.'); + dynamic currentLevel = featureFlags; + + for (final part in keyParts) { + if (currentLevel is Map && currentLevel.containsKey(part)) { + currentLevel = currentLevel[part]; + } else { + return defaultValue; + } + } + + return currentLevel?.toString() ?? defaultValue; + } catch (e) { + debugPrint('FeatureFlag: Error getting string value for flag "$flagKey": $e'); + return defaultValue; + } + } + + /// Gets the int value of a nested feature flag + static int getInt(String flagKey, {int defaultValue = 0}) { + try { + final remoteConfig = FirebaseRemoteConfig.instance; + final featureFlagsJson = remoteConfig.getString('feature_flags'); + + if (featureFlagsJson.isEmpty) { + return defaultValue; + } + + final Map featureFlags = jsonDecode(featureFlagsJson); + final keyParts = flagKey.split('.'); + dynamic currentLevel = featureFlags; + + for (final part in keyParts) { + if (currentLevel is Map && currentLevel.containsKey(part)) { + currentLevel = currentLevel[part]; + } else { + return defaultValue; + } + } + + if (currentLevel is int) { + return currentLevel; + } else if (currentLevel is num) { + return currentLevel.toInt(); + } + + return defaultValue; + } catch (e) { + debugPrint('FeatureFlag: Error getting int value for flag "$flagKey": $e'); + return defaultValue; + } + } + + /// Gets the double value of a nested feature flag + static double getDouble(String flagKey, {double defaultValue = 0.0}) { + try { + final remoteConfig = FirebaseRemoteConfig.instance; + final featureFlagsJson = remoteConfig.getString('feature_flags'); + + if (featureFlagsJson.isEmpty) { + return defaultValue; + } + + final Map featureFlags = jsonDecode(featureFlagsJson); + final keyParts = flagKey.split('.'); + dynamic currentLevel = featureFlags; + + for (final part in keyParts) { + if (currentLevel is Map && currentLevel.containsKey(part)) { + currentLevel = currentLevel[part]; + } else { + return defaultValue; + } + } + + if (currentLevel is double) { + return currentLevel; + } else if (currentLevel is num) { + return currentLevel.toDouble(); + } + + return defaultValue; + } catch (e) { + debugPrint('FeatureFlag: Error getting double value for flag "$flagKey": $e'); + return defaultValue; + } + } + + /// Gets the raw value of a nested feature flag (can be any type) + static dynamic getValue(String flagKey, {dynamic defaultValue}) { + try { + final remoteConfig = FirebaseRemoteConfig.instance; + final featureFlagsJson = remoteConfig.getString('feature_flags'); + + if (featureFlagsJson.isEmpty) { + return defaultValue; + } + + final Map featureFlags = jsonDecode(featureFlagsJson); + final keyParts = flagKey.split('.'); + dynamic currentLevel = featureFlags; + + for (final part in keyParts) { + if (currentLevel is Map && currentLevel.containsKey(part)) { + currentLevel = currentLevel[part]; + } else { + return defaultValue; + } + } + + return currentLevel ?? defaultValue; + } catch (e) { + debugPrint('FeatureFlag: Error getting value for flag "$flagKey": $e'); + return defaultValue; + } + } + + @override + Widget build(BuildContext context) { + final isEnabled = evaluateSync(flagKey); + + if (showDebugInfo && kDebugMode) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: isEnabled ? Colors.green.withValues(alpha: 0.2) : Colors.red.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + 'FeatureFlag: $flagKey = $isEnabled', + style: TextStyle( + fontSize: 10, + color: isEnabled ? Colors.green[800] : Colors.red[800], + fontFamily: 'monospace', + ), + ), + ), + const SizedBox(height: 4), + if (isEnabled) child else (fallback ?? const SizedBox.shrink()), + ], + ); + } + + return isEnabled ? child : (fallback ?? const SizedBox.shrink()); + } +} + +/// A builder widget that provides the feature flag value to its builder function +/// +/// Usage: +/// ```dart +/// FeatureFlagBuilder( +/// 'MY_FEATURE_FLAG', +/// builder: (context, isEnabled) { +/// return Text(isEnabled ? 'Feature is ON' : 'Feature is OFF'); +/// }, +/// ) +/// ``` +class FeatureFlagBuilder extends StatelessWidget { + final String flagKey; + final Widget Function(BuildContext context, bool isEnabled) builder; + + const FeatureFlagBuilder( + this.flagKey, { + super.key, + required this.builder, + }); + + @override + Widget build(BuildContext context) { + final isEnabled = FeatureFlag.evaluateSync(flagKey); + return builder(context, isEnabled); + } +} + +/// Extension to add feature flag functionality to any widget +extension FeatureFlagExtension on Widget { + /// Wraps this widget with a feature flag check + /// + /// Usage: + /// ```dart + /// const Text('Hello').withFeatureFlag('MY_FEATURE_FLAG') + /// ``` + Widget withFeatureFlag(String flagKey, {Widget? fallback}) { + return FeatureFlag( + flagKey, + fallback: fallback, + child: this, + ); + } +} From 92e952eadba4152b7c41d213d1c505c4ab611104 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:54:14 -0400 Subject: [PATCH 11/24] feat: integrate feature flags into profile settings --- .../profile/widgets/profile_settings.dart | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/screens/profile/widgets/profile_settings.dart b/lib/screens/profile/widgets/profile_settings.dart index 2ac1cb9..4ad27a6 100644 --- a/lib/screens/profile/widgets/profile_settings.dart +++ b/lib/screens/profile/widgets/profile_settings.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:miutem/core/models/config/user_config.dart'; import 'package:miutem/styles/styles.dart'; +import 'package:miutem/widgets/feature_flag.dart'; class ProfileSettings extends StatelessWidget { const ProfileSettings({super.key}); @@ -12,7 +13,7 @@ class ProfileSettings extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Sistema', style: Theme.of(context).textTheme.bodyLarge), - SwitchListTile( + FeatureFlag('perfil.notificaciones', child: SwitchListTile( title: const Text('Habilitar Notificaciones'), subtitle: const Text('Recibir notificaciones de la aplicación'), value: UserConfig.to.notificationsEnabled.value, @@ -24,7 +25,7 @@ class ProfileSettings extends StatelessWidget { if (context.mounted) showTextSnackbar(context, title: 'Notificaciones', message: 'Se han habilitado las notificaciones de la aplicación'); } }, - ), + )), Space.small, Text('Pantalla', style: Theme.of(context).textTheme.bodyLarge), ListTile( @@ -34,25 +35,25 @@ class ProfileSettings extends StatelessWidget { ), Space.small, Text('Feedback', style: Theme.of(context).textTheme.bodyLarge), - ListTile( + FeatureFlag('perfil.bug_report', child: ListTile( title: const Text('Reportar un Bug'), subtitle: const Text('Reportar un bug en la aplicación'), onTap: () { // Implementar lógica para reportar un bug }, - ), - ListTile( + )), + FeatureFlag('perfil.feedback_report', child: ListTile( title: const Text('Sugerencias'), subtitle: const Text('Déjanos tus opiniones sobre la App'), onTap: () {}, - ), - ListTile( + )), + FeatureFlag('perfil.desarrolladores', child: ListTile( title: const Text('Desarrolladores de la App'), subtitle: const Text('Vé al equipo que desarrolla Mi UTEM'), onTap: () { // Implementar lógica para ver los desarrolladores de la app }, - ), + )), ], )); From bf4e9b20c44311b4770f7945f397fbba92a56c3d Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:57:52 -0400 Subject: [PATCH 12/24] patch: usar otro nombre para la variable Se utiliza otro nombre para la variable para evitar `shadowing` Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../asignaturas/detalle_asignatura/asignatura_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart index 3aca639..0d4138c 100644 --- a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart +++ b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart @@ -27,7 +27,7 @@ class _AsignaturaScreenState extends State { void initState() { asignatura = widget.asignatura; super.initState(); - cargarAsignaturaConNotas(asignatura: widget.asignatura).then((asignatura) => setState(() => this.asignatura = asignatura)).catchError((error) { + cargarAsignaturaConNotas(asignatura: widget.asignatura).then((loadedAsignatura) => setState(() => this.asignatura = loadedAsignatura)).catchError((error) { if (mounted) showErrorSnackbar(context, "Error al cargar las notas"); }); } From f796f82658e2a8481a4331e18c55f48ea90c689a Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:58:18 -0400 Subject: [PATCH 13/24] patch: cambio de nombre de variable para evitar `shadowing` Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../asignaturas/detalle_asignatura/asignatura_screen.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart index 0d4138c..90f3c2d 100644 --- a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart +++ b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart @@ -40,8 +40,8 @@ class _AsignaturaScreenState extends State { child: RefreshIndicator( onRefresh: () async { try { - final asignatura = await cargarAsignaturaConNotas(asignatura: widget.asignatura); - if (context.mounted) setState(() => this.asignatura = asignatura); + final updatedAsignatura = await cargarAsignaturaConNotas(asignatura: widget.asignatura); + if (context.mounted) setState(() => this.asignatura = updatedAsignatura); } catch (error) { if (context.mounted) showErrorSnackbar(context, "Error al recargar las notas"); } From 9776c7e22a5603a9bdb7813175a0b3fab16a1480 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:41:07 -0400 Subject: [PATCH 14/24] patch Signed-off-by: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> --- .env.example | 2 + .gitignore | 4 + lib/core/models/asignaturas/asignatura.dart | 6 +- lib/core/models/horario.dart | 6 ++ lib/core/models/tokenized_object.dart | 1 + lib/core/models/user/estudiante.dart | 5 ++ lib/core/utils/constants.dart | 4 +- lib/core/utils/horario_data.dart | 74 +++++++++++++++++ lib/main.dart | 2 + .../actions/cargar_notas_asignatura.dart | 32 ++++++++ .../detalle_asignatura/asignatura_screen.dart | 26 +++++- .../models/horario_bloque.dart | 11 +++ .../widgets/card_horario.dart | 33 +++----- .../widgets/seccion_horario.dart | 82 +++++-------------- .../profile/widgets/profile_header.dart | 2 - pubspec.yaml | 1 + 16 files changed, 199 insertions(+), 92 deletions(-) create mode 100644 .env.example create mode 100644 lib/core/utils/horario_data.dart diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c5be108 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +MI_UTEM_SIGA_DEBUG=https://siga.utem.cl +MI_UTEM_API_DEBUG=https://api.exdev.cl \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2377a34..dd28763 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,7 @@ android/app/google-services.json ios/Runner/GoogleService-Info.plist linux/flutter/* macos/Flutter/* + +# env +.env* +!.env.example diff --git a/lib/core/models/asignaturas/asignatura.dart b/lib/core/models/asignaturas/asignatura.dart index eac87be..6415ad8 100644 --- a/lib/core/models/asignaturas/asignatura.dart +++ b/lib/core/models/asignaturas/asignatura.dart @@ -62,12 +62,12 @@ class Asignatura { tipoHora: capitalize(json['tipo_hora'] ?? ''), estado: '', // TODO: Agregar estado de aprobado, reprobado o inscrito. docente: let(json['profesor'] ?? json['docente'], (String? docente) { - final partes = (docente ?? '').split("-").map((it) => it.trim()); - if(partes.isEmpty) { + if(docente == null || docente.isEmpty) { return null; } - if(partes.length == 1) { + final partes = docente.split(RegExp(r'\s*-\s*')).map((it) => it.trim()).toList(); + if(partes.length <= 1) { return Persona(nombreCompleto: capitalize(partes.first)); } diff --git a/lib/core/models/horario.dart b/lib/core/models/horario.dart index 645ec5a..b5f2a83 100644 --- a/lib/core/models/horario.dart +++ b/lib/core/models/horario.dart @@ -167,4 +167,10 @@ class BloqueHorario { ) : BloqueHorario(); static List>? fromJsonMatrix(dynamic json) => json == null ? null : (json as List? ?? []).map((bloque) => (bloque as List? ?? []).map((dia) => BloqueHorario.fromJson(dia)).toList()).toList(); + + toJson() => { + 'asignatura': asignatura?.toJson(), + 'sala': sala, + 'codigo': codigo, + }; } diff --git a/lib/core/models/tokenized_object.dart b/lib/core/models/tokenized_object.dart index 5a3c713..c635435 100644 --- a/lib/core/models/tokenized_object.dart +++ b/lib/core/models/tokenized_object.dart @@ -3,6 +3,7 @@ import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; mixin TokenizedObject { String get token; + bool get ignoreTokenExpiration; JWT? decodeToken() => JWT.tryDecode(token); diff --git a/lib/core/models/user/estudiante.dart b/lib/core/models/user/estudiante.dart index 156b873..173f1be 100644 --- a/lib/core/models/user/estudiante.dart +++ b/lib/core/models/user/estudiante.dart @@ -10,6 +10,9 @@ class Estudiante extends PersonaUtem with TokenizedObject { @override final String token; + @override + final bool ignoreTokenExpiration; + final String correoPersonal; final List perfiles; @@ -21,6 +24,7 @@ class Estudiante extends PersonaUtem with TokenizedObject { required this.correoPersonal, required super.fotoUrl, required this.perfiles, + this.ignoreTokenExpiration = false, }); factory Estudiante.fromJson(Map json) { @@ -34,6 +38,7 @@ class Estudiante extends PersonaUtem with TokenizedObject { correoUtem: datosPersona['correo_utem'], fotoUrl: datosPersona['foto'], perfiles: Perfil.values.where((perfil) => (datosPersona['perfiles'] as List).map((perfil) => (perfil as String).toLowerCase()).contains(perfil.name)).toList(), + ignoreTokenExpiration: json['ignore_token_expiration'] ?? false, ); } diff --git a/lib/core/utils/constants.dart b/lib/core/utils/constants.dart index 1b0c2d5..ed40394 100644 --- a/lib/core/utils/constants.dart +++ b/lib/core/utils/constants.dart @@ -6,9 +6,9 @@ import 'package:logger/logger.dart'; import 'package:shared_preferences/shared_preferences.dart'; final apiUrl = !kDebugMode ? 'https://api.exdev.cl' : (dotenv.env['MI_UTEM_API_DEBUG'] ?? 'https://api.exdev.cl'); -const sigaHost = 'https://siga.utem.cl'; +final sigaHost = !kDebugMode ? 'https://siga.utem.cl' : (dotenv.env['MI_UTEM_SIGA_DEBUG'] ?? 'https://siga.utem.cl'); const miUtemHost = 'https://mi.utem.cl'; -const sigaServiceUri = '$sigaHost/servicios'; // UTEM SIGA API URL +final sigaServiceUri = '$sigaHost/servicios'; // UTEM SIGA API URL const genericUserAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Safari/605.1.15'; diff --git a/lib/core/utils/horario_data.dart b/lib/core/utils/horario_data.dart new file mode 100644 index 0000000..4d73465 --- /dev/null +++ b/lib/core/utils/horario_data.dart @@ -0,0 +1,74 @@ +const List diasHorario = [ + 'Lunes', + 'Martes', + 'Miércoles', + 'Jueves', + 'Viernes', + 'Sábado', + 'Domingo', +]; + +const bloquesHorario = [ + '8:00 - 8:45', + '8:45 - 9:30', + + '9:40 - 10:25', + '10:25 - 11:10', + + '11:20 - 12:05', + '12:05 - 12:50', + + '13:00 - 13:45', + '13:45 - 14:30', + + '14:40 - 15:25', + '15:25 - 16:10', + + '16:20 - 17:05', + '17:05 - 17:50', + + '18:00 - 18:45', + '18:45 - 19:30', + + '19:40 - 20:25', + '20:25 - 21:10', + + '21:20 - 22:05', + '22:05 - 22:50', +]; + +const List horasInicio = [ + "08:00", + "09:40", + "11:20", + "13:00", + "14:40", + "16:20", + "18:00", + "19:40", + "21:20" +]; + +const List horasIntermedio = [ + "08:45", + "10:25", + "12:05", + "13:45", + "15:25", + "17:05", + "18:45", + "20:25", + "22:05" +]; + +const List horasTermino = [ + "09:30", + "11:10", + "12:50", + "14:30", + "16:10", + "17:50", + "19:30", + "21:10", + "22:50" +]; \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 66e9b75..8fbc7d9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:get/get.dart'; import 'package:miutem/core/models/config/user_config.dart'; import 'package:miutem/core/models/preferencia.dart'; @@ -11,6 +12,7 @@ import 'package:miutem/core/utils/http/functions.dart'; import 'package:miutem/styles/styles.dart'; void main() async { + await dotenv.load(); WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( diff --git a/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart b/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart index f591e6c..e9ac319 100644 --- a/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart +++ b/lib/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart @@ -1,8 +1,40 @@ +import 'dart:convert'; + import 'package:get/get.dart'; import 'package:miutem/core/models/asignaturas/asignatura.dart'; import 'package:miutem/core/services/grades_service.dart'; +import 'package:miutem/core/services/horario_service.dart'; +import 'package:miutem/core/utils/constants.dart'; +import 'package:miutem/core/utils/horario_data.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart'; Future cargarAsignaturaConNotas({required Asignatura asignatura, bool forceRefresh = false}) async { final grades = await Get.find().getGrades(asignatura, forceRefresh: forceRefresh); return asignatura.copyWith(grades: grades); +} + +Future> cargarHorarioBloque({required Asignatura asignatura}) async { + try { + final horario = await Get.find().getHorario(); + Map> bloquesPorDia = {}; + for(final (idx, filaBloques) in (horario.horario ?? []).indexed) { + if(filaBloques.isEmpty) continue; // Skip empty rows + for(final (idxDia, bloque) in filaBloques.indexed) { + if(bloque.asignatura == null || bloque.asignatura?.nombre.toUpperCase() != asignatura.nombre.toUpperCase() || bloque.asignatura?.codigo.toUpperCase() != asignatura.codigo.toUpperCase()) continue; // Skip empty blocks + bloquesPorDia[idxDia] ??= {}; + bloquesPorDia[idxDia]![idx] = HorarioBloque( + dia: diasHorario[idxDia], + nombreAsignatura: bloque.asignatura?.nombre ?? 'N/A', + sala: bloque.sala ?? 'N/A', + horaInicio: bloquesHorario[idx].split('-')[0].trim(), + horaFin: bloquesHorario[idx].split('-')[1].trim(), + ); + } + } + + return bloquesPorDia.values.expand((diaBloques) => diaBloques.values).toList(); + } catch (error) { + logger.e('Error al cargar horario bloque', error: error); + return []; + } } \ No newline at end of file diff --git a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart index 90f3c2d..2276249 100644 --- a/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart +++ b/lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:miutem/core/models/asignaturas/asignatura.dart'; +import 'package:miutem/core/utils/constants.dart'; import 'package:miutem/screens/asignaturas/detalle_asignatura/actions/cargar_notas_asignatura.dart'; +import 'package:miutem/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart'; import 'package:miutem/screens/asignaturas/detalle_asignatura/widgets/promedio.dart'; import 'package:miutem/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart'; import 'package:miutem/screens/notas/notas_screen.dart'; @@ -22,14 +24,17 @@ class AsignaturaScreen extends StatefulWidget { class _AsignaturaScreenState extends State { late Asignatura asignatura; + List bloquesHorario = []; @override void initState() { asignatura = widget.asignatura; super.initState(); - cargarAsignaturaConNotas(asignatura: widget.asignatura).then((loadedAsignatura) => setState(() => this.asignatura = loadedAsignatura)).catchError((error) { + cargarAsignaturaConNotas(asignatura: widget.asignatura).then((loadedAsignatura) => setState(() => asignatura = loadedAsignatura)).catchError((error) { if (mounted) showErrorSnackbar(context, "Error al cargar las notas"); }); + + cargarHorarioBloque(asignatura: asignatura).then((bloques) => setState(() => bloquesHorario = bloques)); } @override @@ -39,10 +44,25 @@ class _AsignaturaScreenState extends State { padding: const EdgeInsets.symmetric(horizontal: 25), child: RefreshIndicator( onRefresh: () async { + List tmp = bloquesHorario; try { + setState(() { + bloquesHorario.clear(); + }); + final updatedAsignatura = await cargarAsignaturaConNotas(asignatura: widget.asignatura); - if (context.mounted) setState(() => this.asignatura = updatedAsignatura); + final updatedBloquesHorario = await cargarHorarioBloque(asignatura: updatedAsignatura); + if (context.mounted) { + setState(() { + asignatura = updatedAsignatura; + bloquesHorario = updatedBloquesHorario; + }); + } } catch (error) { + setState(() { + bloquesHorario = tmp; // Revertir a los bloques anteriores en caso de error + }); + logger.e('Error al recargar vista asignatura', error: error); if (context.mounted) showErrorSnackbar(context, "Error al recargar las notas"); } }, @@ -57,7 +77,7 @@ class _AsignaturaScreenState extends State { onTap: () => Navigator.push(context, MaterialPageRoute(builder: (ctx) => NotasScreen(asignatura: asignatura))), ), const SizedBox(height: 12), - SeccionHorario(asignatura: asignatura), + SeccionHorario(bloques: bloquesHorario), const SizedBox(height: 12), ], ), diff --git a/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart b/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart index 70383b4..8a6f57e 100644 --- a/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart +++ b/lib/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + class HorarioBloque { final String dia; final String horaInicio; @@ -12,4 +14,13 @@ class HorarioBloque { required this.nombreAsignatura, required this.sala, }); + + toJson() => { + 'dia': dia, + 'horaInicio': horaInicio, + 'horaFin': horaFin, + 'nombreAsignatura': nombreAsignatura, + 'sala': sala, + }; + } diff --git a/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart b/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart index a207bba..487bf8f 100644 --- a/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart +++ b/lib/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart @@ -9,16 +9,7 @@ class CardHorario extends StatelessWidget { required this.bloque, }); - String formatTime(String time) { - final parts = time.split(':'); - final hours = parts[0].padLeft(2, '0'); - final minutes = parts[1].padLeft(2, '0'); - return '$hours:$minutes'; - } - - String _capitalizeDia(String dia) { - return dia[0].toUpperCase() + dia.substring(1).toLowerCase(); - } + String _capitalizeDia(String dia) => dia[0].toUpperCase() + dia.substring(1).toLowerCase(); @override Widget build(BuildContext context) => Card( @@ -51,15 +42,13 @@ class CardHorario extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - formatTime(bloque.horaInicio), + Text(bloque.horaInicio.trim(), style: const TextStyle( - fontWeight: FontWeight.w700, - fontSize: 16, + fontWeight: FontWeight.w900, + fontSize: 18, ), ), - Text( - formatTime(bloque.horaFin), + Text(bloque.horaFin.trim(), style: const TextStyle( fontWeight: FontWeight.w500, fontSize: 14, @@ -78,17 +67,17 @@ class CardHorario extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - _capitalizeDia(bloque.dia), + _capitalizeDia(bloque.nombreAsignatura), style: const TextStyle( - fontWeight: FontWeight.w700, - fontSize: 16, + fontWeight: FontWeight.w900, + fontSize: 18, ), overflow: TextOverflow.ellipsis, ), Text( - bloque.nombreAsignatura, + bloque.dia, style: const TextStyle( - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w300, fontSize: 14, ), overflow: TextOverflow.ellipsis, @@ -96,7 +85,7 @@ class CardHorario extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - const Icon(Icons.location_on, size: 16), + const Icon(Icons.location_on_outlined, size: 16), const SizedBox(width: 5), Expanded( child: Text( diff --git a/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart b/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart index 540db49..e6fafba 100644 --- a/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart +++ b/lib/screens/asignaturas/detalle_asignatura/widgets/seccion_horario.dart @@ -1,77 +1,38 @@ import 'package:flutter/material.dart'; -import 'package:miutem/core/models/asignaturas/asignatura.dart'; import 'package:miutem/screens/asignaturas/detalle_asignatura/models/horario_bloque.dart'; import 'package:miutem/screens/asignaturas/detalle_asignatura/widgets/card_horario.dart'; import 'package:miutem/screens/horario/horario_screen.dart'; import 'package:miutem/styles/styles.dart'; +import 'package:skeletonizer/skeletonizer.dart'; + +final dummyBloques = [ + HorarioBloque(dia: 'Lunes', horaInicio: '8:00', horaFin: '20:00', nombreAsignatura: 'Club de Desarrollo Experimental', sala: 'M8-103'), + HorarioBloque(dia: 'Martes', horaInicio: '8:00', horaFin: '20:00', nombreAsignatura: 'Club de Desarrollo Experimental', sala: 'M8-103'), + HorarioBloque(dia: 'Miércoles', horaInicio: '8:00', horaFin: '20:00', nombreAsignatura: 'Club de Desarrollo Experimental', sala: 'M8-103'), + HorarioBloque(dia: 'Jueves', horaInicio: '8:00', horaFin: '20:00', nombreAsignatura: 'Club de Desarrollo Experimental', sala: 'M8-103'), +]; class SeccionHorario extends StatelessWidget { - final Asignatura asignatura; + + final List bloques; const SeccionHorario({ super.key, - required this.asignatura, + required this.bloques, }); - List _parseHorario() { - final List bloques = []; - - if (asignatura.horario == null || asignatura.horario!.isEmpty) { - return bloques; - } - - // Parse horario string: "lunes | 13:00 - 13:45 / 13:45 - 14:30 || martes | 9:40 - 10:25 / 10:25 - 11:10 || jueves | 11:20 - 12:05 / 12:05 - 12:50" - final dias = asignatura.horario!.split(' || '); - final salas = asignatura.sala?.split(', ') ?? []; - - for (int i = 0; i < dias.length; i++) { - final partes = dias[i].split(' | '); - if (partes.length != 2) continue; - - final dia = partes[0].trim(); - final horariosDelDia = partes[1].trim(); - final bloquesDeTiempo = horariosDelDia.split(' / '); - - if (bloquesDeTiempo.length >= 2) { - final primerBloque = bloquesDeTiempo[0].split(' - '); - final ultimoBloque = bloquesDeTiempo.last.split(' - '); - - if (primerBloque.length == 2 && ultimoBloque.length == 2) { - final horaInicio = primerBloque[0].trim(); - final horaFin = ultimoBloque[1].trim(); - final sala = i < salas.length ? salas[i].trim() : 'Sin sala'; - - bloques.add(HorarioBloque( - dia: dia, - horaInicio: horaInicio, - horaFin: horaFin, - nombreAsignatura: asignatura.nombre, - sala: sala, - )); - } - } - } - - return bloques; - } - @override - Widget build(BuildContext context) { - final bloques = _parseHorario(); - - if (bloques.isEmpty) { - return const SizedBox.shrink(); - } - - return Column( + Widget build(BuildContext context) => Skeletonizer( + enabled: bloques.isEmpty, + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( + Skeleton.keep(child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Horario', - style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600), + style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w800), ), GestureDetector( child: Text( @@ -81,10 +42,11 @@ class SeccionHorario extends StatelessWidget { onTap: () => Navigator.push(context, MaterialPageRoute(builder: (ctx) => const HorarioScreen())), ), ], - ), - Space.xSmall, - ...bloques.map((bloque) => CardHorario(bloque: bloque)), + )), + const Skeleton.keep(child: Space.xSmall), + ...(bloques.isEmpty ? dummyBloques : bloques).map((bloque) => CardHorario(bloque: bloque)) ], - ); - } + ), + ); } + diff --git a/lib/screens/profile/widgets/profile_header.dart b/lib/screens/profile/widgets/profile_header.dart index 5186c36..7bcf75c 100644 --- a/lib/screens/profile/widgets/profile_header.dart +++ b/lib/screens/profile/widgets/profile_header.dart @@ -25,7 +25,6 @@ class _ProfileHeaderState extends State { @override void initState() { super.initState(); - _logger.d("ProfileHeader initialized"); _loadData(); } @@ -46,7 +45,6 @@ class _ProfileHeaderState extends State { } } catch (e) { _logger.e('Error loading carrera: $e'); - } } } diff --git a/pubspec.yaml b/pubspec.yaml index 60e2196..ed98b95 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,6 +63,7 @@ dev_dependencies: flutter: uses-material-design: true assets: + - .env - assets/launcher_icons/prod/icon_splash.png - assets/videos/login_bg.mp4 - assets/images/login_bg.png From d67045c64a8d612cf7f50e7d9ec7da53b65904fd Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 3 Jan 2026 22:16:52 -0300 Subject: [PATCH 15/24] feat: add configuration files and update environment variables --- .env.example | 4 ++-- .gitignore | 2 ++ .idea/.gitignore | 10 ++++++++++ .idea/discord.xml | 7 +++++++ .idea/misc.xml | 6 ++++++ .idea/vcs.xml | 6 ++++++ lib/core/utils/constants.dart | 4 ++-- lib/main.dart | 3 --- macos/Podfile | 5 +++++ macos/Runner.xcodeproj/project.pbxproj | 6 +++--- 10 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/discord.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml diff --git a/.env.example b/.env.example index c5be108..748f1da 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,2 @@ -MI_UTEM_SIGA_DEBUG=https://siga.utem.cl -MI_UTEM_API_DEBUG=https://api.exdev.cl \ No newline at end of file +SIGA_ENDPOINT=https://siga.utem.cl +EXDEV_API_ENDPOINT=https://api.exdev.cl \ No newline at end of file diff --git a/.gitignore b/.gitignore index c01502e..0ea7ca7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # MiUTEM android/app/google-services.json ios/Runner/GoogleService-Info.plist +.env* +!.env.example # Miscellaneous *.class diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..f8c5fc9 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lib/core/utils/constants.dart b/lib/core/utils/constants.dart index ed40394..7d0b06c 100644 --- a/lib/core/utils/constants.dart +++ b/lib/core/utils/constants.dart @@ -5,8 +5,8 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:logger/logger.dart'; import 'package:shared_preferences/shared_preferences.dart'; -final apiUrl = !kDebugMode ? 'https://api.exdev.cl' : (dotenv.env['MI_UTEM_API_DEBUG'] ?? 'https://api.exdev.cl'); -final sigaHost = !kDebugMode ? 'https://siga.utem.cl' : (dotenv.env['MI_UTEM_SIGA_DEBUG'] ?? 'https://siga.utem.cl'); +final apiUrl = dotenv.env['EXDEV_API_ENDPOINT'] ?? 'https://api.exdev.cl'; +final sigaHost = dotenv.env['SIGA_ENDPOINT'] ?? 'https://siga.utem.cl'; const miUtemHost = 'https://mi.utem.cl'; final sigaServiceUri = '$sigaHost/servicios'; // UTEM SIGA API URL diff --git a/lib/main.dart b/lib/main.dart index 8fbc7d9..0a5635a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,10 +1,7 @@ import 'package:adaptive_theme/adaptive_theme.dart'; -import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:get/get.dart'; -import 'package:miutem/core/models/config/user_config.dart'; import 'package:miutem/core/models/preferencia.dart'; import 'package:miutem/core/services/controllers/local_notifications_controller.dart'; import 'package:miutem/core/services/service_manager.dart'; diff --git a/macos/Podfile b/macos/Podfile index 3ffa125..bcffd24 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -43,5 +43,10 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_macos_build_settings(target) + + # Ensure all Pods use a supported macOS deployment target. + target.build_configurations.each do |config| + config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.15' + end end end diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 6a27ce1..69aa0c3 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -578,7 +578,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -666,7 +666,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -716,7 +716,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; From 259d03d896d8a5c000490f38d6ca0fbbaec61b84 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Sat, 3 Jan 2026 22:20:55 -0300 Subject: [PATCH 16/24] feat: add configuration files and update environment variables --- .idea/git_toolbox_prj.xml | 15 ++ .../ephemeral/Flutter-Generated.xcconfig | 10 +- .../ephemeral/flutter_export_environment.sh | 10 +- macos/Podfile.lock | 34 ++-- pubspec.lock | 188 +++++++++--------- 5 files changed, 132 insertions(+), 125 deletions(-) create mode 100644 .idea/git_toolbox_prj.xml diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 780dc4e..4e00358 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -1,13 +1,13 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/Users/fran/.sdk/flutter -FLUTTER_APPLICATION_PATH=/Users/fran/Development/Apps/miutem +FLUTTER_ROOT=/opt/homebrew/share/flutter +FLUTTER_APPLICATION_PATH=/Users/fran/Development/exdevutem/miutem COCOAPODS_PARALLEL_CODE_SIGN=true -FLUTTER_TARGET=/Users/fran/Development/Apps/miutem/lib/main.dart +FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=3.0.0 FLUTTER_BUILD_NUMBER=142 -DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzIuNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MDc3YjRhNGNlMQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzJmMmIxOGJiMA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My44LjE= +DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049ZjZmZjE1MjlmZA==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049MTUyN2FlMGVjNQ==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC40 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false -PACKAGE_CONFIG=/Users/fran/Development/Apps/miutem/.dart_tool/package_config.json +PACKAGE_CONFIG=/Users/fran/Development/exdevutem/miutem/.dart_tool/package_config.json diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index d71e410..13a239d 100755 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -1,14 +1,14 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/fran/.sdk/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/fran/Development/Apps/miutem" +export "FLUTTER_ROOT=/opt/homebrew/share/flutter" +export "FLUTTER_APPLICATION_PATH=/Users/fran/Development/exdevutem/miutem" export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_TARGET=/Users/fran/Development/Apps/miutem/lib/main.dart" +export "FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=3.0.0" export "FLUTTER_BUILD_NUMBER=142" -export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzIuNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MDc3YjRhNGNlMQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzJmMmIxOGJiMA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My44LjE=" +export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049ZjZmZjE1MjlmZA==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049MTUyN2FlMGVjNQ==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC40" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=/Users/fran/Development/Apps/miutem/.dart_tool/package_config.json" +export "PACKAGE_CONFIG=/Users/fran/Development/exdevutem/miutem/.dart_tool/package_config.json" diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 3879a61..24fd097 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -263,14 +263,14 @@ CHECKOUT OPTIONS: :tag: 11.15.0 SPEC CHECKSUMS: - awesome_notifications: 428f5c15a700b117418aed09e29c21c5806fcf69 - awesome_notifications_core: 43438f2e1b0e1dd9da81aaeb1b4af5ec0447af1a - cloud_firestore: 8f6806cab914d2e8b607a6d8abee6ce7fa0880fd - file_saver: 44e6fbf666677faf097302460e214e977fdd977b + awesome_notifications: 7818a3dbad4836238a68df439c06981d9f0b276c + awesome_notifications_core: 1c16f7521b1757f6d39121289573aa3801ba0299 + cloud_firestore: 92bf414ac4a12c1008efa35a70ffe988f90cf740 + file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e - firebase_analytics: c6a3f80cf2e8681b4e6b3402162acf116c4d3a57 - firebase_core: 2af692f4818474ed52eda1ba6aeb448a6a3352af - firebase_remote_config: bb8bc7e5c54dfcf006175eb91f901e4216d2a522 + firebase_analytics: 3091f96bd17636f6da5092a4701ffacf67c6e455 + firebase_core: 7667f880631ae8ad10e3d6567ab7582fe0682326 + firebase_remote_config: 55c407857ec71f2c5406c04e70ec27109fb47276 FirebaseABTesting: 5e9d432834aebf27ab72100d37af44dfbe8d82f7 FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e @@ -287,21 +287,21 @@ SPEC CHECKSUMS: FirebaseRemoteConfig: b496646b82855e174a7f1e354c65e0e913085168 FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa FirebaseSharedSwift: e17c654ef1f1a616b0b33054e663ad1035c8fd40 - flutter_secure_storage_macos: c2754d3483d20bb207bb9e5a14f1b8e771abcdb9 - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54 + FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + package_info_plus: f0052d280d17aa382b932f399edf32507174e870 + path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - share_plus: 1fa619de8392a4398bfaf176d441853922614e89 - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d - url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 - video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 + share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 + url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd + video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a -PODFILE CHECKSUM: 12a580f9c9fdf6d524385f77d7258e098581c672 +PODFILE CHECKSUM: 04282d4ce2394f1e08aa86e9628717a0ee4ed2ce COCOAPODS: 1.16.2 diff --git a/pubspec.lock b/pubspec.lock index 7efc196..043ee8d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: "direct main" description: name: adaptive_theme - sha256: caa49b4c73b681bf12a641dff77aa1383262a00cf38b9d1a25b180e275ba5ab9 + sha256: "5caccff82e40ef6d3ebb28caaa091ab1865b0e35bd2ab2ddccf49cd336331012" url: "https://pub.dev" source: hosted - version: "3.7.0" + version: "3.7.2" analyzer: dependency: transitive description: @@ -205,18 +205,18 @@ packages: dependency: transitive description: name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + sha256: "701dcfc06da0882883a2657c445103380e53e647060ad8d9dfb710c100996608" url: "https://pub.dev" source: hosted - version: "0.3.4+2" + version: "0.3.5+1" crypto: dependency: transitive description: name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" csslib: dependency: transitive description: @@ -285,10 +285,10 @@ packages: dependency: transitive description: name: expressions - sha256: "308a621b602923dd8a0cf3072793b24850d06453eb49c6b698cbda41a282e904" + sha256: f3b0e99563a9a1bde1138e728eb722f292cc7d2aec55d28136c49b1a370306c5 url: "https://pub.dev" source: hosted - version: "0.2.5+2" + version: "0.2.5+3" extended_masked_text: dependency: "direct main" description: @@ -365,10 +365,10 @@ packages: dependency: transitive description: name: firebase_core_platform_interface - sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" + sha256: cccb4f572325dc14904c02fcc7db6323ad62ba02536833dddb5c02cac7341c64 url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.0.2" firebase_core_web: dependency: transitive description: @@ -450,10 +450,10 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: "8321a6d11a8d13977fa780c89de8d257cce3d841eecfb7a4cadffcc4f12d82dc" + sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.7" flutter_secure_storage: dependency: "direct main" description: @@ -516,10 +516,10 @@ packages: dependency: "direct main" description: name: get - sha256: c79eeb4339f1f3deffd9ec912f8a923834bec55f7b49c9e882b8fef2c139d425 + sha256: "5ed34a7925b85336e15d472cc4cfe7d9ebf4ab8e8b9f688585bf6b50f4c3d79a" url: "https://pub.dev" source: hosted - version: "4.7.2" + version: "4.7.3" get_storage: dependency: "direct main" description: @@ -540,10 +540,10 @@ packages: dependency: "direct main" description: name: google_fonts - sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 + sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.3.3" html: dependency: "direct main" description: @@ -556,10 +556,10 @@ packages: dependency: transitive description: name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.6.0" http_parser: dependency: transitive description: @@ -572,10 +572,10 @@ packages: dependency: transitive description: name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + sha256: "492bd52f6c4fbb6ee41f781ff27765ce5f627910e1e0cbecfa3d9add5562604c" url: "https://pub.dev" source: hosted - version: "4.5.4" + version: "4.7.2" intl: dependency: transitive description: @@ -612,26 +612,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -644,10 +644,10 @@ packages: dependency: "direct main" description: name: logger - sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c" + sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3 url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "2.6.2" logging: dependency: transitive description: @@ -676,18 +676,18 @@ packages: dependency: "direct main" description: name: material_symbols_icons - sha256: "7c50901b39d1ad645ee25d920aed008061e1fd541a897b4ebf2c01d966dbf16b" + sha256: "02555a48e1ec02b16e532dfd4ef13c4f6bf7ec7c20230e58e56641a393433dc3" url: "https://pub.dev" source: hosted - version: "4.2815.1" + version: "4.2892.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -708,18 +708,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" + sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" url: "https://pub.dev" source: hosted - version: "8.3.0" + version: "8.3.1" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" path: dependency: transitive description: @@ -756,18 +756,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.2.22" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.5.1" path_provider_linux: dependency: transitive description: @@ -804,10 +804,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "7.0.1" platform: dependency: transitive description: @@ -900,26 +900,26 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.4" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + sha256: "83af5c682796c0f7719c2bbf74792d113e40ae97981b8f266fa84574573556bc" url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.4.18" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "2.5.6" shared_preferences_linux: dependency: transitive description: @@ -956,10 +956,10 @@ packages: dependency: "direct main" description: name: skeletonizer - sha256: eebc03dc86b298e2d7f61e0ebce5713e9dbbc3e786f825909b4591756f196eb6 + sha256: "83157d8e2e41f0252079cfec496281c16e4c63660052dab8d4cd72a206bb7109" url: "https://pub.dev" source: hosted - version: "2.1.0+1" + version: "2.1.2" sky_engine: dependency: transitive description: flutter @@ -981,14 +981,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" sqflite: dependency: "direct main" description: @@ -1001,18 +993,18 @@ packages: dependency: transitive description: name: sqflite_android - sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" + sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2+2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b" + sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" url: "https://pub.dev" source: hosted - version: "2.5.5" + version: "2.5.6" sqflite_darwin: dependency: transitive description: @@ -1073,10 +1065,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.7" typed_data: dependency: transitive description: @@ -1089,10 +1081,10 @@ packages: dependency: transitive description: name: universal_io - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.1" url_launcher: dependency: "direct main" description: @@ -1105,34 +1097,34 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" + sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611" url: "https://pub.dev" source: hosted - version: "6.3.16" + version: "6.3.28" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "6.3.6" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.5" url_launcher_platform_interface: dependency: transitive description: @@ -1153,58 +1145,58 @@ packages: dependency: transitive description: name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" uuid: dependency: transitive description: name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.5.2" vector_math: dependency: "direct main" description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" video_player: dependency: "direct main" description: name: video_player - sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" + sha256: "096bc28ce10d131be80dfb00c223024eb0fba301315a406728ab43dd99c45bdf" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.10.1" video_player_android: dependency: transitive description: name: video_player_android - sha256: "9d5af2d233ba69df803dcf2f31e66d9a4c6206f2d96178df06b09b0ec3056b39" + sha256: ee4fd520b0cafa02e4a867a0f882092e727cdaa1a2d24762171e787f8a502b0a url: "https://pub.dev" source: hosted - version: "2.8.9" + version: "2.9.1" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: "9fedd55023249f3a02738c195c906b4e530956191febf0838e37d0dac912f953" + sha256: e4d33b79a064498c6eb3a6a492b6a5012573d4943c28d566caf1a6c0840fe78d url: "https://pub.dev" source: hosted - version: "2.8.0" + version: "2.8.8" video_player_platform_interface: dependency: transitive description: name: video_player_platform_interface - sha256: cf2a1d29a284db648fd66cbd18aacc157f9862d77d2cc790f6f9678a46c1db5a + sha256: "57c5d73173f76d801129d0531c2774052c5a7c11ccb962f1830630decd9f24ec" url: "https://pub.dev" source: hosted - version: "6.4.0" + version: "6.6.0" video_player_web: dependency: transitive description: @@ -1217,18 +1209,18 @@ packages: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "15.0.2" watcher: dependency: transitive description: name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" + sha256: f52385d4f73589977c80797e60fe51014f7f2b957b5e9a62c3f6ada439889249 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.0" web: dependency: transitive description: @@ -1241,10 +1233,10 @@ packages: dependency: transitive description: name: win32 - sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e url: "https://pub.dev" source: hosted - version: "5.14.0" + version: "5.15.0" xdg_directories: dependency: transitive description: @@ -1257,10 +1249,10 @@ packages: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "6.6.1" xpath_selector: dependency: transitive description: @@ -1286,5 +1278,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.8.0 <4.0.0" - flutter: ">=3.31.0-0.0.pre" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0" From 21d0877a20df08056ecd20bfe51b8707456fea04 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Tue, 10 Feb 2026 21:37:11 -0300 Subject: [PATCH 17/24] feat: update dependencies and remove deprecated configurations --- .idea/misc.xml | 1 - ios/Podfile | 6 +- ios/Podfile.lock | 1521 +++++++++++++++-- ios/Runner.xcodeproj/project.pbxproj | 18 - macos/Flutter/GeneratedPluginRegistrant.swift | 2 - .../ephemeral/Flutter-Generated.xcconfig | 2 +- .../ephemeral/flutter_export_environment.sh | 2 +- macos/Podfile | 4 - macos/Podfile.lock | 1501 ++++++++++++++-- macos/Runner.xcodeproj/project.pbxproj | 18 - pubspec.lock | 132 +- pubspec.yaml | 10 +- 12 files changed, 2868 insertions(+), 349 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index f8c5fc9..212ae46 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/ios/Podfile b/ios/Podfile index 8295bd3..e5f5d0b 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '13.0' +platform :ios, '16.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -31,10 +31,6 @@ target 'Runner' do use_frameworks! use_modular_headers! - pod 'FirebaseFirestore', - :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', - :tag => '11.15.0' - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do inherit! :search_paths diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8d26435..d0ac3ed 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,129 +1,1320 @@ PODS: + - abseil/algorithm (1.20240722.0): + - abseil/algorithm/algorithm (= 1.20240722.0) + - abseil/algorithm/container (= 1.20240722.0) + - abseil/algorithm/algorithm (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/algorithm/container (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base (1.20240722.0): + - abseil/base/atomic_hook (= 1.20240722.0) + - abseil/base/base (= 1.20240722.0) + - abseil/base/base_internal (= 1.20240722.0) + - abseil/base/config (= 1.20240722.0) + - abseil/base/core_headers (= 1.20240722.0) + - abseil/base/cycleclock_internal (= 1.20240722.0) + - abseil/base/dynamic_annotations (= 1.20240722.0) + - abseil/base/endian (= 1.20240722.0) + - abseil/base/errno_saver (= 1.20240722.0) + - abseil/base/fast_type_id (= 1.20240722.0) + - abseil/base/log_severity (= 1.20240722.0) + - abseil/base/malloc_internal (= 1.20240722.0) + - abseil/base/no_destructor (= 1.20240722.0) + - abseil/base/nullability (= 1.20240722.0) + - abseil/base/poison (= 1.20240722.0) + - abseil/base/prefetch (= 1.20240722.0) + - abseil/base/pretty_function (= 1.20240722.0) + - abseil/base/raw_logging_internal (= 1.20240722.0) + - abseil/base/spinlock_wait (= 1.20240722.0) + - abseil/base/strerror (= 1.20240722.0) + - abseil/base/throw_delegate (= 1.20240722.0) + - abseil/base/atomic_hook (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/base (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/cycleclock_internal + - abseil/base/dynamic_annotations + - abseil/base/log_severity + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/spinlock_wait + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/base_internal (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/config (1.20240722.0): + - abseil/xcprivacy + - abseil/base/core_headers (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/cycleclock_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/xcprivacy + - abseil/base/dynamic_annotations (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/endian (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/xcprivacy + - abseil/base/errno_saver (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/fast_type_id (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/log_severity (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/malloc_internal (1.20240722.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/base/no_destructor (1.20240722.0): + - abseil/base/config + - abseil/base/nullability + - abseil/xcprivacy + - abseil/base/nullability (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/poison (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/xcprivacy + - abseil/base/prefetch (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/pretty_function (1.20240722.0): + - abseil/xcprivacy + - abseil/base/raw_logging_internal (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/log_severity + - abseil/xcprivacy + - abseil/base/spinlock_wait (1.20240722.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/xcprivacy + - abseil/base/strerror (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/xcprivacy + - abseil/base/throw_delegate (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/cleanup/cleanup (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/cleanup/cleanup_internal + - abseil/xcprivacy + - abseil/cleanup/cleanup_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/common (1.20240722.0): + - abseil/meta/type_traits + - abseil/types/optional + - abseil/xcprivacy + - abseil/container/common_policy_traits (1.20240722.0): + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/compressed_tuple (1.20240722.0): + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/container_memory (1.20240722.0): + - abseil/base/config + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/fixed_array (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/xcprivacy + - abseil/container/flat_hash_map (1.20240722.0): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_container_defaults + - abseil/container/raw_hash_map + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/flat_hash_set (1.20240722.0): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_container_defaults + - abseil/container/raw_hash_set + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/hash_container_defaults (1.20240722.0): + - abseil/base/config + - abseil/container/hash_function_defaults + - abseil/xcprivacy + - abseil/container/hash_function_defaults (1.20240722.0): + - abseil/base/config + - abseil/container/common + - abseil/hash/hash + - abseil/meta/type_traits + - abseil/strings/cord + - abseil/strings/strings + - abseil/xcprivacy + - abseil/container/hash_policy_traits (1.20240722.0): + - abseil/container/common_policy_traits + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/hashtable_debug_hooks (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/container/hashtablez_sampler (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/memory/memory + - abseil/profiling/exponential_biased + - abseil/profiling/sample_recorder + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/inlined_vector (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/inlined_vector_internal + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/inlined_vector_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/span + - abseil/xcprivacy + - abseil/container/layout (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/demangle_internal + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/raw_hash_map (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/container_memory + - abseil/container/raw_hash_set + - abseil/xcprivacy + - abseil/container/raw_hash_set (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/endian + - abseil/base/prefetch + - abseil/base/raw_logging_internal + - abseil/container/common + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/hash_policy_traits + - abseil/container/hashtable_debug_hooks + - abseil/container/hashtablez_sampler + - abseil/hash/hash + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/crc/cpu_detect (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/xcprivacy + - abseil/crc/crc32c (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/crc/cpu_detect + - abseil/crc/crc_internal + - abseil/crc/non_temporal_memcpy + - abseil/strings/str_format + - abseil/strings/strings + - abseil/xcprivacy + - abseil/crc/crc_cord_state (1.20240722.0): + - abseil/base/config + - abseil/base/no_destructor + - abseil/crc/crc32c + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/crc/crc_internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/base/raw_logging_internal + - abseil/crc/cpu_detect + - abseil/memory/memory + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/crc/non_temporal_arm_intrinsics (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/crc/non_temporal_memcpy (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/crc/non_temporal_arm_intrinsics + - abseil/xcprivacy + - abseil/debugging/bounded_utf8_length_sequence (1.20240722.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/debugging/debugging_internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/errno_saver + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/debugging/decode_rust_punycode (1.20240722.0): + - abseil/base/config + - abseil/base/nullability + - abseil/debugging/bounded_utf8_length_sequence + - abseil/debugging/utf8_for_code_point + - abseil/xcprivacy + - abseil/debugging/demangle_internal (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/debugging/demangle_rust + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/debugging/demangle_rust (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/decode_rust_punycode + - abseil/xcprivacy + - abseil/debugging/examine_stack (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/xcprivacy + - abseil/debugging/stacktrace (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/xcprivacy + - abseil/debugging/symbolize (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/debugging/demangle_internal + - abseil/strings/strings + - abseil/xcprivacy + - abseil/debugging/utf8_for_code_point (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/flags/commandlineflag (1.20240722.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/flags/commandlineflag_internal + - abseil/strings/strings + - abseil/types/optional + - abseil/xcprivacy + - abseil/flags/commandlineflag_internal (1.20240722.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/xcprivacy + - abseil/flags/config (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/path_util + - abseil/flags/program_name + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/flags/flag (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/commandlineflag + - abseil/flags/config + - abseil/flags/flag_internal + - abseil/flags/reflection + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/flag_internal (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/flags/config + - abseil/flags/marshalling + - abseil/flags/reflection + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/utility/utility + - abseil/xcprivacy + - abseil/flags/marshalling (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/numeric/int128 + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/xcprivacy + - abseil/flags/path_util (1.20240722.0): + - abseil/base/config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/private_handle_accessor (1.20240722.0): + - abseil/base/config + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/program_name (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/path_util + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/flags/reflection (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/container/flat_hash_map + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/flags/config + - abseil/flags/private_handle_accessor + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/functional/any_invocable (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/functional/bind_front (1.20240722.0): + - abseil/base/base_internal + - abseil/container/compressed_tuple + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/functional/function_ref (1.20240722.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/functional/any_invocable + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/hash/city (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/xcprivacy + - abseil/hash/hash (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/container/fixed_array + - abseil/functional/function_ref + - abseil/hash/city + - abseil/hash/low_level_hash + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/types/optional + - abseil/types/variant + - abseil/utility/utility + - abseil/xcprivacy + - abseil/hash/low_level_hash (1.20240722.0): + - abseil/base/config + - abseil/base/endian + - abseil/base/prefetch + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/log/absl_check (1.20240722.0): + - abseil/log/internal/check_impl + - abseil/xcprivacy + - abseil/log/absl_log (1.20240722.0): + - abseil/log/internal/log_impl + - abseil/xcprivacy + - abseil/log/absl_vlog_is_on (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/log/internal/vlog_config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/check (1.20240722.0): + - abseil/log/internal/check_impl + - abseil/log/internal/check_op + - abseil/log/internal/conditions + - abseil/log/internal/log_message + - abseil/log/internal/strip + - abseil/xcprivacy + - abseil/log/globals (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/hash/hash + - abseil/log/internal/vlog_config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/append_truncated (1.20240722.0): + - abseil/base/config + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/check_impl (1.20240722.0): + - abseil/base/core_headers + - abseil/log/internal/check_op + - abseil/log/internal/conditions + - abseil/log/internal/log_message + - abseil/log/internal/strip + - abseil/xcprivacy + - abseil/log/internal/check_op (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/log/internal/nullguard + - abseil/log/internal/nullstream + - abseil/log/internal/strip + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/conditions (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/log/internal/voidify + - abseil/xcprivacy + - abseil/log/internal/config (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/log/internal/fnmatch (1.20240722.0): + - abseil/base/config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/format (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/log/internal/append_truncated + - abseil/log/internal/config + - abseil/log/internal/globals + - abseil/strings/str_format + - abseil/strings/strings + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/globals (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/strings/strings + - abseil/time/time + - abseil/xcprivacy + - abseil/log/internal/log_impl (1.20240722.0): + - abseil/log/absl_vlog_is_on + - abseil/log/internal/conditions + - abseil/log/internal/log_message + - abseil/log/internal/strip + - abseil/xcprivacy + - abseil/log/internal/log_message (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/base/strerror + - abseil/container/inlined_vector + - abseil/debugging/examine_stack + - abseil/log/globals + - abseil/log/internal/append_truncated + - abseil/log/internal/format + - abseil/log/internal/globals + - abseil/log/internal/log_sink_set + - abseil/log/internal/nullguard + - abseil/log/internal/proto + - abseil/log/log_entry + - abseil/log/log_sink + - abseil/log/log_sink_registry + - abseil/memory/memory + - abseil/strings/strings + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/log_sink_set (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/no_destructor + - abseil/base/raw_logging_internal + - abseil/cleanup/cleanup + - abseil/log/globals + - abseil/log/internal/config + - abseil/log/internal/globals + - abseil/log/log_entry + - abseil/log/log_sink + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/nullguard (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/log/internal/nullstream (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/proto (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/strip (1.20240722.0): + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/log/internal/log_message + - abseil/log/internal/nullstream + - abseil/xcprivacy + - abseil/log/internal/vlog_config (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/log/internal/fnmatch + - abseil/memory/memory + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/types/optional + - abseil/xcprivacy + - abseil/log/internal/voidify (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/log/log (1.20240722.0): + - abseil/log/internal/log_impl + - abseil/log/vlog_is_on + - abseil/xcprivacy + - abseil/log/log_entry (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/log/internal/config + - abseil/strings/strings + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/log/log_sink (1.20240722.0): + - abseil/base/config + - abseil/log/log_entry + - abseil/xcprivacy + - abseil/log/log_sink_registry (1.20240722.0): + - abseil/base/config + - abseil/log/internal/log_sink_set + - abseil/log/log_sink + - abseil/xcprivacy + - abseil/log/vlog_is_on (1.20240722.0): + - abseil/log/absl_vlog_is_on + - abseil/xcprivacy + - abseil/memory (1.20240722.0): + - abseil/memory/memory (= 1.20240722.0) + - abseil/memory/memory (1.20240722.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/meta (1.20240722.0): + - abseil/meta/type_traits (= 1.20240722.0) + - abseil/meta/type_traits (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/numeric/bits (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/numeric/int128 (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/bits + - abseil/types/compare + - abseil/xcprivacy + - abseil/numeric/representation (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/profiling/exponential_biased (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/profiling/sample_recorder (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/xcprivacy + - abseil/random/bit_gen_ref (1.20240722.0): + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/random + - abseil/xcprivacy + - abseil/random/distributions (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/internal/fastmath + - abseil/random/internal/generate_real + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/traits + - abseil/random/internal/uniform_helper + - abseil/random/internal/wide_multiply + - abseil/strings/strings + - abseil/xcprivacy + - abseil/random/internal/distribution_caller (1.20240722.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/utility/utility + - abseil/xcprivacy + - abseil/random/internal/fast_uniform_bits (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/fastmath (1.20240722.0): + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/random/internal/generate_real (1.20240722.0): + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/fastmath + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/iostream_state_saver (1.20240722.0): + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/random/internal/nonsecure_base (1.20240722.0): + - abseil/base/core_headers + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/pcg_engine (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/fastmath + - abseil/random/internal/iostream_state_saver + - abseil/xcprivacy + - abseil/random/internal/platform (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/random/internal/pool_urbg (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/random/internal/randen + - abseil/random/internal/seed_material + - abseil/random/internal/traits + - abseil/random/seed_gen_exception + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/randen (1.20240722.0): + - abseil/base/raw_logging_internal + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes + - abseil/random/internal/randen_slow + - abseil/xcprivacy + - abseil/random/internal/randen_engine (1.20240722.0): + - abseil/base/endian + - abseil/meta/type_traits + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/randen + - abseil/xcprivacy + - abseil/random/internal/randen_hwaes (1.20240722.0): + - abseil/base/config + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes_impl + - abseil/xcprivacy + - abseil/random/internal/randen_hwaes_impl (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/xcprivacy + - abseil/random/internal/randen_slow (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/xcprivacy + - abseil/random/internal/salted_seed_seq (1.20240722.0): + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/seed_material + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/seed_material (1.20240722.0): + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/random/internal/fast_uniform_bits + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/traits (1.20240722.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/random/internal/uniform_helper (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/wide_multiply (1.20240722.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/random (1.20240722.0): + - abseil/random/distributions + - abseil/random/internal/nonsecure_base + - abseil/random/internal/pcg_engine + - abseil/random/internal/pool_urbg + - abseil/random/internal/randen_engine + - abseil/random/seed_sequences + - abseil/xcprivacy + - abseil/random/seed_gen_exception (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/random/seed_sequences (1.20240722.0): + - abseil/base/config + - abseil/base/nullability + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/random/seed_gen_exception + - abseil/strings/string_view + - abseil/types/span + - abseil/xcprivacy + - abseil/status/status (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/strerror + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/functional/function_ref + - abseil/memory/memory + - abseil/strings/cord + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/status/statusor (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/status/status + - abseil/strings/has_ostream_operator + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/variant + - abseil/utility/utility + - abseil/xcprivacy + - abseil/strings/charset (1.20240722.0): + - abseil/base/core_headers + - abseil/strings/string_view + - abseil/xcprivacy + - abseil/strings/cord (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/crc/crc32c + - abseil/crc/crc_cord_state + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_info + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_scope + - abseil/strings/cordz_update_tracker + - abseil/strings/internal + - abseil/strings/strings + - abseil/types/compare + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cord_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/inlined_vector + - abseil/container/layout + - abseil/crc/crc_cord_state + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cordz_functions (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/profiling/exponential_biased + - abseil/xcprivacy + - abseil/strings/cordz_handle (1.20240722.0): + - abseil/base/config + - abseil/base/no_destructor + - abseil/base/raw_logging_internal + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/strings/cordz_info (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_handle + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_tracker + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cordz_statistics (1.20240722.0): + - abseil/base/config + - abseil/strings/cordz_update_tracker + - abseil/xcprivacy + - abseil/strings/cordz_update_scope (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/cord_internal + - abseil/strings/cordz_info + - abseil/strings/cordz_update_tracker + - abseil/xcprivacy + - abseil/strings/cordz_update_tracker (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/strings/has_ostream_operator (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/strings/internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/strings/str_format (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/strings/str_format_internal + - abseil/strings/string_view + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/str_format_internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/container/fixed_array + - abseil/container/inlined_vector + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/numeric/representation + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/utility/utility + - abseil/xcprivacy + - abseil/strings/string_view (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/throw_delegate + - abseil/xcprivacy + - abseil/strings/strings (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/charset + - abseil/strings/internal + - abseil/strings/string_view + - abseil/xcprivacy + - abseil/synchronization/graphcycles_internal (1.20240722.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/synchronization/kernel_timeout_internal (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/time/time + - abseil/xcprivacy + - abseil/synchronization/synchronization (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/synchronization/graphcycles_internal + - abseil/synchronization/kernel_timeout_internal + - abseil/time/time + - abseil/xcprivacy + - abseil/time (1.20240722.0): + - abseil/time/internal (= 1.20240722.0) + - abseil/time/time (= 1.20240722.0) + - abseil/time/internal (1.20240722.0): + - abseil/time/internal/cctz (= 1.20240722.0) + - abseil/time/internal/cctz (1.20240722.0): + - abseil/time/internal/cctz/civil_time (= 1.20240722.0) + - abseil/time/internal/cctz/time_zone (= 1.20240722.0) + - abseil/time/internal/cctz/civil_time (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/time/internal/cctz/time_zone (1.20240722.0): + - abseil/base/config + - abseil/time/internal/cctz/civil_time + - abseil/xcprivacy + - abseil/time/time (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/time/internal/cctz/civil_time + - abseil/time/internal/cctz/time_zone + - abseil/types/optional + - abseil/xcprivacy + - abseil/types (1.20240722.0): + - abseil/types/any (= 1.20240722.0) + - abseil/types/bad_any_cast (= 1.20240722.0) + - abseil/types/bad_any_cast_impl (= 1.20240722.0) + - abseil/types/bad_optional_access (= 1.20240722.0) + - abseil/types/bad_variant_access (= 1.20240722.0) + - abseil/types/compare (= 1.20240722.0) + - abseil/types/optional (= 1.20240722.0) + - abseil/types/span (= 1.20240722.0) + - abseil/types/variant (= 1.20240722.0) + - abseil/types/any (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/types/bad_any_cast + - abseil/utility/utility + - abseil/xcprivacy + - abseil/types/bad_any_cast (1.20240722.0): + - abseil/base/config + - abseil/types/bad_any_cast_impl + - abseil/xcprivacy + - abseil/types/bad_any_cast_impl (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/bad_optional_access (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/bad_variant_access (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/compare (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/types/optional (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/bad_optional_access + - abseil/utility/utility + - abseil/xcprivacy + - abseil/types/span (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/throw_delegate + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/types/variant (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/bad_variant_access + - abseil/utility/utility + - abseil/xcprivacy + - abseil/utility/utility (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/xcprivacy (1.20240722.0) - awesome_notifications (0.10.0): - Flutter - IosAwnCore (~> 0.10.0) - awesome_notifications_core (0.0.1): - Flutter - - cloud_firestore (5.6.12): - - Firebase/Firestore (= 11.15.0) + - BoringSSL-GRPC (0.0.37): + - BoringSSL-GRPC/Implementation (= 0.0.37) + - BoringSSL-GRPC/Interface (= 0.0.37) + - BoringSSL-GRPC/Implementation (0.0.37): + - BoringSSL-GRPC/Interface (= 0.0.37) + - BoringSSL-GRPC/Interface (0.0.37) + - cloud_firestore (6.1.1): + - Firebase/Firestore (= 12.6.0) - firebase_core - Flutter - file_saver (0.0.1): - Flutter - - Firebase/Analytics (11.15.0): - - Firebase/Core - - Firebase/Core (11.15.0): + - Firebase/CoreOnly (12.6.0): + - FirebaseCore (~> 12.6.0) + - Firebase/Firestore (12.6.0): - Firebase/CoreOnly - - FirebaseAnalytics (~> 11.15.0) - - Firebase/CoreOnly (11.15.0): - - FirebaseCore (~> 11.15.0) - - Firebase/Firestore (11.15.0): + - FirebaseFirestore (~> 12.6.0) + - Firebase/RemoteConfig (12.6.0): - Firebase/CoreOnly - - FirebaseFirestore (~> 11.15.0) - - Firebase/RemoteConfig (11.15.0): - - Firebase/CoreOnly - - FirebaseRemoteConfig (~> 11.15.0) - - firebase_analytics (11.6.0): - - Firebase/Analytics (= 11.15.0) + - FirebaseRemoteConfig (~> 12.6.0) + - firebase_analytics (12.1.0): - firebase_core + - FirebaseAnalytics (= 12.6.0) - Flutter - - firebase_core (3.15.2): - - Firebase/CoreOnly (= 11.15.0) + - firebase_core (4.3.0): + - Firebase/CoreOnly (= 12.6.0) - Flutter - - firebase_remote_config (5.5.0): - - Firebase/RemoteConfig (= 11.15.0) + - firebase_remote_config (6.1.3): + - Firebase/RemoteConfig (= 12.6.0) - firebase_core - Flutter - - FirebaseABTesting (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseAnalytics (11.15.0): - - FirebaseAnalytics/Default (= 11.15.0) - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) + - FirebaseABTesting (12.6.0): + - FirebaseCore (~> 12.6.0) + - FirebaseAnalytics (12.6.0): + - FirebaseAnalytics/Default (= 12.6.0) + - FirebaseCore (~> 12.6.0) + - FirebaseInstallations (~> 12.6.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseAnalytics/Default (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - GoogleAppMeasurement/Default (= 11.15.0) + - FirebaseAnalytics/Default (12.6.0): + - FirebaseCore (~> 12.6.0) + - FirebaseInstallations (~> 12.6.0) + - GoogleAppMeasurement/Default (= 12.6.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseCore (11.15.0): - - FirebaseCoreInternal (~> 11.15.0) + - FirebaseAppCheckInterop (12.6.0) + - FirebaseCore (12.6.0): + - FirebaseCoreInternal (~> 12.6.0) - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/Logger (~> 8.1) - - FirebaseCoreExtension (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseCoreInternal (11.15.0): + - FirebaseCoreExtension (12.6.0): + - FirebaseCore (~> 12.6.0) + - FirebaseCoreInternal (12.6.0): - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseFirestore (11.15.0): - - FirebaseFirestoreBinary (= 11.15.0) - - FirebaseFirestoreAbseilBinary (1.2024072200.0) - - FirebaseFirestoreBinary (11.15.0): - - FirebaseCore (= 11.15.0) - - FirebaseCoreExtension (= 11.15.0) - - FirebaseFirestoreInternalBinary (= 11.15.0) - - FirebaseSharedSwift (= 11.15.0) - - FirebaseFirestoreGRPCBoringSSLBinary (1.69.0) - - FirebaseFirestoreGRPCCoreBinary (1.69.0): - - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) - - FirebaseFirestoreGRPCBoringSSLBinary (= 1.69.0) - - FirebaseFirestoreGRPCCPPBinary (1.69.0): - - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) - - FirebaseFirestoreGRPCCoreBinary (= 1.69.0) - - FirebaseFirestoreInternalBinary (11.15.0): - - FirebaseCore (= 11.15.0) - - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) - - FirebaseFirestoreGRPCCPPBinary (= 1.69.0) + - FirebaseFirestore (12.6.0): + - FirebaseCore (~> 12.6.0) + - FirebaseCoreExtension (~> 12.6.0) + - FirebaseFirestoreInternal (~> 12.6.0) + - FirebaseSharedSwift (~> 12.6.0) + - FirebaseFirestoreInternal (12.6.0): + - abseil/algorithm (~> 1.20240722.0) + - abseil/base (~> 1.20240722.0) + - abseil/container/flat_hash_map (~> 1.20240722.0) + - abseil/memory (~> 1.20240722.0) + - abseil/meta (~> 1.20240722.0) + - abseil/strings/strings (~> 1.20240722.0) + - abseil/time (~> 1.20240722.0) + - abseil/types (~> 1.20240722.0) + - FirebaseAppCheckInterop (~> 12.6.0) + - FirebaseCore (~> 12.6.0) + - "gRPC-C++ (~> 1.69.0)" + - gRPC-Core (~> 1.69.0) - leveldb-library (~> 1.22) - nanopb (~> 3.30910.0) - - FirebaseInstallations (11.15.0): - - FirebaseCore (~> 11.15.0) + - FirebaseInstallations (12.6.0): + - FirebaseCore (~> 12.6.0) - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseRemoteConfig (11.15.0): - - FirebaseABTesting (~> 11.0) - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - FirebaseRemoteConfigInterop (~> 11.0) - - FirebaseSharedSwift (~> 11.0) + - FirebaseRemoteConfig (12.6.0): + - FirebaseABTesting (~> 12.6.0) + - FirebaseCore (~> 12.6.0) + - FirebaseInstallations (~> 12.6.0) + - FirebaseRemoteConfigInterop (~> 12.6.0) + - FirebaseSharedSwift (~> 12.6.0) - GoogleUtilities/Environment (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseRemoteConfigInterop (11.15.0) - - FirebaseSharedSwift (11.15.0) + - FirebaseRemoteConfigInterop (12.6.0) + - FirebaseSharedSwift (12.6.0) - Flutter (1.0.0) - flutter_native_splash (2.4.3): - Flutter - flutter_secure_storage (6.0.0): - Flutter - - GoogleAdsOnDeviceConversion (2.1.0): + - GoogleAdsOnDeviceConversion (3.2.0): + - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/Logger (~> 8.1) - GoogleUtilities/Network (~> 8.1) - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Core (11.15.0): + - GoogleAppMeasurement/Core (12.6.0): - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Default (11.15.0): - - GoogleAdsOnDeviceConversion (= 2.1.0) - - GoogleAppMeasurement/Core (= 11.15.0) - - GoogleAppMeasurement/IdentitySupport (= 11.15.0) + - GoogleAppMeasurement/Default (12.6.0): + - GoogleAdsOnDeviceConversion (~> 3.2.0) + - GoogleAppMeasurement/Core (= 12.6.0) + - GoogleAppMeasurement/IdentitySupport (= 12.6.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/IdentitySupport (11.15.0): - - GoogleAppMeasurement/Core (= 11.15.0) + - GoogleAppMeasurement/IdentitySupport (12.6.0): + - GoogleAppMeasurement/Core (= 12.6.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) @@ -156,6 +1347,98 @@ PODS: - GoogleUtilities/UserDefaults (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy + - "gRPC-C++ (1.69.0)": + - "gRPC-C++/Implementation (= 1.69.0)" + - "gRPC-C++/Interface (= 1.69.0)" + - "gRPC-C++/Implementation (1.69.0)": + - abseil/algorithm/container (~> 1.20240722.0) + - abseil/base/base (~> 1.20240722.0) + - abseil/base/config (~> 1.20240722.0) + - abseil/base/core_headers (~> 1.20240722.0) + - abseil/base/log_severity (~> 1.20240722.0) + - abseil/base/no_destructor (~> 1.20240722.0) + - abseil/cleanup/cleanup (~> 1.20240722.0) + - abseil/container/flat_hash_map (~> 1.20240722.0) + - abseil/container/flat_hash_set (~> 1.20240722.0) + - abseil/container/inlined_vector (~> 1.20240722.0) + - abseil/flags/flag (~> 1.20240722.0) + - abseil/flags/marshalling (~> 1.20240722.0) + - abseil/functional/any_invocable (~> 1.20240722.0) + - abseil/functional/bind_front (~> 1.20240722.0) + - abseil/functional/function_ref (~> 1.20240722.0) + - abseil/hash/hash (~> 1.20240722.0) + - abseil/log/absl_check (~> 1.20240722.0) + - abseil/log/absl_log (~> 1.20240722.0) + - abseil/log/check (~> 1.20240722.0) + - abseil/log/globals (~> 1.20240722.0) + - abseil/log/log (~> 1.20240722.0) + - abseil/memory/memory (~> 1.20240722.0) + - abseil/meta/type_traits (~> 1.20240722.0) + - abseil/numeric/bits (~> 1.20240722.0) + - abseil/random/bit_gen_ref (~> 1.20240722.0) + - abseil/random/distributions (~> 1.20240722.0) + - abseil/random/random (~> 1.20240722.0) + - abseil/status/status (~> 1.20240722.0) + - abseil/status/statusor (~> 1.20240722.0) + - abseil/strings/cord (~> 1.20240722.0) + - abseil/strings/str_format (~> 1.20240722.0) + - abseil/strings/strings (~> 1.20240722.0) + - abseil/synchronization/synchronization (~> 1.20240722.0) + - abseil/time/time (~> 1.20240722.0) + - abseil/types/optional (~> 1.20240722.0) + - abseil/types/span (~> 1.20240722.0) + - abseil/types/variant (~> 1.20240722.0) + - abseil/utility/utility (~> 1.20240722.0) + - "gRPC-C++/Interface (= 1.69.0)" + - "gRPC-C++/Privacy (= 1.69.0)" + - gRPC-Core (= 1.69.0) + - "gRPC-C++/Interface (1.69.0)" + - "gRPC-C++/Privacy (1.69.0)" + - gRPC-Core (1.69.0): + - gRPC-Core/Implementation (= 1.69.0) + - gRPC-Core/Interface (= 1.69.0) + - gRPC-Core/Implementation (1.69.0): + - abseil/algorithm/container (~> 1.20240722.0) + - abseil/base/base (~> 1.20240722.0) + - abseil/base/config (~> 1.20240722.0) + - abseil/base/core_headers (~> 1.20240722.0) + - abseil/base/log_severity (~> 1.20240722.0) + - abseil/base/no_destructor (~> 1.20240722.0) + - abseil/cleanup/cleanup (~> 1.20240722.0) + - abseil/container/flat_hash_map (~> 1.20240722.0) + - abseil/container/flat_hash_set (~> 1.20240722.0) + - abseil/container/inlined_vector (~> 1.20240722.0) + - abseil/flags/flag (~> 1.20240722.0) + - abseil/flags/marshalling (~> 1.20240722.0) + - abseil/functional/any_invocable (~> 1.20240722.0) + - abseil/functional/bind_front (~> 1.20240722.0) + - abseil/functional/function_ref (~> 1.20240722.0) + - abseil/hash/hash (~> 1.20240722.0) + - abseil/log/check (~> 1.20240722.0) + - abseil/log/globals (~> 1.20240722.0) + - abseil/log/log (~> 1.20240722.0) + - abseil/memory/memory (~> 1.20240722.0) + - abseil/meta/type_traits (~> 1.20240722.0) + - abseil/numeric/bits (~> 1.20240722.0) + - abseil/random/bit_gen_ref (~> 1.20240722.0) + - abseil/random/distributions (~> 1.20240722.0) + - abseil/random/random (~> 1.20240722.0) + - abseil/status/status (~> 1.20240722.0) + - abseil/status/statusor (~> 1.20240722.0) + - abseil/strings/cord (~> 1.20240722.0) + - abseil/strings/str_format (~> 1.20240722.0) + - abseil/strings/strings (~> 1.20240722.0) + - abseil/synchronization/synchronization (~> 1.20240722.0) + - abseil/time/time (~> 1.20240722.0) + - abseil/types/optional (~> 1.20240722.0) + - abseil/types/span (~> 1.20240722.0) + - abseil/types/variant (~> 1.20240722.0) + - abseil/utility/utility (~> 1.20240722.0) + - BoringSSL-GRPC (= 0.0.37) + - gRPC-Core/Interface (= 1.69.0) + - gRPC-Core/Privacy (= 1.69.0) + - gRPC-Core/Interface (1.69.0) + - gRPC-Core/Privacy (1.69.0) - IosAwnCore (0.10.0) - leveldb-library (1.22.6) - nanopb (3.30910.0): @@ -191,7 +1474,6 @@ DEPENDENCIES: - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`) - - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `11.15.0`) - Flutter (from `Flutter`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) @@ -205,18 +1487,17 @@ DEPENDENCIES: SPEC REPOS: trunk: + - abseil + - BoringSSL-GRPC - Firebase - FirebaseABTesting - FirebaseAnalytics + - FirebaseAppCheckInterop - FirebaseCore - FirebaseCoreExtension - FirebaseCoreInternal - - FirebaseFirestoreAbseilBinary - - FirebaseFirestoreBinary - - FirebaseFirestoreGRPCBoringSSLBinary - - FirebaseFirestoreGRPCCoreBinary - - FirebaseFirestoreGRPCCPPBinary - - FirebaseFirestoreInternalBinary + - FirebaseFirestore + - FirebaseFirestoreInternal - FirebaseInstallations - FirebaseRemoteConfig - FirebaseRemoteConfigInterop @@ -224,6 +1505,8 @@ SPEC REPOS: - GoogleAdsOnDeviceConversion - GoogleAppMeasurement - GoogleUtilities + - "gRPC-C++" + - gRPC-Core - IosAwnCore - leveldb-library - nanopb @@ -244,9 +1527,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_core/ios" firebase_remote_config: :path: ".symlinks/plugins/firebase_remote_config/ios" - FirebaseFirestore: - :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.15.0 Flutter: :path: Flutter flutter_native_splash: @@ -268,54 +1548,49 @@ EXTERNAL SOURCES: video_player_avfoundation: :path: ".symlinks/plugins/video_player_avfoundation/darwin" -CHECKOUT OPTIONS: - FirebaseFirestore: - :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.15.0 - SPEC CHECKSUMS: - awesome_notifications: dd5518ff1c80be03d4f1c40f04da9d9cc2a37af5 - awesome_notifications_core: d02eed89738fa362d56cbd372850e9adcd2c6bef - cloud_firestore: 97e42181866db3cba3fe3935895ab779b6acacd6 - file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 - Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e - firebase_analytics: bf93e20703c95030404d6ddbb1adf05bf5c3885b - firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c - firebase_remote_config: 395d35aa770405fd0121c97382671371ea00734a - FirebaseABTesting: 5e9d432834aebf27ab72100d37af44dfbe8d82f7 - FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae - FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e - FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435 - FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 - FirebaseFirestore: 736c2099af30aed7728d5789059fee1914b4d213 - FirebaseFirestoreAbseilBinary: 4cfa8823cedc1b774843e04fe578ad279b387f97 - FirebaseFirestoreBinary: 43abe19da1cb39a10171786e5a2e18fa9d57b6af - FirebaseFirestoreGRPCBoringSSLBinary: c3dfef3ff448ae2c1c85f9baf9fac5afc4db99fa - FirebaseFirestoreGRPCCoreBinary: 565534e160a0415d12185f7f171c52a567382fbd - FirebaseFirestoreGRPCCPPBinary: 6c0134e8d230ee58b9d51dec2a30a48efd6d5dc7 - FirebaseFirestoreInternalBinary: ea89c368772c8fa4c9550a464b36c25796f6182c - FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 - FirebaseRemoteConfig: b496646b82855e174a7f1e354c65e0e913085168 - FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa - FirebaseSharedSwift: e17c654ef1f1a616b0b33054e663ad1035c8fd40 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 - flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 - GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64 - GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 + abseil: a05cc83bf02079535e17169a73c5be5ba47f714b + awesome_notifications: 0f432b28098d193920b11a44cfa9d2d9313a3888 + awesome_notifications_core: 429c28df8746780a474de177e5acde33af87da63 + BoringSSL-GRPC: dded2a44897e45f28f08ae87a55ee4bcd19bc508 + cloud_firestore: 45532e0c1fd1f6a5720af8aa0312470c366b73d2 + file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6 + Firebase: a451a7b61536298fd5cbfe3a746fd40443a50679 + firebase_analytics: 4f9cca09e65f6c2944a862c6dc86f6bed9fb769c + firebase_core: ba00a168e719694f38960502ceb560285603d073 + firebase_remote_config: 4315c34bfba52eb501b69cfa84d519f340385a37 + FirebaseABTesting: 119f0a2b2e68b1ae05d248c5adb2455f148f20c1 + FirebaseAnalytics: d0a97a0db6425e5a5d966340b87f92ca7b13a557 + FirebaseAppCheckInterop: e2178171b4145013c7c1a3cc464d1d446d3a1896 + FirebaseCore: 0e38ad5d62d980a47a64b8e9301ffa311457be04 + FirebaseCoreExtension: 032fd6f8509e591fda8cb76f6651f20d926b121f + FirebaseCoreInternal: 69bf1306a05b8ac43004f6cc1f804bb7b05b229e + FirebaseFirestore: 51ce079b9ddcaa481644164eda649d362c2a6396 + FirebaseFirestoreInternal: 8b1d2b0a1b859b2ddbd63f448c416c5be7367405 + FirebaseInstallations: 631b38da2e11a83daa4bfb482f79d286a5dfa7ad + FirebaseRemoteConfig: c5dfe22828a7ae7673d16224ea92743687e993df + FirebaseRemoteConfigInterop: 3443b8cb8fffd76bb3e03b2a84bfd3db952fcda4 + FirebaseSharedSwift: 79f27fff0addd15c3de19b87fba426f3cc2c964f + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf + flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 + GoogleAdsOnDeviceConversion: d68c69dd9581a0f5da02617b6f377e5be483970f + GoogleAppMeasurement: 3bf40aff49a601af5da1c3345702fcb4991d35ee GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 + "gRPC-C++": cc207623316fb041a7a3e774c252cf68a058b9e8 + gRPC-Core: 860978b7db482de8b4f5e10677216309b5ff6330 IosAwnCore: 653786a911089012092ce831f2945cd339855a89 leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 + url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b + video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a -PODFILE CHECKSUM: 314cb596080ef1b32fcb9923d3afff0f310a59c1 +PODFILE CHECKSUM: f977ce8683a6959e3ca3adeb5684867ade520617 COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 25b4ecc..1235ba1 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -202,7 +202,6 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 8BD6B19860638C874518D2B3 /* [CP] Embed Pods Frameworks */, - C33FEF1B88310600974EB117 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -367,23 +366,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - C33FEF1B88310600974EB117 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index d1b023f..af49e3c 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -14,7 +14,6 @@ import firebase_core import firebase_remote_config import flutter_secure_storage_macos import package_info_plus -import path_provider_foundation import share_plus import shared_preferences_foundation import sqflite_darwin @@ -31,7 +30,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FirebaseRemoteConfigPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 4e00358..b7acaf0 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -6,7 +6,7 @@ FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=3.0.0 FLUTTER_BUILD_NUMBER=142 -DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049ZjZmZjE1MjlmZA==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049MTUyN2FlMGVjNQ==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC40 +DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049OGI4NzI4Njg0OQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index 13a239d..7ba8d02 100755 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -7,7 +7,7 @@ export "FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=3.0.0" export "FLUTTER_BUILD_NUMBER=142" -export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049ZjZmZjE1MjlmZA==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049MTUyN2FlMGVjNQ==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC40" +export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049OGI4NzI4Njg0OQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" diff --git a/macos/Podfile b/macos/Podfile index bcffd24..dd57f52 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -30,10 +30,6 @@ target 'Runner' do use_frameworks! use_modular_headers! - pod 'FirebaseFirestore', - :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', - :tag => '11.15.0' - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do inherit! :search_paths diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 24fd097..62efac2 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,124 +1,1314 @@ PODS: + - abseil/algorithm (1.20240722.0): + - abseil/algorithm/algorithm (= 1.20240722.0) + - abseil/algorithm/container (= 1.20240722.0) + - abseil/algorithm/algorithm (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/algorithm/container (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base (1.20240722.0): + - abseil/base/atomic_hook (= 1.20240722.0) + - abseil/base/base (= 1.20240722.0) + - abseil/base/base_internal (= 1.20240722.0) + - abseil/base/config (= 1.20240722.0) + - abseil/base/core_headers (= 1.20240722.0) + - abseil/base/cycleclock_internal (= 1.20240722.0) + - abseil/base/dynamic_annotations (= 1.20240722.0) + - abseil/base/endian (= 1.20240722.0) + - abseil/base/errno_saver (= 1.20240722.0) + - abseil/base/fast_type_id (= 1.20240722.0) + - abseil/base/log_severity (= 1.20240722.0) + - abseil/base/malloc_internal (= 1.20240722.0) + - abseil/base/no_destructor (= 1.20240722.0) + - abseil/base/nullability (= 1.20240722.0) + - abseil/base/poison (= 1.20240722.0) + - abseil/base/prefetch (= 1.20240722.0) + - abseil/base/pretty_function (= 1.20240722.0) + - abseil/base/raw_logging_internal (= 1.20240722.0) + - abseil/base/spinlock_wait (= 1.20240722.0) + - abseil/base/strerror (= 1.20240722.0) + - abseil/base/throw_delegate (= 1.20240722.0) + - abseil/base/atomic_hook (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/base (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/cycleclock_internal + - abseil/base/dynamic_annotations + - abseil/base/log_severity + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/spinlock_wait + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/base_internal (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/config (1.20240722.0): + - abseil/xcprivacy + - abseil/base/core_headers (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/cycleclock_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/xcprivacy + - abseil/base/dynamic_annotations (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/endian (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/xcprivacy + - abseil/base/errno_saver (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/fast_type_id (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/base/log_severity (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/malloc_internal (1.20240722.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/base/no_destructor (1.20240722.0): + - abseil/base/config + - abseil/base/nullability + - abseil/xcprivacy + - abseil/base/nullability (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/base/poison (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/xcprivacy + - abseil/base/prefetch (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/base/pretty_function (1.20240722.0): + - abseil/xcprivacy + - abseil/base/raw_logging_internal (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/log_severity + - abseil/xcprivacy + - abseil/base/spinlock_wait (1.20240722.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/xcprivacy + - abseil/base/strerror (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/xcprivacy + - abseil/base/throw_delegate (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/cleanup/cleanup (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/cleanup/cleanup_internal + - abseil/xcprivacy + - abseil/cleanup/cleanup_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/common (1.20240722.0): + - abseil/meta/type_traits + - abseil/types/optional + - abseil/xcprivacy + - abseil/container/common_policy_traits (1.20240722.0): + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/compressed_tuple (1.20240722.0): + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/container_memory (1.20240722.0): + - abseil/base/config + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/fixed_array (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/xcprivacy + - abseil/container/flat_hash_map (1.20240722.0): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_container_defaults + - abseil/container/raw_hash_map + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/flat_hash_set (1.20240722.0): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_container_defaults + - abseil/container/raw_hash_set + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/hash_container_defaults (1.20240722.0): + - abseil/base/config + - abseil/container/hash_function_defaults + - abseil/xcprivacy + - abseil/container/hash_function_defaults (1.20240722.0): + - abseil/base/config + - abseil/container/common + - abseil/hash/hash + - abseil/meta/type_traits + - abseil/strings/cord + - abseil/strings/strings + - abseil/xcprivacy + - abseil/container/hash_policy_traits (1.20240722.0): + - abseil/container/common_policy_traits + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/hashtable_debug_hooks (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/container/hashtablez_sampler (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/memory/memory + - abseil/profiling/exponential_biased + - abseil/profiling/sample_recorder + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/inlined_vector (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/inlined_vector_internal + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/container/inlined_vector_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/span + - abseil/xcprivacy + - abseil/container/layout (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/demangle_internal + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/utility/utility + - abseil/xcprivacy + - abseil/container/raw_hash_map (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/container_memory + - abseil/container/raw_hash_set + - abseil/xcprivacy + - abseil/container/raw_hash_set (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/endian + - abseil/base/prefetch + - abseil/base/raw_logging_internal + - abseil/container/common + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/hash_policy_traits + - abseil/container/hashtable_debug_hooks + - abseil/container/hashtablez_sampler + - abseil/hash/hash + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/crc/cpu_detect (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/xcprivacy + - abseil/crc/crc32c (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/crc/cpu_detect + - abseil/crc/crc_internal + - abseil/crc/non_temporal_memcpy + - abseil/strings/str_format + - abseil/strings/strings + - abseil/xcprivacy + - abseil/crc/crc_cord_state (1.20240722.0): + - abseil/base/config + - abseil/base/no_destructor + - abseil/crc/crc32c + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/crc/crc_internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/base/raw_logging_internal + - abseil/crc/cpu_detect + - abseil/memory/memory + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/crc/non_temporal_arm_intrinsics (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/crc/non_temporal_memcpy (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/crc/non_temporal_arm_intrinsics + - abseil/xcprivacy + - abseil/debugging/bounded_utf8_length_sequence (1.20240722.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/debugging/debugging_internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/errno_saver + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/debugging/decode_rust_punycode (1.20240722.0): + - abseil/base/config + - abseil/base/nullability + - abseil/debugging/bounded_utf8_length_sequence + - abseil/debugging/utf8_for_code_point + - abseil/xcprivacy + - abseil/debugging/demangle_internal (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/debugging/demangle_rust + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/debugging/demangle_rust (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/decode_rust_punycode + - abseil/xcprivacy + - abseil/debugging/examine_stack (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/xcprivacy + - abseil/debugging/stacktrace (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/xcprivacy + - abseil/debugging/symbolize (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/debugging/demangle_internal + - abseil/strings/strings + - abseil/xcprivacy + - abseil/debugging/utf8_for_code_point (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/flags/commandlineflag (1.20240722.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/flags/commandlineflag_internal + - abseil/strings/strings + - abseil/types/optional + - abseil/xcprivacy + - abseil/flags/commandlineflag_internal (1.20240722.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/xcprivacy + - abseil/flags/config (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/path_util + - abseil/flags/program_name + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/flags/flag (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/commandlineflag + - abseil/flags/config + - abseil/flags/flag_internal + - abseil/flags/reflection + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/flag_internal (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/flags/config + - abseil/flags/marshalling + - abseil/flags/reflection + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/utility/utility + - abseil/xcprivacy + - abseil/flags/marshalling (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/numeric/int128 + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/xcprivacy + - abseil/flags/path_util (1.20240722.0): + - abseil/base/config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/private_handle_accessor (1.20240722.0): + - abseil/base/config + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/strings/strings + - abseil/xcprivacy + - abseil/flags/program_name (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/flags/path_util + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/flags/reflection (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/container/flat_hash_map + - abseil/flags/commandlineflag + - abseil/flags/commandlineflag_internal + - abseil/flags/config + - abseil/flags/private_handle_accessor + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/functional/any_invocable (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/functional/bind_front (1.20240722.0): + - abseil/base/base_internal + - abseil/container/compressed_tuple + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/xcprivacy + - abseil/functional/function_ref (1.20240722.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/functional/any_invocable + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/hash/city (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/xcprivacy + - abseil/hash/hash (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/container/fixed_array + - abseil/functional/function_ref + - abseil/hash/city + - abseil/hash/low_level_hash + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/types/optional + - abseil/types/variant + - abseil/utility/utility + - abseil/xcprivacy + - abseil/hash/low_level_hash (1.20240722.0): + - abseil/base/config + - abseil/base/endian + - abseil/base/prefetch + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/log/absl_check (1.20240722.0): + - abseil/log/internal/check_impl + - abseil/xcprivacy + - abseil/log/absl_log (1.20240722.0): + - abseil/log/internal/log_impl + - abseil/xcprivacy + - abseil/log/absl_vlog_is_on (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/log/internal/vlog_config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/check (1.20240722.0): + - abseil/log/internal/check_impl + - abseil/log/internal/check_op + - abseil/log/internal/conditions + - abseil/log/internal/log_message + - abseil/log/internal/strip + - abseil/xcprivacy + - abseil/log/globals (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/hash/hash + - abseil/log/internal/vlog_config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/append_truncated (1.20240722.0): + - abseil/base/config + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/check_impl (1.20240722.0): + - abseil/base/core_headers + - abseil/log/internal/check_op + - abseil/log/internal/conditions + - abseil/log/internal/log_message + - abseil/log/internal/strip + - abseil/xcprivacy + - abseil/log/internal/check_op (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/log/internal/nullguard + - abseil/log/internal/nullstream + - abseil/log/internal/strip + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/conditions (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/log/internal/voidify + - abseil/xcprivacy + - abseil/log/internal/config (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/log/internal/fnmatch (1.20240722.0): + - abseil/base/config + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/format (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/log/internal/append_truncated + - abseil/log/internal/config + - abseil/log/internal/globals + - abseil/strings/str_format + - abseil/strings/strings + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/globals (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/strings/strings + - abseil/time/time + - abseil/xcprivacy + - abseil/log/internal/log_impl (1.20240722.0): + - abseil/log/absl_vlog_is_on + - abseil/log/internal/conditions + - abseil/log/internal/log_message + - abseil/log/internal/strip + - abseil/xcprivacy + - abseil/log/internal/log_message (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/base/strerror + - abseil/container/inlined_vector + - abseil/debugging/examine_stack + - abseil/log/globals + - abseil/log/internal/append_truncated + - abseil/log/internal/format + - abseil/log/internal/globals + - abseil/log/internal/log_sink_set + - abseil/log/internal/nullguard + - abseil/log/internal/proto + - abseil/log/log_entry + - abseil/log/log_sink + - abseil/log/log_sink_registry + - abseil/memory/memory + - abseil/strings/strings + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/log_sink_set (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/no_destructor + - abseil/base/raw_logging_internal + - abseil/cleanup/cleanup + - abseil/log/globals + - abseil/log/internal/config + - abseil/log/internal/globals + - abseil/log/log_entry + - abseil/log/log_sink + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/nullguard (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/log/internal/nullstream (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/strings/strings + - abseil/xcprivacy + - abseil/log/internal/proto (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/log/internal/strip (1.20240722.0): + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/log/internal/log_message + - abseil/log/internal/nullstream + - abseil/xcprivacy + - abseil/log/internal/vlog_config (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/log/internal/fnmatch + - abseil/memory/memory + - abseil/strings/strings + - abseil/synchronization/synchronization + - abseil/types/optional + - abseil/xcprivacy + - abseil/log/internal/voidify (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/log/log (1.20240722.0): + - abseil/log/internal/log_impl + - abseil/log/vlog_is_on + - abseil/xcprivacy + - abseil/log/log_entry (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/log/internal/config + - abseil/strings/strings + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/log/log_sink (1.20240722.0): + - abseil/base/config + - abseil/log/log_entry + - abseil/xcprivacy + - abseil/log/log_sink_registry (1.20240722.0): + - abseil/base/config + - abseil/log/internal/log_sink_set + - abseil/log/log_sink + - abseil/xcprivacy + - abseil/log/vlog_is_on (1.20240722.0): + - abseil/log/absl_vlog_is_on + - abseil/xcprivacy + - abseil/memory (1.20240722.0): + - abseil/memory/memory (= 1.20240722.0) + - abseil/memory/memory (1.20240722.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/meta (1.20240722.0): + - abseil/meta/type_traits (= 1.20240722.0) + - abseil/meta/type_traits (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/numeric/bits (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/numeric/int128 (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/bits + - abseil/types/compare + - abseil/xcprivacy + - abseil/numeric/representation (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/profiling/exponential_biased (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/xcprivacy + - abseil/profiling/sample_recorder (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/xcprivacy + - abseil/random/bit_gen_ref (1.20240722.0): + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/random + - abseil/xcprivacy + - abseil/random/distributions (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/internal/fastmath + - abseil/random/internal/generate_real + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/traits + - abseil/random/internal/uniform_helper + - abseil/random/internal/wide_multiply + - abseil/strings/strings + - abseil/xcprivacy + - abseil/random/internal/distribution_caller (1.20240722.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/utility/utility + - abseil/xcprivacy + - abseil/random/internal/fast_uniform_bits (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/fastmath (1.20240722.0): + - abseil/numeric/bits + - abseil/xcprivacy + - abseil/random/internal/generate_real (1.20240722.0): + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/fastmath + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/iostream_state_saver (1.20240722.0): + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/random/internal/nonsecure_base (1.20240722.0): + - abseil/base/core_headers + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/pcg_engine (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/fastmath + - abseil/random/internal/iostream_state_saver + - abseil/xcprivacy + - abseil/random/internal/platform (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/random/internal/pool_urbg (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/random/internal/randen + - abseil/random/internal/seed_material + - abseil/random/internal/traits + - abseil/random/seed_gen_exception + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/randen (1.20240722.0): + - abseil/base/raw_logging_internal + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes + - abseil/random/internal/randen_slow + - abseil/xcprivacy + - abseil/random/internal/randen_engine (1.20240722.0): + - abseil/base/endian + - abseil/meta/type_traits + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/randen + - abseil/xcprivacy + - abseil/random/internal/randen_hwaes (1.20240722.0): + - abseil/base/config + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes_impl + - abseil/xcprivacy + - abseil/random/internal/randen_hwaes_impl (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/xcprivacy + - abseil/random/internal/randen_slow (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/xcprivacy + - abseil/random/internal/salted_seed_seq (1.20240722.0): + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/seed_material + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/seed_material (1.20240722.0): + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/random/internal/fast_uniform_bits + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/random/internal/traits (1.20240722.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/xcprivacy + - abseil/random/internal/uniform_helper (1.20240722.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/internal/wide_multiply (1.20240722.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/traits + - abseil/xcprivacy + - abseil/random/random (1.20240722.0): + - abseil/random/distributions + - abseil/random/internal/nonsecure_base + - abseil/random/internal/pcg_engine + - abseil/random/internal/pool_urbg + - abseil/random/internal/randen_engine + - abseil/random/seed_sequences + - abseil/xcprivacy + - abseil/random/seed_gen_exception (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/random/seed_sequences (1.20240722.0): + - abseil/base/config + - abseil/base/nullability + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/random/seed_gen_exception + - abseil/strings/string_view + - abseil/types/span + - abseil/xcprivacy + - abseil/status/status (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/no_destructor + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/strerror + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/functional/function_ref + - abseil/memory/memory + - abseil/strings/cord + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/status/statusor (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/status/status + - abseil/strings/has_ostream_operator + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/variant + - abseil/utility/utility + - abseil/xcprivacy + - abseil/strings/charset (1.20240722.0): + - abseil/base/core_headers + - abseil/strings/string_view + - abseil/xcprivacy + - abseil/strings/cord (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/crc/crc32c + - abseil/crc/crc_cord_state + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_info + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_scope + - abseil/strings/cordz_update_tracker + - abseil/strings/internal + - abseil/strings/strings + - abseil/types/compare + - abseil/types/optional + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cord_internal (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/inlined_vector + - abseil/container/layout + - abseil/crc/crc_cord_state + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cordz_functions (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/profiling/exponential_biased + - abseil/xcprivacy + - abseil/strings/cordz_handle (1.20240722.0): + - abseil/base/config + - abseil/base/no_destructor + - abseil/base/raw_logging_internal + - abseil/synchronization/synchronization + - abseil/xcprivacy + - abseil/strings/cordz_info (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_handle + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_tracker + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/cordz_statistics (1.20240722.0): + - abseil/base/config + - abseil/strings/cordz_update_tracker + - abseil/xcprivacy + - abseil/strings/cordz_update_scope (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/cord_internal + - abseil/strings/cordz_info + - abseil/strings/cordz_update_tracker + - abseil/xcprivacy + - abseil/strings/cordz_update_tracker (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/strings/has_ostream_operator (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/strings/internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/strings/str_format (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/strings/str_format_internal + - abseil/strings/string_view + - abseil/types/span + - abseil/xcprivacy + - abseil/strings/str_format_internal (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/container/fixed_array + - abseil/container/inlined_vector + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/numeric/representation + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/utility/utility + - abseil/xcprivacy + - abseil/strings/string_view (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/throw_delegate + - abseil/xcprivacy + - abseil/strings/strings (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/nullability + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/charset + - abseil/strings/internal + - abseil/strings/string_view + - abseil/xcprivacy + - abseil/synchronization/graphcycles_internal (1.20240722.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/synchronization/kernel_timeout_internal (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/time/time + - abseil/xcprivacy + - abseil/synchronization/synchronization (1.20240722.0): + - abseil/base/atomic_hook + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/synchronization/graphcycles_internal + - abseil/synchronization/kernel_timeout_internal + - abseil/time/time + - abseil/xcprivacy + - abseil/time (1.20240722.0): + - abseil/time/internal (= 1.20240722.0) + - abseil/time/time (= 1.20240722.0) + - abseil/time/internal (1.20240722.0): + - abseil/time/internal/cctz (= 1.20240722.0) + - abseil/time/internal/cctz (1.20240722.0): + - abseil/time/internal/cctz/civil_time (= 1.20240722.0) + - abseil/time/internal/cctz/time_zone (= 1.20240722.0) + - abseil/time/internal/cctz/civil_time (1.20240722.0): + - abseil/base/config + - abseil/xcprivacy + - abseil/time/internal/cctz/time_zone (1.20240722.0): + - abseil/base/config + - abseil/time/internal/cctz/civil_time + - abseil/xcprivacy + - abseil/time/time (1.20240722.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/time/internal/cctz/civil_time + - abseil/time/internal/cctz/time_zone + - abseil/types/optional + - abseil/xcprivacy + - abseil/types (1.20240722.0): + - abseil/types/any (= 1.20240722.0) + - abseil/types/bad_any_cast (= 1.20240722.0) + - abseil/types/bad_any_cast_impl (= 1.20240722.0) + - abseil/types/bad_optional_access (= 1.20240722.0) + - abseil/types/bad_variant_access (= 1.20240722.0) + - abseil/types/compare (= 1.20240722.0) + - abseil/types/optional (= 1.20240722.0) + - abseil/types/span (= 1.20240722.0) + - abseil/types/variant (= 1.20240722.0) + - abseil/types/any (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/types/bad_any_cast + - abseil/utility/utility + - abseil/xcprivacy + - abseil/types/bad_any_cast (1.20240722.0): + - abseil/base/config + - abseil/types/bad_any_cast_impl + - abseil/xcprivacy + - abseil/types/bad_any_cast_impl (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/bad_optional_access (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/bad_variant_access (1.20240722.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/xcprivacy + - abseil/types/compare (1.20240722.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/types/optional (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/nullability + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/bad_optional_access + - abseil/utility/utility + - abseil/xcprivacy + - abseil/types/span (1.20240722.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/nullability + - abseil/base/throw_delegate + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/types/variant (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/bad_variant_access + - abseil/utility/utility + - abseil/xcprivacy + - abseil/utility/utility (1.20240722.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/meta/type_traits + - abseil/xcprivacy + - abseil/xcprivacy (1.20240722.0) - awesome_notifications (0.0.1): - FlutterMacOS - awesome_notifications_core (0.0.1): - FlutterMacOS - - cloud_firestore (5.6.12): - - Firebase/CoreOnly (~> 11.15.0) - - Firebase/Firestore (~> 11.15.0) + - BoringSSL-GRPC (0.0.37): + - BoringSSL-GRPC/Implementation (= 0.0.37) + - BoringSSL-GRPC/Interface (= 0.0.37) + - BoringSSL-GRPC/Implementation (0.0.37): + - BoringSSL-GRPC/Interface (= 0.0.37) + - BoringSSL-GRPC/Interface (0.0.37) + - cloud_firestore (6.1.2): + - Firebase/CoreOnly (~> 12.8.0) + - Firebase/Firestore (~> 12.8.0) - firebase_core - FlutterMacOS - file_saver (0.0.1): - FlutterMacOS - - Firebase/Analytics (11.15.0): - - Firebase/Core - - Firebase/Core (11.15.0): + - Firebase/CoreOnly (12.8.0): + - FirebaseCore (~> 12.8.0) + - Firebase/Firestore (12.8.0): - Firebase/CoreOnly - - FirebaseAnalytics (~> 11.15.0) - - Firebase/CoreOnly (11.15.0): - - FirebaseCore (~> 11.15.0) - - Firebase/Firestore (11.15.0): + - FirebaseFirestore (~> 12.8.0) + - Firebase/RemoteConfig (12.8.0): - Firebase/CoreOnly - - FirebaseFirestore (~> 11.15.0) - - Firebase/RemoteConfig (11.15.0): - - Firebase/CoreOnly - - FirebaseRemoteConfig (~> 11.15.0) - - firebase_analytics (11.6.0): - - Firebase/Analytics (= 11.15.0) + - FirebaseRemoteConfig (~> 12.8.0) + - firebase_analytics (12.1.2): - firebase_core + - FirebaseAnalytics (= 12.8.0) - FlutterMacOS - - firebase_core (3.15.2): - - Firebase/CoreOnly (~> 11.15.0) + - firebase_core (4.4.0): + - Firebase/CoreOnly (~> 12.8.0) - FlutterMacOS - - firebase_remote_config (5.5.0): - - Firebase/CoreOnly (~> 11.15.0) - - Firebase/RemoteConfig (~> 11.15.0) + - firebase_remote_config (6.1.4): + - Firebase/CoreOnly (~> 12.8.0) + - Firebase/RemoteConfig (~> 12.8.0) - firebase_core - FlutterMacOS - - FirebaseABTesting (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseAnalytics (11.15.0): - - FirebaseAnalytics/Default (= 11.15.0) - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) + - FirebaseABTesting (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseAnalytics (12.8.0): + - FirebaseAnalytics/Default (= 12.8.0) + - FirebaseCore (~> 12.8.0) + - FirebaseInstallations (~> 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseAnalytics/Default (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - GoogleAppMeasurement/Default (= 11.15.0) + - FirebaseAnalytics/Default (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseInstallations (~> 12.8.0) + - GoogleAppMeasurement/Default (= 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseCore (11.15.0): - - FirebaseCoreInternal (~> 11.15.0) + - FirebaseAppCheckInterop (12.8.0) + - FirebaseCore (12.8.0): + - FirebaseCoreInternal (~> 12.8.0) - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/Logger (~> 8.1) - - FirebaseCoreExtension (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseCoreInternal (11.15.0): + - FirebaseCoreExtension (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseCoreInternal (12.8.0): - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseFirestore (11.15.0): - - FirebaseFirestoreBinary (= 11.15.0) - - FirebaseFirestoreAbseilBinary (1.2024072200.0) - - FirebaseFirestoreBinary (11.15.0): - - FirebaseCore (= 11.15.0) - - FirebaseCoreExtension (= 11.15.0) - - FirebaseFirestoreInternalBinary (= 11.15.0) - - FirebaseSharedSwift (= 11.15.0) - - FirebaseFirestoreGRPCBoringSSLBinary (1.69.0) - - FirebaseFirestoreGRPCCoreBinary (1.69.0): - - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) - - FirebaseFirestoreGRPCBoringSSLBinary (= 1.69.0) - - FirebaseFirestoreGRPCCPPBinary (1.69.0): - - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) - - FirebaseFirestoreGRPCCoreBinary (= 1.69.0) - - FirebaseFirestoreInternalBinary (11.15.0): - - FirebaseCore (= 11.15.0) - - FirebaseFirestoreAbseilBinary (= 1.2024072200.0) - - FirebaseFirestoreGRPCCPPBinary (= 1.69.0) + - FirebaseFirestore (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseCoreExtension (~> 12.8.0) + - FirebaseFirestoreInternal (~> 12.8.0) + - FirebaseSharedSwift (~> 12.8.0) + - FirebaseFirestoreInternal (12.8.0): + - abseil/algorithm (~> 1.20240722.0) + - abseil/base (~> 1.20240722.0) + - abseil/container/flat_hash_map (~> 1.20240722.0) + - abseil/memory (~> 1.20240722.0) + - abseil/meta (~> 1.20240722.0) + - abseil/strings/strings (~> 1.20240722.0) + - abseil/time (~> 1.20240722.0) + - abseil/types (~> 1.20240722.0) + - FirebaseAppCheckInterop (~> 12.8.0) + - FirebaseCore (~> 12.8.0) + - "gRPC-C++ (~> 1.69.0)" + - gRPC-Core (~> 1.69.0) - leveldb-library (~> 1.22) - nanopb (~> 3.30910.0) - - FirebaseInstallations (11.15.0): - - FirebaseCore (~> 11.15.0) + - FirebaseInstallations (12.8.0): + - FirebaseCore (~> 12.8.0) - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseRemoteConfig (11.15.0): - - FirebaseABTesting (~> 11.0) - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - FirebaseRemoteConfigInterop (~> 11.0) - - FirebaseSharedSwift (~> 11.0) + - FirebaseRemoteConfig (12.8.0): + - FirebaseABTesting (~> 12.8.0) + - FirebaseCore (~> 12.8.0) + - FirebaseInstallations (~> 12.8.0) + - FirebaseRemoteConfigInterop (~> 12.8.0) + - FirebaseSharedSwift (~> 12.8.0) - GoogleUtilities/Environment (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseRemoteConfigInterop (11.15.0) - - FirebaseSharedSwift (11.15.0) + - FirebaseRemoteConfigInterop (12.8.0) + - FirebaseSharedSwift (12.8.0) - flutter_secure_storage_macos (6.1.3): - FlutterMacOS - FlutterMacOS (1.0.0) - - GoogleAppMeasurement/Core (11.15.0): + - GoogleAppMeasurement/Core (12.8.0): - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Default (11.15.0): - - GoogleAdsOnDeviceConversion (= 2.1.0) - - GoogleAppMeasurement/Core (= 11.15.0) - - GoogleAppMeasurement/IdentitySupport (= 11.15.0) + - GoogleAppMeasurement/Default (12.8.0): + - GoogleAdsOnDeviceConversion (~> 3.2.0) + - GoogleAppMeasurement/Core (= 12.8.0) + - GoogleAppMeasurement/IdentitySupport (= 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/IdentitySupport (11.15.0): - - GoogleAppMeasurement/Core (= 11.15.0) + - GoogleAppMeasurement/IdentitySupport (12.8.0): + - GoogleAppMeasurement/Core (= 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) @@ -151,6 +1341,98 @@ PODS: - GoogleUtilities/UserDefaults (8.1.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy + - "gRPC-C++ (1.69.0)": + - "gRPC-C++/Implementation (= 1.69.0)" + - "gRPC-C++/Interface (= 1.69.0)" + - "gRPC-C++/Implementation (1.69.0)": + - abseil/algorithm/container (~> 1.20240722.0) + - abseil/base/base (~> 1.20240722.0) + - abseil/base/config (~> 1.20240722.0) + - abseil/base/core_headers (~> 1.20240722.0) + - abseil/base/log_severity (~> 1.20240722.0) + - abseil/base/no_destructor (~> 1.20240722.0) + - abseil/cleanup/cleanup (~> 1.20240722.0) + - abseil/container/flat_hash_map (~> 1.20240722.0) + - abseil/container/flat_hash_set (~> 1.20240722.0) + - abseil/container/inlined_vector (~> 1.20240722.0) + - abseil/flags/flag (~> 1.20240722.0) + - abseil/flags/marshalling (~> 1.20240722.0) + - abseil/functional/any_invocable (~> 1.20240722.0) + - abseil/functional/bind_front (~> 1.20240722.0) + - abseil/functional/function_ref (~> 1.20240722.0) + - abseil/hash/hash (~> 1.20240722.0) + - abseil/log/absl_check (~> 1.20240722.0) + - abseil/log/absl_log (~> 1.20240722.0) + - abseil/log/check (~> 1.20240722.0) + - abseil/log/globals (~> 1.20240722.0) + - abseil/log/log (~> 1.20240722.0) + - abseil/memory/memory (~> 1.20240722.0) + - abseil/meta/type_traits (~> 1.20240722.0) + - abseil/numeric/bits (~> 1.20240722.0) + - abseil/random/bit_gen_ref (~> 1.20240722.0) + - abseil/random/distributions (~> 1.20240722.0) + - abseil/random/random (~> 1.20240722.0) + - abseil/status/status (~> 1.20240722.0) + - abseil/status/statusor (~> 1.20240722.0) + - abseil/strings/cord (~> 1.20240722.0) + - abseil/strings/str_format (~> 1.20240722.0) + - abseil/strings/strings (~> 1.20240722.0) + - abseil/synchronization/synchronization (~> 1.20240722.0) + - abseil/time/time (~> 1.20240722.0) + - abseil/types/optional (~> 1.20240722.0) + - abseil/types/span (~> 1.20240722.0) + - abseil/types/variant (~> 1.20240722.0) + - abseil/utility/utility (~> 1.20240722.0) + - "gRPC-C++/Interface (= 1.69.0)" + - "gRPC-C++/Privacy (= 1.69.0)" + - gRPC-Core (= 1.69.0) + - "gRPC-C++/Interface (1.69.0)" + - "gRPC-C++/Privacy (1.69.0)" + - gRPC-Core (1.69.0): + - gRPC-Core/Implementation (= 1.69.0) + - gRPC-Core/Interface (= 1.69.0) + - gRPC-Core/Implementation (1.69.0): + - abseil/algorithm/container (~> 1.20240722.0) + - abseil/base/base (~> 1.20240722.0) + - abseil/base/config (~> 1.20240722.0) + - abseil/base/core_headers (~> 1.20240722.0) + - abseil/base/log_severity (~> 1.20240722.0) + - abseil/base/no_destructor (~> 1.20240722.0) + - abseil/cleanup/cleanup (~> 1.20240722.0) + - abseil/container/flat_hash_map (~> 1.20240722.0) + - abseil/container/flat_hash_set (~> 1.20240722.0) + - abseil/container/inlined_vector (~> 1.20240722.0) + - abseil/flags/flag (~> 1.20240722.0) + - abseil/flags/marshalling (~> 1.20240722.0) + - abseil/functional/any_invocable (~> 1.20240722.0) + - abseil/functional/bind_front (~> 1.20240722.0) + - abseil/functional/function_ref (~> 1.20240722.0) + - abseil/hash/hash (~> 1.20240722.0) + - abseil/log/check (~> 1.20240722.0) + - abseil/log/globals (~> 1.20240722.0) + - abseil/log/log (~> 1.20240722.0) + - abseil/memory/memory (~> 1.20240722.0) + - abseil/meta/type_traits (~> 1.20240722.0) + - abseil/numeric/bits (~> 1.20240722.0) + - abseil/random/bit_gen_ref (~> 1.20240722.0) + - abseil/random/distributions (~> 1.20240722.0) + - abseil/random/random (~> 1.20240722.0) + - abseil/status/status (~> 1.20240722.0) + - abseil/status/statusor (~> 1.20240722.0) + - abseil/strings/cord (~> 1.20240722.0) + - abseil/strings/str_format (~> 1.20240722.0) + - abseil/strings/strings (~> 1.20240722.0) + - abseil/synchronization/synchronization (~> 1.20240722.0) + - abseil/time/time (~> 1.20240722.0) + - abseil/types/optional (~> 1.20240722.0) + - abseil/types/span (~> 1.20240722.0) + - abseil/types/variant (~> 1.20240722.0) + - abseil/utility/utility (~> 1.20240722.0) + - BoringSSL-GRPC (= 0.0.37) + - gRPC-Core/Interface (= 1.69.0) + - gRPC-Core/Privacy (= 1.69.0) + - gRPC-Core/Interface (1.69.0) + - gRPC-Core/Privacy (1.69.0) - leveldb-library (1.22.6) - nanopb (3.30910.0): - nanopb/decode (= 3.30910.0) @@ -159,9 +1441,6 @@ PODS: - nanopb/encode (3.30910.0) - package_info_plus (0.0.1): - FlutterMacOS - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - PromisesObjC (2.4.0) - share_plus (0.0.1): - FlutterMacOS @@ -185,11 +1464,9 @@ DEPENDENCIES: - firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`) - firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`) - firebase_remote_config (from `Flutter/ephemeral/.symlinks/plugins/firebase_remote_config/macos`) - - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `11.15.0`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) @@ -198,24 +1475,25 @@ DEPENDENCIES: SPEC REPOS: trunk: + - abseil + - BoringSSL-GRPC - Firebase - FirebaseABTesting - FirebaseAnalytics + - FirebaseAppCheckInterop - FirebaseCore - FirebaseCoreExtension - FirebaseCoreInternal - - FirebaseFirestoreAbseilBinary - - FirebaseFirestoreBinary - - FirebaseFirestoreGRPCBoringSSLBinary - - FirebaseFirestoreGRPCCoreBinary - - FirebaseFirestoreGRPCCPPBinary - - FirebaseFirestoreInternalBinary + - FirebaseFirestore + - FirebaseFirestoreInternal - FirebaseInstallations - FirebaseRemoteConfig - FirebaseRemoteConfigInterop - FirebaseSharedSwift - GoogleAppMeasurement - GoogleUtilities + - "gRPC-C++" + - gRPC-Core - leveldb-library - nanopb - PromisesObjC @@ -235,17 +1513,12 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos firebase_remote_config: :path: Flutter/ephemeral/.symlinks/plugins/firebase_remote_config/macos - FirebaseFirestore: - :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.15.0 flutter_secure_storage_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos FlutterMacOS: :path: Flutter/ephemeral package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos - path_provider_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin share_plus: :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos shared_preferences_foundation: @@ -257,44 +1530,38 @@ EXTERNAL SOURCES: video_player_avfoundation: :path: Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin -CHECKOUT OPTIONS: - FirebaseFirestore: - :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 11.15.0 - SPEC CHECKSUMS: + abseil: a05cc83bf02079535e17169a73c5be5ba47f714b awesome_notifications: 7818a3dbad4836238a68df439c06981d9f0b276c awesome_notifications_core: 1c16f7521b1757f6d39121289573aa3801ba0299 - cloud_firestore: 92bf414ac4a12c1008efa35a70ffe988f90cf740 + BoringSSL-GRPC: dded2a44897e45f28f08ae87a55ee4bcd19bc508 + cloud_firestore: 71947b640bd24f6f849d9d185e5d0a619fa6b93b file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f - Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e - firebase_analytics: 3091f96bd17636f6da5092a4701ffacf67c6e455 - firebase_core: 7667f880631ae8ad10e3d6567ab7582fe0682326 - firebase_remote_config: 55c407857ec71f2c5406c04e70ec27109fb47276 - FirebaseABTesting: 5e9d432834aebf27ab72100d37af44dfbe8d82f7 - FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae - FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e - FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435 - FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 - FirebaseFirestore: 736c2099af30aed7728d5789059fee1914b4d213 - FirebaseFirestoreAbseilBinary: 4cfa8823cedc1b774843e04fe578ad279b387f97 - FirebaseFirestoreBinary: 43abe19da1cb39a10171786e5a2e18fa9d57b6af - FirebaseFirestoreGRPCBoringSSLBinary: c3dfef3ff448ae2c1c85f9baf9fac5afc4db99fa - FirebaseFirestoreGRPCCoreBinary: 565534e160a0415d12185f7f171c52a567382fbd - FirebaseFirestoreGRPCCPPBinary: 6c0134e8d230ee58b9d51dec2a30a48efd6d5dc7 - FirebaseFirestoreInternalBinary: ea89c368772c8fa4c9550a464b36c25796f6182c - FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 - FirebaseRemoteConfig: b496646b82855e174a7f1e354c65e0e913085168 - FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa - FirebaseSharedSwift: e17c654ef1f1a616b0b33054e663ad1035c8fd40 + Firebase: 9a58fdbc9d8655ed7b79a19cf9690bb007d3d46d + firebase_analytics: baaf472ae2221d731cf1ec69b3e360bd1bbf40c5 + firebase_core: b1697fb64ff2b9ca16baaa821205f8b0c058e5d2 + firebase_remote_config: e77e7e12127f6043b14aa2e1949d7af3218c94e0 + FirebaseABTesting: 31266c7845f9adde0f2e8a59267e9c82e4050898 + FirebaseAnalytics: f20bbad8cb7f65d8a5eaefeb424ae8800a31bdfc + FirebaseAppCheckInterop: ba3dc604a89815379e61ec2365101608d365cf7d + FirebaseCore: 0dbad74bda10b8fb9ca34ad8f375fb9dd3ebef7c + FirebaseCoreExtension: 6605938d51f765d8b18bfcafd2085276a252bee2 + FirebaseCoreInternal: fe5fa466aeb314787093a7dce9f0beeaad5a2a21 + FirebaseFirestore: 67f23000ca238ccbab79127ed59636a9a2689e74 + FirebaseFirestoreInternal: a0e7382af3d208898dcd1d4d52d8a7870632e881 + FirebaseInstallations: 6a14ab3d694ebd9f839c48d330da5547e9ca9dc0 + FirebaseRemoteConfig: e9e3909162a05bc0e796326255fd43250783a2a9 + FirebaseRemoteConfigInterop: 869ddca16614f979e5c931ece11fbb0b8729ed41 + FirebaseSharedSwift: f57ed48f4542b2d7eb4738f4f23ba443f78b3780 flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54 FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 - GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 + GoogleAppMeasurement: 72c9a682fec6290327ea5e3c4b829b247fcb2c17 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 + "gRPC-C++": cc207623316fb041a7a3e774c252cf68a058b9e8 + gRPC-Core: 860978b7db482de8b4f5e10677216309b5ff6330 leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 package_info_plus: f0052d280d17aa382b932f399edf32507174e870 - path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb @@ -302,6 +1569,6 @@ SPEC CHECKSUMS: url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a -PODFILE CHECKSUM: 04282d4ce2394f1e08aa86e9628717a0ee4ed2ce +PODFILE CHECKSUM: 2bbaaa1752f97db94da363e30654aa60e20fb3a0 COCOAPODS: 1.16.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 69aa0c3..2f5d979 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -243,7 +243,6 @@ 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, BE6752570711DC323B9D7F70 /* [CP] Embed Pods Frameworks */, - 1C68EA7950BA34CCD3081D74 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -327,23 +326,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1C68EA7950BA34CCD3081D74 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; diff --git a/pubspec.lock b/pubspec.lock index 043ee8d..a45c5ca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11 + sha256: cd83f7d6bd4e4c0b0b4fef802e8796784032e1cc23d7b0e982cf5d05d9bbe182 url: "https://pub.dev" source: hosted - version: "1.3.59" + version: "1.3.66" adaptive_number: dependency: transitive description: @@ -113,14 +113,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - chalkdart: - dependency: transitive - description: - name: chalkdart - sha256: "7ffc6bd39c81453fb9ba8dbce042a9c960219b75ea1c07196a7fa41c2fab9e86" - url: "https://pub.dev" - source: hosted - version: "3.0.5" characters: dependency: transitive description: @@ -165,26 +157,34 @@ packages: dependency: "direct main" description: name: cloud_firestore - sha256: "2d33da4465bdb81b6685c41b535895065adcb16261beb398f5f3bbc623979e9c" + sha256: "54484b2fc49f41b46f35b60a54b12351181eeaad22c0e3def276a81e17ae7c9b" url: "https://pub.dev" source: hosted - version: "5.6.12" + version: "6.1.2" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - sha256: "413c4e01895cf9cb3de36fa5c219479e06cd4722876274ace5dfc9f13ab2e39b" + sha256: dfaa8b2c0d0a824af289d4159816a5c78417feec264c2194081d645687195158 url: "https://pub.dev" source: hosted - version: "6.6.12" + version: "7.0.6" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - sha256: c1e30fc4a0fcedb08723fb4b1f12ee4e56d937cbf9deae1bda43cbb6367bb4cf + sha256: "35d01f502b3b701d700470d32a8f82704dac8341a66e86c074900cde5bab343d" + url: "https://pub.dev" + source: hosted + version: "5.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" url: "https://pub.dev" source: hosted - version: "4.4.12" + version: "1.0.0" collection: dependency: "direct main" description: @@ -205,10 +205,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "701dcfc06da0882883a2657c445103380e53e647060ad8d9dfb710c100996608" + sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" url: "https://pub.dev" source: hosted - version: "0.3.5+1" + version: "0.3.5+2" crypto: dependency: transitive description: @@ -309,10 +309,10 @@ packages: dependency: transitive description: name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" file: dependency: transitive description: @@ -333,34 +333,34 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: "4f85b161772e1d54a66893ef131c0a44bd9e552efa78b33d5f4f60d2caa5c8a3" + sha256: "07e0a82e9b045dbd14522a0b23764e2dbcc269720e785d63c6a021133ebb766a" url: "https://pub.dev" source: hosted - version: "11.6.0" + version: "12.1.2" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: a44b6d1155ed5cae7641e3de7163111cfd9f6f6c954ca916dc6a3bdfa86bf845 + sha256: "62fd3f27f342c898bd819fb97fa87c0b971e9fbe03357477282c0e14e1a40c3c" url: "https://pub.dev" source: hosted - version: "4.4.3" + version: "5.0.6" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: c7d1ed1f86ae64215757518af5576ff88341c8ce5741988c05cc3b2e07b0b273 + sha256: "8fc488bb008439fc3b850cfac892dec1ff4cd438eee44438919a14c5e61b9828" url: "https://pub.dev" source: hosted - version: "0.5.10+16" + version: "0.6.1+2" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5" + sha256: "923085c881663ef685269b013e241b428e1fb03cdd0ebde265d9b40ff18abf80" url: "https://pub.dev" source: hosted - version: "3.15.2" + version: "4.4.0" firebase_core_platform_interface: dependency: transitive description: @@ -373,34 +373,34 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37" + sha256: "83e7356c704131ca4d8d8dd57e360d8acecbca38b1a3705c7ae46cc34c708084" url: "https://pub.dev" source: hosted - version: "2.24.1" + version: "3.4.0" firebase_remote_config: dependency: "direct main" description: name: firebase_remote_config - sha256: e1635b1e8713f4a823920ec3a56a14034b90ce455d47746ab0da994857f370cf + sha256: "6d7be334b726537b3aa3a3ef1db9782951cd93c2b996eebc33f64a9f140e0409" url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "6.1.4" firebase_remote_config_platform_interface: dependency: transitive description: name: firebase_remote_config_platform_interface - sha256: ce836c5c62056edbe23ef501e6876691ee32476afd12fe95b76e57bba9d25485 + sha256: f895915923bebb9e8b36a6387fac31a9dd36fbb63fa2ee1ea2cbe309634eecdf url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.7" firebase_remote_config_web: dependency: transitive description: name: firebase_remote_config_web - sha256: "9dbd75024bfcd47c05046c95f9cf648a8fc862b096bcf8ea1e4b855d50ea19ad" + sha256: a4de6b86e5eb0416a46948dcb1fa9fce6a71d41f80fa107f6e202ae579ec81b2 url: "https://pub.dev" source: hosted - version: "1.8.9" + version: "1.10.3" fixnum: dependency: transitive description: @@ -544,6 +544,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.3.3" + hooks: + dependency: transitive + description: + name: hooks + sha256: "7a08a0d684cb3b8fb604b78455d5d352f502b68079f7b80b831c62220ab0a4f6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" html: dependency: "direct main" description: @@ -676,10 +684,10 @@ packages: dependency: "direct main" description: name: material_symbols_icons - sha256: "02555a48e1ec02b16e532dfd4ef13c4f6bf7ec7c20230e58e56641a393433dc3" + sha256: c62b15f2b3de98d72cbff0148812f5ef5159f05e61fc9f9a089ec2bb234df082 url: "https://pub.dev" source: hosted - version: "4.2892.0" + version: "4.2906.0" meta: dependency: transitive description: @@ -696,6 +704,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "89e83885ba09da5fdf2cdacc8002a712ca238c28b7f717910b34bcd27b0d03ac" + url: "https://pub.dev" + source: hosted + version: "0.17.4" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" package_config: dependency: transitive description: @@ -764,10 +788,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.0" path_provider_linux: dependency: transitive description: @@ -908,10 +932,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "83af5c682796c0f7719c2bbf74792d113e40ae97981b8f266fa84574573556bc" + sha256: cbc40be9be1c5af4dab4d6e0de4d5d3729e6f3d65b89d21e1815d57705644a6f url: "https://pub.dev" source: hosted - version: "2.4.18" + version: "2.4.20" shared_preferences_foundation: dependency: transitive description: @@ -977,10 +1001,10 @@ packages: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" url: "https://pub.dev" source: hosted - version: "1.10.1" + version: "1.10.2" sqflite: dependency: "direct main" description: @@ -1105,10 +1129,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad + sha256: b1aca26728b7cc7a3af971bb6f601554a8ae9df2e0a006de8450ba06a17ad36a url: "https://pub.dev" source: hosted - version: "6.3.6" + version: "6.4.0" url_launcher_linux: dependency: transitive description: @@ -1137,10 +1161,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" url_launcher_windows: dependency: transitive description: @@ -1185,10 +1209,10 @@ packages: dependency: transitive description: name: video_player_avfoundation - sha256: e4d33b79a064498c6eb3a6a492b6a5012573d4943c28d566caf1a6c0840fe78d + sha256: f46e9e20f1fe429760cf4dc118761336320d1bec0f50d255930c2355f2defb5b url: "https://pub.dev" source: hosted - version: "2.8.8" + version: "2.9.1" video_player_platform_interface: dependency: transitive description: @@ -1217,10 +1241,10 @@ packages: dependency: transitive description: name: watcher - sha256: f52385d4f73589977c80797e60fe51014f7f2b957b5e9a62c3f6ada439889249 + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" web: dependency: transitive description: @@ -1278,5 +1302,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.10.3 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index ed98b95..305803e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,6 @@ dependencies: package_info_plus: ^8.0.2 shared_preferences: ^2.3.2 dart_jsonwebtoken: ^2.14.1 - cloud_firestore: ^5.4.5 google_fonts: ^6.2.1 flutter_native_splash: ^2.4.1 video_player: ^2.9.2 @@ -35,16 +34,17 @@ dependencies: screenshot: ^3.0.0 share_plus: ^10.1.2 # Firebase - firebase_core: ^3.15.2 - firebase_remote_config: ^5.5.0 - firebase_analytics: ^11.6.0 + firebase_core: ^4.3.0 + firebase_remote_config: ^6.1.3 + firebase_analytics: ^12.1.0 + cloud_firestore: ^6.1.1 # Apuntes sqflite: ^2.4.1 flutter_secure_storage: ^9.2.2 path_provider: ^2.1.5 # Awesome-notifications LOCAL awesome_notifications_core: ^0.10.0 - awesome_notifications: ^0.10.0 + awesome_notifications: ^0.10.1 xpath_selector_html_parser: ^3.0.1 html: ^0.15.5 flutter_carousel_widget: ^3.1.0 From a9807e5f5c3a0a29ac9f97e02fe13bbeb818642d Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Tue, 10 Feb 2026 23:45:47 -0300 Subject: [PATCH 18/24] feat: update application namespace and enhance login form with email formatting --- android/app/build.gradle | 4 +-- .../auth/login/widgets/login_form.dart | 2 ++ .../auth/login/widgets/login_form_fields.dart | 17 ++++++++--- .../widgets/utem_email_input_formatter.dart | 29 +++++++++++++++++++ macos/Runner.xcodeproj/project.pbxproj | 3 ++ macos/Runner/DebugProfile.entitlements | 14 +++++---- macos/Runner/Release.entitlements | 10 ++++--- 7 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 lib/screens/auth/login/widgets/utem_email_input_formatter.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 2451673..59ef89b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -9,7 +9,7 @@ plugins { } android { - namespace = "cl.exdev.miutem" + namespace = "cl.inndev.miutem" compileSdk = 34 ndkVersion = flutter.ndkVersion @@ -24,7 +24,7 @@ android { // AQUI SE TIENE QUE USAR LA CONFIGURACION DEL KEYSTORE QUE TIENE LA APP OFICIAL defaultConfig { - applicationId = "cl.exdev.miutem" + applicationId = "cl.inndev.miutem" minSdk = 23 targetSdk = 34 diff --git a/lib/screens/auth/login/widgets/login_form.dart b/lib/screens/auth/login/widgets/login_form.dart index 325bc36..4ae4819 100644 --- a/lib/screens/auth/login/widgets/login_form.dart +++ b/lib/screens/auth/login/widgets/login_form.dart @@ -1,5 +1,6 @@ import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:miutem/core/models/exceptions/custom_exception.dart'; import 'package:miutem/screens/auth/login/actions/login_action.dart'; import 'package:miutem/screens/auth/login/widgets/login_form_fields.dart'; @@ -72,6 +73,7 @@ class _LoginFormState extends State with WidgetsBindingObserver { passwordFocus: _passwordFocus, usernameFocus: _usernameFocus, onLogin: () async { + TextInput.finishAutofillContext(shouldSave: true); showLoadingDialog(context); try { await loginAction( diff --git a/lib/screens/auth/login/widgets/login_form_fields.dart b/lib/screens/auth/login/widgets/login_form_fields.dart index e2023fb..70971e7 100644 --- a/lib/screens/auth/login/widgets/login_form_fields.dart +++ b/lib/screens/auth/login/widgets/login_form_fields.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:miutem/screens/auth/login/widgets/utem_email_input_formatter.dart'; class LoginFormFields extends StatelessWidget { final TextEditingController usernameController, passwordController; @@ -7,23 +8,30 @@ class LoginFormFields extends StatelessWidget { const LoginFormFields({super.key, required this.usernameController, required this.passwordController, required this.passwordFocus, required this.onLogin, required this.usernameFocus}); + String get fullEmail => '${usernameController.text}@utem.cl'; + @override - Widget build(BuildContext context) => Column( + Widget build(BuildContext context) => AutofillGroup( + onDisposeAction: AutofillContextAction.commit, + child: Column( children: [ TextField( decoration: const InputDecoration( labelText: 'Usuario/Correo', - hintText: 'usuario@utem.cl', + hintText: 'usuario', border: OutlineInputBorder(), prefixIcon: Icon(Icons.alternate_email), + suffixText: '@utem.cl', ), controller: usernameController, autocorrect: false, keyboardType: TextInputType.emailAddress, - autofillHints: const [AutofillHints.email], + autofillHints: const [AutofillHints.username, AutofillHints.email], autofocus: true, onSubmitted: (_) => passwordFocus.requestFocus(), focusNode: usernameFocus, + textInputAction: TextInputAction.next, + inputFormatters: [UtemEmailInputFormatter()], ), const SizedBox(height: 10), TextField( @@ -34,6 +42,7 @@ class LoginFormFields extends StatelessWidget { prefixIcon: Icon(Icons.password), ), autofillHints: const [AutofillHints.password], + keyboardType: TextInputType.visiblePassword, textInputAction: TextInputAction.go, focusNode: passwordFocus, obscureText: true, @@ -52,5 +61,5 @@ class LoginFormFields extends StatelessWidget { ), const SizedBox(height: 10) ], - ); + )); } diff --git a/lib/screens/auth/login/widgets/utem_email_input_formatter.dart b/lib/screens/auth/login/widgets/utem_email_input_formatter.dart new file mode 100644 index 0000000..a7d989f --- /dev/null +++ b/lib/screens/auth/login/widgets/utem_email_input_formatter.dart @@ -0,0 +1,29 @@ +import 'package:flutter/services.dart'; + +/// Custom TextInputFormatter that blocks @ symbol input +/// to restrict users to only @utem.cl domain +class UtemEmailInputFormatter extends TextInputFormatter { + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, + TextEditingValue newValue, + ) { + // Remove any @ symbols from the new text + final filteredText = newValue.text.replaceAll('@', ''); + + if (filteredText == newValue.text) { + return newValue; + } + + // Adjust cursor position if @ was removed + final cursorOffset = newValue.text.length - filteredText.length; + final newCursorPosition = (newValue.selection.baseOffset - cursorOffset) + .clamp(0, filteredText.length); + + return TextEditingValue( + text: filteredText, + selection: TextSelection.collapsed(offset: newCursorPosition), + ); + } +} + diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 2f5d979..ab3da6e 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -588,6 +588,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 11.5; MARKETING_VERSION = 3.0.0; + PRODUCT_BUNDLE_IDENTIFIER = cl.utem.miutem; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; @@ -726,6 +727,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 11.5; MARKETING_VERSION = 3.0.0; + PRODUCT_BUNDLE_IDENTIFIER = cl.utem.miutem; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -752,6 +754,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 11.5; MARKETING_VERSION = 3.0.0; + PRODUCT_BUNDLE_IDENTIFIER = cl.utem.miutem; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements index 8002590..b8cd5c2 100644 --- a/macos/Runner/DebugProfile.entitlements +++ b/macos/Runner/DebugProfile.entitlements @@ -2,17 +2,19 @@ + com.apple.developer.authentication-services.autofill-credential-provider + com.apple.security.app-sandbox com.apple.security.cs.allow-jit - com.apple.security.network.server + com.apple.security.files.downloads.read-write com.apple.security.network.client - - com.apple.security.files.downloads.read-write - - keychain-access-groups - + + com.apple.security.network.server + + keychain-access-groups + diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements index 8db76e4..d0df91a 100644 --- a/macos/Runner/Release.entitlements +++ b/macos/Runner/Release.entitlements @@ -2,15 +2,17 @@ + com.apple.developer.authentication-services.autofill-credential-provider + com.apple.security.app-sandbox + com.apple.security.files.downloads.read-write + com.apple.security.network.client com.apple.security.network.server - com.apple.security.files.downloads.read-write - - keychain-access-groups - + keychain-access-groups + From c8d535583a792879e760f10cb275242b56afde79 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:02:50 -0300 Subject: [PATCH 19/24] feat: enhance theme handling and refactor bloque_ramo_card widget --- lib/core/utils/utilities.dart | 9 ++- lib/screens/horario/horario_screen.dart | 7 +- .../widgets/components/bloque_ramo_card.dart | 66 +++++++++++-------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/lib/core/utils/utilities.dart b/lib/core/utils/utilities.dart index 61c3864..587e742 100644 --- a/lib/core/utils/utilities.dart +++ b/lib/core/utils/utilities.dart @@ -68,7 +68,14 @@ String getToday() { /// Devuelve un color dependiendo si es modo oscuro o no. Color themedColor(BuildContext context, {required Color light, required Color dark}) { - final mode = AdaptiveTheme.of(context).mode; + final adaptiveTheme = AdaptiveTheme.maybeOf(context); + + // Si AdaptiveTheme no está disponible, usar el brillo del sistema + if (adaptiveTheme == null) { + return WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark ? dark : light; + } + + final mode = adaptiveTheme.mode; if(mode.isSystem) { return WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark ? dark : light; } diff --git a/lib/screens/horario/horario_screen.dart b/lib/screens/horario/horario_screen.dart index 37f86ae..b34e734 100644 --- a/lib/screens/horario/horario_screen.dart +++ b/lib/screens/horario/horario_screen.dart @@ -155,8 +155,11 @@ class _HorarioScreenState extends State { ext: 'png', mimeType: MimeType.png, ); - if(context.mounted) Navigator.pop(context); - + // Mostrar toast de éxito + if(context.mounted) { + Navigator.pop(context); + showTextSnackbar(context, title: "Horario guardado", message: "El horario se ha guardado correctamente en tu carpeta de descargas."); + } } else { final directory = await getApplicationDocumentsDirectory(); final imagePath = await File('${directory.path}/horario.png').create(); diff --git a/lib/screens/horario/widgets/components/bloque_ramo_card.dart b/lib/screens/horario/widgets/components/bloque_ramo_card.dart index 4237a11..90927b8 100644 --- a/lib/screens/horario/widgets/components/bloque_ramo_card.dart +++ b/lib/screens/horario/widgets/components/bloque_ramo_card.dart @@ -38,45 +38,58 @@ class ClassBlockCard extends StatelessWidget { child: SizedBox( width: width, height: height, - child: ValueListenableBuilder( - valueListenable: AdaptiveTheme.of(context).modeChangeNotifier, - builder: (ctx, mode, child) => DecoratedBox( - decoration: BoxDecoration( - color: themedColor(context, light: AppTheme.lightBlueCard, dark: AppTheme.darkBlueCard), - borderRadius: BorderRadius.circular(10), - ), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text('${block!.asignatura!.codigo}/${block!.asignatura!.seccion}', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal)), - Space.medium, - Text(block!.asignatura!.nombre, style: Theme.of(context).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w700)), - Space.medium, - Text(block!.sala ?? 'SIN SALA', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal)), - ], - ), - ), - ), - ), + child: _buildBlockContent(context), ), ), ), ); + Widget _buildBlockContent(BuildContext context) { + final adaptiveTheme = AdaptiveTheme.maybeOf(context); + + final content = DecoratedBox( + decoration: BoxDecoration( + color: themedColor(context, light: AppTheme.lightBlueCard, dark: AppTheme.darkBlueCard), + borderRadius: BorderRadius.circular(10), + ), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text('${block!.asignatura!.codigo}/${block!.asignatura!.seccion}', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal)), + Space.medium, + Text(block!.asignatura!.nombre, style: Theme.of(context).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w700), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis), + Space.medium, + Text(block!.sala ?? 'SIN SALA', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal)), + ], + ), + ), + ); + + // Si AdaptiveTheme está disponible, escucha los cambios de tema + if (adaptiveTheme != null) { + return ValueListenableBuilder( + valueListenable: adaptiveTheme.modeChangeNotifier, + builder: (ctx, mode, child) => content, + ); + } + + // Si no está disponible (ej: durante captureFromWidget), retorna el contenido directamente + return content; + } + _onTap(BloqueHorario block, BuildContext context) async { showLoadingDialog(context); - final carrera = await Get.find().getCarrera(); final asignatura = (await Get.find() .getAsignaturas(forceRefresh: true)) .firstWhereOrNull((asignatura) => asignatura.id == block.asignatura?.id || asignatura.codigo == block.asignatura?.codigo); - final grades = await Get.find().getGrades(asignatura!); - if (carrera == null || asignatura == null) { + if (asignatura == null) { if(context.mounted) Navigator.pop(context); return; } + // final grades = await Get.find().getGrades(asignatura); if(context.mounted) Navigator.pop(context); // if(context.mounted) Navigator.push(context, MaterialPageRoute(builder: (ctx) => AsignaturaScreen(asignatura))); // Navigator.push(context, MaterialPageRoute(builder: (ctx) => AsignaturaDetalleScreen( @@ -87,11 +100,10 @@ class ClassBlockCard extends StatelessWidget { _onLongPress(BloqueHorario block, BuildContext context) async { showLoadingDialog(context); - final carrera = await Get.find().getCarrera(); final asignatura = (await Get.find() .getAsignaturas(forceRefresh: true)) .firstWhereOrNull((asignatura) => asignatura.id == block.asignatura?.id || asignatura.codigo == block.asignatura?.codigo); - if (carrera == null || asignatura == null) { + if (asignatura == null) { if(context.mounted) Navigator.pop(context); return; } From 21d6e543a0554d14f59589ad4203bb6a498c3834 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:10:39 -0300 Subject: [PATCH 20/24] feat: implement pastel color scheme and contrast text color for class blocks --- .../controllers/horario_controller.dart | 71 ++++++++++++++++++- .../widgets/components/bloque_clase.dart | 60 +++++++++------- .../widgets/components/bloque_ramo_card.dart | 17 +++-- 3 files changed, 110 insertions(+), 38 deletions(-) diff --git a/lib/core/services/controllers/horario_controller.dart b/lib/core/services/controllers/horario_controller.dart index 0761bb0..6cc786d 100644 --- a/lib/core/services/controllers/horario_controller.dart +++ b/lib/core/services/controllers/horario_controller.dart @@ -11,7 +11,51 @@ import 'package:vector_math/vector_math_64.dart' as vector; class HorarioController { final _storage = GetStorage(); - final _randomColors = Colors.primaries.toList()..shuffle(); + + /// Lista de colores pastel de Material Design para las tarjetas de clases + static final List _pastelColors = [ + // Material 100 + const Color(0xFFB3E5FC), // Light Blue 100 + const Color(0xFFC8E6C9), // Green 100 + const Color(0xFFF8BBD9), // Pink 100 + const Color(0xFFFFE0B2), // Orange 100 + const Color(0xFFD1C4E9), // Deep Purple 100 + const Color(0xFFB2EBF2), // Cyan 100 + const Color(0xFFFFF9C4), // Yellow 100 + const Color(0xFFFFCCBC), // Deep Orange 100 + const Color(0xFFC5CAE9), // Indigo 100 + const Color(0xFFDCEDC8), // Light Green 100 + const Color(0xFFF0F4C3), // Lime 100 + const Color(0xFFE1BEE7), // Purple 100 + // Material 200 + const Color(0xFFFFE082), // Amber 200 + const Color(0xFF80DEEA), // Cyan 200 + const Color(0xFFCE93D8), // Purple 200 + const Color(0xFFA5D6A7), // Green 200 + const Color(0xFFEF9A9A), // Red 200 + const Color(0xFF90CAF9), // Blue 200 + const Color(0xFFBCAAA4), // Brown 200 + const Color(0xFFB0BEC5), // Blue Grey 200 + // Material 50 (más claros) + const Color(0xFFE3F2FD), // Blue 50 + const Color(0xFFE8F5E9), // Green 50 + const Color(0xFFFCE4EC), // Pink 50 + const Color(0xFFFFF3E0), // Orange 50 + const Color(0xFFEDE7F6), // Deep Purple 50 + const Color(0xFFE0F7FA), // Cyan 50 + const Color(0xFFFFFDE7), // Yellow 50 + const Color(0xFFFBE9E7), // Deep Orange 50 + // Material 300 (un poco más saturados) + const Color(0xFF81D4FA), // Light Blue 300 + const Color(0xFFF48FB1), // Pink 300 + const Color(0xFFFFB74D), // Orange 300 + const Color(0xFFB39DDB), // Deep Purple 300 + const Color(0xFF4DD0E1), // Cyan 300 + const Color(0xFFAED581), // Light Green 300 + const Color(0xFFBA68C8), // Purple 300 + ]; + + final _randomColors = List.from(_pastelColors)..shuffle(); final _now = DateTime.now(); num daysCount = 6; @@ -90,7 +134,7 @@ class HorarioController { final newColor = color ?? unusedColors.first; final key = '${asignatura.codigo}_${asignatura.tipoHora}'; usedColors.add(newColor); - _storage.write(key, newColor.value); + _storage.write(key, newColor.toARGB32()); } Color? getColor(Asignatura? asignatura){ @@ -98,6 +142,29 @@ class HorarioController { return let(_storage.read('${asignatura.codigo}_${asignatura.tipoHora}'), (dynamic element)=> Color(element)); } + /// Obtiene el color de fondo y el color de texto con contraste para una asignatura + ({Color background, Color text})? getColorWithContrast(Asignatura? asignatura) { + final backgroundColor = getColor(asignatura); + if (backgroundColor == null) return null; + return (background: backgroundColor, text: _getContrastTextColor(backgroundColor)); + } + + /// Calcula el color de texto ideal (claro u oscuro) para un color de fondo dado + /// usando el algoritmo de luminancia relativa de WCAG + static Color _getContrastTextColor(Color backgroundColor) { + // Calcular luminancia relativa según WCAG 2.0 + final double luminance = backgroundColor.computeLuminance(); + + // Si el fondo es claro (luminancia > 0.5), usar texto oscuro + // Si el fondo es oscuro, usar texto claro + // Usamos 0.5 como umbral pero ajustado a 0.45 para mejor contraste en colores pastel + if (luminance > 0.45) { + return const Color(0xFF1A1A1A); // Gris muy oscuro para mejor legibilidad + } else { + return const Color(0xFFFFFFFF); // Blanco + } + } + /// /// Funciones para mover dentro del horario /// diff --git a/lib/screens/horario/widgets/components/bloque_clase.dart b/lib/screens/horario/widgets/components/bloque_clase.dart index 0a96fef..215602b 100644 --- a/lib/screens/horario/widgets/components/bloque_clase.dart +++ b/lib/screens/horario/widgets/components/bloque_clase.dart @@ -8,7 +8,7 @@ class BloqueClase extends StatelessWidget { final BloqueHorario block; final double width; final double height; - final Color textColor; + final Color? textColor; final Color? color; final void Function(BloqueHorario)? onTap; final void Function(BloqueHorario)? onLongPress; @@ -18,41 +18,47 @@ class BloqueClase extends StatelessWidget { required this.block, required this.width, required this.height, - required this.textColor, + this.textColor, this.color = Colors.teal, this.onTap, this.onLongPress, }); @override - Widget build(BuildContext context) => DecoratedBox( - decoration: BoxDecoration( - color: Get.find().getColor(block.asignatura) ?? this.color, - borderRadius: BorderRadius.circular(15), - ), - child: Material( - color: Colors.transparent, - child: InkWell( + Widget build(BuildContext context) { + final colorData = Get.find().getColorWithContrast(block.asignatura); + final backgroundColor = colorData?.background ?? this.color ?? Colors.teal; + final effectiveTextColor = this.textColor ?? colorData?.text ?? Colors.white; + + return DecoratedBox( + decoration: BoxDecoration( + color: backgroundColor, borderRadius: BorderRadius.circular(15), - onTap: () => onTap?.call(block), - onLongPress: () => onLongPress?.call(block), - child: Column( - children: [ - HorarioText.classCode("${block.codigo}", - color: textColor, - ), - HorarioText.className("${block.asignatura?.nombre.toUpperCase()}", - color: textColor, - ), - HorarioText.classLocation(block.sala ?? "Sin sala", - color: textColor, - ), - ], - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(15), + onTap: () => onTap?.call(block), + onLongPress: () => onLongPress?.call(block), + child: Column( + children: [ + HorarioText.classCode("${block.codigo}", + color: effectiveTextColor, + ), + HorarioText.className("${block.asignatura?.nombre.toUpperCase()}", + color: effectiveTextColor, + ), + HorarioText.classLocation(block.sala ?? "Sin sala", + color: effectiveTextColor, + ), + ], + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + ), ), ), - ), - ); + ); + } } diff --git a/lib/screens/horario/widgets/components/bloque_ramo_card.dart b/lib/screens/horario/widgets/components/bloque_ramo_card.dart index 90927b8..5d641e2 100644 --- a/lib/screens/horario/widgets/components/bloque_ramo_card.dart +++ b/lib/screens/horario/widgets/components/bloque_ramo_card.dart @@ -3,13 +3,9 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:miutem/core/models/horario.dart'; import 'package:miutem/core/services/asignaturas_service.dart'; -import 'package:miutem/core/services/carrera_service.dart'; -import 'package:miutem/core/services/grades_service.dart'; +import 'package:miutem/core/services/controllers/horario_controller.dart'; import 'package:miutem/core/utils/utilities.dart'; -import 'package:miutem/screens/asignaturas/lista_asignaturas_screen.dart'; import 'package:miutem/screens/horario/widgets/modals/vista_previa_asignatura_modal.dart'; -import 'package:miutem/screens/tasklist/task_list_screen.dart'; -import 'package:miutem/styles/loading/loading_dialog.dart'; import 'package:miutem/styles/styles.dart'; class ClassBlockCard extends StatelessWidget { @@ -46,10 +42,13 @@ class ClassBlockCard extends StatelessWidget { Widget _buildBlockContent(BuildContext context) { final adaptiveTheme = AdaptiveTheme.maybeOf(context); + final colorData = Get.find().getColorWithContrast(block?.asignatura); + final backgroundColor = colorData?.background ?? themedColor(context, light: AppTheme.lightBlueCard, dark: AppTheme.darkBlueCard); + final textColor = colorData?.text ?? Theme.of(context).textTheme.bodyMedium?.color; final content = DecoratedBox( decoration: BoxDecoration( - color: themedColor(context, light: AppTheme.lightBlueCard, dark: AppTheme.darkBlueCard), + color: backgroundColor, borderRadius: BorderRadius.circular(10), ), child: Center( @@ -57,11 +56,11 @@ class ClassBlockCard extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text('${block!.asignatura!.codigo}/${block!.asignatura!.seccion}', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal)), + Text('${block!.asignatura!.codigo}/${block!.asignatura!.seccion}', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal, color: textColor)), Space.medium, - Text(block!.asignatura!.nombre, style: Theme.of(context).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w700), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis), + Text(block!.asignatura!.nombre, style: Theme.of(context).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w700, color: textColor), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis), Space.medium, - Text(block!.sala ?? 'SIN SALA', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal)), + Text(block!.sala ?? 'SIN SALA', style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.normal, color: textColor)), ], ), ), From 3fec4dfa1a035e336cf6ea2384cb57bf9c5e30fc Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:30:41 -0300 Subject: [PATCH 21/24] =?UTF-8?q?feat:=20add=20Malla=20Hist=C3=B3rica=20sc?= =?UTF-8?q?reen=20and=20related=20components=20for=20displaying=20historic?= =?UTF-8?q?al=20course=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mi_utem/miutem_malla_service.dart | 2 +- .../asignaturas/actions/acceso_rapido.dart | 5 +- .../asignaturas/widgets/acceso_rapido.dart | 2 +- .../malla_historica_screen.dart | 118 +++++++++++ .../components/asignatura_malla_card.dart | 191 ++++++++++++++++++ .../components/semestre_header_card.dart | 46 +++++ .../widgets/screens/malla_blocks_content.dart | 74 +++++++ .../widgets/screens/malla_main_scroller.dart | 85 ++++++++ .../screens/malla_semestres_header.dart | 47 +++++ .../malla_historica/widgets/widgets.dart | 11 + 10 files changed, 578 insertions(+), 3 deletions(-) create mode 100644 lib/screens/malla_historica/malla_historica_screen.dart create mode 100644 lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart create mode 100644 lib/screens/malla_historica/widgets/components/semestre_header_card.dart create mode 100644 lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart create mode 100644 lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart create mode 100644 lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart create mode 100644 lib/screens/malla_historica/widgets/widgets.dart diff --git a/lib/core/services/mi_utem/miutem_malla_service.dart b/lib/core/services/mi_utem/miutem_malla_service.dart index c651141..da2bb76 100644 --- a/lib/core/services/mi_utem/miutem_malla_service.dart +++ b/lib/core/services/mi_utem/miutem_malla_service.dart @@ -32,7 +32,7 @@ class MiUTEMMallaService { throw CustomException(message: "No se pudo obtener la malla. Por favor intenta más tarde.", internalCode: 2); } - return (htmlDoc.querySelectorAll("div[id=collapseTwo][class*=show] > div > div > div > #table-avance").first).querySelectorAll("table > tbody > tr").map((it) { + return (htmlDoc.querySelectorAll("div[id=avance-malla][class*=show] > div > div > div > div > div > #table-avance").first).querySelectorAll("tbody > tr").map((it) { final parts = it.children; return AsignaturaMalla( nivel: int.tryParse(parts[0].text.trim()) ?? 0, diff --git a/lib/screens/asignaturas/actions/acceso_rapido.dart b/lib/screens/asignaturas/actions/acceso_rapido.dart index e976c6f..9e0716d 100644 --- a/lib/screens/asignaturas/actions/acceso_rapido.dart +++ b/lib/screens/asignaturas/actions/acceso_rapido.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; import 'package:miutem/screens/horario/horario_screen.dart'; +import 'package:miutem/screens/malla_historica/malla_historica_screen.dart'; import 'package:miutem/screens/notas/notas_screen.dart'; void visitarCalculadoraNotas(BuildContext context) => Navigator.push(context, MaterialPageRoute(builder: (ctx) => const NotasScreen())); -void visitarHorario(BuildContext context) => Navigator.push(context, MaterialPageRoute(builder: (ctx) => const HorarioScreen())); \ No newline at end of file +void visitarHorario(BuildContext context) => Navigator.push(context, MaterialPageRoute(builder: (ctx) => const HorarioScreen())); + +void visitarMallaHistorica(BuildContext context) => Navigator.push(context, MaterialPageRoute(builder: (ctx) => const MallaHistoricaScreen())); diff --git a/lib/screens/asignaturas/widgets/acceso_rapido.dart b/lib/screens/asignaturas/widgets/acceso_rapido.dart index 0edd38d..750df71 100644 --- a/lib/screens/asignaturas/widgets/acceso_rapido.dart +++ b/lib/screens/asignaturas/widgets/acceso_rapido.dart @@ -31,7 +31,7 @@ class AccesoRapido extends StatelessWidget { label: 'Malla Histórica', icon: AppIcons.historicTimetable, fill: 0, - onTap: () => {}, + onTap: () => visitarMallaHistorica(context), ), const SizedBox(width: 10), CardAccesoRapido( diff --git a/lib/screens/malla_historica/malla_historica_screen.dart b/lib/screens/malla_historica/malla_historica_screen.dart new file mode 100644 index 0000000..d920cd1 --- /dev/null +++ b/lib/screens/malla_historica/malla_historica_screen.dart @@ -0,0 +1,118 @@ +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; +import 'package:miutem/core/models/exceptions/custom_exception.dart'; +import 'package:miutem/core/services/mi_utem/miutem_malla_service.dart'; +import 'package:miutem/core/utils/utils.dart'; +import 'package:miutem/screens/malla_historica/widgets/widgets.dart'; +import 'package:miutem/styles/styles.dart'; + +class MallaHistoricaScreen extends StatefulWidget { + const MallaHistoricaScreen({super.key}); + + @override + State createState() => _MallaHistoricaScreenState(); +} + +class _MallaHistoricaScreenState extends State { + Future>? _mallaFuture; + + @override + void initState() { + super.initState(); + _mallaFuture = _getMalla(); + } + + Future> _getMalla() async { + try { + final malla = await MiUTEMMallaService.get.getMalla(); + logger.d(malla); + return malla; + } catch (e) { + logger.e("Error al obtener la malla histórica", error: e); + rethrow; + } + } + + @override + Widget build(BuildContext context) { + return FutureBuilder>( + future: _mallaFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Scaffold( + appBar: AppBar( + title: const Text("Malla Histórica"), + ), + body: LoadingIndicator.centeredDefault(), + ); + } + + final esErrorOffline = snapshot.hasError && + snapshot.error is DioError && + (snapshot.error as DioError).type == DioErrorType.cancel && + (snapshot.error as DioError).response?.extra["offline"] == true; + + if ((snapshot.hasError && !esErrorOffline) || !snapshot.hasData || snapshot.data == null) { + String errorMessage = "Ocurrió un error al cargar la malla. Por favor intenta más tarde."; + final error = snapshot.error; + if (error != null) { + errorMessage = error is CustomException + ? error.message + : "Ocurrió un error al cargar la malla. Por favor intenta más tarde."; + } + + return Scaffold( + appBar: AppBar( + title: const Text("Malla Histórica"), + actions: [ + IconButton( + onPressed: _reloadData, + icon: const Icon(Icons.refresh_sharp), + tooltip: "Forzar actualización de la malla", + ) + ], + ), + body: Center( + child: CustomErrorWidget( + title: "Error al cargar la malla", + error: errorMessage, + ), + ), + ); + } + + final asignaturas = snapshot.data!; + + return Scaffold( + appBar: AppBar( + title: const Text("Malla Histórica"), + actions: [ + PopupMenuButton( + position: PopupMenuPosition.under, + icon: const Icon(Icons.more_vert), + itemBuilder: (ctx) => [ + PopupMenuItem( + onTap: _reloadData, + child: const ListTile( + leading: Icon(Icons.refresh_sharp), + title: Text("Recargar"), + ), + ), + ], + ), + ], + ), + body: SafeArea( + child: MallaMainScroller( + asignaturas: asignaturas, + ), + ), + ); + }, + ); + } + + void _reloadData() => setState(() => _mallaFuture = _getMalla()); +} + diff --git a/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart b/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart new file mode 100644 index 0000000..8107ca3 --- /dev/null +++ b/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart @@ -0,0 +1,191 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; +import 'package:miutem/core/utils/utilities.dart'; +import 'package:miutem/styles/styles.dart'; + +class AsignaturaMallaCard extends StatelessWidget { + final AsignaturaMalla asignatura; + final double width; + final double height; + final double internalMargin; + + const AsignaturaMallaCard({ + super.key, + required this.asignatura, + required this.width, + required this.height, + this.internalMargin = 8, + }); + + Color _getBackgroundColor(BuildContext context) { + final estado = asignatura.estado.toLowerCase(); + if (estado.contains('aprobado') || estado.contains('aprobada')) { + return themedColor(context, + light: AppTheme.lightGreenCard, + dark: AppTheme.darkGreenCard, + ); + } else if (estado.contains('reprobado') || estado.contains('reprobada')) { + return themedColor(context, + light: AppTheme.lightSalmonCard, + dark: AppTheme.darkSalmonCard, + ); + } else if (estado.contains('cursando') || estado.contains('inscrit')) { + return themedColor(context, + light: AppTheme.lightBlueCard, + dark: AppTheme.darkBlueCard, + ); + } + return themedColor(context, + light: AppTheme.lightYellowCard, + dark: AppTheme.darkYellowCard, + ); + } + + Color _getTextColor(BuildContext context) { + final backgroundColor = _getBackgroundColor(context); + final brightness = ThemeData.estimateBrightnessForColor(backgroundColor); + return brightness == Brightness.light ? Colors.black87 : Colors.white; + } + + @override + Widget build(BuildContext context) { + final backgroundColor = _getBackgroundColor(context); + final textColor = _getTextColor(context); + + return SizedBox( + height: height, + width: width, + child: Padding( + padding: EdgeInsets.all(internalMargin), + child: GestureDetector( + onTap: () => _showAsignaturaDetail(context), + child: DecoratedBox( + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + asignatura.nombre, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + color: textColor, + ), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + Space.xSmall, + Text( + asignatura.tipo, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: textColor.withValues(alpha: 0.8), + ), + textAlign: TextAlign.center, + ), + Space.xSmall, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildChip(context, asignatura.nota, textColor, backgroundColor), + Space.xSmall, + _buildChip(context, asignatura.estado, textColor, backgroundColor), + ], + ), + ], + ), + ), + ), + ), + ), + ); + } + + Widget _buildChip(BuildContext context, String label, Color textColor, Color backgroundColor) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: textColor.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + label, + style: Theme.of(context).textTheme.labelSmall?.copyWith( + color: textColor, + fontWeight: FontWeight.w500, + ), + ), + ); + } + + void _showAsignaturaDetail(BuildContext context) { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + builder: (ctx) => SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + Space.medium, + Text( + asignatura.nombre, + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Space.medium, + _buildDetailRow(context, 'Tipo', asignatura.tipo), + _buildDetailRow(context, 'Estado', asignatura.estado), + _buildDetailRow(context, 'Nota', asignatura.nota), + _buildDetailRow(context, 'Nivel', asignatura.nivel.toString()), + _buildDetailRow(context, 'Intentos', asignatura.intentos.toString()), + Space.large, + ], + ), + ), + ); + } + + Widget _buildDetailRow(BuildContext context, String label, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).textTheme.bodySmall?.color, + ), + ), + Text( + value, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ); + } +} + diff --git a/lib/screens/malla_historica/widgets/components/semestre_header_card.dart b/lib/screens/malla_historica/widgets/components/semestre_header_card.dart new file mode 100644 index 0000000..a0557bf --- /dev/null +++ b/lib/screens/malla_historica/widgets/components/semestre_header_card.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/styles/styles.dart'; + +class SemestreHeaderCard extends StatelessWidget { + final int semestre; + final double width; + final double height; + + const SemestreHeaderCard({ + super.key, + required this.semestre, + required this.width, + required this.height, + }); + + @override + Widget build(BuildContext context) => SizedBox( + height: height, + width: width, + child: DecoratedBox( + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Sem.', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.normal, + ), + ), + Text( + '$semestre', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ); +} + diff --git a/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart b/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart new file mode 100644 index 0000000..94ebdfc --- /dev/null +++ b/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; +import 'package:miutem/screens/malla_historica/widgets/components/asignatura_malla_card.dart'; + +class MallaBlocksContent extends StatelessWidget { + final List> asignaturasPorSemestre; + final double blockHeight; + final double blockWidth; + final double blockInternalMargin; + final double borderWidth; + + const MallaBlocksContent({ + super.key, + required this.asignaturasPorSemestre, + required this.blockHeight, + required this.blockWidth, + this.blockInternalMargin = 8, + this.borderWidth = 2, + }); + + int get _maxAsignaturasPorSemestre { + if (asignaturasPorSemestre.isEmpty) return 0; + return asignaturasPorSemestre.map((s) => s.length).reduce((a, b) => a > b ? a : b); + } + + List get _children { + final rows = []; + final maxRows = _maxAsignaturasPorSemestre; + + for (int rowIndex = 0; rowIndex < maxRows; rowIndex++) { + final currentRow = []; + + for (int semestreIndex = 0; semestreIndex < asignaturasPorSemestre.length; semestreIndex++) { + final asignaturas = asignaturasPorSemestre[semestreIndex]; + + if (rowIndex < asignaturas.length) { + currentRow.add(AsignaturaMallaCard( + asignatura: asignaturas[rowIndex], + height: blockHeight, + width: blockWidth, + internalMargin: blockInternalMargin, + )); + } else { + // Celda vacía + currentRow.add(SizedBox( + height: blockHeight, + width: blockWidth, + )); + } + } + rows.add(TableRow(children: currentRow)); + } + return rows; + } + + @override + Widget build(BuildContext context) => Table( + defaultColumnWidth: FixedColumnWidth(blockWidth), + border: TableBorder( + horizontalInside: BorderSide( + color: Theme.of(context).dividerColor, + style: BorderStyle.solid, + width: borderWidth, + ), + verticalInside: BorderSide( + color: Theme.of(context).dividerColor, + style: BorderStyle.solid, + width: borderWidth, + ), + ), + children: _children, + ); +} + diff --git a/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart b/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart new file mode 100644 index 0000000..232b83e --- /dev/null +++ b/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; +import 'package:miutem/screens/malla_historica/widgets/screens/malla_blocks_content.dart'; +import 'package:miutem/screens/malla_historica/widgets/screens/malla_semestres_header.dart'; + +class MallaMainScroller extends StatelessWidget { + static const double blockWidth = 180.0; + static const double blockHeight = 140.0; + static const double blockInternalMargin = 6.0; + static const double semestreHeaderHeight = 60.0; + static const double borderWidth = 2.0; + + final List asignaturas; + + const MallaMainScroller({ + super.key, + required this.asignaturas, + }); + + /// Agrupa las asignaturas por nivel (semestre) + List> get _asignaturasPorSemestre { + if (asignaturas.isEmpty) return []; + + final maxNivel = asignaturas.map((a) => a.nivel).reduce((a, b) => a > b ? a : b); + final result = List>.generate(maxNivel, (_) => []); + + for (final asignatura in asignaturas) { + if (asignatura.nivel > 0 && asignatura.nivel <= maxNivel) { + result[asignatura.nivel - 1].add(asignatura); + } + } + + return result; + } + + int get _cantidadSemestres => _asignaturasPorSemestre.length; + + int get _maxAsignaturasPorSemestre { + final porSemestre = _asignaturasPorSemestre; + if (porSemestre.isEmpty) return 0; + return porSemestre.map((s) => s.length).reduce((a, b) => a > b ? a : b); + } + + double get totalWidth => blockWidth * _cantidadSemestres; + double get totalHeight => semestreHeaderHeight + (blockHeight * _maxAsignaturasPorSemestre); + + Widget get _mallaSemestresHeader => MallaSemestresHeader( + cantidadSemestres: _cantidadSemestres, + height: semestreHeaderHeight, + semestreWidth: blockWidth, + ); + + Widget get _mallaBlocksContent => MallaBlocksContent( + asignaturasPorSemestre: _asignaturasPorSemestre, + blockHeight: blockHeight, + blockWidth: blockWidth, + blockInternalMargin: blockInternalMargin, + ); + + @override + Widget build(BuildContext context) { + if (asignaturas.isEmpty) { + return const Center( + child: Text('No hay asignaturas para mostrar'), + ); + } + + return InteractiveViewer( + constrained: false, + minScale: 0.3, + maxScale: 2.0, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _mallaSemestresHeader, + _mallaBlocksContent, + ], + ), + ), + ); + } +} + diff --git a/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart b/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart new file mode 100644 index 0000000..9059300 --- /dev/null +++ b/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:miutem/screens/malla_historica/widgets/components/semestre_header_card.dart'; + +class MallaSemestresHeader extends StatelessWidget { + final int cantidadSemestres; + final double height; + final double semestreWidth; + final double borderWidth; + + const MallaSemestresHeader({ + super.key, + required this.cantidadSemestres, + required this.height, + required this.semestreWidth, + this.borderWidth = 2, + }); + + @override + Widget build(BuildContext context) => Table( + defaultColumnWidth: FixedColumnWidth(semestreWidth), + border: TableBorder( + verticalInside: BorderSide( + color: Theme.of(context).dividerColor, + style: BorderStyle.solid, + width: borderWidth, + ), + bottom: BorderSide( + color: Theme.of(context).dividerColor, + style: BorderStyle.solid, + width: borderWidth, + ), + ), + children: [ + TableRow( + children: List.generate( + cantidadSemestres, + (index) => SemestreHeaderCard( + semestre: index + 1, + height: height, + width: semestreWidth, + ), + ), + ), + ], + ); +} + diff --git a/lib/screens/malla_historica/widgets/widgets.dart b/lib/screens/malla_historica/widgets/widgets.dart new file mode 100644 index 0000000..2a39710 --- /dev/null +++ b/lib/screens/malla_historica/widgets/widgets.dart @@ -0,0 +1,11 @@ +/// Components +library; + +export 'components/asignatura_malla_card.dart'; +export 'components/semestre_header_card.dart'; + +/// Screens +export 'screens/malla_blocks_content.dart'; +export 'screens/malla_semestres_header.dart'; +export 'screens/malla_main_scroller.dart'; + From 57781af585b0f9ae26a27056bbdbfd3e41989795 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:21:55 -0300 Subject: [PATCH 22/24] feat: implement caching for Malla data retrieval and enhance UI components --- devtools_options.yaml | 3 + .../models/asignaturas/asignatura_malla.dart | 13 ++ .../mi_utem/miutem_malla_service.dart | 110 ++++++++++- lib/core/utils/http/http_client.dart | 10 + .../malla_historica_screen.dart | 18 +- .../components/asignatura_malla_card.dart | 186 +++++++++--------- .../components/semestre_header_card.dart | 18 +- .../widgets/screens/malla_blocks_content.dart | 86 ++++---- .../widgets/screens/malla_main_scroller.dart | 180 +++++++++++++---- .../screens/malla_semestres_header.dart | 48 ++--- lib/styles/theme/space.dart | 11 ++ 11 files changed, 442 insertions(+), 241 deletions(-) create mode 100644 devtools_options.yaml diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/core/models/asignaturas/asignatura_malla.dart b/lib/core/models/asignaturas/asignatura_malla.dart index 1567aab..1ed95dd 100644 --- a/lib/core/models/asignaturas/asignatura_malla.dart +++ b/lib/core/models/asignaturas/asignatura_malla.dart @@ -13,6 +13,19 @@ class AsignaturaMalla { required this.nota, }); + factory AsignaturaMalla.fromJson(Map json) => AsignaturaMalla( + nivel: json['nivel'] as int, + intentos: json['intentos'] as int, + nombre: json['nombre'] as String, + tipo: json['tipo'] as String, + estado: json['estado'] as String, + nota: json['nota'] as String, + ); + + static List fromJsonList(dynamic json) => json != null + ? (json as List).map((it) => AsignaturaMalla.fromJson(it as Map)).toList() + : []; + toJson() => { 'nivel': nivel, 'intentos': intentos, diff --git a/lib/core/services/mi_utem/miutem_malla_service.dart b/lib/core/services/mi_utem/miutem_malla_service.dart index da2bb76..855e37b 100644 --- a/lib/core/services/mi_utem/miutem_malla_service.dart +++ b/lib/core/services/mi_utem/miutem_malla_service.dart @@ -1,19 +1,115 @@ +import 'dart:convert'; + import 'package:dio/dio.dart'; import 'package:get/get.dart'; import 'package:html/parser.dart' show parse; import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; import 'package:miutem/core/models/exceptions/custom_exception.dart'; import 'package:miutem/core/services/mi_utem/miutem_auth_service.dart'; +import 'package:miutem/core/utils/constants.dart'; import 'package:miutem/core/utils/http/http_client.dart'; import 'package:miutem/core/utils/utils.dart'; +const String _mallaCacheKey = "malla_cache"; +const String _mallaCacheTimestampKey = "malla_cache_timestamp"; +const Duration _cacheDuration = Duration(hours: 6); + class MiUTEMMallaService { static MiUTEMMallaService get get => Get.find(); - Future> getMalla() async { + /// Caché en memoria para evitar lecturas repetidas de SharedPreferences + List? _memoryCache; + DateTime? _memoryCacheTimestamp; + + /// Obtiene la malla, usando caché si está disponible y no ha expirado. + /// [forceRefresh] fuerza una actualización desde el servidor. + Future> getMalla({bool forceRefresh = false}) async { + // Si no se fuerza refresh, intentar obtener desde caché + if (!forceRefresh) { + final cachedMalla = await _getCachedMalla(); + if (cachedMalla != null) { + return cachedMalla; + } + } + + // Obtener desde el servidor + final malla = await _fetchMallaFromServer(); + + // Guardar en caché + await _saveMallaToCache(malla); + + return malla; + } + + /// Obtiene la malla desde el caché (memoria o persistente) + Future?> _getCachedMalla() async { + // Primero revisar caché en memoria + if (_memoryCache != null && _memoryCacheTimestamp != null) { + if (DateTime.now().difference(_memoryCacheTimestamp!) < _cacheDuration) { + logger.d('Malla obtenida desde caché en memoria'); + return _memoryCache; + } + } + + // Si no hay caché en memoria, revisar SharedPreferences + try { + final cachedData = await sharedPreferences.getString(_mallaCacheKey); + final cachedTimestamp = await sharedPreferences.getInt(_mallaCacheTimestampKey); + + if (cachedData != null && cachedTimestamp != null) { + final cacheTime = DateTime.fromMillisecondsSinceEpoch(cachedTimestamp); + if (DateTime.now().difference(cacheTime) < _cacheDuration) { + final jsonList = jsonDecode(cachedData) as List; + final malla = AsignaturaMalla.fromJsonList(jsonList); + + // Actualizar caché en memoria + _memoryCache = malla; + _memoryCacheTimestamp = cacheTime; + + logger.d('Malla obtenida desde caché persistente'); + return malla; + } + } + } catch (e) { + logger.e('Error al leer caché de malla', error: e); + } + + return null; + } + + /// Guarda la malla en caché (memoria y persistente) + Future _saveMallaToCache(List malla) async { + final now = DateTime.now(); + + // Guardar en memoria + _memoryCache = malla; + _memoryCacheTimestamp = now; + + // Guardar en SharedPreferences + try { + final jsonString = jsonEncode(malla.map((e) => e.toJson()).toList()); + await sharedPreferences.setString(_mallaCacheKey, jsonString); + await sharedPreferences.setInt(_mallaCacheTimestampKey, now.millisecondsSinceEpoch); + logger.d('Malla guardada en caché'); + } catch (e) { + logger.e('Error al guardar caché de malla', error: e); + } + } + + /// Limpia el caché de la malla + Future clearCache() async { + _memoryCache = null; + _memoryCacheTimestamp = null; + await sharedPreferences.remove(_mallaCacheKey); + await sharedPreferences.remove(_mallaCacheTimestampKey); + logger.d('Caché de malla limpiado'); + } + + /// Obtiene la malla directamente desde el servidor + Future> _fetchMallaFromServer() async { final cookie = await MiUTEMAuthService.get.login(); - final response = await HttpClient.httpClient.get("$miUtemHost/academicos/mi-malla", + final response = await HttpClient.httpCachedClient.get("$miUtemHost/academicos/mi-malla", options: Options( headers: { 'Cookie': cookie, @@ -32,15 +128,21 @@ class MiUTEMMallaService { throw CustomException(message: "No se pudo obtener la malla. Por favor intenta más tarde.", internalCode: 2); } - return (htmlDoc.querySelectorAll("div[id=avance-malla][class*=show] > div > div > div > div > div > #table-avance").first).querySelectorAll("tbody > tr").map((it) { + logger.d('Malla obtenida desde el servidor'); + return (htmlDoc.querySelectorAll("#avance-malla").first.querySelectorAll("#table-avance").first).querySelectorAll("tbody > tr").map((it) { final parts = it.children; + var nota = parts[5].text.trim(); + if(nota.isEmpty) { + nota = "-"; + } + return AsignaturaMalla( nivel: int.tryParse(parts[0].text.trim()) ?? 0, nombre: parts[1].text.trim(), tipo: parts[2].text.trim(), intentos: int.tryParse(parts[3].text.trim()) ?? 0, estado: parts[4].text.trim(), - nota: parts[5].text.trim(), + nota: nota, ); }).toList(); } diff --git a/lib/core/utils/http/http_client.dart b/lib/core/utils/http/http_client.dart index f6c1d89..b32c9d2 100644 --- a/lib/core/utils/http/http_client.dart +++ b/lib/core/utils/http/http_client.dart @@ -8,6 +8,12 @@ import 'package:miutem/core/utils/http/interceptors/offline_mode_interceptor.dar class HttpClient { + static final DioCacheManager cacheManager = DioCacheManager(CacheConfig( + baseUrl: miUtemHost, + defaultMaxAge: const Duration(days: 7), + defaultMaxStale: const Duration(days: 14), + )); + static final DioCacheManager cacheManagerSiga = DioCacheManager(CacheConfig( baseUrl: sigaServiceUri, defaultMaxAge: const Duration(days: 7), @@ -24,6 +30,10 @@ class HttpClient { errorInterceptor, ]); + static final httpCachedClient = httpClient..interceptors.addAll([ + cacheManager.interceptor, + ]); + static final Dio authClientSiga = httpClient..interceptors.addAll([ cacheManagerSiga.interceptor, ]); diff --git a/lib/screens/malla_historica/malla_historica_screen.dart b/lib/screens/malla_historica/malla_historica_screen.dart index d920cd1..ef02b54 100644 --- a/lib/screens/malla_historica/malla_historica_screen.dart +++ b/lib/screens/malla_historica/malla_historica_screen.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; import 'package:miutem/core/models/exceptions/custom_exception.dart'; import 'package:miutem/core/services/mi_utem/miutem_malla_service.dart'; -import 'package:miutem/core/utils/utils.dart'; import 'package:miutem/screens/malla_historica/widgets/widgets.dart'; import 'package:miutem/styles/styles.dart'; @@ -23,15 +22,8 @@ class _MallaHistoricaScreenState extends State { _mallaFuture = _getMalla(); } - Future> _getMalla() async { - try { - final malla = await MiUTEMMallaService.get.getMalla(); - logger.d(malla); - return malla; - } catch (e) { - logger.e("Error al obtener la malla histórica", error: e); - rethrow; - } + Future> _getMalla({bool forceRefresh = false}) async { + return await MiUTEMMallaService.get.getMalla(forceRefresh: forceRefresh); } @override @@ -113,6 +105,10 @@ class _MallaHistoricaScreenState extends State { ); } - void _reloadData() => setState(() => _mallaFuture = _getMalla()); + void _reloadData() { + setState(() { + _mallaFuture = _getMalla(forceRefresh: true); + }); + } } diff --git a/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart b/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart index 8107ca3..eaa1765 100644 --- a/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart +++ b/lib/screens/malla_historica/widgets/components/asignatura_malla_card.dart @@ -5,16 +5,10 @@ import 'package:miutem/styles/styles.dart'; class AsignaturaMallaCard extends StatelessWidget { final AsignaturaMalla asignatura; - final double width; - final double height; - final double internalMargin; const AsignaturaMallaCard({ super.key, required this.asignatura, - required this.width, - required this.height, - this.internalMargin = 8, }); Color _getBackgroundColor(BuildContext context) { @@ -52,63 +46,61 @@ class AsignaturaMallaCard extends StatelessWidget { final backgroundColor = _getBackgroundColor(context); final textColor = _getTextColor(context); - return SizedBox( - height: height, - width: width, - child: Padding( - padding: EdgeInsets.all(internalMargin), - child: GestureDetector( - onTap: () => _showAsignaturaDetail(context), - child: DecoratedBox( - decoration: BoxDecoration( - color: backgroundColor, - borderRadius: BorderRadius.circular(10), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - asignatura.nombre, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w600, - color: textColor, - ), - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - Space.xSmall, - Text( - asignatura.tipo, - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: textColor.withValues(alpha: 0.8), - ), - textAlign: TextAlign.center, - ), - Space.xSmall, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _buildChip(context, asignatura.nota, textColor, backgroundColor), - Space.xSmall, - _buildChip(context, asignatura.estado, textColor, backgroundColor), - ], + return Padding( + padding: const EdgeInsets.all(6), + child: GestureDetector( + onTap: () => _showAsignaturaDetail(context), + child: Container( + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.all(12), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flexible( + child: Text( + asignatura.nombre, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + color: textColor, ), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + Space.xSmall, + Text( + asignatura.tipo, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: textColor.withValues(alpha: 0.8), + ), + textAlign: TextAlign.center, + ), + Space.xSmall, + Wrap( + alignment: WrapAlignment.center, + spacing: 4, + runSpacing: 4, + children: [ + _buildChip(context, asignatura.nota, textColor), + _buildChip(context, asignatura.estado, textColor), ], ), - ), + ], ), ), ), ); } - Widget _buildChip(BuildContext context, String label, Color textColor, Color backgroundColor) { + Widget _buildChip(BuildContext context, String label, Color textColor) { return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: textColor.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), @@ -119,6 +111,8 @@ class AsignaturaMallaCard extends StatelessWidget { color: textColor, fontWeight: FontWeight.w500, ), + maxLines: 1, + overflow: TextOverflow.ellipsis, ), ); } @@ -126,40 +120,48 @@ class AsignaturaMallaCard extends StatelessWidget { void _showAsignaturaDetail(BuildContext context) { showModalBottomSheet( context: context, + isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), - builder: (ctx) => SingleChildScrollView( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Center( - child: Container( - width: 40, - height: 4, - decoration: BoxDecoration( - color: Theme.of(context).dividerColor, - borderRadius: BorderRadius.circular(2), + builder: (ctx) => DraggableScrollableSheet( + expand: false, + initialChildSize: 0.5, + minChildSize: 0.3, + maxChildSize: 0.9, + builder: (context, scrollController) => SingleChildScrollView( + controller: scrollController, + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Theme.of(context).dividerColor, + borderRadius: BorderRadius.circular(2), + ), ), ), - ), - Space.medium, - Text( - asignatura.nombre, - style: Theme.of(context).textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.bold, + Space.medium, + Text( + asignatura.nombre, + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), ), - ), - Space.medium, - _buildDetailRow(context, 'Tipo', asignatura.tipo), - _buildDetailRow(context, 'Estado', asignatura.estado), - _buildDetailRow(context, 'Nota', asignatura.nota), - _buildDetailRow(context, 'Nivel', asignatura.nivel.toString()), - _buildDetailRow(context, 'Intentos', asignatura.intentos.toString()), - Space.large, - ], + Space.medium, + _buildDetailRow(context, 'Tipo', asignatura.tipo), + _buildDetailRow(context, 'Estado', asignatura.estado), + _buildDetailRow(context, 'Nota', asignatura.nota), + _buildDetailRow(context, 'Nivel', asignatura.nivel.toString()), + _buildDetailRow(context, 'Intentos', asignatura.intentos.toString()), + Space.large, + ], + ), ), ), ); @@ -171,16 +173,21 @@ class AsignaturaMallaCard extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - label, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: Theme.of(context).textTheme.bodySmall?.color, + Flexible( + child: Text( + label, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).textTheme.bodySmall?.color, + ), ), ), - Text( - value, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w600, + Flexible( + child: Text( + value, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + ), + textAlign: TextAlign.end, ), ), ], @@ -188,4 +195,3 @@ class AsignaturaMallaCard extends StatelessWidget { ); } } - diff --git a/lib/screens/malla_historica/widgets/components/semestre_header_card.dart b/lib/screens/malla_historica/widgets/components/semestre_header_card.dart index a0557bf..b3cf035 100644 --- a/lib/screens/malla_historica/widgets/components/semestre_header_card.dart +++ b/lib/screens/malla_historica/widgets/components/semestre_header_card.dart @@ -1,27 +1,22 @@ import 'package:flutter/material.dart'; -import 'package:miutem/styles/styles.dart'; class SemestreHeaderCard extends StatelessWidget { final int semestre; - final double width; - final double height; const SemestreHeaderCard({ super.key, required this.semestre, - required this.width, - required this.height, }); @override - Widget build(BuildContext context) => SizedBox( - height: height, - width: width, - child: DecoratedBox( + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, ), child: Column( + mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( @@ -40,7 +35,6 @@ class SemestreHeaderCard extends StatelessWidget { ), ], ), - ), - ); + ); + } } - diff --git a/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart b/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart index 94ebdfc..c1a7a30 100644 --- a/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart +++ b/lib/screens/malla_historica/widgets/screens/malla_blocks_content.dart @@ -4,18 +4,10 @@ import 'package:miutem/screens/malla_historica/widgets/components/asignatura_mal class MallaBlocksContent extends StatelessWidget { final List> asignaturasPorSemestre; - final double blockHeight; - final double blockWidth; - final double blockInternalMargin; - final double borderWidth; const MallaBlocksContent({ super.key, required this.asignaturasPorSemestre, - required this.blockHeight, - required this.blockWidth, - this.blockInternalMargin = 8, - this.borderWidth = 2, }); int get _maxAsignaturasPorSemestre { @@ -23,52 +15,44 @@ class MallaBlocksContent extends StatelessWidget { return asignaturasPorSemestre.map((s) => s.length).reduce((a, b) => a > b ? a : b); } - List get _children { - final rows = []; + @override + Widget build(BuildContext context) { final maxRows = _maxAsignaturasPorSemestre; - for (int rowIndex = 0; rowIndex < maxRows; rowIndex++) { - final currentRow = []; - - for (int semestreIndex = 0; semestreIndex < asignaturasPorSemestre.length; semestreIndex++) { - final asignaturas = asignaturasPorSemestre[semestreIndex]; - - if (rowIndex < asignaturas.length) { - currentRow.add(AsignaturaMallaCard( - asignatura: asignaturas[rowIndex], - height: blockHeight, - width: blockWidth, - internalMargin: blockInternalMargin, - )); - } else { - // Celda vacía - currentRow.add(SizedBox( - height: blockHeight, - width: blockWidth, - )); - } - } - rows.add(TableRow(children: currentRow)); + if (asignaturasPorSemestre.isEmpty) { + return const SizedBox.shrink(); } - return rows; - } - @override - Widget build(BuildContext context) => Table( - defaultColumnWidth: FixedColumnWidth(blockWidth), - border: TableBorder( - horizontalInside: BorderSide( - color: Theme.of(context).dividerColor, - style: BorderStyle.solid, - width: borderWidth, - ), - verticalInside: BorderSide( - color: Theme.of(context).dividerColor, - style: BorderStyle.solid, - width: borderWidth, - ), - ), - children: _children, - ); + return Column( + mainAxisSize: MainAxisSize.min, + children: List.generate(maxRows, (rowIndex) { + return IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: List.generate(asignaturasPorSemestre.length, (semestreIndex) { + final asignaturas = asignaturasPorSemestre[semestreIndex]; + final hasAsignatura = rowIndex < asignaturas.length; + + return Expanded( + child: Container( + decoration: BoxDecoration( + border: Border( + right: semestreIndex < asignaturasPorSemestre.length - 1 + ? BorderSide(color: Theme.of(context).dividerColor) + : BorderSide.none, + bottom: BorderSide(color: Theme.of(context).dividerColor), + ), + ), + child: hasAsignatura + ? AsignaturaMallaCard(asignatura: asignaturas[rowIndex]) + : const SizedBox.shrink(), + ), + ); + }), + ), + ); + }), + ); + } } diff --git a/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart b/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart index 232b83e..e4c89b8 100644 --- a/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart +++ b/lib/screens/malla_historica/widgets/screens/malla_main_scroller.dart @@ -1,15 +1,9 @@ import 'package:flutter/material.dart'; import 'package:miutem/core/models/asignaturas/asignatura_malla.dart'; -import 'package:miutem/screens/malla_historica/widgets/screens/malla_blocks_content.dart'; -import 'package:miutem/screens/malla_historica/widgets/screens/malla_semestres_header.dart'; +import 'package:miutem/screens/malla_historica/widgets/components/asignatura_malla_card.dart'; +import 'package:miutem/screens/malla_historica/widgets/components/semestre_header_card.dart'; class MallaMainScroller extends StatelessWidget { - static const double blockWidth = 180.0; - static const double blockHeight = 140.0; - static const double blockInternalMargin = 6.0; - static const double semestreHeaderHeight = 60.0; - static const double borderWidth = 2.0; - final List asignaturas; const MallaMainScroller({ @@ -33,30 +27,6 @@ class MallaMainScroller extends StatelessWidget { return result; } - int get _cantidadSemestres => _asignaturasPorSemestre.length; - - int get _maxAsignaturasPorSemestre { - final porSemestre = _asignaturasPorSemestre; - if (porSemestre.isEmpty) return 0; - return porSemestre.map((s) => s.length).reduce((a, b) => a > b ? a : b); - } - - double get totalWidth => blockWidth * _cantidadSemestres; - double get totalHeight => semestreHeaderHeight + (blockHeight * _maxAsignaturasPorSemestre); - - Widget get _mallaSemestresHeader => MallaSemestresHeader( - cantidadSemestres: _cantidadSemestres, - height: semestreHeaderHeight, - semestreWidth: blockWidth, - ); - - Widget get _mallaBlocksContent => MallaBlocksContent( - asignaturasPorSemestre: _asignaturasPorSemestre, - blockHeight: blockHeight, - blockWidth: blockWidth, - blockInternalMargin: blockInternalMargin, - ); - @override Widget build(BuildContext context) { if (asignaturas.isEmpty) { @@ -65,21 +35,147 @@ class MallaMainScroller extends StatelessWidget { ); } + final semestres = _asignaturasPorSemestre; + + return LayoutBuilder( + builder: (context, constraints) { + final isLandscape = constraints.maxWidth > constraints.maxHeight; + final isLargeScreen = constraints.maxWidth > 600; + + // En pantallas grandes o landscape, mostrar vista de tabla scrolleable + if (isLargeScreen || isLandscape) { + return _buildTableView(context, semestres); + } + + // En pantallas pequeñas, mostrar vista de lista vertical por semestre + return _buildListView(context, semestres); + }, + ); + } + + /// Vista de tabla horizontal para pantallas grandes + Widget _buildTableView(BuildContext context, List> semestres) { return InteractiveViewer( constrained: false, - minScale: 0.3, + minScale: 0.5, maxScale: 2.0, - child: Container( - color: Theme.of(context).scaffoldBackgroundColor, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _mallaSemestresHeader, - _mallaBlocksContent, - ], + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: MediaQuery.of(context).size.width, + ), + child: IntrinsicWidth( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + // Header de semestres + Row( + children: List.generate( + semestres.length, + (index) => Expanded( + child: SemestreHeaderCard(semestre: index + 1), + ), + ), + ), + const Divider(height: 1), + // Contenido de asignaturas + _buildAsignaturasTable(context, semestres), + ], + ), + ), + ), ), ), ); } -} + Widget _buildAsignaturasTable(BuildContext context, List> semestres) { + final maxRows = semestres.map((s) => s.length).reduce((a, b) => a > b ? a : b); + + return Column( + mainAxisSize: MainAxisSize.min, + children: List.generate(maxRows, (rowIndex) { + return IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: List.generate(semestres.length, (semestreIndex) { + final asignaturas = semestres[semestreIndex]; + final hasAsignatura = rowIndex < asignaturas.length; + + return Expanded( + child: Container( + decoration: BoxDecoration( + border: Border( + right: semestreIndex < semestres.length - 1 + ? BorderSide(color: Theme.of(context).dividerColor) + : BorderSide.none, + bottom: BorderSide(color: Theme.of(context).dividerColor), + ), + ), + child: hasAsignatura + ? AsignaturaMallaCard(asignatura: asignaturas[rowIndex]) + : const SizedBox.shrink(), + ), + ); + }), + ), + ); + }), + ); + } + + /// Vista de lista vertical para pantallas pequeñas + Widget _buildListView(BuildContext context, List> semestres) { + return ListView.builder( + padding: const EdgeInsets.all(16), + itemCount: semestres.length, + itemBuilder: (context, semestreIndex) { + final asignaturasSemestre = semestres[semestreIndex]; + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Header del semestre + Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text( + 'Semestre ${semestreIndex + 1}', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + ), + // Asignaturas del semestre usando GridView flexible + LayoutBuilder( + builder: (context, constraints) { + // Calcular cuántas columnas caben basándose en el ancho disponible + final crossAxisCount = (constraints.maxWidth / 160).floor().clamp(1, 4); + + return GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: crossAxisCount, + childAspectRatio: 1.2, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + ), + itemCount: asignaturasSemestre.length, + itemBuilder: (context, index) { + return AsignaturaMallaCard(asignatura: asignaturasSemestre[index]); + }, + ); + }, + ), + if (semestreIndex < semestres.length - 1) + const Divider(height: 32), + ], + ); + }, + ); + } +} diff --git a/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart b/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart index 9059300..8fc059b 100644 --- a/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart +++ b/lib/screens/malla_historica/widgets/screens/malla_semestres_header.dart @@ -3,45 +3,31 @@ import 'package:miutem/screens/malla_historica/widgets/components/semestre_heade class MallaSemestresHeader extends StatelessWidget { final int cantidadSemestres; - final double height; - final double semestreWidth; - final double borderWidth; const MallaSemestresHeader({ super.key, required this.cantidadSemestres, - required this.height, - required this.semestreWidth, - this.borderWidth = 2, }); @override - Widget build(BuildContext context) => Table( - defaultColumnWidth: FixedColumnWidth(semestreWidth), - border: TableBorder( - verticalInside: BorderSide( - color: Theme.of(context).dividerColor, - style: BorderStyle.solid, - width: borderWidth, - ), - bottom: BorderSide( - color: Theme.of(context).dividerColor, - style: BorderStyle.solid, - width: borderWidth, - ), - ), - children: [ - TableRow( - children: List.generate( - cantidadSemestres, - (index) => SemestreHeaderCard( - semestre: index + 1, - height: height, - width: semestreWidth, + Widget build(BuildContext context) { + return Row( + children: List.generate( + cantidadSemestres, + (index) => Expanded( + child: Container( + decoration: BoxDecoration( + border: Border( + right: index < cantidadSemestres - 1 + ? BorderSide(color: Theme.of(context).dividerColor) + : BorderSide.none, + bottom: BorderSide(color: Theme.of(context).dividerColor), + ), + ), + child: SemestreHeaderCard(semestre: index + 1), ), ), ), - ], - ); + ); + } } - diff --git a/lib/styles/theme/space.dart b/lib/styles/theme/space.dart index ec5255e..1c259d9 100644 --- a/lib/styles/theme/space.dart +++ b/lib/styles/theme/space.dart @@ -9,4 +9,15 @@ class Space { static const Widget small = SizedBox(height: 12); /// 8 PX para separar elementos muy similares static const Widget xSmall = SizedBox(height: 8); +} + +class HorizontalSpace { + /// 20 PX para separar elementos muy distintos o secciones + static const Widget large = SizedBox(width: 20); + /// 16 PX para separar elementos similares con bordes + static const Widget medium = SizedBox(width: 16); + /// 12 PX para separar elementos similares pequeños + static const Widget small = SizedBox(width: 12); + /// 8 PX para separar elementos muy similares + static const Widget xSmall = SizedBox(width: 8); } \ No newline at end of file From 3fa0dc7a7e9ff9191c0383eadec96d3db1d74595 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:24:42 -0300 Subject: [PATCH 23/24] patch: update depends Signed-off-by: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> --- pubspec.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a45c5ca..aeb17ad 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -309,10 +309,10 @@ packages: dependency: transitive description: name: ffi - sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" file: dependency: transitive description: @@ -1209,10 +1209,10 @@ packages: dependency: transitive description: name: video_player_avfoundation - sha256: f46e9e20f1fe429760cf4dc118761336320d1bec0f50d255930c2355f2defb5b + sha256: "0d753e1d6bcc741a9c182a689434a9f22041f8a2cf5b3bd3b46ae51f057947a3" url: "https://pub.dev" source: hosted - version: "2.9.1" + version: "2.9.2" video_player_platform_interface: dependency: transitive description: From 7d301046358fd4d6d633dfa49cf086d1133115d6 Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Wed, 11 Feb 2026 23:21:27 -0300 Subject: [PATCH 24/24] feat: update deployment target to iOS 13 and refactor caching logic in MiUTEMMallaService --- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile.lock | 151 +++++++++--------- ios/Runner.xcodeproj/project.pbxproj | 6 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 + .../mi_utem/miutem_malla_service.dart | 119 ++------------ lib/core/services/service_manager.dart | 5 +- lib/core/utils/http/functions.dart | 37 +++++ lib/core/utils/http/http_client.dart | 2 +- .../widgets/utem_email_input_formatter.dart | 2 +- .../ephemeral/Flutter-Generated.xcconfig | 2 +- .../ephemeral/flutter_export_environment.sh | 2 +- 11 files changed, 134 insertions(+), 196 deletions(-) diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 7c56964..1dc6cf7 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d0ac3ed..11abf6f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1199,66 +1199,66 @@ PODS: - BoringSSL-GRPC/Implementation (0.0.37): - BoringSSL-GRPC/Interface (= 0.0.37) - BoringSSL-GRPC/Interface (0.0.37) - - cloud_firestore (6.1.1): - - Firebase/Firestore (= 12.6.0) + - cloud_firestore (6.1.2): + - Firebase/Firestore (= 12.8.0) - firebase_core - Flutter - file_saver (0.0.1): - Flutter - - Firebase/CoreOnly (12.6.0): - - FirebaseCore (~> 12.6.0) - - Firebase/Firestore (12.6.0): + - Firebase/CoreOnly (12.8.0): + - FirebaseCore (~> 12.8.0) + - Firebase/Firestore (12.8.0): - Firebase/CoreOnly - - FirebaseFirestore (~> 12.6.0) - - Firebase/RemoteConfig (12.6.0): + - FirebaseFirestore (~> 12.8.0) + - Firebase/RemoteConfig (12.8.0): - Firebase/CoreOnly - - FirebaseRemoteConfig (~> 12.6.0) - - firebase_analytics (12.1.0): + - FirebaseRemoteConfig (~> 12.8.0) + - firebase_analytics (12.1.2): - firebase_core - - FirebaseAnalytics (= 12.6.0) + - FirebaseAnalytics (= 12.8.0) - Flutter - - firebase_core (4.3.0): - - Firebase/CoreOnly (= 12.6.0) + - firebase_core (4.4.0): + - Firebase/CoreOnly (= 12.8.0) - Flutter - - firebase_remote_config (6.1.3): - - Firebase/RemoteConfig (= 12.6.0) + - firebase_remote_config (6.1.4): + - Firebase/RemoteConfig (= 12.8.0) - firebase_core - Flutter - - FirebaseABTesting (12.6.0): - - FirebaseCore (~> 12.6.0) - - FirebaseAnalytics (12.6.0): - - FirebaseAnalytics/Default (= 12.6.0) - - FirebaseCore (~> 12.6.0) - - FirebaseInstallations (~> 12.6.0) + - FirebaseABTesting (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseAnalytics (12.8.0): + - FirebaseAnalytics/Default (= 12.8.0) + - FirebaseCore (~> 12.8.0) + - FirebaseInstallations (~> 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseAnalytics/Default (12.6.0): - - FirebaseCore (~> 12.6.0) - - FirebaseInstallations (~> 12.6.0) - - GoogleAppMeasurement/Default (= 12.6.0) + - FirebaseAnalytics/Default (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseInstallations (~> 12.8.0) + - GoogleAppMeasurement/Default (= 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - FirebaseAppCheckInterop (12.6.0) - - FirebaseCore (12.6.0): - - FirebaseCoreInternal (~> 12.6.0) + - FirebaseAppCheckInterop (12.8.0) + - FirebaseCore (12.8.0): + - FirebaseCoreInternal (~> 12.8.0) - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/Logger (~> 8.1) - - FirebaseCoreExtension (12.6.0): - - FirebaseCore (~> 12.6.0) - - FirebaseCoreInternal (12.6.0): + - FirebaseCoreExtension (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseCoreInternal (12.8.0): - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseFirestore (12.6.0): - - FirebaseCore (~> 12.6.0) - - FirebaseCoreExtension (~> 12.6.0) - - FirebaseFirestoreInternal (~> 12.6.0) - - FirebaseSharedSwift (~> 12.6.0) - - FirebaseFirestoreInternal (12.6.0): + - FirebaseFirestore (12.8.0): + - FirebaseCore (~> 12.8.0) + - FirebaseCoreExtension (~> 12.8.0) + - FirebaseFirestoreInternal (~> 12.8.0) + - FirebaseSharedSwift (~> 12.8.0) + - FirebaseFirestoreInternal (12.8.0): - abseil/algorithm (~> 1.20240722.0) - abseil/base (~> 1.20240722.0) - abseil/container/flat_hash_map (~> 1.20240722.0) @@ -1267,27 +1267,27 @@ PODS: - abseil/strings/strings (~> 1.20240722.0) - abseil/time (~> 1.20240722.0) - abseil/types (~> 1.20240722.0) - - FirebaseAppCheckInterop (~> 12.6.0) - - FirebaseCore (~> 12.6.0) + - FirebaseAppCheckInterop (~> 12.8.0) + - FirebaseCore (~> 12.8.0) - "gRPC-C++ (~> 1.69.0)" - gRPC-Core (~> 1.69.0) - leveldb-library (~> 1.22) - nanopb (~> 3.30910.0) - - FirebaseInstallations (12.6.0): - - FirebaseCore (~> 12.6.0) + - FirebaseInstallations (12.8.0): + - FirebaseCore (~> 12.8.0) - GoogleUtilities/Environment (~> 8.1) - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseRemoteConfig (12.6.0): - - FirebaseABTesting (~> 12.6.0) - - FirebaseCore (~> 12.6.0) - - FirebaseInstallations (~> 12.6.0) - - FirebaseRemoteConfigInterop (~> 12.6.0) - - FirebaseSharedSwift (~> 12.6.0) + - FirebaseRemoteConfig (12.8.0): + - FirebaseABTesting (~> 12.8.0) + - FirebaseCore (~> 12.8.0) + - FirebaseInstallations (~> 12.8.0) + - FirebaseRemoteConfigInterop (~> 12.8.0) + - FirebaseSharedSwift (~> 12.8.0) - GoogleUtilities/Environment (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseRemoteConfigInterop (12.6.0) - - FirebaseSharedSwift (12.6.0) + - FirebaseRemoteConfigInterop (12.8.0) + - FirebaseSharedSwift (12.8.0) - Flutter (1.0.0) - flutter_native_splash (2.4.3): - Flutter @@ -1298,23 +1298,23 @@ PODS: - GoogleUtilities/Logger (~> 8.1) - GoogleUtilities/Network (~> 8.1) - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Core (12.6.0): + - GoogleAppMeasurement/Core (12.8.0): - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Default (12.6.0): + - GoogleAppMeasurement/Default (12.8.0): - GoogleAdsOnDeviceConversion (~> 3.2.0) - - GoogleAppMeasurement/Core (= 12.6.0) - - GoogleAppMeasurement/IdentitySupport (= 12.6.0) + - GoogleAppMeasurement/Core (= 12.8.0) + - GoogleAppMeasurement/IdentitySupport (= 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) - "GoogleUtilities/NSData+zlib (~> 8.1)" - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/IdentitySupport (12.6.0): - - GoogleAppMeasurement/Core (= 12.6.0) + - GoogleAppMeasurement/IdentitySupport (12.8.0): + - GoogleAppMeasurement/Core (= 12.8.0) - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - GoogleUtilities/MethodSwizzler (~> 8.1) - GoogleUtilities/Network (~> 8.1) @@ -1448,9 +1448,6 @@ PODS: - nanopb/encode (3.30910.0) - package_info_plus (0.4.5): - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - PromisesObjC (2.4.0) - share_plus (0.0.1): - Flutter @@ -1478,7 +1475,6 @@ DEPENDENCIES: - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) @@ -1535,8 +1531,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_secure_storage/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" share_plus: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: @@ -1553,29 +1547,29 @@ SPEC CHECKSUMS: awesome_notifications: 0f432b28098d193920b11a44cfa9d2d9313a3888 awesome_notifications_core: 429c28df8746780a474de177e5acde33af87da63 BoringSSL-GRPC: dded2a44897e45f28f08ae87a55ee4bcd19bc508 - cloud_firestore: 45532e0c1fd1f6a5720af8aa0312470c366b73d2 + cloud_firestore: 4bd00c3464706d9e09dabac0bb8e9610456109f5 file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6 - Firebase: a451a7b61536298fd5cbfe3a746fd40443a50679 - firebase_analytics: 4f9cca09e65f6c2944a862c6dc86f6bed9fb769c - firebase_core: ba00a168e719694f38960502ceb560285603d073 - firebase_remote_config: 4315c34bfba52eb501b69cfa84d519f340385a37 - FirebaseABTesting: 119f0a2b2e68b1ae05d248c5adb2455f148f20c1 - FirebaseAnalytics: d0a97a0db6425e5a5d966340b87f92ca7b13a557 - FirebaseAppCheckInterop: e2178171b4145013c7c1a3cc464d1d446d3a1896 - FirebaseCore: 0e38ad5d62d980a47a64b8e9301ffa311457be04 - FirebaseCoreExtension: 032fd6f8509e591fda8cb76f6651f20d926b121f - FirebaseCoreInternal: 69bf1306a05b8ac43004f6cc1f804bb7b05b229e - FirebaseFirestore: 51ce079b9ddcaa481644164eda649d362c2a6396 - FirebaseFirestoreInternal: 8b1d2b0a1b859b2ddbd63f448c416c5be7367405 - FirebaseInstallations: 631b38da2e11a83daa4bfb482f79d286a5dfa7ad - FirebaseRemoteConfig: c5dfe22828a7ae7673d16224ea92743687e993df - FirebaseRemoteConfigInterop: 3443b8cb8fffd76bb3e03b2a84bfd3db952fcda4 - FirebaseSharedSwift: 79f27fff0addd15c3de19b87fba426f3cc2c964f + Firebase: 9a58fdbc9d8655ed7b79a19cf9690bb007d3d46d + firebase_analytics: a3285a9ab410456957496cdb659f00c1cf19a95f + firebase_core: ee30637e6744af8e0c12a6a1e8a9718506ec2398 + firebase_remote_config: 3a5639062e130c4d4b7c4bae347cc3bac90f5a1e + FirebaseABTesting: 31266c7845f9adde0f2e8a59267e9c82e4050898 + FirebaseAnalytics: f20bbad8cb7f65d8a5eaefeb424ae8800a31bdfc + FirebaseAppCheckInterop: ba3dc604a89815379e61ec2365101608d365cf7d + FirebaseCore: 0dbad74bda10b8fb9ca34ad8f375fb9dd3ebef7c + FirebaseCoreExtension: 6605938d51f765d8b18bfcafd2085276a252bee2 + FirebaseCoreInternal: fe5fa466aeb314787093a7dce9f0beeaad5a2a21 + FirebaseFirestore: 67f23000ca238ccbab79127ed59636a9a2689e74 + FirebaseFirestoreInternal: a0e7382af3d208898dcd1d4d52d8a7870632e881 + FirebaseInstallations: 6a14ab3d694ebd9f839c48d330da5547e9ca9dc0 + FirebaseRemoteConfig: e9e3909162a05bc0e796326255fd43250783a2a9 + FirebaseRemoteConfigInterop: 869ddca16614f979e5c931ece11fbb0b8729ed41 + FirebaseSharedSwift: f57ed48f4542b2d7eb4738f4f23ba443f78b3780 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 GoogleAdsOnDeviceConversion: d68c69dd9581a0f5da02617b6f377e5be483970f - GoogleAppMeasurement: 3bf40aff49a601af5da1c3345702fcb4991d35ee + GoogleAppMeasurement: 72c9a682fec6290327ea5e3c4b829b247fcb2c17 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 "gRPC-C++": cc207623316fb041a7a3e774c252cf68a058b9e8 gRPC-Core: 860978b7db482de8b4f5e10677216309b5ff6330 @@ -1583,7 +1577,6 @@ SPEC CHECKSUMS: leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 - path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 1235ba1..9e3a02c 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -459,7 +459,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -591,7 +591,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -642,7 +642,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15cada4..e3773d4 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> Get.find(); - /// Caché en memoria para evitar lecturas repetidas de SharedPreferences - List? _memoryCache; - DateTime? _memoryCacheTimestamp; - /// Obtiene la malla, usando caché si está disponible y no ha expirado. /// [forceRefresh] fuerza una actualización desde el servidor. Future> getMalla({bool forceRefresh = false}) async { - // Si no se fuerza refresh, intentar obtener desde caché - if (!forceRefresh) { - final cachedMalla = await _getCachedMalla(); - if (cachedMalla != null) { - return cachedMalla; - } - } - - // Obtener desde el servidor - final malla = await _fetchMallaFromServer(); - - // Guardar en caché - await _saveMallaToCache(malla); - - return malla; - } - - /// Obtiene la malla desde el caché (memoria o persistente) - Future?> _getCachedMalla() async { - // Primero revisar caché en memoria - if (_memoryCache != null && _memoryCacheTimestamp != null) { - if (DateTime.now().difference(_memoryCacheTimestamp!) < _cacheDuration) { - logger.d('Malla obtenida desde caché en memoria'); - return _memoryCache; - } - } - - // Si no hay caché en memoria, revisar SharedPreferences - try { - final cachedData = await sharedPreferences.getString(_mallaCacheKey); - final cachedTimestamp = await sharedPreferences.getInt(_mallaCacheTimestampKey); - - if (cachedData != null && cachedTimestamp != null) { - final cacheTime = DateTime.fromMillisecondsSinceEpoch(cachedTimestamp); - if (DateTime.now().difference(cacheTime) < _cacheDuration) { - final jsonList = jsonDecode(cachedData) as List; - final malla = AsignaturaMalla.fromJsonList(jsonList); - - // Actualizar caché en memoria - _memoryCache = malla; - _memoryCacheTimestamp = cacheTime; - - logger.d('Malla obtenida desde caché persistente'); - return malla; - } - } - } catch (e) { - logger.e('Error al leer caché de malla', error: e); - } - - return null; - } - - /// Guarda la malla en caché (memoria y persistente) - Future _saveMallaToCache(List malla) async { - final now = DateTime.now(); - - // Guardar en memoria - _memoryCache = malla; - _memoryCacheTimestamp = now; - - // Guardar en SharedPreferences - try { - final jsonString = jsonEncode(malla.map((e) => e.toJson()).toList()); - await sharedPreferences.setString(_mallaCacheKey, jsonString); - await sharedPreferences.setInt(_mallaCacheTimestampKey, now.millisecondsSinceEpoch); - logger.d('Malla guardada en caché'); - } catch (e) { - logger.e('Error al guardar caché de malla', error: e); - } - } - - /// Limpia el caché de la malla - Future clearCache() async { - _memoryCache = null; - _memoryCacheTimestamp = null; - await sharedPreferences.remove(_mallaCacheKey); - await sharedPreferences.remove(_mallaCacheTimestampKey); - logger.d('Caché de malla limpiado'); - } - - /// Obtiene la malla directamente desde el servidor - Future> _fetchMallaFromServer() async { final cookie = await MiUTEMAuthService.get.login(); - final response = await HttpClient.httpCachedClient.get("$miUtemHost/academicos/mi-malla", - options: Options( - headers: { - 'Cookie': cookie, - 'User-Agent': genericUserAgent, - } - ) + final response = await httpClientRequest("$miUtemHost/academicos/mi-malla", + forceRefresh: forceRefresh, + headers: { + 'Cookie': cookie ?? '', + 'User-Agent': genericUserAgent, + }, ); final html = "${response.data}"; - if(!html.contains("La información proporcionada en el módulo debe ser validada por la Dirección General de Docencia.")) { + if (!html.contains("La información proporcionada en el módulo debe ser validada por la Dirección General de Docencia.")) { throw CustomException(message: "No se pudo obtener la malla. Por favor intenta más tarde.", internalCode: 1); } final htmlDoc = parse(html).documentElement; - if(htmlDoc == null) { + if (htmlDoc == null) { throw CustomException(message: "No se pudo obtener la malla. Por favor intenta más tarde.", internalCode: 2); } - logger.d('Malla obtenida desde el servidor'); return (htmlDoc.querySelectorAll("#avance-malla").first.querySelectorAll("#table-avance").first).querySelectorAll("tbody > tr").map((it) { final parts = it.children; var nota = parts[5].text.trim(); - if(nota.isEmpty) { + if (nota.isEmpty) { nota = "-"; } @@ -146,4 +49,4 @@ class MiUTEMMallaService { ); }).toList(); } -} \ No newline at end of file +} diff --git a/lib/core/services/service_manager.dart b/lib/core/services/service_manager.dart index 47a78ca..048eddc 100644 --- a/lib/core/services/service_manager.dart +++ b/lib/core/services/service_manager.dart @@ -19,7 +19,10 @@ import 'package:miutem/core/services/controllers/horario_controller.dart'; /// Inicializa los servicios y los registra en GetX Future initServices() async { // Inicializar Firebase - await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + name: 'miutem-app', + ); Get.lazyPut(() => RemoteConfigService()); await Get.find().initialize(); diff --git a/lib/core/utils/http/functions.dart b/lib/core/utils/http/functions.dart index 3989287..720c89b 100644 --- a/lib/core/utils/http/functions.dart +++ b/lib/core/utils/http/functions.dart @@ -66,6 +66,43 @@ Future sigaClientRequest(String path, { } } +Future httpClientRequest(String uri, { + String method = "GET", + Map? headers, + dynamic data, + String? contentType, + ResponseType? responseType, + Options? options, + bool forceRefresh = false, + Duration ttl = const Duration(days: 7), + Map? extra, + Map? queryParameters, +}) async { + try { + return await HttpClient.httpCachedClient.request(uri, + data: data, + queryParameters: queryParameters, + options: options ?? buildCacheOptions(ttl, + forceRefresh: forceRefresh, + primaryKey: 'api.miutem', + subKey: base64Encode(utf8.encode("$uri/${queryParameters?.entries.map((e) => "${e.key}=${Uri.encodeComponent(e.value)}").join("&")}")), + maxStale: const Duration(days: 14), + options: (options ?? Options()).copyWith( + method: method, + headers: headers, + contentType: contentType, + responseType: responseType, + extra: extra, + ), + ), + ); + } on SocketException { + throw CustomException(message: 'Error al conectar con la API. Por favor intenta más tarde.'); + } catch (e) { + rethrow; + } +} + Future isOffline() async { bool offlineMode = (await Preferencia.isOffline.getAsBool(defaultValue: false, guardar: true)); diff --git a/lib/core/utils/http/http_client.dart b/lib/core/utils/http/http_client.dart index b32c9d2..5231ad5 100644 --- a/lib/core/utils/http/http_client.dart +++ b/lib/core/utils/http/http_client.dart @@ -9,7 +9,6 @@ import 'package:miutem/core/utils/http/interceptors/offline_mode_interceptor.dar class HttpClient { static final DioCacheManager cacheManager = DioCacheManager(CacheConfig( - baseUrl: miUtemHost, defaultMaxAge: const Duration(days: 7), defaultMaxStale: const Duration(days: 14), )); @@ -40,5 +39,6 @@ class HttpClient { static Future clearCache() async { await cacheManagerSiga.clearAll(); + await cacheManager.clearAll(); } } \ No newline at end of file diff --git a/lib/screens/auth/login/widgets/utem_email_input_formatter.dart b/lib/screens/auth/login/widgets/utem_email_input_formatter.dart index a7d989f..9e301f3 100644 --- a/lib/screens/auth/login/widgets/utem_email_input_formatter.dart +++ b/lib/screens/auth/login/widgets/utem_email_input_formatter.dart @@ -9,7 +9,7 @@ class UtemEmailInputFormatter extends TextInputFormatter { TextEditingValue newValue, ) { // Remove any @ symbols from the new text - final filteredText = newValue.text.replaceAll('@', ''); + final filteredText = newValue.text.replaceAll('@utem.cl', '').replaceAll('@', ''); if (filteredText == newValue.text) { return newValue; diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index b7acaf0..dfb069b 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -6,7 +6,7 @@ FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=3.0.0 FLUTTER_BUILD_NUMBER=142 -DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049OGI4NzI4Njg0OQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43 +DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049OGI4NzI4Njg0OQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index 7ba8d02..a3b63fc 100755 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -7,7 +7,7 @@ export "FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=3.0.0" export "FLUTTER_BUILD_NUMBER=142" -export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9WRVJTSU9OPTMuMzguNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049OGI4NzI4Njg0OQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43" +export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNg==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049OGI4NzI4Njg0OQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false"