Skip to content

feat: asignatura screen#24

Open
Im-Fran wants to merge 27 commits intodevfrom
feat/asignatura-screen
Open

feat: asignatura screen#24
Im-Fran wants to merge 27 commits intodevfrom
feat/asignatura-screen

Conversation

@Im-Fran
Copy link
Member

@Im-Fran Im-Fran commented Jul 26, 2025

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:

  • Versión actualizada del SDK de Firebase Firestore de 11.4.0 a 11.15.0 en el ios/Podfile.

Nuevas Características:

  • Pantalla de detalles del tema: Se agregó AsignaturaScreen para 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 cargarAsignaturaConNotas para obtener calificaciones para un tema específico.

  • Programar análisis y visualización:

  • Se introdujo el modelo HorarioBloque para representar los bloques de programación.

  • Se agregó el widget CardHorario para mostrar visualmente los bloques de programación.

  • Implementó el widget SeccionHorario para analizar y mostrar los horarios de los temas.

Refactorización:

  • Navegación de la lista de temas: Se ha modificado ListaAsignaturas para navegar a la nueva AsignaturaScreen cuando 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 AccesoRapido a una carpeta dedicada.

Mejoras menores:

  • Se agregó la importación de temas adaptativos en el formulario de inicio de sesión para futuras mejoras relacionadas con el tema.

XhrdTLS and others added 5 commits November 20, 2024 21:27
- 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
@Im-Fran Im-Fran requested a review from Copilot July 26, 2025 04:14
@Im-Fran Im-Fran self-assigned this Jul 26, 2025
@Im-Fran Im-Fran added the enhancement New feature or request label Jul 26, 2025

This comment was marked as outdated.

Im-Fran and others added 8 commits July 26, 2025 00:16
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>
@Im-Fran Im-Fran requested a review from Copilot July 26, 2025 04:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 supported withOpacity(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 supported withOpacity(0.2) method instead.
                                color: Colors.grey.withValues(alpha: 0.2),

@@ -1,4 +1,4 @@
platform :macos, '11.5'
platform :osx, '10.15'
Copy link

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
platform :osx, '10.15'
platform :osx, '12.0'

Copilot uses AI. Check for mistakes.
Im-Fran and others added 7 commits July 26, 2025 00:57
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>
Signed-off-by: Francisco Solis <30329003+Im-Fran@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
Copilot AI review requested due to automatic review settings February 11, 2026 00:37
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +27 to +65
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'),
),
);
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +24
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,
};
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 14
#!/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"
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 9
// 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
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 3
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
platform :ios, '16.0'

Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +6
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
<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. -->

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +9
final apiUrl = dotenv.env['EXDEV_API_ENDPOINT'] ?? 'https://api.exdev.cl';
final sigaHost = dotenv.env['SIGA_ENDPOINT'] ?? 'https://siga.utem.cl';
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 23
WidgetsFlutterBinding.ensureInitialized();
await initServices();
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WidgetsFlutterBinding.ensureInitialized() is called twice. Keep a single call (at the very start of main) to avoid confusion and ensure initialization order is clear.

Copilot uses AI. Check for mistakes.
Comment on lines 63 to 67
flutter:
uses-material-design: true
assets:
- .env
- assets/launcher_icons/prod/icon_splash.png
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.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.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to 9
import 'package:miutem/core/utils/constants.dart';
import 'package:miutem/screens/notas/actions/cargar_asignaturas_con_notas.dart';
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 11, 2026 03:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +20 to +29
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();
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +5
// 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
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
// AQUI SE TIENE QUE USAR LA CONFIGURACION DEL KEYSTORE QUE TIENE LA APP OFICIAL
defaultConfig {
applicationId = "cl.exdev.miutem"
applicationId = "cl.inndev.miutem"
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.).

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +72
Text(
_capitalizeDia(bloque.nombreAsignatura),
style: const TextStyle(
fontWeight: FontWeight.w900,
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +2
import 'dart:convert';

Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
import 'dart:convert';

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +5
#!/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"
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +37
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));
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Este then(... setState ...) también debería validar mounted antes de actualizar estado por el mismo motivo (posible setState después de dispose).

Suggested change
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);
});

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +51
List<HorarioBloque> tmp = bloquesHorario;
try {
setState(() {
bloquesHorario.clear();
});
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.

android {
namespace = "cl.exdev.miutem"
namespace = "cl.inndev.miutem"
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +37
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));
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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);
});

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 12, 2026 00:22
Signed-off-by: Francisco Solis <30329003+Im-Fran@users.noreply.github.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines 11 to 15
static final DioCacheManager cacheManager = DioCacheManager(CacheConfig(
baseUrl: miUtemHost,
defaultMaxAge: const Duration(days: 7),
defaultMaxStale: const Duration(days: 14),
));
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 23 to 39
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,
]);
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +91 to 94
cardTheme: CardThemeData(
color: scaffoldBackgroundColor,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Theme.of(context).dividerColor)),
),
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +174 to 177
cardTheme: CardThemeData(
color: scaffoldBackgroundColorDark,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Theme.of(context).dividerColor)),
),
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +241 to 243
dialogTheme: DialogThemeData(
backgroundColor: scaffoldBackgroundColorDark,
titleTextStyle: GoogleFonts.inter(
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 22
// 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);

Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +2
import 'dart:convert';

Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import: dart:convert is not referenced in this file. Remove it to avoid analyzer warnings.

Suggested change
import 'dart:convert';

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 28
@@ -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"

Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
#!/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"
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +80
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,
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants