Conversation
- 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
# Conflicts: # lib/screens/asignaturas/asignaturas_screen.dart # lib/screens/home/home_screen.dart # lib/screens/tasklist/task_list_screen.dart # lib/widgets/navigation/bottom_navbar.dart
# Conflicts: # lib/core/utils/theme.dart # lib/main.dart # lib/screens/asignaturas/asignaturas_screen.dart # lib/screens/home/home_screen.dart # lib/screens/profile/profile_screen.dart # lib/screens/tasklist/task_list_screen.dart # lib/screens/widgets_screens.dart # lib/styles/navigation/bottom_navbar.dart # lib/widgets/navigation/top_navigation.dart
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull Request Overview
This pull request introduces a comprehensive subject details screen feature alongside dependency updates and improved navigation with feature flags. The main purpose is to enhance the user experience by providing detailed subject information including grades and schedules, while also implementing a flexible feature flag system for navigation control.
- Adds a new detailed subject screen (
AsignaturaScreen) with grades and schedule visualization - Implements feature flag system for conditional UI rendering and navigation control
- Updates Firebase and other dependencies to newer versions
Reviewed Changes
Copilot reviewed 29 out of 34 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
pubspec.yaml |
Updates Firebase and other package dependencies to newer versions |
macos/Podfile |
Updates Firebase Firestore SDK and platform target |
lib/widgets/feature_flag.dart |
Adds comprehensive feature flag system for conditional UI rendering |
lib/styles/theme/theme.dart |
Updates deprecated theme constructors to new data variants |
lib/styles/navigation/bottom_navbar.dart |
Integrates feature flags into navigation system |
lib/screens/asignaturas/detalle_asignatura/ |
New subject details screen with grades and schedule components |
lib/screens/asignaturas/lista_asignaturas_screen.dart |
Renamed and updated main subjects screen |
lib/screens/notas/notas_screen.dart |
Enhanced notes screen to accept pre-loaded subject data |
lib/core/models/navigation/navigation_item.dart |
Adds feature flag support to navigation items |
Comments suppressed due to low confidence (2)
lib/widgets/feature_flag.dart:261
- The method
withValues(alpha: 0.2)appears to be using a newer Flutter API that may not exist in all Flutter versions. Consider using the more widely supportedwithOpacity(0.2)method instead.
color: isEnabled ? Colors.green.withValues(alpha: 0.2) : Colors.red.withValues(alpha: 0.2),
lib/screens/asignaturas/detalle_asignatura/widgets/promedio.dart:54
- The method
withValues(alpha: 0.2)appears to be using a newer Flutter API that may not exist in all Flutter versions. Consider using the more widely supportedwithOpacity(0.2)method instead.
color: Colors.grey.withValues(alpha: 0.2),
| @@ -1,4 +1,4 @@ | |||
| platform :macos, '11.5' | |||
| platform :osx, '10.15' | |||
There was a problem hiding this comment.
The platform declaration has changed from 'macos' to 'osx', but macOS 10.15 (Catalina) is quite old. Consider using a more recent macOS version like '11.0' or '12.0' for better compatibility with newer Firebase SDKs and features.
| platform :osx, '10.15' | |
| platform :osx, '12.0' |
lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart
Outdated
Show resolved
Hide resolved
lib/screens/asignaturas/detalle_asignatura/asignatura_screen.dart
Outdated
Show resolved
Hide resolved
Se utiliza otro nombre para la variable para evitar `shadowing` Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
# Conflicts: # .gitignore # ios/Podfile.lock # linux/flutter/ephemeral/.plugin_symlinks/flutter_secure_storage_linux # linux/flutter/ephemeral/.plugin_symlinks/package_info_plus # linux/flutter/ephemeral/.plugin_symlinks/share_plus # macos/Flutter/GeneratedPluginRegistrant.swift # macos/Flutter/ephemeral/Flutter-Generated.xcconfig # macos/Flutter/ephemeral/flutter_export_environment.sh # macos/Podfile.lock # pubspec.lock
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 37 out of 47 changed files in this pull request and generated 13 comments.
Files not reviewed (5)
- .idea/.gitignore: Language not supported
- .idea/discord.xml: Language not supported
- .idea/git_toolbox_prj.xml: Language not supported
- .idea/misc.xml: Language not supported
- .idea/vcs.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| List<NavigationItem> 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'), | ||
| ), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Current navigation depends on Remote Config feature_flags; when that parameter is missing/empty (e.g., first run offline or defaults not set), FeatureFlag.evaluateSync returns false and enabledScreens becomes empty, making the app show the fallback scaffold with no navigation. Consider default-enabling core nav items when flags are unavailable, or ship a local default feature_flags JSON via Remote Config defaults / app constants.
| import 'dart:convert'; | ||
|
|
||
| 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, | ||
| }); | ||
|
|
||
| toJson() => { | ||
| 'dia': dia, | ||
| 'horaInicio': horaInicio, | ||
| 'horaFin': horaFin, | ||
| 'nombreAsignatura': nombreAsignatura, | ||
| 'sala': sala, | ||
| }; |
There was a problem hiding this comment.
Unused import dart:convert. Also toJson() should be typed (e.g., Map<String, dynamic> toJson()) for better type-safety and to match typical model conventions.
| #!/bin/sh | ||
| # This is a generated file; do not edit or check into version control. | ||
| 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/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_OBFUSCATION=false" | ||
| export "TRACK_WIDGET_CREATION=true" | ||
| export "TREE_SHAKE_ICONS=false" | ||
| export "PACKAGE_CONFIG=/Users/fran/Development/exdevutem/miutem/.dart_tool/package_config.json" |
There was a problem hiding this comment.
These macos/Flutter/ephemeral/* files are generated (and even state they should not be checked in) and include developer-specific absolute paths. They should be removed from version control and left ignored by .gitignore.
| // This is a generated file; do not edit or check into version control. | ||
| FLUTTER_ROOT=/opt/homebrew/share/flutter | ||
| FLUTTER_APPLICATION_PATH=/Users/fran/Development/exdevutem/miutem | ||
| COCOAPODS_PARALLEL_CODE_SIGN=true | ||
| 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 |
There was a problem hiding this comment.
This file is generated and contains machine-specific absolute paths; it should not be committed. Remove it and rely on Flutter to regenerate it locally / in CI.
| # Uncomment this line to define a global platform for your project | ||
| platform :ios, '13.0' | ||
| platform :ios, '16.0' | ||
|
|
There was a problem hiding this comment.
Raising the iOS deployment target from 13.0 to 16.0 is a breaking operational change (drops support for older iOS versions). If this isn’t strictly required by the updated Firebase/Flutter plugins, consider keeping the previous minimum; otherwise, call this out explicitly in release notes/PR description and verify stakeholders agree.
| <component name="DiscordProjectSettings"> | ||
| <option name="show" value="PROJECT_FILES" /> | ||
| <option name="description" value="" /> | ||
| </component> |
There was a problem hiding this comment.
These .idea/* files look like IDE/user-specific settings (e.g., Discord/GitToolBox). Adding them to the repo can create noisy diffs and doesn’t help app runtime behavior. Consider removing them and adding .idea/ to .gitignore (or only committing a minimal, agreed-upon subset).
| <component name="DiscordProjectSettings"> | |
| <option name="show" value="PROJECT_FILES" /> | |
| <option name="description" value="" /> | |
| </component> | |
| <!-- Intentionally left blank. | |
| IDE-specific Discord plugin settings are not tracked in version control. --> |
| final apiUrl = dotenv.env['EXDEV_API_ENDPOINT'] ?? 'https://api.exdev.cl'; | ||
| final sigaHost = dotenv.env['SIGA_ENDPOINT'] ?? 'https://siga.utem.cl'; |
There was a problem hiding this comment.
apiUrl no longer uses kDebugMode, so package:flutter/foundation.dart at the top of this file becomes unused and will typically fail dart analyze under flutter_lints. Remove that import (or reintroduce the intended debug/release branching).
| WidgetsFlutterBinding.ensureInitialized(); | ||
| await initServices(); |
There was a problem hiding this comment.
WidgetsFlutterBinding.ensureInitialized() is called twice. Keep a single call (at the very start of main) to avoid confusion and ensure initialization order is clear.
| flutter: | ||
| uses-material-design: true | ||
| assets: | ||
| - .env | ||
| - assets/launcher_icons/prod/icon_splash.png |
There was a problem hiding this comment.
.env is added as a Flutter asset, but .gitignore ignores .env* and this PR doesn’t include a .env file. A fresh clone/CI build will fail because the declared asset is missing. Consider packaging .env.example as the default asset (and loading that), or generate/provide .env as part of the build pipeline instead of declaring a missing asset in pubspec.yaml.
| import 'package:miutem/core/utils/constants.dart'; | ||
| import 'package:miutem/screens/notas/actions/cargar_asignaturas_con_notas.dart'; |
There was a problem hiding this comment.
Unused import package:miutem/core/utils/constants.dart; this file doesn’t reference anything from it. This will trigger an analyzer warning/error under common lint settings.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 45 out of 55 changed files in this pull request and generated 17 comments.
Files not reviewed (5)
- .idea/.gitignore: Language not supported
- .idea/discord.xml: Language not supported
- .idea/git_toolbox_prj.xml: Language not supported
- .idea/misc.xml: Language not supported
- .idea/vcs.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| final List<NavigationItem> 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<NavigationItem> get enabledScreens { | ||
| return allScreens.where((screen) => FeatureFlag.evaluateSync(screen.featureFlag)).toList(); | ||
| } |
There was a problem hiding this comment.
enabledScreens filtra TODO el navbar por feature flags. Con la implementación actual, si feature_flags aún no está disponible (o no incluye estas keys), enabledScreens puede quedar vacío y el usuario verá el fallback. Para robustez, conviene tener defaults locales (p. ej. habilitar siempre Home) o un fallback que muestre allScreens cuando Remote Config aún no está inicializado.
| // This is a generated file; do not edit or check into version control. | ||
| FLUTTER_ROOT=/opt/homebrew/share/flutter | ||
| FLUTTER_APPLICATION_PATH=/Users/fran/Development/exdevutem/miutem | ||
| COCOAPODS_PARALLEL_CODE_SIGN=true | ||
| FLUTTER_TARGET=/Users/fran/Development/exdevutem/miutem/lib/main.dart |
There was a problem hiding this comment.
Archivo generado (y con paths absolutos locales) que no debería versionarse. Ya está contemplado por el .gitignore (**/macos/Flutter/ephemeral), así que debe eliminarse del PR para evitar exponer rutas locales y ruido en diffs.
| // AQUI SE TIENE QUE USAR LA CONFIGURACION DEL KEYSTORE QUE TIENE LA APP OFICIAL | ||
| defaultConfig { | ||
| applicationId = "cl.exdev.miutem" | ||
| applicationId = "cl.inndev.miutem" |
There was a problem hiding this comment.
Cambio de applicationId (nombre de paquete) es breaking para actualizaciones en Play Store y para cualquier integración que dependa del bundle id. No está mencionado en la descripción del PR; si es intencional, sería bueno documentar la razón y validar impactos (Firebase config, links, firmas, etc.).
| Text( | ||
| _capitalizeDia(bloque.nombreAsignatura), | ||
| style: const TextStyle( | ||
| fontWeight: FontWeight.w900, |
There was a problem hiding this comment.
Aquí se está aplicando _capitalizeDia al nombreAsignatura, lo que fuerza minúsculas y puede degradar nombres propios/abreviaturas. Además, el nombre del helper sugiere que se quería capitalizar el día. Considera mostrar nombreAsignatura tal cual (o con capitalize más conservador) y aplicar la capitalización a bloque.dia si es necesario.
| import 'dart:convert'; | ||
|
|
There was a problem hiding this comment.
Import dart:convert no se usa en este archivo (provoca warning y puede romper flutter analyze si se trata como error). Eliminar el import o usarlo realmente.
| import 'dart:convert'; |
| #!/bin/sh | ||
| # This is a generated file; do not edit or check into version control. | ||
| export "FLUTTER_ROOT=/opt/homebrew/share/flutter" | ||
| export "FLUTTER_APPLICATION_PATH=/Users/fran/Development/exdevutem/miutem" | ||
| export "COCOAPODS_PARALLEL_CODE_SIGN=true" |
There was a problem hiding this comment.
Este archivo es generado y además contiene rutas absolutas del entorno local (/Users/..., FLUTTER_ROOT=...). No debería estar en el repo (también está cubierto por el .gitignore). Eliminarlo del control de versiones para evitar filtrar paths locales y reducir churn.
| 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)); |
There was a problem hiding this comment.
Este then(... setState ...) también debería validar mounted antes de actualizar estado por el mismo motivo (posible setState después de dispose).
| 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)); | |
| cargarAsignaturaConNotas(asignatura: widget.asignatura).then((loadedAsignatura) { | |
| if (!mounted) return; | |
| setState(() => asignatura = loadedAsignatura); | |
| }).catchError((error) { | |
| if (mounted) showErrorSnackbar(context, "Error al cargar las notas"); | |
| }); | |
| cargarHorarioBloque(asignatura: asignatura).then((bloques) { | |
| if (!mounted) return; | |
| setState(() => bloquesHorario = bloques); | |
| }); |
| List<HorarioBloque> tmp = bloquesHorario; | ||
| try { | ||
| setState(() { | ||
| bloquesHorario.clear(); | ||
| }); |
There was a problem hiding this comment.
tmp apunta a la MISMA lista que bloquesHorario. Luego haces bloquesHorario.clear(), lo que también vacía tmp, por lo que el rollback en el catch no restaura nada. Usa una copia inmutable (final tmp = List<HorarioBloque>.of(bloquesHorario);) antes de limpiar.
|
|
||
| android { | ||
| namespace = "cl.exdev.miutem" | ||
| namespace = "cl.inndev.miutem" |
There was a problem hiding this comment.
Cambio de namespace de Android. Esto es una modificación de alto impacto (paquete/manifest, Play Store, deep links, etc.) y no está mencionada en la descripción del PR. Confirmar que es intencional y que el resto de la configuración (applicationId, google-services, intent-filters) se actualiza en consecuencia.
| 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)); |
There was a problem hiding this comment.
En initState, el then(... setState ...) no valida mounted. Si el usuario sale rápido de la pantalla, puede disparar setState() called after dispose. Agrega un if (!mounted) return; antes de llamar a setState en ambos futures.
| 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)); | |
| cargarAsignaturaConNotas(asignatura: widget.asignatura).then((loadedAsignatura) { | |
| if (!mounted) return; | |
| setState(() => asignatura = loadedAsignatura); | |
| }).catchError((error) { | |
| if (mounted) showErrorSnackbar(context, "Error al cargar las notas"); | |
| }); | |
| cargarHorarioBloque(asignatura: asignatura).then((bloques) { | |
| if (!mounted) return; | |
| setState(() => bloquesHorario = bloques); | |
| }); |
Signed-off-by: Francisco Solis <30329003+Im-Fran@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 67 changed files in this pull request and generated 12 comments.
Files not reviewed (5)
- .idea/.gitignore: Language not supported
- .idea/discord.xml: Language not supported
- .idea/git_toolbox_prj.xml: Language not supported
- .idea/misc.xml: Language not supported
- .idea/vcs.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static final DioCacheManager cacheManager = DioCacheManager(CacheConfig( | ||
| baseUrl: miUtemHost, | ||
| defaultMaxAge: const Duration(days: 7), | ||
| defaultMaxStale: const Duration(days: 14), | ||
| )); |
There was a problem hiding this comment.
A new cacheManager is introduced here for miUtemHost, but clearCache() below still only clears the SIGA cache manager. If logout is expected to clear all HTTP caches, clearCache() should also clear this new cache manager.
| static final Dio dioClient = Dio()..interceptors.addAll([ | ||
| HeadersInterceptor(), | ||
| logInterceptor, | ||
| ]); | ||
|
|
||
| static final Dio httpClient = dioClient..interceptors.addAll([ | ||
| OfflineModeInterceptor(), | ||
| errorInterceptor, | ||
| ]); | ||
|
|
||
| static final httpCachedClient = httpClient..interceptors.addAll([ | ||
| cacheManager.interceptor, | ||
| ]); | ||
|
|
||
| static final Dio authClientSiga = httpClient..interceptors.addAll([ | ||
| cacheManagerSiga.interceptor, | ||
| ]); |
There was a problem hiding this comment.
httpCachedClient is created via httpClient..interceptors.addAll(...), but httpClient itself is also created from dioClient..interceptors.addAll(...). Because cascades return the same Dio instance, dioClient, httpClient, httpCachedClient, and authClientSiga end up being the same client with interceptors continually appended. This can cause duplicated interceptors, unexpected caching on auth requests, and hard-to-debug behavior. Create separate Dio() instances per client (or clone options) instead of reusing/mutating the same instance.
| cardTheme: CardThemeData( | ||
| color: scaffoldBackgroundColor, | ||
| shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Theme.of(context).dividerColor)), | ||
| ), |
There was a problem hiding this comment.
ThemeData.cardTheme typically expects a CardTheme. Using CardThemeData here will be a compile error unless the Flutter SDK version in this repo actually defines CardThemeData. Verify the correct theme type and adjust accordingly.
| cardTheme: CardThemeData( | ||
| color: scaffoldBackgroundColorDark, | ||
| shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Theme.of(context).dividerColor)), | ||
| ), |
There was a problem hiding this comment.
Same as above: ThemeData.cardTheme usually takes CardTheme; CardThemeData may not exist depending on Flutter SDK. If it doesn’t, this will fail to compile in the dark theme as well.
| dialogTheme: DialogThemeData( | ||
| backgroundColor: scaffoldBackgroundColorDark, | ||
| titleTextStyle: GoogleFonts.inter( |
There was a problem hiding this comment.
ThemeData.dialogTheme typically expects a DialogTheme. Using DialogThemeData here will be a compile error unless the Flutter SDK version in this repo actually defines DialogThemeData. Verify the correct theme type and adjust accordingly.
| // 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); | ||
|
|
There was a problem hiding this comment.
This formatter only removes @ characters. If a user pastes a full email like usuario@utem.cl, it becomes usuarioutem.cl, which then combines with the UI suffix and produces an invalid address. Consider stripping the whole @utem.cl suffix (case-insensitive) and/or rejecting non-username characters rather than only removing @.
| import 'dart:convert'; | ||
|
|
There was a problem hiding this comment.
Unused import: dart:convert is not referenced in this file. Remove it to avoid analyzer warnings.
| import 'dart:convert'; |
| @@ -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" | |||
|
|
|||
There was a problem hiding this comment.
Changing namespace/applicationId will change the Android package name and app identity, which breaks upgrade paths (users won’t receive updates from the old applicationId) and affects Firebase config, deep links, etc. If this wasn’t intentional, revert; if it is intentional, it should be called out explicitly in the PR description and coordinated with release/signing configs.
| #!/bin/sh | ||
| # This is a generated file; do not edit or check into version control. | ||
| 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/exdevutem/miutem/lib/main.dart" |
There was a problem hiding this comment.
This file is under macos/Flutter/ephemeral/ and even states it is generated and should not be checked into version control. It also contains absolute local paths (e.g. /Users/...) that are machine-specific and may leak environment details. Remove it from the repo and ensure the ignore rule is effective.
| String _capitalizeDia(String dia) => 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(bloque.horaInicio.trim(), | ||
| style: const TextStyle( | ||
| fontWeight: FontWeight.w900, | ||
| fontSize: 18, | ||
| ), | ||
| ), | ||
| Text(bloque.horaFin.trim(), | ||
| 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.nombreAsignatura), | ||
| style: const TextStyle( | ||
| fontWeight: FontWeight.w900, | ||
| fontSize: 18, | ||
| ), | ||
| overflow: TextOverflow.ellipsis, | ||
| ), | ||
| Text( | ||
| bloque.dia, | ||
| style: const TextStyle( | ||
| fontWeight: FontWeight.w300, |
There was a problem hiding this comment.
_capitalizeDia lowercases the entire string after the first character, and it's being applied to bloque.nombreAsignatura. This will mangle subject names (e.g. multi-word names and acronyms) and the helper name suggests it should be applied to bloque.dia instead. Use bloque.nombreAsignatura as-is for the title, and apply capitalization (if needed) to the day field.
…n MiUTEMMallaService
Esta solicitud de extracción introduce varias actualizaciones en múltiples archivos para mejorar la funcionalidad, mejorar la experiencia del usuario y optimizar la organización del código. Los cambios más significativos incluyen actualizar el SDK de Firebase Firestore, agregar nuevas pantallas y widgets para mostrar información detallada del tema y refactorizar el código existente para una mejor modularidad.
Actualizaciones de dependencia:
11.4.0a11.15.0en elios/Podfile.Nuevas Características:
Pantalla de detalles del tema: Se agregó
AsignaturaScreenpara mostrar información detallada del tema, incluidas las calificaciones y los horarios. Esta pantalla captura calificaciones de forma asíncrona y proporciona funcionalidad de actualización.Funcionalidad de carga de calificaciones: Se agregó la función
cargarAsignaturaConNotaspara obtener calificaciones para un tema específico.Programar análisis y visualización:
Se introdujo el modelo
HorarioBloquepara representar los bloques de programación.Se agregó el widget
CardHorariopara mostrar visualmente los bloques de programación.Implementó el widget
SeccionHorariopara analizar y mostrar los horarios de los temas.Refactorización:
Navegación de la lista de temas: Se ha modificado
ListaAsignaturaspara navegar a la nuevaAsignaturaScreencuando se toca una tarjeta de tema.Mejoras de la estructura de archivos: Rutas de importación actualizadas para una mejor organización, como mover acciones de
AccesoRapidoa una carpeta dedicada.Mejoras menores: