Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions lib/core/services/controllers/horario_controller.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "package:flutter/material.dart";
import "package:flutter/scheduler.dart";
import "package:get/get.dart";
import "package:get_storage/get_storage.dart";
import "package:miutem/core/models/asignaturas/asignatura.dart";
Expand Down Expand Up @@ -98,8 +99,14 @@ class HorarioController {

void init(BuildContext context){
zoom.value = RemoteConfigService.horarioZoom;
moveViewportToCurrentPeriodAndDay(context);
setZoom(zoom.value);

SchedulerBinding.instance.addPostFrameCallback((_) {
if (context.mounted) {
setZoom(zoom.value);
moveViewportToCurrentPeriodAndDay(context);
}
});


blockContentController.addListener(_blockContentControllerListener);
daysHeaderController.addListener(_daysHeaderControllerListener);
Expand Down Expand Up @@ -216,6 +223,11 @@ class HorarioController {
void moveViewportToCurrentPeriodAndDay(BuildContext context){
final periodIndex = indexOfCurrentPeriod ?? 0;
final dayIndex = indexOfCurrentDayStartingAtMonday ?? 0;

// Resetear el zoom al valor por defecto
zoom.value = RemoteConfigService.horarioZoom;
setZoom(zoom.value);

moveViewportToPeriodIndexAndDayIndex(context, periodIndex, dayIndex);
isCenteredInCurrentPeriodAndDay.value = true;
}
Expand Down
163 changes: 104 additions & 59 deletions lib/screens/horario/horario_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import "package:path_provider/path_provider.dart";
import "package:screenshot/screenshot.dart";
import "package:share_plus/share_plus.dart";

/// Widget contenedor que carga el horario
class HorarioScreen extends StatefulWidget {
const HorarioScreen({super.key});

Expand All @@ -20,15 +21,14 @@ class HorarioScreen extends StatefulWidget {
}

class _HorarioScreenState extends State<HorarioScreen> {
final ScreenshotController _screenshotController = ScreenshotController();

bool _forceRefresh = false;
late Future<Horario?> _horarioFuture;
final horarioController = Get.find<HorarioController>();

@override
void initState() {
_forceRefresh = false;
super.initState();
horarioController.init(context);
_horarioFuture = _loadHorario();
}

@override
Expand All @@ -37,16 +37,20 @@ class _HorarioScreenState extends State<HorarioScreen> {
super.dispose();
}

Future<Horario?> _loadHorario({bool forceRefresh = false}) async {
return await horarioController.getHorario(forceRefresh: forceRefresh);
}

void _reloadData() {
setState(() {
_horarioFuture = _loadHorario(forceRefresh: true);
});
}

@override
Widget build(BuildContext context) {
horarioController.init(context);
return FutureBuilder<Horario?>(
future: () async {
_moveViewportToCurrentTime();
final data = await horarioController.getHorario(forceRefresh: _forceRefresh);
_forceRefresh = false;
return data;
}(),
future: _horarioFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Scaffold(
Expand All @@ -59,6 +63,7 @@ class _HorarioScreenState extends State<HorarioScreen> {

final horario = snapshot.data;
final esErrorOffline = snapshot.hasError && snapshot.error is DioException && (snapshot.error as DioException).type == DioExceptionType.cancel && (snapshot.error as DioException).response?.extra["offline"] == true;

Comment thread
xsilvamo marked this conversation as resolved.
if ((snapshot.hasError && !esErrorOffline) || !snapshot.hasData || horario == null) {
String errorMessage = "Ocurrió un error al cargar el horario! Por favor intenta más tarde.";
final error = snapshot.error;
Expand Down Expand Up @@ -86,57 +91,56 @@ class _HorarioScreenState extends State<HorarioScreen> {
);
}

return Scaffold(
appBar: AppBar(
title: const Text("Horario"),
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"),
),
),
PopupMenuItem(
onTap: () => _captureAndShareScreenshot(context, horario),
child: const ListTile(
leading: Icon(Icons.share),
title: Text("Compartir"),
),
),
if (!horarioController.isCenteredInCurrentPeriodAndDay.value) PopupMenuItem(
onTap: _moveViewportToCurrentTime,
child: const ListTile(
leading: Icon(Icons.center_focus_strong),
title: Text("Centrar en hora actual"),
),
),
],
),
],
),
body: SafeArea(
child: Screenshot(
controller: _screenshotController,
child: HorarioMainScroller(
horario: horario,
),
),
),
// Una vez cargado, pasar el horario al widget stateless
return HorarioScreenContent(
horario: horario,
horarioController: horarioController,
onReload: _reloadData,
);
},
);
}
}

/// Widget sin estado que solo muestra el horario cargado
class HorarioScreenContent extends StatelessWidget {
final Horario horario;
final HorarioController horarioController;
final VoidCallback onReload;
final ScreenshotController _screenshotController = ScreenshotController();

void _moveViewportToCurrentTime() {
horarioController.moveViewportToCurrentPeriodAndDay(context);
HorarioScreenContent({
super.key,
required this.horario,
required this.horarioController,
required this.onReload,
});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Horario"),
actions: [
_HorarioMenuButton(
horarioController: horarioController,
onReload: onReload,
onCapture: _captureAndShareScreenshot,
),
],
),
body: SafeArea(
child: Screenshot(
controller: _screenshotController,
child: HorarioMainScroller(
horario: horario,
),
),
),
);
}

void _captureAndShareScreenshot(BuildContext context, Horario horario) async {
Future<void> _captureAndShareScreenshot(BuildContext context) async {
showLoadingDialog(context);
final horarioScroller = HorarioMainScroller(
horario: horario,
Expand All @@ -155,8 +159,7 @@ class _HorarioScreenState extends State<HorarioScreen> {
ext: "png",
mimeType: MimeType.png,
);
// Mostrar toast de éxito
if(context.mounted) {
if (context.mounted) {
Navigator.pop(context);
showTextSnackbar(context, title: "Horario guardado", message: "El horario se ha guardado correctamente en tu carpeta de descargas.");
}
Expand All @@ -165,11 +168,53 @@ class _HorarioScreenState extends State<HorarioScreen> {
final imagePath = await File("${directory.path}/horario.png").create();
await imagePath.writeAsBytes(image);

if(context.mounted) Navigator.pop(context);
if (context.mounted) Navigator.pop(context);

await Share.shareXFiles([XFile(imagePath.path)]);
}
}
}

/// Widget para el menú del horario
class _HorarioMenuButton extends StatelessWidget {
final HorarioController horarioController;
final VoidCallback onReload;
final Future<void> Function(BuildContext) onCapture;

void _reloadData() => setState(() => _forceRefresh = true);
const _HorarioMenuButton({
required this.horarioController,
required this.onReload,
required this.onCapture,
});

@override
Widget build(BuildContext context) {
return PopupMenuButton(
position: PopupMenuPosition.under,
icon: const Icon(Icons.more_vert),
itemBuilder: (ctx) => [
PopupMenuItem(
onTap: onReload,
child: const ListTile(
leading: Icon(Icons.refresh_sharp),
title: Text("Recargar"),
),
),
PopupMenuItem(
onTap: () => onCapture(context),
child: const ListTile(
leading: Icon(Icons.share),
title: Text("Compartir"),
),
),
PopupMenuItem(
onTap: () => horarioController.moveViewportToCurrentPeriodAndDay(context),
child: const ListTile(
leading: Icon(Icons.center_focus_strong),
title: Text("Centrar en hora actual"),
),
),
],
);
}
}
15 changes: 8 additions & 7 deletions lib/screens/horario/widgets/screens/horario_main_scroller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,15 @@ class HorarioMainScrollerState extends State<HorarioMainScroller> {
child: Stack(
children: [
widget._horarioPeriodsHeader,
HorarioIndicator(
maxWidth: HorarioMainScroller.daysWidth,
initialMargin: const EdgeInsets.only(
top: HorarioMainScroller.dayHeight,
left: HorarioMainScroller.periodWidth,
if (widget.showActive)
HorarioIndicator(
maxWidth: HorarioMainScroller.daysWidth,
initialMargin: const EdgeInsets.only(
top: HorarioMainScroller.dayHeight,
left: HorarioMainScroller.periodWidth,
),
heightByMinute: HorarioMainScroller.blockHeight / 100,
),
heightByMinute: HorarioMainScroller.blockHeight / 100,
),
],
),
),
Expand Down
Loading